.. autoclass:: sqlalchemy.orm.properties.ColumnProperty
:members:
-.. autoclass:: sqlalchemy.orm.properties.ComparableProperty
+.. autoclass:: sqlalchemy.orm.descriptor_props.ComparableProperty
:members:
.. autoclass:: sqlalchemy.orm.descriptor_props.CompositeProperty
:members:
:inherited-members:
-.. autoclass:: sqlalchemy.orm.properties.RelationshipProperty
+.. autoclass:: sqlalchemy.orm.relationships.RelationshipProperty
:members:
:inherited-members:
from sqlalchemy.orm import mapper
from sqlalchemy.orm import object_mapper
from sqlalchemy.orm.exc import UnmappedColumnError
-from sqlalchemy.orm.properties import RelationshipProperty
+from sqlalchemy.orm.relationships import RelationshipProperty
def col_references_table(col, table):
if not (name.startswith("_") or _inspect.ismodule(obj))
)
- _sa_util.dependencies.resolve_all("sqlalchemy")
+ _sa_util.preloaded.import_prefix("sqlalchemy")
__go(locals())
from .. import util as _sa_util
-_sa_util.dependencies.resolve_all("sqlalchemy.ext")
+_sa_util.preloaded.import_prefix("sqlalchemy.ext")
from ...orm import comparable_property
from ...orm import exc as orm_exc
from ...orm import interfaces
-from ...orm import properties
+from ...orm import relationships
from ...orm import synonym as _orm_synonym
from ...orm.base import _inspect_mapped_class
from ...orm.base import _mapper_or_none
metadata = mapper.class_.metadata
for rel in mapper._props.values():
if (
- isinstance(rel, properties.RelationshipProperty)
+ isinstance(rel, relationships.RelationshipProperty)
and rel.secondary is not None
):
if isinstance(rel.secondary, Table):
from ...orm.attributes import QueryableAttribute
from ...orm.base import _is_mapped_class
from ...orm.base import InspectionAttr
+from ...orm.descriptor_props import CompositeProperty
from ...orm.interfaces import MapperProperty
from ...orm.properties import ColumnProperty
-from ...orm.properties import CompositeProperty
from ...schema import Column
from ...schema import Table
from ...sql import expression
from ... import inspection
from ... import util
from ...orm import class_mapper
+from ...orm import ColumnProperty
from ...orm import interfaces
-from ...orm.properties import ColumnProperty
-from ...orm.properties import RelationshipProperty
-from ...orm.properties import SynonymProperty
+from ...orm import RelationshipProperty
+from ...orm import SynonymProperty
from ...schema import _get_table_key
if not (name.startswith("_") or _inspect.ismodule(obj))
)
- _sa_util.dependencies.resolve_all("sqlalchemy.orm")
- _sa_util.dependencies.resolve_all("sqlalchemy.ext")
+ _sa_util.preloaded.import_prefix("sqlalchemy.orm")
+ _sa_util.preloaded.import_prefix("sqlalchemy.ext")
__go(locals())
"""
from . import attributes
-from . import properties
from . import query
from .interfaces import MapperProperty
from .interfaces import PropComparator
mapper.class_manager.instrument_attribute(self.key, proxy_attr)
-@util.langhelpers.dependency_for("sqlalchemy.orm.properties", add_to_all=True)
class CompositeProperty(DescriptorProperty):
"""Defines a "composite" mapped attribute, representing a collection
of columns as one attribute.
return str(self.parent.class_.__name__) + "." + self.key
-@util.langhelpers.dependency_for("sqlalchemy.orm.properties", add_to_all=True)
class ConcreteInheritedProperty(DescriptorProperty):
"""A 'do nothing' :class:`.MapperProperty` that disables
an attribute on a concrete subclass that is only present
self.descriptor = NoninheritedConcreteProp()
-@util.langhelpers.dependency_for("sqlalchemy.orm.properties", add_to_all=True)
class SynonymProperty(DescriptorProperty):
def __init__(
self,
attr = getattr(self.parent.class_, self.name)
return attr.impl.get_history(*arg, **kw)
+ @util.preload_module("sqlalchemy.orm.properties")
def set_parent(self, parent, init):
+ properties = util.preloaded.orm_properties
+
if self.map_column:
# implement the 'map_column' option.
if self.key not in parent.persist_selectable.c:
self.parent = parent
-@util.langhelpers.dependency_for("sqlalchemy.orm.properties", add_to_all=True)
@util.deprecated_cls(
"0.7",
":func:`.comparable_property` is deprecated and will be removed in a "
from . import interfaces
from . import object_mapper
from . import object_session
-from . import properties
+from . import relationships
from . import strategies
from . import util as orm_util
from .query import Query
@log.class_logger
-@properties.RelationshipProperty.strategy_for(lazy="dynamic")
+@relationships.RelationshipProperty.strategy_for(lazy="dynamic")
class DynaLoader(strategies.AbstractRelationshipLoader):
def init_class_attribute(self, mapper):
self.is_class_level = True
_InstanceEventsHold.populate(class_, classmanager)
@classmethod
- @util.dependencies("sqlalchemy.orm")
- def _accept_with(cls, orm, target):
+ @util.preload_module("sqlalchemy.orm")
+ def _accept_with(cls, target):
+ orm = util.preloaded.orm
+
if isinstance(target, instrumentation.ClassManager):
return target
elif isinstance(target, mapperlib.Mapper):
_MapperEventsHold.populate(class_, mapper)
@classmethod
- @util.dependencies("sqlalchemy.orm")
- def _accept_with(cls, orm, target):
+ @util.preload_module("sqlalchemy.orm")
+ def _accept_with(cls, target):
+ orm = util.preloaded.orm
+
if target is orm.mapper:
return mapperlib.Mapper
elif isinstance(target, type):
class UnmappedInstanceError(UnmappedError):
"""An mapping operation was requested for an unknown instance."""
- @util.dependencies("sqlalchemy.orm.base")
- def __init__(self, base, obj, msg=None):
+ @util.preload_module("sqlalchemy.orm.base")
+ def __init__(self, obj, msg=None):
+ base = util.preloaded.orm_base
+
if not msg:
try:
base.class_mapper(type(obj))
"""
- @util.dependencies("sqlalchemy.orm.base")
- def __init__(self, base, state, msg=None):
+ @util.preload_module("sqlalchemy.orm.base")
+ def __init__(self, state, msg=None):
+ base = util.preloaded.orm_base
+
if not msg:
msg = (
"Instance '%s' has been deleted, or its "
return cls_name
-@util.dependencies("sqlalchemy.orm.base")
-def _default_unmapped(base, cls):
+@util.preload_module("sqlalchemy.orm.base")
+def _default_unmapped(cls):
+ base = util.preloaded.orm_base
+
try:
mappers = base.manager_of_class(cls).mappers
except NO_STATE:
cursor.close()
-@util.dependencies("sqlalchemy.orm.query")
-def merge_result(querylib, query, iterator, load=True):
+@util.preload_module("sqlalchemy.orm.query")
+def merge_result(query, iterator, load=True):
"""Merge a result into this :class:`.Query` object's Session."""
+ querylib = util.preloaded.orm_query
session = query.session
if load:
def _prop_set(self):
return frozenset(self._props.values())
+ @util.preload_module("sqlalchemy.orm.descriptor_props")
def _adapt_inherited_property(self, key, prop, init):
+ descriptor_props = util.preloaded.orm_descriptor_props
+
if not self.concrete:
self._configure_property(key, prop, init=False, setparent=False)
elif key not in self._props:
):
self._configure_property(
key,
- properties.ConcreteInheritedProperty(),
+ descriptor_props.ConcreteInheritedProperty(),
init=init,
setparent=True,
)
+ @util.preload_module("sqlalchemy.orm.descriptor_props")
def _configure_property(self, key, prop, init=True, setparent=True):
+ descriptor_props = util.preloaded.orm_descriptor_props
self._log("_configure_property(%s, %s)", key, prop.__class__.__name__)
if not isinstance(prop, MapperProperty):
self._props[key],
(
properties.ColumnProperty,
- properties.ConcreteInheritedProperty,
+ descriptor_props.ConcreteInheritedProperty,
),
)
):
if self.configured:
self._expire_memoizations()
+ @util.preload_module("sqlalchemy.orm.descriptor_props")
def _property_from_column(self, key, prop):
- """generate/update a :class:`.ColumnProprerty` given a
+ """generate/update a :class:`.ColumnProperty` given a
:class:`.Column` object. """
-
+ descriptor_props = util.preloaded.orm_descriptor_props
# we were passed a Column or a list of Columns;
# generate a properties.ColumnProperty
columns = util.to_list(prop)
)
return prop
elif prop is None or isinstance(
- prop, properties.ConcreteInheritedProperty
+ prop, descriptor_props.ConcreteInheritedProperty
):
mapped_column = []
for c in columns:
)
@_memoized_configured_property
+ @util.preload_module("sqlalchemy.orm.descriptor_props")
def synonyms(self):
"""Return a namespace of all :class:`.SynonymProperty`
properties maintained by this :class:`.Mapper`.
objects.
"""
- return self._filter_properties(properties.SynonymProperty)
+ descriptor_props = util.preloaded.orm_descriptor_props
+
+ return self._filter_properties(descriptor_props.SynonymProperty)
@_memoized_configured_property
def column_attrs(self):
"""
return self._filter_properties(properties.ColumnProperty)
+ @util.preload_module("sqlalchemy.orm.relationships")
@_memoized_configured_property
def relationships(self):
"""A namespace of all :class:`.RelationshipProperty` properties
objects.
"""
- return self._filter_properties(properties.RelationshipProperty)
+ return self._filter_properties(
+ util.preloaded.orm_relationships.RelationshipProperty
+ )
@_memoized_configured_property
+ @util.preload_module("sqlalchemy.orm.descriptor_props")
def composites(self):
"""Return a namespace of all :class:`.CompositeProperty`
properties maintained by this :class:`.Mapper`.
objects.
"""
- return self._filter_properties(properties.CompositeProperty)
+ return self._filter_properties(
+ util.preloaded.orm_descriptor_props.CompositeProperty
+ )
def _filter_properties(self, type_):
if Mapper._new_mappers:
return None
- @util.dependencies(
+ @util.preload_module(
"sqlalchemy.ext.baked", "sqlalchemy.orm.strategy_options"
)
- def _subclass_load_via_in(self, baked, strategy_options, entity):
+ def _subclass_load_via_in(self, entity):
"""Assemble a BakedQuery that can load the columns local to
this subclass as a SELECT with IN.
"""
+ strategy_options = util.preloaded.orm_strategy_options
+ baked = util.preloaded.ext_baked
+
assert self.inherits
polymorphic_prop = self._columntoproperty[self.polymorphic_on]
def _do_before_compile(self):
raise NotImplementedError()
- @util.dependencies("sqlalchemy.orm.query")
- def _do_pre(self, querylib):
+ @util.preload_module("sqlalchemy.orm.query")
+ def _do_pre(self):
+ querylib = util.preloaded.orm_query
query = self.query
self.context = querylib.QueryContext(query)
from __future__ import absolute_import
from . import attributes
+from .descriptor_props import ComparableProperty
+from .descriptor_props import CompositeProperty
+from .descriptor_props import ConcreteInheritedProperty
+from .descriptor_props import SynonymProperty
from .interfaces import PropComparator
from .interfaces import StrategizedProperty
+from .relationships import RelationshipProperty
from .util import _orm_full_deannotate
from .. import log
from .. import util
from ..sql import roles
-__all__ = ["ColumnProperty"]
+__all__ = [
+ "ColumnProperty",
+ "ComparableProperty",
+ "CompositeProperty",
+ "ConcreteInheritedProperty",
+ "RelationshipProperty",
+ "SynonymProperty",
+]
@log.class_logger
if self.raiseload:
self.strategy_key += (("raiseload", True),)
- @util.dependencies("sqlalchemy.orm.state", "sqlalchemy.orm.strategies")
- def _memoized_attr__deferred_column_loader(self, state, strategies):
+ @util.preload_module("sqlalchemy.orm.state", "sqlalchemy.orm.strategies")
+ def _memoized_attr__deferred_column_loader(self):
+ state = util.preloaded.orm_state
+ strategies = util.preloaded.orm_strategies
return state.InstanceState._instance_level_callable_processor(
self.parent.class_manager,
strategies.LoadDeferredColumns(self.key),
self.key,
)
- @util.dependencies("sqlalchemy.orm.state", "sqlalchemy.orm.strategies")
- def _memoized_attr__raise_column_loader(self, state, strategies):
+ @util.preload_module("sqlalchemy.orm.state", "sqlalchemy.orm.strategies")
+ def _memoized_attr__raise_column_loader(self):
+ state = util.preloaded.orm_state
+ strategies = util.preloaded.orm_strategies
return state.InstanceState._instance_level_callable_processor(
self.parent.class_manager,
strategies.LoadDeferredColumns(self.key, True),
from . import interfaces
from . import loading
from . import persistence
-from . import properties
from .base import _assertions
from .base import _entity_descriptor
from .base import _is_aliased_class
"""
self._invoke_all_eagers = value
+ @util.preload_module("sqlalchemy.orm.relationships")
def with_parent(self, instance, property=None, from_entity=None): # noqa
"""Add filtering criterion that relates the given instance
to a child object or collection, using its attribute state
"zero" entity of the :class:`.Query` itself.
"""
+ relationships = util.preloaded.orm_relationships
if from_entity:
entity_zero = inspect(from_entity)
for prop in mapper.iterate_properties:
if (
- isinstance(prop, properties.RelationshipProperty)
+ isinstance(prop, relationships.RelationshipProperty)
and prop.mapper is entity_zero.mapper
):
property = prop # noqa
class LockmodeArg(ForUpdateArg):
@classmethod
- def parse_legacy_query(self, mode):
+ def parse_legacy_query(cls, mode):
if mode in (None, False):
return None
import weakref
from . import attributes
-from . import dependency
-from . import mapper as mapperlib
from .base import state_str
from .interfaces import MANYTOMANY
from .interfaces import MANYTOONE
@log.class_logger
-@util.langhelpers.dependency_for("sqlalchemy.orm.properties", add_to_all=True)
class RelationshipProperty(StrategizedProperty):
"""Describes an object property that holds a single item or list
of items that correspond to a related database table.
return _orm_annotate(self.__negated_contains_or_equals(other))
@util.memoized_property
+ @util.preload_module("sqlalchemy.orm.mapper")
def property(self):
+ mapperlib = util.preloaded.orm_mapper
if mapperlib.Mapper._new_mappers:
mapperlib.Mapper._configure_all()
return self.prop
)
@util.memoized_property
+ @util.preload_module("sqlalchemy.orm.mapper")
def entity(self): # type: () -> Union[AliasedInsp, mapperlib.Mapper]
"""Return the target mapped entity, which is an inspect() of the
class or aliased class that is referred towards.
"""
+ mapperlib = util.preloaded.orm_mapper
if callable(self.argument) and not isinstance(
self.argument, (type, mapperlib.Mapper)
):
self._calculated_foreign_keys = jc.foreign_key_columns
self.secondary_synchronize_pairs = jc.secondary_synchronize_pairs
+ @util.preload_module("sqlalchemy.orm.mapper")
def _check_conflicts(self):
"""Test that this relationship is legal, warn about
inheritance conflicts."""
-
+ mapperlib = util.preloaded.orm_mapper
if self.parent.non_primary and not mapperlib.class_mapper(
self.parent.class_, configure=False
).has_property(self.key):
if self.back_populates:
self._add_reverse_property(self.back_populates)
+ @util.preload_module("sqlalchemy.orm.dependency")
def _post_init(self):
+ dependency = util.preloaded.orm_dependency
+
if self.uselist is None:
self.uselist = self.direction is not MANYTOONE
if not self.viewonly:
_track_overlapping_sync_targets = weakref.WeakKeyDictionary()
+ @util.preload_module("sqlalchemy.orm.mapper")
def _warn_for_conflicting_sync_targets(self):
+ mapperlib = util.preloaded.orm_mapper
if not self.support_sync:
return
close_all_sessions()
@classmethod
- @util.dependencies("sqlalchemy.orm.util")
- def identity_key(cls, orm_util, *args, **kwargs):
+ @util.preload_module("sqlalchemy.orm.util")
+ def identity_key(cls, *args, **kwargs):
"""Return an identity key.
This is an alias of :func:`.util.identity_key`.
"""
- return orm_util.identity_key(*args, **kwargs)
+ return util.perload.orm_util.identity_key(*args, **kwargs)
@classmethod
def object_session(cls, instance):
return self.key is not None and not self._attached
@property
- @util.dependencies("sqlalchemy.orm.session")
- def _attached(self, sessionlib):
+ @util.preload_module("sqlalchemy.orm.session")
+ def _attached(self):
return (
self.session_id is not None
- and self.session_id in sessionlib._sessions
+ and self.session_id in util.preloaded.orm_session._sessions
)
def _track_last_known_value(self, key):
self._last_known_values[key] = NO_VALUE
@property
- @util.dependencies("sqlalchemy.orm.session")
- def session(self, sessionlib):
+ @util.preload_module("sqlalchemy.orm.session")
+ def session(self):
"""Return the owning :class:`.Session` for this instance,
or ``None`` if none available.
fully detached under normal circumstances.
"""
- return sessionlib._state_session(self)
+ return util.preloaded.orm_session._state_session(self)
@property
def object(self):
from . import loading
from . import properties
from . import query
+from . import relationships
from . import unitofwork
from . import util as orm_util
from .base import _DEFER_FOR_STATE
@log.class_logger
-@properties.RelationshipProperty.strategy_for(do_nothing=True)
+@relationships.RelationshipProperty.strategy_for(do_nothing=True)
class DoNothingLoader(LoaderStrategy):
"""Relationship loader that makes no change to the object's state.
@log.class_logger
-@properties.RelationshipProperty.strategy_for(lazy="noload")
-@properties.RelationshipProperty.strategy_for(lazy=None)
+@relationships.RelationshipProperty.strategy_for(lazy="noload")
+@relationships.RelationshipProperty.strategy_for(lazy=None)
class NoLoader(AbstractRelationshipLoader):
"""Provide loading behavior for a :class:`.RelationshipProperty`
with "lazy=None".
@log.class_logger
-@properties.RelationshipProperty.strategy_for(lazy=True)
-@properties.RelationshipProperty.strategy_for(lazy="select")
-@properties.RelationshipProperty.strategy_for(lazy="raise")
-@properties.RelationshipProperty.strategy_for(lazy="raise_on_sql")
-@properties.RelationshipProperty.strategy_for(lazy="baked_select")
+@relationships.RelationshipProperty.strategy_for(lazy=True)
+@relationships.RelationshipProperty.strategy_for(lazy="select")
+@relationships.RelationshipProperty.strategy_for(lazy="raise")
+@relationships.RelationshipProperty.strategy_for(lazy="raise_on_sql")
+@relationships.RelationshipProperty.strategy_for(lazy="baked_select")
class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
"""Provide loading behavior for a :class:`.RelationshipProperty`
with "lazy=True", that is loads when first accessed.
for pk in self.mapper.primary_key
]
- @util.dependencies("sqlalchemy.ext.baked")
- def _memoized_attr__bakery(self, baked):
- return baked.bakery(size=50)
+ @util.preload_module("sqlalchemy.ext.baked")
+ def _memoized_attr__bakery(self):
+ return util.preloaded.ext_baked.bakery(size=50)
- @util.dependencies("sqlalchemy.orm.strategy_options")
- def _emit_lazyload(
- self, strategy_options, session, state, primary_key_identity, passive
- ):
+ @util.preload_module("sqlalchemy.orm.strategy_options")
+ def _emit_lazyload(self, session, state, primary_key_identity, passive):
# emit lazy load now using BakedQuery, to cut way down on the overhead
# of generating queries.
# there are two big things we are trying to guard against here:
# lazy loaders. Currently the LRU cache is local to the LazyLoader,
# however add ourselves to the initial cache key just to future
# proof in case it moves
+ strategy_options = util.preloaded.orm_strategy_options
q = self._bakery(lambda session: session.query(self.entity), self)
q.add_criteria(
)
-@properties.RelationshipProperty.strategy_for(lazy="immediate")
+@relationships.RelationshipProperty.strategy_for(lazy="immediate")
class ImmediateLoader(PostLoader):
__slots__ = ()
@log.class_logger
-@properties.RelationshipProperty.strategy_for(lazy="subquery")
+@relationships.RelationshipProperty.strategy_for(lazy="subquery")
class SubqueryLoader(PostLoader):
__slots__ = ("join_depth",)
@log.class_logger
-@properties.RelationshipProperty.strategy_for(lazy="joined")
-@properties.RelationshipProperty.strategy_for(lazy=False)
+@relationships.RelationshipProperty.strategy_for(lazy="joined")
+@relationships.RelationshipProperty.strategy_for(lazy=False)
class JoinedLoader(AbstractRelationshipLoader):
"""Provide loading behavior for a :class:`.RelationshipProperty`
using joined eager loading.
@log.class_logger
-@properties.RelationshipProperty.strategy_for(lazy="selectin")
+@relationships.RelationshipProperty.strategy_for(lazy="selectin")
class SelectInLoader(PostLoader, util.MemoizedSlots):
__slots__ = (
"join_depth",
(("lazy", "select"),)
).init_class_attribute(mapper)
- @util.dependencies("sqlalchemy.ext.baked")
- def _memoized_attr__bakery(self, baked):
- return baked.bakery(size=50)
+ @util.preload_module("sqlalchemy.ext.baked")
+ def _memoized_attr__bakery(self):
+ return util.preloaded.ext_baked.bakery(size=50)
def create_row_processor(
self, context, path, loadopt, mapper, result, adapter, populators
effective_entity,
)
- @util.dependencies("sqlalchemy.ext.baked")
def _load_for_path(
- self, baked, context, path, states, load_only, effective_entity
+ self, context, path, states, load_only, effective_entity
):
-
if load_only and self.key not in load_only:
return
from . import attributes
from . import exc as orm_exc
-from . import persistence
from . import util as orm_util
from .. import event
from .. import util
self.mapper = mapper
self.isdelete = isdelete
+ @util.preload_module("sqlalchemy.orm.persistence")
def execute(self, uow):
+ persistence = util.preloaded.orm_persistence
states, cols = uow.post_update_states[self.mapper]
states = [s for s in states if uow.states[s][0] == self.isdelete]
self.mapper = mapper
assert mapper is mapper.base_mapper
+ @util.preload_module("sqlalchemy.orm.persistence")
def execute(self, uow):
- persistence.save_obj(
+ util.preloaded.orm_persistence.save_obj(
self.mapper,
uow.states_for_mapper_hierarchy(self.mapper, False, False),
uow,
self.mapper = mapper
assert mapper is mapper.base_mapper
+ @util.preload_module("sqlalchemy.orm.persistence")
def execute(self, uow):
- persistence.delete_obj(
+ util.preloaded.orm_persistence.delete_obj(
self.mapper,
uow.states_for_mapper_hierarchy(self.mapper, True, False),
uow,
self.state = state
self.mapper = state.mapper.base_mapper
+ @util.preload_module("sqlalchemy.orm.persistence")
def execute_aggregate(self, uow, recs):
+ persistence = util.preloaded.orm_persistence
cls_ = self.__class__
mapper = self.mapper
our_recs = [
self.state = state
self.mapper = state.mapper.base_mapper
+ @util.preload_module("sqlalchemy.orm.persistence")
def execute_aggregate(self, uow, recs):
+ persistence = util.preloaded.orm_persistence
cls_ = self.__class__
mapper = self.mapper
our_recs = [
_prepare_annotations(FromClause, AnnotatedFromClause)
_prepare_annotations(ClauseList, Annotated)
- _sa_util.dependencies.resolve_all("sqlalchemy.sql")
+ _sa_util.preloaded.import_prefix("sqlalchemy.sql")
from . import naming # noqa
del self._non_defaults[key]
+@util.preload_module("sqlalchemy.dialects")
+def _kw_reg_for_dialect(dialect_name):
+ dialect_cls = util.preloaded.dialects.registry.load(dialect_name)
+ if dialect_cls.construct_arguments is None:
+ return None
+ return dict(dialect_cls.construct_arguments)
+
+
class DialectKWArgs(object):
"""Establish the ability for a class to have dialect-specific arguments
with defaults and constructor validation.
"""A synonym for :attr:`.DialectKWArgs.dialect_kwargs`."""
return self.dialect_kwargs
- @util.dependencies("sqlalchemy.dialects")
- def _kw_reg_for_dialect(dialects, dialect_name):
- dialect_cls = dialects.registry.load(dialect_name)
- if dialect_cls.construct_arguments is None:
- return None
- return dict(dialect_cls.construct_arguments)
-
_kw_registry = util.PopulateDict(_kw_reg_for_dialect)
def _kw_reg_for_dialect_cls(self, dialect_name):
return expanded_state
- @util.dependencies("sqlalchemy.engine.result")
- def _create_result_map(self, result):
+ @util.preload_module("sqlalchemy.engine.result")
+ def _create_result_map(self):
"""utility method used for unit tests only."""
+ result = util.preloaded.engine_result
return result.CursorResultMetaData._create_description_match_map(
self._result_columns
)
ident = self.quote_identifier(ident)
return ident
- @util.dependencies("sqlalchemy.sql.naming")
- def format_constraint(self, naming, constraint, _alembic_quote=True):
+ @util.preload_module("sqlalchemy.sql.naming")
+ def format_constraint(self, constraint, _alembic_quote=True):
+ naming = util.preloaded.sql_naming
+
if isinstance(constraint.name, elements._defer_name):
name = naming._constraint_name_for_table(
constraint, constraint.table
return self
- @util.dependencies("sqlalchemy.engine.default")
- def compile(self, default, bind=None, dialect=None, **kw):
+ @util.preload_module("sqlalchemy.engine.default")
+ def compile(self, bind=None, dialect=None, **kw):
"""Compile this SQL expression.
The return value is a :class:`~.Compiled` object.
"""
+ default = util.preloaded.engine_default
if not dialect:
if bind:
dialect = bind.dialect
else:
new_params[key] = existing._with_value(value)
- @util.dependencies("sqlalchemy.sql.selectable")
- def columns(self, selectable, *cols, **types):
+ @util.preload_module("sqlalchemy.sql.selectable")
+ def columns(self, *cols, **types):
r"""Turn this :class:`.TextClause` object into a
:class:`.TextualSelect` object that serves the same role as a SELECT
statement.
argument as it also indicates positional ordering.
"""
+ selectable = util.preloaded.sql_selectable
positional_input_cols = [
ColumnClause(col.key, types.pop(col.key))
if col.key in types
)
@util.memoized_property
- @util.dependencies("sqlalchemy.sql.sqltypes")
- def _arg_is_typed(self, sqltypes):
+ @util.preload_module("sqlalchemy.sql.sqltypes")
+ def _arg_is_typed(self):
+ sqltypes = util.preloaded.sql_sqltypes
+
if self.is_clause_element:
return not isinstance(self.arg.type, sqltypes.NullType)
else:
def is_clause_element(self):
return False
- @util.dependencies("sqlalchemy.sql.functions.func")
- def next_value(self, func):
+ @util.preload_module("sqlalchemy.sql.functions")
+ def next_value(self):
"""Return a :class:`.next_value` function element
which will render the appropriate increment function
for this :class:`.Sequence` within any SQL expression.
"""
- return func.next_value(self, bind=self.bind)
+ return util.preloaded.sql_functions.func.next_value(
+ self, bind=self.bind
+ )
def _set_parent(self, column):
super(Sequence, self)._set_parent(column)
"""
return self._bind
- @util.dependencies("sqlalchemy.engine.url")
- def _bind_to(self, url, bind):
+ @util.preload_module("sqlalchemy.engine.url")
+ def _bind_to(self, bind):
"""Bind this MetaData to an Engine, Connection, string or URL."""
-
+ url = util.preloaded.engine_url
if isinstance(bind, util.string_types + (url.URL,)):
self._bind = sqlalchemy.create_engine(bind)
else:
return getattr(self.context, "_engine", None)
- @util.dependencies("sqlalchemy.engine.url")
- def _bind_to(self, url, bind):
+ @util.preload_module("sqlalchemy.engine.url")
+ def _bind_to(self, bind):
"""Bind to a Connectable in the caller's thread."""
-
+ url = util.preloaded.engine_url
if isinstance(bind, util.string_types + (url.URL,)):
try:
self.context._engine = self.__engines[bind]
"deprecated, and will be removed in a future release. Similar "
"functionality is available via the sqlalchemy.sql.visitors module.",
)
- @util.dependencies("sqlalchemy.sql.util")
- def replace_selectable(self, sqlutil, old, alias):
+ @util.preload_module("sqlalchemy.sql.util")
+ def replace_selectable(self, old, alias):
"""replace all occurrences of FromClause 'old' with the given Alias
object, returning a copy of this :class:`.FromClause`.
"""
-
- return sqlutil.ClauseAdapter(alias).traverse(self)
+ return util.preloaded.sql_util.ClauseAdapter(alias).traverse(self)
def corresponding_column(self, column, require_embedded=False):
"""Given a :class:`.ColumnElement`, return the exported
":class:`.functions.count` function available from the "
":attr:`.func` namespace.",
)
- @util.dependencies("sqlalchemy.sql.functions")
- def count(self, functions, whereclause=None, **params):
+ @util.preload_module("sqlalchemy.sql.functions")
+ def count(self, whereclause=None, **params):
"""return a SELECT COUNT generated against this
:class:`.FromClause`.
:class:`.functions.count`
"""
-
+ functions = util.preloaded.sql_functions
if self.primary_key:
col = list(self.primary_key)[0]
else:
def self_group(self, against=None):
return FromGrouping(self)
- @util.dependencies("sqlalchemy.sql.util")
- def _populate_column_collection(self, sqlutil):
+ @util.preload_module("sqlalchemy.sql.util")
+ def _populate_column_collection(self):
+ sqlutil = util.preloaded.sql_util
columns = [c for c in self.left.columns] + [
c for c in self.right.columns
]
def bind(self):
return self.left.bind or self.right.bind
- @util.dependencies("sqlalchemy.sql.util")
- def alias(self, sqlutil, name=None, flat=False):
+ @util.preload_module("sqlalchemy.sql.util")
+ def alias(self, name=None, flat=False):
r"""return an alias of this :class:`.Join`.
The default behavior here is to first produce a SELECT
:func:`~.expression.alias`
"""
+ sqlutil = util.preloaded.sql_util
if flat:
assert name is None, "Can't send name argument with flat"
left_a, right_a = (
self.seed = seed
super(TableSample, self)._init(selectable, name=name)
- @util.dependencies("sqlalchemy.sql.functions")
- def _get_method(self, functions):
+ @util.preload_module("sqlalchemy.sql.functions")
+ def _get_method(self):
+ functions = util.preloaded.sql_functions
if isinstance(self.sampling, functions.Function):
return self.sampling
else:
self._columns.add(c)
c.table = self
- @util.dependencies("sqlalchemy.sql.dml")
- def insert(self, dml, values=None, inline=False, **kwargs):
+ @util.preload_module("sqlalchemy.sql.dml")
+ def insert(self, values=None, inline=False, **kwargs):
"""Generate an :func:`.insert` construct against this
:class:`.TableClause`.
See :func:`.insert` for argument and usage information.
"""
+ return util.preloaded.sql_dml.Insert(
+ self, values=values, inline=inline, **kwargs
+ )
- return dml.Insert(self, values=values, inline=inline, **kwargs)
-
- @util.dependencies("sqlalchemy.sql.dml")
- def update(
- self, dml, whereclause=None, values=None, inline=False, **kwargs
- ):
+ @util.preload_module("sqlalchemy.sql.dml")
+ def update(self, whereclause=None, values=None, inline=False, **kwargs):
"""Generate an :func:`.update` construct against this
:class:`.TableClause`.
See :func:`.update` for argument and usage information.
"""
-
- return dml.Update(
+ return util.preloaded.sql_dml.Update(
self,
whereclause=whereclause,
values=values,
**kwargs
)
- @util.dependencies("sqlalchemy.sql.dml")
- def delete(self, dml, whereclause=None, **kwargs):
+ @util.preload_module("sqlalchemy.sql.dml")
+ def delete(self, whereclause=None, **kwargs):
"""Generate a :func:`.delete` construct against this
:class:`.TableClause`.
See :func:`.delete` for argument and usage information.
"""
-
- return dml.Delete(self, whereclause, **kwargs)
+ return util.preloaded.sql_dml.Delete(self, whereclause, **kwargs)
@property
def _from_objects(self):
"""
return self.add_columns(column)
- @util.dependencies("sqlalchemy.sql.util")
- def reduce_columns(self, sqlutil, only_synonyms=True):
+ @util.preload_module("sqlalchemy.sql.util")
+ def reduce_columns(self, only_synonyms=True):
"""Return a new :func`.select` construct with redundantly
named, equivalently-valued columns removed from the columns clause.
"""
return self.with_only_columns(
- sqlutil.reduce_columns(
+ util.preloaded.sql_util.reduce_columns(
self.inner_columns,
only_synonyms=only_synonyms,
*(self._whereclause,) + tuple(self._from_obj)
not self.native_enum or not compiler.dialect.supports_native_enum
)
- @util.dependencies("sqlalchemy.sql.schema")
- def _set_table(self, schema, column, table):
+ @util.preload_module("sqlalchemy.sql.schema")
+ def _set_table(self, column, table):
+ schema = util.preloaded.sql_schema
SchemaType._set_table(self, column, table)
if not self.create_constraint:
and compiler.dialect.non_native_boolean_check_constraint
)
- @util.dependencies("sqlalchemy.sql.schema")
- def _set_table(self, schema, column, table):
+ @util.preload_module("sqlalchemy.sql.schema")
+ def _set_table(self, column, table):
+ schema = util.preloaded.sql_schema
if not self.create_constraint:
return
class Comparator(Indexable.Comparator, Concatenable.Comparator):
"""Define comparison operations for :class:`.types.JSON`."""
- @util.dependencies("sqlalchemy.sql.default_comparator")
- def _setup_getitem(self, default_comparator, index):
+ def _setup_getitem(self, index):
if not isinstance(index, util.string_types) and isinstance(
index, compat.collections_abc.Sequence
):
"ARRAY type; please use the dialect-specific ARRAY type"
)
- @util.dependencies("sqlalchemy.sql.elements")
- def any(self, elements, other, operator=None):
+ @util.preload_module("sqlalchemy.sql.elements")
+ def any(self, other, operator=None):
"""Return ``other operator ANY (array)`` clause.
Argument places are switched, because ANY requires array
:meth:`.types.ARRAY.Comparator.all`
"""
+ elements = util.preloaded.sql_elements
operator = operator if operator else operators.eq
return operator(
coercions.expect(roles.ExpressionElementRole, other),
elements.CollectionAggregate._create_any(self.expr),
)
- @util.dependencies("sqlalchemy.sql.elements")
- def all(self, elements, other, operator=None):
+ @util.preload_module("sqlalchemy.sql.elements")
+ def all(self, other, operator=None):
"""Return ``other operator ALL (array)`` clause.
Argument places are switched, because ALL requires array
:meth:`.types.ARRAY.Comparator.any`
"""
+ elements = util.preloaded.sql_elements
operator = operator if operator else operators.eq
return operator(
coercions.expect(roles.ExpressionElementRole, other),
_get_children = _GetChildren()
-@util.dependencies("sqlalchemy.sql.elements")
-def _resolve_name_for_compare(elements, element, name, anon_map, **kw):
- if isinstance(name, elements._anonymous_label):
+@util.preload_module("sqlalchemy.sql.elements")
+def _resolve_name_for_compare(element, name, anon_map, **kw):
+ if isinstance(name, util.preloaded.sql_elements._anonymous_label):
name = name.apply_map(anon_map)
return name
self.expr = expr
self.type = expr.type
- @util.dependencies("sqlalchemy.sql.default_comparator")
- def operate(self, default_comparator, op, *other, **kwargs):
+ @util.preload_module("sqlalchemy.sql.default_comparator")
+ def operate(self, op, *other, **kwargs):
+ default_comparator = util.preloaded.sql_default_comparator
o = default_comparator.operator_lookup[op.__name__]
return o[0](self.expr, op, *(other + o[1:]), **kwargs)
- @util.dependencies("sqlalchemy.sql.default_comparator")
- def reverse_operate(self, default_comparator, op, other, **kwargs):
+ @util.preload_module("sqlalchemy.sql.default_comparator")
+ def reverse_operate(self, op, other, **kwargs):
+ default_comparator = util.preloaded.sql_default_comparator
o = default_comparator.operator_lookup[op.__name__]
return o[0](self.expr, op, other, reverse=True, *o[1:], **kwargs)
return dialect.type_compiler.process(self)
- @util.dependencies("sqlalchemy.engine.default")
- def _default_dialect(self, default):
+ @util.preload_module("sqlalchemy.engine.default")
+ def _default_dialect(self):
+ default = util.preloaded.engine_default
if self.__class__.__module__.startswith("sqlalchemy.dialects"):
tokens = self.__class__.__module__.split(".")[0:3]
mod = ".".join(tokens)
from .langhelpers import counter # noqa
from .langhelpers import decode_slice # noqa
from .langhelpers import decorator # noqa
-from .langhelpers import dependencies # noqa
from .langhelpers import dictlike_iteritems # noqa
from .langhelpers import duck_type_collection # noqa
from .langhelpers import ellipses_string # noqa
from .langhelpers import only_once # noqa
from .langhelpers import PluginLoader # noqa
from .langhelpers import portable_instancemethod # noqa
+from .langhelpers import preloaded # noqa
+from .langhelpers import preload_module # noqa
from .langhelpers import quoted_token_parser # noqa
from .langhelpers import safe_reraise # noqa
from .langhelpers import set_creation_order # noqa
return self._fallback_getattr(key)
-def dependency_for(modulename, add_to_all=False):
- def decorate(obj):
- tokens = modulename.split(".")
- mod = compat.import_(
- ".".join(tokens[0:-1]), globals(), locals(), [tokens[-1]]
- )
- mod = getattr(mod, tokens[-1])
- setattr(mod, obj.__name__, obj)
- if add_to_all and hasattr(mod, "__all__"):
- mod.__all__.append(obj.__name__)
- return obj
-
- return decorate
-
-
-class dependencies(object):
- """Apply imported dependencies as arguments to a function.
-
- E.g.::
-
- @util.dependencies(
- "sqlalchemy.sql.widget",
- "sqlalchemy.engine.default"
- );
- def some_func(self, widget, default, arg1, arg2, **kw):
- # ...
-
- Rationale is so that the impact of a dependency cycle can be
- associated directly with the few functions that cause the cycle,
- and not pollute the module-level namespace.
-
+class _ModuleRegistry:
+ """Registry of modules to load in a package init file.
+
+ To avoid potential thread safety issues for imports that are deferred
+ in a function, like https://bugs.python.org/issue38884, these modules
+ are added to the system module cache by importing them after the packages
+ has finished initialization.
+
+ A global instance is provided under the name :attr:`.preloaded`. Use
+ the function :func:`.preload_module` to register modules to load and
+ :meth:`.import_prefix` to load all the modules that start with the
+ given path.
+
+ While the modules are loaded in the global module cache, it's advisable
+ to access them using :attr:`.preloaded` to ensure that it was actually
+ registered. Each registered module is added to the instance ``__dict__``
+ in the form `<package>_<module>`, omitting ``sqlalchemy`` from the package
+ name. Example: ``sqlalchemy.sql.util`` becomes ``preloaded.sql_util``.
"""
- def __init__(self, *deps):
- self.import_deps = []
- for dep in deps:
- tokens = dep.split(".")
- self.import_deps.append(
- dependencies._importlater(".".join(tokens[0:-1]), tokens[-1])
- )
-
- def __call__(self, fn):
- import_deps = self.import_deps
- spec = compat.inspect_getfullargspec(fn)
-
- spec_zero = list(spec[0])
- hasself = spec_zero[0] in ("self", "cls")
-
- for i in range(len(import_deps)):
- spec[0][i + (1 if hasself else 0)] = "import_deps[%r]" % i
-
- inner_spec = format_argspec_plus(spec, grouped=False)
+ def __init__(self, prefix="sqlalchemy"):
+ self.module_registry = set()
- for impname in import_deps:
- del spec_zero[1 if hasself else 0]
- spec[0][:] = spec_zero
+ def preload_module(self, *deps):
+ """Adds the specified modules to the list to load.
- outer_spec = format_argspec_plus(spec, grouped=False)
-
- code = "lambda %(args)s: fn(%(apply_kw)s)" % {
- "args": outer_spec["args"],
- "apply_kw": inner_spec["apply_kw"],
- }
-
- decorated = eval(code, locals())
- decorated.__defaults__ = getattr(fn, "im_func", fn).__defaults__
- return update_wrapper(decorated, fn)
-
- @classmethod
- def resolve_all(cls, path):
- for m in list(dependencies._unresolved):
- if m._full_path.startswith(path):
- m._resolve()
-
- _unresolved = set()
- _by_key = {}
-
- class _importlater(object):
- _unresolved = set()
-
- _by_key = {}
+ This method can be used both as a normal function and as a decorator.
+ No change is performed to the decorated object.
+ """
+ self.module_registry.update(deps)
+ return lambda fn: fn
- def __new__(cls, path, addtl):
- key = path + "." + addtl
- if key in dependencies._by_key:
- return dependencies._by_key[key]
- else:
- dependencies._by_key[key] = imp = object.__new__(cls)
- return imp
-
- def __init__(self, path, addtl):
- self._il_path = path
- self._il_addtl = addtl
- dependencies._unresolved.add(self)
-
- @property
- def _full_path(self):
- return self._il_path + "." + self._il_addtl
-
- @memoized_property
- def module(self):
- if self in dependencies._unresolved:
- raise ImportError(
- "importlater.resolve_all() hasn't "
- "been called (this is %s %s)"
- % (self._il_path, self._il_addtl)
+ def import_prefix(self, path):
+ """Resolve all the modules in the registry that start with the
+ specified path.
+ """
+ for module in self.module_registry:
+ key = module.split("sqlalchemy.")[-1].replace(".", "_")
+ if module.startswith(path) and key not in self.__dict__:
+ tokens = module.split(".")
+ compat.import_(
+ ".".join(tokens[0:-1]), globals(), locals(), [tokens[-1]]
)
+ self.__dict__[key] = sys.modules[module]
- return getattr(self._initial_import, self._il_addtl)
- def _resolve(self):
- dependencies._unresolved.discard(self)
- self._initial_import = compat.import_(
- self._il_path, globals(), locals(), [self._il_addtl]
- )
-
- def __getattr__(self, key):
- if key == "module":
- raise ImportError(
- "Could not resolve module %s" % self._full_path
- )
- try:
- attr = getattr(self.module, key)
- except AttributeError:
- raise AttributeError(
- "Module %s has no attribute '%s'" % (self._full_path, key)
- )
- self.__dict__[key] = attr
- return attr
+preloaded = _ModuleRegistry()
+preload_module = preloaded.preload_module
# from paste.deploy.converters
import copy
import datetime
import inspect
+import sys
from sqlalchemy import exc
from sqlalchemy import sql
repr(timezone(datetime.timedelta(hours=5))),
"sqlalchemy.util.timezone(%r)" % (datetime.timedelta(hours=5)),
)
+
+
+class TestModuleRegistry(fixtures.TestBase):
+ def test_modules_are_loaded(self):
+ to_restore = []
+ for m in ("xml.dom", "wsgiref.simple_server"):
+ to_restore.append((m, sys.modules.pop(m, None)))
+ try:
+ mr = langhelpers._ModuleRegistry()
+
+ ret = mr.preload_module(
+ "xml.dom", "wsgiref.simple_server", "sqlalchemy.sql.util"
+ )
+ o = object()
+ is_(ret(o), o)
+
+ is_false(hasattr(mr, "xml_dom"))
+ mr.import_prefix("xml")
+ is_true("xml.dom" in sys.modules)
+ is_(sys.modules["xml.dom"], mr.xml_dom)
+
+ is_true("wsgiref.simple_server" not in sys.modules)
+ mr.import_prefix("wsgiref")
+ is_true("wsgiref.simple_server" in sys.modules)
+ is_(sys.modules["wsgiref.simple_server"], mr.wsgiref_simple_server)
+
+ mr.import_prefix("sqlalchemy")
+ is_(sys.modules["sqlalchemy.sql.util"], mr.sql_util)
+ finally:
+ for name, mod in to_restore:
+ if mod is not None:
+ sys.modules[name] = mod
from sqlalchemy.orm import configure_mappers
from sqlalchemy.orm import create_session
from sqlalchemy.orm import deferred
+from sqlalchemy.orm import descriptor_props
from sqlalchemy.orm import exc as orm_exc
from sqlalchemy.orm import joinedload
from sqlalchemy.orm import mapper
-from sqlalchemy.orm import properties
from sqlalchemy.orm import relationship
from sqlalchemy.orm import Session
from sqlalchemy.orm.events import MapperEvents
assert ASub.brap.property is A.data.property
assert isinstance(
- ASub.brap.original_property, properties.SynonymProperty
+ ASub.brap.original_property, descriptor_props.SynonymProperty
)
def test_alt_name_attr_subclass_relationship_inline(self):
assert ASub.brap.property is A.b.property
assert isinstance(
- ASub.brap.original_property, properties.SynonymProperty
+ ASub.brap.original_property, descriptor_props.SynonymProperty
)
ASub(brap=B())
A.brap = A.data
assert A.brap.property is A.data.property
- assert isinstance(A.brap.original_property, properties.SynonymProperty)
+ assert isinstance(
+ A.brap.original_property, descriptor_props.SynonymProperty
+ )
def test_alt_name_attr_subclass_relationship_attrset(self):
# [ticket:2900]
id = Column("id", Integer, primary_key=True)
assert A.brap.property is A.b.property
- assert isinstance(A.brap.original_property, properties.SynonymProperty)
+ assert isinstance(
+ A.brap.original_property, descriptor_props.SynonymProperty
+ )
A(brap=B())
def test_eager_order_by(self):
self.classes.User,
)
- from sqlalchemy.orm.properties import RelationshipProperty
+ from sqlalchemy.orm.relationships import RelationshipProperty
# NOTE: this API changed in 0.8, previously __clause_element__()
# gave the parent selecatable, now it gives the
# TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set 2.7_sqlite_pysqlite_dbapiunicode_cextensions 3812
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 3812
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set 3.7_sqlite_pysqlite_dbapiunicode_cextensions 3933
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 3933
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set 2.7_sqlite_pysqlite_dbapiunicode_cextensions 3567
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 3567
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set 3.7_sqlite_pysqlite_dbapiunicode_cextensions 3688
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 3688
# TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove 2.7_sqlite_pysqlite_dbapiunicode_cextensions 6026
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 6026
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove 3.7_sqlite_pysqlite_dbapiunicode_cextensions 6228
-test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 6228
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove 2.7_sqlite_pysqlite_dbapiunicode_cextensions 5626
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove 2.7_sqlite_pysqlite_dbapiunicode_nocextensions 5626
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove 3.7_sqlite_pysqlite_dbapiunicode_cextensions 5828
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove 3.7_sqlite_pysqlite_dbapiunicode_nocextensions 5828
# TEST: test.aaa_profiling.test_orm.BranchedOptionTest.test_generate_path_cache_key_bound_branching
with expect_deprecated_20(
"The `database` package is deprecated and will be removed in v2.0 "
):
- import_('sqlalchemy.databases')
+ import_("sqlalchemy.databases")