From: Mike Bayer Date: Wed, 29 May 2019 21:27:19 +0000 (-0400) Subject: Use fully vendored getfullargspec X-Git-Tag: rel_1_4_0b1~850 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df99e1ef5f334ce7f4c8118c3e0bdf2949f54de3;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Use fully vendored getfullargspec Replaced the Python compatbility routines for ``getfullargspec()`` with a fully vendored version 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. Fixes: #4674 Change-Id: I1ab8729c4072634db80c79bb7bc44197dc5e7114 --- diff --git a/doc/build/changelog/unreleased_13/4674.rst b/doc/build/changelog/unreleased_13/4674.rst new file mode 100644 index 0000000000..827929cce6 --- /dev/null +++ b/doc/build/changelog/unreleased_13/4674.rst @@ -0,0 +1,12 @@ +.. change:: + :tags: bug, orm, py3k + :tickets: 4674 + + Replaced the Python compatbility routines for ``getfullargspec()`` with a + fully vendored version 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. diff --git a/lib/sqlalchemy/util/compat.py b/lib/sqlalchemy/util/compat.py index c12f2d3798..386aaf731f 100644 --- a/lib/sqlalchemy/util/compat.py +++ b/lib/sqlalchemy/util/compat.py @@ -9,6 +9,7 @@ import collections import contextlib +import inspect import operator import sys import time @@ -44,19 +45,6 @@ FullArgSpec = collections.namedtuple( ], ) -FullArgSpec = collections.namedtuple( - "FullArgSpec", - [ - "args", - "varargs", - "varkw", - "defaults", - "kwonlyargs", - "kwonlydefaults", - "annotations", - ], -) - try: import threading except ImportError: @@ -70,6 +58,45 @@ else: safe_kwarg = str +def inspect_getfullargspec(func): + """Fully vendored version of 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]) + kwonlyargs = list(names[nargs : nargs + nkwargs]) + step = 0 + + 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 FullArgSpec( + args, + varargs, + varkw, + func.__defaults__, + kwonlyargs, + func.__kwdefaults__ if py3k else None, + func.__annotations__ if py3k else {}, + ) + + if py3k: import base64 import builtins @@ -78,7 +105,6 @@ if py3k: import pickle from functools import reduce - from inspect import getfullargspec as inspect_getfullargspec from io import BytesIO as byte_buffer from io import StringIO from itertools import zip_longest @@ -149,7 +175,6 @@ else: from StringIO import StringIO # noqa from cStringIO import StringIO as byte_buffer # noqa - from inspect import getargspec as _getargspec from itertools import izip_longest as zip_longest # noqa from urllib import quote # noqa from urllib import quote_plus # noqa @@ -168,9 +193,6 @@ else: text_type = unicode # noqa int_types = int, long # noqa - def inspect_getfullargspec(func): - return FullArgSpec(*_getargspec(func)[0:4] + ([], None, {})) - callable = callable # noqa cmp = cmp # noqa reduce = reduce # noqa