From 91f8772a819eebe9402cad46c36cf12bf0c27237 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 11:58:25 +0100 Subject: [PATCH 01/19] Drop Python 3.6, 3.7 support These are both EOL [1]. Users can continue using an older version of wrapt where needed. [1] https://devguide.python.org/versions/ Signed-off-by: Stephen Finucane --- .github/workflows/main.yml | 111 ++++++++----------------------------- setup.cfg | 10 +--- 2 files changed, 25 insertions(+), 96 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2aa76d97..8a853351 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,19 +17,14 @@ jobs: os: - ubuntu-20.04 python-version: - # - 2.7 - # - 3.5 - - 3.6 - - 3.7 - - 3.8 - - 3.9 + - "3.8" + - "3.9" - "3.10" - - 3.11 - - 3.12 - # - pypy-2.7 - - pypy-3.8 - - pypy-3.9 - - pypy-3.10 + - "3.11" + - "3.12" + - "pypy-3.8" + - "pypy-3.9" + - "pypy-3.10" steps: - name: Checkout code uses: actions/checkout@v3 @@ -55,7 +50,6 @@ jobs: # strategy: # matrix: # python: - # #- {os: ubuntu-20.04, python-version: 3.7, pyver: py37} # #- {os: ubuntu-20.04, python-version: 3.8, pyver: py38} # #- {os: ubuntu-20.04, python-version: 3.9, pyver: py39} # - {os: ubuntu-20.04, python-version: "3.10", pyver: py310} @@ -91,19 +85,14 @@ jobs: os: - macos-latest python-version: - # - 2.7 - # - 3.5 - - 3.6 - - 3.7 - - 3.8 - - 3.9 + - "3.8" + - "3.9" - "3.10" - - 3.11 - - 3.12 - # - pypy-2.7 - - pypy-3.8 - - pypy-3.9 - - pypy-3.10 + - "3.11" + - "3.12" + - "pypy-3.8" + - "pypy-3.9" + - "pypy-3.10" steps: - name: Checkout code uses: actions/checkout@v3 @@ -123,29 +112,6 @@ jobs: name: coverage path: .coverage.* - # test_windows_py27: - # name: Test (${{ matrix.os }}, ${{ matrix.python-version }}) - # runs-on: ${{ matrix.os }} - # strategy: - # matrix: - # os: - # - windows-latest - # python-version: - # - 2.7 - # steps: - # - name: Checkout code - # uses: actions/checkout@v3 - # - name: Setup Python ${{ matrix.python-version }} - # uses: actions/setup-python@v4 - # with: - # python-version: ${{ matrix.python-version }} - # - name: Update pip - # run: python -m pip install -U pip wheel setuptools - # - name: Install tox - # run: python -m pip install "tox<4.0.0" "tox-gh-actions<3.0.0" - # - name: Test with tox - # run: python -m tox -e py27,py27-without-extensions - test_windows: name: Test (${{ matrix.os }}, ${{ matrix.python-version }}) runs-on: ${{ matrix.os }} @@ -154,18 +120,14 @@ jobs: os: - windows-latest python-version: - # - 3.5 - - 3.6 - - 3.7 - - 3.8 - - 3.9 + - "3.8" + - "3.9" - "3.10" - - 3.11 - - 3.12 - # - pypy-2.7 - - pypy-3.8 - - pypy-3.9 - - pypy-3.10 + - "3.11" + - "3.12" + - "pypy-3.8" + - "pypy-3.9" + - "pypy-3.10" steps: - name: Checkout code uses: actions/checkout@v3 @@ -208,40 +170,12 @@ jobs: name: dist path: dist/* - # bdist_wheel_legacy: - # name: Build wheels (2.7-3.5) on ${{ matrix.os }} - # needs: - # - test_linux - # - test_macos - # - test_windows_py27 - # - test_windows - # runs-on: ${{ matrix.os }} - # strategy: - # matrix: - # os: [ubuntu-20.04, windows-latest, macos-latest] - # steps: - # - uses: actions/checkout@v3 - # - name: Build wheels - # uses: pypa/cibuildwheel@v1.11.1.post1 - # with: - # output-dir: dist - # env: - # WRAPT_INSTALL_EXTENSIONS: true - # CIBW_BUILD: cp27* cp35* - # CIBW_SKIP: cp27-win* - # CIBW_BUILD_VERBOSITY: 1 - # - uses: actions/upload-artifact@v3 - # with: - # name: dist - # path: dist/*.whl - bdist_wheel: - name: Build wheels (3.6+) on ${{ matrix.os }} for ${{ matrix.arch }} + name: Build wheels on ${{ matrix.os }} for ${{ matrix.arch }} needs: - test_linux #- test_aarch64_linux - test_macos - # - test_windows_py27 - test_windows runs-on: ${{ matrix.os }} strategy: @@ -278,7 +212,6 @@ jobs: needs: - test_linux - test_macos - # - test_windows_py27 - test_windows runs-on: ubuntu-20.04 steps: diff --git a/setup.cfg b/setup.cfg index 9c282c93..799008f0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,8 +17,6 @@ classifiers = Development Status :: 5 - Production/Stable License :: OSI Approved :: BSD License Programming Language :: Python :: 3 - Programming Language :: Python :: 3.6 - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 @@ -33,7 +31,7 @@ project_urls = [options] zip_safe = false -python_requires = >= 3.6 +python_requires = >= 3.8 packages = find: package_dir = =src @@ -70,14 +68,12 @@ norecursedirs = .tox venv [tox:tox] envlist = - py{36,37,38,39,310,311,312} - py{36,37,38,39,310,311,312}-{without,install,disable}-extensions, + py{38,39,310,311,312} + py{38,39,310,311,312}-{without,install,disable}-extensions, pypy-without-extensions [gh-actions] python = - 3.6: py36, py36-without-extensions, py36-install-extensions, py36-disable-extensions - 3.7: py37, py37-without-extensions, py37-install-extensions, py37-disable-extensions 3.8: py38, py38-without-extensions, py38-install-extensions, py38-disable-extensions 3.9: py39, py39-without-extensions, py39-install-extensions, py39-disable-extensions 3.10: py310, py310-without-extensions, py310-install-extensions, py310-disable-extensions From 2bfe73d79ea35e9e6a63c6007d62d670ae491a7c Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:32:08 +0100 Subject: [PATCH 02/19] tox: Migrate to tox v4 tox 4 doesn't seem to like the use of setup.cfg. We can also remove the use of a custom install command for Python 3.11 since coverage has fixed the binary packages for same. Signed-off-by: Stephen Finucane --- .github/workflows/main.yml | 8 ++++---- setup.cfg | 32 -------------------------------- tox.ini | 25 +++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 36 deletions(-) create mode 100644 tox.ini diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8a853351..002dc216 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,7 +35,7 @@ jobs: - name: Update pip run: python -m pip install -U pip wheel setuptools - name: Install tox - run: python -m pip install "tox<4.0.0" "tox-gh-actions<3.0.0" + run: python -m pip install tox tox-gh-actions - name: Test with tox run: python -m tox - name: Store partial coverage reports @@ -73,7 +73,7 @@ jobs: # ${{ env.py }} -m venv .env && \ # source .env/bin/activate && \ # pip install -U pip wheel setuptools && \ - # pip install "tox<4.0.0" "tox-gh-actions<3.0.0" && \ + # pip install tox tox-gh-actions && \ # tox -e ${{ matrix.python.pyver }} && \ # deactivate' @@ -103,7 +103,7 @@ jobs: - name: Update pip run: python -m pip install -U pip wheel setuptools - name: Install tox - run: python -m pip install "tox<4.0.0" "tox-gh-actions<3.0.0" + run: python -m pip install tox tox-gh-actions - name: Test with tox run: python -m tox - name: Store partial coverage reports @@ -138,7 +138,7 @@ jobs: - name: Update pip run: python -m pip install -U pip wheel setuptools - name: Install tox - run: python -m pip install "tox<4.0.0" "tox-gh-actions<3.0.0" + run: python -m pip install tox tox-gh-actions - name: Test with tox run: python -m tox diff --git a/setup.cfg b/setup.cfg index 799008f0..c0d8c1a6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -63,35 +63,3 @@ src = [tool:pytest] norecursedirs = .tox venv - -# --- Tox automation configuration --------------------------------------------- - -[tox:tox] -envlist = - py{38,39,310,311,312} - py{38,39,310,311,312}-{without,install,disable}-extensions, - pypy-without-extensions - -[gh-actions] -python = - 3.8: py38, py38-without-extensions, py38-install-extensions, py38-disable-extensions - 3.9: py39, py39-without-extensions, py39-install-extensions, py39-disable-extensions - 3.10: py310, py310-without-extensions, py310-install-extensions, py310-disable-extensions - 3.11: py311, py311-without-extensions, py311-install-extensions, py311-disable-extensions - 3.12: py312, py312-without-extensions, py312-install-extensions, py312-disable-extensions - pypy-3.8: pypy-without-extensions - pypy-3.9: pypy-without-extensions - pypy-3.10: pypy-without-extensions - -[testenv] -deps = - coverage - pytest -install_command = - py311,py311-{without,install,disable}-extensions: python -m pip install --no-binary coverage {opts} {packages} -commands = - python -m coverage run --rcfile {toxinidir}/setup.cfg -m pytest -v {posargs} {toxinidir}/tests -setenv = - without-extensions: WRAPT_INSTALL_EXTENSIONS = false - install-extensions,disable-extensions: WRAPT_INSTALL_EXTENSIONS = true - disable-extensions: WRAPT_DISABLE_EXTENSIONS = true diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..edd3fa73 --- /dev/null +++ b/tox.ini @@ -0,0 +1,25 @@ +[tox] +minversion = 4.0.0 +envlist = py{38,39,310,311,312},py{38,39,310,311,312}-{without,install,disable}-extensions,pypy-without-extensions + +[testenv] +setenv = + without-extensions: WRAPT_INSTALL_EXTENSIONS = false + install-extensions,disable-extensions: WRAPT_INSTALL_EXTENSIONS = true + disable-extensions: WRAPT_DISABLE_EXTENSIONS = true +deps = + coverage + pytest +commands = + python -m coverage run --rcfile {toxinidir}/setup.cfg -m pytest -v {posargs} {toxinidir}/tests + +[gh-actions] +python = + 3.8: py38, py38-without-extensions, py38-install-extensions, py38-disable-extensions + 3.9: py39, py39-without-extensions, py39-install-extensions, py39-disable-extensions + 3.10: py310, py310-without-extensions, py310-install-extensions, py310-disable-extensions + 3.11: py311, py311-without-extensions, py311-install-extensions, py311-disable-extensions + 3.12: py312, py312-without-extensions, py312-install-extensions, py312-disable-extensions + pypy-3.8: pypy-without-extensions + pypy-3.9: pypy-without-extensions + pypy-3.10: pypy-without-extensions From 9f3006597660496b14ce7bd52945ea2bcf0640b0 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:07:47 +0100 Subject: [PATCH 03/19] compat: Remove 'exec_' wrapper We can just use the built-in variant as-is now. Signed-off-by: Stephen Finucane --- src/wrapt/decorators.py | 20 +------------------- tests/compat.py | 22 ---------------------- tests/test_adapter.py | 4 ++-- tests/test_adapter_py3.py | 4 ++-- tests/test_adapter_py33.py | 4 ++-- tests/test_class.py | 4 ++-- tests/test_class_py37.py | 2 +- tests/test_function.py | 4 ++-- tests/test_function_wrapper.py | 3 ++- tests/test_inner_classmethod.py | 4 ++-- tests/test_inner_staticmethod.py | 4 ++-- tests/test_instancemethod.py | 4 ++-- tests/test_nested_function.py | 4 ++-- tests/test_object_proxy.py | 4 ++-- tests/test_outer_classmethod.py | 4 ++-- tests/test_outer_staticmethod.py | 4 ++-- tests/test_update_attributes.py | 2 +- 17 files changed, 29 insertions(+), 68 deletions(-) diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index c80a4bb7..dd1c7d6c 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -9,27 +9,9 @@ if PY2: string_types = basestring, - - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - else: string_types = str, - import builtins - - exec_ = getattr(builtins, "exec") - del builtins - from functools import partial from inspect import isclass from threading import Lock, RLock @@ -226,7 +208,7 @@ def _build(wrapped, wrapper, enabled=None, adapter=None): adapter = adapter[:-1] adapter = formatargspec(*adapter) - exec_('def adapter{}: pass'.format(adapter), ns, ns) + exec('def adapter{}: pass'.format(adapter), ns, ns) adapter = ns['adapter'] # Override the annotations for the manufactured diff --git a/tests/compat.py b/tests/compat.py index 83b61f94..eaf4eb52 100644 --- a/tests/compat.py +++ b/tests/compat.py @@ -5,28 +5,6 @@ PYXY = tuple(sys.version_info[:2]) -if PY3: - import builtins - exec_ = getattr(builtins, "exec") - del builtins - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - try: from inspect import getfullargspec except ImportError: diff --git a/tests/test_adapter.py b/tests/test_adapter.py index 85063c28..aba420ea 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -6,7 +6,7 @@ import wrapt -from compat import PY2, exec_, getfullargspec +from compat import PY2, getfullargspec DECORATORS_CODE = """ import wrapt @@ -19,7 +19,7 @@ def adapter1(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) def function1(arg1, arg2): '''documentation''' diff --git a/tests/test_adapter_py3.py b/tests/test_adapter_py3.py index b6d48f17..6c51925e 100644 --- a/tests/test_adapter_py3.py +++ b/tests/test_adapter_py3.py @@ -8,7 +8,7 @@ import wrapt -from compat import PY2, exec_ +from compat import PY2 DECORATORS_CODE = """ import wrapt @@ -28,7 +28,7 @@ def adapter2(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) def function1(arg1, arg2) -> Iterable: '''documentation''' diff --git a/tests/test_adapter_py33.py b/tests/test_adapter_py33.py index 0cc8b2eb..21117d1d 100644 --- a/tests/test_adapter_py33.py +++ b/tests/test_adapter_py33.py @@ -6,7 +6,7 @@ import wrapt -from compat import PY2, PY3, exec_ +from compat import PY2, PY3 DECORATORS_CODE = """ import wrapt @@ -19,7 +19,7 @@ def adapter1(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) def function1(arg1, arg2): '''documentation''' diff --git a/tests/test_class.py b/tests/test_class.py index d0f83845..8e9e1c87 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -6,7 +6,7 @@ import wrapt -from compat import PY2, PY3, exec_ +from compat import PY2, PY3 DECORATORS_CODE = """ import wrapt @@ -17,7 +17,7 @@ def passthru_decorator(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) class class1(object): pass diff --git a/tests/test_class_py37.py b/tests/test_class_py37.py index cdab1b6d..878f537a 100644 --- a/tests/test_class_py37.py +++ b/tests/test_class_py37.py @@ -6,7 +6,7 @@ import wrapt -from compat import PY2, PY3, exec_ +from compat import PY2, PY3 class TestInheritance(unittest.TestCase): diff --git a/tests/test_function.py b/tests/test_function.py index cb77b35c..7da01b95 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -6,7 +6,7 @@ import wrapt -from compat import exec_, getfullargspec +from compat import getfullargspec DECORATORS_CODE = """ import wrapt @@ -17,7 +17,7 @@ def passthru_decorator(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) def function1(arg): '''documentation''' diff --git a/tests/test_function_wrapper.py b/tests/test_function_wrapper.py index c353b205..7a5cb69e 100644 --- a/tests/test_function_wrapper.py +++ b/tests/test_function_wrapper.py @@ -4,7 +4,8 @@ import wrapt -from compat import PY2, PY3, exec_ +from compat import PY2, PY3 + class TestClassInheritence(unittest.TestCase): diff --git a/tests/test_inner_classmethod.py b/tests/test_inner_classmethod.py index e2127ab9..5a642f88 100644 --- a/tests/test_inner_classmethod.py +++ b/tests/test_inner_classmethod.py @@ -5,7 +5,7 @@ import wrapt -from compat import exec_, getfullargspec +from compat import getfullargspec DECORATORS_CODE = """ import wrapt @@ -16,7 +16,7 @@ def passthru_decorator(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) class Class(object): @classmethod diff --git a/tests/test_inner_staticmethod.py b/tests/test_inner_staticmethod.py index bd3756f4..706d9520 100644 --- a/tests/test_inner_staticmethod.py +++ b/tests/test_inner_staticmethod.py @@ -5,7 +5,7 @@ import wrapt -from compat import exec_, getfullargspec +from compat import getfullargspec DECORATORS_CODE = """ import wrapt @@ -16,7 +16,7 @@ def passthru_decorator(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) class Class(object): @staticmethod diff --git a/tests/test_instancemethod.py b/tests/test_instancemethod.py index 90e13ad7..83a60a3e 100644 --- a/tests/test_instancemethod.py +++ b/tests/test_instancemethod.py @@ -6,7 +6,7 @@ import wrapt -from compat import exec_, getfullargspec +from compat import getfullargspec DECORATORS_CODE = """ import wrapt @@ -17,7 +17,7 @@ def passthru_decorator(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) class OldClass1(): def function(self, arg): diff --git a/tests/test_nested_function.py b/tests/test_nested_function.py index ca65263b..667e14bc 100644 --- a/tests/test_nested_function.py +++ b/tests/test_nested_function.py @@ -5,7 +5,7 @@ import wrapt -from compat import exec_, getfullargspec +from compat import getfullargspec DECORATORS_CODE = """ import wrapt @@ -16,7 +16,7 @@ def passthru_decorator(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) def function1(): def inner(arg): diff --git a/tests/test_object_proxy.py b/tests/test_object_proxy.py index 91a010b3..76c7d8de 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -9,7 +9,7 @@ import wrapt -from compat import PY2, PY3, exec_ +from compat import PY2, PY3 OBJECTS_CODE = """ class TargetBaseClass(object): @@ -24,7 +24,7 @@ def target(): """ objects = types.ModuleType('objects') -exec_(OBJECTS_CODE, objects.__dict__, objects.__dict__) +exec(OBJECTS_CODE, objects.__dict__, objects.__dict__) class TestAttributeAccess(unittest.TestCase): diff --git a/tests/test_outer_classmethod.py b/tests/test_outer_classmethod.py index ab807646..8e6a001c 100644 --- a/tests/test_outer_classmethod.py +++ b/tests/test_outer_classmethod.py @@ -5,7 +5,7 @@ import wrapt -from compat import PYXY, exec_, getfullargspec +from compat import PYXY, getfullargspec DECORATORS_CODE = """ import wrapt @@ -16,7 +16,7 @@ def passthru_decorator(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) class Class(object): @classmethod diff --git a/tests/test_outer_staticmethod.py b/tests/test_outer_staticmethod.py index 959c7ffd..a1609a4b 100644 --- a/tests/test_outer_staticmethod.py +++ b/tests/test_outer_staticmethod.py @@ -5,7 +5,7 @@ import wrapt -from compat import exec_, getfullargspec +from compat import getfullargspec DECORATORS_CODE = """ import wrapt @@ -16,7 +16,7 @@ def passthru_decorator(wrapped, instance, args, kwargs): """ decorators = types.ModuleType('decorators') -exec_(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) +exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) class Class(object): @staticmethod diff --git a/tests/test_update_attributes.py b/tests/test_update_attributes.py index 9850c1b1..e82ca7e5 100644 --- a/tests/test_update_attributes.py +++ b/tests/test_update_attributes.py @@ -4,7 +4,7 @@ import wrapt -from compat import PY2, PY3, exec_ +from compat import PY2, PY3 @wrapt.decorator def passthru_decorator(wrapped, instance, args, kwargs): From ffd3f43ae526d3af592507c739314868d040560a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:10:49 +0100 Subject: [PATCH 04/19] compat: Remove 'string_types' declarations Just use 'str'. Signed-off-by: Stephen Finucane --- src/wrapt/decorators.py | 7 +------ src/wrapt/importer.py | 4 +--- src/wrapt/patches.py | 9 +-------- src/wrapt/wrappers.py | 5 ----- 4 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index dd1c7d6c..4f28ddc0 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -7,11 +7,6 @@ PY2 = sys.version_info[0] == 2 -if PY2: - string_types = basestring, -else: - string_types = str, - from functools import partial from inspect import isclass from threading import Lock, RLock @@ -202,7 +197,7 @@ def _build(wrapped, wrapper, enabled=None, adapter=None): annotations = {} - if not isinstance(adapter, string_types): + if not isinstance(adapter, str): if len(adapter) == 7: annotations = adapter[-1] adapter = adapter[:-1] diff --git a/src/wrapt/importer.py b/src/wrapt/importer.py index 23fcbd2f..d64792ff 100644 --- a/src/wrapt/importer.py +++ b/src/wrapt/importer.py @@ -9,10 +9,8 @@ PY2 = sys.version_info[0] == 2 if PY2: - string_types = basestring, find_spec = None else: - string_types = str, from importlib.util import find_spec from .__wrapt__ import ObjectProxy @@ -49,7 +47,7 @@ def register_post_import_hook(hook, name): # Create a deferred import hook if hook is a string name rather than # a callable function. - if isinstance(hook, string_types): + if isinstance(hook, str): hook = _create_import_hook_from_string(hook) with _post_import_hooks_lock: diff --git a/src/wrapt/patches.py b/src/wrapt/patches.py index e22adf7c..863c368e 100644 --- a/src/wrapt/patches.py +++ b/src/wrapt/patches.py @@ -1,19 +1,12 @@ import inspect import sys -PY2 = sys.version_info[0] == 2 - -if PY2: - string_types = basestring, -else: - string_types = str, - from .__wrapt__ import FunctionWrapper # Helper functions for applying wrappers to existing functions. def resolve_path(module, name): - if isinstance(module, string_types): + if isinstance(module, str): __import__(module) module = sys.modules[module] diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index dfc3440d..133703ca 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -4,11 +4,6 @@ PY2 = sys.version_info[0] == 2 -if PY2: - string_types = basestring, -else: - string_types = str, - def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" return meta("NewBase", bases, {}) From dd812f436aafcce2c6d34520878af3377b806730 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:14:36 +0100 Subject: [PATCH 05/19] compat: Remove PY2 helper Signed-off-by: Stephen Finucane --- src/wrapt/decorators.py | 11 -------- src/wrapt/importer.py | 45 +++++++-------------------------- src/wrapt/wrappers.py | 12 +++------ tests/compat.py | 1 - tests/test_adapter.py | 5 +--- tests/test_adapter_py3.py | 5 ---- tests/test_adapter_py33.py | 5 +--- tests/test_class.py | 2 +- tests/test_class_py37.py | 2 +- tests/test_function_wrapper.py | 2 +- tests/test_object_proxy.py | 2 +- tests/test_post_import_hooks.py | 5 +--- tests/test_update_attributes.py | 2 +- 13 files changed, 21 insertions(+), 78 deletions(-) diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index 4f28ddc0..0df86183 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -5,8 +5,6 @@ import sys -PY2 = sys.version_info[0] == 2 - from functools import partial from inspect import isclass from threading import Lock, RLock @@ -79,9 +77,6 @@ def __signature__(self): else: return signature(self._self_adapter) - if PY2: - func_code = __code__ - func_defaults = __defaults__ class _BoundAdapterWrapper(BoundFunctionWrapper): @@ -97,8 +92,6 @@ def __signature__(self): else: return signature(self._self_parent._self_adapter) - if PY2: - im_func = __func__ class AdapterWrapper(FunctionWrapper): @@ -123,10 +116,6 @@ def __defaults__(self): def __kwdefaults__(self): return self._self_surrogate.__kwdefaults__ - if PY2: - func_code = __code__ - func_defaults = __defaults__ - @property def __signature__(self): return self._self_surrogate.__signature__ diff --git a/src/wrapt/importer.py b/src/wrapt/importer.py index d64792ff..b224231d 100644 --- a/src/wrapt/importer.py +++ b/src/wrapt/importer.py @@ -3,16 +3,10 @@ """ +from importlib.util import find_spec import sys import threading -PY2 = sys.version_info[0] == 2 - -if PY2: - find_spec = None -else: - from importlib.util import find_spec - from .__wrapt__ import ObjectProxy # The dictionary registering any post import hooks to be triggered once @@ -211,33 +205,15 @@ def find_module(self, fullname, path=None): # Now call back into the import system again. try: - if not find_spec: - # For Python 2 we don't have much choice but to - # call back in to __import__(). This will - # actually cause the module to be imported. If no - # module could be found then ImportError will be - # raised. Otherwise we return a loader which - # returns the already loaded module and invokes - # the post import hooks. - - __import__(fullname) - - return _ImportHookLoader() - - else: - # For Python 3 we need to use find_spec().loader - # from the importlib.util module. It doesn't actually - # import the target module and only finds the - # loader. If a loader is found, we need to return - # our own loader which will then in turn call the - # real loader to import the module and invoke the - # post import hooks. - - loader = getattr(find_spec(fullname), "loader", None) - - if loader and not isinstance(loader, _ImportHookChainedLoader): - return _ImportHookChainedLoader(loader) + # Use find_spec().loader from the importlib.util module. It doesn't + # actually import the target module and only finds the loader. If a + # loader is found, we need to return our own loader which will then + # in turn call the real loader to import the module and invoke the + # post import hooks. + loader = getattr(find_spec(fullname), "loader", None) + if loader and not isinstance(loader, _ImportHookChainedLoader): + return _ImportHookChainedLoader(loader) finally: del self.in_progress[fullname] @@ -269,9 +245,6 @@ def find_spec(self, fullname, path=None, target=None): # Now call back into the import system again. try: - # This should only be Python 3 so find_spec() should always - # exist so don't need to check. - spec = find_spec(fullname) loader = getattr(spec, "loader", None) diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index 133703ca..a8c4f8bc 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -2,8 +2,6 @@ import operator import inspect -PY2 = sys.version_info[0] == 2 - def with_metaclass(meta, *bases): """Create a base class with a metaclass.""" return meta("NewBase", bases, {}) @@ -111,9 +109,8 @@ def __dir__(self): def __str__(self): return str(self.__wrapped__) - if not PY2: - def __bytes__(self): - return bytes(self.__wrapped__) + def __bytes__(self): + return bytes(self.__wrapped__) def __repr__(self): return '<{} at 0x{:x} for {} at 0x{:x}>'.format( @@ -124,9 +121,8 @@ def __repr__(self): def __reversed__(self): return reversed(self.__wrapped__) - if not PY2: - def __round__(self): - return round(self.__wrapped__) + def __round__(self): + return round(self.__wrapped__) if sys.hexversion >= 0x03070000: def __mro_entries__(self, bases): diff --git a/tests/compat.py b/tests/compat.py index eaf4eb52..862dff83 100644 --- a/tests/compat.py +++ b/tests/compat.py @@ -1,6 +1,5 @@ import sys -PY2 = sys.version_info[0] < 3 PY3 = sys.version_info[0] >= 3 PYXY = tuple(sys.version_info[:2]) diff --git a/tests/test_adapter.py b/tests/test_adapter.py index aba420ea..b96b2ce7 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -6,7 +6,7 @@ import wrapt -from compat import PY2, getfullargspec +from compat import getfullargspec DECORATORS_CODE = """ import wrapt @@ -88,9 +88,6 @@ def test_signature(self): # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - if PY2: - return - def _adapter(arg1, arg2, arg3=None, *args, **kwargs): pass function1a_signature = str(inspect.signature(_adapter)) diff --git a/tests/test_adapter_py3.py b/tests/test_adapter_py3.py index 6c51925e..6b4e5091 100644 --- a/tests/test_adapter_py3.py +++ b/tests/test_adapter_py3.py @@ -8,8 +8,6 @@ import wrapt -from compat import PY2 - DECORATORS_CODE = """ import wrapt from typing import Iterable @@ -88,9 +86,6 @@ def test_signature(self): # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - if PY2: - return - def _adapter(arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: pass function1a_signature = str(inspect.signature(_adapter)) diff --git a/tests/test_adapter_py33.py b/tests/test_adapter_py33.py index 21117d1d..93845739 100644 --- a/tests/test_adapter_py33.py +++ b/tests/test_adapter_py33.py @@ -6,7 +6,7 @@ import wrapt -from compat import PY2, PY3 +from compat import PY3 DECORATORS_CODE = """ import wrapt @@ -52,9 +52,6 @@ def test_signature(self): # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - if PY2: - return - def _adapter(arg1, arg2, *, arg3=None, **kwargs): pass function1a_signature = str(inspect.signature(_adapter)) diff --git a/tests/test_class.py b/tests/test_class.py index 8e9e1c87..0c9f2561 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -6,7 +6,7 @@ import wrapt -from compat import PY2, PY3 +from compat import PY3 DECORATORS_CODE = """ import wrapt diff --git a/tests/test_class_py37.py b/tests/test_class_py37.py index 878f537a..3ec9ab41 100644 --- a/tests/test_class_py37.py +++ b/tests/test_class_py37.py @@ -6,7 +6,7 @@ import wrapt -from compat import PY2, PY3 +from compat import PY3 class TestInheritance(unittest.TestCase): diff --git a/tests/test_function_wrapper.py b/tests/test_function_wrapper.py index 7a5cb69e..9721fe6f 100644 --- a/tests/test_function_wrapper.py +++ b/tests/test_function_wrapper.py @@ -4,7 +4,7 @@ import wrapt -from compat import PY2, PY3 +from compat import PY3 class TestClassInheritence(unittest.TestCase): diff --git a/tests/test_object_proxy.py b/tests/test_object_proxy.py index 76c7d8de..178cf29d 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -9,7 +9,7 @@ import wrapt -from compat import PY2, PY3 +from compat import PY3 OBJECTS_CODE = """ class TargetBaseClass(object): diff --git a/tests/test_post_import_hooks.py b/tests/test_post_import_hooks.py index 5113e8d2..00afb765 100644 --- a/tests/test_post_import_hooks.py +++ b/tests/test_post_import_hooks.py @@ -7,7 +7,7 @@ import wrapt from wrapt.importer import _post_import_hooks -from compat import PY2, PY3 +from compat import PY3 class TestPostImportHooks(unittest.TestCase): @@ -148,9 +148,6 @@ def test_import_deadlock_3(self): # there is a module import lock per named module and so we do not have # this problem. - if PY2: - return - hooks_called = [] @wrapt.when_imported('this') diff --git a/tests/test_update_attributes.py b/tests/test_update_attributes.py index e82ca7e5..fd63e8f0 100644 --- a/tests/test_update_attributes.py +++ b/tests/test_update_attributes.py @@ -4,7 +4,7 @@ import wrapt -from compat import PY2, PY3 +from compat import PY3 @wrapt.decorator def passthru_decorator(wrapped, instance, args, kwargs): From 9ebc304fb512b793bf93aaf030260b9da5cd19c8 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:15:57 +0100 Subject: [PATCH 06/19] compat: Remove PY3 helper Signed-off-by: Stephen Finucane --- tests/compat.py | 2 -- tests/test_adapter_py33.py | 2 -- tests/test_class.py | 2 -- tests/test_class_py37.py | 1 - tests/test_function_wrapper.py | 2 -- tests/test_object_proxy.py | 30 +++++++++------------------ tests/test_post_import_hooks.py | 1 - tests/test_update_attributes.py | 36 ++++++++------------------------- 8 files changed, 17 insertions(+), 59 deletions(-) diff --git a/tests/compat.py b/tests/compat.py index 862dff83..7d80c152 100644 --- a/tests/compat.py +++ b/tests/compat.py @@ -1,7 +1,5 @@ import sys -PY3 = sys.version_info[0] >= 3 - PYXY = tuple(sys.version_info[:2]) try: diff --git a/tests/test_adapter_py33.py b/tests/test_adapter_py33.py index 93845739..61fd4acf 100644 --- a/tests/test_adapter_py33.py +++ b/tests/test_adapter_py33.py @@ -6,8 +6,6 @@ import wrapt -from compat import PY3 - DECORATORS_CODE = """ import wrapt diff --git a/tests/test_class.py b/tests/test_class.py index 0c9f2561..d8d943b1 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -6,8 +6,6 @@ import wrapt -from compat import PY3 - DECORATORS_CODE = """ import wrapt diff --git a/tests/test_class_py37.py b/tests/test_class_py37.py index 3ec9ab41..142d44e9 100644 --- a/tests/test_class_py37.py +++ b/tests/test_class_py37.py @@ -6,7 +6,6 @@ import wrapt -from compat import PY3 class TestInheritance(unittest.TestCase): diff --git a/tests/test_function_wrapper.py b/tests/test_function_wrapper.py index 9721fe6f..64d000c1 100644 --- a/tests/test_function_wrapper.py +++ b/tests/test_function_wrapper.py @@ -4,8 +4,6 @@ import wrapt -from compat import PY3 - class TestClassInheritence(unittest.TestCase): diff --git a/tests/test_object_proxy.py b/tests/test_object_proxy.py index 178cf29d..7665c0c3 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -9,8 +9,6 @@ import wrapt -from compat import PY3 - OBJECTS_CODE = """ class TargetBaseClass(object): "documentation" @@ -68,9 +66,7 @@ def function1(*args, **kwargs): self.assertEqual(function2, function1) self.assertEqual(function2.__wrapped__, function1) self.assertEqual(function2.__name__, function1.__name__) - - if PY3: - self.assertEqual(function2.__qualname__, function1.__qualname__) + self.assertEqual(function2.__qualname__, function1.__qualname__) function2.__wrapped__ = None @@ -79,9 +75,7 @@ def function1(*args, **kwargs): self.assertEqual(function2, None) self.assertEqual(function2.__wrapped__, None) self.assertFalse(hasattr(function2, '__name__')) - - if PY3: - self.assertFalse(hasattr(function2, '__qualname__')) + self.assertFalse(hasattr(function2, '__qualname__')) def function3(*args, **kwargs): return args, kwargs @@ -91,9 +85,7 @@ def function3(*args, **kwargs): self.assertEqual(function2, function3) self.assertEqual(function2.__wrapped__, function3) self.assertEqual(function2.__name__, function3.__name__) - - if PY3: - self.assertEqual(function2.__qualname__, function3.__qualname__) + self.assertEqual(function2.__qualname__, function3.__qualname__) def test_delete_wrapped(self): def function1(*args, **kwargs): @@ -876,9 +868,6 @@ def test_int(self): self.assertEqual(int(one), 1) - if not PY3: - self.assertEqual(long(one), 1) - def test_float(self): one = wrapt.ObjectProxy(1) @@ -1797,15 +1786,14 @@ def test_callable_proxy_is_callable(self): class SpecialMethods(unittest.TestCase): def test_class_bytes(self): - if PY3: - class Class(object): - def __bytes__(self): - return b'BYTES' - instance = Class() + class Class(object): + def __bytes__(self): + return b'BYTES' + instance = Class() - proxy = wrapt.ObjectProxy(instance) + proxy = wrapt.ObjectProxy(instance) - self.assertEqual(bytes(instance), bytes(proxy)) + self.assertEqual(bytes(instance), bytes(proxy)) def test_str_format(self): instance = 'abcd' diff --git a/tests/test_post_import_hooks.py b/tests/test_post_import_hooks.py index 00afb765..1fab39b2 100644 --- a/tests/test_post_import_hooks.py +++ b/tests/test_post_import_hooks.py @@ -7,7 +7,6 @@ import wrapt from wrapt.importer import _post_import_hooks -from compat import PY3 class TestPostImportHooks(unittest.TestCase): diff --git a/tests/test_update_attributes.py b/tests/test_update_attributes.py index fd63e8f0..f51a7e46 100644 --- a/tests/test_update_attributes.py +++ b/tests/test_update_attributes.py @@ -4,7 +4,6 @@ import wrapt -from compat import PY3 @wrapt.decorator def passthru_decorator(wrapped, instance, args, kwargs): @@ -45,10 +44,9 @@ def test_update_qualname(self): def function(): pass - if PY3: - method = self.test_update_qualname - self.assertEqual(function.__qualname__, - (method.__qualname__ + '..function')) + method = self.test_update_qualname + self.assertEqual(function.__qualname__, + (method.__qualname__ + '..function')) function.__qualname__ = 'override_qualname' @@ -63,10 +61,9 @@ def wrapper(wrapped, instance, args, kwargs): instance = wrapt.FunctionWrapper(function, wrapper) - if PY3: - method = self.test_update_qualname_modified_on_original - self.assertEqual(instance.__qualname__, - (method.__qualname__ + '..function')) + method = self.test_update_qualname_modified_on_original + self.assertEqual(instance.__qualname__, + (method.__qualname__ + '..function')) instance.__qualname__ = 'override_qualname' @@ -134,18 +131,10 @@ def test_update_annotations(self): def function(): pass - if PY3: - self.assertEqual(function.__annotations__, {}) - - else: - def run(*args): - function.__annotations__ - - self.assertRaises(AttributeError, run, ()) + self.assertEqual(function.__annotations__, {}) override_annotations = {'override_annotations': ''} function.__annotations__ = override_annotations - self.assertEqual(function.__wrapped__.__annotations__, override_annotations) self.assertEqual(function.__annotations__, override_annotations) @@ -157,19 +146,10 @@ def wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) instance = wrapt.FunctionWrapper(function, wrapper) - - if PY3: - self.assertEqual(instance.__annotations__, {}) - - else: - def run(*args): - instance.__annotations__ - - self.assertRaises(AttributeError, run, ()) + self.assertEqual(instance.__annotations__, {}) override_annotations = {'override_annotations': ''} instance.__annotations__ = override_annotations - self.assertEqual(function.__annotations__, override_annotations) self.assertEqual(instance.__annotations__, override_annotations) From a483255e4a06f349c5b41f684f767525e5b2512b Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:20:47 +0100 Subject: [PATCH 07/19] compat: Remove getfullargspec wrapper Signed-off-by: Stephen Finucane --- docs/decorators.rst | 16 ++++++------- src/wrapt/arguments.py | 6 ++--- src/wrapt/decorators.py | 5 ++-- tests/compat.py | 5 ---- tests/test_adapter.py | 40 +++++++++++++++----------------- tests/test_adapter_py3.py | 2 +- tests/test_function.py | 8 +++---- tests/test_inner_classmethod.py | 13 +++++------ tests/test_inner_staticmethod.py | 13 +++++------ tests/test_instancemethod.py | 20 +++++++--------- tests/test_nested_function.py | 9 ++++--- tests/test_outer_classmethod.py | 13 ++++++----- tests/test_outer_staticmethod.py | 13 +++++------ 13 files changed, 74 insertions(+), 89 deletions(-) diff --git a/docs/decorators.rst b/docs/decorators.rst index 00eb3865..87c3d5ad 100644 --- a/docs/decorators.rst +++ b/docs/decorators.rst @@ -361,9 +361,9 @@ To obtain the argument specification of a decorated function the standard >>> print(inspect.getargspec(function)) ArgSpec(args=['arg1', 'arg2'], varargs=None, keywords=None, defaults=None) -If using Python 3, the ``getfullargspec()`` or ``signature()`` functions -from the ``inspect`` module can also be used, and would be required to -be used if wanting the result to include any annotations. +The ``getfullargspec()`` or ``signature()`` functions from the ``inspect`` +module can also be used, and would be required to be used if wanting the result +to include any annotations. In other words, applying a decorator created using ``@wrapt.decorator`` to a function is signature preserving and does not result in the loss of the @@ -479,11 +479,11 @@ instead appear. If you need to generate the argument specification based on the function being wrapped dynamically, you can instead pass a tuple of the form which -is returned by ``inspect.getargspec()`` or ``inspect.getfullargspec()``, -or a string of the form which is returned by ``inspect.formatargspec()``. -In these two cases the decorator will automatically compile a stub function -to use as the adapter. This eliminates the need for a caller to generate -the stub function if generating the signature on the fly. +is returned by ``inspect.getfullargspec()``, or a string of the form which is +returned by ``inspect.formatargspec()``. In these two cases the decorator will +automatically compile a stub function to use as the adapter. This eliminates +the need for a caller to generate the stub function if generating the signature +on the fly. Do note though that you should use ``inspect.getfullargspec()`` if wanting to have annotations preserved. In the case of providing the signature as a diff --git a/src/wrapt/arguments.py b/src/wrapt/arguments.py index 032bc059..07bb1152 100644 --- a/src/wrapt/arguments.py +++ b/src/wrapt/arguments.py @@ -1,6 +1,6 @@ # The inspect.formatargspec() function was dropped in Python 3.11 but we need -# need it for when constructing signature changing decorators based on result of -# inspect.getargspec() or inspect.getfullargspec(). The code here implements +# need it for when constructing signature changing decorators based on result +# of inspect.getargspec() or inspect.getfullargspec(). The code here implements # inspect.formatargspec() base on Parameter and Signature from inspect module, # which were added in Python 3.6. Thanks to Cyril Jouve for the implementation. @@ -35,4 +35,4 @@ def formatargspec(args, varargs=None, varkw=None, defaults=None, if varkw: parameters.append(Parameter(varkw, Parameter.VAR_KEYWORD)) return_annotation = annotations.get('return', Signature.empty) - return str(Signature(parameters, return_annotation=return_annotation)) \ No newline at end of file + return str(Signature(parameters, return_annotation=return_annotation)) diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index 0df86183..8b8b6924 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -21,9 +21,8 @@ # Adapter wrapper for the wrapped function which will overlay certain # properties from the adapter function onto the wrapped function so that -# functions such as inspect.getargspec(), inspect.getfullargspec(), -# inspect.signature() and inspect.getsource() return the correct results -# one would expect. +# functions such as inspect.getfullargspec(), inspect.signature() and +# inspect.getsource() return the correct results one would expect. class _AdapterFunctionCode(CallableObjectProxy): diff --git a/tests/compat.py b/tests/compat.py index 7d80c152..f5c7a2c9 100644 --- a/tests/compat.py +++ b/tests/compat.py @@ -1,8 +1,3 @@ import sys PYXY = tuple(sys.version_info[:2]) - -try: - from inspect import getfullargspec -except ImportError: - from inspect import getargspec as getfullargspec diff --git a/tests/test_adapter.py b/tests/test_adapter.py index b96b2ce7..550f0d0d 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -1,13 +1,11 @@ from __future__ import print_function -import unittest import inspect import types +import unittest import wrapt -from compat import getfullargspec - DECORATORS_CODE = """ import wrapt @@ -72,15 +70,15 @@ def test_argspec(self): def _adapter(arg1, arg2, arg3=None, *args, **kwargs): pass - function1a_argspec = getfullargspec(_adapter) - function1d_argspec = getfullargspec(function1d) + function1a_argspec = inspect.getfullargspec(_adapter) + function1d_argspec = inspect.getfullargspec(function1d) self.assertEqual(function1a_argspec, function1d_argspec) # Now bind the function to an instance. The argspec should # still match. bound_function1d = function1d.__get__(object(), object) - bound_function1d_argspec = getfullargspec(bound_function1d) + bound_function1d_argspec = inspect.getfullargspec(bound_function1d) self.assertEqual(function1a_argspec, bound_function1d_argspec) def test_signature(self): @@ -104,7 +102,7 @@ class TestDynamicAdapter(unittest.TestCase): def test_dynamic_adapter_function(self): def _adapter(arg1, arg2, arg3=None, *args, **kwargs): pass - argspec = getfullargspec(_adapter) + argspec = inspect.getfullargspec(_adapter) @wrapt.decorator(adapter=argspec) def _wrapper_1(wrapped, instance, args, kwargs): @@ -114,7 +112,7 @@ def _wrapper_1(wrapped, instance, args, kwargs): def _function_1(): pass - self.assertEqual(getfullargspec(_function_1), argspec) + self.assertEqual(inspect.getfullargspec(_function_1), argspec) args = '(arg1, arg2, arg3=None, *args, **kwargs)' @@ -126,12 +124,12 @@ def _wrapper_2(wrapped, instance, args, kwargs): def _function_2(): pass - self.assertEqual(getfullargspec(_function_2), argspec) + self.assertEqual(inspect.getfullargspec(_function_2), argspec) def test_dynamic_adapter_instancemethod(self): def _adapter(self, arg1, arg2, arg3=None, *args, **kwargs): pass - argspec = getfullargspec(_adapter) + argspec = inspect.getfullargspec(_adapter) @wrapt.decorator(adapter=argspec) def _wrapper_1(wrapped, instance, args, kwargs): @@ -144,8 +142,8 @@ def function(self): instance1 = Class1() - self.assertEqual(getfullargspec(Class1.function), argspec) - self.assertEqual(getfullargspec(instance1.function), argspec) + self.assertEqual(inspect.getfullargspec(Class1.function), argspec) + self.assertEqual(inspect.getfullargspec(instance1.function), argspec) args = '(self, arg1, arg2, arg3=None, *args, **kwargs)' @@ -160,13 +158,13 @@ def function(self): instance2 = Class2() - self.assertEqual(getfullargspec(Class2.function), argspec) - self.assertEqual(getfullargspec(instance2.function), argspec) + self.assertEqual(inspect.getfullargspec(Class2.function), argspec) + self.assertEqual(inspect.getfullargspec(instance2.function), argspec) def test_dynamic_adapter_classmethod(self): def _adapter(cls, arg1, arg2, arg3=None, *args, **kwargs): pass - argspec = getfullargspec(_adapter) + argspec = inspect.getfullargspec(_adapter) @wrapt.decorator(adapter=argspec) def _wrapper_1(wrapped, instance, args, kwargs): @@ -180,8 +178,8 @@ def function(cls): instance1 = Class1() - self.assertEqual(getfullargspec(Class1.function), argspec) - self.assertEqual(getfullargspec(instance1.function), argspec) + self.assertEqual(inspect.getfullargspec(Class1.function), argspec) + self.assertEqual(inspect.getfullargspec(instance1.function), argspec) args = '(cls, arg1, arg2, arg3=None, *args, **kwargs)' @@ -197,12 +195,12 @@ def function(self): instance2 = Class2() - self.assertEqual(getfullargspec(Class2.function), argspec) - self.assertEqual(getfullargspec(instance2.function), argspec) + self.assertEqual(inspect.getfullargspec(Class2.function), argspec) + self.assertEqual(inspect.getfullargspec(instance2.function), argspec) def test_adapter_factory(self): def factory(wrapped): - argspec = getfullargspec(wrapped) + argspec = inspect.getfullargspec(wrapped) argspec.args.insert(0, 'arg0') return argspec @@ -214,7 +212,7 @@ def _wrapper_1(wrapped, instance, args, kwargs): def _function_1(arg1, arg2): pass - argspec = getfullargspec(_function_1) + argspec = inspect.getfullargspec(_function_1) self.assertEqual(argspec.args, ['arg0', 'arg1', 'arg2']) diff --git a/tests/test_adapter_py3.py b/tests/test_adapter_py3.py index 6b4e5091..e4839e8f 100644 --- a/tests/test_adapter_py3.py +++ b/tests/test_adapter_py3.py @@ -1,8 +1,8 @@ from __future__ import print_function import inspect -import unittest import types +import unittest from typing import Iterable diff --git a/tests/test_function.py b/tests/test_function.py index 7da01b95..0fed4ac6 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -1,13 +1,11 @@ from __future__ import print_function -import unittest import inspect import types +import unittest import wrapt -from compat import getfullargspec - DECORATORS_CODE = """ import wrapt @@ -57,8 +55,8 @@ def test_doc_string(self): def test_argspec(self): # Test preservation of function argument specification. - function1o_argspec = getfullargspec(function1o) - function1d_argspec = getfullargspec(function1d) + function1o_argspec = inspect.getfullargspec(function1o) + function1d_argspec = inspect.getfullargspec(function1d) self.assertEqual(function1o_argspec, function1d_argspec) def test_getmembers(self): diff --git a/tests/test_inner_classmethod.py b/tests/test_inner_classmethod.py index 5a642f88..ed6c04ad 100644 --- a/tests/test_inner_classmethod.py +++ b/tests/test_inner_classmethod.py @@ -1,12 +1,11 @@ from __future__ import print_function -import unittest +import inspect import types +import unittest import wrapt -from compat import getfullargspec - DECORATORS_CODE = """ import wrapt @@ -94,15 +93,15 @@ def test_instance_doc_string(self): def test_class_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(Original.function) - function_argspec = getfullargspec(Class.function) + original_argspec = inspect.getfullargspec(Original.function) + function_argspec = inspect.getfullargspec(Class.function) self.assertEqual(original_argspec, function_argspec) def test_instance_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(Original().function) - function_argspec = getfullargspec(Class().function) + original_argspec = inspect.getfullargspec(Original().function) + function_argspec = inspect.getfullargspec(Class().function) self.assertEqual(original_argspec, function_argspec) def test_class_isinstance(self): diff --git a/tests/test_inner_staticmethod.py b/tests/test_inner_staticmethod.py index 706d9520..8cd84a30 100644 --- a/tests/test_inner_staticmethod.py +++ b/tests/test_inner_staticmethod.py @@ -1,12 +1,11 @@ from __future__ import print_function -import unittest +import inspect import types +import unittest import wrapt -from compat import getfullargspec - DECORATORS_CODE = """ import wrapt @@ -94,15 +93,15 @@ def test_instance_doc_string(self): def test_class_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(Original.function) - function_argspec = getfullargspec(Class.function) + original_argspec = inspect.getfullargspec(Original.function) + function_argspec = inspect.getfullargspec(Class.function) self.assertEqual(original_argspec, function_argspec) def test_instance_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(Original().function) - function_argspec = getfullargspec(Class().function) + original_argspec = inspect.getfullargspec(Original().function) + function_argspec = inspect.getfullargspec(Class().function) self.assertEqual(original_argspec, function_argspec) def test_class_isinstance(self): diff --git a/tests/test_instancemethod.py b/tests/test_instancemethod.py index 83a60a3e..c8d5232c 100644 --- a/tests/test_instancemethod.py +++ b/tests/test_instancemethod.py @@ -1,13 +1,11 @@ from __future__ import print_function -import unittest import inspect import types +import unittest import wrapt -from compat import getfullargspec - DECORATORS_CODE = """ import wrapt @@ -95,15 +93,15 @@ def test_instance_doc_string(self): def test_class_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(OldClass1o.function) - function_argspec = getfullargspec(OldClass1d.function) + original_argspec = inspect.getfullargspec(OldClass1o.function) + function_argspec = inspect.getfullargspec(OldClass1d.function) self.assertEqual(original_argspec, function_argspec) def test_instance_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(OldClass1o().function) - function_argspec = getfullargspec(OldClass1d().function) + original_argspec = inspect.getfullargspec(OldClass1o().function) + function_argspec = inspect.getfullargspec(OldClass1d().function) self.assertEqual(original_argspec, function_argspec) def test_getmembers(self): @@ -198,15 +196,15 @@ def test_instance_doc_string(self): def test_class_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(NewClass1o.function) - function_argspec = getfullargspec(NewClass1d.function) + original_argspec = inspect.getfullargspec(NewClass1o.function) + function_argspec = inspect.getfullargspec(NewClass1d.function) self.assertEqual(original_argspec, function_argspec) def test_instance_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(NewClass1o().function) - function_argspec = getfullargspec(NewClass1d().function) + original_argspec = inspect.getfullargspec(NewClass1o().function) + function_argspec = inspect.getfullargspec(NewClass1d().function) self.assertEqual(original_argspec, function_argspec) def test_class_isinstance(self): diff --git a/tests/test_nested_function.py b/tests/test_nested_function.py index 667e14bc..794224b4 100644 --- a/tests/test_nested_function.py +++ b/tests/test_nested_function.py @@ -1,12 +1,11 @@ from __future__ import print_function -import unittest +import inspect import types +import unittest import wrapt -from compat import getfullargspec - DECORATORS_CODE = """ import wrapt @@ -65,8 +64,8 @@ def test_doc_string(self): def test_argspec(self): # Test preservation of function argument specification. - function1o_argspec = getfullargspec(function1o()) - function1d_argspec = getfullargspec(function1d()) + function1o_argspec = inspect.getfullargspec(function1o()) + function1d_argspec = inspect.getfullargspec(function1d()) self.assertEqual(function1o_argspec, function1d_argspec) def test_isinstance(self): diff --git a/tests/test_outer_classmethod.py b/tests/test_outer_classmethod.py index 8e6a001c..84897f6a 100644 --- a/tests/test_outer_classmethod.py +++ b/tests/test_outer_classmethod.py @@ -1,11 +1,12 @@ from __future__ import print_function -import unittest +import inspect import types +import unittest import wrapt -from compat import PYXY, getfullargspec +from compat import PYXY DECORATORS_CODE = """ import wrapt @@ -94,15 +95,15 @@ def test_instance_doc_string(self): def test_class_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(Original.function) - function_argspec = getfullargspec(Class.function) + original_argspec = inspect.getfullargspec(Original.function) + function_argspec = inspect.getfullargspec(Class.function) self.assertEqual(original_argspec, function_argspec) def test_instance_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(Original().function) - function_argspec = getfullargspec(Class().function) + original_argspec = inspect.getfullargspec(Original().function) + function_argspec = inspect.getfullargspec(Class().function) self.assertEqual(original_argspec, function_argspec) def test_class_isinstance(self): diff --git a/tests/test_outer_staticmethod.py b/tests/test_outer_staticmethod.py index a1609a4b..bf221978 100644 --- a/tests/test_outer_staticmethod.py +++ b/tests/test_outer_staticmethod.py @@ -1,12 +1,11 @@ from __future__ import print_function -import unittest +import inspect import types +import unittest import wrapt -from compat import getfullargspec - DECORATORS_CODE = """ import wrapt @@ -94,15 +93,15 @@ def test_instance_doc_string(self): def test_class_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(Original.function) - function_argspec = getfullargspec(Class.function) + original_argspec = inspect.getfullargspec(Original.function) + function_argspec = inspect.getfullargspec(Class.function) self.assertEqual(original_argspec, function_argspec) def test_instance_argspec(self): # Test preservation of instance method argument specification. - original_argspec = getfullargspec(Original().function) - function_argspec = getfullargspec(Class().function) + original_argspec = inspect.getfullargspec(Original().function) + function_argspec = inspect.getfullargspec(Class().function) self.assertEqual(original_argspec, function_argspec) def test_class_isinstance(self): From 4b214f1a61dd3c635db9a981862634bbd35c7ba1 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:29:48 +0100 Subject: [PATCH 08/19] Remove final unnecessary users of sys.version_info Signed-off-by: Stephen Finucane --- setup.py | 8 ++------ src/wrapt/wrappers.py | 3 --- tests/conftest.py | 12 ------------ tests/test_formatargspec_py35.py | 10 +++------- tests/test_post_import_hooks.py | 10 +++------- 5 files changed, 8 insertions(+), 35 deletions(-) diff --git a/setup.py b/setup.py index 77262b2f..df496748 100644 --- a/setup.py +++ b/setup.py @@ -15,12 +15,8 @@ disable_extensions = wrapt_env.lower() == 'false' force_extensions = wrapt_env.lower() == 'true' else: - if platform.system() == 'Windows' and sys.version_info[0] < 3: - disable_extensions = True - force_extensions = False - else: - disable_extensions = False - force_extensions = False + disable_extensions = False + force_extensions = False if platform.python_implementation() != "CPython": disable_extensions = True diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index a8c4f8bc..fa6bdf5f 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -369,9 +369,6 @@ def __invert__(self): def __int__(self): return int(self.__wrapped__) - def __long__(self): - return long(self.__wrapped__) - def __float__(self): return float(self.__wrapped__) diff --git a/tests/conftest.py b/tests/conftest.py index 318d2263..13f7c38d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,18 +19,6 @@ def construct_dummy(path, parent): return DummyCollector(path, parent=parent) def pytest_pycollect_makemodule(path, parent): - if '_py33' in path.basename and version < (3, 3): - return construct_dummy(path, parent) - if '_py34' in path.basename and version < (3, 4): - return construct_dummy(path, parent) - if '_py35' in path.basename and version < (3, 5): - return construct_dummy(path, parent) - if '_py36' in path.basename and version < (3, 6): - return construct_dummy(path, parent) - if '_py37' in path.basename and version < (3, 7): - return construct_dummy(path, parent) - if '_py38' in path.basename and version < (3, 8): - return construct_dummy(path, parent) if '_py39' in path.basename and version < (3, 9): return construct_dummy(path, parent) if '_py310' in path.basename and version < (3, 10): diff --git a/tests/test_formatargspec_py35.py b/tests/test_formatargspec_py35.py index 6e47507e..2ae58fcb 100644 --- a/tests/test_formatargspec_py35.py +++ b/tests/test_formatargspec_py35.py @@ -1,13 +1,12 @@ +import inspect import unittest -import sys -from inspect import getfullargspec from wrapt import formatargspec class TestFormatargspec35(unittest.TestCase): def assertFormatEqual(self, func, ref): - formatted = formatargspec(*getfullargspec(func)) + formatted = formatargspec(*inspect.getfullargspec(func)) self.assertEqual(formatted, ref) def test_formatargspec(self): @@ -21,10 +20,7 @@ def foo3(a, b, *args, **kwargs): pass self.assertFormatEqual(foo3, '(a, b, *args, **kwargs)') def foo4(a: int, b) -> list: pass - if sys.version_info[:2] < (3, 7): - formatted4 = '(a:int, b) -> list' - else: - formatted4 = '(a: int, b) -> list' + formatted4 = '(a: int, b) -> list' self.assertFormatEqual(foo4, formatted4) # examples from https://www.python.org/dev/peps/pep-3102/ diff --git a/tests/test_post_import_hooks.py b/tests/test_post_import_hooks.py index 1fab39b2..e10dd649 100644 --- a/tests/test_post_import_hooks.py +++ b/tests/test_post_import_hooks.py @@ -180,13 +180,9 @@ def hook_this(module): import this - if sys.version_info[:2] >= (3, 3): - from importlib.machinery import SourceFileLoader - self.assertIsInstance(this.__loader__, SourceFileLoader) - self.assertIsInstance(this.__spec__.loader, SourceFileLoader) - - else: - self.assertEqual(hasattr(this, "__loader__"), False) + from importlib.machinery import SourceFileLoader + self.assertIsInstance(this.__loader__, SourceFileLoader) + self.assertIsInstance(this.__spec__.loader, SourceFileLoader) if __name__ == '__main__': unittest.main() From bd35246c3a2260df5cc95b8a3926a6a8b3cdb504 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:27:33 +0100 Subject: [PATCH 09/19] Remove __future__.print_function imports This is not necessary in Python 3-only code. Signed-off-by: Stephen Finucane --- blog/14-automatic-patching-of-python-applications.md | 2 -- tests/test_adapter.py | 2 -- tests/test_adapter_py3.py | 2 -- tests/test_adapter_py33.py | 4 +--- tests/test_arguments.py | 2 -- tests/test_attribute_wrapper.py | 2 -- tests/test_callable_object_proxy.py | 2 -- tests/test_class.py | 4 +--- tests/test_class_py37.py | 4 ---- tests/test_copy.py | 5 +---- tests/test_decorators.py | 2 -- tests/test_descriptors_py36.py | 2 -- tests/test_function.py | 2 -- tests/test_function_wrapper.py | 2 -- tests/test_inheritance_py37.py | 5 +---- tests/test_inner_classmethod.py | 2 -- tests/test_inner_staticmethod.py | 2 -- tests/test_instancemethod.py | 2 -- tests/test_memoize.py | 5 +---- tests/test_monkey_patching.py | 4 +--- tests/test_nested_function.py | 2 -- tests/test_object_proxy.py | 8 +++----- tests/test_outer_classmethod.py | 2 -- tests/test_outer_staticmethod.py | 2 -- tests/test_pickle.py | 5 +---- tests/test_post_import_hooks.py | 4 +--- tests/test_synchronized_lock.py | 2 -- tests/test_update_attributes.py | 2 -- tests/test_weak_function_proxy.py | 2 -- 29 files changed, 11 insertions(+), 75 deletions(-) diff --git a/blog/14-automatic-patching-of-python-applications.md b/blog/14-automatic-patching-of-python-applications.md index c3034cd4..5abc518f 100644 --- a/blog/14-automatic-patching-of-python-applications.md +++ b/blog/14-automatic-patching-of-python-applications.md @@ -370,8 +370,6 @@ name of the entry point defined in the setup.py file for autowrapt. The actual code for the `autowrapt_this()` function was: ```python -from __future__ import print_function - def autowrapt_this(module): print('The wrapt package is absolutely amazing and you should use it.') ``` diff --git a/tests/test_adapter.py b/tests/test_adapter.py index 550f0d0d..6b90bf12 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_adapter_py3.py b/tests/test_adapter_py3.py index e4839e8f..bb208d61 100644 --- a/tests/test_adapter_py3.py +++ b/tests/test_adapter_py3.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_adapter_py33.py b/tests/test_adapter_py33.py index 61fd4acf..edd7fba7 100644 --- a/tests/test_adapter_py33.py +++ b/tests/test_adapter_py33.py @@ -1,8 +1,6 @@ -from __future__ import print_function - -import unittest import inspect import types +import unittest import wrapt diff --git a/tests/test_arguments.py b/tests/test_arguments.py index 0b7379d3..274d9393 100644 --- a/tests/test_arguments.py +++ b/tests/test_arguments.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import wrapt diff --git a/tests/test_attribute_wrapper.py b/tests/test_attribute_wrapper.py index f68315aa..6fcd5f25 100644 --- a/tests/test_attribute_wrapper.py +++ b/tests/test_attribute_wrapper.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import wrapt diff --git a/tests/test_callable_object_proxy.py b/tests/test_callable_object_proxy.py index 5421a06a..e9b5a7f9 100644 --- a/tests/test_callable_object_proxy.py +++ b/tests/test_callable_object_proxy.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import wrapt diff --git a/tests/test_class.py b/tests/test_class.py index d8d943b1..801e24c8 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -1,8 +1,6 @@ -from __future__ import print_function - -import unittest import inspect import types +import unittest import wrapt diff --git a/tests/test_class_py37.py b/tests/test_class_py37.py index 142d44e9..af98fd45 100644 --- a/tests/test_class_py37.py +++ b/tests/test_class_py37.py @@ -1,8 +1,4 @@ -from __future__ import print_function - import unittest -import inspect -import types import wrapt diff --git a/tests/test_copy.py b/tests/test_copy.py index cbce9280..5b36bbde 100644 --- a/tests/test_copy.py +++ b/tests/test_copy.py @@ -1,8 +1,5 @@ -from __future__ import print_function - -import unittest - import copy +import unittest import wrapt diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 2213abc9..844f6308 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import wrapt diff --git a/tests/test_descriptors_py36.py b/tests/test_descriptors_py36.py index 2b51a740..4896efd3 100644 --- a/tests/test_descriptors_py36.py +++ b/tests/test_descriptors_py36.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import wrapt diff --git a/tests/test_function.py b/tests/test_function.py index 0fed4ac6..aa29243f 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_function_wrapper.py b/tests/test_function_wrapper.py index 64d000c1..f9b28010 100644 --- a/tests/test_function_wrapper.py +++ b/tests/test_function_wrapper.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import wrapt diff --git a/tests/test_inheritance_py37.py b/tests/test_inheritance_py37.py index 755b5990..de3c24b2 100644 --- a/tests/test_inheritance_py37.py +++ b/tests/test_inheritance_py37.py @@ -1,9 +1,6 @@ -from __future__ import print_function - -import unittest - import abc import _py_abc +import unittest import wrapt diff --git a/tests/test_inner_classmethod.py b/tests/test_inner_classmethod.py index ed6c04ad..0d29c0b8 100644 --- a/tests/test_inner_classmethod.py +++ b/tests/test_inner_classmethod.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_inner_staticmethod.py b/tests/test_inner_staticmethod.py index 8cd84a30..f10f01df 100644 --- a/tests/test_inner_staticmethod.py +++ b/tests/test_inner_staticmethod.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_instancemethod.py b/tests/test_instancemethod.py index c8d5232c..f7ad05ca 100644 --- a/tests/test_instancemethod.py +++ b/tests/test_instancemethod.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_memoize.py b/tests/test_memoize.py index 27d3f5d2..ae8acfd8 100644 --- a/tests/test_memoize.py +++ b/tests/test_memoize.py @@ -1,8 +1,5 @@ -from __future__ import print_function - -import unittest -import threading import inspect +import unittest import wrapt diff --git a/tests/test_monkey_patching.py b/tests/test_monkey_patching.py index d640f5c7..c341d749 100644 --- a/tests/test_monkey_patching.py +++ b/tests/test_monkey_patching.py @@ -1,7 +1,5 @@ -from __future__ import print_function - -import unittest import sys +import unittest import wrapt diff --git a/tests/test_nested_function.py b/tests/test_nested_function.py index 794224b4..5a608a0c 100644 --- a/tests/test_nested_function.py +++ b/tests/test_nested_function.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_object_proxy.py b/tests/test_object_proxy.py index 7665c0c3..1edf062b 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -1,9 +1,7 @@ -from __future__ import print_function - -import unittest -import types -import sys import re +import sys +import types +import unittest is_pypy = '__pypy__' in sys.builtin_module_names diff --git a/tests/test_outer_classmethod.py b/tests/test_outer_classmethod.py index 84897f6a..3cc9ce90 100644 --- a/tests/test_outer_classmethod.py +++ b/tests/test_outer_classmethod.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_outer_staticmethod.py b/tests/test_outer_staticmethod.py index bf221978..60dfe0b9 100644 --- a/tests/test_outer_staticmethod.py +++ b/tests/test_outer_staticmethod.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import inspect import types import unittest diff --git a/tests/test_pickle.py b/tests/test_pickle.py index 41e91044..291c747c 100644 --- a/tests/test_pickle.py +++ b/tests/test_pickle.py @@ -1,8 +1,5 @@ -from __future__ import print_function - -import unittest - import pickle +import unittest import wrapt diff --git a/tests/test_post_import_hooks.py b/tests/test_post_import_hooks.py index e10dd649..6e2c741f 100644 --- a/tests/test_post_import_hooks.py +++ b/tests/test_post_import_hooks.py @@ -1,8 +1,6 @@ -from __future__ import print_function - -import unittest import sys import threading +import unittest import wrapt from wrapt.importer import _post_import_hooks diff --git a/tests/test_synchronized_lock.py b/tests/test_synchronized_lock.py index 0e43f7af..f98b3873 100644 --- a/tests/test_synchronized_lock.py +++ b/tests/test_synchronized_lock.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import wrapt diff --git a/tests/test_update_attributes.py b/tests/test_update_attributes.py index f51a7e46..b21fc244 100644 --- a/tests/test_update_attributes.py +++ b/tests/test_update_attributes.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import wrapt diff --git a/tests/test_weak_function_proxy.py b/tests/test_weak_function_proxy.py index 2babe95c..c3718a30 100644 --- a/tests/test_weak_function_proxy.py +++ b/tests/test_weak_function_proxy.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import unittest import gc From 7353e5165735910b2794bf935182b85fef671591 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 13:14:34 +0100 Subject: [PATCH 10/19] Remove custom metaclass wrapper Another py2/py3 diff. Signed-off-by: Stephen Finucane --- src/wrapt/wrappers.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index fa6bdf5f..c6f594ca 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -2,9 +2,6 @@ import operator import inspect -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) class _ObjectProxyMethods(object): @@ -49,6 +46,7 @@ def __dict__(self): def __weakref__(self): return self.__wrapped__.__weakref__ + class _ObjectProxyMetaType(type): def __new__(cls, name, bases, dictionary): # Copy our special properties into the class so that they @@ -60,8 +58,11 @@ def __new__(cls, name, bases, dictionary): return type.__new__(cls, name, bases, dictionary) -class ObjectProxy(with_metaclass(_ObjectProxyMetaType)): +class _ObjectProxyBase(metaclass=_ObjectProxyMetaType): ... + + +class ObjectProxy(_ObjectProxyBase): __slots__ = '__wrapped__' def __init__(self, wrapped): From 27d146965b980391fb1d85615832e2e955b1b76d Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 13:45:29 +0100 Subject: [PATCH 11/19] Remove unnecessary import guards Signed-off-by: Stephen Finucane --- src/wrapt/__wrapt__.py | 11 -------- src/wrapt/arguments.py | 62 ++++++++++++++++++++--------------------- src/wrapt/decorators.py | 7 +---- tests/conftest.py | 5 +--- 4 files changed, 32 insertions(+), 53 deletions(-) diff --git a/src/wrapt/__wrapt__.py b/src/wrapt/__wrapt__.py index 9933b2c9..cae9006b 100644 --- a/src/wrapt/__wrapt__.py +++ b/src/wrapt/__wrapt__.py @@ -1,14 +1,3 @@ -import os - from .wrappers import (ObjectProxy, CallableObjectProxy, PartialCallableObjectProxy, FunctionWrapper, BoundFunctionWrapper, _FunctionWrapperBase) - -try: - if not os.environ.get('WRAPT_DISABLE_EXTENSIONS'): - from ._wrappers import (ObjectProxy, CallableObjectProxy, - PartialCallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, _FunctionWrapperBase) - -except ImportError: - pass diff --git a/src/wrapt/arguments.py b/src/wrapt/arguments.py index 07bb1152..c433174a 100644 --- a/src/wrapt/arguments.py +++ b/src/wrapt/arguments.py @@ -4,35 +4,33 @@ # inspect.formatargspec() base on Parameter and Signature from inspect module, # which were added in Python 3.6. Thanks to Cyril Jouve for the implementation. -try: - from inspect import Parameter, Signature -except ImportError: - from inspect import formatargspec -else: - def formatargspec(args, varargs=None, varkw=None, defaults=None, - kwonlyargs=(), kwonlydefaults={}, annotations={}): - if kwonlydefaults is None: - kwonlydefaults = {} - ndefaults = len(defaults) if defaults else 0 - parameters = [ - Parameter( - arg, - Parameter.POSITIONAL_OR_KEYWORD, - default=defaults[i] if i >= 0 else Parameter.empty, - annotation=annotations.get(arg, Parameter.empty), - ) for i, arg in enumerate(args, ndefaults - len(args)) - ] - if varargs: - parameters.append(Parameter(varargs, Parameter.VAR_POSITIONAL)) - parameters.extend( - Parameter( - kwonlyarg, - Parameter.KEYWORD_ONLY, - default=kwonlydefaults.get(kwonlyarg, Parameter.empty), - annotation=annotations.get(kwonlyarg, Parameter.empty), - ) for kwonlyarg in kwonlyargs - ) - if varkw: - parameters.append(Parameter(varkw, Parameter.VAR_KEYWORD)) - return_annotation = annotations.get('return', Signature.empty) - return str(Signature(parameters, return_annotation=return_annotation)) +from inspect import Parameter, Signature + + +def formatargspec(args, varargs=None, varkw=None, defaults=None, + kwonlyargs=(), kwonlydefaults={}, annotations={}): + if kwonlydefaults is None: + kwonlydefaults = {} + ndefaults = len(defaults) if defaults else 0 + parameters = [ + Parameter( + arg, + Parameter.POSITIONAL_OR_KEYWORD, + default=defaults[i] if i >= 0 else Parameter.empty, + annotation=annotations.get(arg, Parameter.empty), + ) for i, arg in enumerate(args, ndefaults - len(args)) + ] + if varargs: + parameters.append(Parameter(varargs, Parameter.VAR_POSITIONAL)) + parameters.extend( + Parameter( + kwonlyarg, + Parameter.KEYWORD_ONLY, + default=kwonlydefaults.get(kwonlyarg, Parameter.empty), + annotation=annotations.get(kwonlyarg, Parameter.empty), + ) for kwonlyarg in kwonlyargs + ) + if varkw: + parameters.append(Parameter(varkw, Parameter.VAR_KEYWORD)) + return_annotation = annotations.get('return', Signature.empty) + return str(Signature(parameters, return_annotation=return_annotation)) diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index 8b8b6924..02a6819a 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -6,16 +6,11 @@ import sys from functools import partial -from inspect import isclass +from inspect import isclass, signature from threading import Lock, RLock from .arguments import formatargspec -try: - from inspect import signature -except ImportError: - pass - from .__wrapt__ import (FunctionWrapper, BoundFunctionWrapper, ObjectProxy, CallableObjectProxy) diff --git a/tests/conftest.py b/tests/conftest.py index 13f7c38d..ef192d27 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,6 @@ import sys -try: - from pytest import File as FileCollector -except ImportError: - from pytest.collect import File as FileCollector +from pytest import File as FileCollector version = tuple(sys.version_info[:2]) From 3bd5bacad4ab030f84d329bee6242c272decdd7d Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:46:10 +0100 Subject: [PATCH 12/19] Integrate pre-commit For running linters. Only a minimal configuration is enabled for now. Signed-off-by: Stephen Finucane --- .pre-commit-config.yaml | 15 +++++++++++++++ README.rst | 4 ++-- docs/changes.rst | 4 ++-- docs/index.rst | 2 +- docs/quick-start.rst | 4 ++-- docs/wrappers.rst | 12 ++++++------ src/wrapt/_wrappers.c | 2 +- src/wrapt/wrappers.py | 2 +- tests/test_post_import_hooks.py | 2 +- tox.ini | 25 +++++++++++++++++-------- 10 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..0f6bdbd3 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,15 @@ +--- +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: trailing-whitespace + - id: mixed-line-ending + args: ['--fix', 'lf'] + exclude: '.*\.(svg)$' + - id: check-byte-order-marker + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: debug-statements + - id: check-yaml + files: .*\.(yaml|yml)$ diff --git a/README.rst b/README.rst index af0d61c7..f1d0db49 100644 --- a/README.rst +++ b/README.rst @@ -49,7 +49,7 @@ other functions. .. code-block:: python import wrapt - + @wrapt.decorator def pass_through(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @@ -98,7 +98,7 @@ The above rules can be summarised with the following example. .. code-block:: python import inspect - + @wrapt.decorator def universal(wrapped, instance, args, kwargs): if instance is None: diff --git a/docs/changes.rst b/docs/changes.rst index ecd7f39c..df663639 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -299,7 +299,7 @@ Version 1.11.0 result in an exception being raised to indicate that a proxy object had not been initialised when in fact the argument wasn't even an instance of a proxy object. - + Because an incorrect cast in C level code was being performed and an attribute in memory checked on the basis of it being a type different to what it actually was, technically it may have resulted in a process @@ -574,7 +574,7 @@ Version 1.10.0 * The ``inspect.signature()`` function was only added in Python 3.3. Use fallback when doesn't exist and on Python 3.2 or earlier Python 3 versions. - + Note that testing is only performed for Python 3.3+, so it isn't actually known if the ``wrapt`` package works on Python 3.2. diff --git a/docs/index.rst b/docs/index.rst index a9ec9ba3..c2e72ef3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -75,7 +75,7 @@ Blog Posts Blog posts related to the **wrapt** module: -* https://github.com/GrahamDumpleton/wrapt/tree/master/blog +* https://github.com/GrahamDumpleton/wrapt/tree/master/blog Installation ------------ diff --git a/docs/quick-start.rst b/docs/quick-start.rst index c9c61b65..ebcba7b6 100644 --- a/docs/quick-start.rst +++ b/docs/quick-start.rst @@ -21,7 +21,7 @@ other functions. :: import wrapt - + @wrapt.decorator def pass_through(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @@ -70,7 +70,7 @@ The above rules can be summarised with the following example. :: import inspect - + @wrapt.decorator def universal(wrapped, instance, args, kwargs): if instance is None: diff --git a/docs/wrappers.rst b/docs/wrappers.rst index dc940e4f..3d5735da 100644 --- a/docs/wrappers.rst +++ b/docs/wrappers.rst @@ -157,7 +157,7 @@ some specific behaviour of the proxy. def function(): print('executing', function.__name__) - + class CallableWrapper(wrapt.ObjectProxy): def __call__(self, *args, **kwargs): @@ -208,7 +208,7 @@ change will also be reflected in the wrapped object. >>> function.attribute 1 - >>> proxy.attribute + >>> proxy.attribute 1 If an attribute was updated on the wrapped object directly, that change is @@ -247,7 +247,7 @@ be prefixed with ``_self_``. return wrapped(*args, **kwargs) finally: print('exiting', wrapped.__name__) - + >>> proxy = CallableWrapper(function, wrapper) >>> proxy._self_wrapper @@ -281,11 +281,11 @@ definition. @attribute.deleter def attribute(self): del self._self_attribute - + >>> proxy = CustomProxy(1) >>> print proxy.attribute 1 - >>> proxy.attribute = 2 + >>> proxy.attribute = 2 >>> print proxy.attribute 2 >>> del proxy.attribute @@ -405,7 +405,7 @@ The above rules can be summarised with the following example. :: import inspect - + def wrapper(wrapped, instance, args, kwargs): if instance is None: if inspect.isclass(wrapped): diff --git a/src/wrapt/_wrappers.c b/src/wrapt/_wrappers.c index e0e1b5bc..031f88d5 100644 --- a/src/wrapt/_wrappers.c +++ b/src/wrapt/_wrappers.c @@ -2845,7 +2845,7 @@ static PyObject *WraptBoundFunctionWrapper_call( #endif } - /* + /* * We need to do things different depending on whether we are likely * wrapping an instance method vs a static method or class method. */ diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index c6f594ca..afc08ee9 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -468,7 +468,7 @@ def _unpack_self(self, *args): return self, args self, args = _unpack_self(*args) - + _args = self._self_args + args _kwargs = dict(self._self_kwargs) diff --git a/tests/test_post_import_hooks.py b/tests/test_post_import_hooks.py index 6e2c741f..00e8f5ee 100644 --- a/tests/test_post_import_hooks.py +++ b/tests/test_post_import_hooks.py @@ -152,7 +152,7 @@ def hook_this(module): hooks_called.append('this') self.assertFalse('wsgiref' in sys.modules) - + @wrapt.when_imported('wsgiref') def hook_wsgiref(module): hooks_called.append('wsgiref') diff --git a/tox.ini b/tox.ini index edd3fa73..1a3d71d1 100644 --- a/tox.ini +++ b/tox.ini @@ -13,13 +13,22 @@ deps = commands = python -m coverage run --rcfile {toxinidir}/setup.cfg -m pytest -v {posargs} {toxinidir}/tests +[testenv:lint] +description = + Run style checks. +skip_install = true +deps = + pre-commit +commands = + pre-commit run --all-files --show-diff-on-failure + [gh-actions] python = - 3.8: py38, py38-without-extensions, py38-install-extensions, py38-disable-extensions - 3.9: py39, py39-without-extensions, py39-install-extensions, py39-disable-extensions - 3.10: py310, py310-without-extensions, py310-install-extensions, py310-disable-extensions - 3.11: py311, py311-without-extensions, py311-install-extensions, py311-disable-extensions - 3.12: py312, py312-without-extensions, py312-install-extensions, py312-disable-extensions - pypy-3.8: pypy-without-extensions - pypy-3.9: pypy-without-extensions - pypy-3.10: pypy-without-extensions + 3.8: lint, py38, py38-without-extensions, py38-install-extensions, py38-disable-extensions + 3.9: lint, py39, py39-without-extensions, py39-install-extensions, py39-disable-extensions + 3.10: lint, py310, py310-without-extensions, py310-install-extensions, py310-disable-extensions + 3.11: lint, py311, py311-without-extensions, py311-install-extensions, py311-disable-extensions + 3.12: lint, py312, py312-without-extensions, py312-install-extensions, py312-disable-extensionws + pypy-3.8: lint, pypy-without-extensions + pypy-3.9: lint, pypy-without-extensions + pypy-3.10: lint, pypy-without-extensions From 339a856a568c2908961848d98d5810ac8ee7df3d Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:48:33 +0100 Subject: [PATCH 13/19] Format code with ruff Signed-off-by: Stephen Finucane --- .pre-commit-config.yaml | 6 + docs/benchmarks.py | 10 +- docs/conf.py | 125 ++++++----- pyproject.toml | 7 + setup.py | 4 +- src/wrapt/__init__.py | 42 +++- src/wrapt/__wrapt__.py | 11 +- src/wrapt/arguments.py | 17 +- src/wrapt/decorators.py | 55 +++-- src/wrapt/importer.py | 34 ++- src/wrapt/patches.py | 18 +- src/wrapt/weakrefs.py | 24 ++- src/wrapt/wrappers.py | 108 ++++++---- tests/conftest.py | 3 + tests/module1.py | 1 + tests/module2.py | 1 + tests/test_adapter.py | 26 ++- tests/test_adapter_py3.py | 47 +++-- tests/test_adapter_py33.py | 13 +- tests/test_arguments.py | 26 ++- tests/test_attribute_wrapper.py | 3 +- tests/test_callable_object_proxy.py | 3 +- tests/test_class.py | 11 +- tests/test_class_py37.py | 34 ++- tests/test_copy.py | 15 +- tests/test_decorators.py | 6 +- tests/test_descriptors_py36.py | 3 +- tests/test_formatargspec_py35.py | 26 ++- tests/test_formatargspec_py38.py | 34 ++- tests/test_function.py | 9 +- tests/test_function_wrapper.py | 64 ++++-- tests/test_inheritance_py37.py | 5 +- tests/test_inner_classmethod.py | 40 ++-- tests/test_inner_staticmethod.py | 40 ++-- tests/test_instancemethod.py | 113 ++++++---- tests/test_memoize.py | 8 +- tests/test_monkey_patching.py | 74 +++---- tests/test_nested_function.py | 12 +- tests/test_object_proxy.py | 315 +++++++++++++++++++++------- tests/test_outer_classmethod.py | 44 ++-- tests/test_outer_staticmethod.py | 40 ++-- tests/test_pickle.py | 11 +- tests/test_post_import_hooks.py | 6 +- tests/test_synchronized_lock.py | 18 +- tests/test_update_attributes.py | 18 +- tests/test_weak_function_proxy.py | 9 +- 46 files changed, 1028 insertions(+), 511 deletions(-) create mode 100644 pyproject.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f6bdbd3..fa30ede2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,3 +13,9 @@ repos: - id: debug-statements - id: check-yaml files: .*\.(yaml|yml)$ + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.5.0 + hooks: + #- id: ruff + # args: [ --fix ] + - id: ruff-format diff --git a/docs/benchmarks.py b/docs/benchmarks.py index 05665c5b..e7c5dba1 100644 --- a/docs/benchmarks.py +++ b/docs/benchmarks.py @@ -1,36 +1,44 @@ import wrapt # https://pypi.python.org/pypi/wrapt import decorator # https://pypi.python.org/pypi/decorator + def function1(): pass + def wrapper2(func): def _wrapper2(*args, **kwargs): return func(*args, **kwargs) + return _wrapper2 + @wrapper2 def function2(): pass + @wrapt.decorator def wrapper3(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + @wrapper3 def function3(): pass + @decorator.decorator def wrapper4(wrapped, *args, **kwargs): return wrapped(*args, **kwargs) + @wrapper4 def function4(): pass -class Class(object): +class Class(object): def function1(self): pass diff --git a/docs/conf.py b/docs/conf.py index 255558b5..17fb785b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,12 +16,12 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. @@ -34,14 +34,14 @@ source_suffix = '.rst' # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. -project = u'wrapt' -copyright = u'2013-2023, Graham Dumpleton' +project = 'wrapt' +copyright = '2013-2023, Graham Dumpleton' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -54,40 +54,40 @@ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # -- Options for HTML output --------------------------------------------------- @@ -96,32 +96,33 @@ # a list of builtin themes. import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -130,44 +131,44 @@ # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'wraptdoc' @@ -176,42 +177,45 @@ # -- Options for LaTeX output -------------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'wrapt.tex', u'wrapt Documentation', - u'Graham Dumpleton', 'manual'), + ( + 'index', + 'wrapt.tex', + 'wrapt Documentation', + 'Graham Dumpleton', + 'manual', + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output -------------------------------------------- @@ -219,12 +223,11 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'wrapt', u'wrapt Documentation', - [u'Graham Dumpleton'], 1) + ('index', 'wrapt', 'wrapt Documentation', ['Graham Dumpleton'], 1) ] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ @@ -233,19 +236,25 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'wrapt', u'wrapt Documentation', - u'Graham Dumpleton', 'wrapt', 'One line description of project.', - 'Miscellaneous'), + ( + 'index', + 'wrapt', + 'wrapt Documentation', + 'Graham Dumpleton', + 'wrapt', + 'One line description of project.', + 'Miscellaneous', + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..f34de5b6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,7 @@ +[tool.ruff] +line-length = 79 +indent-width = 4 +target-version = "py38" + +[tool.ruff.format] +quote-style = "preserve" diff --git a/setup.py b/setup.py index df496748..4fd8058d 100644 --- a/setup.py +++ b/setup.py @@ -34,6 +34,4 @@ # --- Setup ------------------------------------------------------------------ -setuptools.setup( - ext_modules=[] if disable_extensions else extensions -) +setuptools.setup(ext_modules=[] if disable_extensions else extensions) diff --git a/src/wrapt/__init__.py b/src/wrapt/__init__.py index ed31a943..082fc44b 100644 --- a/src/wrapt/__init__.py +++ b/src/wrapt/__init__.py @@ -1,20 +1,40 @@ __version_info__ = ('1', '16', '0') __version__ = '.'.join(__version_info__) -from .__wrapt__ import (ObjectProxy, CallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, PartialCallableObjectProxy) - -from .patches import (resolve_path, apply_patch, wrap_object, wrap_object_attribute, - function_wrapper, wrap_function_wrapper, patch_function_wrapper, - transient_function_wrapper) +from .__wrapt__ import ( + ObjectProxy, + CallableObjectProxy, + FunctionWrapper, + BoundFunctionWrapper, + PartialCallableObjectProxy, +) + +from .patches import ( + resolve_path, + apply_patch, + wrap_object, + wrap_object_attribute, + function_wrapper, + wrap_function_wrapper, + patch_function_wrapper, + transient_function_wrapper, +) from .weakrefs import WeakFunctionProxy -from .decorators import (adapter_factory, AdapterFactory, decorator, - synchronized) - -from .importer import (register_post_import_hook, when_imported, - notify_module_loaded, discover_post_import_hooks) +from .decorators import ( + adapter_factory, + AdapterFactory, + decorator, + synchronized, +) + +from .importer import ( + register_post_import_hook, + when_imported, + notify_module_loaded, + discover_post_import_hooks, +) # Import of inspect.getcallargs() included for backward compatibility. An # implementation of this was previously bundled and made available here for diff --git a/src/wrapt/__wrapt__.py b/src/wrapt/__wrapt__.py index cae9006b..c25eb1a2 100644 --- a/src/wrapt/__wrapt__.py +++ b/src/wrapt/__wrapt__.py @@ -1,3 +1,8 @@ -from .wrappers import (ObjectProxy, CallableObjectProxy, - PartialCallableObjectProxy, FunctionWrapper, - BoundFunctionWrapper, _FunctionWrapperBase) +from .wrappers import ( + ObjectProxy, + CallableObjectProxy, + PartialCallableObjectProxy, + FunctionWrapper, + BoundFunctionWrapper, + _FunctionWrapperBase, +) diff --git a/src/wrapt/arguments.py b/src/wrapt/arguments.py index c433174a..e3d0c62a 100644 --- a/src/wrapt/arguments.py +++ b/src/wrapt/arguments.py @@ -7,8 +7,15 @@ from inspect import Parameter, Signature -def formatargspec(args, varargs=None, varkw=None, defaults=None, - kwonlyargs=(), kwonlydefaults={}, annotations={}): +def formatargspec( + args, + varargs=None, + varkw=None, + defaults=None, + kwonlyargs=(), + kwonlydefaults={}, + annotations={}, +): if kwonlydefaults is None: kwonlydefaults = {} ndefaults = len(defaults) if defaults else 0 @@ -18,7 +25,8 @@ def formatargspec(args, varargs=None, varkw=None, defaults=None, Parameter.POSITIONAL_OR_KEYWORD, default=defaults[i] if i >= 0 else Parameter.empty, annotation=annotations.get(arg, Parameter.empty), - ) for i, arg in enumerate(args, ndefaults - len(args)) + ) + for i, arg in enumerate(args, ndefaults - len(args)) ] if varargs: parameters.append(Parameter(varargs, Parameter.VAR_POSITIONAL)) @@ -28,7 +36,8 @@ def formatargspec(args, varargs=None, varkw=None, defaults=None, Parameter.KEYWORD_ONLY, default=kwonlydefaults.get(kwonlyarg, Parameter.empty), annotation=annotations.get(kwonlyarg, Parameter.empty), - ) for kwonlyarg in kwonlyargs + ) + for kwonlyarg in kwonlyargs ) if varkw: parameters.append(Parameter(varkw, Parameter.VAR_KEYWORD)) diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index 02a6819a..d1d373c6 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -11,16 +11,20 @@ from .arguments import formatargspec -from .__wrapt__ import (FunctionWrapper, BoundFunctionWrapper, ObjectProxy, - CallableObjectProxy) +from .__wrapt__ import ( + FunctionWrapper, + BoundFunctionWrapper, + ObjectProxy, + CallableObjectProxy, +) # Adapter wrapper for the wrapped function which will overlay certain # properties from the adapter function onto the wrapped function so that # functions such as inspect.getfullargspec(), inspect.signature() and # inspect.getsource() return the correct results one would expect. -class _AdapterFunctionCode(CallableObjectProxy): +class _AdapterFunctionCode(CallableObjectProxy): def __init__(self, wrapped_code, adapter_code): super(_AdapterFunctionCode, self).__init__(wrapped_code) self._self_adapter_code = adapter_code @@ -45,16 +49,17 @@ def co_kwonlyargcount(self): def co_varnames(self): return self._self_adapter_code.co_varnames -class _AdapterFunctionSurrogate(CallableObjectProxy): +class _AdapterFunctionSurrogate(CallableObjectProxy): def __init__(self, wrapped, adapter): super(_AdapterFunctionSurrogate, self).__init__(wrapped) self._self_adapter = adapter @property def __code__(self): - return _AdapterFunctionCode(self.__wrapped__.__code__, - self._self_adapter.__code__) + return _AdapterFunctionCode( + self.__wrapped__.__code__, self._self_adapter.__code__ + ) @property def __defaults__(self): @@ -73,11 +78,11 @@ def __signature__(self): class _BoundAdapterWrapper(BoundFunctionWrapper): - @property def __func__(self): - return _AdapterFunctionSurrogate(self.__wrapped__.__func__, - self._self_parent._self_adapter) + return _AdapterFunctionSurrogate( + self.__wrapped__.__func__, self._self_parent._self_adapter + ) @property def __signature__(self): @@ -88,14 +93,14 @@ def __signature__(self): class AdapterWrapper(FunctionWrapper): - __bound_function_wrapper__ = _BoundAdapterWrapper def __init__(self, *args, **kwargs): adapter = kwargs.pop('adapter') super(AdapterWrapper, self).__init__(*args, **kwargs) self._self_surrogate = _AdapterFunctionSurrogate( - self.__wrapped__, adapter) + self.__wrapped__, adapter + ) self._self_adapter = adapter @property @@ -114,17 +119,21 @@ def __kwdefaults__(self): def __signature__(self): return self._self_surrogate.__signature__ + class AdapterFactory(object): def __call__(self, wrapped): raise NotImplementedError() + class DelegatedAdapterFactory(AdapterFactory): def __init__(self, factory): super(DelegatedAdapterFactory, self).__init__() self.factory = factory + def __call__(self, wrapped): return self.factory(wrapped) + adapter_factory = DelegatedAdapterFactory # Decorator for creating other decorators. This decorator and the @@ -134,6 +143,7 @@ def __call__(self, wrapped): # function so the wrapper is effectively indistinguishable from the # original wrapped function. + def decorator(wrapper=None, enabled=None, adapter=None, proxy=FunctionWrapper): # The decorator should be supplied with a single positional argument # which is the wrapper function to be used to implement the @@ -196,8 +206,12 @@ def _build(wrapped, wrapper, enabled=None, adapter=None): if annotations: adapter.__annotations__ = annotations - return AdapterWrapper(wrapped=wrapped, wrapper=wrapper, - enabled=enabled, adapter=adapter) + return AdapterWrapper( + wrapped=wrapped, + wrapper=wrapper, + enabled=enabled, + adapter=adapter, + ) return proxy(wrapped=wrapped, wrapper=wrapper, enabled=enabled) @@ -257,8 +271,9 @@ def _capture(target_wrapped): # Finally build the wrapper itself and return it. - return _build(target_wrapped, target_wrapper, - _enabled, adapter) + return _build( + target_wrapped, target_wrapper, _enabled, adapter + ) return _capture @@ -392,8 +407,10 @@ def _capture(target_wrapped): # decorator again wrapped in a partial using the collected # arguments. - return partial(decorator, enabled=enabled, adapter=adapter, - proxy=proxy) + return partial( + decorator, enabled=enabled, adapter=adapter, proxy=proxy + ) + # Decorator for implementing thread synchronization. It can be used as a # decorator, in which case the synchronization context is determined by @@ -405,6 +422,7 @@ def _capture(target_wrapped): # synchronization primitive without creating a separate lock against the # derived or supplied context. + def synchronized(wrapped): # Determine if being passed an object which is a synchronization # primitive. We can't check by type for Lock, RLock, Semaphore etc, @@ -430,7 +448,6 @@ def _synchronized(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) class _PartialDecorator(CallableObjectProxy): - def __enter__(self): lock.acquire() return lock @@ -487,7 +504,6 @@ def _synchronized_wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) class _FinalDecorator(FunctionWrapper): - def __enter__(self): self._self_lock = _synchronized_lock(self.__wrapped__) self._self_lock.acquire() @@ -498,4 +514,5 @@ def __exit__(self, *args): return _FinalDecorator(wrapped=wrapped, wrapper=_synchronized_wrapper) + synchronized._synchronized_meta_lock = Lock() diff --git a/src/wrapt/importer.py b/src/wrapt/importer.py index b224231d..a5329ca2 100644 --- a/src/wrapt/importer.py +++ b/src/wrapt/importer.py @@ -26,6 +26,7 @@ # proxy callback being registered which will defer loading of the # specified module containing the callback function until required. + def _create_import_hook_from_string(name): def import_hook(module): module_name, function = name.split(':') @@ -35,8 +36,10 @@ def import_hook(module): for attr in attrs: callback = getattr(callback, attr) return callback(module) + return import_hook + def register_post_import_hook(hook, name): # Create a deferred import hook if hook is a string name rather than # a callable function. @@ -70,8 +73,10 @@ def register_post_import_hook(hook, name): if module is not None: hook(module) + # Register post import hooks defined as package entry points. + def _create_import_hook_from_entrypoint(entrypoint): def import_hook(module): __import__(entrypoint.module_name) @@ -79,8 +84,10 @@ def import_hook(module): for attr in entrypoint.attrs: callback = getattr(callback, attr) return callback(module) + return import_hook + def discover_post_import_hooks(group): try: import pkg_resources @@ -91,11 +98,13 @@ def discover_post_import_hooks(group): callback = _create_import_hook_from_entrypoint(entrypoint) register_post_import_hook(callback, entrypoint.name) + # Indicate that a module has been loaded. Any post import hooks which # were registered against the target module will be invoked. If an # exception is raised in any of the post import hooks, that will cause # the import of the target module to fail. + def notify_module_loaded(module): name = getattr(module, '__name__', None) @@ -109,30 +118,31 @@ def notify_module_loaded(module): for hook in hooks: hook(module) + # A custom module import finder. This intercepts attempts to import # modules and watches out for attempts to import target modules of # interest. When a module of interest is imported, then any post import # hooks which are registered will be invoked. -class _ImportHookLoader: +class _ImportHookLoader: def load_module(self, fullname): module = sys.modules[fullname] notify_module_loaded(module) return module -class _ImportHookChainedLoader(ObjectProxy): +class _ImportHookChainedLoader(ObjectProxy): def __init__(self, loader): super(_ImportHookChainedLoader, self).__init__(loader) if hasattr(loader, "load_module"): - self.__self_setattr__('load_module', self._self_load_module) + self.__self_setattr__('load_module', self._self_load_module) if hasattr(loader, "create_module"): - self.__self_setattr__('create_module', self._self_create_module) + self.__self_setattr__('create_module', self._self_create_module) if hasattr(loader, "exec_module"): - self.__self_setattr__('exec_module', self._self_exec_module) + self.__self_setattr__('exec_module', self._self_exec_module) def _self_set_loader(self, module): # Set module's loader to self.__wrapped__ unless it's already set to @@ -146,7 +156,8 @@ def _self_set_loader(self, module): # module loader was used. It isn't clear whether the attribute still # existed in that case or was set to None. - class UNDEFINED: pass + class UNDEFINED: + pass if getattr(module, "__loader__", UNDEFINED) in (None, self): try: @@ -154,8 +165,10 @@ class UNDEFINED: pass except AttributeError: pass - if (getattr(module, "__spec__", None) is not None - and getattr(module.__spec__, "loader", None) is self): + if ( + getattr(module, "__spec__", None) is not None + and getattr(module.__spec__, "loader", None) is self + ): module.__spec__.loader = self.__wrapped__ def _self_load_module(self, fullname): @@ -176,8 +189,8 @@ def _self_exec_module(self, module): self.__wrapped__.exec_module(module) notify_module_loaded(module) -class ImportHookFinder: +class ImportHookFinder: def __init__(self): self.in_progress = {} @@ -256,11 +269,14 @@ def find_spec(self, fullname, path=None, target=None): finally: del self.in_progress[fullname] + # Decorator for marking that a function should be called as a post # import hook when the target module is imported. + def when_imported(name): def register(hook): register_post_import_hook(hook, name) return hook + return register diff --git a/src/wrapt/patches.py b/src/wrapt/patches.py index 863c368e..02defc62 100644 --- a/src/wrapt/patches.py +++ b/src/wrapt/patches.py @@ -5,6 +5,7 @@ # Helper functions for applying wrappers to existing functions. + def resolve_path(module, name): if isinstance(module, str): __import__(module) @@ -46,23 +47,26 @@ def lookup_attribute(parent, attribute): return (parent, attribute, original) + def apply_patch(parent, attribute, replacement): setattr(parent, attribute, replacement) + def wrap_object(module, name, factory, args=(), kwargs={}): (parent, attribute, original) = resolve_path(module, name) wrapper = factory(original, *args, **kwargs) apply_patch(parent, attribute, wrapper) return wrapper + # Function for applying a proxy object to an attribute of a class # instance. The wrapper works by defining an attribute of the same name # on the class which is a descriptor and which intercepts access to the # instance attribute. Note that this cannot be used on attributes which # are themselves defined by a property object. -class AttributeWrapper(object): +class AttributeWrapper(object): def __init__(self, attribute, factory, args, kwargs): self.attribute = attribute self.factory = factory @@ -79,6 +83,7 @@ def __set__(self, instance, value): def __delete__(self, instance): del instance.__dict__[self.attribute] + def wrap_object_attribute(module, name, factory, args=(), kwargs={}): path, attribute = name.rsplit('.', 1) parent = resolve_path(module, path)[2] @@ -86,11 +91,13 @@ def wrap_object_attribute(module, name, factory, args=(), kwargs={}): apply_patch(parent, attribute, wrapper) return wrapper + # Functions for creating a simple decorator using a FunctionWrapper, # plus short cut functions for applying wrappers to functions. These are # for use when doing monkey patching. For a more featured way of # creating decorators see the decorator decorator instead. + def function_wrapper(wrapper): def _wrapper(wrapped, instance, args, kwargs): target_wrapped = args[0] @@ -101,16 +108,21 @@ def _wrapper(wrapped, instance, args, kwargs): else: target_wrapper = wrapper.__get__(instance, type(instance)) return FunctionWrapper(target_wrapped, target_wrapper) + return FunctionWrapper(wrapper, _wrapper) + def wrap_function_wrapper(module, name, wrapper): return wrap_object(module, name, FunctionWrapper, (wrapper,)) + def patch_function_wrapper(module, name, enabled=None): def _wrapper(wrapper): return wrap_object(module, name, FunctionWrapper, (wrapper, enabled)) + return _wrapper + def transient_function_wrapper(module, name): def _decorator(wrapper): def _wrapper(wrapped, instance, args, kwargs): @@ -121,6 +133,7 @@ def _wrapper(wrapped, instance, args, kwargs): target_wrapper = wrapper.__get__(None, instance) else: target_wrapper = wrapper.__get__(instance, type(instance)) + def _execute(wrapped, instance, args, kwargs): (parent, attribute, original) = resolve_path(module, name) replacement = FunctionWrapper(original, target_wrapper) @@ -129,6 +142,9 @@ def _execute(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) finally: setattr(parent, attribute, original) + return FunctionWrapper(target_wrapped, _execute) + return FunctionWrapper(wrapper, _wrapper) + return _decorator diff --git a/src/wrapt/weakrefs.py b/src/wrapt/weakrefs.py index f931b60d..23d052d5 100644 --- a/src/wrapt/weakrefs.py +++ b/src/wrapt/weakrefs.py @@ -12,6 +12,7 @@ # and the original function. The function is then rebound at the point # of a call via the weak function proxy. + def _weak_function_proxy_callback(ref, proxy, callback): if proxy._self_expired: return @@ -25,8 +26,8 @@ def _weak_function_proxy_callback(ref, proxy, callback): if callback is not None: callback(proxy) -class WeakFunctionProxy(ObjectProxy): +class WeakFunctionProxy(ObjectProxy): __slots__ = ('_self_expired', '_self_instance') def __init__(self, wrapped, callback=None): @@ -43,22 +44,25 @@ def __init__(self, wrapped, callback=None): # the callback here so as not to cause any odd reference cycles. _callback = callback and functools.partial( - _weak_function_proxy_callback, proxy=self, - callback=callback) + _weak_function_proxy_callback, proxy=self, callback=callback + ) self._self_expired = False if isinstance(wrapped, _FunctionWrapperBase): - self._self_instance = weakref.ref(wrapped._self_instance, - _callback) + self._self_instance = weakref.ref( + wrapped._self_instance, _callback + ) if wrapped._self_parent is not None: super(WeakFunctionProxy, self).__init__( - weakref.proxy(wrapped._self_parent, _callback)) + weakref.proxy(wrapped._self_parent, _callback) + ) else: super(WeakFunctionProxy, self).__init__( - weakref.proxy(wrapped, _callback)) + weakref.proxy(wrapped, _callback) + ) return @@ -66,13 +70,15 @@ def __init__(self, wrapped, callback=None): self._self_instance = weakref.ref(wrapped.__self__, _callback) super(WeakFunctionProxy, self).__init__( - weakref.proxy(wrapped.__func__, _callback)) + weakref.proxy(wrapped.__func__, _callback) + ) except AttributeError: self._self_instance = None super(WeakFunctionProxy, self).__init__( - weakref.proxy(wrapped, _callback)) + weakref.proxy(wrapped, _callback) + ) def __call__(*args, **kwargs): def _unpack_self(self, *args): diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index afc08ee9..5446365c 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -4,7 +4,6 @@ class _ObjectProxyMethods(object): - # We use properties to override the values of __module__ and # __doc__. If we add these in ObjectProxy, the derived class # __dict__ will still be setup to have string variants of these @@ -81,7 +80,9 @@ def __init__(self, wrapped): # using a property and it must instead be set explicitly. try: - object.__setattr__(self, '__annotations__', wrapped.__annotations__) + object.__setattr__( + self, '__annotations__', wrapped.__annotations__ + ) except AttributeError: pass @@ -115,9 +116,11 @@ def __bytes__(self): def __repr__(self): return '<{} at 0x{:x} for {} at 0x{:x}>'.format( - type(self).__name__, id(self), - type(self.__wrapped__).__name__, - id(self.__wrapped__)) + type(self).__name__, + id(self), + type(self.__wrapped__).__name__, + id(self.__wrapped__), + ) def __reversed__(self): return reversed(self.__wrapped__) @@ -126,6 +129,7 @@ def __round__(self): return round(self.__wrapped__) if sys.hexversion >= 0x03070000: + def __mro_entries__(self, bases): return (self.__wrapped__,) @@ -175,7 +179,9 @@ def __setattr__(self, name, value): except AttributeError: pass try: - object.__setattr__(self, '__annotations__', value.__annotations__) + object.__setattr__( + self, '__annotations__', value.__annotations__ + ) except AttributeError: pass @@ -425,15 +431,13 @@ def __deepcopy__(self, memo): raise NotImplementedError('object proxy must define __deepcopy__()') def __reduce__(self): - raise NotImplementedError( - 'object proxy must define __reduce_ex__()') + raise NotImplementedError('object proxy must define __reduce_ex__()') def __reduce_ex__(self, protocol): - raise NotImplementedError( - 'object proxy must define __reduce_ex__()') + raise NotImplementedError('object proxy must define __reduce_ex__()') -class CallableObjectProxy(ObjectProxy): +class CallableObjectProxy(ObjectProxy): def __call__(*args, **kwargs): def _unpack_self(self, *args): return self, args @@ -442,8 +446,8 @@ def _unpack_self(self, *args): return self.__wrapped__(*args, **kwargs) -class PartialCallableObjectProxy(ObjectProxy): +class PartialCallableObjectProxy(ObjectProxy): def __init__(*args, **kwargs): def _unpack_self(self, *args): return self, args @@ -476,14 +480,25 @@ def _unpack_self(self, *args): return self.__wrapped__(*_args, **_kwargs) -class _FunctionWrapperBase(ObjectProxy): - - __slots__ = ('_self_instance', '_self_wrapper', '_self_enabled', - '_self_binding', '_self_parent') - - def __init__(self, wrapped, instance, wrapper, enabled=None, - binding='function', parent=None): +class _FunctionWrapperBase(ObjectProxy): + __slots__ = ( + '_self_instance', + '_self_wrapper', + '_self_enabled', + '_self_binding', + '_self_parent', + ) + + def __init__( + self, + wrapped, + instance, + wrapper, + enabled=None, + binding='function', + parent=None, + ): super(_FunctionWrapperBase, self).__init__(wrapped) object.__setattr__(self, '_self_instance', instance) @@ -522,9 +537,14 @@ def __get__(self, instance, owner): if not inspect.isclass(self.__wrapped__): descriptor = self.__wrapped__.__get__(instance, owner) - return self.__bound_function_wrapper__(descriptor, instance, - self._self_wrapper, self._self_enabled, - self._self_binding, self) + return self.__bound_function_wrapper__( + descriptor, + instance, + self._self_wrapper, + self._self_enabled, + self._self_binding, + self, + ) return self @@ -538,13 +558,16 @@ def __get__(self, instance, owner): # function from the parent again. if self._self_instance is None and self._self_binding == 'function': - descriptor = self._self_parent.__wrapped__.__get__( - instance, owner) + descriptor = self._self_parent.__wrapped__.__get__(instance, owner) return self._self_parent.__bound_function_wrapper__( - descriptor, instance, self._self_wrapper, - self._self_enabled, self._self_binding, - self._self_parent) + descriptor, + instance, + self._self_wrapper, + self._self_enabled, + self._self_binding, + self._self_parent, + ) return self @@ -575,8 +598,9 @@ def _unpack_self(self, *args): if self._self_instance is None: instance = getattr(self.__wrapped__, '__self__', None) if instance is not None: - return self._self_wrapper(self.__wrapped__, instance, - args, kwargs) + return self._self_wrapper( + self.__wrapped__, instance, args, kwargs + ) # This is generally invoked when the wrapped function is being # called as a normal function and is not bound to a class as an @@ -584,8 +608,9 @@ def _unpack_self(self, *args): # wrapped function was a method, but this wrapper was in turn # wrapped using the staticmethod decorator. - return self._self_wrapper(self.__wrapped__, self._self_instance, - args, kwargs) + return self._self_wrapper( + self.__wrapped__, self._self_instance, args, kwargs + ) def __set_name__(self, owner, name): # This is a special method use to supply information to @@ -614,8 +639,8 @@ def __subclasscheck__(self, subclass): else: return issubclass(subclass, self.__wrapped__) -class BoundFunctionWrapper(_FunctionWrapperBase): +class BoundFunctionWrapper(_FunctionWrapperBase): def __call__(*args, **kwargs): def _unpack_self(self, *args): return self, args @@ -652,11 +677,14 @@ def _unpack_self(self, *args): raise TypeError('missing 1 required positional argument') instance, args = args[0], args[1:] - wrapped = PartialCallableObjectProxy(self.__wrapped__, instance) + wrapped = PartialCallableObjectProxy( + self.__wrapped__, instance + ) return self._self_wrapper(wrapped, instance, args, kwargs) - return self._self_wrapper(self.__wrapped__, self._self_instance, - args, kwargs) + return self._self_wrapper( + self.__wrapped__, self._self_instance, args, kwargs + ) else: # As in this case we would be dealing with a classmethod or @@ -674,11 +702,10 @@ def _unpack_self(self, *args): instance = getattr(self.__wrapped__, '__self__', None) - return self._self_wrapper(self.__wrapped__, instance, args, - kwargs) + return self._self_wrapper(self.__wrapped__, instance, args, kwargs) -class FunctionWrapper(_FunctionWrapperBase): +class FunctionWrapper(_FunctionWrapperBase): __bound_function_wrapper__ = BoundFunctionWrapper def __init__(self, wrapped, wrapper, enabled=None): @@ -769,5 +796,6 @@ def __init__(self, wrapped, wrapper, enabled=None): else: binding = 'function' - super(FunctionWrapper, self).__init__(wrapped, None, wrapper, - enabled, binding) + super(FunctionWrapper, self).__init__( + wrapped, None, wrapper, enabled, binding + ) diff --git a/tests/conftest.py b/tests/conftest.py index ef192d27..4520ca4b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,10 +4,12 @@ version = tuple(sys.version_info[:2]) + class DummyCollector(FileCollector): def collect(self): return [] + def construct_dummy(path, parent): if hasattr(DummyCollector, "from_parent"): item = DummyCollector.from_parent(parent, fspath=path) @@ -15,6 +17,7 @@ def construct_dummy(path, parent): else: return DummyCollector(path, parent=parent) + def pytest_pycollect_makemodule(path, parent): if '_py39' in path.basename and version < (3, 9): return construct_dummy(path, parent) diff --git a/tests/module1.py b/tests/module1.py index 7dfba642..947e02d3 100644 --- a/tests/module1.py +++ b/tests/module1.py @@ -1,2 +1,3 @@ import time + time.sleep(0.1) # simulate slow code diff --git a/tests/module2.py b/tests/module2.py index 7dfba642..947e02d3 100644 --- a/tests/module2.py +++ b/tests/module2.py @@ -1,2 +1,3 @@ import time + time.sleep(0.1) # simulate slow code diff --git a/tests/test_adapter.py b/tests/test_adapter.py index 6b90bf12..b87a58de 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -17,21 +17,25 @@ def adapter1(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + def function1(arg1, arg2): '''documentation''' return arg1, arg2 + function1o = function1 + @decorators.adapter1 def function1(arg1, arg2): '''documentation''' return arg1, arg2 + function1d = function1 -class TestAdapterAttributes(unittest.TestCase): +class TestAdapterAttributes(unittest.TestCase): def test_object_name(self): # Test preservation of function __name__ attribute. @@ -59,14 +63,15 @@ def test_doc_string(self): self.assertEqual(function1d.__doc__, 'documentation') -class TestArgumentSpecification(unittest.TestCase): +class TestArgumentSpecification(unittest.TestCase): def test_argspec(self): # Test preservation of function argument specification. It # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - def _adapter(arg1, arg2, arg3=None, *args, **kwargs): pass + def _adapter(arg1, arg2, arg3=None, *args, **kwargs): + pass function1a_argspec = inspect.getfullargspec(_adapter) function1d_argspec = inspect.getfullargspec(function1d) @@ -84,7 +89,8 @@ def test_signature(self): # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - def _adapter(arg1, arg2, arg3=None, *args, **kwargs): pass + def _adapter(arg1, arg2, arg3=None, *args, **kwargs): + pass function1a_signature = str(inspect.signature(_adapter)) function1d_signature = str(inspect.signature(function1d)) @@ -95,10 +101,11 @@ def test_isinstance(self): self.assertTrue(isinstance(function1d, type(function1o))) -class TestDynamicAdapter(unittest.TestCase): +class TestDynamicAdapter(unittest.TestCase): def test_dynamic_adapter_function(self): - def _adapter(arg1, arg2, arg3=None, *args, **kwargs): pass + def _adapter(arg1, arg2, arg3=None, *args, **kwargs): + pass argspec = inspect.getfullargspec(_adapter) @@ -125,7 +132,8 @@ def _function_2(): self.assertEqual(inspect.getfullargspec(_function_2), argspec) def test_dynamic_adapter_instancemethod(self): - def _adapter(self, arg1, arg2, arg3=None, *args, **kwargs): pass + def _adapter(self, arg1, arg2, arg3=None, *args, **kwargs): + pass argspec = inspect.getfullargspec(_adapter) @@ -160,7 +168,8 @@ def function(self): self.assertEqual(inspect.getfullargspec(instance2.function), argspec) def test_dynamic_adapter_classmethod(self): - def _adapter(cls, arg1, arg2, arg3=None, *args, **kwargs): pass + def _adapter(cls, arg1, arg2, arg3=None, *args, **kwargs): + pass argspec = inspect.getfullargspec(_adapter) @@ -214,5 +223,6 @@ def _function_1(arg1, arg2): self.assertEqual(argspec.args, ['arg0', 'arg1', 'arg2']) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_adapter_py3.py b/tests/test_adapter_py3.py index bb208d61..6238994a 100644 --- a/tests/test_adapter_py3.py +++ b/tests/test_adapter_py3.py @@ -26,47 +26,58 @@ def adapter2(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + def function1(arg1, arg2) -> Iterable: '''documentation''' return arg1, arg2 + function1o = function1 + @decorators.adapter1 def function1(arg1, arg2) -> Iterable: '''documentation''' return arg1, arg2 + function1d = function1 + def function2(arg1, arg2) -> Iterable: '''documentation''' return arg1, arg2 + function2o = function2 + @decorators.adapter1 def function2(arg1, arg2) -> Iterable: '''documentation''' return arg1, arg2 + function2d = function2 -class TestAdapterAttributesWithAnnotations(unittest.TestCase): +class TestAdapterAttributesWithAnnotations(unittest.TestCase): def test_annotations(self): # Test preservation of function __annotations__ attribute. - self.assertEqual(function1d.__annotations__, function1o.__annotations__) + self.assertEqual( + function1d.__annotations__, function1o.__annotations__ + ) -class TestArgumentSpecificationWithAnnotations(unittest.TestCase): +class TestArgumentSpecificationWithAnnotations(unittest.TestCase): def test_argspec(self): # Test preservation of function argument specification. It # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - def _adapter(arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: pass + def _adapter(arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: + pass function1a_argspec = inspect.getfullargspec(_adapter) function1d_argspec = inspect.getfullargspec(function1d) @@ -84,7 +95,8 @@ def test_signature(self): # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - def _adapter(arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: pass + def _adapter(arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: + pass function1a_signature = str(inspect.signature(_adapter)) function1d_signature = str(inspect.signature(function1d)) @@ -95,10 +107,11 @@ def test_isinstance(self): self.assertTrue(isinstance(function1d, type(function1o))) -class TestDynamicAdapterWithAnnotations(unittest.TestCase): +class TestDynamicAdapterWithAnnotations(unittest.TestCase): def test_dynamic_adapter_function(self): - def _adapter1(arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: pass + def _adapter1(arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: + pass argspec1 = inspect.getfullargspec(_adapter1) @@ -116,7 +129,8 @@ def _function_1(): # annotations which reference a non builtin type, so use test # function which returns int rather than Iterable. - def _adapter2(arg1, arg2, arg3=None, *args, **kwargs) -> int: pass + def _adapter2(arg1, arg2, arg3=None, *args, **kwargs) -> int: + pass argspec2 = inspect.getfullargspec(_adapter2) @@ -128,12 +142,15 @@ def _wrapper_2(wrapped, instance, args, kwargs): @_wrapper_2 def _function_2(): - pass + pass self.assertEqual(inspect.getfullargspec(_function_2), argspec2) def test_dynamic_adapter_instancemethod(self): - def _adapter1(self, arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: pass + def _adapter1( + self, arg1, arg2, arg3=None, *args, **kwargs + ) -> Iterable: + pass argspec1 = inspect.getfullargspec(_adapter1) @@ -154,7 +171,8 @@ def function(self): # Can't use a function signature with adapter factory which has # annotations which reference a non builtin type. - def _adapter2(self, arg1, arg2, arg3=None, *args, **kwargs) -> int: pass + def _adapter2(self, arg1, arg2, arg3=None, *args, **kwargs) -> int: + pass argspec2 = inspect.getfullargspec(_adapter2) @@ -175,7 +193,8 @@ def function(self): self.assertEqual(inspect.getfullargspec(instance2.function), argspec2) def test_dynamic_adapter_classmethod(self): - def _adapter1(cls, arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: pass + def _adapter1(cls, arg1, arg2, arg3=None, *args, **kwargs) -> Iterable: + pass argspec1 = inspect.getfullargspec(_adapter1) @@ -197,7 +216,8 @@ def function(cls): # Can't use a function signature with adapter factory which has # annotations which reference a non builtin type. - def _adapter2(cls, arg1, arg2, arg3=None, *args, **kwargs) -> int: pass + def _adapter2(cls, arg1, arg2, arg3=None, *args, **kwargs) -> int: + pass argspec2 = inspect.getfullargspec(_adapter2) @@ -237,5 +257,6 @@ def _function_1(arg1, arg2) -> Iterable: self.assertEqual(argspec.args, ['arg0', 'arg1', 'arg2']) self.assertEqual(argspec.annotations, {'return': Iterable}) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_adapter_py33.py b/tests/test_adapter_py33.py index edd7fba7..65ab5edb 100644 --- a/tests/test_adapter_py33.py +++ b/tests/test_adapter_py33.py @@ -17,27 +17,32 @@ def adapter1(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + def function1(arg1, arg2): '''documentation''' return arg1, arg2 + function1o = function1 + @decorators.adapter1 def function1(arg1, arg2): '''documentation''' return arg1, arg2 + function1d = function1 -class TestArgumentSpecification(unittest.TestCase): +class TestArgumentSpecification(unittest.TestCase): def test_getfullargspec(self): # Test preservation of function argument specification. It # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - def _adapter(arg1, arg2, *, arg3=None, **kwargs): pass + def _adapter(arg1, arg2, *, arg3=None, **kwargs): + pass function1a_argspec = inspect.getfullargspec(_adapter) function1d_argspec = inspect.getfullargspec(function1d) @@ -48,11 +53,13 @@ def test_signature(self): # actually needs to match that of the adapter function the # prototype of which was supplied via the dummy function. - def _adapter(arg1, arg2, *, arg3=None, **kwargs): pass + def _adapter(arg1, arg2, *, arg3=None, **kwargs): + pass function1a_signature = str(inspect.signature(_adapter)) function1d_signature = str(inspect.signature(function1d)) self.assertEqual(function1a_signature, function1d_signature) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_arguments.py b/tests/test_arguments.py index 274d9393..3acb5b70 100644 --- a/tests/test_arguments.py +++ b/tests/test_arguments.py @@ -2,20 +2,34 @@ import wrapt -class TestArguments(unittest.TestCase): +class TestArguments(unittest.TestCase): def test_getcallargs(self): def function(a, b=2, c=3, d=4, e=5, *args, **kwargs): pass - expected = {'a': 10, 'c': 3, 'b': 20, 'e': 5, 'd': 40, - 'args': (), 'kwargs': {'f': 50}} + expected = { + 'a': 10, + 'c': 3, + 'b': 20, + 'e': 5, + 'd': 40, + 'args': (), + 'kwargs': {'f': 50}, + } calculated = wrapt.getcallargs(function, 10, 20, d=40, f=50) self.assertEqual(expected, calculated) - expected = {'a': 10, 'c': 30, 'b': 20, 'e': 50, 'd': 40, - 'args': (60,), 'kwargs': {}} + expected = { + 'a': 10, + 'c': 30, + 'b': 20, + 'e': 50, + 'd': 40, + 'args': (60,), + 'kwargs': {}, + } calculated = wrapt.getcallargs(function, 10, 20, 30, 40, 50, 60) self.assertEqual(expected, calculated) @@ -24,5 +38,5 @@ def test_unexpected_unicode_keyword(self): def function(a=2): pass - kwargs = { u'b': 40 } + kwargs = {'b': 40} self.assertRaises(TypeError, wrapt.getcallargs, function, **kwargs) diff --git a/tests/test_attribute_wrapper.py b/tests/test_attribute_wrapper.py index 6fcd5f25..93ace875 100644 --- a/tests/test_attribute_wrapper.py +++ b/tests/test_attribute_wrapper.py @@ -2,12 +2,13 @@ import wrapt + class Class(object): def __init__(self, value): self.value = value -class TestAttributeProxy(unittest.TestCase): +class TestAttributeProxy(unittest.TestCase): def test_wrap_attribute(self): wrapt.wrap_object_attribute(__name__, 'Class.value', wrapt.ObjectProxy) diff --git a/tests/test_callable_object_proxy.py b/tests/test_callable_object_proxy.py index e9b5a7f9..c01c2143 100644 --- a/tests/test_callable_object_proxy.py +++ b/tests/test_callable_object_proxy.py @@ -2,8 +2,8 @@ import wrapt -class TestPartialCallableObjectProxy(unittest.TestCase): +class TestPartialCallableObjectProxy(unittest.TestCase): def test_no_arguments(self): def func0(): return ((), {}) @@ -64,5 +64,6 @@ def func0(*args, **kwargs): self.assertEqual(partial0(), (args, kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_class.py b/tests/test_class.py index 801e24c8..86592fed 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -15,21 +15,23 @@ def passthru_decorator(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + class class1(object): pass + class1o = class1 class1d = decorators.passthru_decorator(class1) -class TestIntrospection(unittest.TestCase): +class TestIntrospection(unittest.TestCase): def test_getmembers(self): class1o_members = inspect.getmembers(class1o) class1d_members = inspect.getmembers(class1d) -class TestInheritance(unittest.TestCase): +class TestInheritance(unittest.TestCase): def test_single_inheritance(self): @wrapt.decorator def passthru(wrapped, instance, args, kwargs): @@ -60,4 +62,7 @@ def __init__(self): self.assertTrue(isinstance(derived, DerivedClass)) self.assertEqual(derived.value, 2) - self.assertEqual(type(derived).__mro__, (DerivedClass, BaseClass.__wrapped__, object)) + self.assertEqual( + type(derived).__mro__, + (DerivedClass, BaseClass.__wrapped__, object), + ) diff --git a/tests/test_class_py37.py b/tests/test_class_py37.py index af98fd45..b4d33c4c 100644 --- a/tests/test_class_py37.py +++ b/tests/test_class_py37.py @@ -4,7 +4,6 @@ class TestInheritance(unittest.TestCase): - def test_single_inheritance(self): @wrapt.decorator def passthru(wrapped, instance, args, kwargs): @@ -27,7 +26,9 @@ def __init__(self): self.assertEqual(base.value, 1) self.assertEqual(type(base).__mro__, (BaseClass.__wrapped__, object)) - self.assertEqual(BaseClass.__mro_entries__(()), (BaseClass.__wrapped__,)) + self.assertEqual( + BaseClass.__mro_entries__(()), (BaseClass.__wrapped__,) + ) derived = DerivedClass() @@ -36,7 +37,10 @@ def __init__(self): self.assertTrue(isinstance(derived, DerivedClass)) self.assertEqual(derived.value, 2) - self.assertEqual(type(derived).__mro__, (DerivedClass, BaseClass.__wrapped__, object)) + self.assertEqual( + type(derived).__mro__, + (DerivedClass, BaseClass.__wrapped__, object), + ) def test_multiple_inheritance(self): @wrapt.decorator @@ -61,8 +65,15 @@ class DerivedClass(BaseClass1, BaseClass2): self.assertTrue(isinstance(derived, BaseClass2.__wrapped__)) self.assertTrue(isinstance(derived, DerivedClass)) - self.assertEqual(type(derived).__mro__, (DerivedClass, - BaseClass1.__wrapped__, BaseClass2.__wrapped__, object)) + self.assertEqual( + type(derived).__mro__, + ( + DerivedClass, + BaseClass1.__wrapped__, + BaseClass2.__wrapped__, + object, + ), + ) def test_multiple_inheritance_common(self): @wrapt.decorator @@ -92,6 +103,13 @@ class DerivedClass(BaseClass1, BaseClass2): self.assertTrue(isinstance(derived, BaseClass2.__wrapped__)) self.assertTrue(isinstance(derived, DerivedClass)) - self.assertEqual(type(derived).__mro__, (DerivedClass, - BaseClass1.__wrapped__, BaseClass2.__wrapped__, - CommonClass.__wrapped__, object)) + self.assertEqual( + type(derived).__mro__, + ( + DerivedClass, + BaseClass1.__wrapped__, + BaseClass2.__wrapped__, + CommonClass.__wrapped__, + object, + ), + ) diff --git a/tests/test_copy.py b/tests/test_copy.py index 5b36bbde..97e94e0d 100644 --- a/tests/test_copy.py +++ b/tests/test_copy.py @@ -3,24 +3,25 @@ import wrapt -class CustomObjectProxy(wrapt.ObjectProxy): +class CustomObjectProxy(wrapt.ObjectProxy): def __copy__(self): return CustomObjectProxy(copy.copy(self.__wrapped__)) def __deepcopy__(self, memo): return CustomObjectProxy(copy.deepcopy(self.__wrapped__, memo)) -class TestObjectCopy(unittest.TestCase): +class TestObjectCopy(unittest.TestCase): def test_copy(self): proxy1 = wrapt.ObjectProxy([1]) with self.assertRaises(NotImplementedError) as context: proxy2 = copy.copy(proxy1) - self.assertTrue(str(context.exception) == - 'object proxy must define __copy__()') + self.assertTrue( + str(context.exception) == 'object proxy must define __copy__()' + ) def test_deepcopy(self): proxy1 = wrapt.ObjectProxy([1]) @@ -28,8 +29,9 @@ def test_deepcopy(self): with self.assertRaises(NotImplementedError) as context: proxy2 = copy.deepcopy(proxy1) - self.assertTrue(str(context.exception) == - 'object proxy must define __deepcopy__()') + self.assertTrue( + str(context.exception) == 'object proxy must define __deepcopy__()' + ) def test_copy_proxy(self): proxy1 = CustomObjectProxy([1]) @@ -47,5 +49,6 @@ def test_deepcopy_proxy(self): self.assertEqual(proxy1, proxy2) self.assertEqual(proxy1.__wrapped__, proxy2.__wrapped__) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 844f6308..bbfe9836 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -2,8 +2,8 @@ import wrapt -class TestDecorator(unittest.TestCase): +class TestDecorator(unittest.TestCase): def test_no_parameters(self): _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -27,6 +27,7 @@ def test_instance_method_as_decorator(self): class Instance(object): def __init__(self): self.count = 0 + @wrapt.decorator def decorator(self, wrapped, instance, args, kwargs): self.count += 1 @@ -54,6 +55,7 @@ def test_class_method_as_decorator(self): class Instance(object): count = 0 + @wrapt.decorator @classmethod def decorator(cls, wrapped, instance, args, kwargs): @@ -99,6 +101,7 @@ def test_class_type_as_decorator_args(self): class ClassDecorator(object): def __init__(self, arg): assert arg == 1 + def __call__(self, wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @@ -110,5 +113,6 @@ def _function(*args, **kwargs): self.assertEqual(result, (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_descriptors_py36.py b/tests/test_descriptors_py36.py index 4896efd3..134ffeb3 100644 --- a/tests/test_descriptors_py36.py +++ b/tests/test_descriptors_py36.py @@ -2,8 +2,8 @@ import wrapt -class TestObjectDescriptors(unittest.TestCase): +class TestObjectDescriptors(unittest.TestCase): def test_set_name(self): @wrapt.decorator def _decorator(wrapped, instance, args, kwargs): @@ -32,5 +32,6 @@ def method(self): self.assertEqual(attribute_name, ["method"]) self.assertEqual(instance.method(), True) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_formatargspec_py35.py b/tests/test_formatargspec_py35.py index 2ae58fcb..b7658c61 100644 --- a/tests/test_formatargspec_py35.py +++ b/tests/test_formatargspec_py35.py @@ -3,29 +3,41 @@ from wrapt import formatargspec -class TestFormatargspec35(unittest.TestCase): +class TestFormatargspec35(unittest.TestCase): def assertFormatEqual(self, func, ref): formatted = formatargspec(*inspect.getfullargspec(func)) self.assertEqual(formatted, ref) def test_formatargspec(self): - def foo1(): pass + def foo1(): + pass + self.assertFormatEqual(foo1, '()') - def foo2(a, b='c'): pass + def foo2(a, b='c'): + pass + self.assertFormatEqual(foo2, ("(a, b='c')")) - def foo3(a, b, *args, **kwargs): pass + def foo3(a, b, *args, **kwargs): + pass + self.assertFormatEqual(foo3, '(a, b, *args, **kwargs)') - def foo4(a: int, b) -> list: pass + def foo4(a: int, b) -> list: + pass + formatted4 = '(a: int, b) -> list' self.assertFormatEqual(foo4, formatted4) # examples from https://www.python.org/dev/peps/pep-3102/ - def sortwords(*wordlist, case_sensitive=False): pass + def sortwords(*wordlist, case_sensitive=False): + pass + self.assertFormatEqual(sortwords, '(*wordlist, case_sensitive=False)') - def compare(a, b, *, key=None): pass + def compare(a, b, *, key=None): + pass + self.assertFormatEqual(compare, '(a, b, *, key=None)') diff --git a/tests/test_formatargspec_py38.py b/tests/test_formatargspec_py38.py index 0d4cfb79..b0c5e7f8 100644 --- a/tests/test_formatargspec_py38.py +++ b/tests/test_formatargspec_py38.py @@ -4,34 +4,50 @@ from wrapt import formatargspec -class TestFormatargspec38(unittest.TestCase): +class TestFormatargspec38(unittest.TestCase): def assertFormatEqual(self, func, ref): formatted = formatargspec(*getfullargspec(func)) self.assertEqual(formatted, ref) def test_formatargspec(self): # exemples from https://www.python.org/dev/peps/pep-0570/ - def name1(p1, p2, /, p_or_kw, *, kw): pass + def name1(p1, p2, /, p_or_kw, *, kw): + pass + self.assertFormatEqual(name1, '(p1, p2, p_or_kw, *, kw)') - def name2(p1, p2=None, /, p_or_kw=None, *, kw): pass + def name2(p1, p2=None, /, p_or_kw=None, *, kw): + pass + self.assertFormatEqual(name2, '(p1, p2=None, p_or_kw=None, *, kw)') - def name3(p1, p2=None, /, *, kw): pass + def name3(p1, p2=None, /, *, kw): + pass + self.assertFormatEqual(name3, '(p1, p2=None, *, kw)') - def name4(p1, p2=None, /): pass + def name4(p1, p2=None, /): + pass + self.assertFormatEqual(name4, '(p1, p2=None)') - def name5(p1, p2, /, p_or_kw): pass + def name5(p1, p2, /, p_or_kw): + pass + self.assertFormatEqual(name5, '(p1, p2, p_or_kw)') - def name6(p1, p2, /): pass + def name6(p1, p2, /): + pass + self.assertFormatEqual(name6, '(p1, p2)') - def name7(p_or_kw, *, kw): pass + def name7(p_or_kw, *, kw): + pass + self.assertFormatEqual(name7, '(p_or_kw, *, kw)') - def name8(*, kw): pass + def name8(*, kw): + pass + self.assertFormatEqual(name8, '(*, kw)') diff --git a/tests/test_function.py b/tests/test_function.py index aa29243f..262ca915 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -15,16 +15,18 @@ def passthru_decorator(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + def function1(arg): '''documentation''' return arg + function1o = function1 function1d = decorators.passthru_decorator(function1) -assert(function1d is not function1o) +assert function1d is not function1o -class TestNamingFunction(unittest.TestCase): +class TestNamingFunction(unittest.TestCase): def test_object_name(self): # Test preservation of function __name__ attribute. @@ -66,8 +68,8 @@ def test_isinstance(self): self.assertTrue(isinstance(function1d, type(function1o))) -class TestCallingFunction(unittest.TestCase): +class TestCallingFunction(unittest.TestCase): def test_call_function(self): _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -87,5 +89,6 @@ def _function(*args, **kwargs): self.assertEqual(result, (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_function_wrapper.py b/tests/test_function_wrapper.py index f9b28010..96dc3bd0 100644 --- a/tests/test_function_wrapper.py +++ b/tests/test_function_wrapper.py @@ -4,7 +4,6 @@ class TestClassInheritence(unittest.TestCase): - def test_function_type_inheritence(self): @wrapt.decorator def _decorator(wrapped, instance, args, kwargs): @@ -73,15 +72,17 @@ def function(*args, **kwargs): self.assertFalse(isinstance(instance.function, wrapt.FunctionWrapper)) self.assertTrue(isinstance(instance.function, wrapt.ObjectProxy)) -class TestAttributeAccess(unittest.TestCase): +class TestAttributeAccess(unittest.TestCase): def test_function_attributes(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) def function1(*args, **kwargs): return args, kwargs + function2 = decorator2(function1) self.assertEqual(function2.__wrapped__, function1) @@ -91,11 +92,13 @@ def function1(*args, **kwargs): def test_instancemethod_attributes(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): def function1(self, *args, **kwargs): return args, kwargs + function2 = decorator2(function1) self.assertEqual(function2.__wrapped__, function1) @@ -111,12 +114,14 @@ def function1(self, *args, **kwargs): def test_classmethod_attributes(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): @classmethod def function1(cls, *args, **kwargs): return args, kwargs + function2 = decorator2(function1) self.assertEqual(function2.__wrapped__, function1) @@ -132,12 +137,14 @@ def function1(cls, *args, **kwargs): def test_staticmethod_attributes(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): @staticmethod def function1(*args, **kwargs): return args, kwargs + function2 = decorator2(function1) self.assertEqual(function2.__wrapped__, function1) @@ -147,6 +154,7 @@ def function1(*args, **kwargs): def test_instancemethod_attributes_external_class(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): @@ -166,6 +174,7 @@ def function1(self, *args, **kwargs): def test_classmethod_attributes_external_class(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): @@ -181,6 +190,7 @@ def function1(cls, *args, **kwargs): def test_staticmethod_attributes_external_class(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): @@ -200,6 +210,7 @@ def function1(*args, **kwargs): def test_instancemethod_attributes_external_instance(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): @@ -220,6 +231,7 @@ def function1(self, *args, **kwargs): def test_classmethod_attributes_external_instance(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): @@ -235,6 +247,7 @@ def function1(cls, *args, **kwargs): def test_staticmethod_attributes_external_instance(self): def decorator1(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + decorator2 = wrapt.decorator(decorator1) class Class(object): @@ -251,8 +264,8 @@ def function1(*args, **kwargs): self.assertEqual(function2._self_binding, 'function') -class TestParentReference(unittest.TestCase): +class TestParentReference(unittest.TestCase): def test_function_decorator(self): @wrapt.decorator def _decorator(wrapped, instance, args, kwargs): @@ -328,8 +341,8 @@ def function_sm_inner(): self.assertNotEqual(Class.function_sm_inner._self_parent, None) -class TestGuardArgument(unittest.TestCase): +class TestGuardArgument(unittest.TestCase): def test_boolean_false_guard_on_decorator(self): @wrapt.decorator(enabled=False) def _decorator(wrapped, instance, args, kwargs): @@ -355,8 +368,10 @@ def function(): def test_boolean_dynamic_guard_on_decorator(self): class Guard(object): value = True + def __nonzero__(self): return self.value + __bool__ = __nonzero__ guard = Guard() @@ -387,6 +402,7 @@ def function(): def test_function_guard_on_decorator(self): value = True + def guard(): return value @@ -416,6 +432,7 @@ def function(): def test_guard_on_instancemethod(self): value = True + def guard(): return value @@ -448,10 +465,9 @@ def function(self): self.assertEqual(len(result), 0) -class TestDerivedFunctionWrapper(unittest.TestCase): +class TestDerivedFunctionWrapper(unittest.TestCase): def test_override_bound_type(self): - class _BoundFunctionWrapper(wrapt.BoundFunctionWrapper): ATTRIBUTE = 1 @@ -475,10 +491,9 @@ def wrapper(wrapped, instance, args, kwargs): self.assertTrue(isinstance(_bound_wrapper, _BoundFunctionWrapper)) self.assertEqual(_bound_wrapper.ATTRIBUTE, 1) -class TestFunctionBinding(unittest.TestCase): +class TestFunctionBinding(unittest.TestCase): def test_double_binding(self): - def function(): pass @@ -495,23 +510,25 @@ def wrapper(wrapped, instance, args, kwargs): self.assertTrue(_bound_wrapper_1._self_parent is _wrapper) - self.assertTrue(isinstance(_bound_wrapper_1, - wrapt.BoundFunctionWrapper)) + self.assertTrue( + isinstance(_bound_wrapper_1, wrapt.BoundFunctionWrapper) + ) self.assertEqual(_bound_wrapper_1._self_instance, instance) _bound_wrapper_2 = _bound_wrapper_1.__get__(instance, type(instance)) self.assertTrue(_bound_wrapper_2._self_parent is _wrapper) - self.assertTrue(isinstance(_bound_wrapper_2, - wrapt.BoundFunctionWrapper)) - self.assertEqual(_bound_wrapper_2._self_instance, - _bound_wrapper_1._self_instance) + self.assertTrue( + isinstance(_bound_wrapper_2, wrapt.BoundFunctionWrapper) + ) + self.assertEqual( + _bound_wrapper_2._self_instance, _bound_wrapper_1._self_instance + ) self.assertTrue(_bound_wrapper_1 is _bound_wrapper_2) def test_re_bind_after_none(self): - def function(): pass @@ -528,34 +545,36 @@ def wrapper(wrapped, instance, args, kwargs): self.assertTrue(_bound_wrapper_1._self_parent is _wrapper) - self.assertTrue(isinstance(_bound_wrapper_1, - wrapt.BoundFunctionWrapper)) + self.assertTrue( + isinstance(_bound_wrapper_1, wrapt.BoundFunctionWrapper) + ) self.assertEqual(_bound_wrapper_1._self_instance, None) _bound_wrapper_2 = _bound_wrapper_1.__get__(instance, type(instance)) self.assertTrue(_bound_wrapper_2._self_parent is _wrapper) - self.assertTrue(isinstance(_bound_wrapper_2, - wrapt.BoundFunctionWrapper)) + self.assertTrue( + isinstance(_bound_wrapper_2, wrapt.BoundFunctionWrapper) + ) self.assertEqual(_bound_wrapper_2._self_instance, instance) self.assertTrue(_bound_wrapper_1 is not _bound_wrapper_2) -class TestInvalidWrapper(unittest.TestCase): +class TestInvalidWrapper(unittest.TestCase): def test_none_for_wrapped(self): - def run(*args): def _wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) + wrapper = wrapt.FunctionWrapper(None, _wrapper) wrapper.__get__(list(), list)() self.assertRaises(AttributeError, run, ()) -class TestInvalidCalling(unittest.TestCase): +class TestInvalidCalling(unittest.TestCase): def test_missing_self_via_class(self): @wrapt.decorator def _decorator(wrapped, instance, args, kwargs): @@ -571,5 +590,6 @@ def run(*args): self.assertRaises(TypeError, run, ()) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_inheritance_py37.py b/tests/test_inheritance_py37.py index de3c24b2..91a36455 100644 --- a/tests/test_inheritance_py37.py +++ b/tests/test_inheritance_py37.py @@ -4,8 +4,8 @@ import wrapt -class TestClassInheritance(unittest.TestCase): +class TestClassInheritance(unittest.TestCase): def test_basic_inheritance(self): @wrapt.decorator def wrapper(wrapped, instance, args, kwargs): @@ -47,8 +47,10 @@ def method(self): def function(): pass + class F(wrapt.FunctionWrapper): pass + instance = F(function, wrapper) self.assertTrue(isinstance(instance, wrapt.FunctionWrapper)) @@ -174,5 +176,6 @@ def method(self): self.assertTrue(isinstance(D1(), B1)) self.assertTrue(isinstance(D1(), C1)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_inner_classmethod.py b/tests/test_inner_classmethod.py index 0d29c0b8..1b84583e 100644 --- a/tests/test_inner_classmethod.py +++ b/tests/test_inner_classmethod.py @@ -15,14 +15,17 @@ def passthru_decorator(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + class Class(object): @classmethod def function(self, arg): '''documentation''' return arg + Original = Class + class Class(object): @decorators.passthru_decorator @classmethod @@ -30,19 +33,19 @@ def function(self, arg): '''documentation''' return arg -class TestNamingInnerClassMethod(unittest.TestCase): +class TestNamingInnerClassMethod(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(Class.function.__name__, - Original.function.__name__) + self.assertEqual(Class.function.__name__, Original.function.__name__) def test_instance_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(Class().function.__name__, - Original().function.__name__) + self.assertEqual( + Class().function.__name__, Original().function.__name__ + ) def test_class_object_qualname(self): # Test preservation of instance method __qualname__ attribute. @@ -67,26 +70,26 @@ def test_instance_object_qualname(self): def test_class_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(Class.function.__module__, - Original.function.__module__) + self.assertEqual( + Class.function.__module__, Original.function.__module__ + ) def test_instance_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(Class().function.__module__, - Original().function.__module__) + self.assertEqual( + Class().function.__module__, Original().function.__module__ + ) def test_class_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(Class.function.__doc__, - Original.function.__doc__) + self.assertEqual(Class.function.__doc__, Original.function.__doc__) def test_instance_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(Class().function.__doc__, - Original().function.__doc__) + self.assertEqual(Class().function.__doc__, Original().function.__doc__) def test_class_argspec(self): # Test preservation of instance method argument specification. @@ -105,17 +108,17 @@ def test_instance_argspec(self): def test_class_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(Class.function, - type(Original.function))) + self.assertTrue(isinstance(Class.function, type(Original.function))) def test_instance_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(Class().function, - type(Original().function))) + self.assertTrue( + isinstance(Class().function, type(Original().function)) + ) -class TestCallingInnerClassMethod(unittest.TestCase): +class TestCallingInnerClassMethod(unittest.TestCase): def test_class_call_function(self): # Test calling classmethod. @@ -328,5 +331,6 @@ def _decorator(wrapped, instance, args, kwargs): self.assertEqual(result, (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_inner_staticmethod.py b/tests/test_inner_staticmethod.py index f10f01df..816fcb44 100644 --- a/tests/test_inner_staticmethod.py +++ b/tests/test_inner_staticmethod.py @@ -15,14 +15,17 @@ def passthru_decorator(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + class Class(object): @staticmethod def function(self, arg): '''documentation''' return arg + Original = Class + class Class(object): @decorators.passthru_decorator @staticmethod @@ -30,25 +33,26 @@ def function(self, arg): '''documentation''' return arg -class TestNamingInnerStaticMethod(unittest.TestCase): +class TestNamingInnerStaticMethod(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(Class.function.__name__, - Original.function.__name__) + self.assertEqual(Class.function.__name__, Original.function.__name__) def test_instance_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(Class().function.__name__, - Original().function.__name__) + self.assertEqual( + Class().function.__name__, Original().function.__name__ + ) def test_class_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(Class.function.__module__, - Original.function.__module__) + self.assertEqual( + Class.function.__module__, Original.function.__module__ + ) def test_class_object_qualname(self): # Test preservation of instance method __qualname__ attribute. @@ -73,20 +77,19 @@ def test_instance_object_qualname(self): def test_instance_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(Class().function.__module__, - Original().function.__module__) + self.assertEqual( + Class().function.__module__, Original().function.__module__ + ) def test_class_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(Class.function.__doc__, - Original.function.__doc__) + self.assertEqual(Class.function.__doc__, Original.function.__doc__) def test_instance_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(Class().function.__doc__, - Original().function.__doc__) + self.assertEqual(Class().function.__doc__, Original().function.__doc__) def test_class_argspec(self): # Test preservation of instance method argument specification. @@ -105,17 +108,17 @@ def test_instance_argspec(self): def test_class_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(Class.function, - type(Original.function))) + self.assertTrue(isinstance(Class.function, type(Original.function))) def test_instance_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(Class().function, - type(Original().function))) + self.assertTrue( + isinstance(Class().function, type(Original().function)) + ) -class TestCallingInnerStaticMethod(unittest.TestCase): +class TestCallingInnerStaticMethod(unittest.TestCase): def test_class_call_function(self): # Test calling staticmethod. @@ -276,5 +279,6 @@ def _function(*args, **kwargs): self.assertEqual(result, (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_instancemethod.py b/tests/test_instancemethod.py index f7ad05ca..5ea1c985 100644 --- a/tests/test_instancemethod.py +++ b/tests/test_instancemethod.py @@ -15,34 +15,40 @@ def passthru_decorator(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) -class OldClass1(): + +class OldClass1: def function(self, arg): '''documentation''' return arg + OldClass1o = OldClass1 -class OldClass1(): + +class OldClass1: @decorators.passthru_decorator def function(self, arg): '''documentation''' return arg + OldClass1d = OldClass1 -class TestNamingInstanceMethodOldStyle(unittest.TestCase): +class TestNamingInstanceMethodOldStyle(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(OldClass1d.function.__name__, - OldClass1o.function.__name__) + self.assertEqual( + OldClass1d.function.__name__, OldClass1o.function.__name__ + ) def test_instance_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(OldClass1d().function.__name__, - OldClass1o().function.__name__) + self.assertEqual( + OldClass1d().function.__name__, OldClass1o().function.__name__ + ) def test_class_object_qualname(self): # Test preservation of instance method __qualname__ attribute. @@ -67,26 +73,30 @@ def test_instance_object_qualname(self): def test_class_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(OldClass1d.function.__module__, - OldClass1o.function.__module__) + self.assertEqual( + OldClass1d.function.__module__, OldClass1o.function.__module__ + ) def test_instance_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(OldClass1d().function.__module__, - OldClass1o().function.__module__) + self.assertEqual( + OldClass1d().function.__module__, OldClass1o().function.__module__ + ) def test_class_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(OldClass1d.function.__doc__, - OldClass1o.function.__doc__) + self.assertEqual( + OldClass1d.function.__doc__, OldClass1o.function.__doc__ + ) def test_instance_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(OldClass1d().function.__doc__, - OldClass1o().function.__doc__) + self.assertEqual( + OldClass1d().function.__doc__, OldClass1o().function.__doc__ + ) def test_class_argspec(self): # Test preservation of instance method argument specification. @@ -109,43 +119,51 @@ def test_getmembers(self): def test_class_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(OldClass1d.function, - type(OldClass1o.function))) + self.assertTrue( + isinstance(OldClass1d.function, type(OldClass1o.function)) + ) def test_instance_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(OldClass1d().function, - type(OldClass1o().function))) + self.assertTrue( + isinstance(OldClass1d().function, type(OldClass1o().function)) + ) + class NewClass1(object): def function(self, arg): '''documentation''' return arg + NewClass1o = NewClass1 + class NewClass1(object): @decorators.passthru_decorator def function(self, arg): '''documentation''' return arg + NewClass1d = NewClass1 -class TestNamingInstanceMethodNewStyle(unittest.TestCase): +class TestNamingInstanceMethodNewStyle(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(NewClass1d.function.__name__, - NewClass1o.function.__name__) + self.assertEqual( + NewClass1d.function.__name__, NewClass1o.function.__name__ + ) def test_instance_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(NewClass1d().function.__name__, - NewClass1o().function.__name__) + self.assertEqual( + NewClass1d().function.__name__, NewClass1o().function.__name__ + ) def test_class_object_qualname(self): # Test preservation of instance method __qualname__ attribute. @@ -170,26 +188,30 @@ def test_instance_object_qualname(self): def test_class_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(NewClass1d.function.__module__, - NewClass1o.function.__module__) + self.assertEqual( + NewClass1d.function.__module__, NewClass1o.function.__module__ + ) def test_instance_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(NewClass1d().function.__module__, - NewClass1o().function.__module__) + self.assertEqual( + NewClass1d().function.__module__, NewClass1o().function.__module__ + ) def test_class_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(NewClass1d.function.__doc__, - NewClass1o.function.__doc__) + self.assertEqual( + NewClass1d.function.__doc__, NewClass1o.function.__doc__ + ) def test_instance_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(NewClass1d().function.__doc__, - NewClass1o().function.__doc__) + self.assertEqual( + NewClass1d().function.__doc__, NewClass1o().function.__doc__ + ) def test_class_argspec(self): # Test preservation of instance method argument specification. @@ -208,17 +230,19 @@ def test_instance_argspec(self): def test_class_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(NewClass1d.function, - type(NewClass1o.function))) + self.assertTrue( + isinstance(NewClass1d.function, type(NewClass1o.function)) + ) def test_instance_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(NewClass1d().function, - type(NewClass1o().function))) + self.assertTrue( + isinstance(NewClass1d().function, type(NewClass1o().function)) + ) -class TestCallingInstanceMethodOldStyle(unittest.TestCase): +class TestCallingInstanceMethodOldStyle(unittest.TestCase): def test_class_call_function(self): # Test calling instancemethod via class and passing in the class # instance directly. @@ -239,12 +263,12 @@ def _decorator(wrapped, instance, args, kwargs): def _function(*args, **kwargs): return args, kwargs - class Class(): + class Class: @_decorator def _function(self, *args, **kwargs): return (args, kwargs) - result = Class._function(*((Class(),)+_args), **_kwargs) + result = Class._function(*((Class(),) + _args), **_kwargs) self.assertEqual(result, (_args, _kwargs)) @@ -267,7 +291,7 @@ def _decorator(wrapped, instance, args, kwargs): def _function(*args, **kwargs): return args, kwargs - class Class(): + class Class: @_decorator def _function(self, *args, **kwargs): return (args, kwargs) @@ -296,13 +320,13 @@ def _decorator(wrapped, instance, args, kwargs): def _function(*args, **kwargs): return args, kwargs - class Class(): + class Class: @_decorator @_decorator def _function(self, *args, **kwargs): return (args, kwargs) - result = Class._function(*((Class(),)+_args), **_kwargs) + result = Class._function(*((Class(),) + _args), **_kwargs) self.assertEqual(result, (_args, _kwargs)) @@ -325,7 +349,7 @@ def _decorator(wrapped, instance, args, kwargs): def _function(*args, **kwargs): return args, kwargs - class Class(): + class Class: @_decorator @_decorator def _function(self, *args, **kwargs): @@ -335,8 +359,8 @@ def _function(self, *args, **kwargs): self.assertEqual(result, (_args, _kwargs)) -class TestCallingInstanceMethodNewStyle(unittest.TestCase): +class TestCallingInstanceMethodNewStyle(unittest.TestCase): def test_class_call_function(self): # Test calling instancemethod via class and passing in the class # instance directly. @@ -453,5 +477,6 @@ def _function(self, *args, **kwargs): self.assertEqual(result, (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_memoize.py b/tests/test_memoize.py index ae8acfd8..9f0b9478 100644 --- a/tests/test_memoize.py +++ b/tests/test_memoize.py @@ -3,6 +3,7 @@ import wrapt + @wrapt.decorator def memoize(wrapped, instance, args, kwargs): if instance is None and inspect.isclass(wrapped): @@ -27,12 +28,13 @@ def memoize(wrapped, instance, args, kwargs): result = cache[key] = wrapped(*args, **kwargs) return result + @memoize def function1(count, text): return count * text -class C1(object): +class C1(object): @memoize def function1(self, count, text): return count * text @@ -47,10 +49,11 @@ def function2(cls, count, text): def function3(count, text): return count * text + c1 = C1() -class TestSynchronized(unittest.TestCase): +class TestSynchronized(unittest.TestCase): def test_function(self): value1 = function1(10, '0123456789') value2 = function1(10, '0123456789') @@ -87,5 +90,6 @@ def test_staticmethod(self): self.assertTrue(hasattr(C1.function3, '_memoize_cache')) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_monkey_patching.py b/tests/test_monkey_patching.py index c341d749..7831b793 100644 --- a/tests/test_monkey_patching.py +++ b/tests/test_monkey_patching.py @@ -3,51 +3,62 @@ import wrapt + def global_function_1(*args, **kwargs): return args, kwargs + def global_function_2(*args, **kwargs): return args, kwargs + def global_function_3(*args, **kwargs): return args, kwargs + def global_function_3_enabled_literal_false(*args, **kwargs): return args, kwargs + def global_function_3_enabled_literal_true(*args, **kwargs): return args, kwargs + def global_function_3_enabled_callable(*args, **kwargs): return args, kwargs + def global_function_4(*args, **kwargs): return args, kwargs + class Class_1(object): def method(self, *args, **kwargs): return args, kwargs + class Class_2(object): @classmethod def method(cls, *args, **kwargs): return cls, args, kwargs + class Class_2_1(Class_2): pass + class Class_2_2(Class_2_1): pass + class Class_3(object): @staticmethod def method(*args, **kwargs): return args, kwargs -class TestMonkeyPatching(unittest.TestCase): +class TestMonkeyPatching(unittest.TestCase): def test_function_wrapper(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -71,7 +82,6 @@ def function(*args, **kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_function_wrapper_instance_method(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -99,7 +109,6 @@ def function(*args, **kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_function_wrapper_class_method(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -126,7 +135,6 @@ def function(*args, **kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_wrap_function_module_name(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -147,7 +155,6 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_wrap_function_module(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -170,7 +177,6 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_wrap_instance_method_module_name(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -185,8 +191,7 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(kwargs, _kwargs) return wrapped(*args, **kwargs) - wrapt.wrap_function_wrapper(__name__, 'Class_1.method', - wrapper) + wrapt.wrap_function_wrapper(__name__, 'Class_1.method', wrapper) result = _instance.method(*_args, **_kwargs) @@ -194,7 +199,6 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_wrap_class_method_module_name(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -207,8 +211,7 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(kwargs, _kwargs) return wrapped(*args, **kwargs) - wrapt.wrap_function_wrapper(__name__, 'Class_2.method', - wrapper) + wrapt.wrap_function_wrapper(__name__, 'Class_2.method', wrapper) result = Class_2.method(*_args, **_kwargs) @@ -227,8 +230,7 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(kwargs, _kwargs) return wrapped(*args, **kwargs) - wrapt.wrap_function_wrapper(__name__, 'Class_2_1.method', - wrapper) + wrapt.wrap_function_wrapper(__name__, 'Class_2_1.method', wrapper) result = Class_2_1.method(*_args, **_kwargs) self.assertEqual(result, (Class_2_1, _args, _kwargs)) @@ -241,7 +243,6 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_wrap_static_method_module_name(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -254,8 +255,7 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(kwargs, _kwargs) return wrapped(*args, **kwargs) - wrapt.wrap_function_wrapper(__name__, 'Class_3.method', - wrapper) + wrapt.wrap_function_wrapper(__name__, 'Class_3.method', wrapper) result = Class_3.method(*_args, **_kwargs) @@ -263,7 +263,6 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_patch_function_module_name(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -283,13 +282,14 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_patch_function_module_name_enabled_literal_false(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} called = [] - @wrapt.patch_function_wrapper(__name__, 'global_function_3_enabled_literal_false', enabled=False) + @wrapt.patch_function_wrapper( + __name__, 'global_function_3_enabled_literal_false', enabled=False + ) def wrapper(wrapped, instance, args, kwargs): called.append((args, kwargs)) self.assertEqual(instance, None) @@ -303,13 +303,14 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called, []) def test_patch_function_module_name_enabled_literal_true(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} called = [] - @wrapt.patch_function_wrapper(__name__, 'global_function_3_enabled_literal_true', enabled=True) + @wrapt.patch_function_wrapper( + __name__, 'global_function_3_enabled_literal_true', enabled=True + ) def wrapper(wrapped, instance, args, kwargs): called.append((args, kwargs)) self.assertEqual(instance, None) @@ -323,7 +324,6 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_patch_function_module_name_enabled_callable(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -334,7 +334,9 @@ def test_patch_function_module_name_enabled_callable(self): def enabled(): return enable - @wrapt.patch_function_wrapper(__name__, 'global_function_3_enabled_callable', enabled=enabled) + @wrapt.patch_function_wrapper( + __name__, 'global_function_3_enabled_callable', enabled=enabled + ) def wrapper(wrapped, instance, args, kwargs): called.append((args, kwargs)) self.assertEqual(instance, None) @@ -355,7 +357,6 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_patch_function_module(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -380,14 +381,14 @@ def _test_transient_function_wrapper(self, *args, **kwargs): return args, kwargs def test_transient_function_wrapper(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} called = [] - @wrapt.transient_function_wrapper(__name__, - 'TestMonkeyPatching._test_transient_function_wrapper') + @wrapt.transient_function_wrapper( + __name__, 'TestMonkeyPatching._test_transient_function_wrapper' + ) def wrapper(wrapped, instance, args, kwargs): called.append((args, kwargs)) self.assertEqual(wrapped, self._test_transient_function_wrapper) @@ -406,7 +407,6 @@ def function(*args, **kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_transient_function_wrapper_instance_method(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -415,11 +415,14 @@ def test_transient_function_wrapper_instance_method(self): _self = self class wrapper(object): - @wrapt.transient_function_wrapper(__name__, - 'TestMonkeyPatching._test_transient_function_wrapper') + @wrapt.transient_function_wrapper( + __name__, 'TestMonkeyPatching._test_transient_function_wrapper' + ) def __call__(self, wrapped, instance, args, kwargs): called.append((args, kwargs)) - _self.assertEqual(wrapped, _self._test_transient_function_wrapper) + _self.assertEqual( + wrapped, _self._test_transient_function_wrapper + ) _self.assertEqual(instance, _self) _self.assertEqual(args, _args) _self.assertEqual(kwargs, _kwargs) @@ -434,10 +437,9 @@ def function(*args, **kwargs): self.assertEqual(result, (_args, _kwargs)) self.assertEqual(called[0], (_args, _kwargs)) -class TestExplicitMonkeyPatching(unittest.TestCase): +class TestExplicitMonkeyPatching(unittest.TestCase): def test_patch_instance_method_class(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -465,7 +467,6 @@ def function(self, *args, **kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_patch_instance_method_dict(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -493,7 +494,6 @@ def function(self, *args, **kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_patch_instance_method_instance(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -521,7 +521,6 @@ def function(self, *args, **kwargs): self.assertEqual(called[0], (_args, _kwargs)) def test_patch_instance_method_extracted(self): - _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -548,5 +547,6 @@ def function(self, *args, **kwargs): self.assertEqual(result, (_args, _kwargs)) self.assertEqual(called[0], (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_nested_function.py b/tests/test_nested_function.py index 5a608a0c..53631d21 100644 --- a/tests/test_nested_function.py +++ b/tests/test_nested_function.py @@ -15,25 +15,31 @@ def passthru_decorator(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + def function1(): def inner(arg): '''documentation''' return arg + return inner + function1o = function1 + def function1(): @decorators.passthru_decorator def inner(arg): '''documentation''' return arg + return inner + function1d = function1 -class TestNamingNestedFunction(unittest.TestCase): +class TestNamingNestedFunction(unittest.TestCase): def test_object_name(self): # Test preservation of function __name__ attribute. @@ -71,8 +77,8 @@ def test_isinstance(self): self.assertTrue(isinstance(function1d(), type(function1o()))) -class TestCallingNestedFunction(unittest.TestCase): +class TestCallingNestedFunction(unittest.TestCase): def test_call_function(self): _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -92,11 +98,13 @@ def _function(): @decorators.passthru_decorator def inner(*args, **kwargs): return args, kwargs + return inner result = _function()(*_args, **_kwargs) self.assertEqual(result, (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_object_proxy.py b/tests/test_object_proxy.py index 1edf062b..663532a2 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -22,8 +22,8 @@ def target(): objects = types.ModuleType('objects') exec(OBJECTS_CODE, objects.__dict__, objects.__dict__) -class TestAttributeAccess(unittest.TestCase): +class TestAttributeAccess(unittest.TestCase): def test_init_not_called(self): a = wrapt.ObjectProxy.__new__(wrapt.ObjectProxy) b = wrapt.ObjectProxy.__new__(wrapt.ObjectProxy) @@ -41,6 +41,7 @@ def test_init_not_called(self): def test_attributes(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) self.assertEqual(function2.__wrapped__, function1) @@ -48,6 +49,7 @@ def function1(*args, **kwargs): def test_get_wrapped(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) self.assertEqual(function2.__wrapped__, function1) @@ -59,6 +61,7 @@ def function1(*args, **kwargs): def test_set_wrapped(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) self.assertEqual(function2, function1) @@ -88,6 +91,7 @@ def function3(*args, **kwargs): def test_delete_wrapped(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) def run(*args): @@ -98,6 +102,7 @@ def run(*args): def test_proxy_attribute(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) function2._self_variable = True @@ -117,6 +122,7 @@ def function1(*args, **kwargs): def test_wrapped_attribute(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) function2.variable = True @@ -185,8 +191,8 @@ def value(self): WrappedObject(Object()).value == "value" -class TestNamingObjectProxy(unittest.TestCase): +class TestNamingObjectProxy(unittest.TestCase): def test_class_object_name(self): # Test preservation of class __name__ attribute. @@ -277,8 +283,8 @@ def test_function_doc_string(self): self.assertEqual(wrapper.__doc__, target.__doc__) -class TestTypeObjectProxy(unittest.TestCase): +class TestTypeObjectProxy(unittest.TestCase): def test_class_of_class(self): # Test preservation of class __class__ attribute. @@ -310,8 +316,8 @@ def test_class_of_function(self): self.assertTrue(isinstance(wrapper, type(target))) -class TestDirObjectProxy(unittest.TestCase): +class TestDirObjectProxy(unittest.TestCase): def test_dir_of_class(self): # Test preservation of class __dir__ attribute. @@ -360,8 +366,8 @@ def test_vars_of_function(self): self.assertEqual(vars(wrapper), vars(target)) -class TestCallingObject(unittest.TestCase): +class TestCallingObject(unittest.TestCase): def test_function_no_args(self): _args = () _kwargs = {} @@ -766,8 +772,8 @@ def function(*args, **kwargs): self.assertEqual(result, (_args, _kwargs)) -class TestIterObjectProxy(unittest.TestCase): +class TestIterObjectProxy(unittest.TestCase): def test_iteration(self): items = [1, 2] @@ -777,12 +783,13 @@ def test_iteration(self): self.assertEqual(result, items) -class TestContextManagerObjectProxy(unittest.TestCase): +class TestContextManagerObjectProxy(unittest.TestCase): def test_context_manager(self): class Class(object): def __enter__(self): return self + def __exit__(*args, **kwargs): return @@ -793,11 +800,12 @@ def __exit__(*args, **kwargs): with wrapper: pass -class TestEqualityObjectProxy(unittest.TestCase): +class TestEqualityObjectProxy(unittest.TestCase): def test_object_hash(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) self.assertEqual(hash(function2), hash(function1)) @@ -805,6 +813,7 @@ def function1(*args, **kwargs): def test_mapping_key(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) table = dict() @@ -846,8 +855,8 @@ def test_comparison(self): self.assertTrue(two == two) self.assertTrue(two != three) -class TestAsNumberObjectProxy(unittest.TestCase): +class TestAsNumberObjectProxy(unittest.TestCase): def test_nonzero(self): true = wrapt.ObjectProxy(True) false = wrapt.ObjectProxy(False) @@ -875,9 +884,9 @@ def test_add(self): one = wrapt.ObjectProxy(1) two = wrapt.ObjectProxy(2) - self.assertEqual(one+two, 1+2) - self.assertEqual(1+two, 1+2) - self.assertEqual(one+2, 1+2) + self.assertEqual(one + two, 1 + 2) + self.assertEqual(1 + two, 1 + 2) + self.assertEqual(one + 2, 1 + 2) def test_add_uninitialized_args(self): result = object() @@ -902,9 +911,9 @@ def test_sub(self): one = wrapt.ObjectProxy(1) two = wrapt.ObjectProxy(2) - self.assertEqual(one-two, 1-2) - self.assertEqual(1-two, 1-2) - self.assertEqual(one-2, 1-2) + self.assertEqual(one - two, 1 - 2) + self.assertEqual(1 - two, 1 - 2) + self.assertEqual(one - 2, 1 - 2) def test_sub_uninitialized_args(self): result = object() @@ -929,9 +938,9 @@ def test_mul(self): two = wrapt.ObjectProxy(2) three = wrapt.ObjectProxy(3) - self.assertEqual(two*three, 2*3) - self.assertEqual(2*three, 2*3) - self.assertEqual(two*3, 2*3) + self.assertEqual(two * three, 2 * 3) + self.assertEqual(2 * three, 2 * 3) + self.assertEqual(two * 3, 2 * 3) def test_mul_uninitialized_args(self): result = object() @@ -959,9 +968,9 @@ def test_div(self): two = wrapt.ObjectProxy(2) three = wrapt.ObjectProxy(3) - self.assertEqual(two/three, 2/3) - self.assertEqual(2/three, 2/3) - self.assertEqual(two/3, 2/3) + self.assertEqual(two / three, 2 / 3) + self.assertEqual(2 / three, 2 / 3) + self.assertEqual(two / 3, 2 / 3) def test_div_uninitialized_args(self): result = object() @@ -986,9 +995,9 @@ def test_floordiv(self): two = wrapt.ObjectProxy(2) four = wrapt.ObjectProxy(4) - self.assertEqual(four//two, 4//2) - self.assertEqual(4//two, 4//2) - self.assertEqual(four//2, 4//2) + self.assertEqual(four // two, 4 // 2) + self.assertEqual(4 // two, 4 // 2) + self.assertEqual(four // 2, 4 // 2) def test_floordiv_uninitialized_args(self): result = object() @@ -1290,12 +1299,12 @@ def test_idiv(self): two = wrapt.ObjectProxy(2) value /= 2 - self.assertEqual(value, 2/2) + self.assertEqual(value, 2 / 2) self.assertEqual(type(value), wrapt.ObjectProxy) value /= two - self.assertEqual(value, 2/2/2) + self.assertEqual(value, 2 / 2 / 2) self.assertEqual(type(value), wrapt.ObjectProxy) @@ -1304,12 +1313,12 @@ def test_ifloordiv(self): two = wrapt.ObjectProxy(2) value //= 2 - self.assertEqual(value, 2//2) + self.assertEqual(value, 2 // 2) self.assertEqual(type(value), wrapt.ObjectProxy) value //= two - self.assertEqual(value, 2//2//2) + self.assertEqual(value, 2 // 2 // 2) self.assertEqual(type(value), wrapt.ObjectProxy) @@ -1453,13 +1462,14 @@ def test_index(self): class Class(object): def __index__(self): return 1 + value = wrapt.ObjectProxy(Class()) items = [0, 1, 2] self.assertEqual(items[value], items[1]) -class TestAsSequenceObjectProxy(unittest.TestCase): +class TestAsSequenceObjectProxy(unittest.TestCase): def test_length(self): value = wrapt.ObjectProxy(list(range(3))) @@ -1512,8 +1522,8 @@ def test_delslice(self): self.assertEqual(len(value), 2) self.assertEqual(value, [0, 4]) -class TestAsMappingObjectProxy(unittest.TestCase): +class TestAsMappingObjectProxy(unittest.TestCase): def test_length(self): value = wrapt.ObjectProxy(dict.fromkeys(range(3), False)) @@ -1545,8 +1555,8 @@ def test_delitem(self): self.assertEqual(len(value), 2) -class TestObjectRepresentationObjectProxy(unittest.TestCase): +class TestObjectRepresentationObjectProxy(unittest.TestCase): def test_str(self): value = wrapt.ObjectProxy(10) @@ -1570,12 +1580,10 @@ def test_repr(self): self.assertNotEqual(repr(value).find('ObjectProxy at'), -1) -class TestDerivedClassCreation(unittest.TestCase): +class TestDerivedClassCreation(unittest.TestCase): def test_derived_new(self): - class DerivedObjectProxy(wrapt.ObjectProxy): - def __new__(cls, wrapped): instance = super(DerivedObjectProxy, cls).__new__(cls) instance.__init__(wrapped) @@ -1589,9 +1597,7 @@ def function(): obj = DerivedObjectProxy(function) def test_derived_setattr(self): - class DerivedObjectProxy(wrapt.ObjectProxy): - def __init__(self, wrapped): self._self_attribute = True super(DerivedObjectProxy, self).__init__(wrapped) @@ -1602,9 +1608,7 @@ def function(): obj = DerivedObjectProxy(function) def test_derived_missing_init(self): - class DerivedObjectProxy(wrapt.ObjectProxy): - def __init__(self, wrapped): self.__wrapped__ = wrapped @@ -1616,10 +1620,9 @@ def function(): self.assertEqual(function, obj) self.assertEqual(function, obj.__wrapped__) -class DerivedClassAttributes(unittest.TestCase): +class DerivedClassAttributes(unittest.TestCase): def test_setup_class_attributes(self): - def function(): pass @@ -1640,7 +1643,6 @@ class DerivedObjectProxy(wrapt.ObjectProxy): self.assertFalse(hasattr(function, 'ATTRIBUTE')) def test_override_class_attributes(self): - def function(): pass @@ -1666,7 +1668,6 @@ class DerivedObjectProxy(wrapt.ObjectProxy): self.assertFalse(hasattr(function, 'ATTRIBUTE')) def test_class_properties(self): - def function(): pass @@ -1674,12 +1675,15 @@ class DerivedObjectProxy(wrapt.ObjectProxy): def __init__(self, wrapped): super(DerivedObjectProxy, self).__init__(wrapped) self._self_attribute = 1 + @property def ATTRIBUTE(self): return self._self_attribute + @ATTRIBUTE.setter def ATTRIBUTE(self, value): self._self_attribute = value + @ATTRIBUTE.deleter def ATTRIBUTE(self): del self._self_attribute @@ -1712,10 +1716,9 @@ def ATTRIBUTE(self): self.assertFalse(hasattr(obj, 'ATTRIBUTE')) self.assertFalse(hasattr(function, 'ATTRIBUTE')) -class OverrideAttributeAccess(unittest.TestCase): +class OverrideAttributeAccess(unittest.TestCase): def test_attr_functions(self): - def function(): pass @@ -1726,7 +1729,6 @@ def function(): self.assertTrue(hasattr(proxy, '__delattr__')) def test_override_getattr(self): - def function(): pass @@ -1749,8 +1751,8 @@ def __getattr__(self, name): self.assertTrue('attribute' in accessed) -class CallableFunction(unittest.TestCase): +class CallableFunction(unittest.TestCase): def test_proxy_hasattr_call(self): proxy = wrapt.ObjectProxy(None) @@ -1781,12 +1783,13 @@ def test_callable_proxy_is_callable(self): self.assertTrue(callable(proxy)) -class SpecialMethods(unittest.TestCase): +class SpecialMethods(unittest.TestCase): def test_class_bytes(self): class Class(object): def __bytes__(self): return b'BYTES' + instance = Class() proxy = wrapt.ObjectProxy(instance) @@ -1808,7 +1811,7 @@ def test_list_reversed(self): self.assertEqual(list(reversed(instance)), list(reversed(proxy))) def test_complex(self): - instance = 1.0+2j + instance = 1.0 + 2j proxy = wrapt.ObjectProxy(instance) @@ -1832,8 +1835,8 @@ def test_fractions_round(self): self.assertEqual(round(instance), round(proxy)) -class TestArgumentUnpacking(unittest.TestCase): +class TestArgumentUnpacking(unittest.TestCase): def test_self_keyword_argument_on_dict(self): # A dict when given self as keyword argument uses it to create item in # the dict and no attempt is made to use a positional argument. @@ -1867,12 +1870,24 @@ def __init__(self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) with self.assertRaises(TypeError) as e: wrapt.CallableObjectProxy(Object)(self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_2(self): class Object: @@ -1883,12 +1898,24 @@ def __init__(self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(arg1='arg1', self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) with self.assertRaises(TypeError) as e: wrapt.CallableObjectProxy(Object)(arg1='arg1', self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_renamed(self): class Object: @@ -1935,15 +1962,27 @@ def __init__(_self, self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(_self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument '_self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument '_self'.*", + str(e.exception), + ), + None, + ) with self.assertRaises(TypeError) as e: wrapt.CallableObjectProxy(Object)(_self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument '_self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument '_self'.*", + str(e.exception), + ), + None, + ) -class TestArgumentUnpackingPartial(unittest.TestCase): +class TestArgumentUnpackingPartial(unittest.TestCase): def test_self_keyword_argument_on_dict_1(self): # A dict when given self as keyword argument uses it to create item in # the dict and no attempt is made to use a positional argument. @@ -2009,14 +2048,26 @@ def __init__(self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) wrapper = wrapt.PartialCallableObjectProxy(Object, self='self') with self.assertRaises(TypeError) as e: o = wrapper() - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_1b(self): class Object: @@ -2027,14 +2078,26 @@ def __init__(self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) wrapper = wrapt.PartialCallableObjectProxy(Object) with self.assertRaises(TypeError) as e: o = wrapper(self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_2a(self): class Object: @@ -2045,14 +2108,28 @@ def __init__(self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(arg1='arg1', self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) - wrapper = wrapt.PartialCallableObjectProxy(Object, arg1='arg1', self='self') + wrapper = wrapt.PartialCallableObjectProxy( + Object, arg1='arg1', self='self' + ) with self.assertRaises(TypeError) as e: o = wrapper() - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_2b(self): class Object: @@ -2063,14 +2140,26 @@ def __init__(self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(arg1='arg1', self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) wrapper = wrapt.PartialCallableObjectProxy(Object) with self.assertRaises(TypeError) as e: o = wrapper(arg1='arg1', self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_renamed_1(self): class Object: @@ -2160,14 +2249,26 @@ def __init__(_self, self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(_self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument '_self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument '_self'.*", + str(e.exception), + ), + None, + ) wrapper = wrapt.PartialCallableObjectProxy(Object, _self='self') with self.assertRaises(TypeError) as e: o = wrapper() - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument '_self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument '_self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_overloaded_2b(self): class Object: @@ -2179,17 +2280,29 @@ def __init__(_self, self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(_self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument '_self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument '_self'.*", + str(e.exception), + ), + None, + ) wrapper = wrapt.PartialCallableObjectProxy(Object) with self.assertRaises(TypeError) as e: o = wrapper(_self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument '_self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument '_self'.*", + str(e.exception), + ), + None, + ) -class TestArgumentUnpackingWrapperBase(unittest.TestCase): +class TestArgumentUnpackingWrapperBase(unittest.TestCase): def test_self_keyword_argument_on_dict(self): # A dict when given self as keyword argument uses it to create item in # the dict and no attempt is made to use a positional argument. @@ -2232,12 +2345,24 @@ def __init__(self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) with self.assertRaises(TypeError) as e: wrapt.FunctionWrapper(Object, wrapper)(self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_2(self): def wrapper(wrapped, instance, args, kwargs): @@ -2251,12 +2376,24 @@ def __init__(self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(arg1='arg1', self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) with self.assertRaises(TypeError) as e: wrapt.FunctionWrapper(Object, wrapper)(arg1='arg1', self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument 'self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument 'self'.*", + str(e.exception), + ), + None, + ) def test_self_keyword_argument_on_class_init_renamed(self): def wrapper(wrapped, instance, args, kwargs): @@ -2312,15 +2449,27 @@ def __init__(_self, self, *args, **kwargs): with self.assertRaises(TypeError) as e: Object(_self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument '_self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument '_self'.*", + str(e.exception), + ), + None, + ) with self.assertRaises(TypeError) as e: wrapt.FunctionWrapper(Object, wrapper)(_self='self') - self.assertNotEqual(re.match(".*got multiple values for (keyword )?argument '_self'.*", str(e.exception)), None) + self.assertNotEqual( + re.match( + ".*got multiple values for (keyword )?argument '_self'.*", + str(e.exception), + ), + None, + ) -class TestArgumentUnpackingBoundFunctionWrapper(unittest.TestCase): +class TestArgumentUnpackingBoundFunctionWrapper(unittest.TestCase): def test_self_keyword_argument_on_classmethod(self): def wrapper(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) @@ -2350,8 +2499,8 @@ def function(_self, self, *args, **kwargs): self.assertEqual(result, ('self', (), {})) -class TestArgumentUnpackingDecorator(unittest.TestCase): +class TestArgumentUnpackingDecorator(unittest.TestCase): def test_self_keyword_argument_on_function(self): @wrapt.decorator def wrapper(wrapped, instance, args, kwargs): @@ -2406,11 +2555,14 @@ def function(_self, self, *args, **kwargs): self.assertEqual(result, ('self', (), dict(arg1='arg1'))) -class TestOverridingSpecialAttributes(unittest.TestCase): +class TestOverridingSpecialAttributes(unittest.TestCase): def test_overriding_class_attribute(self): - class Object1: pass - class Object2(Object1): pass + class Object1: + pass + + class Object2(Object1): + pass o1 = Object1() @@ -2424,5 +2576,6 @@ class Object2(Object1): pass self.assertEqual(o2.__class__, type(o1)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_outer_classmethod.py b/tests/test_outer_classmethod.py index 3cc9ce90..47a9926d 100644 --- a/tests/test_outer_classmethod.py +++ b/tests/test_outer_classmethod.py @@ -17,14 +17,17 @@ def passthru_decorator(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + class Class(object): @classmethod def function(self, arg): '''documentation''' return arg + Original = Class + class Class(object): @classmethod @decorators.passthru_decorator @@ -32,19 +35,19 @@ def function(self, arg): '''documentation''' return arg -class TestNamingOuterClassMethod(unittest.TestCase): +class TestNamingOuterClassMethod(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(Class.function.__name__, - Original.function.__name__) + self.assertEqual(Class.function.__name__, Original.function.__name__) def test_instance_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(Class().function.__name__, - Original().function.__name__) + self.assertEqual( + Class().function.__name__, Original().function.__name__ + ) def test_class_object_qualname(self): # Test preservation of instance method __qualname__ attribute. @@ -69,26 +72,26 @@ def test_instance_object_qualname(self): def test_class_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(Class.function.__module__, - Original.function.__module__) + self.assertEqual( + Class.function.__module__, Original.function.__module__ + ) def test_instance_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(Class().function.__module__, - Original().function.__module__) + self.assertEqual( + Class().function.__module__, Original().function.__module__ + ) def test_class_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(Class.function.__doc__, - Original.function.__doc__) + self.assertEqual(Class.function.__doc__, Original.function.__doc__) def test_instance_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(Class().function.__doc__, - Original().function.__doc__) + self.assertEqual(Class().function.__doc__, Original().function.__doc__) def test_class_argspec(self): # Test preservation of instance method argument specification. @@ -107,17 +110,17 @@ def test_instance_argspec(self): def test_class_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(Class.function, - type(Original.function))) + self.assertTrue(isinstance(Class.function, type(Original.function))) def test_instance_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(Class().function, - type(Original().function))) + self.assertTrue( + isinstance(Class().function, type(Original().function)) + ) -class TestCallingOuterClassMethod(unittest.TestCase): +class TestCallingOuterClassMethod(unittest.TestCase): def test_class_call_function(self): # Test calling classmethod. Prior to Python 3.9, the instance # and class passed to the wrapper will both be None because our @@ -135,7 +138,7 @@ def test_class_call_function(self): def _decorator(wrapped, instance, args, kwargs): if PYXY < (3, 9): self.assertEqual(instance, None) - self.assertEqual(args, (Class,)+_args) + self.assertEqual(args, (Class,) + _args) else: self.assertEqual(instance, Class) self.assertEqual(args, _args) @@ -177,7 +180,7 @@ def test_instance_call_function(self): def _decorator(wrapped, instance, args, kwargs): if PYXY < (3, 9): self.assertEqual(instance, None) - self.assertEqual(args, (Class,)+_args) + self.assertEqual(args, (Class,) + _args) else: self.assertEqual(instance, Class) self.assertEqual(args, _args) @@ -202,5 +205,6 @@ def _function(cls, *args, **kwargs): self.assertEqual(result, (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_outer_staticmethod.py b/tests/test_outer_staticmethod.py index 60dfe0b9..778aed64 100644 --- a/tests/test_outer_staticmethod.py +++ b/tests/test_outer_staticmethod.py @@ -15,14 +15,17 @@ def passthru_decorator(wrapped, instance, args, kwargs): decorators = types.ModuleType('decorators') exec(DECORATORS_CODE, decorators.__dict__, decorators.__dict__) + class Class(object): @staticmethod def function(self, arg): '''documentation''' return arg + Original = Class + class Class(object): @staticmethod @decorators.passthru_decorator @@ -30,19 +33,19 @@ def function(self, arg): '''documentation''' return arg -class TestNamingOuterStaticMethod(unittest.TestCase): +class TestNamingOuterStaticMethod(unittest.TestCase): def test_class_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(Class.function.__name__, - Original.function.__name__) + self.assertEqual(Class.function.__name__, Original.function.__name__) def test_instance_object_name(self): # Test preservation of instance method __name__ attribute. - self.assertEqual(Class().function.__name__, - Original().function.__name__) + self.assertEqual( + Class().function.__name__, Original().function.__name__ + ) def test_class_object_qualname(self): # Test preservation of instance method __qualname__ attribute. @@ -67,26 +70,26 @@ def test_instance_object_qualname(self): def test_class_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(Class.function.__module__, - Original.function.__module__) + self.assertEqual( + Class.function.__module__, Original.function.__module__ + ) def test_instance_module_name(self): # Test preservation of instance method __module__ attribute. - self.assertEqual(Class().function.__module__, - Original().function.__module__) + self.assertEqual( + Class().function.__module__, Original().function.__module__ + ) def test_class_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(Class.function.__doc__, - Original.function.__doc__) + self.assertEqual(Class.function.__doc__, Original.function.__doc__) def test_instance_doc_string(self): # Test preservation of instance method __doc__ attribute. - self.assertEqual(Class().function.__doc__, - Original().function.__doc__) + self.assertEqual(Class().function.__doc__, Original().function.__doc__) def test_class_argspec(self): # Test preservation of instance method argument specification. @@ -105,17 +108,17 @@ def test_instance_argspec(self): def test_class_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(Class.function, - type(Original.function))) + self.assertTrue(isinstance(Class.function, type(Original.function))) def test_instance_isinstance(self): # Test preservation of isinstance() checks. - self.assertTrue(isinstance(Class().function, - type(Original().function))) + self.assertTrue( + isinstance(Class().function, type(Original().function)) + ) -class TestCallingOuterStaticMethod(unittest.TestCase): +class TestCallingOuterStaticMethod(unittest.TestCase): def test_class_call_function(self): # Test calling staticmethod. The instance and class passed to the # wrapper will both be None because our decorator is surrounded @@ -177,5 +180,6 @@ def _function(*args, **kwargs): self.assertEqual(result, (_args, _kwargs)) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_pickle.py b/tests/test_pickle.py index 291c747c..872c11e7 100644 --- a/tests/test_pickle.py +++ b/tests/test_pickle.py @@ -3,21 +3,23 @@ import wrapt -class CustomObjectProxy(wrapt.ObjectProxy): +class CustomObjectProxy(wrapt.ObjectProxy): def __reduce_ex__(self, proto): return (list, (self.__wrapped__,)) -class TestObjectPickle(unittest.TestCase): +class TestObjectPickle(unittest.TestCase): def test_pickle(self): proxy = wrapt.ObjectProxy([1]) with self.assertRaises(NotImplementedError) as context: data = pickle.dumps(proxy) - self.assertTrue(str(context.exception) == - 'object proxy must define __reduce_ex__()') + self.assertTrue( + str(context.exception) + == 'object proxy must define __reduce_ex__()' + ) def test_pickle_proxy(self): proxy1 = CustomObjectProxy([1]) @@ -26,5 +28,6 @@ def test_pickle_proxy(self): self.assertEqual(proxy1.__wrapped__, restored) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_post_import_hooks.py b/tests/test_post_import_hooks.py index 00e8f5ee..5ec1bce7 100644 --- a/tests/test_post_import_hooks.py +++ b/tests/test_post_import_hooks.py @@ -7,7 +7,6 @@ class TestPostImportHooks(unittest.TestCase): - def setUp(self): super(TestPostImportHooks, self).setUp() @@ -80,6 +79,7 @@ def hook_this(module): invoked.append(1) import this + self.assertEqual(len(invoked), 1) del sys.modules['this'] @@ -131,6 +131,7 @@ def hook_xxx(module): self.assertFalse(thread.is_alive()) import this + del sys.modules['this'] def test_import_deadlock_3(self): @@ -167,6 +168,7 @@ def worker(): self.assertFalse(thread.is_alive()) import this + del sys.modules['this'] self.assertEqual(hooks_called, ['this', 'wsgiref']) @@ -179,8 +181,10 @@ def hook_this(module): import this from importlib.machinery import SourceFileLoader + self.assertIsInstance(this.__loader__, SourceFileLoader) self.assertIsInstance(this.__spec__.loader, SourceFileLoader) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_synchronized_lock.py b/tests/test_synchronized_lock.py index f98b3873..ff894eb6 100644 --- a/tests/test_synchronized_lock.py +++ b/tests/test_synchronized_lock.py @@ -4,12 +4,13 @@ from compat import PYXY + @wrapt.synchronized def function(): print('function') -class C1(object): +class C1(object): @wrapt.synchronized def function1(self): print('function1') @@ -24,18 +25,21 @@ def function2(cls): def function3(): print('function3') + c1 = C1() + @wrapt.synchronized class C2(object): pass + @wrapt.synchronized class C3: pass -class C4(object): +class C4(object): # Prior to Python 3.9, this yields undesirable results due to how # class method is implemented. The classmethod doesn't bind the # method to the class before calling. As a consequence, the @@ -54,22 +58,25 @@ def function2(cls): def function3(): print('function3') + c4 = C4() -class C5(object): +class C5(object): def __bool__(self): return False - __nonzero__=__bool__ + + __nonzero__ = __bool__ @wrapt.synchronized def function1(self): print('function1') + c5 = C5() -class TestSynchronized(unittest.TestCase): +class TestSynchronized(unittest.TestCase): def test_synchronized_function(self): _lock0 = getattr(function, '_synchronized_lock', None) self.assertEqual(_lock0, None) @@ -292,5 +299,6 @@ def test_synchronized_false_instance(self): _lock2 = getattr(c5, '_synchronized_lock', None) self.assertNotEqual(_lock2, None) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_update_attributes.py b/tests/test_update_attributes.py index b21fc244..19af79bd 100644 --- a/tests/test_update_attributes.py +++ b/tests/test_update_attributes.py @@ -7,8 +7,8 @@ def passthru_decorator(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) -class TestUpdateAttributes(unittest.TestCase): +class TestUpdateAttributes(unittest.TestCase): def test_update_name(self): @passthru_decorator def function(): @@ -37,14 +37,14 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(instance.__name__, 'override_name') def test_update_qualname(self): - @passthru_decorator def function(): pass method = self.test_update_qualname - self.assertEqual(function.__qualname__, - (method.__qualname__ + '..function')) + self.assertEqual( + function.__qualname__, (method.__qualname__ + '..function') + ) function.__qualname__ = 'override_qualname' @@ -60,8 +60,9 @@ def wrapper(wrapped, instance, args, kwargs): instance = wrapt.FunctionWrapper(function, wrapper) method = self.test_update_qualname_modified_on_original - self.assertEqual(instance.__qualname__, - (method.__qualname__ + '..function')) + self.assertEqual( + instance.__qualname__, (method.__qualname__ + '..function') + ) instance.__qualname__ = 'override_qualname' @@ -133,7 +134,9 @@ def function(): override_annotations = {'override_annotations': ''} function.__annotations__ = override_annotations - self.assertEqual(function.__wrapped__.__annotations__, override_annotations) + self.assertEqual( + function.__wrapped__.__annotations__, override_annotations + ) self.assertEqual(function.__annotations__, override_annotations) def test_update_annotations_modified_on_original(self): @@ -151,5 +154,6 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(function.__annotations__, override_annotations) self.assertEqual(instance.__annotations__, override_annotations) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_weak_function_proxy.py b/tests/test_weak_function_proxy.py index c3718a30..a0ea983a 100644 --- a/tests/test_weak_function_proxy.py +++ b/tests/test_weak_function_proxy.py @@ -3,8 +3,8 @@ import wrapt -class TestWeakFunctionProxy(unittest.TestCase): +class TestWeakFunctionProxy(unittest.TestCase): def test_isinstance(self): def function(a, b): return a, b @@ -188,15 +188,18 @@ def squeal(self): self.assertEqual(method(), 'bark') -class TestArgumentUnpackingWeakFunctionProxy(unittest.TestCase): +class TestArgumentUnpackingWeakFunctionProxy(unittest.TestCase): def test_self_keyword_argument(self): def function(self, *args, **kwargs): return self, args, kwargs proxy = wrapt.WeakFunctionProxy(function) - self.assertEqual(proxy(self='self', arg1='arg1'), ('self', (), dict(arg1='arg1'))) + self.assertEqual( + proxy(self='self', arg1='arg1'), ('self', (), dict(arg1='arg1')) + ) + if __name__ == '__main__': unittest.main() From 0b787f23b6ede3c7e047dff28c8a2312e37ebcbc Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 12:53:08 +0100 Subject: [PATCH 14/19] Enable ruff linting Signed-off-by: Stephen Finucane --- .pre-commit-config.yaml | 4 ++-- docs/conf.py | 4 +--- setup.py | 1 - src/wrapt/__init__.py | 27 +++++++++++++++++++++++++++ src/wrapt/__wrapt__.py | 9 +++++++++ src/wrapt/decorators.py | 3 --- tests/test_adapter_py33.py | 1 - tests/test_class.py | 4 ++-- tests/test_copy.py | 4 ++-- tests/test_formatargspec_py38.py | 1 - tests/test_function.py | 4 ++-- tests/test_instancemethod.py | 4 ++-- tests/test_object_proxy.py | 22 +++++++++++----------- tests/test_pickle.py | 2 +- tests/test_post_import_hooks.py | 20 ++++++++++---------- tests/test_synchronized_lock.py | 12 ++++++------ 16 files changed, 75 insertions(+), 47 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fa30ede2..52a5f680 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,6 +16,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.5.0 hooks: - #- id: ruff - # args: [ --fix ] + - id: ruff + args: [ --fix ] - id: ruff-format diff --git a/docs/conf.py b/docs/conf.py index 17fb785b..6bf45b73 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,7 +11,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import sphinx_rtd_theme # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -95,8 +95,6 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] diff --git a/setup.py b/setup.py index 4fd8058d..44ead8fd 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ import os -import sys import platform import setuptools diff --git a/src/wrapt/__init__.py b/src/wrapt/__init__.py index 082fc44b..37ab926c 100644 --- a/src/wrapt/__init__.py +++ b/src/wrapt/__init__.py @@ -48,3 +48,30 @@ # bundled implementation here in case any user of wrapt was also needing it. from .arguments import formatargspec + +__all__ = [ + 'ObjectProxy', + 'CallableObjectProxy', + 'FunctionWrapper', + 'BoundFunctionWrapper', + 'PartialCallableObjectProxy', + 'resolve_path', + 'apply_patch', + 'wrap_object', + 'wrap_object_attribute', + 'function_wrapper', + 'wrap_function_wrapper', + 'patch_function_wrapper', + 'transient_function_wrapper', + 'WeakFunctionProxy', + 'adapter_factory', + 'AdapterFactory', + 'decorator', + 'synchronized', + 'register_post_import_hook', + 'when_imported', + 'notify_module_loaded', + 'discover_post_import_hooks', + 'getcallargs', + 'formatargspec', +] diff --git a/src/wrapt/__wrapt__.py b/src/wrapt/__wrapt__.py index c25eb1a2..c2b1271a 100644 --- a/src/wrapt/__wrapt__.py +++ b/src/wrapt/__wrapt__.py @@ -6,3 +6,12 @@ BoundFunctionWrapper, _FunctionWrapperBase, ) + +__all__ = [ + 'ObjectProxy', + 'CallableObjectProxy', + 'PartialCallableObjectProxy', + 'FunctionWrapper', + 'BoundFunctionWrapper', + '_FunctionWrapperBase', +] diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index d1d373c6..ede087dd 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -3,8 +3,6 @@ """ -import sys - from functools import partial from inspect import isclass, signature from threading import Lock, RLock @@ -14,7 +12,6 @@ from .__wrapt__ import ( FunctionWrapper, BoundFunctionWrapper, - ObjectProxy, CallableObjectProxy, ) diff --git a/tests/test_adapter_py33.py b/tests/test_adapter_py33.py index 65ab5edb..a9022522 100644 --- a/tests/test_adapter_py33.py +++ b/tests/test_adapter_py33.py @@ -2,7 +2,6 @@ import types import unittest -import wrapt DECORATORS_CODE = """ import wrapt diff --git a/tests/test_class.py b/tests/test_class.py index 86592fed..154811b0 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -27,8 +27,8 @@ class class1(object): class TestIntrospection(unittest.TestCase): def test_getmembers(self): - class1o_members = inspect.getmembers(class1o) - class1d_members = inspect.getmembers(class1d) + inspect.getmembers(class1o) + inspect.getmembers(class1d) class TestInheritance(unittest.TestCase): diff --git a/tests/test_copy.py b/tests/test_copy.py index 97e94e0d..1955a4d2 100644 --- a/tests/test_copy.py +++ b/tests/test_copy.py @@ -17,7 +17,7 @@ def test_copy(self): proxy1 = wrapt.ObjectProxy([1]) with self.assertRaises(NotImplementedError) as context: - proxy2 = copy.copy(proxy1) + copy.copy(proxy1) self.assertTrue( str(context.exception) == 'object proxy must define __copy__()' @@ -27,7 +27,7 @@ def test_deepcopy(self): proxy1 = wrapt.ObjectProxy([1]) with self.assertRaises(NotImplementedError) as context: - proxy2 = copy.deepcopy(proxy1) + copy.deepcopy(proxy1) self.assertTrue( str(context.exception) == 'object proxy must define __deepcopy__()' diff --git a/tests/test_formatargspec_py38.py b/tests/test_formatargspec_py38.py index b0c5e7f8..38f0b940 100644 --- a/tests/test_formatargspec_py38.py +++ b/tests/test_formatargspec_py38.py @@ -1,5 +1,4 @@ import unittest -import sys from inspect import getfullargspec from wrapt import formatargspec diff --git a/tests/test_function.py b/tests/test_function.py index 262ca915..fd628290 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -60,8 +60,8 @@ def test_argspec(self): self.assertEqual(function1o_argspec, function1d_argspec) def test_getmembers(self): - function1o_members = inspect.getmembers(function1o) - function1d_members = inspect.getmembers(function1d) + inspect.getmembers(function1o) + inspect.getmembers(function1d) def test_isinstance(self): # Test preservation of isinstance() checks. diff --git a/tests/test_instancemethod.py b/tests/test_instancemethod.py index 5ea1c985..94942506 100644 --- a/tests/test_instancemethod.py +++ b/tests/test_instancemethod.py @@ -113,8 +113,8 @@ def test_instance_argspec(self): self.assertEqual(original_argspec, function_argspec) def test_getmembers(self): - original_members = inspect.getmembers(OldClass1o().function) - function_members = inspect.getmembers(OldClass1d().function) + inspect.getmembers(OldClass1o().function) + inspect.getmembers(OldClass1d().function) def test_class_isinstance(self): # Test preservation of isinstance() checks. diff --git a/tests/test_object_proxy.py b/tests/test_object_proxy.py index 663532a2..f0e35323 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -3,10 +3,10 @@ import types import unittest -is_pypy = '__pypy__' in sys.builtin_module_names - import wrapt +is_pypy = '__pypy__' in sys.builtin_module_names + OBJECTS_CODE = """ class TargetBaseClass(object): "documentation" @@ -166,7 +166,7 @@ def value(self): try: WrappedObject(Object()).value == "value" - except ValueError as e: + except ValueError: pass else: @@ -1594,7 +1594,7 @@ def __init__(self, wrapped): def function(): pass - obj = DerivedObjectProxy(function) + DerivedObjectProxy(function) def test_derived_setattr(self): class DerivedObjectProxy(wrapt.ObjectProxy): @@ -1605,7 +1605,7 @@ def __init__(self, wrapped): def function(): pass - obj = DerivedObjectProxy(function) + DerivedObjectProxy(function) def test_derived_missing_init(self): class DerivedObjectProxy(wrapt.ObjectProxy): @@ -2059,7 +2059,7 @@ def __init__(self, *args, **kwargs): wrapper = wrapt.PartialCallableObjectProxy(Object, self='self') with self.assertRaises(TypeError) as e: - o = wrapper() + wrapper() self.assertNotEqual( re.match( @@ -2089,7 +2089,7 @@ def __init__(self, *args, **kwargs): wrapper = wrapt.PartialCallableObjectProxy(Object) with self.assertRaises(TypeError) as e: - o = wrapper(self='self') + wrapper(self='self') self.assertNotEqual( re.match( @@ -2121,7 +2121,7 @@ def __init__(self, *args, **kwargs): ) with self.assertRaises(TypeError) as e: - o = wrapper() + wrapper() self.assertNotEqual( re.match( @@ -2151,7 +2151,7 @@ def __init__(self, *args, **kwargs): wrapper = wrapt.PartialCallableObjectProxy(Object) with self.assertRaises(TypeError) as e: - o = wrapper(arg1='arg1', self='self') + wrapper(arg1='arg1', self='self') self.assertNotEqual( re.match( @@ -2260,7 +2260,7 @@ def __init__(_self, self, *args, **kwargs): wrapper = wrapt.PartialCallableObjectProxy(Object, _self='self') with self.assertRaises(TypeError) as e: - o = wrapper() + wrapper() self.assertNotEqual( re.match( @@ -2291,7 +2291,7 @@ def __init__(_self, self, *args, **kwargs): wrapper = wrapt.PartialCallableObjectProxy(Object) with self.assertRaises(TypeError) as e: - o = wrapper(_self='self') + wrapper(_self='self') self.assertNotEqual( re.match( diff --git a/tests/test_pickle.py b/tests/test_pickle.py index 872c11e7..550b2204 100644 --- a/tests/test_pickle.py +++ b/tests/test_pickle.py @@ -14,7 +14,7 @@ def test_pickle(self): proxy = wrapt.ObjectProxy([1]) with self.assertRaises(NotImplementedError) as context: - data = pickle.dumps(proxy) + pickle.dumps(proxy) self.assertTrue( str(context.exception) diff --git a/tests/test_post_import_hooks.py b/tests/test_post_import_hooks.py index 5ec1bce7..3bb4aa27 100644 --- a/tests/test_post_import_hooks.py +++ b/tests/test_post_import_hooks.py @@ -27,14 +27,14 @@ def hook_this(module): self.assertEqual(len(invoked), 0) - import this + import this # noqa self.assertEqual(len(invoked), 1) def test_after_import(self): invoked = [] - import this + import this # noqa self.assertEqual(len(invoked), 0) @@ -57,7 +57,7 @@ def hook_this_one(module): self.assertEqual(len(invoked_one), 0) self.assertEqual(len(invoked_two), 0) - import this + import this # noqa self.assertEqual(len(invoked_one), 1) self.assertEqual(len(invoked_two), 0) @@ -78,13 +78,13 @@ def hook_this(module): self.assertEqual(module.__name__, 'this') invoked.append(1) - import this + import this # noqa self.assertEqual(len(invoked), 1) del sys.modules['this'] wrapt.register_post_import_hook(hook_this, 'this') - import this + import this # noqa self.assertEqual(len(invoked), 2) @@ -94,7 +94,7 @@ def test_import_deadlock_1(self): # been imported, creates a thread which in turn attempts to register # another import hook. - import this + import this # noqa @wrapt.when_imported('this') def hook_this(module): @@ -130,7 +130,7 @@ def hook_xxx(module): self.assertFalse(thread.is_alive()) - import this + import this # noqa del sys.modules['this'] @@ -159,7 +159,7 @@ def hook_wsgiref(module): hooks_called.append('wsgiref') def worker(): - import wsgiref + import wsgiref # noqa thread = threading.Thread(target=worker) thread.start() @@ -167,7 +167,7 @@ def worker(): self.assertFalse(thread.is_alive()) - import this + import this # noqa del sys.modules['this'] @@ -178,7 +178,7 @@ def test_loader(self): def hook_this(module): pass - import this + import this # noqa from importlib.machinery import SourceFileLoader diff --git a/tests/test_synchronized_lock.py b/tests/test_synchronized_lock.py index ff894eb6..60736965 100644 --- a/tests/test_synchronized_lock.py +++ b/tests/test_synchronized_lock.py @@ -247,18 +247,18 @@ def test_synchronized_type_new_style(self): _lock0 = getattr(C2, '_synchronized_lock', None) self.assertEqual(_lock0, None) - c2 = C2() + C2() _lock1 = getattr(C2, '_synchronized_lock', None) self.assertNotEqual(_lock1, None) - c2 = C2() + C2() _lock2 = getattr(C2, '_synchronized_lock', None) self.assertNotEqual(_lock2, None) self.assertEqual(_lock2, _lock1) - c2 = C2() + C2() _lock3 = getattr(C2, '_synchronized_lock', None) self.assertNotEqual(_lock3, None) @@ -271,18 +271,18 @@ def test_synchronized_type_old_style(self): _lock0 = getattr(C3, '_synchronized_lock', None) self.assertEqual(_lock0, None) - c2 = C3() + C3() _lock1 = getattr(C3, '_synchronized_lock', None) self.assertNotEqual(_lock1, None) - c2 = C3() + C3() _lock2 = getattr(C3, '_synchronized_lock', None) self.assertNotEqual(_lock2, None) self.assertEqual(_lock2, _lock1) - c2 = C3() + C3() _lock3 = getattr(C3, '_synchronized_lock', None) self.assertNotEqual(_lock3, None) From 8f65b12bf70352f94970fd5db15d693300a0838a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 13:06:01 +0100 Subject: [PATCH 15/19] docs: Remove cruft from configuration file Signed-off-by: Stephen Finucane --- docs/conf.py | 208 ++------------------------------------------------- 1 file changed, 6 insertions(+), 202 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 6bf45b73..4b05458d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,31 +1,8 @@ -# -*- coding: utf-8 -*- -# -# wrapt documentation build configuration file, created by -# sphinx-quickstart on Tue Aug 13 20:38:04 2013. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. +# wrapt documentation build configuration file import sphinx_rtd_theme -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [] +# -- General configuration ---------------------------------------------------- # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -33,15 +10,12 @@ # The suffix of source filenames. source_suffix = '.rst' -# The encoding of source files. -# source_encoding = 'utf-8-sig' - # The master toctree document. master_doc = 'index' # General information about the project. project = 'wrapt' -copyright = '2013-2023, Graham Dumpleton' +copyright = '2013-, Graham Dumpleton' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -52,45 +26,15 @@ # The full version, including alpha/beta/rc tags. release = '1.16.0' -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] -# The reST default role (used for this markup: `text`) to use for all documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False - -# -- Options for HTML output --------------------------------------------------- +# -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. @@ -98,93 +42,15 @@ html_theme = 'sphinx_rtd_theme' html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -# html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -# html_favicon = None - # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True +# -- Options for LaTeX output ------------------------------------------------- -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'wraptdoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - #'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - #'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). +# Grouping the document tree into LaTeX files. latex_documents = [ ( 'index', @@ -194,65 +60,3 @@ 'manual', ), ] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'wrapt', 'wrapt Documentation', ['Graham Dumpleton'], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------------ - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - 'index', - 'wrapt', - 'wrapt Documentation', - 'Graham Dumpleton', - 'wrapt', - 'One line description of project.', - 'Miscellaneous', - ), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False From 2b60be764eab6a39ea5c6b839786055b1a39aaa3 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 13:11:44 +0100 Subject: [PATCH 16/19] Enable mypy linting Signed-off-by: Stephen Finucane --- .pre-commit-config.yaml | 11 +++++++++++ src/wrapt/decorators.py | 2 +- src/wrapt/importer.py | 3 ++- src/wrapt/wrappers.py | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 52a5f680..6f916f0e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,3 +19,14 @@ repos: - id: ruff args: [ --fix ] - id: ruff-format + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.10.1 + hooks: + - id: mypy + exclude: | + (?x)( + tests/.* + | docs/.* + ) + additional_dependencies: + - "types-setuptools" diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index ede087dd..41459b7f 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -512,4 +512,4 @@ def __exit__(self, *args): return _FinalDecorator(wrapped=wrapped, wrapper=_synchronized_wrapper) -synchronized._synchronized_meta_lock = Lock() +setattr(synchronized, '_synchronized_meta_lock', Lock()) diff --git a/src/wrapt/importer.py b/src/wrapt/importer.py index a5329ca2..2418f9da 100644 --- a/src/wrapt/importer.py +++ b/src/wrapt/importer.py @@ -6,6 +6,7 @@ from importlib.util import find_spec import sys import threading +from typing import Callable from .__wrapt__ import ObjectProxy @@ -15,7 +16,7 @@ # module will be truncated but the list left in the dictionary. This # acts as a flag to indicate that the module had already been imported. -_post_import_hooks = {} +_post_import_hooks: dict[str, list[Callable[[object], object]]] = {} _post_import_hooks_init = False _post_import_hooks_lock = threading.RLock() diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index 5446365c..16313759 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -337,7 +337,7 @@ def __imod__(self, other): self.__wrapped__ %= other return self - def __ipow__(self, other): + def __ipow__(self, other, *args): self.__wrapped__ **= other return self From 410e42bcc5d6206484ab0ad30b3d06e263aeea58 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 28 Jun 2024 13:42:53 +0100 Subject: [PATCH 17/19] Add initial type hints This is *super* early, but it add hints for the two most commonly used entry points for wrapt. Signed-off-by: Stephen Finucane --- src/wrapt/decorators.py | 30 +++++++++++++++++++++++++++++- src/wrapt/importer.py | 4 ++-- src/wrapt/wrappers.py | 13 +++++++++---- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/wrapt/decorators.py b/src/wrapt/decorators.py index 41459b7f..00065125 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -6,6 +6,7 @@ from functools import partial from inspect import isclass, signature from threading import Lock, RLock +from typing import Any, Callable, Optional, Type, TypeVar, Union, overload from .arguments import formatargspec @@ -15,6 +16,10 @@ CallableObjectProxy, ) +F = TypeVar('F', bound=Callable[..., Any]) +A = TypeVar('A', bound=Callable[..., Any]) +T = TypeVar('T', bound=Any) + # Adapter wrapper for the wrapped function which will overlay certain # properties from the adapter function onto the wrapped function so that # functions such as inspect.getfullargspec(), inspect.signature() and @@ -141,7 +146,30 @@ def __call__(self, wrapped): # original wrapped function. -def decorator(wrapper=None, enabled=None, adapter=None, proxy=FunctionWrapper): +@overload +def decorator( + wrapper: None = None, + enabled: Optional[bool] = None, + adapter: Optional[A] = None, + proxy: Type[FunctionWrapper] = FunctionWrapper, +) -> 'partial[F]': ... + + +@overload +def decorator( + wrapper: F, + enabled: Optional[bool] = None, + adapter: Optional[A] = None, + proxy: Type[FunctionWrapper] = FunctionWrapper, +) -> F: ... + + +def decorator( + wrapper: Optional[F] = None, + enabled: Optional[bool] = None, + adapter: Optional[A] = None, + proxy: Type[FunctionWrapper] = FunctionWrapper, +) -> Union[F, 'partial[F]']: # The decorator should be supplied with a single positional argument # which is the wrapper function to be used to implement the # decorator. This may be preceded by a step whereby the keyword diff --git a/src/wrapt/importer.py b/src/wrapt/importer.py index 2418f9da..c94b24d2 100644 --- a/src/wrapt/importer.py +++ b/src/wrapt/importer.py @@ -6,7 +6,7 @@ from importlib.util import find_spec import sys import threading -from typing import Callable +from typing import Callable, Dict, List from .__wrapt__ import ObjectProxy @@ -16,7 +16,7 @@ # module will be truncated but the list left in the dictionary. This # acts as a flag to indicate that the module had already been imported. -_post_import_hooks: dict[str, list[Callable[[object], object]]] = {} +_post_import_hooks: Dict[str, List[Callable[[object], object]]] = {} _post_import_hooks_init = False _post_import_hooks_lock = threading.RLock() diff --git a/src/wrapt/wrappers.py b/src/wrapt/wrappers.py index 16313759..5c4c3ccd 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -1,6 +1,10 @@ -import sys -import operator import inspect +import operator +import sys +from typing import Any, Generic, TypeVar + + +T = TypeVar("T", bound=Any) class _ObjectProxyMethods(object): @@ -61,10 +65,11 @@ def __new__(cls, name, bases, dictionary): class _ObjectProxyBase(metaclass=_ObjectProxyMetaType): ... -class ObjectProxy(_ObjectProxyBase): +class ObjectProxy(_ObjectProxyBase, Generic[T]): __slots__ = '__wrapped__' + __wrapped__: T - def __init__(self, wrapped): + def __init__(self, wrapped: T): object.__setattr__(self, '__wrapped__', wrapped) # Python 3.2+ has the __qualname__ attribute, but it does not From a0f6dfa762ce9c49d0458c2d85a7f2d03720d3c8 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 4 Jul 2024 15:21:05 +0100 Subject: [PATCH 18/19] tox: Rename pypy target Without suffix we end up using pypy2, which is incompatible. Signed-off-by: Stephen Finucane --- tox.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tox.ini b/tox.ini index 1a3d71d1..c23e4e9b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 4.0.0 -envlist = py{38,39,310,311,312},py{38,39,310,311,312}-{without,install,disable}-extensions,pypy-without-extensions +envlist = py{38,39,310,311,312},py{38,39,310,311,312}-{without,install,disable}-extensions,pypy{38,39,310,311}-without-extensions [testenv] setenv = @@ -29,6 +29,6 @@ python = 3.10: lint, py310, py310-without-extensions, py310-install-extensions, py310-disable-extensions 3.11: lint, py311, py311-without-extensions, py311-install-extensions, py311-disable-extensions 3.12: lint, py312, py312-without-extensions, py312-install-extensions, py312-disable-extensionws - pypy-3.8: lint, pypy-without-extensions - pypy-3.9: lint, pypy-without-extensions - pypy-3.10: lint, pypy-without-extensions + pypy-3.8: lint, pypy38-without-extensions + pypy-3.9: lint, pypy39-without-extensions + pypy-3.10: lint, pypy310-without-extensions From a45972d4a76c18016c985bee460fee6e38d80607 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 5 Jul 2024 10:44:52 +0100 Subject: [PATCH 19/19] Update GitHub action for building wheels. Signed-off-by: Stephen Finucane --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 002dc216..83cf89f8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -193,7 +193,7 @@ jobs: if: ${{ matrix.arch == 'aarch64' }} uses: docker/setup-qemu-action@v2 - name: Build wheels - uses: pypa/cibuildwheel@v2.16.2 + uses: pypa/cibuildwheel@v2.19.2 with: output-dir: dist env: