]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
Vendor python3 formatargspec, import from collections.abc
authorStefan Tjarks <66305+stj@users.noreply.github.com>
Thu, 22 Nov 2018 03:08:56 +0000 (22:08 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 28 Nov 2018 03:48:51 +0000 (22:48 -0500)
Resolved remaining Python 3 deprecation warnings, covering
the use of inspect.formatargspec() with a vendored version
copied from the Python standard library, importing
collections.abc above Python 3.3 when testing against abstract
base classes, fixed one occurrence of log.warn(), as well as a few
invalid escape sequences.

Add DeprecationWarning to the test suite as an error raise
as has been the case within SQLAlchemy for some time now.

Fixes: #507
Co-authored-by: Mike Bayer <mike_mp@zzzcomputing.com>
Change-Id: I121121b3d2dd90e6f3c9b16dec2fc80b9699c400
Pull-request: https://bitbucket.org/zzzeek/alembic/pull-requests/85

alembic/operations/base.py
alembic/testing/provision.py
alembic/testing/warnings.py
alembic/util/compat.py
alembic/util/langhelpers.py
alembic/util/messaging.py
docs/build/unreleased/507.rst [new file with mode: 0644]
tests/test_op.py
tests/test_version_traversal.py

index ef6ecf8ff476fce0cbe71c7bc3060d67ba6784a8..1ae95241063441754e97994f4293b5a8895e5f87 100644 (file)
@@ -5,9 +5,9 @@ from ..util import sqla_compat
 from . import batch
 from . import schemaobj
 from ..util.compat import exec_
+from ..util.compat import inspect_formatargspec
 from ..util.compat import inspect_getargspec
 import textwrap
-import inspect
 
 __all__ = ('Operations', 'BatchOperations')
 
@@ -99,14 +99,14 @@ class Operations(util.ModuleClsProxy):
 
             name_args[0:2] = ['self']
 
-            args = inspect.formatargspec(*spec)
+            args = inspect_formatargspec(*spec)
             num_defaults = len(spec[3]) if spec[3] else 0
             if num_defaults:
                 defaulted_vals = name_args[0 - num_defaults:]
             else:
                 defaulted_vals = ()
 
-            apply_kw = inspect.formatargspec(
+            apply_kw = inspect_formatargspec(
                 name_args, spec[1], spec[2],
                 defaulted_vals,
                 formatvalue=lambda x: '=' + x)
index 546ef23c225fd941c19eeceebf1636da9710d27f..15d9e1cd5a154f01cf3795e8ded3c6e000f15132 100644 (file)
@@ -256,6 +256,7 @@ def _oracle_create_db(cfg, eng, ident):
         conn.execute("grant unlimited tablespace to %s_ts1" % ident)
         conn.execute("grant unlimited tablespace to %s_ts2" % ident)
 
+
 @_configure_follower.for_db("oracle")
 def _oracle_configure_follower(config, ident):
     config.test_schema = "%s_ts1" % ident
@@ -268,7 +269,7 @@ def _ora_drop_ignore(conn, dbname):
         log.info("Reaped db: %s" % dbname)
         return True
     except exc.DatabaseError as err:
-        log.warn("couldn't drop db: %s" % err)
+        log.warning("couldn't drop db: %s" % err)
         return False
 
 
index 397938f0ba66132d27aaa945884aebfc5c3a9432..de91778593f626c9548a2b872e862310cbfc5290 100644 (file)
@@ -17,11 +17,11 @@ import re
 
 def setup_filters():
     """Set global warning behavior for the test suite."""
-
     warnings.filterwarnings('ignore',
                             category=sa_exc.SAPendingDeprecationWarning)
     warnings.filterwarnings('error', category=sa_exc.SADeprecationWarning)
     warnings.filterwarnings('error', category=sa_exc.SAWarning)
+    warnings.filterwarnings('error', category=DeprecationWarning)
 
 
 def assert_warnings(fn, warning_msgs, regex=False):
index b3e0d57ac7b4204b111ec0dc34d6f96389656c5c..dec2ca8fecbaeb1f2015e9b7c55aecd8e38ac25a 100644 (file)
@@ -7,6 +7,7 @@ if sys.version_info < (2, 7):
 py27 = sys.version_info >= (2, 7)
 py2k = sys.version_info.major < 3
 py3k = sys.version_info.major >= 3
+py33 = sys.version_info >= (3, 3)
 py35 = sys.version_info >= (3, 5)
 py36 = sys.version_info >= (3, 6)
 
@@ -47,6 +48,11 @@ else:
 
     range = xrange
 
+if py33:
+    import collections.abc as collections_abc
+else:
+    import collections as collections_abc
+
 if py3k:
     import collections
     ArgSpec = collections.namedtuple(
@@ -62,6 +68,63 @@ if py3k:
 else:
     from inspect import getargspec as inspect_getargspec  # noqa
 
+if py35:
+    from inspect import formatannotation
+
+    def inspect_formatargspec(
+            args, varargs=None, varkw=None, defaults=None,
+            kwonlyargs=(), kwonlydefaults={}, annotations={},
+            formatarg=str,
+            formatvarargs=lambda name: '*' + name,
+            formatvarkw=lambda name: '**' + name,
+            formatvalue=lambda value: '=' + repr(value),
+            formatreturns=lambda text: ' -> ' + text,
+            formatannotation=formatannotation):
+        """Copy formatargspec from python 3.7 standard library.
+
+        Python 3 has deprecated formatargspec and requested that Signature
+        be used instead, however this requires a full reimplementation
+        of formatargspec() in terms of creating Parameter objects and such.
+        Instead of introducing all the object-creation overhead and having
+        to reinvent from scratch, just copy their compatibility routine.
+
+        """
+
+        def formatargandannotation(arg):
+            result = formatarg(arg)
+            if arg in annotations:
+                result += ': ' + formatannotation(annotations[arg])
+            return result
+        specs = []
+        if defaults:
+            firstdefault = len(args) - len(defaults)
+        for i, arg in enumerate(args):
+            spec = formatargandannotation(arg)
+            if defaults and i >= firstdefault:
+                spec = spec + formatvalue(defaults[i - firstdefault])
+            specs.append(spec)
+        if varargs is not None:
+            specs.append(formatvarargs(formatargandannotation(varargs)))
+        else:
+            if kwonlyargs:
+                specs.append('*')
+        if kwonlyargs:
+            for kwonlyarg in kwonlyargs:
+                spec = formatargandannotation(kwonlyarg)
+                if kwonlydefaults and kwonlyarg in kwonlydefaults:
+                    spec += formatvalue(kwonlydefaults[kwonlyarg])
+                specs.append(spec)
+        if varkw is not None:
+            specs.append(formatvarkw(formatargandannotation(varkw)))
+        result = '(' + ', '.join(specs) + ')'
+        if 'return' in annotations:
+            result += formatreturns(formatannotation(annotations['return']))
+        return result
+
+else:
+    from inspect import formatargspec as inspect_formatargspec
+
+
 if py3k:
     from configparser import ConfigParser as SafeConfigParser
     import configparser
index aa016f04e2497dc37254552d99d6ff32df584a52..832332cbe76647aeeb01b09a55d922b30ca6fe4f 100644 (file)
@@ -1,12 +1,14 @@
 import textwrap
 import warnings
-import inspect
 import uuid
 import collections
 
+from .compat import collections_abc
+
 from .compat import callable, exec_, string_types, with_metaclass
 
 from .compat import inspect_getargspec
+from .compat import inspect_formatargspec
 
 
 class _ModuleClsMeta(type):
@@ -75,7 +77,7 @@ class ModuleClsProxy(with_metaclass(_ModuleClsMeta)):
         spec = inspect_getargspec(fn)
         if spec[0] and spec[0][0] == 'self':
             spec[0].pop(0)
-        args = inspect.formatargspec(*spec)
+        args = inspect_formatargspec(*spec)
         num_defaults = 0
         if spec[3]:
             num_defaults += len(spec[3])
@@ -85,7 +87,7 @@ class ModuleClsProxy(with_metaclass(_ModuleClsMeta)):
         else:
             defaulted_vals = ()
 
-        apply_kw = inspect.formatargspec(
+        apply_kw = inspect_formatargspec(
             name_args, spec[1], spec[2],
             defaulted_vals,
             formatvalue=lambda x: '=' + x)
@@ -189,7 +191,7 @@ def to_list(x, default=None):
         return default
     elif isinstance(x, string_types):
         return [x]
-    elif isinstance(x, collections.Iterable):
+    elif isinstance(x, collections_abc.Iterable):
         return list(x)
     else:
         return [x]
@@ -200,7 +202,7 @@ def to_tuple(x, default=None):
         return default
     elif isinstance(x, string_types):
         return (x, )
-    elif isinstance(x, collections.Iterable):
+    elif isinstance(x, collections_abc.Iterable):
         return tuple(x)
     else:
         return (x, )
index c202e96c2e2d5a80fc410f6c3161cd8d8c6849cc..872345b52f6aec432758934927a02084a0a81b3e 100644 (file)
@@ -1,9 +1,10 @@
 from .compat import py27, binary_type, string_types
+from .compat import collections_abc
+
 import sys
 from sqlalchemy.engine import url
 import warnings
 import textwrap
-import collections
 import logging
 
 log = logging.getLogger(__name__)
@@ -88,7 +89,7 @@ def format_as_comma(value):
         return ""
     elif isinstance(value, string_types):
         return value
-    elif isinstance(value, collections.Iterable):
+    elif isinstance(value, collections_abc.Iterable):
         return ", ".join(value)
     else:
         raise ValueError("Don't know how to comma-format %r" % value)
diff --git a/docs/build/unreleased/507.rst b/docs/build/unreleased/507.rst
new file mode 100644 (file)
index 0000000..7293ba4
--- /dev/null
@@ -0,0 +1,10 @@
+.. change::
+    :tags: bug, py3k
+    :tickets: 507
+
+    Resolved remaining Python 3 deprecation warnings, covering
+    the use of inspect.formatargspec() with a vendored version
+    copied from the Python standard library, importing
+    collections.abc above Python 3.3 when testing against abstract
+    base classes, fixed one occurrence of log.warn(), as well as a few
+    invalid escape sequences.
\ No newline at end of file
index 63e4a7481117d44c6b4126ffa52910732991a554..f9a6c51d2da23abfde81a02a0394269ea4f7ef3b 100644 (file)
@@ -36,7 +36,7 @@ class OpTest(TestBase):
         op_fixture()
         assert_raises_message(
             ValueError,
-            "String or text\(\) construct expected",
+            r"String or text\(\) construct expected",
             op.create_index, 'name', 'tname', [func.foo(column('x'))]
         )
 
index 08c737f10c9e875cef164f67fb8f75b29033f845..f69a9bd24a3ba1a6b2d8de7c9aac2764aadac0fd 100644 (file)
@@ -183,7 +183,7 @@ class RevisionPathTest(MigrationTest):
         assert_raises_message(
             util.CommandError,
             r"Destination %s is not a valid downgrade "
-            "target from current head\(s\)" % self.b.revision[0:3],
+            r"target from current head\(s\)" % self.b.revision[0:3],
             self.env._downgrade_revs, self.b.revision[0:3], None
         )
 
@@ -192,7 +192,7 @@ class RevisionPathTest(MigrationTest):
         assert_raises_message(
             util.CommandError,
             r"Destination %s is not a valid downgrade "
-            "target from current head\(s\)" % self.c.revision[0:4],
+            r"target from current head\(s\)" % self.c.revision[0:4],
             self.env._downgrade_revs, self.c.revision[0:4], self.b.revision
         )