Anonymous avatar Anonymous committed 11e40e2

- Added an explicit check for the case that the name
'metadata' is used for a column attribute on a
declarative class. [ticket:2050]

Comments (0)

Files changed (3)

   - oursql dialect accepts the same "ssl" arguments in 
     create_engine() as that of MySQLdb.  [ticket:2047]
 
+- declarative
+  - Added an explicit check for the case that the name
+    'metadata' is used for a column attribute on a 
+    declarative class. [ticket:2050]
+
+
 0.6.6
 =====
 - orm

lib/sqlalchemy/ext/declarative.py

 from sqlalchemy.orm.interfaces import MapperProperty
 from sqlalchemy.orm.properties import RelationshipProperty, ColumnProperty, CompositeProperty
 from sqlalchemy.orm.util import _is_mapped_class
-from sqlalchemy import util, exceptions
+from sqlalchemy import util, exc
 from sqlalchemy.sql import util as sql_util, expression
 
 
 
     """
     if '_decl_class_registry' in cls.__dict__:
-        raise exceptions.InvalidRequestError(
+        raise exc.InvalidRequestError(
                             "Class %r already has been "
                             "instrumented declaratively" % cls)
     cls._decl_class_registry = registry
                                     ):
                     table_args = cls.__table_args__
                     if not isinstance(table_args, (tuple, dict, type(None))):
-                        raise exceptions.ArgumentError(
+                        raise exc.ArgumentError(
                                 "__table_args__ value must be a tuple, "
                                 "dict, or None")
                     if base is not cls:
 
                 if isinstance(obj, Column):
                     if obj.foreign_keys:
-                        raise exceptions.InvalidRequestError(
+                        raise exc.InvalidRequestError(
                         "Columns with foreign keys to other columns "
                         "must be declared as @classproperty callables "
                         "on declarative mixin classes. ")
                         column_copies[obj]._creation_order = \
                                 obj._creation_order
                 elif isinstance(obj, MapperProperty):
-                    raise exceptions.InvalidRequestError(
+                    raise exc.InvalidRequestError(
                         "Mapper properties (i.e. deferred,"
                         "column_property(), relationship(), etc.) must "
                         "be declared as @classproperty callables "
             continue
         if not isinstance(value, (Column, MapperProperty)):
             continue
+        if k == 'metadata':
+            raise exc.InvalidRequestError(
+                "Attribute name 'metadata' is reserved "
+                "for the MetaData instance when using a "
+                "declarative base class."
+            )
         prop = _deferred_relationship(cls, value)
         our_stuff[k] = prop
 
                 args = table_args[0:-1]
                 table_kw = table_args[-1]
                 if len(table_args) < 2 or not isinstance(table_kw, dict):
-                    raise exceptions.ArgumentError(
+                    raise exc.ArgumentError(
                         "Tuple form of __table_args__ is "
                         "(arg1, arg2, arg3, ..., {'kw1':val1, "
                         "'kw2':val2, ...})"
         if cols:
             for c in cols:
                 if not table.c.contains_column(c):
-                    raise exceptions.ArgumentError(
+                    raise exc.ArgumentError(
                         "Can't add additional column %r when "
                         "specifying __table__" % c.key
                     )
         mapper_cls = mapper
 
     if table is None and 'inherits' not in mapper_args:
-        raise exceptions.InvalidRequestError(
+        raise exc.InvalidRequestError(
             "Class %r does not have a __table__ or __tablename__ "
             "specified and does not inherit from an existing "
             "table-mapped class." % cls
             # single table inheritance.
             # ensure no table args
             if table_args:
-                raise exceptions.ArgumentError(
+                raise exc.ArgumentError(
                     "Can't place __table_args__ on an inherited class "
                     "with no table."
                     )
             # add any columns declared here to the inherited table.
             for c in cols:
                 if c.primary_key:
-                    raise exceptions.ArgumentError(
+                    raise exc.ArgumentError(
                         "Can't place primary key columns on an inherited "
                         "class with no table."
                         )
                 if c.name in inherited_table.c:
-                    raise exceptions.ArgumentError(
+                    raise exc.ArgumentError(
                         "Column '%s' on class %s conflicts with "
                         "existing column '%s'" % 
                         (c, cls, inherited_table.c[c.name])
         mapper = class_mapper(self.cls, compile=False)
         if mapper:
             if not mapper.has_property(key):
-                raise exceptions.InvalidRequestError(
+                raise exc.InvalidRequestError(
                             "Class %r does not have a mapped column named %r"
                             % (self.cls, key))
 
             prop = mapper.get_property(key)
             if not isinstance(prop, ColumnProperty):
-                raise exceptions.InvalidRequestError(
+                raise exc.InvalidRequestError(
                             "Property %r is not an instance of"
                             " ColumnProperty (i.e. does not correspond"
                             " directly to a Column)." % key)
                 else:
                     return x
             except NameError, n:
-                raise exceptions.InvalidRequestError(
+                raise exc.InvalidRequestError(
                     "When initializing mapper %s, expression %r failed to "
                     "locate a name (%r). If this is a class name, consider "
                     "adding this relationship() to the %r class after "

test/ext/test_declarative.py

 
         decl.instrument_declarative(User,{},Base.metadata)
 
+    def test_reserved_identifiers(self):
+        def go1():
+            class User1(Base):
+                __tablename__ = 'user1'
+                id = Column(Integer, primary_key=True)
+                metadata = Column(Integer)
+
+        def go2():
+            class User2(Base):
+                __tablename__ = 'user2'
+                id = Column(Integer, primary_key=True)
+                metadata = relationship("Address")
+
+        for go in (go1, go2):
+            assert_raises_message(
+                exc.InvalidRequestError,
+                "Attribute name 'metadata' is reserved "
+                "for the MetaData instance when using a "
+                "declarative base class.",
+                go
+            )
 
     def test_undefer_column_name(self):
         # TODO: not sure if there was an explicit
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.