From: Mike Bayer Date: Sat, 15 Mar 2008 20:18:54 +0000 (+0000) Subject: - the "synonym" function is now directly usable with X-Git-Tag: rel_0_4_5~94 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=288f9d53e37853825652074fcd5d1063f5c8992f;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - the "synonym" function is now directly usable with "declarative". Pass in the decorated property using the "instrument" keyword argument, e.g.: somekey = synonym('_somekey', instrument=property(g, s)) - declared_synonym deprecated --- diff --git a/CHANGES b/CHANGES index 01f0546eda..006849a420 100644 --- a/CHANGES +++ b/CHANGES @@ -16,7 +16,13 @@ CHANGES from being used with inheritance - Session.execute can now find binds from metadata - + +- extensions + - the "synonym" function is now directly usable with + "declarative". Pass in the decorated property using + the "instrument" keyword argument, e.g.: + somekey = synonym('_somekey', instrument=property(g, s)) + 0.4.4 ------ - sql diff --git a/doc/build/content/plugins.txt b/doc/build/content/plugins.txt index ed3869c248..8c1d3a55bd 100644 --- a/doc/build/content/plugins.txt +++ b/doc/build/content/plugins.txt @@ -17,7 +17,7 @@ declarative moves these three types of configuration underneath the individual m in most cases: {python} - from sqlalchemy.ext.declarative import declarative_base, declared_synonym + from sqlalchemy.ext.declarative import declarative_base engine = create_engine('sqlite://') Base = declarative_base(engine) @@ -81,8 +81,8 @@ using them: user_id = Column('user_id', Integer, ForeignKey('users.id')) user = relation(User, primaryjoin=user_id==User.id) -Synonyms are one area where `declarative` needs to slightly change the usual SQLAlchemy configurational syntax. To define a getter/setter which -proxies to an underlying attribute, use `declared_synonym`: +Synonyms are one area where `declarative` needs to slightly change the usual SQLAlchemy configurational syntax. To define a +getter/setter which proxies to an underlying attribute, use `synonym` with the `instruments` argument: {python} class MyClass(Base): @@ -94,7 +94,7 @@ proxies to an underlying attribute, use `declared_synonym`: return self._some_attr def _set_attr(self, attr) self._some_attr = attr - attr = declared_synonym(property(_get_attr, _set_attr), '_attr') + attr = synonym('_attr', instruments=property(_get_attr, _set_attr)) The above synonym is then usable as an instance attribute as well as a class-level expression construct: diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index b1bd07fbf5..4feb474566 100644 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -6,7 +6,7 @@ declarative moves these three types of configuration underneath the individual mapped class. Regular SQLAlchemy schema and ORM constructs are used in most cases:: - from sqlalchemy.ext.declarative import declarative_base, declared_synonym + from sqlalchemy.ext.declarative import declarative_base engine = create_engine('sqlite://') Base = declarative_base(engine) @@ -73,7 +73,7 @@ using them:: Synonyms are one area where ``declarative`` needs to slightly change the usual SQLAlchemy configurational syntax. To define a getter/setter which proxies -to an underlying attribute, use ``declared_synonym``:: +to an underlying attribute, use ``synonym`` with the ``instruments`` argument:: class MyClass(Base): __tablename__ = 'sometable' @@ -84,7 +84,7 @@ to an underlying attribute, use ``declared_synonym``:: return self._some_attr def _set_attr(self, attr) self._some_attr = attr - attr = declared_synonym(property(_get_attr, _set_attr), '_attr') + attr = synonym('_attr', instruments=property(_get_attr, _set_attr)) The above synonym is then usable as an instance attribute as well as a class-level expression construct:: @@ -146,6 +146,7 @@ from sqlalchemy.schema import Table, SchemaItem, Column, MetaData from sqlalchemy.orm import synonym as _orm_synonym, mapper from sqlalchemy.orm.interfaces import MapperProperty from sqlalchemy.orm.properties import PropertyLoader +from sqlalchemy import util __all__ = ['declarative_base', 'declared_synonym'] @@ -158,13 +159,10 @@ class DeclarativeMeta(type): our_stuff = {} for k in dict_: value = dict_[k] - if not isinstance(value, (Column, MapperProperty, declared_synonym)): + if not isinstance(value, (Column, MapperProperty)): continue - if isinstance(value, declared_synonym): - value._setup(cls, k, our_stuff) - else: - prop = _deferred_relation(cls, value) - our_stuff[k] = prop + prop = _deferred_relation(cls, value) + our_stuff[k] = prop table = None if '__table__' not in cls.__dict__: @@ -195,8 +193,6 @@ class DeclarativeMeta(type): cls.__mapper__.add_property(key, value) elif isinstance(value, MapperProperty): cls.__mapper__.add_property(key, _deferred_relation(cls, value)) - elif isinstance(value, declared_synonym): - value._setup(cls, key, None) else: type.__setattr__(cls, key, value) else: @@ -211,23 +207,11 @@ def _deferred_relation(cls, prop): return prop -class declared_synonym(object): - def __init__(self, prop, name, mapperprop=None): - self.prop = prop - self.name = name - self.mapperprop = mapperprop - - def _setup(self, cls, key, init_dict): - prop = self.mapperprop or getattr(cls, self.name) - prop = _deferred_relation(cls, prop) - setattr(cls, key, self.prop) - if init_dict is not None: - init_dict[self.name] = prop - init_dict[key] = _orm_synonym(self.name) - else: - setattr(cls, self.name, prop) - setattr(cls, key, _orm_synonym(self.name)) - +def declared_synonym(prop, name): + """deprecated. use synonym(name, instrument=prop).""" + + return _orm_synonym(name, instrument=prop) +declared_synonym = util.deprecated(declared_synonym) def declarative_base(engine=None, metadata=None): lcl_metadata = metadata or MetaData() diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index 46c81952f8..d7b5580647 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -547,7 +547,7 @@ def mapper(class_, local_table=None, *args, **params): return Mapper(class_, local_table, *args, **params) -def synonym(name, map_column=False, proxy=False): +def synonym(name, map_column=False, instrument=None, proxy=False): """Set up `name` as a synonym to another mapped property. Used with the ``properties`` dictionary sent to [sqlalchemy.orm#mapper()]. @@ -589,7 +589,7 @@ def synonym(name, map_column=False, proxy=False): is not already available. """ - return SynonymProperty(name, map_column=map_column) + return SynonymProperty(name, map_column=map_column, instrument=instrument) def compile_mappers(): """Compile all mappers that have been defined. diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 4a8e592cee..36a6632554 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -653,9 +653,10 @@ class Mapper(object): for col in col.proxy_set: self._columntoproperty[col] = prop elif isinstance(prop, SynonymProperty) and setparent: - prop.instrument = getattr(self.class_, key, None) - if isinstance(prop.instrument, Mapper._CompileOnAttr): - prop.instrument = object.__getattribute__(prop.instrument, 'existing_prop') + if prop.instrument is None: + prop.instrument = getattr(self.class_, key, None) + if isinstance(prop.instrument, Mapper._CompileOnAttr): + prop.instrument = object.__getattribute__(prop.instrument, 'existing_prop') if prop.map_column: if not key in self.mapped_table.c: raise exceptions.ArgumentError("Can't compile synonym '%s': no column on table '%s' named '%s'" % (prop.name, self.mapped_table.description, key)) diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 79c4ba63b0..1866693b4d 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -150,10 +150,10 @@ class CompositeProperty(ColumnProperty): other.__composite_values__())]) class SynonymProperty(MapperProperty): - def __init__(self, name, map_column=None): + def __init__(self, name, map_column=None, instrument=None): self.name = name self.map_column=map_column - self.instrument = None + self.instrument = instrument def setup(self, querycontext, **kwargs): pass @@ -177,7 +177,6 @@ class SynonymProperty(MapperProperty): return s return getattr(obj, self.name) self.instrument = SynonymProp() - sessionlib.register_attribute(class_, self.key, uselist=False, proxy_property=self.instrument, useobject=False, comparator=comparator) def merge(self, session, source, dest, _recursive): diff --git a/test/ext/declarative.py b/test/ext/declarative.py index 66ceb718b3..ef5fc87c6c 100644 --- a/test/ext/declarative.py +++ b/test/ext/declarative.py @@ -93,7 +93,7 @@ class DeclarativeTest(TestBase): self._name = "SOMENAME " + name def _get_name(self): return self._name - name = declared_synonym(property(_get_name, _set_name), '_name') + name = synonym('_name', instrument=property(_get_name, _set_name)) Base.metadata.create_all() @@ -104,7 +104,52 @@ class DeclarativeTest(TestBase): sess.flush() self.assertEquals(sess.query(User).filter(User.name=="SOMENAME someuser").one(), u1) + @testing.uses_deprecated('Call to deprecated function declared_synonym') + def test_decl_synonym_inline(self): + class User(Base, Fixture): + __tablename__ = 'users' + + id = Column('id', Integer, primary_key=True) + _name = Column('name', String(50)) + def _set_name(self, name): + self._name = "SOMENAME " + name + def _get_name(self): + return self._name + name = declared_synonym(property(_get_name, _set_name), '_name') + + Base.metadata.create_all() + + sess = create_session() + u1 = User(name='someuser') + assert u1.name == "SOMENAME someuser", u1.name + sess.save(u1) + sess.flush() + self.assertEquals(sess.query(User).filter(User.name=="SOMENAME someuser").one(), u1) + def test_synonym_added(self): + class User(Base, Fixture): + __tablename__ = 'users' + + id = Column('id', Integer, primary_key=True) + _name = Column('name', String(50)) + def _set_name(self, name): + self._name = "SOMENAME " + name + def _get_name(self): + return self._name + name = property(_get_name, _set_name) + User.name = synonym('_name', instrument=User.name) + + Base.metadata.create_all() + + sess = create_session() + u1 = User(name='someuser') + assert u1.name == "SOMENAME someuser", u1.name + sess.save(u1) + sess.flush() + self.assertEquals(sess.query(User).filter(User.name=="SOMENAME someuser").one(), u1) + + @testing.uses_deprecated('Call to deprecated function declared_synonym') + def test_decl_synonym_added(self): class User(Base, Fixture): __tablename__ = 'users'