]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- The ``info`` parameter has been added to the constructor for
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 13 Aug 2014 23:45:34 +0000 (19:45 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 13 Aug 2014 23:45:34 +0000 (19:45 -0400)
:class:`.SynonymProperty` and :class:`.ComparableProperty`.
- The ``info`` parameter has been added as a constructor argument
to all schema constructs including :class:`.MetaData`,
:class:`.Index`, :class:`.ForeignKey`, :class:`.ForeignKeyConstraint`,
:class:`.UniqueConstraint`, :class:`.PrimaryKeyConstraint`,
:class:`.CheckConstraint`.

fixes #2963

doc/build/changelog/changelog_10.rst
lib/sqlalchemy/orm/descriptor_props.py
lib/sqlalchemy/sql/schema.py
lib/sqlalchemy/util/langhelpers.py
test/orm/test_mapper.py
test/sql/test_metadata.py

index c59d7c912d9cbfcd6e97c9c88d19beb5715cf422..815de72c71a4527472cc3464e1a9bfed98e59424 100644 (file)
 .. changelog::
        :version: 1.0.0
 
+    .. change::
+        :tags: orm, feature
+        :tickets: 2963
+
+        The ``info`` parameter has been added to the constructor for
+        :class:`.SynonymProperty` and :class:`.ComparableProperty`.
+
+    .. change::
+        :tags: sql, feature
+        :tickets: 2963
+
+        The ``info`` parameter has been added as a constructor argument
+        to all schema constructs including :class:`.MetaData`,
+        :class:`.Index`, :class:`.ForeignKey`, :class:`.ForeignKeyConstraint`,
+        :class:`.UniqueConstraint`, :class:`.PrimaryKeyConstraint`,
+        :class:`.CheckConstraint`.
+
     .. change::
         :tags: orm, feature
         :tickets: 2971
index 5ed24b8c0fe16eaaa54d9dc3f87ada986074aa77..f0f9a6468e84d234b960f218f9a07bb47e9b348f 100644 (file)
@@ -496,7 +496,7 @@ class SynonymProperty(DescriptorProperty):
 
     def __init__(self, name, map_column=None,
                  descriptor=None, comparator_factory=None,
-                 doc=None):
+                 doc=None, info=None):
         """Denote an attribute name as a synonym to a mapped property,
         in that the attribute will mirror the value and expression behavior
         of another attribute.
@@ -531,6 +531,11 @@ class SynonymProperty(DescriptorProperty):
           conjunction with the ``descriptor`` argument in order to link a
           user-defined descriptor as a "wrapper" for an existing column.
 
+        :param info: Optional data dictionary which will be populated into the
+            :attr:`.InspectionAttr.info` attribute of this object.
+
+            .. versionadded:: 1.0.0
+
         :param comparator_factory: A subclass of :class:`.PropComparator`
           that will provide custom comparison behavior at the SQL expression
           level.
@@ -556,6 +561,8 @@ class SynonymProperty(DescriptorProperty):
         self.descriptor = descriptor
         self.comparator_factory = comparator_factory
         self.doc = doc or (descriptor and descriptor.__doc__) or None
+        if info:
+            self.info = info
 
         util.set_creation_order(self)
 
@@ -608,7 +615,8 @@ class SynonymProperty(DescriptorProperty):
 class ComparableProperty(DescriptorProperty):
     """Instruments a Python property for use in query expressions."""
 
-    def __init__(self, comparator_factory, descriptor=None, doc=None):
+    def __init__(
+            self, comparator_factory, descriptor=None, doc=None, info=None):
         """Provides a method of applying a :class:`.PropComparator`
         to any Python descriptor attribute.
 
@@ -670,10 +678,17 @@ class ComparableProperty(DescriptorProperty):
           The like-named descriptor will be automatically retrieved from the
           mapped class if left blank in a ``properties`` declaration.
 
