⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 attributes.py

📁 SQLAlchemy. 经典的Python ORM框架。学习必看。
💻 PY
📖 第 1 页 / 共 3 页
字号:
# attributes.py - manages object attributes# Copyright (C) 2005, 2006, 2007, 2008 Michael Bayer mike_mp@zzzcomputing.com## This module is part of SQLAlchemy and is released under# the MIT License: http://www.opensource.org/licenses/mit-license.phpimport weakref, threading, operatorfrom itertools import chainimport UserDictfrom sqlalchemy import utilfrom sqlalchemy.orm import interfaces, collectionsfrom sqlalchemy.orm.util import identity_equalfrom sqlalchemy import exceptionsPASSIVE_NORESULT = object()ATTR_WAS_SET = object()NO_VALUE = object()NEVER_SET = object()class InstrumentedAttribute(interfaces.PropComparator):    """public-facing instrumented attribute, placed in the    class dictionary.    """    def __init__(self, impl, comparator=None):        """Construct an InstrumentedAttribute.        comparator          a sql.Comparator to which class-level compare/math events will be sent        """        self.impl = impl        self.comparator = comparator    def __set__(self, instance, value):        self.impl.set(instance._state, value, None)    def __delete__(self, instance):        self.impl.delete(instance._state)    def __get__(self, instance, owner):        if instance is None:            return self        return self.impl.get(instance._state)    def get_history(self, instance, **kwargs):        return self.impl.get_history(instance._state, **kwargs)    def clause_element(self):        return self.comparator.clause_element()    def expression_element(self):        return self.comparator.expression_element()    def operate(self, op, *other, **kwargs):        return op(self.comparator, *other, **kwargs)    def reverse_operate(self, op, other, **kwargs):        return op(other, self.comparator, **kwargs)    def hasparent(self, instance, optimistic=False):        return self.impl.hasparent(instance._state, optimistic=optimistic)    def _property(self):        from sqlalchemy.orm.mapper import class_mapper        return class_mapper(self.impl.class_).get_property(self.impl.key)    property = property(_property, doc="the MapperProperty object associated with this attribute")class ProxiedAttribute(InstrumentedAttribute):    """a 'proxy' attribute which adds InstrumentedAttribute    class-level behavior to any user-defined class property.    """    class ProxyImpl(object):        accepts_scalar_loader = False        def __init__(self, key):            self.key = key    def __init__(self, key, user_prop, comparator=None):        self.user_prop = user_prop        self._comparator = comparator        self.key = key        self.impl = ProxiedAttribute.ProxyImpl(key)    def comparator(self):        if callable(self._comparator):            self._comparator = self._comparator()        return self._comparator    comparator = property(comparator)    def __get__(self, instance, owner):        if instance is None:            self.user_prop.__get__(instance, owner)            return self        return self.user_prop.__get__(instance, owner)    def __set__(self, instance, value):        return self.user_prop.__set__(instance, value)    def __delete__(self, instance):        return self.user_prop.__delete__(instance)class AttributeImpl(object):    """internal implementation for instrumented attributes."""    def __init__(self, class_, key, callable_, trackparent=False, extension=None, compare_function=None, **kwargs):        """Construct an AttributeImpl.        class_          the class to be instrumented.        key          string name of the attribute        callable_          optional function which generates a callable based on a parent          instance, which produces the "default" values for a scalar or          collection attribute when it's first accessed, if not present          already.        trackparent          if True, attempt to track if an instance has a parent attached          to it via this attribute.        extension          an AttributeExtension object which will receive          set/delete/append/remove/etc. events.        compare_function          a function that compares two values which are normally          assignable to this attribute.        """        self.class_ = class_        self.key = key        self.callable_ = callable_        self.trackparent = trackparent        if compare_function is None:            self.is_equal = operator.eq        else:            self.is_equal = compare_function        self.extensions = util.to_list(extension or [])    def hasparent(self, state, optimistic=False):        """Return the boolean value of a `hasparent` flag attached to the given item.        The `optimistic` flag determines what the default return value        should be if no `hasparent` flag can be located.        As this function is used to determine if an instance is an        *orphan*, instances that were loaded from storage should be        assumed to not be orphans, until a True/False value for this        flag is set.        An instance attribute that is loaded by a callable function        will also not have a `hasparent` flag.        """        return state.parents.get(id(self), optimistic)    def sethasparent(self, state, value):        """Set a boolean flag on the given item corresponding to        whether or not it is attached to a parent object via the        attribute represented by this ``InstrumentedAttribute``.        """        state.parents[id(self)] = value    def set_callable(self, state, callable_):        """Set a callable function for this attribute on the given object.        This callable will be executed when the attribute is next        accessed, and is assumed to construct part of the instances        previously stored state. When its value or values are loaded,        they will be established as part of the instance's *committed        state*.  While *trackparent* information will be assembled for        these instances, attribute-level event handlers will not be        fired.        The callable overrides the class level callable set in the        ``InstrumentedAttribute` constructor.        """        if callable_ is None:            self.initialize(state)        else:            state.callables[self.key] = callable_    def get_history(self, state, passive=False):        raise NotImplementedError()    def _get_callable(self, state):        if self.key in state.callables:            return state.callables[self.key]        elif self.callable_ is not None:            return self.callable_(state.obj())        else:            return None    def initialize(self, state):        """Initialize this attribute on the given object instance with an empty value."""        state.dict[self.key] = None        return None    def get(self, state, passive=False):        """Retrieve a value from the given object.        If a callable is assembled on this object's attribute, and        passive is False, the callable will be executed and the        resulting value will be set as the new value for this attribute.        """        try:            return state.dict[self.key]        except KeyError:            # if no history, check for lazy callables, etc.            if self.key not in state.committed_state:                callable_ = self._get_callable(state)                if callable_ is not None:                    if passive:                        return PASSIVE_NORESULT                    value = callable_()                    if value is not ATTR_WAS_SET:                        return self.set_committed_value(state, value)                    else:                        if self.key not in state.dict:                            return self.get(state, passive=passive)                        return state.dict[self.key]            # Return a new, empty value            return self.initialize(state)    def append(self, state, value, initiator, passive=False):        self.set(state, value, initiator)    def remove(self, state, value, initiator, passive=False):        self.set(state, None, initiator)    def set(self, state, value, initiator):        raise NotImplementedError()    def get_committed_value(self, state):        """return the unchanged value of this attribute"""        if self.key in state.committed_state:            return state.committed_state.get(self.key)        else:            return self.get(state)    def set_committed_value(self, state, value):        """set an attribute value on the given instance and 'commit' it."""        state.commit_attr(self, value)        # remove per-instance callable, if any        state.callables.pop(self.key, None)        state.dict[self.key] = value        return valueclass ScalarAttributeImpl(AttributeImpl):    """represents a scalar value-holding InstrumentedAttribute."""    accepts_scalar_loader = True    def delete(self, state):        if self.key not in state.committed_state:            state.committed_state[self.key] = state.dict.get(self.key, NO_VALUE)        # TODO: catch key errors, convert to attributeerror?        del state.dict[self.key]        state.modified=True    def get_history(self, state, passive=False):        return _create_history(self, state, state.dict.get(self.key, NO_VALUE))    def set(self, state, value, initiator):        if initiator is self:            return        if self.key not in state.committed_state:            state.committed_state[self.key] = state.dict.get(self.key, NO_VALUE)        state.dict[self.key] = value        state.modified=True    def type(self):        self.property.columns[0].type    type = property(type)class MutableScalarAttributeImpl(ScalarAttributeImpl):    """represents a scalar value-holding InstrumentedAttribute, which can detect    changes within the value itself.    """    def __init__(self, class_, key, callable_, copy_function=None, compare_function=None, **kwargs):        super(ScalarAttributeImpl, self).__init__(class_, key, callable_, compare_function=compare_function, **kwargs)        class_._class_state.has_mutable_scalars = True        if copy_function is None:            raise exceptions.ArgumentError("MutableScalarAttributeImpl requires a copy function")        self.copy = copy_function    def get_history(self, state, passive=False):        return _create_history(self, state, state.dict.get(self.key, NO_VALUE))    def commit_to_state(self, state, value):        state.committed_state[self.key] = self.copy(value)    def check_mutable_modified(self, state):        (added, unchanged, deleted) = self.get_history(state, passive=True)        if added or deleted:            state.modified = True            return True        else:            return False    def set(self, state, value, initiator):        if initiator is self:            return        if self.key not in state.committed_state:            if self.key in state.dict:                state.committed_state[self.key] = self.copy(state.dict[self.key])            else:                state.committed_state[self.key] = NO_VALUE        state.dict[self.key] = value        state.modified=Trueclass ScalarObjectAttributeImpl(ScalarAttributeImpl):    """represents a scalar-holding InstrumentedAttribute, where the target object is also instrumented.    Adds events to delete/set operations.    """    accepts_scalar_loader = False    def __init__(self, class_, key, callable_, trackparent=False, extension=None, copy_function=None, compare_function=None, **kwargs):        super(ScalarObjectAttributeImpl, self).__init__(class_, key,          callable_, trackparent=trackparent, extension=extension,          compare_function=compare_function, **kwargs)        if compare_function is None:            self.is_equal = identity_equal    def delete(self, state):        old = self.get(state)        # TODO: catch key errors, convert to attributeerror?        del state.dict[self.key]        self.fire_remove_event(state, old, self)    def get_history(self, state, passive=False):        if self.key in state.dict:            return _create_history(self, state, state.dict[self.key])        else:            current = self.get(state, passive=passive)            if current is PASSIVE_NORESULT:                return (None, None, None)            else:                return _create_history(self, state, current)    def set(self, state, value, initiator):        """Set a value on the given InstanceState.        `initiator` is the ``InstrumentedAttribute`` that initiated the        ``set()` operation and is used to control the depth of a circular        setter operation.        """        if initiator is self:            return        # TODO: add options to allow the get() to be passive        old = self.get(state)        state.dict[self.key] = value        self.fire_replace_event(state, value, old, initiator)    def fire_remove_event(self, state, value, initiator):        if self.key not in state.committed_state:            state.committed_state[self.key] = value        state.modified = True        if self.trackparent and value is not None:            self.sethasparent(value._state, False)        instance = state.obj()        for ext in self.extensions:            ext.remove(instance, value, initiator or self)    def fire_replace_event(self, state, value, previous, initiator):        if self.key not in state.committed_state:            state.committed_state[self.key] = previous        state.modified = True        if self.trackparent:            if value is not None:                self.sethasparent(value._state, True)            if previous is not value and previous is not None:                self.sethasparent(previous._state, False)        instance = state.obj()        for ext in self.extensions:            ext.set(instance, value, previous, initiator or self)class CollectionAttributeImpl(AttributeImpl):    """A collection-holding attribute that instruments changes in membership.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -