U aA@sdZddlmZddlmZddlmZddlmZddlmZddl m Z ddl m Z dd l mZdd lmZdd lmZdd lmZed dddZGdddeZGdddeZGdddeZdS)z1Public API functions and helpers for declarative.) inspection)util)exc)registry) relationships)_mapper_or_none) _resolver)_DeferredMapperConfig)polymorphic_union)Table) OrderedDictz2.0zthe instrument_declarative function is deprecated and will be removed in SQLAlhcemy 2.0. Please use :meth:`_orm.registry.map_declarativelycCst||d|dS)zGiven a class, configure the class declaratively, using the given registry, which can be any dictionary, and MetaData object. )metadataZclass_registryN)rZmap_declaratively)clsZ cls_registryr rfC:\Users\vtejo\AppData\Local\Temp\pip-unpacked-wheel-nyjtotrf\sqlalchemy\ext\declarative\extensions.pyinstrument_declaratives rc@s(eZdZdZeddZeddZdS) ConcreteBasea_ A helper class for 'concrete' declarative mappings. :class:`.ConcreteBase` will use the :func:`.polymorphic_union` function automatically, against all tables mapped as a subclass to this class. The function is called via the ``__declare_last__()`` function, which is essentially a hook for the :meth:`.after_configured` event. :class:`.ConcreteBase` produces a mapped table for the class itself. Compare to :class:`.AbstractConcreteBase`, which does not. Example:: from sqlalchemy.ext.declarative import ConcreteBase class Employee(ConcreteBase, Base): __tablename__ = 'employee' employee_id = Column(Integer, primary_key=True) name = Column(String(50)) __mapper_args__ = { 'polymorphic_identity':'employee', 'concrete':True} class Manager(Employee): __tablename__ = 'manager' employee_id = Column(Integer, primary_key=True) name = Column(String(50)) manager_data = Column(String(40)) __mapper_args__ = { 'polymorphic_identity':'manager', 'concrete':True} The name of the discriminator column used by :func:`.polymorphic_union` defaults to the name ``type``. To suit the use case of a mapping where an actual column in a mapped table is already named ``type``, the discriminator name can be configured by setting the ``_concrete_discriminator_name`` attribute:: class Employee(ConcreteBase, Base): _concrete_discriminator_name = '_concrete_discriminator' .. versionadded:: 1.3.19 Added the ``_concrete_discriminator_name`` attribute to :class:`_declarative.ConcreteBase` so that the virtual discriminator column name can be customized. .. versionchanged:: 1.4.2 The ``_concrete_discriminator_name`` attribute need only be placed on the basemost class to take correct effect for all subclasses. An explicit error message is now raised if the mapped column names conflict with the discriminator name, whereas in the 1.3.x series there would be some warnings and then a non-useful query would be generated. .. seealso:: :class:`.AbstractConcreteBase` :ref:`concrete_inheritance` cCsttdd|D|dS)Ncss|]}|j|jfVqdSN)Zpolymorphic_identity local_table).0mprrr ksz9ConcreteBase._create_polymorphic_union..pjoin)r r )rmappersdiscriminator_namerrr_create_polymorphic_unionhsz&ConcreteBase._create_polymorphic_unioncCsX|j}|jrdSt|ddpd}t|j}|||}|d|f||j|dS)N_concrete_discriminator_nametype*) __mapper__Zwith_polymorphicgetattrlistZself_and_descendantsrZ_set_with_polymorphicZ_set_polymorphic_onc)rmrrrrrr__declare_first__rs  zConcreteBase.__declare_first__N)__name__ __module__ __qualname____doc__ classmethodrr$rrrrr(s ? rc@s8eZdZdZdZeddZeddZeddZd S) AbstractConcreteBasea7A helper class for 'concrete' declarative mappings. :class:`.AbstractConcreteBase` will use the :func:`.polymorphic_union` function automatically, against all tables mapped as a subclass to this class. The function is called via the ``__declare_last__()`` function, which is essentially a hook for the :meth:`.after_configured` event. :class:`.AbstractConcreteBase` does produce a mapped class for the base class, however it is not persisted to any table; it is instead mapped directly to the "polymorphic" selectable directly and is only used for selecting. Compare to :class:`.ConcreteBase`, which does create a persisted table for the base class. .. note:: The :class:`.AbstractConcreteBase` class does not intend to set up the mapping for the base class until all the subclasses have been defined, as it needs to create a mapping against a selectable that will include all subclass tables. In order to achieve this, it waits for the **mapper configuration event** to occur, at which point it scans through all the configured subclasses and sets up a mapping that will query against all subclasses at once. While this event is normally invoked automatically, in the case of :class:`.AbstractConcreteBase`, it may be necessary to invoke it explicitly after **all** subclass mappings are defined, if the first operation is to be a query against this base class. To do so, invoke :func:`.configure_mappers` once all the desired classes have been configured:: from sqlalchemy.orm import configure_mappers configure_mappers() .. seealso:: :func:`_orm.configure_mappers` Example:: from sqlalchemy.ext.declarative import AbstractConcreteBase class Employee(AbstractConcreteBase, Base): pass class Manager(Employee): __tablename__ = 'manager' employee_id = Column(Integer, primary_key=True) name = Column(String(50)) manager_data = Column(String(40)) __mapper_args__ = { 'polymorphic_identity':'manager', 'concrete':True} configure_mappers() The abstract base class is handled by declarative in a special way; at class configuration time, it behaves like a declarative mixin or an ``__abstract__`` base class. Once classes are configured and mappings are produced, it then gets mapped itself, but after all of its descendants. This is a very unique system of mapping not found in any other SQLAlchemy system. Using this approach, we can specify columns and properties that will take place on mapped subclasses, in the way that we normally do as in :ref:`declarative_mixins`:: class Company(Base): __tablename__ = 'company' id = Column(Integer, primary_key=True) class Employee(AbstractConcreteBase, Base): employee_id = Column(Integer, primary_key=True) @declared_attr def company_id(cls): return Column(ForeignKey('company.id')) @declared_attr def company(cls): return relationship("Company") class Manager(Employee): __tablename__ = 'manager' name = Column(String(50)) manager_data = Column(String(40)) __mapper_args__ = { 'polymorphic_identity':'manager', 'concrete':True} configure_mappers() When we make use of our mappings however, both ``Manager`` and ``Employee`` will have an independently usable ``.company`` attribute:: session.query(Employee).filter(Employee.company.has(id=5)) .. versionchanged:: 1.0.0 - The mechanics of :class:`.AbstractConcreteBase` have been reworked to support relationships established directly on the abstract base, without any special configurational steps. .. seealso:: :class:`.ConcreteBase` :ref:`concrete_inheritance` TcCs |dSr)_sa_decl_prepare_nocascaderrrrr$sz&AbstractConcreteBase.__declare_first__c st|ddrdSt|}g}t|}|r`|}||t|}|dk r*||q*t|ddpnd| |t |j }t|j D]"\}}||krj|j|j |<q|_|jptfdd} | |_|} |D]*} t| } | r| jr|| jkr| | qdS)Nrrrcs}j|d<|S)NZpolymorphic_on)r")argsrZm_argsrrr mapper_args#szDAbstractConcreteBase._sa_decl_prepare_nocascade..mapper_args)r r Zconfig_for_clsr!__subclasses__popextendrappendrsetZdeclared_columnsZ propertiesitemsr"keyrZmapper_args_fndictmapZconcrete __bases__Z_set_concrete_base) rto_maprstackklassmnZ declared_colskvr/r#Zsclssmrr.rr+s6        z/AbstractConcreteBase._sa_decl_prepare_nocascadecCstj|dt|ddS)NzClass %s is a subclass of AbstractConcreteBase and has a mapping pending until all subclasses are defined. Call the sqlalchemy.orm.configure_mappers() function after all subclasses have been defined to complete the mapping of this class.msgorm_excZUnmappedClassErrorZ_safe_cls_namer,rrr_sa_raise_deferred_config1s z.AbstractConcreteBase._sa_raise_deferred_configN) r%r&r'r(Z __no_table__r)r$r+rErrrrr*sr  5r*c@sLeZdZdZeddZeddZeddZedd Zed d Z d S) DeferredReflectiona A helper class for construction of mappings based on a deferred reflection step. Normally, declarative can be used with reflection by setting a :class:`_schema.Table` object using autoload_with=engine as the ``__table__`` attribute on a declarative class. The caveat is that the :class:`_schema.Table` must be fully reflected, or at the very least have a primary key column, at the point at which a normal declarative mapping is constructed, meaning the :class:`_engine.Engine` must be available at class declaration time. The :class:`.DeferredReflection` mixin moves the construction of mappers to be at a later point, after a specific method is called which first reflects all :class:`_schema.Table` objects created so far. Classes can define it as such:: from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import DeferredReflection Base = declarative_base() class MyClass(DeferredReflection, Base): __tablename__ = 'mytable' Above, ``MyClass`` is not yet mapped. After a series of classes have been defined in the above fashion, all tables can be reflected and mappings created using :meth:`.prepare`:: engine = create_engine("someengine://...") DeferredReflection.prepare(engine) The :class:`.DeferredReflection` mixin can be applied to individual classes, used as the base for the declarative base itself, or used in a custom abstract class. Using an abstract base allows that only a subset of classes to be prepared for a particular prepare step, which is necessary for applications that use more than one engine. For example, if an application has two engines, you might use two bases, and prepare each separately, e.g.:: class ReflectedOne(DeferredReflection, Base): __abstract__ = True class ReflectedTwo(DeferredReflection, Base): __abstract__ = True class MyClass(ReflectedOne): __tablename__ = 'mytable' class MyOtherClass(ReflectedOne): __tablename__ = 'myothertable' class YetAnotherClass(ReflectedTwo): __tablename__ = 'yetanothertable' # ... etc. Above, the class hierarchies for ``ReflectedOne`` and ``ReflectedTwo`` can be configured separately:: ReflectedOne.prepare(engine_one) ReflectedTwo.prepare(engine_two) c Cst|}t|}|D]}||j|||jj }|j j }|j D]}t|tjrR|jdk rRt|jtr||j|qRt|jtrRt|jj |\}} | |j|_|jj|||f7_||_qRqW5QRXdS)zjReflect all :class:`_schema.Table` objects for all current :class:`.DeferredReflection` subclassesN)r Zclasses_for_baserinspectZ_inspection_context_sa_decl_preparerr8rrclass_r Z_propsvalues isinstancerZRelationshipPropertyZ secondaryr _reflect_tablestrrparentZ _resolvers_sa_deferred_table_resolver) rZenginer:ZinspZthingyZmapperr rel_Z resolve_argrrrprepares0      zDeferredReflection.preparecsfdd}|S)Ncst|}||Sr)r rL)r6t1r inspectorr rr_resolves  z@DeferredReflection._sa_deferred_table_resolver.._resolver)rrUr rVrrTrrOsz.DeferredReflection._sa_deferred_table_resolvercCs|dk r|||dSr)rL)rrrUrrrrHsz#DeferredReflection._sa_decl_preparecCstj|dt|ddS)NzClass %s is a subclass of DeferredReflection. Mappings are not produced until the .prepare() method is called on the class hierarchy.rArCr,rrrrEs z,DeferredReflection._sa_raise_deferred_configcCst|j|jdd||jddS)NTF)Zextend_existingZautoload_replaceZ autoload_withschema)r namer rW)rtablerUrrrrLsz!DeferredReflection._reflect_tableN) r%r&r'r(r)rRrOrHrErLrrrrrF>sB #   rFN)r(rrZormrrDrrZorm.baserZorm.clsregistryrZ orm.decl_baser Zorm.utilr rWr r deprecatedrobjectrr*rFrrrrs(            Z=