+        :param info: Optional data dictionary which will be populated into the
+            :attr:`.InspectionAttr.info` attribute of this object.
+
+            .. versionadded:: 1.0.0
+
         """
         self.descriptor = descriptor
         self.comparator_factory = comparator_factory
         self.doc = doc or (descriptor and descriptor.__doc__) or None
+        if info:
+            self.info = info
         util.set_creation_order(self)
 
     def _comparator_factory(self, mapper):
index 69b3af306d199c13248dd2b2eedec71830c534e2..8099dca75948cebedf4ca8a5f5f8c401167df35c 100644 (file)
@@ -76,7 +76,7 @@ class SchemaItem(SchemaEventTarget, visitors.Visitable):
         return []
 
     def __repr__(self):
-        return util.generic_repr(self)
+        return util.generic_repr(self, omit_kwarg=['info'])
 
     @property
     @util.deprecated('0.9', 'Use ``<obj>.name.quote``')
@@ -1403,6 +1403,7 @@ class ForeignKey(DialectKWArgs, SchemaItem):
     def __init__(self, column, _constraint=None, use_alter=False, name=None,
                  onupdate=None, ondelete=None, deferrable=None,
                  initially=None, link_to_name=False, match=None,
+                 info=None,
                  **dialect_kw):
         """
         Construct a column-level FOREIGN KEY.
@@ -1453,6 +1454,11 @@ class ForeignKey(DialectKWArgs, SchemaItem):
             DDL for this constraint. Typical values include SIMPLE, PARTIAL
             and FULL.
 
+        :param info: Optional data dictionary which will be populated into the
+            :attr:`.SchemaItem.info` attribute of this object.
+
+            .. versionadded:: 1.0.0
+
         :param \**dialect_kw:  Additional keyword arguments are dialect
             specific, and passed in the form ``<dialectname>_<argname>``.  The
             arguments are ultimately handled by a corresponding
@@ -1499,6 +1505,8 @@ class ForeignKey(DialectKWArgs, SchemaItem):
         self.initially = initially
         self.link_to_name = link_to_name
         self.match = match
+        if info:
+            self.info = info
         self._unvalidated_dialect_kw = dialect_kw
 
     def __repr__(self):
@@ -2223,7 +2231,7 @@ class Constraint(DialectKWArgs, SchemaItem):
     __visit_name__ = 'constraint'
 
     def __init__(self, name=None, deferrable=None, initially=None,
-                 _create_rule=None,
+                 _create_rule=None, info=None,
                  **dialect_kw):
         """Create a SQL constraint.
 
@@ -2238,6 +2246,11 @@ class Constraint(DialectKWArgs, SchemaItem):
           Optional string.  If set, emit INITIALLY <value> when issuing DDL
           for this constraint.
 
+        :param info: Optional data dictionary which will be populated into the
+            :attr:`.SchemaItem.info` attribute of this object.
+
+            .. versionadded:: 1.0.0
+
         :param _create_rule:
           a callable which is passed the DDLCompiler object during
           compilation. Returns True or False to signal inline generation of
@@ -2265,6 +2278,8 @@ class Constraint(DialectKWArgs, SchemaItem):
         self.name = name
         self.deferrable = deferrable
         self.initially = initially
+        if info:
+            self.info = info
         self._create_rule = _create_rule
         util.set_creation_order(self)
         self._validate_dialect_kwargs(dialect_kw)
@@ -2381,7 +2396,7 @@ class CheckConstraint(Constraint):
     """
 
     def __init__(self, sqltext, name=None, deferrable=None,
-                 initially=None, table=None, _create_rule=None,
+                 initially=None, table=None, info=None, _create_rule=None,
                  _autoattach=True):
         """Construct a CHECK constraint.
 
@@ -2404,10 +2419,15 @@ class CheckConstraint(Constraint):
           Optional string.  If set, emit INITIALLY <value> when issuing DDL
           for this constraint.
 
+        :param info: Optional data dictionary which will be populated into the
+            :attr:`.SchemaItem.info` attribute of this object.
+
+            .. versionadded:: 1.0.0
+
         """
 
         super(CheckConstraint, self).\
-            __init__(name, deferrable, initially, _create_rule)
+            __init__(name, deferrable, initially, _create_rule, info=info)
         self.sqltext = _literal_as_text(sqltext)
         if table is not None:
             self._set_parent_with_dispatch(table)
