From 7f07d43fb127a2b2283a7d17a714ed175498b6b9 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 28 Dec 2011 11:10:49 -0500 Subject: [PATCH] - [feature] Added "class_registry" argument to declarative_base(). Allows two or more declarative bases to share the same registry of class names. --- CHANGES | 4 ++++ lib/sqlalchemy/ext/declarative.py | 13 ++++++++++++- test/ext/test_declarative.py | 17 +++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index f5540e1e0f..56aede3c88 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,10 @@ CHANGES - [bug] Fixed bug whereby hybrid_property didn't work as a kw arg in any(), has(). + - [feature] Added "class_registry" argument to + declarative_base(). Allows two or more declarative + bases to share the same registry of class names. + - Py3K - [bug] Fixed inappropriate usage of util.py3k flag and renamed it to util.py3k_warning, since diff --git a/lib/sqlalchemy/ext/declarative.py b/lib/sqlalchemy/ext/declarative.py index 91d770197c..dc84c5dfb6 100755 --- a/lib/sqlalchemy/ext/declarative.py +++ b/lib/sqlalchemy/ext/declarative.py @@ -1500,6 +1500,7 @@ _declarative_constructor.__name__ = '__init__' def declarative_base(bind=None, metadata=None, mapper=None, cls=object, name='Base', constructor=_declarative_constructor, + class_registry=None, metaclass=DeclarativeMeta): """Construct a base class for declarative class definitions. @@ -1543,6 +1544,13 @@ def declarative_base(bind=None, metadata=None, mapper=None, cls=object, no __init__ will be provided and construction will fall back to cls.__init__ by way of the normal Python semantics. + :param class_registry: optional dictionary that will serve as the + registry of class names-> mapped classes when string names + are used to identify classes inside of :func:`.relationship` + and others. Allows two or more declarative base classes + to share the same registry of class names for simplified + inter-base relationships. + :param metaclass: Defaults to :class:`.DeclarativeMeta`. A metaclass or __metaclass__ compatible callable to use as the meta type of the generated @@ -1553,8 +1561,11 @@ def declarative_base(bind=None, metadata=None, mapper=None, cls=object, if bind: lcl_metadata.bind = bind + if class_registry is None: + class_registry = {} + bases = not isinstance(cls, tuple) and (cls,) or cls - class_dict = dict(_decl_class_registry=dict(), + class_dict = dict(_decl_class_registry=class_registry, metadata=lcl_metadata) if constructor: diff --git a/test/ext/test_declarative.py b/test/ext/test_declarative.py index 2e2989a646..3069c2bfec 100644 --- a/test/ext/test_declarative.py +++ b/test/ext/test_declarative.py @@ -368,6 +368,23 @@ class DeclarativeTest(DeclarativeTestBase): assert class_mapper(User).get_property('props').secondary \ is user_to_prop + def test_shared_class_registry(self): + reg = {} + Base1 = decl.declarative_base(testing.db, class_registry=reg) + Base2 = decl.declarative_base(testing.db, class_registry=reg) + + class A(Base1): + __tablename__ = 'a' + id = Column(Integer, primary_key=True) + + class B(Base2): + __tablename__ = 'b' + id = Column(Integer, primary_key=True) + aid = Column(Integer, ForeignKey(A.id)) + as_ = relationship("A") + + assert B.as_.property.mapper.class_ is A + def test_uncompiled_attributes_in_relationship(self): class Address(Base, fixtures.ComparableEntity): -- 2.47.2