def __hash__(self):
raise TypeError("%s objects are unhashable" % type(self).__name__)
-_NotProvided = object()
+_NotProvided = util.symbol('_NotProvided')
class _AssociationDict(object):
"""Generic proxying list which proxies dict operations to a another dict,
converting association objects to and from a simplified value.
from sqlalchemy.orm.util import identity_equal
from sqlalchemy import exceptions
-PASSIVE_NORESULT = object()
-ATTR_WAS_SET = object()
-NO_VALUE = object()
-NEVER_SET = object()
+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
setattr(fn, '_sa_instrumented', True)
fn.__doc__ = getattr(getattr(dict, fn.__name__), '__doc__')
- Unspecified=object()
+ Unspecified=sautil.symbol('Unspecified')
def __setitem__(fn):
def __setitem__(self, key, value, _sa_initiator=None):
setattr(fn, '_sa_instrumented', True)
fn.__doc__ = getattr(getattr(Set, fn.__name__), '__doc__')
- Unspecified=object()
+ Unspecified=sautil.symbol('Unspecified')
def add(fn):
def add(self, value, _sa_initiator=None):
"""
from itertools import chain
-from sqlalchemy import exceptions, logging
+from sqlalchemy import exceptions, logging, util
from sqlalchemy.sql import expression
class_mapper = None
'ExtensionOption', 'PropertyOption',
'AttributeExtension', 'StrategizedOption', 'LoaderStrategy' ]
-EXT_CONTINUE = EXT_PASS = object()
-EXT_STOP = object()
+EXT_CONTINUE = EXT_PASS = util.symbol('EXT_CONTINUE')
+EXT_STOP = util.symbol('EXT_STOP')
class MapperExtension(object):
"""Base implementation for customizing Mapper behavior.
# a constant returned by _get_attr_by_column to indicate
# this mapper is not handling an attribute for a particular
# column
-NO_ATTRIBUTE = object()
+NO_ATTRIBUTE = util.symbol('NO_ATTRIBUTE')
# lock used to synchronize the "mapper compile" step
_COMPILE_MUTEX = util.threading.Lock()
from operator import and_, or_, inv, add, mul, sub, div, mod, truediv, \
lt, le, ne, gt, ge, eq
-
-from sqlalchemy.util import Set
+from sqlalchemy.util import Set, symbol
def from_():
raise NotImplementedError()
_commutative = Set([eq, ne, add, mul])
def is_commutative(op):
return op in _commutative
-
-_smallest = object()
-_largest = object()
+
+_smallest = symbol('_smallest')
+_largest = symbol('_largest')
_PRECEDENCE = {
from_:15,
def _get_key(self):
return self.scopefunc()
+class symbol(object):
+ """A constant symbol.
+
+ >>> symbol('foo') is symbol('foo')
+ True
+ >>> symbol('foo')
+ <symbol 'foo>
+
+ A slight refinement of the MAGICCOOKIE=object() pattern. The primary
+ advantage of symbol() is its repr(). They are also singletons.
+ """
+
+ symbols = {}
+ _lock = threading.Lock()
+
+ def __new__(cls, name):
+ try:
+ symbol._lock.acquire()
+ sym = cls.symbols.get(name)
+ if sym is None:
+ cls.symbols[name] = sym = object.__new__(cls, name)
+ return sym
+ finally:
+ symbol._lock.release()
+
+ def __init__(self, name):
+ """Construct a new named symbol.
+
+ Repeated calls of symbol('name') will all return the same instance.
+ """
+
+ assert isinstance(name, str)
+ self.name = name
+ def __repr__(self):
+ return "<symbol '%s>" % self.name
+
def warn(msg):
if isinstance(msg, basestring):
warnings.warn(msg, exceptions.SAWarning, stacklevel=3)