@@ -2463,7 +2483,7 @@ class ForeignKeyConstraint(Constraint):
     def __init__(self, columns, refcolumns, name=None, onupdate=None,
                  ondelete=None, deferrable=None, initially=None,
                  use_alter=False, link_to_name=False, match=None,
-                 table=None, **dialect_kw):
+                 table=None, info=None, **dialect_kw):
         """Construct a composite-capable FOREIGN KEY.
 
         :param columns: A sequence of local column names. The named columns
@@ -2508,6 +2528,11 @@ class ForeignKeyConstraint(Constraint):
           DDL for this constraint. Typical values include SIMPLE, PARTIAL
           and FULL.
 
+        :param info: Optional data dictionary which will be populated into the
+            :attr:`.SchemaItem.info` attribute of this object.
+
+            .. versionadded:: 1.0.0
+
         :param \**dialect_kw:  Additional keyword arguments are dialect
           specific, and passed in the form ``<dialectname>_<argname>``.  See
           the documentation regarding an individual dialect at
@@ -2517,7 +2542,7 @@ class ForeignKeyConstraint(Constraint):
 
         """
         super(ForeignKeyConstraint, self).\
-            __init__(name, deferrable, initially, **dialect_kw)
+            __init__(name, deferrable, initially, info=info, **dialect_kw)
 
         self.onupdate = onupdate
         self.ondelete = ondelete
@@ -2888,6 +2913,11 @@ class Index(DialectKWArgs, ColumnCollectionMixin, SchemaItem):
             the index.  Works in the same manner as that of
             :paramref:`.Column.quote`.
 
+        :param info=None: Optional data dictionary which will be populated
+            into the :attr:`.SchemaItem.info` attribute of this object.
+
+            .. versionadded:: 1.0.0
+
         :param \**kw: Additional keyword arguments not mentioned above are
             dialect specific, and passed in the form
             ``<dialectname>_<argname>``. See the documentation regarding an
@@ -2910,6 +2940,8 @@ class Index(DialectKWArgs, ColumnCollectionMixin, SchemaItem):
         self.expressions = expressions
         self.name = quoted_name(name, kw.pop("quote", None))
         self.unique = kw.pop('unique', False)
+        if 'info' in kw:
+            self.info = kw.pop('info')
         self._validate_dialect_kwargs(kw)
 
         # will call _set_parent() if table-bound column
@@ -3020,7 +3052,8 @@ class MetaData(SchemaItem):
 
     def __init__(self, bind=None, reflect=False, schema=None,
                  quote_schema=None,
-                 naming_convention=DEFAULT_NAMING_CONVENTION
+                 naming_convention=DEFAULT_NAMING_CONVENTION,
+                 info=None
                  ):
         """Create a new MetaData object.
 
@@ -3046,6 +3079,11 @@ class MetaData(SchemaItem):
             :class:`.Sequence`, and other objects which make usage of the
             local ``schema`` name.
 
+        :param info: Optional data dictionary which will be populated into the
+            :attr:`.SchemaItem.info` attribute of this object.
+
+            .. versionadded:: 1.0.0
+
         :param naming_convention: a dictionary referring to values which
           will establish default naming conventions for :class:`.Constraint`
           and :class:`.Index` objects, for those objects which are not given
@@ -3117,6 +3155,8 @@ class MetaData(SchemaItem):
         self.tables = util.immutabledict()
         self.schema = quoted_name(schema, quote_schema)
         self.naming_convention = naming_convention
+        if info:
+            self.info = info
         self._schemas = set()
         self._sequences = {}
         self._fk_memos = collections.defaultdict(list)
index 8d6fe5a28f10482bc8b1d19317c971143c982099..828e8f1f322b0ebdeb05b958a5772d19fc2504ec 100644 (file)
@@ -435,7 +435,7 @@ def unbound_method_to_callable(func_or_cls):
         return func_or_cls
 
 
-def generic_repr(obj, additional_kw=(), to_inspect=None):
+def generic_repr(obj, additional_kw=(), to_inspect=None, omit_kwarg=()):
     """Produce a __repr__() based on direct association of the __init__()
     specification vs. same-named attributes present.
 
