Skip to content

Commit

Permalink
Merge branch 'release/1.14.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
GrahamDumpleton committed Mar 10, 2022
2 parents 4c61482 + 7e2a140 commit 77634fa
Show file tree
Hide file tree
Showing 24 changed files with 414 additions and 90 deletions.
56 changes: 51 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- 3.8
- 3.9
- "3.10"
#- 3.11-dev
- 3.11-dev
- pypy-2.7
- pypy-3.6
- pypy-3.7
Expand All @@ -42,6 +42,41 @@ jobs:
name: coverage
path: .coverage.*

test_aarch64_linux:
name: Test (${{ matrix.python.os }}, ${{ matrix.python.python-version }}, aarch64)
runs-on: ${{ matrix.python.os }}
strategy:
matrix:
python:
- {os: ubuntu-latest, python-version: 3.6, pyver: py36}
- {os: ubuntu-latest, python-version: 3.7, pyver: py37}
- {os: ubuntu-latest, python-version: 3.8, pyver: py38}
- {os: ubuntu-latest, python-version: 3.9, pyver: py39}
- {os: ubuntu-latest, python-version: "3.10", pyver: py310}
env:
py: python${{ matrix.python.python-version }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
id: qemu
uses: docker/setup-qemu-action@v1
- name: Test with tox
run: |
docker run --rm -v ${{ github.workspace }}:/io:rw --workdir=/io \
arm64v8/ubuntu \
bash -exc 'apt-get update && \
apt install software-properties-common -y && \
add-apt-repository ppa:deadsnakes/ppa -y && \
apt install -y ${{ env.py }} && \
apt install -y ${{ env.py }}-venv && \
${{ env.py }} -m venv .env && \
source .env/bin/activate && \
pip install -U pip wheel setuptools && \
pip install tox tox-gh-actions && \
tox -e ${{ matrix.python.pyver }} && \
deactivate'
test_macos:
name: Test (${{ matrix.os }}, ${{ matrix.python-version }})
runs-on: ${{ matrix.os }}
Expand All @@ -57,7 +92,7 @@ jobs:
- 3.8
- 3.9
- "3.10"
#- 3.11-dev
- 3.11-dev
- pypy-2.7
#- pypy-3.6
- pypy-3.7
Expand Down Expand Up @@ -117,7 +152,7 @@ jobs:
- 3.8
- 3.9
- "3.10"
#- 3.11-dev
- 3.11-dev
- pypy-2.7
- pypy-3.6
- pypy-3.7
Expand Down Expand Up @@ -187,26 +222,37 @@ jobs:
path: dist/*.whl

bdist_wheel:
name: Build wheels (3.6+) on ${{ matrix.os }}
name: Build wheels (3.6+) on ${{ matrix.os }} for ${{ matrix.arch }}
needs:
- test_linux
- test_aarch64_linux
- test_macos
- test_windows_py27
- test_windows
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
arch: [auto]
include:
- os: ubuntu-latest
arch: aarch64
- os: macos-latest
arch: arm64
steps:
- uses: actions/checkout@v2
- name: Set up QEMU
if: ${{ matrix.arch == 'aarch64' }}
uses: docker/setup-qemu-action@v1
- name: Build wheels
uses: pypa/cibuildwheel@v2.2.0
uses: pypa/cibuildwheel@v2.3.1
with:
output-dir: dist
env:
WRAPT_INSTALL_EXTENSIONS: true
CIBW_SKIP: pp*
CIBW_BUILD_VERBOSITY: 1
CIBW_ARCHS: ${{ matrix.arch }}
- uses: actions/upload-artifact@v2
with:
name: dist
Expand Down
23 changes: 23 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details

# Required
version: 2

# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py

# Build documentation with MkDocs
#mkdocs:
# configuration: mkdocs.yml

# Optionally build your docs in additional formats such as PDF
#formats:
# - pdf

# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.8
# install:
# - requirements: docs/requirements.txt
26 changes: 26 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,32 @@
Release Notes
=============

Version 1.14.0
--------------

**Bugs Fixed**

* Python 3.11 dropped `inspect.formatargspec()` which was used in creating
signature changing decorators. Now bundling a version of this function
which uses `Parameter` and `Signature` from `inspect` module when available.
The replacement function is exposed as `wrapt.formatargspec()` if need it
for your own code.

* When using a decorator on a class, `isinstance()` checks wouldn't previously
work as expected and you had to manually use `Type.__wrapped__` to access
the real type when doing instance checks. The `__instancecheck__` hook is now
implemented such that you don't have to use `Type.__wrapped__` instead of
`Type` as last argument to `isinstance()`.

* Eliminated deprecation warnings related to Python module import system, which
would have turned into broken code in Python 3.12. This was used by the post
import hook mechanism.

**New Features**

* Binary wheels provided on PyPi for `aarch64` Linux systems and macOS
native silicon where supported by Python when using `pypa/cibuildwheel`.

Version 1.13.3
--------------

Expand Down
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ python =
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 =
Expand Down
13 changes: 12 additions & 1 deletion src/wrapt/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version_info__ = ('1', '13', '3')
__version_info__ = ('1', '14', '0')
__version__ = '.'.join(__version_info__)

from .wrappers import (ObjectProxy, CallableObjectProxy, FunctionWrapper,
Expand All @@ -13,4 +13,15 @@
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
# Python <2.7. Avoid using this in future.

from inspect import getcallargs

# Variant of inspect.formatargspec() included here for forward compatibility.
# This is being done because Python 3.11 dropped inspect.formatargspec() but
# code for handling signature changing decorators relied on it. Exposing the
# bundled implementation here in case any user of wrapt was also needing it.

from .arguments import formatargspec
29 changes: 29 additions & 0 deletions src/wrapt/_wrappers.c
Original file line number Diff line number Diff line change
Expand Up @@ -2544,6 +2544,33 @@ static PyObject *WraptFunctionWrapperBase_set_name(

/* ------------------------------------------------------------------------- */

static PyObject *WraptFunctionWrapperBase_instancecheck(
WraptFunctionWrapperObject *self, PyObject *instance)
{
PyObject *object = NULL;
PyObject *result = NULL;

int check = 0;

if (!self->object_proxy.wrapped) {
PyErr_SetString(PyExc_ValueError, "wrapper has not been initialized");
return NULL;
}

check = PyObject_IsInstance(instance, self->object_proxy.wrapped);

if (check < 0) {
return NULL;
}

result = check ? Py_True : Py_False;

Py_INCREF(result);
return result;
}

/* ------------------------------------------------------------------------- */

static PyObject *WraptFunctionWrapperBase_subclasscheck(
WraptFunctionWrapperObject *self, PyObject *args)
{
Expand Down Expand Up @@ -2656,6 +2683,8 @@ static PyObject *WraptFunctionWrapperBase_get_self_parent(
static PyMethodDef WraptFunctionWrapperBase_methods[] = {
{ "__set_name__", (PyCFunction)WraptFunctionWrapperBase_set_name,
METH_VARARGS | METH_KEYWORDS, 0 },
{ "__instancecheck__", (PyCFunction)WraptFunctionWrapperBase_instancecheck,
METH_O, 0},
{ "__subclasscheck__", (PyCFunction)WraptFunctionWrapperBase_subclasscheck,
METH_VARARGS, 0 },
{ NULL, NULL },
Expand Down
38 changes: 38 additions & 0 deletions src/wrapt/arguments.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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
# inspect.formatargspec() base on Parameter and Signature from inspect module,
# which were added in Python 3.6. Thanks to Cyril Jouve for the implementation.

try:
from inspect import Parameter, Signature
except ImportError:
from inspect import formatargspec
else:
def formatargspec(args, varargs=None, varkw=None, defaults=None,
kwonlyargs=(), kwonlydefaults={}, annotations={}):
if kwonlydefaults is None:
kwonlydefaults = {}
ndefaults = len(defaults) if defaults else 0
parameters = [
Parameter(
arg,
Parameter.POSITIONAL_OR_KEYWORD,
default=defaults[i] if i >= 0 else Parameter.empty,
annotation=annotations.get(arg, Parameter.empty),
) for i, arg in enumerate(args, ndefaults - len(args))
]
if varargs:
parameters.append(Parameter(varargs, Parameter.VAR_POSITIONAL))
parameters.extend(
Parameter(
kwonlyarg,
Parameter.KEYWORD_ONLY,
default=kwonlydefaults.get(kwonlyarg, Parameter.empty),
annotation=annotations.get(kwonlyarg, Parameter.empty),
) for kwonlyarg in kwonlyargs
)
if varkw:
parameters.append(Parameter(varkw, Parameter.VAR_KEYWORD))
return_annotation = annotations.get('return', Signature.empty)
return str(Signature(parameters, return_annotation=return_annotation))
9 changes: 5 additions & 4 deletions src/wrapt/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ def exec_(_code_, _globs_=None, _locs_=None):
del builtins

from functools import partial
from inspect import ismethod, isclass, formatargspec
from collections import namedtuple
from inspect import isclass
from threading import Lock, RLock

from .arguments import formatargspec

try:
from inspect import signature
except ImportError:
Expand Down Expand Up @@ -383,7 +384,7 @@ def _capture(target_wrapped):
# This one is a bit strange because binding was actually
# performed on the wrapper created by our decorator
# factory. We need to apply that binding to the decorator
# wrapper function which which the decorator factory
# wrapper function that the decorator factory
# was applied to.

target_wrapper = wrapper.__get__(None, instance)
Expand All @@ -407,7 +408,7 @@ def _capture(target_wrapped):
# This one is a bit strange because binding was actually
# performed on the wrapper created by our decorator
# factory. We need to apply that binding to the decorator
# wrapper function which which the decorator factory
# wrapper function that the decorator factory
# was applied to.

target_wrapper = wrapper.__get__(instance, type(instance))
Expand Down
Loading

0 comments on commit 77634fa

Please sign in to comment.