]> git.ipfire.org Git - thirdparty/sqlalchemy/alembic.git/commitdiff
Use vendored getargspec()
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 29 May 2019 21:32:57 +0000 (17:32 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 29 May 2019 22:50:25 +0000 (18:50 -0400)
Replaced the Python compatbility routines for ``getargspec()`` with a fully
vendored version based on ``getfullargspec()`` from Python 3.3.
Originally, Python was emitting deprecation warnings for this function in
Python 3.8 alphas.  While this change was reverted, it was observed that
Python 3 implementations for ``getfullargspec()`` are an order of magnitude
slower as of the 3.4 series where it was rewritten against ``Signature``.
While Python plans to improve upon this situation, SQLAlchemy projects for
now are using a simple replacement to avoid any future issues.

Change-Id: If5f3e2f6cc0df8d89e6c3035e024df3319964bf9
Fixes: #563
alembic/util/compat.py
docs/build/unreleased/563.rst [new file with mode: 0644]

index 994cbc9aae11448186c39b50f7aa9d47289fee3d..d57df9e30e9561b55a5d72f3965af420962e2777 100644 (file)
@@ -1,3 +1,5 @@
+import collections
+import inspect
 import io
 import sys
 
@@ -11,6 +13,41 @@ py33 = sys.version_info >= (3, 3)
 py35 = sys.version_info >= (3, 5)
 py36 = sys.version_info >= (3, 6)
 
+
+ArgSpec = collections.namedtuple(
+    "ArgSpec", ["args", "varargs", "keywords", "defaults"]
+)
+
+
+def inspect_getargspec(func):
+    """getargspec based on fully vendored getfullargspec from Python 3.3."""
+
+    if inspect.ismethod(func):
+        func = func.__func__
+    if not inspect.isfunction(func):
+        raise TypeError("{!r} is not a Python function".format(func))
+
+    co = func.__code__
+    if not inspect.iscode(co):
+        raise TypeError("{!r} is not a code object".format(co))
+
+    nargs = co.co_argcount
+    names = co.co_varnames
+    nkwargs = co.co_kwonlyargcount if py3k else 0
+    args = list(names[:nargs])
+
+    nargs += nkwargs
+    varargs = None
+    if co.co_flags & inspect.CO_VARARGS:
+        varargs = co.co_varnames[nargs]
+        nargs = nargs + 1
+    varkw = None
+    if co.co_flags & inspect.CO_VARKEYWORDS:
+        varkw = co.co_varnames[nargs]
+
+    return ArgSpec(args, varargs, varkw, func.__defaults__)
+
+
 if py3k:
     from io import StringIO
 else:
@@ -55,22 +92,6 @@ if py33:
 else:
     import collections as collections_abc  # noqa
 
-if py3k:
-    import collections
-
-    ArgSpec = collections.namedtuple(
-        "ArgSpec", ["args", "varargs", "keywords", "defaults"]
-    )
-
-    from inspect import getfullargspec as inspect_getfullargspec
-
-    def inspect_getargspec(func):
-        return ArgSpec(*inspect_getfullargspec(func)[0:4])
-
-
-else:
-    from inspect import getargspec as inspect_getargspec  # noqa
-
 if py35:
     from inspect import formatannotation
 
diff --git a/docs/build/unreleased/563.rst b/docs/build/unreleased/563.rst
new file mode 100644 (file)
index 0000000..63d23df
--- /dev/null
@@ -0,0 +1,13 @@
+.. change::
+    :tags: bug, py3k
+    :tickets: 563
+
+    Replaced the Python compatbility routines for ``getargspec()`` with a fully
+    vendored version based on ``getfullargspec()`` from Python 3.3.
+    Originally, Python was emitting deprecation warnings for this function in
+    Python 3.8 alphas.  While this change was reverted, it was observed that
+    Python 3 implementations for ``getfullargspec()`` are an order of magnitude
+    slower as of the 3.4 series where it was rewritten against ``Signature``.
+    While Python plans to improve upon this situation, SQLAlchemy projects for
+    now are using a simple replacement to avoid any future issues.
+