diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2aa76d97..83cf89f8 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 @@ -40,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 @@ -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} @@ -79,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' @@ -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 @@ -114,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 @@ -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 @@ -176,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 @@ -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: @@ -259,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: @@ -278,7 +212,6 @@ jobs: needs: - test_linux - test_macos - # - test_windows_py27 - test_windows runs-on: ubuntu-20.04 steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..6f916f0e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,32 @@ +--- +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)$ + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.5.0 + hooks: + - 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/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/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/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/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/conf.py b/docs/conf.py index 255558b5..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 sys, os - -# 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' +import sphinx_rtd_theme -# 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 = u'wrapt' -copyright = u'2013-2023, Graham Dumpleton' +project = 'wrapt' +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,200 +26,37 @@ # 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. -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 = {} - -# 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 +# -- Options for LaTeX output ------------------------------------------------- -# 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 - -# 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', '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 - -# 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', u'wrapt Documentation', - [u'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', u'wrapt Documentation', - u'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 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/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/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.cfg b/setup.cfg index 9c282c93..c0d8c1a6 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 @@ -65,37 +63,3 @@ src = [tool:pytest] norecursedirs = .tox venv - -# --- Tox automation configuration --------------------------------------------- - -[tox:tox] -envlist = - py{36,37,38,39,310,311,312} - py{36,37,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 - 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/setup.py b/setup.py index 77262b2f..44ead8fd 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ import os -import sys import platform import setuptools @@ -15,12 +14,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 @@ -38,6 +33,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..37ab926c 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 .__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 .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 .decorators import ( + adapter_factory, + AdapterFactory, + decorator, + synchronized, +) -from .importer import (register_post_import_hook, when_imported, - notify_module_loaded, discover_post_import_hooks) +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 @@ -28,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 9933b2c9..c2b1271a 100644 --- a/src/wrapt/__wrapt__.py +++ b/src/wrapt/__wrapt__.py @@ -1,14 +1,17 @@ -import os +from .wrappers import ( + ObjectProxy, + CallableObjectProxy, + PartialCallableObjectProxy, + FunctionWrapper, + BoundFunctionWrapper, + _FunctionWrapperBase, +) -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 +__all__ = [ + 'ObjectProxy', + 'CallableObjectProxy', + 'PartialCallableObjectProxy', + 'FunctionWrapper', + 'BoundFunctionWrapper', + '_FunctionWrapperBase', +] 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/arguments.py b/src/wrapt/arguments.py index 032bc059..e3d0c62a 100644 --- a/src/wrapt/arguments.py +++ b/src/wrapt/arguments.py @@ -1,38 +1,45 @@ # 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. -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 +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), ) - 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 + 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 c80a4bb7..00065125 100644 --- a/src/wrapt/decorators.py +++ b/src/wrapt/decorators.py @@ -3,55 +3,30 @@ """ -import sys - -PY2 = sys.version_info[0] == 2 - -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 inspect import isclass, signature from threading import Lock, RLock +from typing import Any, Callable, Optional, Type, TypeVar, Union, overload from .arguments import formatargspec -try: - from inspect import signature -except ImportError: - pass +from .__wrapt__ import ( + FunctionWrapper, + BoundFunctionWrapper, + CallableObjectProxy, +) -from .__wrapt__ import (FunctionWrapper, BoundFunctionWrapper, ObjectProxy, - 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.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): +class _AdapterFunctionCode(CallableObjectProxy): def __init__(self, wrapped_code, adapter_code): super(_AdapterFunctionCode, self).__init__(wrapped_code) self._self_adapter_code = adapter_code @@ -76,16 +51,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): @@ -102,16 +78,13 @@ def __signature__(self): else: return signature(self._self_adapter) - if PY2: - func_code = __code__ - func_defaults = __defaults__ 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): @@ -120,18 +93,16 @@ def __signature__(self): else: return signature(self._self_parent._self_adapter) - if PY2: - im_func = __func__ 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 @@ -146,25 +117,25 @@ 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__ + 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 @@ -174,7 +145,31 @@ 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): + +@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 @@ -220,13 +215,13 @@ 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] 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 @@ -236,8 +231,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) @@ -297,8 +296,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 @@ -432,8 +432,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 @@ -445,6 +447,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, @@ -470,7 +473,6 @@ def _synchronized(wrapped, instance, args, kwargs): return wrapped(*args, **kwargs) class _PartialDecorator(CallableObjectProxy): - def __enter__(self): lock.acquire() return lock @@ -527,7 +529,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() @@ -538,4 +539,5 @@ 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 23fcbd2f..c94b24d2 100644 --- a/src/wrapt/importer.py +++ b/src/wrapt/importer.py @@ -3,17 +3,10 @@ """ +from importlib.util import find_spec import sys import threading - -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 typing import Callable, Dict, List from .__wrapt__ import ObjectProxy @@ -23,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() @@ -34,6 +27,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(':') @@ -43,13 +37,15 @@ 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. - if isinstance(hook, string_types): + if isinstance(hook, str): hook = _create_import_hook_from_string(hook) with _post_import_hooks_lock: @@ -78,8 +74,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) @@ -87,8 +85,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 @@ -99,11 +99,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) @@ -117,30 +119,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 @@ -154,7 +157,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: @@ -162,8 +166,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): @@ -184,8 +190,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 = {} @@ -213,33 +219,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] @@ -271,9 +259,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) @@ -285,11 +270,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 e22adf7c..02defc62 100644 --- a/src/wrapt/patches.py +++ b/src/wrapt/patches.py @@ -1,19 +1,13 @@ 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] @@ -53,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 @@ -86,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] @@ -93,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] @@ -108,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): @@ -128,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) @@ -136,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 dfc3440d..5c4c3ccd 100644 --- a/src/wrapt/wrappers.py +++ b/src/wrapt/wrappers.py @@ -1,20 +1,13 @@ -import sys -import operator import inspect +import operator +import sys +from typing import Any, Generic, TypeVar -PY2 = sys.version_info[0] == 2 -if PY2: - string_types = basestring, -else: - string_types = str, +T = TypeVar("T", bound=Any) -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - return meta("NewBase", bases, {}) 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 @@ -56,6 +49,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 @@ -67,11 +61,15 @@ 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, 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 @@ -87,7 +85,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 @@ -116,24 +116,25 @@ 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( - 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__) - 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): return (self.__wrapped__,) @@ -183,7 +184,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 @@ -339,7 +342,7 @@ def __imod__(self, other): self.__wrapped__ %= other return self - def __ipow__(self, other): + def __ipow__(self, other, *args): self.__wrapped__ **= other return self @@ -378,9 +381,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__) @@ -436,15 +436,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 @@ -453,8 +451,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 @@ -479,7 +477,7 @@ def _unpack_self(self, *args): return self, args self, args = _unpack_self(*args) - + _args = self._self_args + args _kwargs = dict(self._self_kwargs) @@ -487,14 +485,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) @@ -533,9 +542,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 @@ -549,13 +563,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 @@ -586,8 +603,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 @@ -595,8 +613,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 @@ -625,8 +644,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 @@ -663,11 +682,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 @@ -685,11 +707,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): @@ -780,5 +801,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/compat.py b/tests/compat.py index 83b61f94..f5c7a2c9 100644 --- a/tests/compat.py +++ b/tests/compat.py @@ -1,33 +1,3 @@ import sys -PY2 = sys.version_info[0] < 3 -PY3 = sys.version_info[0] >= 3 - 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: - from inspect import getargspec as getfullargspec diff --git a/tests/conftest.py b/tests/conftest.py index 318d2263..4520ca4b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,16 +1,15 @@ 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]) + class DummyCollector(FileCollector): def collect(self): return [] + def construct_dummy(path, parent): if hasattr(DummyCollector, "from_parent"): item = DummyCollector.from_parent(parent, fspath=path) @@ -18,19 +17,8 @@ def construct_dummy(path, parent): else: 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/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 85063c28..b87a58de 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -1,13 +1,9 @@ -from __future__ import print_function - -import unittest import inspect import types +import unittest import wrapt -from compat import PY2, exec_, getfullargspec - DECORATORS_CODE = """ import wrapt @@ -19,23 +15,27 @@ 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''' 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. @@ -63,24 +63,25 @@ 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 = 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): @@ -88,10 +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. - if PY2: - return - - 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)) @@ -102,12 +101,13 @@ 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 = getfullargspec(_adapter) + argspec = inspect.getfullargspec(_adapter) @wrapt.decorator(adapter=argspec) def _wrapper_1(wrapped, instance, args, kwargs): @@ -117,7 +117,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)' @@ -129,12 +129,13 @@ 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 + 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): @@ -147,8 +148,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)' @@ -163,13 +164,14 @@ 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 + 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): @@ -183,8 +185,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)' @@ -200,12 +202,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 @@ -217,9 +219,10 @@ 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']) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_adapter_py3.py b/tests/test_adapter_py3.py index b6d48f17..6238994a 100644 --- a/tests/test_adapter_py3.py +++ b/tests/test_adapter_py3.py @@ -1,15 +1,11 @@ -from __future__ import print_function - import inspect -import unittest import types +import unittest from typing import Iterable import wrapt -from compat import PY2, exec_ - DECORATORS_CODE = """ import wrapt from typing import Iterable @@ -28,49 +24,60 @@ 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''' 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) @@ -88,10 +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. - if PY2: - return - - 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)) @@ -102,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) @@ -123,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) @@ -135,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) @@ -161,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) @@ -182,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) @@ -204,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) @@ -244,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 0cc8b2eb..a9022522 100644 --- a/tests/test_adapter_py33.py +++ b/tests/test_adapter_py33.py @@ -1,12 +1,7 @@ -from __future__ import print_function - -import unittest import inspect import types +import unittest -import wrapt - -from compat import PY2, PY3, exec_ DECORATORS_CODE = """ import wrapt @@ -19,29 +14,34 @@ 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''' 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) @@ -52,14 +52,13 @@ 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 + 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 0b7379d3..3acb5b70 100644 --- a/tests/test_arguments.py +++ b/tests/test_arguments.py @@ -1,23 +1,35 @@ -from __future__ import print_function - import unittest 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) @@ -26,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 f68315aa..93ace875 100644 --- a/tests/test_attribute_wrapper.py +++ b/tests/test_attribute_wrapper.py @@ -1,15 +1,14 @@ -from __future__ import print_function - import unittest 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 5421a06a..c01c2143 100644 --- a/tests/test_callable_object_proxy.py +++ b/tests/test_callable_object_proxy.py @@ -1,11 +1,9 @@ -from __future__ import print_function - import unittest import wrapt -class TestPartialCallableObjectProxy(unittest.TestCase): +class TestPartialCallableObjectProxy(unittest.TestCase): def test_no_arguments(self): def func0(): return ((), {}) @@ -66,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 d0f83845..154811b0 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -1,13 +1,9 @@ -from __future__ import print_function - -import unittest import inspect import types +import unittest import wrapt -from compat import PY2, PY3, exec_ - DECORATORS_CODE = """ import wrapt @@ -17,23 +13,25 @@ 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 + 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) + inspect.getmembers(class1o) + inspect.getmembers(class1d) -class TestInheritance(unittest.TestCase): +class TestInheritance(unittest.TestCase): def test_single_inheritance(self): @wrapt.decorator def passthru(wrapped, instance, args, kwargs): @@ -64,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 cdab1b6d..b4d33c4c 100644 --- a/tests/test_class_py37.py +++ b/tests/test_class_py37.py @@ -1,15 +1,9 @@ -from __future__ import print_function - import unittest -import inspect -import types import wrapt -from compat import PY2, PY3, exec_ class TestInheritance(unittest.TestCase): - def test_single_inheritance(self): @wrapt.decorator def passthru(wrapped, instance, args, kwargs): @@ -32,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() @@ -41,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 @@ -66,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 @@ -97,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 cbce9280..1955a4d2 100644 --- a/tests/test_copy.py +++ b/tests/test_copy.py @@ -1,38 +1,37 @@ -from __future__ import print_function - -import unittest - import copy +import unittest 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) + 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]) with self.assertRaises(NotImplementedError) as context: - proxy2 = copy.deepcopy(proxy1) + 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]) @@ -50,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 2213abc9..bbfe9836 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -1,11 +1,9 @@ -from __future__ import print_function - import unittest import wrapt -class TestDecorator(unittest.TestCase): +class TestDecorator(unittest.TestCase): def test_no_parameters(self): _args = (1, 2) _kwargs = {'one': 1, 'two': 2} @@ -29,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 @@ -56,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): @@ -101,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) @@ -112,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 2b51a740..134ffeb3 100644 --- a/tests/test_descriptors_py36.py +++ b/tests/test_descriptors_py36.py @@ -1,11 +1,9 @@ -from __future__ import print_function - import unittest import wrapt -class TestObjectDescriptors(unittest.TestCase): +class TestObjectDescriptors(unittest.TestCase): def test_set_name(self): @wrapt.decorator def _decorator(wrapped, instance, args, kwargs): @@ -34,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 6e47507e..b7658c61 100644 --- a/tests/test_formatargspec_py35.py +++ b/tests/test_formatargspec_py35.py @@ -1,35 +1,43 @@ +import inspect import unittest -import sys -from inspect import getfullargspec from wrapt import formatargspec -class TestFormatargspec35(unittest.TestCase): +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): - 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 - if sys.version_info[:2] < (3, 7): - formatted4 = '(a:int, b) -> list' - else: - formatted4 = '(a: int, b) -> list' + 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..38f0b940 100644 --- a/tests/test_formatargspec_py38.py +++ b/tests/test_formatargspec_py38.py @@ -1,37 +1,52 @@ import unittest -import sys from inspect import getfullargspec 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 cb77b35c..fd628290 100644 --- a/tests/test_function.py +++ b/tests/test_function.py @@ -1,13 +1,9 @@ -from __future__ import print_function - -import unittest import inspect import types +import unittest import wrapt -from compat import exec_, getfullargspec - DECORATORS_CODE = """ import wrapt @@ -17,18 +13,20 @@ 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''' 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. @@ -57,21 +55,21 @@ 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): - 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. 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} @@ -91,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 c353b205..96dc3bd0 100644 --- a/tests/test_function_wrapper.py +++ b/tests/test_function_wrapper.py @@ -1,13 +1,9 @@ -from __future__ import print_function - import unittest import wrapt -from compat import PY2, PY3, exec_ class TestClassInheritence(unittest.TestCase): - def test_function_type_inheritence(self): @wrapt.decorator def _decorator(wrapped, instance, args, kwargs): @@ -76,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) @@ -94,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) @@ -114,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) @@ -135,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) @@ -150,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): @@ -169,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): @@ -184,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): @@ -203,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): @@ -223,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): @@ -238,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): @@ -254,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): @@ -331,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): @@ -358,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() @@ -390,6 +402,7 @@ def function(): def test_function_guard_on_decorator(self): value = True + def guard(): return value @@ -419,6 +432,7 @@ def function(): def test_guard_on_instancemethod(self): value = True + def guard(): return value @@ -451,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 @@ -478,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 @@ -498,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 @@ -531,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): @@ -574,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 755b5990..91a36455 100644 --- a/tests/test_inheritance_py37.py +++ b/tests/test_inheritance_py37.py @@ -1,14 +1,11 @@ -from __future__ import print_function - -import unittest - import abc import _py_abc +import unittest import wrapt -class TestClassInheritance(unittest.TestCase): +class TestClassInheritance(unittest.TestCase): def test_basic_inheritance(self): @wrapt.decorator def wrapper(wrapped, instance, args, kwargs): @@ -50,8 +47,10 @@ def method(self): def function(): pass + class F(wrapt.FunctionWrapper): pass + instance = F(function, wrapper) self.assertTrue(isinstance(instance, wrapt.FunctionWrapper)) @@ -177,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 e2127ab9..1b84583e 100644 --- a/tests/test_inner_classmethod.py +++ b/tests/test_inner_classmethod.py @@ -1,12 +1,9 @@ -from __future__ import print_function - -import unittest +import inspect import types +import unittest import wrapt -from compat import exec_, getfullargspec - DECORATORS_CODE = """ import wrapt @@ -16,7 +13,8 @@ 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 @@ -24,8 +22,10 @@ def function(self, arg): '''documentation''' return arg + Original = Class + class Class(object): @decorators.passthru_decorator @classmethod @@ -33,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. @@ -70,55 +70,55 @@ 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. - 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): # 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. @@ -331,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 bd3756f4..816fcb44 100644 --- a/tests/test_inner_staticmethod.py +++ b/tests/test_inner_staticmethod.py @@ -1,12 +1,9 @@ -from __future__ import print_function - -import unittest +import inspect import types +import unittest import wrapt -from compat import exec_, getfullargspec - DECORATORS_CODE = """ import wrapt @@ -16,7 +13,8 @@ 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 @@ -24,8 +22,10 @@ def function(self, arg): '''documentation''' return arg + Original = Class + class Class(object): @decorators.passthru_decorator @staticmethod @@ -33,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. @@ -76,49 +77,48 @@ 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. - 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): # 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. @@ -279,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 90e13ad7..94942506 100644 --- a/tests/test_instancemethod.py +++ b/tests/test_instancemethod.py @@ -1,13 +1,9 @@ -from __future__ import print_function - -import unittest import inspect import types +import unittest import wrapt -from compat import exec_, getfullargspec - DECORATORS_CODE = """ import wrapt @@ -17,36 +13,42 @@ 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(): +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. @@ -71,85 +73,97 @@ 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. - 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): - 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. - 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. @@ -174,55 +188,61 @@ 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. - 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): # 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. @@ -243,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)) @@ -271,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) @@ -300,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)) @@ -329,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): @@ -339,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. @@ -457,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 27d3f5d2..9f0b9478 100644 --- a/tests/test_memoize.py +++ b/tests/test_memoize.py @@ -1,11 +1,9 @@ -from __future__ import print_function - -import unittest -import threading import inspect +import unittest import wrapt + @wrapt.decorator def memoize(wrapped, instance, args, kwargs): if instance is None and inspect.isclass(wrapped): @@ -30,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 @@ -50,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') @@ -90,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 d640f5c7..7831b793 100644 --- a/tests/test_monkey_patching.py +++ b/tests/test_monkey_patching.py @@ -1,55 +1,64 @@ -from __future__ import print_function - -import unittest import sys +import unittest 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} @@ -73,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} @@ -101,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} @@ -128,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} @@ -149,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} @@ -172,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} @@ -187,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) @@ -196,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} @@ -209,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) @@ -229,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)) @@ -243,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} @@ -256,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) @@ -265,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} @@ -285,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) @@ -305,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) @@ -325,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} @@ -336,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) @@ -357,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} @@ -382,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) @@ -408,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} @@ -417,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) @@ -436,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} @@ -467,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} @@ -495,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} @@ -523,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} @@ -550,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 ca65263b..53631d21 100644 --- a/tests/test_nested_function.py +++ b/tests/test_nested_function.py @@ -1,12 +1,9 @@ -from __future__ import print_function - -import unittest +import inspect import types +import unittest import wrapt -from compat import exec_, getfullargspec - DECORATORS_CODE = """ import wrapt @@ -16,27 +13,33 @@ 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): '''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. @@ -65,8 +68,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): @@ -74,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} @@ -95,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 91a010b3..f0e35323 100644 --- a/tests/test_object_proxy.py +++ b/tests/test_object_proxy.py @@ -1,15 +1,11 @@ -from __future__ import print_function - -import unittest -import types -import sys import re - -is_pypy = '__pypy__' in sys.builtin_module_names +import sys +import types +import unittest import wrapt -from compat import PY2, PY3, exec_ +is_pypy = '__pypy__' in sys.builtin_module_names OBJECTS_CODE = """ class TargetBaseClass(object): @@ -24,10 +20,10 @@ def target(): """ objects = types.ModuleType('objects') -exec_(OBJECTS_CODE, objects.__dict__, objects.__dict__) +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) @@ -45,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) @@ -52,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) @@ -63,14 +61,13 @@ def function1(*args, **kwargs): def test_set_wrapped(self): def function1(*args, **kwargs): return args, kwargs + function2 = wrapt.ObjectProxy(function1) 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 +76,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,13 +86,12 @@ 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): return args, kwargs + function2 = wrapt.ObjectProxy(function1) def run(*args): @@ -108,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 @@ -127,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 @@ -170,7 +166,7 @@ def value(self): try: WrappedObject(Object()).value == "value" - except ValueError as e: + except ValueError: pass else: @@ -195,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. @@ -287,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. @@ -320,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. @@ -370,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 = {} @@ -776,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] @@ -787,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 @@ -803,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)) @@ -815,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() @@ -856,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) @@ -876,9 +875,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) @@ -888,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() @@ -915,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() @@ -942,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() @@ -972,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() @@ -999,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() @@ -1303,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) @@ -1317,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) @@ -1466,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))) @@ -1525,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)) @@ -1558,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) @@ -1583,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) @@ -1599,12 +1594,10 @@ def __init__(self, wrapped): def function(): pass - obj = DerivedObjectProxy(function) + DerivedObjectProxy(function) def test_derived_setattr(self): - class DerivedObjectProxy(wrapt.ObjectProxy): - def __init__(self, wrapped): self._self_attribute = True super(DerivedObjectProxy, self).__init__(wrapped) @@ -1612,12 +1605,10 @@ def __init__(self, wrapped): def function(): pass - obj = DerivedObjectProxy(function) + DerivedObjectProxy(function) def test_derived_missing_init(self): - class DerivedObjectProxy(wrapt.ObjectProxy): - def __init__(self, wrapped): self.__wrapped__ = wrapped @@ -1629,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 @@ -1653,7 +1643,6 @@ class DerivedObjectProxy(wrapt.ObjectProxy): self.assertFalse(hasattr(function, 'ATTRIBUTE')) def test_override_class_attributes(self): - def function(): pass @@ -1679,7 +1668,6 @@ class DerivedObjectProxy(wrapt.ObjectProxy): self.assertFalse(hasattr(function, 'ATTRIBUTE')) def test_class_properties(self): - def function(): pass @@ -1687,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 @@ -1725,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 @@ -1739,7 +1729,6 @@ def function(): self.assertTrue(hasattr(proxy, '__delattr__')) def test_override_getattr(self): - def function(): pass @@ -1762,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) @@ -1794,18 +1783,18 @@ def test_callable_proxy_is_callable(self): self.assertTrue(callable(proxy)) -class SpecialMethods(unittest.TestCase): +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' @@ -1822,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) @@ -1846,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. @@ -1881,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: @@ -1897,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: @@ -1949,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. @@ -2023,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() + 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: @@ -2041,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') + 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: @@ -2059,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() + 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: @@ -2077,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') + 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: @@ -2174,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() + 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: @@ -2193,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') + 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. @@ -2246,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): @@ -2265,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): @@ -2326,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) @@ -2364,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): @@ -2420,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() @@ -2438,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 ab807646..47a9926d 100644 --- a/tests/test_outer_classmethod.py +++ b/tests/test_outer_classmethod.py @@ -1,11 +1,10 @@ -from __future__ import print_function - -import unittest +import inspect import types +import unittest import wrapt -from compat import PYXY, exec_, getfullargspec +from compat import PYXY DECORATORS_CODE = """ import wrapt @@ -16,7 +15,8 @@ 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 @@ -24,8 +24,10 @@ def function(self, arg): '''documentation''' return arg + Original = Class + class Class(object): @classmethod @decorators.passthru_decorator @@ -33,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. @@ -70,55 +72,55 @@ 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. - 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): # 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 @@ -136,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) @@ -178,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) @@ -203,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 959c7ffd..778aed64 100644 --- a/tests/test_outer_staticmethod.py +++ b/tests/test_outer_staticmethod.py @@ -1,12 +1,9 @@ -from __future__ import print_function - -import unittest +import inspect import types +import unittest import wrapt -from compat import exec_, getfullargspec - DECORATORS_CODE = """ import wrapt @@ -16,7 +13,8 @@ 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 @@ -24,8 +22,10 @@ def function(self, arg): '''documentation''' return arg + Original = Class + class Class(object): @staticmethod @decorators.passthru_decorator @@ -33,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. @@ -70,55 +70,55 @@ 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. - 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): # 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 @@ -180,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 41e91044..550b2204 100644 --- a/tests/test_pickle.py +++ b/tests/test_pickle.py @@ -1,26 +1,25 @@ -from __future__ import print_function - -import unittest - import pickle +import unittest 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) + 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]) @@ -29,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 5113e8d2..3bb4aa27 100644 --- a/tests/test_post_import_hooks.py +++ b/tests/test_post_import_hooks.py @@ -1,16 +1,12 @@ -from __future__ import print_function - -import unittest import sys import threading +import unittest import wrapt from wrapt.importer import _post_import_hooks -from compat import PY2, PY3 class TestPostImportHooks(unittest.TestCase): - def setUp(self): super(TestPostImportHooks, self).setUp() @@ -31,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) @@ -61,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) @@ -82,12 +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) @@ -97,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): @@ -133,7 +130,8 @@ def hook_xxx(module): self.assertFalse(thread.is_alive()) - import this + import this # noqa + del sys.modules['this'] def test_import_deadlock_3(self): @@ -148,9 +146,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') @@ -158,13 +153,13 @@ 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') def worker(): - import wsgiref + import wsgiref # noqa thread = threading.Thread(target=worker) thread.start() @@ -172,7 +167,8 @@ def worker(): self.assertFalse(thread.is_alive()) - import this + import this # noqa + del sys.modules['this'] self.assertEqual(hooks_called, ['this', 'wsgiref']) @@ -182,15 +178,13 @@ def test_loader(self): def hook_this(module): pass - import this + import this # noqa + + from importlib.machinery import SourceFileLoader - if sys.version_info[:2] >= (3, 3): - from importlib.machinery import SourceFileLoader - self.assertIsInstance(this.__loader__, SourceFileLoader) - self.assertIsInstance(this.__spec__.loader, SourceFileLoader) + self.assertIsInstance(this.__loader__, SourceFileLoader) + self.assertIsInstance(this.__spec__.loader, SourceFileLoader) - else: - self.assertEqual(hasattr(this, "__loader__"), False) if __name__ == '__main__': unittest.main() diff --git a/tests/test_synchronized_lock.py b/tests/test_synchronized_lock.py index 0e43f7af..60736965 100644 --- a/tests/test_synchronized_lock.py +++ b/tests/test_synchronized_lock.py @@ -1,17 +1,16 @@ -from __future__ import print_function - import unittest import wrapt from compat import PYXY + @wrapt.synchronized def function(): print('function') -class C1(object): +class C1(object): @wrapt.synchronized def function1(self): print('function1') @@ -26,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 @@ -56,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) @@ -242,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) @@ -266,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) @@ -294,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 9850c1b1..19af79bd 100644 --- a/tests/test_update_attributes.py +++ b/tests/test_update_attributes.py @@ -1,17 +1,14 @@ -from __future__ import print_function - import unittest import wrapt -from compat import PY2, PY3, exec_ @wrapt.decorator 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(): @@ -40,15 +37,14 @@ def wrapper(wrapped, instance, args, kwargs): self.assertEqual(instance.__name__, 'override_name') def test_update_qualname(self): - @passthru_decorator 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 +59,10 @@ 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,19 +130,13 @@ 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.__wrapped__.__annotations__, override_annotations + ) self.assertEqual(function.__annotations__, override_annotations) def test_update_annotations_modified_on_original(self): @@ -157,21 +147,13 @@ 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) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_weak_function_proxy.py b/tests/test_weak_function_proxy.py index 2babe95c..a0ea983a 100644 --- a/tests/test_weak_function_proxy.py +++ b/tests/test_weak_function_proxy.py @@ -1,12 +1,10 @@ -from __future__ import print_function - import unittest import gc import wrapt -class TestWeakFunctionProxy(unittest.TestCase): +class TestWeakFunctionProxy(unittest.TestCase): def test_isinstance(self): def function(a, b): return a, b @@ -190,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() diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..c23e4e9b --- /dev/null +++ b/tox.ini @@ -0,0 +1,34 @@ +[tox] +minversion = 4.0.0 +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 = + 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 + +[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: 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, pypy38-without-extensions + pypy-3.9: lint, pypy39-without-extensions + pypy-3.10: lint, pypy310-without-extensions