]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- merge default tip
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 5 Dec 2010 19:56:26 +0000 (14:56 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 5 Dec 2010 19:56:26 +0000 (14:56 -0500)
16 files changed:
1  2 
lib/sqlalchemy/dialects/postgresql/base.py
lib/sqlalchemy/orm/query.py
lib/sqlalchemy/sql/expression.py
lib/sqlalchemy/sql/operators.py
lib/sqlalchemy/util/langhelpers.py
test/aaa_profiling/test_memusage.py
test/base/test_utils.py
test/dialect/test_postgresql.py
test/ext/test_sqlsoup.py
test/orm/inheritance/test_basic.py
test/orm/test_eager_relations.py
test/orm/test_expire.py
test/orm/test_mapper.py
test/orm/test_query.py
test/perf/insertspeed.py
test/sql/test_compiler.py

Simple merge
Simple merge
index 67830f7cf5ffdb31879efcd52d5a631df6378326,68e30e646d88e9a41c3ca0b471b24f0f41d47cd1..0577e66687b34ee13f67a4e1e330ff34464b3562
@@@ -83,7 -83,8 +83,8 @@@ def desc_op(a)
  def asc_op(a):
      return a.asc()
  
- _commutative = set([eq, ne, add, mul, and_])
 -
+ _commutative = set([eq, ne, add, mul])
++
  def is_commutative(op):
      return op in _commutative
  
index aac22ba309f48987acc4561fd6f5603f1ab54ba0,0000000000000000000000000000000000000000..d85793ee0760560dd125da65070ac4a28515ef8c
mode 100644,000000..100644
--- /dev/null
@@@ -1,689 -1,0 +1,691 @@@
-         m = __import__(self._il_path)
-         for token in self._il_path.split(".")[1:]:
-             m = getattr(m, token)
 +"""Routines to help with the creation, loading and introspection of 
 +modules, classes, hierarchies, attributes, functions, and methods.
 +
 +"""
 +import itertools
 +import inspect
 +import operator
 +import types
 +import warnings
 +from compat import update_wrapper, set_types, threading
 +from sqlalchemy import exc
 +
 +def _unique_symbols(used, *bases):
 +    used = set(used)
 +    for base in bases:
 +        pool = itertools.chain((base,),
 +                               itertools.imap(lambda i: base + str(i),
 +                                              xrange(1000)))
 +        for sym in pool:
 +            if sym not in used:
 +                used.add(sym)
 +                yield sym
 +                break
 +        else:
 +            raise NameError("exhausted namespace for symbol base %s" % base)
 +
 +def decorator(target):
 +    """A signature-matching decorator factory."""
 +
 +    def decorate(fn):
 +        if not inspect.isfunction(fn):
 +            raise Exception("not a decoratable function")
 +        spec = inspect.getargspec(fn)
 +        names = tuple(spec[0]) + spec[1:3] + (fn.func_name,)
 +        targ_name, fn_name = _unique_symbols(names, 'target', 'fn')
 +
 +        metadata = dict(target=targ_name, fn=fn_name)
 +        metadata.update(format_argspec_plus(spec, grouped=False))
 +
 +        code = 'lambda %(args)s: %(target)s(%(fn)s, %(apply_kw)s)' % (
 +                metadata)
 +        decorated = eval(code, {targ_name:target, fn_name:fn})
 +        decorated.func_defaults = getattr(fn, 'im_func', fn).func_defaults
 +        return update_wrapper(decorated, fn)
 +    return update_wrapper(decorate, target)
 +
 +
 +
 +def get_cls_kwargs(cls):
 +    """Return the full set of inherited kwargs for the given `cls`.
 +
 +    Probes a class's __init__ method, collecting all named arguments.  If the
 +    __init__ defines a \**kwargs catch-all, then the constructor is presumed to
 +    pass along unrecognized keywords to it's base classes, and the collection
 +    process is repeated recursively on each of the bases.
 +    
 +    """
 +
 +    for c in cls.__mro__:
 +        if '__init__' in c.__dict__:
 +            stack = set([c])
 +            break
 +    else:
 +        return []
 +
 +    args = set()
 +    while stack:
 +        class_ = stack.pop()
 +        ctr = class_.__dict__.get('__init__', False)
 +        if not ctr or not isinstance(ctr, types.FunctionType):
 +            stack.update(class_.__bases__)
 +            continue
 +        names, _, has_kw, _ = inspect.getargspec(ctr)
 +        args.update(names)
 +        if has_kw:
 +            stack.update(class_.__bases__)
 +    args.discard('self')
 +    return args
 +
 +def get_func_kwargs(func):
 +    """Return the full set of legal kwargs for the given `func`."""
 +    return inspect.getargspec(func)[0]
 +
 +def format_argspec_plus(fn, grouped=True):
 +    """Returns a dictionary of formatted, introspected function arguments.
 +
 +    A enhanced variant of inspect.formatargspec to support code generation.
 +
 +    fn
 +       An inspectable callable or tuple of inspect getargspec() results.
 +    grouped
 +      Defaults to True; include (parens, around, argument) lists
 +
 +    Returns:
 +
 +    args
 +      Full inspect.formatargspec for fn
 +    self_arg
 +      The name of the first positional argument, varargs[0], or None
 +      if the function defines no positional arguments.
 +    apply_pos
 +      args, re-written in calling rather than receiving syntax.  Arguments are
 +      passed positionally.
 +    apply_kw
 +      Like apply_pos, except keyword-ish args are passed as keywords.
 +
 +    Example::
 +
 +      >>> format_argspec_plus(lambda self, a, b, c=3, **d: 123)
 +      {'args': '(self, a, b, c=3, **d)',
 +       'self_arg': 'self',
 +       'apply_kw': '(self, a, b, c=c, **d)',
 +       'apply_pos': '(self, a, b, c, **d)'}
 +
 +    """
 +    spec = callable(fn) and inspect.getargspec(fn) or fn
 +    args = inspect.formatargspec(*spec)
 +    if spec[0]:
 +        self_arg = spec[0][0]
 +    elif spec[1]:
 +        self_arg = '%s[0]' % spec[1]
 +    else:
 +        self_arg = None
 +    apply_pos = inspect.formatargspec(spec[0], spec[1], spec[2])
 +    defaulted_vals = spec[3] is not None and spec[0][0-len(spec[3]):] or ()
 +    apply_kw = inspect.formatargspec(spec[0], spec[1], spec[2], defaulted_vals,
 +                                     formatvalue=lambda x: '=' + x)
 +    if grouped:
 +        return dict(args=args, self_arg=self_arg,
 +                    apply_pos=apply_pos, apply_kw=apply_kw)
 +    else:
 +        return dict(args=args[1:-1], self_arg=self_arg,
 +                    apply_pos=apply_pos[1:-1], apply_kw=apply_kw[1:-1])
 +
 +def format_argspec_init(method, grouped=True):
 +    """format_argspec_plus with considerations for typical __init__ methods
 +
 +    Wraps format_argspec_plus with error handling strategies for typical
 +    __init__ cases::
 +
 +      object.__init__ -> (self)
 +      other unreflectable (usually C) -> (self, *args, **kwargs)
 +
 +    """
 +    try:
 +        return format_argspec_plus(method, grouped=grouped)
 +    except TypeError:
 +        self_arg = 'self'
 +        if method is object.__init__:
 +            args = grouped and '(self)' or 'self'
 +        else:
 +            args = (grouped and '(self, *args, **kwargs)'
 +                            or 'self, *args, **kwargs')
 +        return dict(self_arg='self', args=args, apply_pos=args, apply_kw=args)
 +
 +def getargspec_init(method):
 +    """inspect.getargspec with considerations for typical __init__ methods
 +
 +    Wraps inspect.getargspec with error handling for typical __init__ cases::
 +
 +      object.__init__ -> (self)
 +      other unreflectable (usually C) -> (self, *args, **kwargs)
 +
 +    """
 +    try:
 +        return inspect.getargspec(method)
 +    except TypeError:
 +        if method is object.__init__:
 +            return (['self'], None, None, None)
 +        else:
 +            return (['self'], 'args', 'kwargs', None)
 +
 +    
 +def unbound_method_to_callable(func_or_cls):
 +    """Adjust the incoming callable such that a 'self' argument is not required."""
 +
 +    if isinstance(func_or_cls, types.MethodType) and not func_or_cls.im_self:
 +        return func_or_cls.im_func
 +    else:
 +        return func_or_cls
 +
 +class portable_instancemethod(object):
 +    """Turn an instancemethod into a (parent, name) pair
 +    to produce a serializable callable.
 +    
 +    """
 +    def __init__(self, meth):
 +        self.target = meth.im_self
 +        self.name = meth.__name__
 +
 +    def __call__(self, *arg, **kw):
 +        return getattr(self.target, self.name)(*arg, **kw)
 +        
 +def class_hierarchy(cls):
 +    """Return an unordered sequence of all classes related to cls.
 +
 +    Traverses diamond hierarchies.
 +
 +    Fibs slightly: subclasses of builtin types are not returned.  Thus
 +    class_hierarchy(class A(object)) returns (A, object), not A plus every
 +    class systemwide that derives from object.
 +
 +    Old-style classes are discarded and hierarchies rooted on them
 +    will not be descended.
 +
 +    """
 +    # Py2K
 +    if isinstance(cls, types.ClassType):
 +        return list()
 +    # end Py2K
 +    hier = set([cls])
 +    process = list(cls.__mro__)
 +    while process:
 +        c = process.pop()
 +        # Py2K
 +        if isinstance(c, types.ClassType):
 +            continue
 +        for b in (_ for _ in c.__bases__
 +                  if _ not in hier and not isinstance(_, types.ClassType)):
 +        # end Py2K
 +        # Py3K
 +        #for b in (_ for _ in c.__bases__
 +        #          if _ not in hier):
 +            process.append(b)
 +            hier.add(b)
 +        # Py3K
 +        #if c.__module__ == 'builtins' or not hasattr(c, '__subclasses__'):
 +        #    continue
 +        # Py2K
 +        if c.__module__ == '__builtin__' or not hasattr(c, '__subclasses__'):
 +            continue
 +        # end Py2K
 +        for s in [_ for _ in c.__subclasses__() if _ not in hier]:
 +            process.append(s)
 +            hier.add(s)
 +    return list(hier)
 +
 +def iterate_attributes(cls):
 +    """iterate all the keys and attributes associated 
 +       with a class, without using getattr().
 +
 +       Does not use getattr() so that class-sensitive 
 +       descriptors (i.e. property.__get__()) are not called.
 +
 +    """
 +    keys = dir(cls)
 +    for key in keys:
 +        for c in cls.__mro__:
 +            if key in c.__dict__:
 +                yield (key, c.__dict__[key])
 +                break
 +
 +def monkeypatch_proxied_specials(into_cls, from_cls, skip=None, only=None,
 +                                 name='self.proxy', from_instance=None):
 +    """Automates delegation of __specials__ for a proxying type."""
 +
 +    if only:
 +        dunders = only
 +    else:
 +        if skip is None:
 +            skip = ('__slots__', '__del__', '__getattribute__',
 +                    '__metaclass__', '__getstate__', '__setstate__')
 +        dunders = [m for m in dir(from_cls)
 +                   if (m.startswith('__') and m.endswith('__') and
 +                       not hasattr(into_cls, m) and m not in skip)]
 +    for method in dunders:
 +        try:
 +            fn = getattr(from_cls, method)
 +            if not hasattr(fn, '__call__'):
 +                continue
 +            fn = getattr(fn, 'im_func', fn)
 +        except AttributeError:
 +            continue
 +        try:
 +            spec = inspect.getargspec(fn)
 +            fn_args = inspect.formatargspec(spec[0])
 +            d_args = inspect.formatargspec(spec[0][1:])
 +        except TypeError:
 +            fn_args = '(self, *args, **kw)'
 +            d_args = '(*args, **kw)'
 +
 +        py = ("def %(method)s%(fn_args)s: "
 +              "return %(name)s.%(method)s%(d_args)s" % locals())
 +
 +        env = from_instance is not None and {name: from_instance} or {}
 +        exec py in env
 +        try:
 +            env[method].func_defaults = fn.func_defaults
 +        except AttributeError:
 +            pass
 +        setattr(into_cls, method, env[method])
 +
 +def as_interface(obj, cls=None, methods=None, required=None):
 +    """Ensure basic interface compliance for an instance or dict of callables.
 +
 +    Checks that ``obj`` implements public methods of ``cls`` or has members
 +    listed in ``methods``. If ``required`` is not supplied, implementing at
 +    least one interface method is sufficient. Methods present on ``obj`` that
 +    are not in the interface are ignored.
 +
 +    If ``obj`` is a dict and ``dict`` does not meet the interface
 +    requirements, the keys of the dictionary are inspected. Keys present in
 +    ``obj`` that are not in the interface will raise TypeErrors.
 +
 +    Raises TypeError if ``obj`` does not meet the interface criteria.
 +
 +    In all passing cases, an object with callable members is returned.  In the
 +    simple case, ``obj`` is returned as-is; if dict processing kicks in then
 +    an anonymous class is returned.
 +
 +    obj
 +      A type, instance, or dictionary of callables.
 +    cls
 +      Optional, a type.  All public methods of cls are considered the
 +      interface.  An ``obj`` instance of cls will always pass, ignoring
 +      ``required``..
 +    methods
 +      Optional, a sequence of method names to consider as the interface.
 +    required
 +      Optional, a sequence of mandatory implementations. If omitted, an
 +      ``obj`` that provides at least one interface method is considered
 +      sufficient.  As a convenience, required may be a type, in which case
 +      all public methods of the type are required.
 +
 +    """
 +    if not cls and not methods:
 +        raise TypeError('a class or collection of method names are required')
 +
 +    if isinstance(cls, type) and isinstance(obj, cls):
 +        return obj
 +
 +    interface = set(methods or [m for m in dir(cls) if not m.startswith('_')])
 +    implemented = set(dir(obj))
 +
 +    complies = operator.ge
 +    if isinstance(required, type):
 +        required = interface
 +    elif not required:
 +        required = set()
 +        complies = operator.gt
 +    else:
 +        required = set(required)
 +
 +    if complies(implemented.intersection(interface), required):
 +        return obj
 +
 +    # No dict duck typing here.
 +    if not type(obj) is dict:
 +        qualifier = complies is operator.gt and 'any of' or 'all of'
 +        raise TypeError("%r does not implement %s: %s" % (
 +            obj, qualifier, ', '.join(interface)))
 +
 +    class AnonymousInterface(object):
 +        """A callable-holding shell."""
 +
 +    if cls:
 +        AnonymousInterface.__name__ = 'Anonymous' + cls.__name__
 +    found = set()
 +
 +    for method, impl in dictlike_iteritems(obj):
 +        if method not in interface:
 +            raise TypeError("%r: unknown in this interface" % method)
 +        if not callable(impl):
 +            raise TypeError("%r=%r is not callable" % (method, impl))
 +        setattr(AnonymousInterface, method, staticmethod(impl))
 +        found.add(method)
 +
 +    if complies(found, required):
 +        return AnonymousInterface
 +
 +    raise TypeError("dictionary does not contain required keys %s" %
 +                    ', '.join(required - found))
 +
 +
 +class memoized_property(object):
 +    """A read-only @property that is only evaluated once."""
 +    def __init__(self, fget, doc=None):
 +        self.fget = fget
 +        self.__doc__ = doc or fget.__doc__
 +        self.__name__ = fget.__name__
 +
 +    def __get__(self, obj, cls):
 +        if obj is None:
 +            return self
 +        obj.__dict__[self.__name__] = result = self.fget(obj)
 +        return result
 +
 +
 +class memoized_instancemethod(object):
 +    """Decorate a method memoize its return value.
 +
 +    Best applied to no-arg methods: memoization is not sensitive to
 +    argument values, and will always return the same value even when
 +    called with different arguments.
 +
 +    """
 +    def __init__(self, fget, doc=None):
 +        self.fget = fget
 +        self.__doc__ = doc or fget.__doc__
 +        self.__name__ = fget.__name__
 +
 +    def __get__(self, obj, cls):
 +        if obj is None:
 +            return self
 +        def oneshot(*args, **kw):
 +            result = self.fget(obj, *args, **kw)
 +            memo = lambda *a, **kw: result
 +            memo.__name__ = self.__name__
 +            memo.__doc__ = self.__doc__
 +            obj.__dict__[self.__name__] = memo
 +            return result
 +        oneshot.__name__ = self.__name__
 +        oneshot.__doc__ = self.__doc__
 +        return oneshot
 +
 +def reset_memoized(instance, name):
 +    instance.__dict__.pop(name, None)
 +
 +
 +class group_expirable_memoized_property(object):
 +    """A family of @memoized_properties that can be expired in tandem."""
 +
 +    def __init__(self):
 +        self.attributes = []
 +
 +    def expire_instance(self, instance):
 +        """Expire all memoized properties for *instance*."""
 +        stash = instance.__dict__
 +        for attribute in self.attributes:
 +            stash.pop(attribute, None)
 +
 +    def __call__(self, fn):
 +        self.attributes.append(fn.__name__)
 +        return memoized_property(fn)
 +
 +class importlater(object):
 +    """Deferred import object.
 +    
 +    e.g.::
 +    
 +        somesubmod = importlater("mypackage.somemodule", "somesubmod")
 +        
 +    is equivalent to::
 +    
 +        from mypackage.somemodule import somesubmod
 +        
 +    except evaluted upon attribute access to "somesubmod".
 +    
 +    """
 +    def __init__(self, path, addtl=None):
 +        self._il_path = path
 +        self._il_addtl = addtl
 +    
 +    @memoized_property
 +    def module(self):
-                 raise AttributeError(
 +        if self._il_addtl:
++            m = __import__(self._il_path, globals(), locals(), 
++                                [self._il_addtl])
 +            try:
 +                return getattr(m, self._il_addtl)
 +            except AttributeError:
++                raise ImportError(
 +                        "Module %s has no attribute '%s'" % 
 +                        (self._il_path, self._il_addtl)
 +                    )
 +        else:
++            m = __import__(self._il_path)
++            for token in self._il_path.split(".")[1:]:
++                m = getattr(m, token)
 +            return m
 +        
 +    def __getattr__(self, key):
 +        try:
 +            attr = getattr(self.module, key)
 +        except AttributeError:
 +            raise AttributeError(
 +                        "Module %s has no attribute '%s'" % 
 +                        (self._il_path, key)
 +                    )
 +        self.__dict__[key] = attr
 +        return attr
 +
 +# from paste.deploy.converters
 +def asbool(obj):
 +    if isinstance(obj, (str, unicode)):
 +        obj = obj.strip().lower()
 +        if obj in ['true', 'yes', 'on', 'y', 't', '1']:
 +            return True
 +        elif obj in ['false', 'no', 'off', 'n', 'f', '0']:
 +            return False
 +        else:
 +            raise ValueError("String is not true/false: %r" % obj)
 +    return bool(obj)
 +
 +def bool_or_str(*text):
 +    """Return a callable that will evaulate a string as 
 +    boolean, or one of a set of "alternate" string values.
 +    
 +    """
 +    def bool_or_value(obj):
 +        if obj in text:
 +            return obj
 +        else:
 +            return asbool(obj)
 +    return bool_or_value
 +    
 +def coerce_kw_type(kw, key, type_, flexi_bool=True):
 +    """If 'key' is present in dict 'kw', coerce its value to type 'type\_' if
 +    necessary.  If 'flexi_bool' is True, the string '0' is considered false
 +    when coercing to boolean.
 +    """
 +
 +    if key in kw and type(kw[key]) is not type_ and kw[key] is not None:
 +        if type_ is bool and flexi_bool:
 +            kw[key] = asbool(kw[key])
 +        else:
 +            kw[key] = type_(kw[key])
 +
 +def duck_type_collection(specimen, default=None):
 +    """Given an instance or class, guess if it is or is acting as one of
 +    the basic collection types: list, set and dict.  If the __emulates__
 +    property is present, return that preferentially.
 +    """
 +
 +    if hasattr(specimen, '__emulates__'):
 +        # canonicalize set vs sets.Set to a standard: the builtin set
 +        if (specimen.__emulates__ is not None and
 +            issubclass(specimen.__emulates__, set_types)):
 +            return set
 +        else:
 +            return specimen.__emulates__
 +
 +    isa = isinstance(specimen, type) and issubclass or isinstance
 +    if isa(specimen, list):
 +        return list
 +    elif isa(specimen, set_types):
 +        return set
 +    elif isa(specimen, dict):
 +        return dict
 +
 +    if hasattr(specimen, 'append'):
 +        return list
 +    elif hasattr(specimen, 'add'):
 +        return set
 +    elif hasattr(specimen, 'set'):
 +        return dict
 +    else:
 +        return default
 +
 +def assert_arg_type(arg, argtype, name):
 +    if isinstance(arg, argtype):
 +        return arg
 +    else:
 +        if isinstance(argtype, tuple):
 +            raise exc.ArgumentError(
 +                            "Argument '%s' is expected to be one of type %s, got '%s'" % 
 +                            (name, ' or '.join("'%s'" % a for a in argtype), type(arg)))
 +        else:
 +            raise exc.ArgumentError(
 +                            "Argument '%s' is expected to be of type '%s', got '%s'" % 
 +                            (name, argtype, type(arg)))
 +
 +
 +def dictlike_iteritems(dictlike):
 +    """Return a (key, value) iterator for almost any dict-like object."""
 +
 +    # Py3K
 +    #if hasattr(dictlike, 'items'):
 +    #    return dictlike.items()
 +    # Py2K
 +    if hasattr(dictlike, 'iteritems'):
 +        return dictlike.iteritems()
 +    elif hasattr(dictlike, 'items'):
 +        return iter(dictlike.items())
 +    # end Py2K
 +
 +    getter = getattr(dictlike, '__getitem__', getattr(dictlike, 'get', None))
 +    if getter is None:
 +        raise TypeError(
 +            "Object '%r' is not dict-like" % dictlike)
 +
 +    if hasattr(dictlike, 'iterkeys'):
 +        def iterator():
 +            for key in dictlike.iterkeys():
 +                yield key, getter(key)
 +        return iterator()
 +    elif hasattr(dictlike, 'keys'):
 +        return iter((key, getter(key)) for key in dictlike.keys())
 +    else:
 +        raise TypeError(
 +            "Object '%r' is not dict-like" % dictlike)
 +
 +
 +class classproperty(property):
 +    """A decorator that behaves like @property except that operates
 +    on classes rather than instances.
 +
 +    The decorator is currently special when using the declarative
 +    module, but note that the 
 +    :class:`~.sqlalchemy.ext.declarative.declared_attr`
 +    decorator should be used for this purpose with declarative.
 +    
 +    """
 +    
 +    def __init__(self, fget, *arg, **kw):
 +        super(classproperty, self).__init__(fget, *arg, **kw)
 +        self.__doc__ = fget.__doc__
 +        
 +    def __get__(desc, self, cls):
 +        return desc.fget(cls)
 +
 +
 +class _symbol(object):
 +    def __init__(self, name):
 +        """Construct a new named symbol."""
 +        assert isinstance(name, str)
 +        self.name = name
 +    def __reduce__(self):
 +        return symbol, (self.name,)
 +    def __repr__(self):
 +        return "<symbol '%s>" % self.name
 +_symbol.__name__ = 'symbol'
 +
 +
 +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.
 +
 +    Repeated calls of symbol('name') will all return the same instance.
 +
 +    """
 +    symbols = {}
 +    _lock = threading.Lock()
 +
 +    def __new__(cls, name):
 +        cls._lock.acquire()
 +        try:
 +            sym = cls.symbols.get(name)
 +            if sym is None:
 +                cls.symbols[name] = sym = _symbol(name)
 +            return sym
 +        finally:
 +            symbol._lock.release()
 +
 +
 +_creation_order = 1
 +def set_creation_order(instance):
 +    """Assign a '_creation_order' sequence to the given instance.
 +
 +    This allows multiple instances to be sorted in order of creation
 +    (typically within a single thread; the counter is not particularly
 +    threadsafe).
 +
 +    """
 +    global _creation_order
 +    instance._creation_order = _creation_order
 +    _creation_order +=1
 +
 +def warn_exception(func, *args, **kwargs):
 +    """executes the given function, catches all exceptions and converts to a warning."""
 +    try:
 +        return func(*args, **kwargs)
 +    except:
 +        warn("%s('%s') ignored" % sys.exc_info()[0:2])
 +
 +
 +def warn(msg, stacklevel=3):
 +    """Issue a warning.
 +    
 +    If msg is a string, :class:`.exc.SAWarning` is used as 
 +    the category.
 +    
 +    .. note:: This function is swapped out when the test suite
 +       runs, with a compatible version that uses 
 +       warnings.warn_explicit, so that the warnings registry can
 +       be controlled.
 +       
 +    """
 +    if isinstance(msg, basestring):
 +        warnings.warn(msg, exc.SAWarning, stacklevel=stacklevel)
 +    else:
 +        warnings.warn(msg, stacklevel=stacklevel)
 +
 +NoneType = type(None)
index f6de1fa2f5c2f02f8a4f5995c1e403b80ae7bdf8,43a4a3eb55ab01e877e1eb8f3c4758d1a79cb0f9..53d7ff2e4a15679ba961f4c04e5983f326a3f4a4
@@@ -5,13 -5,16 +5,16 @@@ from sqlalchemy.orm.mapper import _mapp
  from sqlalchemy.orm.session import _sessions
  from sqlalchemy.util import jython
  import operator
 -from sqlalchemy.test import testing, engines
 +from test.lib import testing, engines
  from sqlalchemy import MetaData, Integer, String, ForeignKey, \
      PickleType, create_engine, Unicode
 -from sqlalchemy.test.schema import Table, Column
 +from test.lib.schema import Table, Column
  import sqlalchemy as sa
  from sqlalchemy.sql import column
 -from sqlalchemy.test.util import gc_collect
+ from sqlalchemy.processors import to_decimal_processor_factory, \
+     to_unicode_processor_factory
 +from test.lib.util import gc_collect
+ from decimal import Decimal as _python_Decimal
  import gc
  import weakref
  from test.orm import _base
Simple merge
Simple merge
index f0ac6cbed12b5396a3bb10c88051ca3b5d3d25e4,0767d6c7aa4ad67e29f0128abb4504b9e5dc70db..66f7030684143bddbdb3cd5793afe9479ce1e9c7
@@@ -1,7 -1,8 +1,8 @@@
  from sqlalchemy.ext import sqlsoup
- from test.lib.testing import TestBase, eq_, assert_raises
 -from sqlalchemy.test.testing import TestBase, eq_, assert_raises, \
++from test.lib.testing import TestBase, eq_, assert_raises, \
+     assert_raises_message
  from sqlalchemy import create_engine, or_, desc, select, func, exc, \
-     Table, util
+     Table, util, Column, Integer
  from sqlalchemy.orm import scoped_session, sessionmaker
  import datetime
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge