Skip to content

Commit a18b395

Browse files
hynekTinchepre-commit-ci[bot]
authored
Add support for Python 3.11 (#969)
* Add support for Python 3.11 Co-authored-by: Tin Tvrtković <tinchester@gmail.com> * Tin/py311 (#973) * Fix test_slots::TestPickle::test_no_getstate_setstate_for_dict_classes * Fix annotations * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Tweak tests for 3.10 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Tweak tests some more Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Tin Tvrtković <tinchester@gmail.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent a7e82b5 commit a18b395

File tree

7 files changed

+44
-31
lines changed

7 files changed

+44
-31
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
strategy:
2424
fail-fast: false
2525
matrix:
26-
python-version: ["3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "pypy-3.7", "pypy-3.8"]
26+
python-version: ["3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11.0-beta - 3.11", "pypy-3.7", "pypy-3.8"]
2727

2828
steps:
2929
- uses: actions/checkout@v3

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"Programming Language :: Python :: 3.8",
4040
"Programming Language :: Python :: 3.9",
4141
"Programming Language :: Python :: 3.10",
42+
"Programming Language :: Python :: 3.11",
4243
"Programming Language :: Python :: Implementation :: CPython",
4344
"Programming Language :: Python :: Implementation :: PyPy",
4445
"Topic :: Software Development :: Libraries :: Python Modules",

src/attr/_compat.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,10 @@ def force_x_to_be_a_cell(): # pragma: no cover
111111
# Convert this code object to a code object that sets the
112112
# function's first _freevar_ (not cellvar) to the argument.
113113
if sys.version_info >= (3, 8):
114-
# CPython 3.8+ has an incompatible CodeType signature
115-
# (added a posonlyargcount argument) but also added
116-
# CodeType.replace() to do this without counting parameters.
117-
set_first_freevar_code = co.replace(
118-
co_cellvars=co.co_freevars, co_freevars=co.co_cellvars
119-
)
114+
115+
def set_closure_cell(cell, value):
116+
cell.cell_contents = value
117+
120118
else:
121119
args = [co.co_argcount]
122120
args.append(co.co_kwonlyargcount)
@@ -140,15 +138,15 @@ def force_x_to_be_a_cell(): # pragma: no cover
140138
)
141139
set_first_freevar_code = types.CodeType(*args)
142140

143-
def set_closure_cell(cell, value):
144-
# Create a function using the set_first_freevar_code,
145-
# whose first closure cell is `cell`. Calling it will
146-
# change the value of that cell.
147-
setter = types.FunctionType(
148-
set_first_freevar_code, {}, "setter", (), (cell,)
149-
)
150-
# And call it to set the cell.
151-
setter(value)
141+
def set_closure_cell(cell, value):
142+
# Create a function using the set_first_freevar_code,
143+
# whose first closure cell is `cell`. Calling it will
144+
# change the value of that cell.
145+
setter = types.FunctionType(
146+
set_first_freevar_code, {}, "setter", (), (cell,)
147+
)
148+
# And call it to set the cell.
149+
setter(value)
152150

153151
# Make sure it works on this interpreter:
154152
def make_func_with_cell():

tests/test_annotations.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ class C:
9494
assert 1 == len(attr.fields(C))
9595
assert_init_annotations(C, x=typing.List[int])
9696

97+
@pytest.mark.skipif(
98+
sys.version_info[:2] < (3, 11),
99+
reason="Incompatible behavior on older Pythons",
100+
)
97101
@pytest.mark.parametrize("slots", [True, False])
98102
def test_auto_attribs(self, slots):
99103
"""
@@ -149,7 +153,7 @@ class C:
149153
x=typing.List[int],
150154
y=int,
151155
z=int,
152-
foo=typing.Optional[typing.Any],
156+
foo=typing.Any,
153157
)
154158

155159
@pytest.mark.parametrize("slots", [True, False])
@@ -384,8 +388,9 @@ def noop():
384388

385389
assert attr.converters.optional(noop).__annotations__ == {}
386390

387-
@pytest.mark.xfail(
388-
sys.version_info[:2] == (3, 6), reason="Does not work on 3.6."
391+
@pytest.mark.skipif(
392+
sys.version_info[:2] < (3, 11),
393+
reason="Incompatible behavior on older Pythons",
389394
)
390395
@pytest.mark.parametrize("slots", [True, False])
391396
def test_annotations_strings(self, slots):
@@ -417,7 +422,7 @@ class C:
417422
x=typing.List[int],
418423
y=int,
419424
z=int,
420-
foo=typing.Optional[typing.Any],
425+
foo=typing.Any,
421426
)
422427

423428
@pytest.mark.parametrize("slots", [True, False])

tests/test_make.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2275,7 +2275,9 @@ class C:
22752275
def __getstate__(self):
22762276
return ("hi",)
22772277

2278-
assert None is getattr(C(), "__setstate__", None)
2278+
assert getattr(object, "__setstate__", None) is getattr(
2279+
C, "__setstate__", None
2280+
)
22792281

22802282
@attr.s(slots=slots, auto_detect=True)
22812283
class C:
@@ -2291,7 +2293,9 @@ def __setstate__(self, state):
22912293
i.__setstate__(())
22922294

22932295
assert True is i.called
2294-
assert None is getattr(C(), "__getstate__", None)
2296+
assert getattr(object, "__getstate__", None) is getattr(
2297+
C, "__getstate__", None
2298+
)
22952299

22962300
@pytest.mark.skipif(PY310, reason="Pre-3.10 only.")
22972301
def test_match_args_pre_310(self):

tests/test_slots.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -660,10 +660,12 @@ def test_no_getstate_setstate_for_dict_classes(self):
660660
As long as getstate_setstate is None, nothing is done to dict
661661
classes.
662662
"""
663-
i = C1(1, 2)
664-
665-
assert None is getattr(i, "__getstate__", None)
666-
assert None is getattr(i, "__setstate__", None)
663+
assert getattr(object, "__getstate__", None) is getattr(
664+
C1, "__getstate__", None
665+
)
666+
assert getattr(object, "__setstate__", None) is getattr(
667+
C1, "__setstate__", None
668+
)
667669

668670
def test_no_getstate_setstate_if_option_false(self):
669671
"""
@@ -674,10 +676,12 @@ def test_no_getstate_setstate_if_option_false(self):
674676
class C:
675677
x = attr.ib()
676678

677-
i = C(42)
678-
679-
assert None is getattr(i, "__getstate__", None)
680-
assert None is getattr(i, "__setstate__", None)
679+
assert getattr(object, "__getstate__", None) is getattr(
680+
C, "__getstate__", None
681+
)
682+
assert getattr(object, "__setstate__", None) is getattr(
683+
C, "__setstate__", None
684+
)
681685

682686
@pytest.mark.parametrize("cls", [C2(1), C2Slots(1)])
683687
def test_getstate_set_state_force_true(self, cls):

tox.ini

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ python =
1616
3.8: py38, changelog
1717
3.9: py39, pyright
1818
3.10: py310, manifest, typing, docs
19+
3.11: py311
1920
pypy-3: pypy3
2021

2122

2223
[tox]
23-
envlist = typing,pre-commit,py35,py36,py37,py38,py39,py310,pypy3,pyright,manifest,docs,pypi-description,changelog,coverage-report
24+
envlist = typing,pre-commit,py35,py36,py37,py38,py39,py310,py311,pypy3,pyright,manifest,docs,pypi-description,changelog,coverage-report
2425
isolated_build = True
2526

2627

0 commit comments

Comments
 (0)