Skip to content

Commit fc586b9

Browse files
authored
Merge pull request #2394 from Textualize/python3.11b
Add Python 3.11.0-beta4 to CI
2 parents dbd7135 + a44aa44 commit fc586b9

File tree

6 files changed

+108
-14
lines changed

6 files changed

+108
-14
lines changed

.github/workflows/pythonpackage.yml

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
matrix:
1010
os: [windows-latest, ubuntu-latest, macos-latest]
11-
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
11+
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11.0-beta.4"]
1212
defaults:
1313
run:
1414
shell: bash
@@ -35,10 +35,16 @@ jobs:
3535
run: |
3636
source $VENV
3737
make typecheck
38-
- name: Test with pytest
38+
- name: Test with pytest (with coverage)
39+
if: matrix.python-version != '3.11.0-beta.4'
3940
run: |
4041
source $VENV
4142
pytest tests -v --cov=./rich --cov-report=xml:./coverage.xml --cov-report term-missing
43+
- name: Test with pytest (no coverage)
44+
if: matrix.python-version == '3.11.0-beta.4'
45+
run: |
46+
source $VENV
47+
pytest tests -v
4248
- name: Upload code coverage
4349
uses: codecov/codecov-action@v2
4450
with:

Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
test:
22
TERM=unknown pytest --cov-report term-missing --cov=rich tests/ -vv
3+
test-no-cov:
4+
TERM=unknown pytest tests/ -vv
35
format-check:
46
black --check .
57
format:

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ classifiers = [
2020
"Programming Language :: Python :: 3.8",
2121
"Programming Language :: Python :: 3.9",
2222
"Programming Language :: Python :: 3.10",
23+
"Programming Language :: Python :: 3.11",
2324
"Typing :: Typed",
2425
]
2526
include = ["rich/py.typed"]

rich/color.py

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ class ColorSystem(IntEnum):
2929
def __repr__(self) -> str:
3030
return f"ColorSystem.{self.name}"
3131

32+
def __str__(self) -> str:
33+
return repr(self)
34+
3235

3336
class ColorType(IntEnum):
3437
"""Type of color stored in Color class."""

tests/test_inspect.py

+89-12
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
reason="rendered differently on py3.10",
3939
)
4040

