Re: [Sqlalchemy-tickets] [sqlalchemy] #2526: can we get subclass mappers to self-collect?
Brought to you by:
zzzeek
From: sqlalchemy <mi...@zz...> - 2012-06-26 17:14:12
|
#2526: can we get subclass mappers to self-collect? ------------------------------+------------------------------- Reporter: zzzeek | Owner: zzzeek Type: enhancement | Status: new Priority: medium | Milestone: 0.8.0 Component: orm | Severity: major - 1-3 hours Resolution: | Keywords: Progress State: in queue | ------------------------------+------------------------------- Description changed by zzzeek: Old description: > would need a lot of weak references for this to work automatically, > particularly the memoizations somehow, which would add some real > performance overhead: > > {{{ > #!diff > diff -r 8b5adc1e004e lib/sqlalchemy/ext/declarative.py > --- a/lib/sqlalchemy/ext/declarative.py Mon Jun 25 16:42:39 2012 -0400 > +++ b/lib/sqlalchemy/ext/declarative.py Tue Jun 26 12:58:56 2012 -0400 > @@ -1036,7 +1036,7 @@ > from sqlalchemy.sql import util as sql_util, expression > from sqlalchemy import event > from sqlalchemy.orm.util import polymorphic_union, _mapper_or_none > - > +import weakref > > __all__ = 'declarative_base', 'synonym_for', \ > 'comparable_using', 'instrument_declarative' > @@ -1718,7 +1718,7 @@ > lcl_metadata.bind = bind > > if class_registry is None: > - class_registry = {} > + class_registry = weakref.WeakValueDictionary() > > bases = not isinstance(cls, tuple) and (cls,) or cls > class_dict = dict(_decl_class_registry=class_registry, > diff -r 8b5adc1e004e lib/sqlalchemy/orm/mapper.py > --- a/lib/sqlalchemy/orm/mapper.py Mon Jun 25 16:42:39 2012 -0400 > +++ b/lib/sqlalchemy/orm/mapper.py Tue Jun 26 12:58:56 2012 -0400 > @@ -166,7 +166,7 @@ > # names with Mappers that will be used to construct object > instances > # upon a select operation. > if _polymorphic_map is None: > - self.polymorphic_map = {} > + self.polymorphic_map = weakref.WeakValueDictionary() > else: > self.polymorphic_map = _polymorphic_map > > @@ -432,7 +432,8 @@ > being present.""" > > # a set of all mappers which inherit from this one. > - self._inheriting_mappers = set() > + # TODO: WeakSet is only in 2.7, would need compat > + self._inheriting_mappers = weakref.WeakSet() > > if self.inherits: > if isinstance(self.inherits, type): > }}} > > {{{ > #!python > from sqlalchemy import * > from sqlalchemy.orm import * > from sqlalchemy.ext.declarative import declarative_base > > Base= declarative_base() > > class Root(Base): > __tablename__ = 'root' > id = Column(Integer, primary_key=True) > type = Column(String) > __mapper_args__ = { > 'polymorphic_on':type, > 'polymorphic_identity':'root' > } > > assert not Root.__mapper__._inheriting_mappers > > class Sub(Root): > __tablename__ = 'sub' > metadata = MetaData() > id = Column(Integer, ForeignKey(Root.id), primary_key=True) > __mapper_args__ = { > 'polymorphic_identity':'sub' > } > > e = create_engine("sqlite://") > Base.metadata.create_all(e) > Sub.metadata.create_all(e) > compile_mappers() > s = Session(e) > > s.add_all([Root()]) > print s.query(Root).all() > > del Sub > > # this step is required, though, unless we > # make the memoizations weak too, that would > # be a real performance hit > Root.__mapper__._expire_memoizations() > > import gc > gc.collect() > assert not Root.__mapper__._inheriting_mappers > }}} New description: would need a lot of weak references for this to work automatically, particularly the memoizations somehow, which would add some real performance overhead: {{{ #!diff diff -r 8b5adc1e004e lib/sqlalchemy/ext/declarative.py --- a/lib/sqlalchemy/ext/declarative.py Mon Jun 25 16:42:39 2012 -0400 +++ b/lib/sqlalchemy/ext/declarative.py Tue Jun 26 12:58:56 2012 -0400 @@ -1036,7 +1036,7 @@ from sqlalchemy.sql import util as sql_util, expression from sqlalchemy import event from sqlalchemy.orm.util import polymorphic_union, _mapper_or_none - +import weakref __all__ = 'declarative_base', 'synonym_for', \ 'comparable_using', 'instrument_declarative' @@ -1718,7 +1718,7 @@ lcl_metadata.bind = bind if class_registry is None: - class_registry = {} + class_registry = weakref.WeakValueDictionary() bases = not isinstance(cls, tuple) and (cls,) or cls class_dict = dict(_decl_class_registry=class_registry, diff -r 8b5adc1e004e lib/sqlalchemy/orm/mapper.py --- a/lib/sqlalchemy/orm/mapper.py Mon Jun 25 16:42:39 2012 -0400 +++ b/lib/sqlalchemy/orm/mapper.py Tue Jun 26 12:58:56 2012 -0400 @@ -166,7 +166,7 @@ # names with Mappers that will be used to construct object instances # upon a select operation. if _polymorphic_map is None: - self.polymorphic_map = {} + self.polymorphic_map = weakref.WeakValueDictionary() else: self.polymorphic_map = _polymorphic_map @@ -432,7 +432,8 @@ being present.""" # a set of all mappers which inherit from this one. - self._inheriting_mappers = set() + # TODO: WeakSet is only in 2.7, would need compat + self._inheriting_mappers = weakref.WeakSet() if self.inherits: if isinstance(self.inherits, type): }}} {{{ #!python from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base Base= declarative_base() class Root(Base): __tablename__ = 'root' id = Column(Integer, primary_key=True) type = Column(String) __mapper_args__ = { 'polymorphic_on':type, 'polymorphic_identity':'root' } assert not Root.__mapper__._inheriting_mappers class Sub(Root): __tablename__ = 'sub' metadata = MetaData() id = Column(Integer, ForeignKey(Root.id), primary_key=True) __mapper_args__ = { 'polymorphic_identity':'sub' } e = create_engine("sqlite://") Base.metadata.create_all(e) Sub.metadata.create_all(e) compile_mappers() s = Session(e) s.add_all([Root(), Sub()]) print s.query(Root).all() del Sub # this step is required, though, unless we # make the memoizations weak too, that would # be a real performance hit Root.__mapper__._expire_memoizations() import gc gc.collect() assert not Root.__mapper__._inheriting_mappers }}} -- -- Ticket URL: <http://www.sqlalchemy.org/trac/ticket/2526#comment:2> sqlalchemy <http://www.sqlalchemy.org/> The Database Toolkit for Python |