From abc8e45b2f94dee88aa712b21470d65f942f12b2 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 27 Sep 2010 10:01:48 -0400 Subject: [PATCH] @mapperproperty -> @declared_attr --- CHANGES | 4 +- doc/build/orm/extensions/declarative.rst | 2 +- lib/sqlalchemy/ext/declarative.py | 62 ++++++++++---------- lib/sqlalchemy/util.py | 2 +- test/ext/test_declarative.py | 74 ++++++++++++------------ 5 files changed, 72 insertions(+), 72 deletions(-) diff --git a/CHANGES b/CHANGES index ed4e5132cc..d43732e468 100644 --- a/CHANGES +++ b/CHANGES @@ -133,13 +133,13 @@ CHANGES not the singleton NULLTYPE instance. [ticket:1907] - declarative - - @classproperty (soon/now @mapperproperty) takes effect for + - @classproperty (soon/now @declared_attr) takes effect for __mapper_args__, __table_args__, __tablename__ on a base class that is not a mixin, as well as mixins. [ticket:1922] - @classproperty 's official name/location for usage - with declarative is sqlalchemy.ext.declarative.mapperproperty. + with declarative is sqlalchemy.ext.declarative.declared_attr. Same thing, but moving there since it is more of a "marker" that's specific to declararative, not just an attribute technique. [ticket:1915] diff --git a/doc/build/orm/extensions/declarative.rst b/doc/build/orm/extensions/declarative.rst index 97b94840b7..4bdb68fa77 100644 --- a/doc/build/orm/extensions/declarative.rst +++ b/doc/build/orm/extensions/declarative.rst @@ -8,7 +8,7 @@ API Reference .. autofunction:: declarative_base -.. autoclass:: mapperproperty +.. autoclass:: declared_attr .. autofunction:: _declarative_constructor diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index be1cb75ec9..cbda848e80 100755 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -589,13 +589,13 @@ keys, as a :class:`ForeignKey` itself contains references to columns which can't be properly recreated at this level. For columns that have foreign keys, as well as for the variety of mapper-level constructs that require destination-explicit context, the -:func:`~.mapperproperty` decorator is provided so that +:func:`~.declared_attr` decorator is provided so that patterns common to many classes can be defined as callables:: - from sqlalchemy.ext.declarative import mapperproperty + from sqlalchemy.ext.declarative import declared_attr class ReferenceAddressMixin(object): - @mapperproperty + @declared_attr def address_id(cls): return Column(Integer, ForeignKey('address.id')) @@ -608,14 +608,14 @@ point at which the ``User`` class is constructed, and the declarative extension can use the resulting :class:`Column` object as returned by the method without the need to copy it. -Columns generated by :func:`~.mapperproperty` can also be +Columns generated by :func:`~.declared_attr` can also be referenced by ``__mapper_args__`` to a limited degree, currently by ``polymorphic_on`` and ``version_id_col``, by specifying the classdecorator itself into the dictionary - the declarative extension will resolve them at class construction time:: class MyMixin: - @mapperproperty + @declared_attr def type_(cls): return Column(String(50)) @@ -630,18 +630,18 @@ Mixing in Relationships Relationships created by :func:`~sqlalchemy.orm.relationship` are provided with declarative mixin classes exclusively using the -:func:`.mapperproperty` approach, eliminating any ambiguity +:func:`.declared_attr` approach, eliminating any ambiguity which could arise when copying a relationship and its possibly column-bound contents. Below is an example which combines a foreign key column and a relationship so that two classes ``Foo`` and ``Bar`` can both be configured to reference a common target class via many-to-one:: class RefTargetMixin(object): - @mapperproperty + @declared_attr def target_id(cls): return Column('target_id', ForeignKey('target.id')) - @mapperproperty + @declared_attr def target(cls): return relationship("Target") @@ -664,11 +664,11 @@ To reference the mixin class in these expressions, use the given ``cls`` to get it's name:: class RefTargetMixin(object): - @mapperproperty + @declared_attr def target_id(cls): return Column('target_id', ForeignKey('target.id')) - @mapperproperty + @declared_attr def target(cls): return relationship("Target", primaryjoin="Target.id==%s.target_id" % cls.__name__ @@ -681,12 +681,12 @@ Like :func:`~sqlalchemy.orm.relationship`, all :class:`~sqlalchemy.orm.interfaces.MapperProperty` subclasses such as :func:`~sqlalchemy.orm.deferred`, :func:`~sqlalchemy.orm.column_property`, etc. ultimately involve references to columns, and therefore, when -used with declarative mixins, have the :func:`.mapperproperty` +used with declarative mixins, have the :func:`.declared_attr` requirement so that no reliance on copying is needed:: class SomethingMixin(object): - @mapperproperty + @declared_attr def dprop(cls): return deferred(Column(Integer)) @@ -711,10 +711,10 @@ where you wanted to use that mixin in a single table inheritance hierarchy, you can explicitly specify ``__tablename__`` as ``None`` to indicate that the class should not have a table mapped:: - from sqlalchemy.ext.declarative import mapperproperty + from sqlalchemy.ext.declarative import declared_attr class Tablename: - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() @@ -738,11 +738,11 @@ has a mapped table. As an example, here's a mixin that will only allow single table inheritance:: - from sqlalchemy.ext.declarative import mapperproperty + from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import has_inherited_table class Tablename: - @mapperproperty + @declared_attr def __tablename__(cls): if has_inherited_table(cls): return None @@ -762,11 +762,11 @@ table inheritance, you would need a slightly different mixin and use it on any joined table child classes in addition to their parent classes:: - from sqlalchemy.ext.declarative import mapperproperty + from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import has_inherited_table class Tablename: - @mapperproperty + @declared_attr def __tablename__(cls): if (has_inherited_table(cls) and Tablename not in cls.__bases__): @@ -796,11 +796,11 @@ In the case of ``__table_args__`` or ``__mapper_args__`` specified with declarative mixins, you may want to combine some parameters from several mixins with those you wish to define on the class iteself. The -:func:`.mapperproperty` decorator can be used +:func:`.declared_attr` decorator can be used here to create user-defined collation routines that pull from multiple collections:: - from sqlalchemy.ext.declarative import mapperproperty + from sqlalchemy.ext.declarative import declared_attr class MySQLSettings: __table_args__ = {'mysql_engine':'InnoDB'} @@ -811,7 +811,7 @@ from multiple collections:: class MyModel(Base,MySQLSettings,MyOtherMixin): __tablename__='my_model' - @mapperproperty + @declared_attr def __table_args__(self): args = dict() args.update(MySQLSettings.__table_args__) @@ -897,7 +897,7 @@ def _as_declarative(cls, classname, dict_): tablename = None parent_columns = () - declarative_props = (mapperproperty, util.classproperty) + declarative_props = (declared_attr, util.classproperty) for base in cls.__mro__: class_mapped = _is_mapped_class(base) @@ -1265,30 +1265,30 @@ def comparable_using(comparator_factory): return comparable_property(comparator_factory, fn) return decorate -class mapperproperty(property): +class declared_attr(property): """Mark a class-level method as representing the definition of a mapped property or special declarative member name. - .. note:: @mapperproperty is available as + .. note:: @declared_attr is available as sqlalchemy.util.classproperty for SQLAlchemy versions 0.6.2, 0.6.3, 0.6.4. - @mapperproperty turns the attribute into a scalar-like + @declared_attr turns the attribute into a scalar-like property that can be invoked from the uninstantiated class. Declarative treats attributes specifically marked with - @mapperproperty as returning a construct that is specific + @declared_attr as returning a construct that is specific to mapping or declarative table configuration. The name of the attribute is that of what the non-dynamic version of the attribute would be. - @mapperproperty is more often than not applicable to mixins, + @declared_attr is more often than not applicable to mixins, to define relationships that are to be applied to different implementors of the class:: class ProvidesUser(object): "A mixin that adds a 'user' relationship to classes." - @mapperproperty + @declared_attr def user(self): return relationship("User") @@ -1299,11 +1299,11 @@ class mapperproperty(property): id = Column(Integer, primary_key=True) type = Column(String(50), nullable=False) - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() - @mapperproperty + @declared_attr def __mapper_args__(cls): if cls.__name__ == 'Employee': return { @@ -1316,7 +1316,7 @@ class mapperproperty(property): """ def __init__(self, fget, *arg, **kw): - super(mapperproperty, self).__init__(fget, *arg, **kw) + super(declared_attr, self).__init__(fget, *arg, **kw) self.__doc__ = fget.__doc__ def __get__(desc, self, cls): diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py index 3b64c5ef1f..76aaed34d9 100644 --- a/lib/sqlalchemy/util.py +++ b/lib/sqlalchemy/util.py @@ -1803,7 +1803,7 @@ class classproperty(property): The decorator is currently special when using the declarative module, but note that the - :class:`~.sqlalchemy.ext.declarative.mapperproperty` + :class:`~.sqlalchemy.ext.declarative.declared_attr` decorator should be used for this purpose with declarative. """ diff --git a/test/ext/test_declarative.py b/test/ext/test_declarative.py index c9159f9537..81e6829e43 100644 --- a/test/ext/test_declarative.py +++ b/test/ext/test_declarative.py @@ -14,7 +14,7 @@ from sqlalchemy.orm import relationship, create_session, class_mapper, \ from sqlalchemy.test.testing import eq_ from sqlalchemy.util import classproperty from test.orm._base import ComparableEntity, MappedTest -from sqlalchemy.ext.declarative import mapperproperty +from sqlalchemy.ext.declarative import declared_attr class DeclarativeTestBase(testing.TestBase, testing.AssertsExecutionResults): def setup(self): @@ -694,7 +694,7 @@ class DeclarativeTest(DeclarativeTestBase): eq_(sess.query(User).all(), [User(name='u1', address_count=2, addresses=[Address(email='one'), Address(email='two')])]) - def test_useless_mapperproperty(self): + def test_useless_declared_attr(self): class Address(Base, ComparableEntity): __tablename__ = 'addresses' @@ -711,7 +711,7 @@ class DeclarativeTest(DeclarativeTestBase): name = Column('name', String(50)) addresses = relationship('Address', backref='user') - @mapperproperty + @declared_attr def address_count(cls): # this doesn't really gain us anything. but if # one is used, lets have it function as expected... @@ -2198,7 +2198,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): def test_table_name_inherited(self): class MyMixin: - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() id = Column(Integer, primary_key=True) @@ -2223,7 +2223,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): def test_table_name_not_inherited(self): class MyMixin: - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() id = Column(Integer, primary_key=True) @@ -2236,12 +2236,12 @@ class DeclarativeMixinTest(DeclarativeTestBase): def test_table_name_inheritance_order(self): class MyMixin1: - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() + '1' class MyMixin2: - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() + '2' @@ -2253,7 +2253,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): def test_table_name_dependent_on_subclass(self): class MyHistoryMixin: - @mapperproperty + @declared_attr def __tablename__(cls): return cls.parent_name + '_changelog' @@ -2277,7 +2277,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): def test_table_args_inherited_descriptor(self): class MyMixin: - @mapperproperty + @declared_attr def __table_args__(cls): return {'info': cls.__name__} @@ -2316,10 +2316,10 @@ class DeclarativeMixinTest(DeclarativeTestBase): eq_(MyModel.__table__.kwargs, {'mysql_engine': 'InnoDB'}) - def test_mapper_args_mapperproperty(self): + def test_mapper_args_declared_attr(self): class ComputedMapperArgs: - @mapperproperty + @declared_attr def __mapper_args__(cls): if cls.__name__ == 'Person': return {'polymorphic_on': cls.discriminator} @@ -2339,13 +2339,13 @@ class DeclarativeMixinTest(DeclarativeTestBase): is Person.__table__.c.type eq_(class_mapper(Engineer).polymorphic_identity, 'Engineer') - def test_mapper_args_mapperproperty_two(self): + def test_mapper_args_declared_attr_two(self): - # same as test_mapper_args_mapperproperty, but we repeat + # same as test_mapper_args_declared_attr, but we repeat # ComputedMapperArgs on both classes for no apparent reason. class ComputedMapperArgs: - @mapperproperty + @declared_attr def __mapper_args__(cls): if cls.__name__ == 'Person': return {'polymorphic_on': cls.discriminator} @@ -2380,7 +2380,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): __tablename__ = 'test' - @mapperproperty + @declared_attr def __table_args__(self): info = {} args = dict(info=info) @@ -2408,7 +2408,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): class MyMixin: - @mapperproperty + @declared_attr def __mapper_args__(cls): # tenuous, but illustrates the problem! @@ -2470,7 +2470,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): __tablename__ = 'test' - @mapperproperty + @declared_attr def __mapper_args__(cls): args = {} args.update(MyMixin1.__mapper_args__) @@ -2497,15 +2497,15 @@ class DeclarativeMixinTest(DeclarativeTestBase): def test_mapper_args_property(self): class MyModel(Base): - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() - @mapperproperty + @declared_attr def __table_args__(cls): return {'mysql_engine':'InnoDB'} - @mapperproperty + @declared_attr def __mapper_args__(cls): args = {} args['polymorphic_identity'] = cls.__name__ @@ -2528,18 +2528,18 @@ class DeclarativeMixinTest(DeclarativeTestBase): eq_(MySubModel.__table__.name, 'mysubmodel') def test_mapper_args_custom_base(self): - """test the @mapperproperty approach from a custom base.""" + """test the @declared_attr approach from a custom base.""" class Base(object): - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() - @mapperproperty + @declared_attr def __table_args__(cls): return {'mysql_engine':'InnoDB'} - @mapperproperty + @declared_attr def id(self): return Column(Integer, primary_key=True) @@ -2584,7 +2584,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): class CommonMixin: - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() __table_args__ = {'mysql_engine': 'InnoDB'} @@ -2614,7 +2614,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): class CommonMixin: - @mapperproperty + @declared_attr def __tablename__(cls): return cls.__name__.lower() __table_args__ = {'mysql_engine': 'InnoDB'} @@ -2651,7 +2651,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): class NoJoinedTableNameMixin: - @mapperproperty + @declared_attr def __tablename__(cls): if decl.has_inherited_table(cls): return None @@ -2679,7 +2679,7 @@ class DeclarativeMixinTest(DeclarativeTestBase): class TableNameMixin: - @mapperproperty + @declared_attr def __tablename__(cls): if decl.has_inherited_table(cls) and TableNameMixin \ not in cls.__bases__: @@ -2804,7 +2804,7 @@ class DeclarativeMixinPropertyTest(DeclarativeTestBase): class MyMixin(object): - @mapperproperty + @declared_attr def prop_hoho(cls): return column_property(Column('prop', String(50))) @@ -2843,20 +2843,20 @@ class DeclarativeMixinPropertyTest(DeclarativeTestBase): def test_doc(self): """test documentation transfer. - the documentation situation with @mapperproperty is problematic. + the documentation situation with @declared_attr is problematic. at least see if mapped subclasses get the doc. """ class MyMixin(object): - @mapperproperty + @declared_attr def type_(cls): """this is a document.""" return Column(String(50)) - @mapperproperty + @declared_attr def t2(cls): """this is another document.""" @@ -2875,7 +2875,7 @@ class DeclarativeMixinPropertyTest(DeclarativeTestBase): class MyMixin(object): - @mapperproperty + @declared_attr def type_(cls): return Column(String(50)) __mapper_args__ = {'polymorphic_on': type_} @@ -2894,7 +2894,7 @@ class DeclarativeMixinPropertyTest(DeclarativeTestBase): class MyMixin(object): - @mapperproperty + @declared_attr def data(cls): return deferred(Column('data', String(50))) @@ -2918,19 +2918,19 @@ class DeclarativeMixinPropertyTest(DeclarativeTestBase): class RefTargetMixin(object): - @mapperproperty + @declared_attr def target_id(cls): return Column('target_id', ForeignKey('target.id')) if usestring: - @mapperproperty + @declared_attr def target(cls): return relationship('Target', primaryjoin='Target.id==%s.target_id' % cls.__name__) else: - @mapperproperty + @declared_attr def target(cls): return relationship('Target') -- 2.47.2