def test_bitflags(self): sym1 = util.symbol('sym1', canonical=1) sym2 = util.symbol('sym2', canonical=2) assert sym1 & sym1 assert not sym1 & sym2 assert not sym1 & sym1 & sym2
def _on_field_change(offer, value, old_value, initiator): if old_value == symbol('NO_VALUE') or old_value == symbol('NEVER_SET'): old_value = None if offer.offer_id and value != old_value and old_value is not None: log = OfferLog(offer=offer) log.offer_id = offer.offer_id setattr(log, field, old_value) db.session.add(log) db.session.commit()
def test_composites(self): sym1 = util.symbol('sym1', canonical=1) sym2 = util.symbol('sym2', canonical=2) sym3 = util.symbol('sym3', canonical=4) sym4 = util.symbol('sym4', canonical=8) assert sym1 & (sym2 | sym1 | sym4) assert not sym1 & (sym2 | sym3) assert not (sym1 | sym2) & (sym3 | sym4) assert (sym1 | sym2) & (sym2 | sym4)
def set_banner_fileUpload(target, value, oldvalue, initiator): """ Delete banner file when set This function is called every time the banner fileupload attribute is set. The function deletes the old image file when the fileupload attribute is set to a new value (a new image file is uploaded). """ if oldvalue != symbol("NO_VALUE") and oldvalue != symbol("NEVER_SET") and value != oldvalue: os.remove(os.path.join(app.config["UPLOAD_FOLDER"], oldvalue))
def test_basic(self): sym1 = util.symbol('foo') assert sym1.name == 'foo' sym2 = util.symbol('foo') assert sym1 is sym2 assert sym1 == sym2 sym3 = util.symbol('bar') assert sym1 is not sym3 assert sym1 != sym3
def test_pickle(self): sym1 = util.symbol('foo') sym2 = util.symbol('foo') assert sym1 is sym2 # default s = util.pickle.dumps(sym1) sym3 = util.pickle.loads(s) for protocol in 0, 1, 2: print protocol serial = util.pickle.dumps(sym1) rt = util.pickle.loads(serial) assert rt is sym1 assert rt is sym2
def _install_lookup_strategy(implementation): """Replace global class/object management functions with either faster or more comprehensive implementations, based on whether or not extended class instrumentation has been detected. This function is called only by InstrumentationRegistry() and unit tests specific to this behavior. """ global instance_state, instance_dict, manager_of_class if implementation is util.symbol('native'): instance_state = attrgetter(ClassManager.STATE_ATTR) instance_dict = attrgetter("__dict__") def manager_of_class(cls): return cls.__dict__.get(ClassManager.MANAGER_ATTR, None) else: instance_state = instrumentation_registry.state_of instance_dict = instrumentation_registry.dict_of manager_of_class = instrumentation_registry.manager_of_class attributes.instance_state = instance_state attributes.instance_dict = instance_dict attributes.manager_of_class = manager_of_class
def tearDownAll(self): clear_mappers() attributes._install_lookup_strategy(util.symbol('native'))
return cls.__dict__.get(ClassManager.MANAGER_ATTR, None) else: instance_state = instrumentation_registry.state_of instance_dict = instrumentation_registry.dict_of manager_of_class = instrumentation_registry.manager_of_class attributes.instance_state = instance_state attributes.instance_dict = instance_dict attributes.manager_of_class = manager_of_class _create_manager_for_cls = instrumentation_registry.create_manager_for_cls # Install default "lookup" strategies. These are basically # very fast attrgetters for key attributes. # When a custom ClassManager is installed, more expensive per-class # strategies are copied over these. _install_lookup_strategy(util.symbol('native')) def find_native_user_instrumentation_hook(cls): """Find user-specified instrumentation management for a class.""" return getattr(cls, INSTRUMENTATION_MANAGER, None) instrumentation_finders.append(find_native_user_instrumentation_hook) def _generate_init(class_, class_manager): """Build an __init__ decorator that triggers ClassManager events.""" # TODO: we should use the ClassManager's notion of the # original '__init__' method, once ClassManager is fixed # to always reference that. original__init__ = class_.__init__ assert original__init__
""" # TODO: performance def __init__(comp): if isinstance(comp, dict): pass elif isinstance(comp, list): pass elif isinstance(comp, str): pass def apply(self, operation, target, *args, **kwargs): pass COMPOSIVE_PROXY = util.symbol('COMPOSIVE_PROXY') class ComposiveProxy(interfaces.InspectionAttrInfo): """A descriptor that presents a read/write view of an object attribute.""" is_attribute = False extension_type = COMPOSIVE_PROXY def __init__(self, target_collection, composition): """ """ self.owning_class = None self.key = '_%s_%s_%s' % (type(self).__name__, target_collection, id(self))
raise NotImplementedError() def concat_op(a, b): return a.concat(b) def desc_op(a): return a.desc() def asc_op(a): return a.asc() _commutative = set([eq, ne, add, mul]) def is_commutative(op): return op in _commutative _smallest = symbol('_smallest') _largest = symbol('_largest') _PRECEDENCE = { from_: 15, mul: 7, div: 7, mod: 7, add: 6, sub: 6, concat_op: 6, match_op: 6, ilike_op: 5, notilike_op: 5, like_op: 5, notlike_op: 5,
# sqlalchemy/event.py # Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file> # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Base event API.""" from sqlalchemy import util, exc import weakref CANCEL = util.symbol('CANCEL') NO_RETVAL = util.symbol('NO_RETVAL') def listen(target, identifier, fn, *args, **kw): """Register a listener function for the given target. e.g.:: from sqlalchemy import event from sqlalchemy.schema import UniqueConstraint def unique_constraint_name(const, table): const.name = "uq_%s_%s" % ( table.name, list(const.columns)[0].name ) event.listen( UniqueConstraint, "after_parent_attach", unique_constraint_name)
try: return proxies[module] except KeyError: return proxies.setdefault(module, _DBProxy(module, **params)) def clear_managers(): """Remove all current DB-API 2.0 managers. All pools and connections are disposed. """ for manager in proxies.itervalues(): manager.close() proxies.clear() reset_rollback = util.symbol('reset_rollback') reset_commit = util.symbol('reset_commit') reset_none = util.symbol('reset_none') class Pool(log.Identified): """Abstract base class for connection pools.""" def __init__(self, creator, recycle=-1, echo=None, use_threadlocal=False, logging_name=None, reset_on_return=True, listeners=None, events=None, _dispatch=None):
def _is_hybrid_property(orm_descriptor): return orm_descriptor.extension_type == symbol('HYBRID_PROPERTY')
return list(self) def __repr__(self): return repr(list(self)) def __hash__(self): raise TypeError("%s objects are unhashable" % type(self).__name__) for func_name, func in list(locals().items()): if (util.callable(func) and func.__name__ == func_name and not func.__doc__ and hasattr(list, func_name)): func.__doc__ = getattr(list, func_name).__doc__ del func_name, func _NotProvided = util.symbol('_NotProvided') class _AssociationDict(_AssociationCollection): """Generic, converting, dict-to-dict proxy.""" def _create(self, key, value): return self.creator(key, value) def _get(self, object): return self.getter(object) def _set(self, object, key, value): return self.setter(object, key, value) def __getitem__(self, key): return self._get(self.col[key])
def nullslast_op(a): return a.nullslast() _commutative = set([eq, ne, add, mul]) def is_commutative(op): return op in _commutative def is_ordering_modifier(op): return op in (asc_op, desc_op, nullsfirst_op, nullslast_op) _associative = _commutative.union([concat_op, and_, or_]) _smallest = symbol('_smallest') _largest = symbol('_largest') _PRECEDENCE = { from_: 15, mul: 7, truediv: 7, # Py2K div: 7, # end Py2K mod: 7, neg: 7, add: 6, sub: 6, concat_op: 6, match_op: 6,
def set_only_once(target, new_value, old_value, initiator): if old_value == new_value: return if old_value not in [None, symbol('NEVER_SET'), symbol('NO_VALUE')]: raise AttributeError("Attempted to set an immutable attribute")
This module is usually not directly visible to user applications, but defines a large part of the ORM's interactivity. """ import operator from operator import itemgetter from sqlalchemy import util, event, exc as sa_exc from sqlalchemy.orm import interfaces, collections, events mapperutil = util.importlater("sqlalchemy.orm", "util") PASSIVE_NO_RESULT = util.symbol('PASSIVE_NO_RESULT') ATTR_WAS_SET = util.symbol('ATTR_WAS_SET') ATTR_EMPTY = util.symbol('ATTR_EMPTY') NO_VALUE = util.symbol('NO_VALUE') NEVER_SET = util.symbol('NEVER_SET') PASSIVE_RETURN_NEVER_SET = util.symbol( 'PASSIVE_RETURN_NEVER_SET' """Symbol indicating that loader callables can be fired off, but if no callable is applicable and no value is present, the attribute should remain non-initialized. NEVER_SET is returned in this case. """) PASSIVE_NO_INITIALIZE = util.symbol( 'PASSIVE_NO_INITIALIZE', """Symbol indicating that loader callables should
For more information on the PostgreSQL feature, see the ``ON CONFLICT` section of the `INSERT` statement in the PostgreSQL docs <http://www.postgresql.org/docs/current/static/sql-insert.html#SQL-ON-CONFLICT>`_. """ import sqlalchemy.dialects.postgresql.base from sqlalchemy.sql import compiler, expression, crud from sqlalchemy import util from sqlalchemy.sql.expression import ClauseElement, ColumnClause, ColumnElement from sqlalchemy.ext.compiler import compiles from sqlalchemy.exc import CompileError from sqlalchemy.schema import UniqueConstraint, PrimaryKeyConstraint, Index from collections import Iterable ISINSERT = util.symbol('ISINSERT') ISUPDATE = util.symbol('ISUPDATE') ISDELETE = util.symbol('ISDELETE') def _setup_crud_params(compiler, stmt, local_stmt_type, **kw): restore_isinsert = compiler.isinsert restore_isupdate = compiler.isupdate restore_isdelete = compiler.isdelete should_restore = ( restore_isinsert or restore_isupdate or restore_isdelete ) or len(compiler.stack) > 1 if local_stmt_type is ISINSERT: compiler.isupdate = False compiler.isinsert = True
# Replace __init__(), feed defaults original_init = cls.__init__ def __init__(self, /, **values): return original_init(self, **{**defaults, **values}) cls.__init__ = __init__ # Done return cls return wrapper def dataclass_notset(*names): """ Set a default NOTSET value for a dataclass with __slots__ Example: @dataclass_notset('key') @dataclass class Object: key: str """ return dataclass_defaults(**{ name: NOTSET for name in names }) # Marker for values not yet set NOTSET = symbol('NOTSET')
def unit_set(target, value, oldvalue, initiator): """ Listen for the unit 'set' event and convert target's value when the new unit is different/""" if (oldvalue != symbol('NO_VALUE')) and (oldvalue != value): target.value = (target.value*oldvalue).to(value).value
def _is_hybrid_method(orm_descriptor): return orm_descriptor.extension_type == symbol('HYBRID_METHOD')
def teardown_class(cls): clear_mappers() attributes._install_lookup_strategy(util.symbol('native'))
# attributes.py - manages object attributes # Copyright (C) 2005, 2006, 2007, 2008 Michael Bayer [email protected] # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php import operator, weakref from itertools import chain import UserDict from sqlalchemy import util from sqlalchemy.orm import interfaces, collections from sqlalchemy.orm.util import identity_equal from sqlalchemy import exceptions PASSIVE_NORESULT = util.symbol("PASSIVE_NORESULT") ATTR_WAS_SET = util.symbol("ATTR_WAS_SET") NO_VALUE = util.symbol("NO_VALUE") NEVER_SET = util.symbol("NEVER_SET") 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 """
# sqlalchemy/event.py # Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file> # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Base event API.""" from sqlalchemy import util, exc CANCEL = util.symbol('CANCEL') NO_RETVAL = util.symbol('NO_RETVAL') def listen(target, identifier, fn, *args, **kw): """Register a listener function for the given target. e.g.:: from sqlalchemy import event from sqlalchemy.schema import UniqueConstraint def unique_constraint_name(const, table): const.name = "uq_%s_%s" % ( table.name, list(const.columns)[0].name ) event.listen( UniqueConstraint, "after_parent_attach", unique_constraint_name)
"EXT_STOP", "ExtensionOption", "InstrumentationManager", "LoaderStrategy", "MapperExtension", "MapperOption", "MapperProperty", "PropComparator", "PropertyOption", "SessionExtension", "StrategizedOption", "StrategizedProperty", "build_path", ) EXT_CONTINUE = util.symbol("EXT_CONTINUE") EXT_STOP = util.symbol("EXT_STOP") ONETOMANY = util.symbol("ONETOMANY") MANYTOONE = util.symbol("MANYTOONE") MANYTOMANY = util.symbol("MANYTOMANY") class MapperExtension(object): """Base implementation for customizing ``Mapper`` behavior. New extension classes subclass ``MapperExtension`` and are specified using the ``extension`` mapper() argument, which is a single ``MapperExtension`` or a list of such. A single mapper can maintain a chain of ``MapperExtension`` objects. When a particular mapping event occurs, the corresponding method
else: instance_state = instrumentation_registry.state_of instance_dict = instrumentation_registry.dict_of manager_of_class = instrumentation_registry.manager_of_class attributes.instance_state = instance_state attributes.instance_dict = instance_dict attributes.manager_of_class = manager_of_class _create_manager_for_cls = instrumentation_registry.create_manager_for_cls # Install default "lookup" strategies. These are basically # very fast attrgetters for key attributes. # When a custom ClassManager is installed, more expensive per-class # strategies are copied over these. _install_lookup_strategy(util.symbol('native')) def find_native_user_instrumentation_hook(cls): """Find user-specified instrumentation management for a class.""" return getattr(cls, INSTRUMENTATION_MANAGER, None) instrumentation_finders.append(find_native_user_instrumentation_hook) def _generate_init(class_, class_manager): """Build an __init__ decorator that triggers ClassManager events.""" # TODO: we should use the ClassManager's notion of the # original '__init__' method, once ClassManager is fixed
_commutative = set([eq, ne, add, mul]) def is_commutative(op): return op in _commutative def is_ordering_modifier(op): return op in (asc_op, desc_op, nullsfirst_op, nullslast_op) _associative = _commutative.union([concat_op, and_, or_]) _smallest = symbol("_smallest") _largest = symbol("_largest") _PRECEDENCE = { from_: 15, mul: 7, truediv: 7, # Py2K div: 7, # end Py2K mod: 7, neg: 7, add: 6, sub: 6, concat_op: 6, match_op: 6,
def teardown_class(cls): clear_mappers() instrumentation._install_lookup_strategy(util.symbol('native'))
def parse_select(d): """ Defintion of a select query according to http://www.postgresql.org/docs/9.3/static/sql-select.html not implemented: [ WITH [ RECURSIVE ] with_query [, ...] ] [ WINDOW window_name AS ( window_definition ) [, ...] ] [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...] ] """ distinct = d.get('distinct', False) L = None keyword = d.get('keyword') if keyword and keyword.lower() in ['union', 'except', 'intersect']: partials = [] for part_sel in d.get('selects', []): t = part_sel.get('type') if t == 'grouping': grouping = get_or_403(part_sel, 'grouping') if isinstance(grouping, dict): partials.append(parse_select(grouping)) elif isinstance(grouping, list): partials = map(parse_select, grouping) else: APIError( 'Cannot handle grouping type. Dictionary or list expected.' ) elif t == 'select': partials.append(parse_select(part_sel)) else: raise APIError('Unknown select type: ' + t) query = CompoundSelect(util.symbol(keyword), *partials) else: kwargs = dict(distinct=distinct) if 'fields' in d and d['fields']: L = [] for field in d['fields']: col = parse_expression(field) if 'as' in field: col.label(read_pgid(field['as'])) L.append(col) if 'from' in d: kwargs['from_obj'] = parse_from_item(get_or_403(d, 'from')) else: kwargs['from_obj'] = [] if not L: L = '*' kwargs['columns'] = L query = select(**kwargs) # [ WHERE condition ] if d.get('where', False): query = query.where(parse_condition(d['where'])) if 'group_by' in d: query = query.group_by(*[parse_expression(f) for f in d['group_by']]) if 'having' in d: query.having([parse_condition(f) for f in d['having']]) if 'select' in d: for constraint in d['select']: type = get_or_403(constraint, 'type') subquery = parse_select(get_or_403(constraint, 'query')) if type.lower() == 'union': query.union(subquery) elif type.lower() == 'intersect': query.intersect(subquery) elif type.lower() == 'except': query.except_(subquery) if 'order_by' in d: for ob in d['order_by']: expr = parse_expression(ob) if isinstance(ob, dict): desc = ob.get('ordering', 'asc').lower() == 'desc' if desc: expr = expr.desc() query = query.order_by(expr) if 'limit' in d: if isinstance(d['limit'], int) or d['limit'].isdigit(): query = query.limit(int(d['limit'])) else: raise APIError('Invalid LIMIT: Expected a digit') if 'offset' in d: if isinstance(d['offset'], int) or d['offset'].isdigit(): query = query.offset(int(d['offset'])) else: raise APIError('Invalid LIMIT: Expected a digit') return query
# sqlalchemy/event.py # Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file> # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php """Base event API.""" from sqlalchemy import util, exc CANCEL = util.symbol("CANCEL") NO_RETVAL = util.symbol("NO_RETVAL") def listen(target, identifier, fn, *args, **kw): """Register a listener function for the given target. e.g.:: from sqlalchemy import event from sqlalchemy.schema import UniqueConstraint def unique_constraint_name(const, table): const.name = "uq_%s_%s" % ( table.name, list(const.columns)[0].name ) event.listen( UniqueConstraint, "after_parent_attach", unique_constraint_name)
This module is usually not directly visible to user applications, but defines a large part of the ORM's interactivity. """ import operator from operator import itemgetter from sqlalchemy import util, event, exc as sa_exc from sqlalchemy.orm import interfaces, collections, events mapperutil = util.importlater("sqlalchemy.orm", "util") PASSIVE_NO_RESULT = util.symbol('PASSIVE_NO_RESULT') ATTR_WAS_SET = util.symbol('ATTR_WAS_SET') ATTR_EMPTY = util.symbol('ATTR_EMPTY') NO_VALUE = util.symbol('NO_VALUE') NEVER_SET = util.symbol('NEVER_SET') PASSIVE_RETURN_NEVER_SET = util.symbol('PASSIVE_RETURN_NEVER_SET' """Symbol indicating that loader callables can be fired off, but if no callable is applicable and no value is present, the attribute should remain non-initialized. NEVER_SET is returned in this case. """) PASSIVE_NO_INITIALIZE = util.symbol('PASSIVE_NO_INITIALIZE', """Symbol indicating that loader callables should not be fired off, and a non-initialized attribute
def parse_select(d): """ Defintion of a select query according to http://www.postgresql.org/docs/9.3/static/sql-select.html not implemented: [ WITH [ RECURSIVE ] with_query [, ...] ] [ WINDOW window_name AS ( window_definition ) [, ...] ] [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...] ] """ distinct = d.get("distinct", False) L = None keyword = d.get("keyword") if keyword and keyword.lower() in ["union", "except", "intersect"]: partials = [] for part_sel in d.get("selects", []): t = part_sel.get("type") if t == "grouping": grouping = get_or_403(part_sel, "grouping") if isinstance(grouping, dict): partials.append(parse_select(grouping)) elif isinstance(grouping, list): partials = map(parse_select, grouping) else: APIError( "Cannot handle grouping type. Dictionary or list expected." ) elif t == "select": partials.append(parse_select(part_sel)) else: raise APIError("Unknown select type: " + t) query = CompoundSelect(util.symbol(keyword), *partials) else: kwargs = dict(distinct=distinct) if "fields" in d and d["fields"]: L = [] for field in d["fields"]: if isinstance(field, str): field = dict(type="column", column=field) col = parse_expression(field) if "as" in field: col.label(read_pgid(field["as"])) L.append(col) if "from" in d: kwargs["from_obj"] = parse_from_item(get_or_403(d, "from")) else: kwargs["from_obj"] = [] if not L: L = "*" kwargs["columns"] = L query = select(**kwargs) # [ WHERE condition ] if d.get("where", False): query = query.where(parse_condition(d["where"])) if "group_by" in d: query = query.group_by(*[parse_expression(f) for f in d["group_by"]]) if "having" in d: query.having([parse_condition(f) for f in d["having"]]) if "select" in d: for constraint in d["select"]: type = get_or_403(constraint, "type") subquery = parse_select(get_or_403(constraint, "query")) if type.lower() == "union": query.union(subquery) elif type.lower() == "intersect": query.intersect(subquery) elif type.lower() == "except": query.except_(subquery) if "order_by" in d: for ob in d["order_by"]: expr = parse_expression(ob) if isinstance(ob, dict): desc = ob.get("ordering", "asc").lower() == "desc" if desc: expr = expr.desc() query = query.order_by(expr) if "limit" in d: if isinstance(d["limit"], int) or d["limit"].isdigit(): query = query.limit(int(d["limit"])) else: raise APIError("Invalid LIMIT: Expected a digit") if "offset" in d: if isinstance(d["offset"], int) or d["offset"].isdigit(): query = query.offset(int(d["offset"])) else: raise APIError("Invalid LIMIT: Expected a digit") return query
def _dict_decorators(): """Tailored instrumentation wrappers for any dict-like mapping class.""" def _tidy(fn): setattr(fn, '_sa_instrumented', True) fn.__doc__ = getattr(getattr(dict, fn.__name__), '__doc__') Unspecified = util.symbol('Unspecified') def __setitem__(fn): def __setitem__(self, key, value, _sa_initiator=None): if key in self: __del(self, self[key], _sa_initiator) value = __set(self, value, _sa_initiator) fn(self, key, value) _tidy(__setitem__) return __setitem__ def __delitem__(fn): def __delitem__(self, key, _sa_initiator=None): if key in self: __del(self, self[key], _sa_initiator) fn(self, key) _tidy(__delitem__) return __delitem__ def clear(fn): def clear(self): for key in self: __del(self, self[key]) fn(self) _tidy(clear) return clear def pop(fn): def pop(self, key, default=Unspecified): if key in self: __del(self, self[key]) if default is Unspecified: return fn(self, key) else: return fn(self, key, default) _tidy(pop) return pop def popitem(fn): def popitem(self): __before_delete(self) item = fn(self) __del(self, item[1]) return item _tidy(popitem) return popitem def setdefault(fn): def setdefault(self, key, default=None): if key not in self: self.__setitem__(key, default) return default else: return self.__getitem__(key) _tidy(setdefault) return setdefault if sys.version_info < (2, 4): def update(fn): def update(self, other): for key in other.keys(): if key not in self or self[key] is not other[key]: self[key] = other[key] _tidy(update) return update else: def update(fn): def update(self, __other=Unspecified, **kw): if __other is not Unspecified: if hasattr(__other, 'keys'): for key in __other.keys(): if (key not in self or self[key] is not __other[key]): self[key] = __other[key] else: for key, value in __other: if key not in self or self[key] is not value: self[key] = value for key in kw: if key not in self or self[key] is not kw[key]: self[key] = kw[key] _tidy(update) return update l = locals().copy() l.pop('_tidy') l.pop('Unspecified') return l
except KeyError: return proxies.setdefault(module, _DBProxy(module, **params)) def clear_managers(): """Remove all current DB-API 2.0 managers. All pools and connections are disposed. """ for manager in proxies.itervalues(): manager.close() proxies.clear() reset_rollback = util.symbol('reset_rollback') reset_commit = util.symbol('reset_commit') reset_none = util.symbol('reset_none') class Pool(log.Identified): """Abstract base class for connection pools.""" def __init__(self, creator, recycle=-1, echo=None, use_threadlocal=False, logging_name=None, reset_on_return=True, listeners=None, events=None,
def _set_decorators(): """Tailored instrumentation wrappers for any set-like class.""" def _tidy(fn): setattr(fn, '_sa_instrumented', True) fn.__doc__ = getattr(getattr(set, fn.__name__), '__doc__') Unspecified = util.symbol('Unspecified') def add(fn): def add(self, value, _sa_initiator=None): if value not in self: value = __set(self, value, _sa_initiator) # testlib.pragma exempt:__hash__ fn(self, value) _tidy(add) return add if sys.version_info < (2, 4): def discard(fn): def discard(self, value, _sa_initiator=None): if value in self: self.remove(value, _sa_initiator) _tidy(discard) return discard else: def discard(fn): def discard(self, value, _sa_initiator=None): # testlib.pragma exempt:__hash__ if value in self: __del(self, value, _sa_initiator) # testlib.pragma exempt:__hash__ fn(self, value) _tidy(discard) return discard def remove(fn): def remove(self, value, _sa_initiator=None): # testlib.pragma exempt:__hash__ if value in self: __del(self, value, _sa_initiator) # testlib.pragma exempt:__hash__ fn(self, value) _tidy(remove) return remove def pop(fn): def pop(self): __before_delete(self) item = fn(self) __del(self, item) return item _tidy(pop) return pop def clear(fn): def clear(self): for item in list(self): self.remove(item) _tidy(clear) return clear def update(fn): def update(self, value): for item in value: self.add(item) _tidy(update) return update def __ior__(fn): def __ior__(self, value): if not _set_binops_check_strict(self, value): return NotImplemented for item in value: self.add(item) return self _tidy(__ior__) return __ior__ def difference_update(fn): def difference_update(self, value): for item in value: self.discard(item) _tidy(difference_update) return difference_update def __isub__(fn): def __isub__(self, value): if not _set_binops_check_strict(self, value): return NotImplemented for item in value: self.discard(item) return self _tidy(__isub__) return __isub__ def intersection_update(fn): def intersection_update(self, other): want, have = self.intersection(other), set(self) remove, add = have - want, want - have for item in remove: self.remove(item) for item in add: self.add(item) _tidy(intersection_update) return intersection_update def __iand__(fn): def __iand__(self, other): if not _set_binops_check_strict(self, other): return NotImplemented want, have = self.intersection(other), set(self) remove, add = have - want, want - have for item in remove: self.remove(item) for item in add: self.add(item) return self _tidy(__iand__) return __iand__ def symmetric_difference_update(fn): def symmetric_difference_update(self, other): want, have = self.symmetric_difference(other), set(self) remove, add = have - want, want - have for item in remove: self.remove(item) for item in add: self.add(item) _tidy(symmetric_difference_update) return symmetric_difference_update def __ixor__(fn): def __ixor__(self, other): if not _set_binops_check_strict(self, other): return NotImplemented want, have = self.symmetric_difference(other), set(self) remove, add = have - want, want - have for item in remove: self.remove(item) for item in add: self.add(item) return self _tidy(__ixor__) return __ixor__ l = locals().copy() l.pop('_tidy') l.pop('Unspecified') return l
# attributes.py - manages object attributes # Copyright (C) 2005, 2006, 2007, 2008 Michael Bayer [email protected] # # This module is part of SQLAlchemy and is released under # the MIT License: http://www.opensource.org/licenses/mit-license.php import operator, weakref from itertools import chain import UserDict from sqlalchemy import util from sqlalchemy.orm import interfaces, collections from sqlalchemy.orm.util import identity_equal from sqlalchemy import exceptions PASSIVE_NORESULT = util.symbol('PASSIVE_NORESULT') ATTR_WAS_SET = util.symbol('ATTR_WAS_SET') NO_VALUE = util.symbol('NO_VALUE') NEVER_SET = util.symbol('NEVER_SET') 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 """
'EXT_STOP', 'ExtensionOption', 'InstrumentationManager', 'LoaderStrategy', 'MapperExtension', 'MapperOption', 'MapperProperty', 'PropComparator', 'PropertyOption', 'SessionExtension', 'StrategizedOption', 'StrategizedProperty', 'build_path', ) EXT_CONTINUE = util.symbol('EXT_CONTINUE') EXT_STOP = util.symbol('EXT_STOP') ONETOMANY = util.symbol('ONETOMANY') MANYTOONE = util.symbol('MANYTOONE') MANYTOMANY = util.symbol('MANYTOMANY') from .deprecated_interfaces import AttributeExtension, SessionExtension, \ MapperExtension class MapperProperty(object): """Manage the relationship of a ``Mapper`` to a single class attribute, as well as that attribute as it appears on individual instances of the class, including attribute instrumentation, attribute access, loading behavior, and dependency calculations.
'EXT_STOP', 'ExtensionOption', 'InstrumentationManager', 'LoaderStrategy', 'MapperExtension', 'MapperOption', 'MapperProperty', 'PropComparator', 'PropertyOption', 'SessionExtension', 'StrategizedOption', 'StrategizedProperty', 'build_path', ) EXT_CONTINUE = util.symbol('EXT_CONTINUE') EXT_STOP = util.symbol('EXT_STOP') ONETOMANY = util.symbol('ONETOMANY') MANYTOONE = util.symbol('MANYTOONE') MANYTOMANY = util.symbol('MANYTOMANY') class MapperExtension(object): """Base implementation for customizing ``Mapper`` behavior. New extension classes subclass ``MapperExtension`` and are specified using the ``extension`` mapper() argument, which is a single ``MapperExtension`` or a list of such. A single mapper can maintain a chain of ``MapperExtension`` objects. When a particular mapping event occurs, the corresponding method on each ``MapperExtension`` is invoked serially, and each method
def copy(self): return list(self) def __repr__(self): return repr(list(self)) def __hash__(self): raise TypeError("%s objects are unhashable" % type(self).__name__) for func_name, func in locals().items(): if util.callable(func) and func.func_name == func_name and not func.__doc__ and hasattr(list, func_name): func.__doc__ = getattr(list, func_name).__doc__ del func_name, func _NotProvided = util.symbol("_NotProvided") class _AssociationDict(_AssociationCollection): """Generic, converting, dict-to-dict proxy.""" def _create(self, key, value): return self.creator(key, value) def _get(self, object): return self.getter(object) def _set(self, object, key, value): return self.setter(object, key, value) def __getitem__(self, key):
from sqlalchemy.orm.attributes import InstrumentedAttribute, QueryableAttribute from sqlalchemy.orm.base import InspectionAttr, MANYTOMANY, MANYTOONE, ONETOMANY from sqlalchemy.orm.dynamic import DynaLoader from sqlalchemy.sql import ColumnElement, Selectable from sqlalchemy.sql.elements import Label from sqlalchemy.sql.type_api import TypeEngine from sqlalchemy.util import symbol from sa2schema import SAAttributeType from sa2schema.compat import Literal, get_args, get_origin from sa2schema.util import get_deep_subclasses from .defs import AttributeType from .property import get_property_loads_attribute_names # Value not provided (e.g. `default` value) NOT_PROVIDED = symbol('NOT_PROVIDED') # AttributeInfo type variable Info_T = TypeVar('Info_T') @dataclass class AttributeInfo: """ Information about an SqlAlchemy attribute. Base class.""" # To support new properties on SqlAlchemy models, just implement another class. # If the extracted type is unsatisfactory, it can be overridden with annotations. # Attribute type attribute_type: AttributeType # Attribute itself