@@ -484,6 +484,8 @@ def generic_repr(obj, additional_kw=(), to_inspect=None):
         output.extend([repr(val) for val in getattr(obj, vargs)])
 
     for arg, defval in kw_args.items():
+        if arg in omit_kwarg:
+            continue
         try:
             val = getattr(obj, arg, missing)
             if val is not missing and val != defval:
index e33c93977f32775b8abaa29f9ef72cdf0e65b5bf..0a9cbfc718c3f8ff2196299f7321c67bbd9e7c21 100644 (file)
@@ -414,7 +414,9 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL):
         for constructor, args in [
             (column_property, (users.c.name,)),
             (relationship, (Address,)),
-            (composite, (MyComposite, 'id', 'name'))
+            (composite, (MyComposite, 'id', 'name')),
+            (synonym, 'foo'),
+            (comparable_property, 'foo')
         ]:
             obj = constructor(info={"x": "y"}, *args)
             eq_(obj.info, {"x": "y"})
index 3a252c646b16116a24de1da7e133a37f645ba78a..ff2755ab1dd5b2e4d43496b3b30d587cd9884e36 100644 (file)
@@ -956,6 +956,71 @@ class ToMetaDataTest(fixtures.TestBase, ComparesTables):
             'mytable.myid = othertable.myid')
 
 
+class InfoTest(fixtures.TestBase):
+    def test_metadata_info(self):
+        m1 = MetaData()
+        eq_(m1.info, {})
+
+        m1 = MetaData(info={"foo": "bar"})
+        eq_(m1.info, {"foo": "bar"})
+
+    def test_foreignkey_constraint_info(self):
+        fkc = ForeignKeyConstraint(['a'], ['b'], name='bar')
+        eq_(fkc.info, {})
+
+        fkc = ForeignKeyConstraint(
+            ['a'], ['b'], name='bar', info={"foo": "bar"})
+        eq_(fkc.info, {"foo": "bar"})
+
+    def test_foreignkey_info(self):
+        fkc = ForeignKey('a')
+        eq_(fkc.info, {})
+
+        fkc = ForeignKey('a', info={"foo": "bar"})
+        eq_(fkc.info, {"foo": "bar"})
+
+    def test_primarykey_constraint_info(self):
+        pkc = PrimaryKeyConstraint('a', name='x')
+        eq_(pkc.info, {})
+
+        pkc = PrimaryKeyConstraint('a', name='x', info={'foo': 'bar'})
+        eq_(pkc.info, {'foo': 'bar'})
+
+    def test_unique_constraint_info(self):
+        uc = UniqueConstraint('a', name='x')
+        eq_(uc.info, {})
+
+        uc = UniqueConstraint('a', name='x', info={'foo': 'bar'})
+        eq_(uc.info, {'foo': 'bar'})
+
+    def test_check_constraint_info(self):
+        cc = CheckConstraint('foo=bar', name='x')
+        eq_(cc.info, {})
+
+        cc = CheckConstraint('foo=bar', name='x', info={'foo': 'bar'})
+        eq_(cc.info, {'foo': 'bar'})
+
+    def test_index_info(self):
+        ix = Index('x', 'a')
+        eq_(ix.info, {})
+
+        ix = Index('x', 'a', info={'foo': 'bar'})
+        eq_(ix.info, {'foo': 'bar'})
+
+    def test_column_info(self):
+        c = Column('x', Integer)
+        eq_(c.info, {})
+
+        c = Column('x', Integer, info={'foo': 'bar'})
+        eq_(c.info, {'foo': 'bar'})
+
+    def test_table_info(self):
+        t = Table('x', MetaData())
+        eq_(t.info, {})
+
+        t = Table('x', MetaData(), info={'foo': 'bar'})
+        eq_(t.info, {'foo': 'bar'})
+
 class TableTest(fixtures.TestBase, AssertsCompiledSQL):
 
     @testing.skip_if('mssql', 'different col format')