From 217948f5c79e03956de998af86fef77ebc3edb76 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Wed, 1 Jan 2020 18:24:03 -0500 Subject: Enable F821 In Ia63a510f9c1d08b055eef62cf047f1f427f0450c we introduced "lambda combinations" which use a bit of function closure inspection in order to allow for testing combinations that make use of symbols that come from test fixtures, or from the test itself. Two problems. One is that we can't use F821 flake8 rule without either adding lots of noqas, skipping the file, or adding arguments to the lambdas themselves that are then populated, which makes for a very verbose system. The other is that the system is already verbose with all those lambdas and the magic in use is a non-explicit kind, hence F821 reminds us that if we can improve upon this, we should. So let's improve upon it by making it so that the "lambda" is just once and up front for the whole thing, and let it accept the arguments directly. This still requires magic, because these test cases need to resolve at test collection time, not test runtime. But we will instead substitute a namespace up front that can be coerced into its desired form within the tests. Additionally, there's a little bit of py2k compatible type annotations present; f821 is checking these, so we have to add those imports also using the TYPE_CHECKING boolean so they don't take place in py2k. Change-Id: Idb7e7a0c8af86d9ab133f548511306ef68cdba14 --- lib/sqlalchemy/testing/__init__.py | 1 + lib/sqlalchemy/testing/exclusions.py | 4 +++- lib/sqlalchemy/testing/util.py | 26 ++++++++++++++++++++++++-- 3 files changed, 28 insertions(+), 3 deletions(-) (limited to 'lib/sqlalchemy/testing') diff --git a/lib/sqlalchemy/testing/__init__.py b/lib/sqlalchemy/testing/__init__.py index e5425dd81..ab1198da8 100644 --- a/lib/sqlalchemy/testing/__init__.py +++ b/lib/sqlalchemy/testing/__init__.py @@ -54,6 +54,7 @@ from .util import adict # noqa from .util import fail # noqa from .util import flag_combinations # noqa from .util import force_drop_names # noqa +from .util import lambda_combinations # noqa from .util import metadata_fixture # noqa from .util import provide_metadata # noqa from .util import resolve_lambda # noqa diff --git a/lib/sqlalchemy/testing/exclusions.py b/lib/sqlalchemy/testing/exclusions.py index 8b17f64c7..b2828b107 100644 --- a/lib/sqlalchemy/testing/exclusions.py +++ b/lib/sqlalchemy/testing/exclusions.py @@ -159,7 +159,9 @@ class compound(object): for fail in self.fails: if self._check_combinations(combination, fail) and fail(config): if util.py2k: - str_ex = unicode(ex).encode("utf-8", errors="ignore") + str_ex = unicode(ex).encode( # noqa: F821 + "utf-8", errors="ignore" + ) else: str_ex = str(ex) print( diff --git a/lib/sqlalchemy/testing/util.py b/lib/sqlalchemy/testing/util.py index 74c9b1aeb..de20bb794 100644 --- a/lib/sqlalchemy/testing/util.py +++ b/lib/sqlalchemy/testing/util.py @@ -12,13 +12,14 @@ import sys import time import types +from . import mock from ..util import decorator from ..util import defaultdict +from ..util import inspect_getfullargspec from ..util import jython from ..util import py2k from ..util import pypy - if jython: def jython_gc_collect(*args): @@ -276,6 +277,25 @@ def flag_combinations(*combinations): ) +def lambda_combinations(lambda_arg_sets, **kw): + from . import config + + args = inspect_getfullargspec(lambda_arg_sets) + + arg_sets = lambda_arg_sets(*[mock.Mock() for arg in args[0]]) + + def create_fixture(pos): + def fixture(**kw): + return lambda_arg_sets(**kw)[pos] + + fixture.__name__ = "fixture_%3.3d" % pos + return fixture + + return config.combinations( + *[(create_fixture(i),) for i in range(len(arg_sets))], **kw + ) + + def resolve_lambda(__fn, **kw): """Given a no-arg lambda and a namespace, return a new lambda that has all the values filled in. @@ -285,10 +305,12 @@ def resolve_lambda(__fn, **kw): """ + pos_args = inspect_getfullargspec(__fn)[0] + pass_pos_args = {arg: kw.pop(arg) for arg in pos_args} glb = dict(__fn.__globals__) glb.update(kw) new_fn = types.FunctionType(__fn.__code__, glb) - return new_fn() + return new_fn(**pass_pos_args) def metadata_fixture(ddl="function"): -- cgit v1.2.1