<p dir="auto">test case, from <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="384635415" data-permission-text="Title is private" data-url="https://github.com/sqlalchemy/sqlalchemy/issues/3583" data-hovercard-type="issue" data-hovercard-url="/sqlalchemy/sqlalchemy/issues/3583/hovercard" href="https://github.com/sqlalchemy/sqlalchemy/issues/3583">#3583</a>:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from sqlalchemy import *
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import *


Base = declarative_base()


class A(Base):
    __tablename__ = &quot;test_a&quot;

    id = Column(Integer, primary_key=True)
    b_rel = relationship(
        &quot;B&quot;, collection_class=set, cascade=&quot;all, delete-orphan&quot;
    )
    b = association_proxy(&quot;b_rel&quot;, &quot;value&quot;, creator=lambda x: B(value=x))


class B(Base):
    __tablename__ = &quot;test_b&quot;
    __table_args__ = (UniqueConstraint(&quot;a_id&quot;, &quot;value&quot;),)

    id = Column(Integer, primary_key=True)
    a_id = Column(Integer, ForeignKey(&quot;test_a.id&quot;), nullable=False)
    value = Column(String)


e = create_engine(&quot;sqlite:///:memory:&quot;, echo=True)
# e = create_engine('postgresql:///test', echo=True)
Base.metadata.create_all(e)
# e.execute('TRUNCATE test_a, test_b;')
s = Session(e)

a = A()
a.b = {&quot;x&quot;, &quot;y&quot;, &quot;z&quot;}
s.add(a)
s.commit()

print(&quot;\nadding existing element to set&quot;)
a.b.add(&quot;x&quot;)
s.flush()

print(&quot;\nassigning same items to set&quot;)
a.b = set(a.b)
s.flush()
"><pre class="notranslate"><code class="notranslate">from sqlalchemy import *
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import *


Base = declarative_base()


class A(Base):
    __tablename__ = "test_a"

    id = Column(Integer, primary_key=True)
    b_rel = relationship(
        "B", collection_class=set, cascade="all, delete-orphan"
    )
    b = association_proxy("b_rel", "value", creator=lambda x: B(value=x))


class B(Base):
    __tablename__ = "test_b"
    __table_args__ = (UniqueConstraint("a_id", "value"),)

    id = Column(Integer, primary_key=True)
    a_id = Column(Integer, ForeignKey("test_a.id"), nullable=False)
    value = Column(String)


e = create_engine("sqlite:///:memory:", echo=True)
# e = create_engine('postgresql:///test', echo=True)
Base.metadata.create_all(e)
# e.execute('TRUNCATE test_a, test_b;')
s = Session(e)

a = A()
a.b = {"x", "y", "z"}
s.add(a)
s.commit()

print("\nadding existing element to set")
a.b.add("x")
s.flush()

print("\nassigning same items to set")
a.b = set(a.b)
s.flush()

</code></pre></div>
<p dir="auto">since this issue was added the association proxy has been highly modified</p>
<p dir="auto"><strong>Migrated issue, originally created by Michael Bayer (<a href="https://github.com/zzzeek">@zzzeek</a>)</strong></p>
<p dir="auto">the "clear" here is clumsy and <a href="we">originally thought was</a> the ultimate cause of the original issue in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="384626979" data-permission-text="Title is private" data-url="https://github.com/sqlalchemy/sqlalchemy/issues/2637" data-hovercard-type="issue" data-hovercard-url="/sqlalchemy/sqlalchemy/issues/2637/hovercard" href="https://github.com/sqlalchemy/sqlalchemy/issues/2637">#2637</a> <a href="but">it's not</a>.   Might be nicer if we had a bulk replace built in for those collections, would emit fewer events.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="    def __set__(self, obj, values):
        if self.owning_class is None:
            self.owning_class = type(obj)

        if self.scalar:
            creator = self.creator and self.creator or self.target_class
            target = getattr(obj, self.target_collection)
            if target is None:
                setattr(obj, self.target_collection, creator(values))
            else:
                self._scalar_set(target, values)
        else:
            proxy = self.__get__(obj, None)
            if proxy is not values:
                proxy.clear()
                self._set(proxy, values)"><pre class="notranslate"><code class="notranslate">    def __set__(self, obj, values):
        if self.owning_class is None:
            self.owning_class = type(obj)

        if self.scalar:
            creator = self.creator and self.creator or self.target_class
            target = getattr(obj, self.target_collection)
            if target is None:
                setattr(obj, self.target_collection, creator(values))
            else:
                self._scalar_set(target, values)
        else:
            proxy = self.__get__(obj, None)
            if proxy is not values:
                proxy.clear()
                self._set(proxy, values)
</code></pre></div>
<p dir="auto"><strong>Migrated issue, originally created by Anonymous</strong></p>
<p dir="auto">After executing <code class="notranslate">table.tometadata(metadata)</code>, the new table's new column's <code class="notranslate">info</code> dictionaries are references to the original columns' dictionaries instead of a copy of the dictionary.</p>
<p dir="auto">If this is by design for some reason, no hard feelings, close ticket, but seems bad design to me to have the new instances of the columns referencing the original columns' <code class="notranslate">info</code> dictionaries.</p>