]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- move topological, queue into util
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 5 Dec 2010 17:51:24 +0000 (12:51 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 5 Dec 2010 17:51:24 +0000 (12:51 -0500)
- move function_named into test.lib.util
- use @decorator for all decorators in test/

22 files changed:
lib/sqlalchemy/orm/unitofwork.py
lib/sqlalchemy/pool.py
lib/sqlalchemy/sql/util.py
lib/sqlalchemy/util/__init__.py
lib/sqlalchemy/util/compat.py
lib/sqlalchemy/util/langhelpers.py
lib/sqlalchemy/util/queue.py [moved from lib/sqlalchemy/queue.py with 100% similarity]
lib/sqlalchemy/util/topological.py [moved from lib/sqlalchemy/topological.py with 100% similarity]
test/base/test_dependency.py
test/lib/engines.py
test/lib/profiling.py
test/lib/testing.py
test/lib/util.py
test/orm/_base.py
test/orm/inheritance/test_abc_polymorphic.py
test/orm/inheritance/test_basic.py
test/orm/inheritance/test_magazine.py
test/orm/inheritance/test_polymorph.py
test/orm/inheritance/test_polymorph2.py
test/orm/test_attributes.py
test/orm/test_dynamic.py
test/orm/test_instrumentation.py

index db20acb90bb14582d4308ddf2942d067ecea2725..7ee633f3e56eb8763cdc402a3c030894beac72fd 100644 (file)
@@ -12,7 +12,8 @@ organizes them in order of dependency, and executes.
 
 """
 
-from sqlalchemy import util, topological
+from sqlalchemy import util
+from sqlalchemy.util import topological
 from sqlalchemy.orm import attributes, interfaces
 from sqlalchemy.orm import util as mapperutil
 from sqlalchemy.orm.util import _state_mapper
index 58b3a39c1b51cccc61861f8a21b69e81d2bd3850..4ae6ec022f0bb30ce56c572039f87d62a9f20788 100644 (file)
@@ -20,7 +20,7 @@ SQLAlchemy connection pool.
 import weakref, time, threading
 
 from sqlalchemy import exc, log, event, events, interfaces, util
-from sqlalchemy import queue as sqla_queue
+from sqlalchemy.util import queue as sqla_queue
 from sqlalchemy.util import threading, pickle, memoized_property
 
 proxies = {}
index 638549e12c2abbac17e80c4249e9999cf00df1e1..757de37c40b0b02f4d9217a127aeedbae9270534 100644 (file)
@@ -1,4 +1,5 @@
-from sqlalchemy import exc, schema, topological, util, sql, types as sqltypes
+from sqlalchemy import exc, schema, util, sql, types as sqltypes
+from sqlalchemy.util import topological
 from sqlalchemy.sql import expression, operators, visitors
 from itertools import chain
 
index 4aaf41205c9090d82abd00d71e8b68767b1d3e76..aa150874fc085938058ac969b3604337ba488f5b 100644 (file)
@@ -20,7 +20,7 @@ from langhelpers import iterate_attributes, class_hierarchy, \
     portable_instancemethod, unbound_method_to_callable, \
     getargspec_init, format_argspec_init, format_argspec_plus, \
     get_func_kwargs, get_cls_kwargs, decorator, as_interface, \
-    function_named, memoized_property, memoized_instancemethod, \
+    memoized_property, memoized_instancemethod, \
     reset_memoized, group_expirable_memoized_property, importlater, \
     monkeypatch_proxied_specials, asbool, bool_or_str, coerce_kw_type,\
     duck_type_collection, assert_arg_type, symbol, dictlike_iteritems,\
@@ -29,4 +29,3 @@ from langhelpers import iterate_attributes, class_hierarchy, \
 from deprecations import warn_deprecated, warn_pending_deprecation, \
     deprecated, pending_deprecation
 
-
index 5f00102c114f22748d3413173fcaa836995b935c..090f45212e6ca1a3e880af2c8b18d87a75feaba3 100644 (file)
@@ -1,4 +1,5 @@
 """Handle Python version/platform incompatibilities."""
+
 import sys
 
 # Py2K
index 68d9709f82fec9cdcb9838ff8c10caeebff33f03..aac22ba309f48987acc4561fd6f5603f1ab54ba0 100644 (file)
@@ -371,20 +371,6 @@ def as_interface(obj, cls=None, methods=None, required=None):
     raise TypeError("dictionary does not contain required keys %s" %
                     ', '.join(required - found))
 
-def function_named(fn, name):
-    """Return a function with a given __name__.
-
-    Will assign to __name__ and return the original function if possible on
-    the Python implementation, otherwise a new function will be constructed.
-
-    """
-    try:
-        fn.__name__ = name
-    except TypeError:
-        fn = types.FunctionType(fn.func_code, fn.func_globals, name,
-                          fn.func_defaults, fn.func_closure)
-    return fn
-
 
 class memoized_property(object):
     """A read-only @property that is only evaluated once."""
index 6d4662be564210218bd53c85ef1e67acc5a78b37..1853b4d52c6fa8d432179b1384507ae302c26f3e 100644 (file)
@@ -1,10 +1,9 @@
-import sqlalchemy.topological as topological
+from sqlalchemy.util import topological
 from test.lib import TestBase
 from test.lib.testing import assert_raises, eq_
 from test.lib.util import conforms_partial_ordering
 from sqlalchemy import exc, util
 
-
 class DependencySortTest(TestBase):
 
     def assert_sort(self, tuples, allitems=None):
index 0f3ccf288827b520f3cdbeaef41d1ef802bce0a8..a57795f157faa3feaa05ec03084cde258d6bf6f0 100644 (file)
@@ -1,7 +1,8 @@
 import sys, types, weakref
 from collections import deque
 from test.bootstrap import config
-from sqlalchemy.util import function_named, callable
+from test.lib.util import decorator
+from sqlalchemy.util import callable
 from sqlalchemy import event
 import re
 import warnings
@@ -44,42 +45,38 @@ testing_reaper = ConnectionKiller()
 def drop_all_tables(metadata):
     testing_reaper.close_all()
     metadata.drop_all()
-    
-def assert_conns_closed(fn):
-    def decorated(*args, **kw):
-        try:
-            fn(*args, **kw)
-        finally:
-            testing_reaper.assert_all_closed()
-    return function_named(decorated, fn.__name__)
-
-def rollback_open_connections(fn):
+
+@decorator
+def assert_conns_closed(fn, *args, **kw):
+    try:
+        fn(*args, **kw)
+    finally:
+        testing_reaper.assert_all_closed()
+
+@decorator
+def rollback_open_connections(fn, *args, **kw):
     """Decorator that rolls back all open connections after fn execution."""
 
-    def decorated(*args, **kw):
-        try:
-            fn(*args, **kw)
-        finally:
-            testing_reaper.rollback_all()
-    return function_named(decorated, fn.__name__)
+    try:
+        fn(*args, **kw)
+    finally:
+        testing_reaper.rollback_all()
 
-def close_first(fn):
+@decorator
+def close_first(fn, *args, **kw):
     """Decorator that closes all connections before fn execution."""
-    def decorated(*args, **kw):
-        testing_reaper.close_all()
-        fn(*args, **kw)
-    return function_named(decorated, fn.__name__)
+    
+    testing_reaper.close_all()
+    fn(*args, **kw)
     
     
-def close_open_connections(fn):
+@decorator
+def close_open_connections(fn, *args, **kw):
     """Decorator that closes all connections after fn execution."""
-
-    def decorated(*args, **kw):
-        try:
-            fn(*args, **kw)
-        finally:
-            testing_reaper.close_all()
-    return function_named(decorated, fn.__name__)
+    try:
+        fn(*args, **kw)
+    finally:
+        testing_reaper.close_all()
 
 def all_dialects(exclude=None):
     import sqlalchemy.databases as d
index f6c21bde85cfe075195a0558088f00dd37d58465..eeb3901cb3fa6db81442c67826c83d74cea62407 100644 (file)
@@ -6,7 +6,7 @@ in a more fine-grained way than nose's profiling plugin.
 """
 
 import os, sys
-from test.lib.util import function_named, gc_collect
+from test.lib.util import gc_collect, decorator
 from nose import SkipTest
 
 __all__ = 'profiled', 'function_call_count', 'conditional_call_count'
@@ -38,34 +38,33 @@ def profiled(target=None, **target_opts):
     all_targets.add(target)
 
     filename = "%s.prof" % target
-
-    def decorator(fn):
-        def profiled(*args, **kw):
-            if (target not in profile_config['targets'] and
-                not target_opts.get('always', None)):
-                return fn(*args, **kw)
-
-            elapsed, load_stats, result = _profile(
-                filename, fn, *args, **kw)
-
-            report = target_opts.get('report', profile_config['report'])
-            if report:
-                sort_ = target_opts.get('sort', profile_config['sort'])
-                limit = target_opts.get('limit', profile_config['limit'])
-                print "Profile report for target '%s' (%s)" % (
-                    target, filename)
-
-                stats = load_stats()
-                stats.sort_stats(*sort_)
-                if limit:
-                    stats.print_stats(limit)
-                else:
-                    stats.print_stats()
-                #stats.print_callers()
-            os.unlink(filename)
-            return result
-        return function_named(profiled, fn.__name__)
-    return decorator
+    
+    @decorator
+    def decorate(fn, *args, **kw):
+        if (target not in profile_config['targets'] and
+            not target_opts.get('always', None)):
+            return fn(*args, **kw)
+
+        elapsed, load_stats, result = _profile(
+            filename, fn, *args, **kw)
+
+        report = target_opts.get('report', profile_config['report'])
+        if report:
+            sort_ = target_opts.get('sort', profile_config['sort'])
+            limit = target_opts.get('limit', profile_config['limit'])
+            print "Profile report for target '%s' (%s)" % (
+                target, filename)
+
+            stats = load_stats()
+            stats.sort_stats(*sort_)
+            if limit:
+                stats.print_stats(limit)
+            else:
+                stats.print_stats()
+            #stats.print_callers()
+        os.unlink(filename)
+        return result
+    return decorate
 
 def function_call_count(count=None, versions={}, variance=0.05):
     """Assert a target for a test case's function call count.
@@ -109,35 +108,34 @@ def function_call_count(count=None, versions={}, variance=0.05):
 
     if count is None:
         return lambda fn: fn
+    
+    @decorator
+    def decorate(fn, *args, **kw):
+        try:
+            filename = "%s.prof" % fn.__name__
 
-    def decorator(fn):
-        def counted(*args, **kw):
-            try:
-                filename = "%s.prof" % fn.__name__
+            elapsed, stat_loader, result = _profile(
+                filename, fn, *args, **kw)
 
-                elapsed, stat_loader, result = _profile(
-                    filename, fn, *args, **kw)
+            stats = stat_loader()
+            calls = stats.total_calls
 
-                stats = stat_loader()
-                calls = stats.total_calls
+            stats.sort_stats('calls', 'cumulative')
+            stats.print_stats()
+            #stats.print_callers()
+            deviance = int(count * variance)
+            if (calls < (count - deviance) or
+                calls > (count + deviance)):
+                raise AssertionError(
+                    "Function call count %s not within %s%% "
+                    "of expected %s. (Python version %s)" % (
+                    calls, (variance * 100), count, py_version))
 
-                stats.sort_stats('calls', 'cumulative')
-                stats.print_stats()
-                #stats.print_callers()
-                deviance = int(count * variance)
-                if (calls < (count - deviance) or
-                    calls > (count + deviance)):
-                    raise AssertionError(
-                        "Function call count %s not within %s%% "
-                        "of expected %s. (Python version %s)" % (
-                        calls, (variance * 100), count, py_version))
-
-                return result
-            finally:
-                if os.path.exists(filename):
-                    os.unlink(filename)
-        return function_named(counted, fn.__name__)
-    return decorator
+            return result
+        finally:
+            if os.path.exists(filename):
+                os.unlink(filename)
+    return decorate
 
 def conditional_call_count(discriminator, categories):
     """Apply a function call count conditionally at runtime.
@@ -153,17 +151,15 @@ def conditional_call_count(discriminator, categories):
     have a function count penalty not seen in the full suite, due to lazy
     initialization in the DB-API, SA, etc.
     """
-
-    def decorator(fn):
-        def at_runtime(*args, **kw):
-            criteria = categories.get(discriminator(), None)
-            if criteria is None:
-                return fn(*args, **kw)
-
-            rewrapped = function_call_count(*criteria)(fn)
-            return rewrapped(*args, **kw)
-        return function_named(at_runtime, fn.__name__)
-    return decorator
+    @decorator
+    def decorate(fn, *args, **kw):
+        criteria = categories.get(discriminator(), None)
+        if criteria is None:
+            return fn(*args, **kw)
+
+        rewrapped = function_call_count(*criteria)(fn)
+        return rewrapped(*args, **kw)
+    return decorate
 
 
 def _profile(filename, fn, *args, **kw):
index 8f4838d0a2ad8a4cc83580f33100c239b1334d5a..6a2c62959e4bca5478535c82221228839beca9e1 100644 (file)
@@ -10,7 +10,7 @@ from cStringIO import StringIO
 
 from test.bootstrap import config
 from test.lib import assertsql, util as testutil
-from sqlalchemy.util import function_named, py3k
+from sqlalchemy.util import py3k, decorator
 from engines import drop_all_tables
 
 from sqlalchemy import exc as sa_exc, util, types as sqltypes, schema, \
@@ -47,44 +47,39 @@ def fails_if(callable_, reason=None):
     docstring = getattr(callable_, '__doc__', None) or callable_.__name__
     description = docstring.split('\n')[0]
 
-    def decorate(fn):
-        fn_name = fn.__name__
-        def maybe(*args, **kw):
-            if not callable_():
-                return fn(*args, **kw)
+    @decorator
+    def decorate(fn, *args, **kw):
+        if not callable_():
+            return fn(*args, **kw)
+        else:
+            try:
+                fn(*args, **kw)
+            except Exception, ex:
+                print ("'%s' failed as expected (condition: %s): %s " % (
+                    fn.__name__, description, str(ex)))
+                return True
             else:
-                try:
-                    fn(*args, **kw)
-                except Exception, ex:
-                    print ("'%s' failed as expected (condition: %s): %s " % (
-                        fn_name, description, str(ex)))
-                    return True
-                else:
-                    raise AssertionError(
-                        "Unexpected success for '%s' (condition: %s)" %
-                        (fn_name, description))
-        return function_named(maybe, fn_name)
+                raise AssertionError(
+                    "Unexpected success for '%s' (condition: %s)" %
+                    (fn.__name__, description))
     return decorate
 
-
-def future(fn):
+@decorator
+def future(fn, *args, **kw):
     """Mark a test as expected to unconditionally fail.
 
     Takes no arguments, omit parens when using as a decorator.
     """
 
-    fn_name = fn.__name__
-    def decorated(*args, **kw):
-        try:
-            fn(*args, **kw)
-        except Exception, ex:
-            print ("Future test '%s' failed as expected: %s " % (
-                fn_name, str(ex)))
-            return True
-        else:
-            raise AssertionError(
-                "Unexpected success for future test '%s'" % fn_name)
-    return function_named(decorated, fn_name)
+    try:
+        fn(*args, **kw)
+    except Exception, ex:
+        print ("Future test '%s' failed as expected: %s " % (
+            fn.__name__, str(ex)))
+        return True
+    else:
+        raise AssertionError(
+            "Unexpected success for future test '%s'" % fn.__name__)
 
 def db_spec(*dbs):
     dialects = set([x for x in dbs if '+' not in x])
@@ -110,25 +105,23 @@ def fails_on(dbs, reason):
     """
 
     spec = db_spec(dbs)
-     
-    def decorate(fn):
-        fn_name = fn.__name__
-        def maybe(*args, **kw):
-            if not spec(config.db):
-                return fn(*args, **kw)
+    
+    @decorator
+    def decorate(fn, *args, **kw):
+        if not spec(config.db):
+            return fn(*args, **kw)
+        else:
+            try:
+                fn(*args, **kw)
+            except Exception, ex:
+                print ("'%s' failed as expected on DB implementation "
+                        "'%s+%s': %s" % (
+                    fn.__name__, config.db.name, config.db.driver, reason))
+                return True
             else:
-                try:
-                    fn(*args, **kw)
-                except Exception, ex:
-                    print ("'%s' failed as expected on DB implementation "
-                            "'%s+%s': %s" % (
-                        fn_name, config.db.name, config.db.driver, reason))
-                    return True
-                else:
-                    raise AssertionError(
-                         "Unexpected success for '%s' on DB implementation '%s+%s'" %
-                         (fn_name, config.db.name, config.db.driver))
-        return function_named(maybe, fn_name)
+                raise AssertionError(
+                     "Unexpected success for '%s' on DB implementation '%s+%s'" %
+                     (fn.__name__, config.db.name, config.db.driver))
     return decorate
 
 def fails_on_everything_except(*dbs):
@@ -140,24 +133,22 @@ def fails_on_everything_except(*dbs):
 
     spec = db_spec(*dbs)
     
-    def decorate(fn):
-        fn_name = fn.__name__
-        def maybe(*args, **kw):
-            if spec(config.db):
-                return fn(*args, **kw)
+    @decorator
+    def decorate(fn, *args, **kw):
+        if spec(config.db):
+            return fn(*args, **kw)
+        else:
+            try:
+                fn(*args, **kw)
+            except Exception, ex:
+                print ("'%s' failed as expected on DB implementation "
+                        "'%s+%s': %s" % (
+                    fn.__name__, config.db.name, config.db.driver, str(ex)))
+                return True
             else:
-                try:
-                    fn(*args, **kw)
-                except Exception, ex:
-                    print ("'%s' failed as expected on DB implementation "
-                            "'%s+%s': %s" % (
-                        fn_name, config.db.name, config.db.driver, str(ex)))
-                    return True
-                else:
-                    raise AssertionError(
-                      "Unexpected success for '%s' on DB implementation '%s+%s'" %
-                      (fn_name, config.db.name, config.db.driver))
-        return function_named(maybe, fn_name)
+                raise AssertionError(
+                  "Unexpected success for '%s' on DB implementation '%s+%s'" %
+                  (fn.__name__, config.db.name, config.db.driver))
     return decorate
 
 def crashes(db, reason):
@@ -169,19 +160,17 @@ def crashes(db, reason):
     """
     carp = _should_carp_about_exclusion(reason)
     spec = db_spec(db)
-    def decorate(fn):
-        fn_name = fn.__name__
-        def maybe(*args, **kw):
-            if spec(config.db):
-                msg = "'%s' unsupported on DB implementation '%s+%s': %s" % (
-                    fn_name, config.db.name, config.db.driver, reason)
-                print msg
-                if carp:
-                    print >> sys.stderr, msg
-                return True
-            else:
-                return fn(*args, **kw)
-        return function_named(maybe, fn_name)
+    @decorator
+    def decorate(fn, *args, **kw):
+        if spec(config.db):
+            msg = "'%s' unsupported on DB implementation '%s+%s': %s" % (
+                fn.__name__, config.db.name, config.db.driver, reason)
+            print msg
+            if carp:
+                print >> sys.stderr, msg
+            return True
+        else:
+            return fn(*args, **kw)
     return decorate
 
 def _block_unconditionally(db, reason):
@@ -194,37 +183,33 @@ def _block_unconditionally(db, reason):
     """
     carp = _should_carp_about_exclusion(reason)
     spec = db_spec(db)
-    def decorate(fn):
-        fn_name = fn.__name__
-        def maybe(*args, **kw):
-            if spec(config.db):
-                msg = "'%s' unsupported on DB implementation '%s+%s': %s" % (
-                    fn_name, config.db.name, config.db.driver, reason)
-                print msg
-                if carp:
-                    print >> sys.stderr, msg
-                return True
-            else:
-                return fn(*args, **kw)
-        return function_named(maybe, fn_name)
+    @decorator
+    def decorate(fn, *args, **kw):
+        if spec(config.db):
+            msg = "'%s' unsupported on DB implementation '%s+%s': %s" % (
+                fn.__name__, config.db.name, config.db.driver, reason)
+            print msg
+            if carp:
+                print >> sys.stderr, msg
+            return True
+        else:
+            return fn(*args, **kw)
     return decorate
 
 def only_on(dbs, reason):
     carp = _should_carp_about_exclusion(reason)
     spec = db_spec(*util.to_list(dbs))
-    def decorate(fn):
-        fn_name = fn.__name__
-        def maybe(*args, **kw):
-            if spec(config.db):
-                return fn(*args, **kw)
-            else:
-                msg = "'%s' unsupported on DB implementation '%s+%s': %s" % (
-                    fn_name, config.db.name, config.db.driver, reason)
-                print msg
-                if carp:
-                    print >> sys.stderr, msg
-                return True
-        return function_named(maybe, fn_name)
+    @decorator
+    def decorate(fn, *args, **kw):
+        if spec(config.db):
+            return fn(*args, **kw)
+        else:
+            msg = "'%s' unsupported on DB implementation '%s+%s': %s" % (
+                fn.__name__, config.db.name, config.db.driver, reason)
+            print msg
+            if carp:
+                print >> sys.stderr, msg
+            return True
     return decorate
     
 def exclude(db, op, spec, reason):
@@ -241,19 +226,17 @@ def exclude(db, op, spec, reason):
     """
     carp = _should_carp_about_exclusion(reason)
     
-    def decorate(fn):
-        fn_name = fn.__name__
-        def maybe(*args, **kw):
-            if _is_excluded(db, op, spec):
-                msg = "'%s' unsupported on DB %s version '%s': %s" % (
-                    fn_name, config.db.name, _server_version(), reason)
-                print msg
-                if carp:
-                    print >> sys.stderr, msg
-                return True
-            else:
-                return fn(*args, **kw)
-        return function_named(maybe, fn_name)
+    @decorator
+    def decorate(fn, *args, **kw):
+        if _is_excluded(db, op, spec):
+            msg = "'%s' unsupported on DB %s version '%s': %s" % (
+                fn.__name__, config.db.name, _server_version(), reason)
+            print msg
+            if carp:
+                print >> sys.stderr, msg
+            return True
+        else:
+            return fn(*args, **kw)
     return decorate
 
 def _should_carp_about_exclusion(reason):
@@ -312,19 +295,17 @@ def skip_if(predicate, reason=None):
     reason = reason or predicate.__name__
     carp = _should_carp_about_exclusion(reason)
     
-    def decorate(fn):
-        fn_name = fn.__name__
-        def maybe(*args, **kw):
-            if predicate():
-                msg = "'%s' skipped on DB %s version '%s': %s" % (
-                    fn_name, config.db.name, _server_version(), reason)
-                print msg
-                if carp:
-                    print >> sys.stderr, msg
-                return True
-            else:
-                return fn(*args, **kw)
-        return function_named(maybe, fn_name)
+    @decorator
+    def decorate(fn, *args, **kw):
+        if predicate():
+            msg = "'%s' skipped on DB %s version '%s': %s" % (
+                fn.__name__, config.db.name, _server_version(), reason)
+            print msg
+            if carp:
+                print >> sys.stderr, msg
+            return True
+        else:
+            return fn(*args, **kw)
     return decorate
 
 def emits_warning(*messages):
@@ -339,26 +320,26 @@ def emits_warning(*messages):
     # and may work on non-CPython if they keep to the spirit of
     # warnings.showwarning's docstring.
     # - update: jython looks ok, it uses cpython's module
-    def decorate(fn):
-        def safe(*args, **kw):
-            # todo: should probably be strict about this, too
-            filters = [dict(action='ignore',
-                            category=sa_exc.SAPendingDeprecationWarning)]
-            if not messages:
-                filters.append(dict(action='ignore',
-                                     category=sa_exc.SAWarning))
-            else:
-                filters.extend(dict(action='ignore',
-                                     message=message,
-                                     category=sa_exc.SAWarning)
-                                for message in messages)
-            for f in filters:
-                warnings.filterwarnings(**f)
-            try:
-                return fn(*args, **kw)
-            finally:
-                resetwarnings()
-        return function_named(safe, fn.__name__)
+    
+    @decorator
+    def decorate(fn, *args, **kw):
+        # todo: should probably be strict about this, too
+        filters = [dict(action='ignore',
+                        category=sa_exc.SAPendingDeprecationWarning)]
+        if not messages:
+            filters.append(dict(action='ignore',
+                                 category=sa_exc.SAWarning))
+        else:
+            filters.extend(dict(action='ignore',
+                                 message=message,
+                                 category=sa_exc.SAWarning)
+                            for message in messages)
+        for f in filters:
+            warnings.filterwarnings(**f)
+        try:
+            return fn(*args, **kw)
+        finally:
+            resetwarnings()
     return decorate
 
 def emits_warning_on(db, *warnings):
@@ -370,21 +351,20 @@ def emits_warning_on(db, *warnings):
     """
     spec = db_spec(db)
     
-    def decorate(fn):
-        def maybe(*args, **kw):
-            if isinstance(db, basestring):
-                if not spec(config.db):
-                    return fn(*args, **kw)
-                else:
-                    wrapped = emits_warning(*warnings)(fn)
-                    return wrapped(*args, **kw)
+    @decorator
+    def decorate(fn, *args, **kw):
+        if isinstance(db, basestring):
+            if not spec(config.db):
+                return fn(*args, **kw)
             else:
-                if not _is_excluded(*db):
-                    return fn(*args, **kw)
-                else:
-                    wrapped = emits_warning(*warnings)(fn)
-                    return wrapped(*args, **kw)
-        return function_named(maybe, fn.__name__)
+                wrapped = emits_warning(*warnings)(fn)
+                return wrapped(*args, **kw)
+        else:
+            if not _is_excluded(*db):
+                return fn(*args, **kw)
+            else:
+                wrapped = emits_warning(*warnings)(fn)
+                return wrapped(*args, **kw)
     return decorate
 
 def assert_warnings(fn, warnings):
@@ -411,32 +391,30 @@ def uses_deprecated(*messages):
     verbiage emitted by the sqlalchemy.util.deprecated decorator.
     """
 
-    
-    def decorate(fn):
-        def safe(*args, **kw):
-            # todo: should probably be strict about this, too
-            filters = [dict(action='ignore',
-                            category=sa_exc.SAPendingDeprecationWarning)]
-            if not messages:
-                filters.append(dict(action='ignore',
-                                    category=sa_exc.SADeprecationWarning))
-            else:
-                filters.extend(
-                    [dict(action='ignore',
-                          message=message,
-                          category=sa_exc.SADeprecationWarning)
-                     for message in
-                     [ (m.startswith('//') and
-                        ('Call to deprecated function ' + m[2:]) or m)
-                       for m in messages] ])
-
-            for f in filters:
-                warnings.filterwarnings(**f)
-            try:
-                return fn(*args, **kw)
-            finally:
-                resetwarnings()
-        return function_named(safe, fn.__name__)
+    @decorator
+    def decorate(fn, *args, **kw):
+        # todo: should probably be strict about this, too
+        filters = [dict(action='ignore',
+                        category=sa_exc.SAPendingDeprecationWarning)]
+        if not messages:
+            filters.append(dict(action='ignore',
+                                category=sa_exc.SADeprecationWarning))
+        else:
+            filters.extend(
+                [dict(action='ignore',
+                      message=message,
+                      category=sa_exc.SADeprecationWarning)
+                 for message in
+                 [ (m.startswith('//') and
+                    ('Call to deprecated function ' + m[2:]) or m)
+                   for m in messages] ])
+
+        for f in filters:
+            warnings.filterwarnings(**f)
+        try:
+            return fn(*args, **kw)
+        finally:
+            resetwarnings()
     return decorate
 
 def testing_warn(msg, stacklevel=3):
@@ -569,24 +547,24 @@ def fixture(table, columns, *rows):
                                     for column_values in rows])
     table.append_ddl_listener('after-create', onload)
 
-def provide_metadata(fn):
+@decorator
+def provide_metadata(fn, *args, **kw):
     """Provides a bound MetaData object for a single test, 
     drops it afterwards."""
-    def maybe(*args, **kw):
-        metadata = schema.MetaData(db)
-        context = dict(fn.func_globals)
-        context['metadata'] = metadata
-        # jython bug #1034
-        rebound = types.FunctionType(
-            fn.func_code, context, fn.func_name, fn.func_defaults,
-            fn.func_closure)
-        try:
-            return rebound(*args, **kw)
-        finally:
-            metadata.drop_all()
-    return function_named(maybe, fn.__name__)
-    
-def resolve_artifact_names(fn):
+    metadata = schema.MetaData(db)
+    context = dict(fn.func_globals)
+    context['metadata'] = metadata
+    # jython bug #1034
+    rebound = types.FunctionType(
+        fn.func_code, context, fn.func_name, fn.func_defaults,
+        fn.func_closure)
+    try:
+        return rebound(*args, **kw)
+    finally:
+        metadata.drop_all()
+
+@decorator
+def resolve_artifact_names(fn, *args, **kw):
     """Decorator, augment function globals with tables and classes.
 
     Swaps out the function's globals at execution time. The 'global' statement
@@ -601,17 +579,15 @@ def resolve_artifact_names(fn):
     # Also: it's lame that CPython accepts a dict-subclass for globals, but
     # only calls dict methods.  That would allow 'global' to pass through to
     # the func_globals.
-    def resolved(*args, **kwargs):
-        self = args[0]
-        context = dict(fn.func_globals)
-        for source in self._artifact_registries:
-            context.update(getattr(self, source))
-        # jython bug #1034
-        rebound = types.FunctionType(
-            fn.func_code, context, fn.func_name, fn.func_defaults,
-            fn.func_closure)
-        return rebound(*args, **kwargs)
-    return function_named(resolved, fn.func_name)
+    self = args[0]
+    context = dict(fn.func_globals)
+    for source in self._artifact_registries:
+        context.update(getattr(self, source))
+    # jython bug #1034
+    rebound = types.FunctionType(
+        fn.func_code, context, fn.func_name, fn.func_defaults,
+        fn.func_closure)
+    return rebound(*args, **kw)
 
 class adict(dict):
     """Dict keys available as attributes.  Shadows."""
index e5277f07685ee5dfccdc3ca38b64ca9e6812e9a0..b8cc05a818b4daaf4a810ffa79471df5a472b65a 100644 (file)
@@ -1,4 +1,4 @@
-from sqlalchemy.util import jython, function_named, defaultdict
+from sqlalchemy.util import jython, defaultdict, decorator
 
 import gc
 import time
@@ -105,3 +105,22 @@ def all_partial_orderings(tuples, elements):
     
     return iter(_all_orderings(elements))
 
+
+def function_named(fn, name):
+    """Return a function with a given __name__.
+
+    Will assign to __name__ and return the original function if possible on
+    the Python implementation, otherwise a new function will be constructed.
+
+    This function should be phased out as much as possible
+    in favor of @decorator.   Tests that "generate" many named tests
+    should be modernized.
+    
+    """
+    try:
+        fn.__name__ = name
+    except TypeError:
+        fn = types.FunctionType(fn.func_code, fn.func_globals, name,
+                          fn.func_defaults, fn.func_closure)
+    return fn
+
index 4ccc1015747878d008e665fa3f94922a3422bf51..345009d400839754e8a9fe802a21bbdd532a0780 100644 (file)
@@ -6,7 +6,6 @@ import sqlalchemy.exceptions as sa_exc
 from test.lib import config, testing
 from test.lib.testing import resolve_artifact_names, adict
 from test.lib.engines import drop_all_tables
-from sqlalchemy.util import function_named
 from test.lib.entities import BasicEntity, ComparableEntity
 
 Entity = BasicEntity
index fb229003b7b34a7f147bb4e422e0d4917180477c..58569ab9c026730f293e9a83f755dd2df2dfc49b 100644 (file)
@@ -2,7 +2,7 @@ from sqlalchemy import *
 from sqlalchemy import util
 from sqlalchemy.orm import *
 
-from sqlalchemy.util import function_named
+from test.lib.util import function_named
 from test.orm import _base, _fixtures
 from test.lib.schema import Table, Column
 
index 544aa1abea4d9227bde494091f1709206c5321cb..d6b9d89f4f6badca28cfade5bfc0ebae5a5a6c29 100644 (file)
@@ -7,7 +7,6 @@ from sqlalchemy.orm import exc as orm_exc, attributes
 from test.lib.assertsql import AllOf, CompiledSQL
 
 from test.lib import testing, engines
-from sqlalchemy.util import function_named
 from test.orm import _base, _fixtures
 from test.lib.schema import Table, Column
 
index 307c54a9cc4006dc041cead7c1a619237eab6d8c..e38a1ec33abe99d252b2cfb248d0ab9b61e51ccd 100644 (file)
@@ -2,7 +2,7 @@ from sqlalchemy import *
 from sqlalchemy.orm import *
 
 from test.lib import testing
-from sqlalchemy.util import function_named
+from test.lib.util import function_named
 from test.orm import _base
 from test.lib.schema import Table, Column
 
index 8539baa765eb37f025c1521852341544b6c286ef..7e31c476baaeae38bc3f1758f1b861de7873dc41 100644 (file)
@@ -6,7 +6,7 @@ from sqlalchemy.orm import *
 from sqlalchemy.orm import exc as orm_exc
 from sqlalchemy import exc as sa_exc
 from test.lib import Column, testing
-from sqlalchemy.util import function_named
+from test.lib.util import function_named
 from test.orm import _fixtures, _base
 
 class Person(_fixtures.Base):
index 030b931a56dd5b6d24da990fa1275035cf5fc257..2a9341692d9c44868d263c52f5fd4b4ded73f01a 100644 (file)
@@ -8,7 +8,7 @@ from sqlalchemy import util
 from sqlalchemy.orm import *
 
 from test.lib import TestBase, AssertsExecutionResults, testing
-from sqlalchemy.util import function_named
+from test.lib.util import function_named
 from test.orm import _base, _fixtures
 from test.lib.testing import eq_
 from test.lib.schema import Table, Column
index 395911b644003ec19b074cb39e47a470dd4b8e6f..c0481f96b49fb2d5a487019a039dce104903d098 100644 (file)
@@ -7,8 +7,8 @@ from test.lib import *
 from test.lib.testing import eq_, ne_, assert_raises
 from test.orm import _base
 from test.lib.util import gc_collect, all_partial_orderings
-from sqlalchemy.util import cmp, jython
-from sqlalchemy import event, topological
+from sqlalchemy.util import cmp, jython, topological
+from sqlalchemy import event
 
 # global for pickling tests
 MyTest = None
index c89503278df1f932d552d61179913631d89e2b32..0958d60dd3dd1138831ae8a8d6663251148a2fb4 100644 (file)
@@ -7,7 +7,6 @@ from test.lib.schema import Table, Column
 from sqlalchemy.orm import mapper, relationship, create_session, Query, attributes
 from sqlalchemy.orm.dynamic import AppenderMixin
 from test.lib.testing import eq_, AssertsCompiledSQL, assert_raises_message
-from sqlalchemy.util import function_named
 from test.orm import _base, _fixtures
 
 
index 4b37013502fc059ae94ea928acb968906aeb5366..f7ba025e06fef267ffcb038ad1a85f9a5848b787 100644 (file)
@@ -7,29 +7,26 @@ from sqlalchemy.orm import mapper, relationship, create_session, \
 from test.lib.schema import Table
 from test.lib.schema import Column
 from test.lib.testing import eq_, ne_
-from sqlalchemy.util import function_named
+from test.lib.util import decorator
 from test.orm import _base
 
+@decorator
+def modifies_instrumentation_finders(fn, *args, **kw):
+    pristine = instrumentation.instrumentation_finders[:]
+    try:
+        fn(*args, **kw)
+    finally:
+        del instrumentation.instrumentation_finders[:]
+        instrumentation.instrumentation_finders.extend(pristine)
 
-def modifies_instrumentation_finders(fn):
-    def decorated(*args, **kw):
-        pristine = instrumentation.instrumentation_finders[:]
+def with_lookup_strategy(strategy):
+    @decorator
+    def decorate(fn, *args, **kw):
         try:
-            fn(*args, **kw)
+            instrumentation._install_lookup_strategy(strategy)
+            return fn(*args, **kw)
         finally:
-            del instrumentation.instrumentation_finders[:]
-            instrumentation.instrumentation_finders.extend(pristine)
-    return function_named(decorated, fn.func_name)
-
-def with_lookup_strategy(strategy):
-    def decorate(fn):
-        def wrapped(*args, **kw):
-            try:
-                instrumentation._install_lookup_strategy(strategy)
-                return fn(*args, **kw)
-            finally:
-                instrumentation._install_lookup_strategy(sa.util.symbol('native'))
-        return function_named(wrapped, fn.func_name)
+            instrumentation._install_lookup_strategy(sa.util.symbol('native'))
     return decorate