41+
skip_py311 = pytest.mark.skipif(
42+
sys.version_info.minor == 11 and sys.version_info.major == 3,
43+
reason="rendered differently on py3.11",
44+
)
45+
4146
skip_pypy3 = pytest.mark.skipif(
4247
hasattr(sys, "pypy_version_info"),
4348
reason="rendered differently on pypy3",
@@ -93,23 +98,24 @@ def test_render():
9398
result = console.file.getvalue()
9499
print(repr(result))
95100
expected = "╭────────────── <class 'tests.test_inspect.Foo'> ──────────────╮\n│ Foo test │\n│ │\n│ broken = InspectError() │\n│ __init__ = def __init__(foo: int) -> None: constructor docs. │\n│ method = def method(a, b) -> str: Multi line │\n╰──────────────────────────────────────────────────────────────╯\n"
96-
assert expected == result
101+
assert result == expected
97102

98103

99104
@skip_pypy3
100105
def test_inspect_text():
106+
num_attributes = 34 if sys.version_info >= (3, 11) else 33
101107
expected = (
102108
"╭──────────────── <class 'str'> ─────────────────╮\n"
103109
"│ str(object='') -> str │\n"
104110
"│ str(bytes_or_buffer[, encoding[, errors]]) -> │\n"
105111
"│ str │\n"
106112
"│ │\n"
107-
"│ 33 attribute(s) not shown. Run │\n"
113+
f"│ {num_attributes} attribute(s) not shown. Run │\n"
108114
"│ inspect(inspect) for options. │\n"
109115
"╰────────────────────────────────────────────────╯\n"
110116
)
111117
print(repr(expected))
112-
assert expected == render("Hello")
118+
assert render("Hello") == expected
113119

114120

115121
@skip_py36
@@ -136,8 +142,10 @@ def test_inspect_empty_dict():
136142
assert render({}).startswith(expected)
137143

138144

145+
@skip_py311
139146
@skip_pypy3
140-
def test_inspect_builtin_function():
147+
def test_inspect_builtin_function_except_python311():
148+
# Pre-3.11 Python versions - print builtin has no signature available
141149
expected = (
142150
"╭────────── <built-in function print> ───────────╮\n"
143151
"│ def print(...) │\n"
@@ -149,7 +157,28 @@ def test_inspect_builtin_function():
149157
"│ inspect(inspect) for options. │\n"
150158
"╰────────────────────────────────────────────────╯\n"
151159
)
152-
assert expected == render(print)
160+
assert render(print) == expected
161+
162+
163+
@pytest.mark.skipif(
164+
sys.version_info < (3, 11), reason="print builtin signature only available on 3.11+"
165+
)
166+
@skip_pypy3
167+
def test_inspect_builtin_function_only_python311():
168+
# On 3.11, the print builtin *does* have a signature, unlike in prior versions
169+
expected = (
170+
"╭────────── <built-in function print> ───────────╮\n"
171+
"│ def print(*args, sep=' ', end='\\n', file=None, │\n"
172+
"│ flush=False): │\n"
173+
"│ │\n"
174+
"│ Prints the values to a stream, or to │\n"
175+
"│ sys.stdout by default. │\n"
176+
"│ │\n"
177+
"│ 30 attribute(s) not shown. Run │\n"
178+
"│ inspect(inspect) for options. │\n"
179+
"╰────────────────────────────────────────────────╯\n"
180+
)
181+
assert render(print) == expected
153182

154183

155184
@skip_pypy3
@@ -186,13 +215,14 @@ def test_inspect_integer_with_value():
186215
expected = "╭────── <class 'int'> ───────╮\n│ int([x]) -> integer │\n│ int(x, base=10) -> integer │\n│ │\n│ ╭────────────────────────╮ │\n│ │ 1 │ │\n│ ╰────────────────────────╯ │\n│ │\n│ denominator = 1 │\n│ imag = 0 │\n│ numerator = 1 │\n│ real = 1 │\n╰────────────────────────────╯\n"
187216
value = render(1, value=True)
188217
print(repr(value))
189-
assert expected == value
218+
assert value == expected
190219

191220

192221
@skip_py36
193222
@skip_py37
194223
@skip_py310
195-
def test_inspect_integer_with_methods():
224+
@skip_py311
225+
def test_inspect_integer_with_methods_python38_and_python39():
196226
expected = (
197227
"╭──────────────── <class 'int'> ─────────────────╮\n"
198228
"│ int([x]) -> integer │\n"
@@ -222,14 +252,15 @@ def test_inspect_integer_with_methods():
222252
"│ an integer. │\n"
223253
"╰────────────────────────────────────────────────╯\n"
224254
)
225-
assert expected == render(1, methods=True)
255+
assert render(1, methods=True) == expected
226256

227257

228258
@skip_py36
229259
@skip_py37
230260
@skip_py38
231261
@skip_py39
232-
def test_inspect_integer_with_methods():
262+
@skip_py311
263+
def test_inspect_integer_with_methods_python310only():
233264
expected = (
234265
"╭──────────────── <class 'int'> ─────────────────╮\n"
235266
"│ int([x]) -> integer │\n"
@@ -263,7 +294,51 @@ def test_inspect_integer_with_methods():
263294
"│ an integer. │\n"
264295
"╰────────────────────────────────────────────────╯\n"
265296
)
266-
assert expected == render(1, methods=True)
297+
assert render(1, methods=True) == expected
298+
299+
300+
@skip_py36
301+
@skip_py37
302+
@skip_py38
303+
@skip_py39
304+
@skip_py310
305+
def test_inspect_integer_with_methods_python311_and_above():
306+
# to_bytes and from_bytes methods on int had minor signature change -
307+
# they now, as of 3.11, have default values for all of their parameters
308+
expected = (
309+
"╭──────────────── <class 'int'> ─────────────────╮\n"
310+
"│ int([x]) -> integer │\n"
311+
"│ int(x, base=10) -> integer │\n"
312+
"│ │\n"
313+
"│ denominator = 1 │\n"
314+
"│ imag = 0 │\n"
315+
"│ numerator = 1 │\n"
316+
"│ real = 1 │\n"
317+
"│ as_integer_ratio = def as_integer_ratio(): │\n"
318+
"│ Return integer ratio. │\n"
319+
"│ bit_count = def bit_count(): Number of │\n"
320+
"│ ones in the binary │\n"
321+
"│ representation of the │\n"
322+
"│ absolute value of self. │\n"
323+
"│ bit_length = def bit_length(): Number of │\n"
324+
"│ bits necessary to represent │\n"
325+
"│ self in binary. │\n"
326+
"│ conjugate = def conjugate(...) Returns │\n"
327+
"│ self, the complex conjugate │\n"
328+
"│ of any int. │\n"
329+
"│ from_bytes = def from_bytes(bytes, │\n"
330+
"│ byteorder='big', *, │\n"
331+
"│ signed=False): Return the │\n"
332+
"│ integer represented by the │\n"
333+
"│ given array of bytes. │\n"
334+
"│ to_bytes = def to_bytes(length=1, │\n"
335+
"│ byteorder='big', *, │\n"
336+
"│ signed=False): Return an │\n"
337+
"│ array of bytes representing │\n"
338+
"│ an integer. │\n"
339+
"╰────────────────────────────────────────────────╯\n"
340+
)
341+
assert render(1, methods=True) == expected
267342

268343

269344
@skip_py36
@@ -387,8 +462,10 @@ def test_object_types_mro(obj: object, expected_result: Sequence[Type]):
387462
[str, ["builtins.str", "builtins.object"]],
388463
[Foo(1), [f"{__name__}.Foo", "builtins.object"]],
389464
[Foo, [f"{__name__}.Foo", "builtins.object"]],
390-
[FooSubclass(1), [f"{__name__}.FooSubclass", f"{__name__}.Foo", "builtins.object"]],
391-
[FooSubclass, [f"{__name__}.FooSubclass", f"{__name__}.Foo", "builtins.object"]],
465+
[FooSubclass(1),
466+
[f"{__name__}.FooSubclass", f"{__name__}.Foo", "builtins.object"]],
467+
[FooSubclass,
468+
[f"{__name__}.FooSubclass", f"{__name__}.Foo", "builtins.object"]],
392469
# fmt: on
393470
),
394471
)

tests/test_pretty.py

+5
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
sys.version_info.minor == 10 and sys.version_info.major == 3,
3737
reason="rendered differently on py3.10",
3838
)
39+
skip_py311 = pytest.mark.skipif(
40+
sys.version_info.minor == 11 and sys.version_info.major == 3,
41+
reason="rendered differently on py3.11",
42+
)
3943

4044

4145
def test_install():
@@ -493,6 +497,7 @@ class Nada:
493497

494498
@skip_py36
495499
@skip_py310
500+
@skip_py311
496501
def test_attrs_broken():
497502
@attr.define
498503
class Foo:

0 commit comments

Comments
 (0)