From 19d1c85db9c862172f0cffd0872a942aef26d934 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Wed, 22 Nov 2023 12:48:40 -0500 Subject: [PATCH] re-run formatter, but with docstring code snippet formatting enabled --- Lib/_pydatetime.py | 2 +- Lib/_pydecimal.py | 610 ++-- Lib/antigravity.py | 2 +- Lib/collections/__init__.py | 112 +- Lib/difflib.py | 115 +- Lib/doctest.py | 77 +- Lib/enum.py | 4 +- Lib/fractions.py | 14 +- Lib/ftplib.py | 4 +- Lib/heapq.py | 4 +- Lib/idlelib/pyparse.py | 2 +- Lib/importlib/metadata/__init__.py | 31 +- Lib/importlib/metadata/_collections.py | 2 +- Lib/importlib/metadata/_functools.py | 2 +- Lib/importlib/metadata/_itertools.py | 6 +- Lib/importlib/metadata/_text.py | 20 +- Lib/importlib/resources/_common.py | 2 +- Lib/importlib/resources/_itertools.py | 2 +- Lib/ipaddress.py | 5 +- Lib/pickle.py | 2 +- Lib/pickletools.py | 50 +- Lib/poplib.py | 2 +- Lib/pydoc.py | 12 +- Lib/secrets.py | 6 +- Lib/shutil.py | 6 +- Lib/socket.py | 2 +- Lib/statistics.py | 32 +- Lib/subprocess.py | 19 +- Lib/test/sample_doctest.py | 12 +- Lib/test/test_buffer.py | 2461 ++++++++------ Lib/test/test_clinic.py | 1410 +++++--- Lib/test/test_cmd.py | 6 +- Lib/test/test_dataclasses/__init__.py | 1988 ++++++----- Lib/test/test_descr.py | 2264 +++++++++---- Lib/test/test_doctest.py | 598 ++-- Lib/test/test_doctest2.py | 22 +- Lib/test/test_enum.py | 2930 +++++++++++------ Lib/test/test_functools.py | 1280 ++++--- Lib/test/test_getopt.py | 9 +- Lib/test/test_grammar.py | 1832 +++++++---- Lib/test/test_import/__init__.py | 1017 +++--- Lib/test/test_importlib/_context.py | 2 +- Lib/test/test_importlib/_path.py | 10 +- Lib/test/test_importlib/resources/_path.py | 8 +- .../test_importlib/resources/update-zips.py | 7 +- .../test_importlib/test_namespace_pkgs.py | 3 +- Lib/test/test_json/test_enum.py | 125 +- Lib/test/test_pdb.py | 1271 +++---- Lib/test/test_pkg.py | 255 +- Lib/test/test_statistics.py | 20 +- Lib/test/test_yield_from.py | 642 ++-- Lib/test/time_hashlib.py | 60 +- Lib/test/tokenizedata/bad_coding2.py | 4 +- Lib/test/tokenizedata/coding20731.py | 3 +- Lib/turtle.py | 83 +- Lib/typing.py | 28 +- Lib/unittest/mock.py | 4 +- Lib/zipfile/_path/__init__.py | 42 +- Lib/zipfile/_path/glob.py | 10 +- 59 files changed, 11966 insertions(+), 7587 deletions(-) diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index c6e3a13f51d313..b14337fd62fc72 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -2588,7 +2588,7 @@ def __repr__(self): >>> tz = timezone.utc >>> repr(tz) 'datetime.timezone.utc' - >>> tz = timezone(timedelta(hours=-5), 'EST') + >>> tz = timezone(timedelta(hours=-5), "EST") >>> repr(tz) "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')" """ diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index 70aff5cb222829..03169add2d4cde 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -556,11 +556,9 @@ def sin(x): ... ctx = getcontext() ... ctx.prec += 2 ... print(ctx.prec) - ... 30 >>> with localcontext(ExtendedContext): ... print(getcontext().prec) - ... 9 >>> print(getcontext().prec) 28 @@ -594,15 +592,15 @@ class Decimal(object): def __new__(cls, value="0", context=None): """Create a decimal point instance. - >>> Decimal('3.14') # string input + >>> Decimal("3.14") # string input Decimal('3.14') >>> Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent) Decimal('3.14') - >>> Decimal(314) # int + >>> Decimal(314) # int Decimal('314') - >>> Decimal(Decimal(314)) # another decimal instance + >>> Decimal(Decimal(314)) # another decimal instance Decimal('314') - >>> Decimal(' 3.14 \\n') # leading and trailing whitespace okay + >>> Decimal(" 3.14 \\n") # leading and trailing whitespace okay Decimal('3.14') """ @@ -763,11 +761,11 @@ def from_float(cls, f): >>> Decimal.from_float(0.1) Decimal('0.1000000000000000055511151231257827021181583404541015625') - >>> Decimal.from_float(float('nan')) + >>> Decimal.from_float(float("nan")) Decimal('NaN') - >>> Decimal.from_float(float('inf')) + >>> Decimal.from_float(float("inf")) Decimal('Infinity') - >>> Decimal.from_float(-float('inf')) + >>> Decimal.from_float(-float("inf")) Decimal('-Infinity') >>> Decimal.from_float(-0.0) Decimal('-0') @@ -1059,11 +1057,11 @@ def as_integer_ratio(self): Returns a pair (n, d) of integers. When called on an infinity or NaN, raises OverflowError or ValueError respectively. - >>> Decimal('3.14').as_integer_ratio() + >>> Decimal("3.14").as_integer_ratio() (157, 50) - >>> Decimal('-123e5').as_integer_ratio() + >>> Decimal("-123e5").as_integer_ratio() (-12300000, 1) - >>> Decimal('0.00').as_integer_ratio() + >>> Decimal("0.00").as_integer_ratio() (0, 1) """ @@ -1925,21 +1923,21 @@ def __round__(self, n=None): and lies exactly halfway between two integers then it is rounded to the integer with even last digit. - >>> round(Decimal('123.456')) + >>> round(Decimal("123.456")) 123 - >>> round(Decimal('-456.789')) + >>> round(Decimal("-456.789")) -457 - >>> round(Decimal('-3.0')) + >>> round(Decimal("-3.0")) -3 - >>> round(Decimal('2.5')) + >>> round(Decimal("2.5")) 2 - >>> round(Decimal('3.5')) + >>> round(Decimal("3.5")) 4 - >>> round(Decimal('Inf')) + >>> round(Decimal("Inf")) Traceback (most recent call last): ... OverflowError: cannot round an infinity - >>> round(Decimal('NaN')) + >>> round(Decimal("NaN")) Traceback (most recent call last): ... ValueError: cannot round a NaN @@ -1951,15 +1949,15 @@ def __round__(self, n=None): For an integer n, round(self, -n) is exactly equivalent to self.quantize(Decimal('1En')). - >>> round(Decimal('123.456'), 0) + >>> round(Decimal("123.456"), 0) Decimal('123') - >>> round(Decimal('123.456'), 2) + >>> round(Decimal("123.456"), 2) Decimal('123.46') - >>> round(Decimal('123.456'), -2) + >>> round(Decimal("123.456"), -2) Decimal('1E+2') - >>> round(Decimal('-Infinity'), 37) + >>> round(Decimal("-Infinity"), 37) Decimal('NaN') - >>> round(Decimal('sNaN123'), 0) + >>> round(Decimal("sNaN123"), 0) Decimal('NaN123') """ @@ -4285,13 +4283,13 @@ def abs(self, a): operation on the operand. Otherwise, the result is the same as using the plus operation on the operand. - >>> ExtendedContext.abs(Decimal('2.1')) + >>> ExtendedContext.abs(Decimal("2.1")) Decimal('2.1') - >>> ExtendedContext.abs(Decimal('-100')) + >>> ExtendedContext.abs(Decimal("-100")) Decimal('100') - >>> ExtendedContext.abs(Decimal('101.5')) + >>> ExtendedContext.abs(Decimal("101.5")) Decimal('101.5') - >>> ExtendedContext.abs(Decimal('-101.5')) + >>> ExtendedContext.abs(Decimal("-101.5")) Decimal('101.5') >>> ExtendedContext.abs(-1) Decimal('1') @@ -4302,9 +4300,9 @@ def abs(self, a): def add(self, a, b): """Return the sum of the two operands. - >>> ExtendedContext.add(Decimal('12'), Decimal('7.00')) + >>> ExtendedContext.add(Decimal("12"), Decimal("7.00")) Decimal('19.00') - >>> ExtendedContext.add(Decimal('1E+2'), Decimal('1.01E+4')) + >>> ExtendedContext.add(Decimal("1E+2"), Decimal("1.01E+4")) Decimal('1.02E+4') >>> ExtendedContext.add(1, Decimal(2)) Decimal('3') @@ -4329,7 +4327,7 @@ def canonical(self, a): As we do not have different encodings for the same number, the received object already is in its canonical form. - >>> ExtendedContext.canonical(Decimal('2.50')) + >>> ExtendedContext.canonical(Decimal("2.50")) Decimal('2.50') """ if not isinstance(a, Decimal): @@ -4350,17 +4348,17 @@ def compare(self, a, b): subtraction: '-1' if the result is less than zero, '0' if the result is zero or negative zero, or '1' if the result is greater than zero. - >>> ExtendedContext.compare(Decimal('2.1'), Decimal('3')) + >>> ExtendedContext.compare(Decimal("2.1"), Decimal("3")) Decimal('-1') - >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.1')) + >>> ExtendedContext.compare(Decimal("2.1"), Decimal("2.1")) Decimal('0') - >>> ExtendedContext.compare(Decimal('2.1'), Decimal('2.10')) + >>> ExtendedContext.compare(Decimal("2.1"), Decimal("2.10")) Decimal('0') - >>> ExtendedContext.compare(Decimal('3'), Decimal('2.1')) + >>> ExtendedContext.compare(Decimal("3"), Decimal("2.1")) Decimal('1') - >>> ExtendedContext.compare(Decimal('2.1'), Decimal('-3')) + >>> ExtendedContext.compare(Decimal("2.1"), Decimal("-3")) Decimal('1') - >>> ExtendedContext.compare(Decimal('-3'), Decimal('2.1')) + >>> ExtendedContext.compare(Decimal("-3"), Decimal("2.1")) Decimal('-1') >>> ExtendedContext.compare(1, 2) Decimal('-1') @@ -4379,21 +4377,21 @@ def compare_signal(self, a, b): NaNs taking precedence over quiet NaNs. >>> c = ExtendedContext - >>> c.compare_signal(Decimal('2.1'), Decimal('3')) + >>> c.compare_signal(Decimal("2.1"), Decimal("3")) Decimal('-1') - >>> c.compare_signal(Decimal('2.1'), Decimal('2.1')) + >>> c.compare_signal(Decimal("2.1"), Decimal("2.1")) Decimal('0') >>> c.flags[InvalidOperation] = 0 >>> print(c.flags[InvalidOperation]) 0 - >>> c.compare_signal(Decimal('NaN'), Decimal('2.1')) + >>> c.compare_signal(Decimal("NaN"), Decimal("2.1")) Decimal('NaN') >>> print(c.flags[InvalidOperation]) 1 >>> c.flags[InvalidOperation] = 0 >>> print(c.flags[InvalidOperation]) 0 - >>> c.compare_signal(Decimal('sNaN'), Decimal('2.1')) + >>> c.compare_signal(Decimal("sNaN"), Decimal("2.1")) Decimal('NaN') >>> print(c.flags[InvalidOperation]) 1 @@ -4414,17 +4412,17 @@ def compare_total(self, a, b): value. Note that a total ordering is defined for all possible abstract representations. - >>> ExtendedContext.compare_total(Decimal('12.73'), Decimal('127.9')) + >>> ExtendedContext.compare_total(Decimal("12.73"), Decimal("127.9")) Decimal('-1') - >>> ExtendedContext.compare_total(Decimal('-127'), Decimal('12')) + >>> ExtendedContext.compare_total(Decimal("-127"), Decimal("12")) Decimal('-1') - >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.3')) + >>> ExtendedContext.compare_total(Decimal("12.30"), Decimal("12.3")) Decimal('-1') - >>> ExtendedContext.compare_total(Decimal('12.30'), Decimal('12.30')) + >>> ExtendedContext.compare_total(Decimal("12.30"), Decimal("12.30")) Decimal('0') - >>> ExtendedContext.compare_total(Decimal('12.3'), Decimal('12.300')) + >>> ExtendedContext.compare_total(Decimal("12.3"), Decimal("12.300")) Decimal('1') - >>> ExtendedContext.compare_total(Decimal('12.3'), Decimal('NaN')) + >>> ExtendedContext.compare_total(Decimal("12.3"), Decimal("NaN")) Decimal('-1') >>> ExtendedContext.compare_total(1, 2) Decimal('-1') @@ -4447,9 +4445,9 @@ def compare_total_mag(self, a, b): def copy_abs(self, a): """Returns a copy of the operand with the sign set to 0. - >>> ExtendedContext.copy_abs(Decimal('2.1')) + >>> ExtendedContext.copy_abs(Decimal("2.1")) Decimal('2.1') - >>> ExtendedContext.copy_abs(Decimal('-100')) + >>> ExtendedContext.copy_abs(Decimal("-100")) Decimal('100') >>> ExtendedContext.copy_abs(-1) Decimal('1') @@ -4460,9 +4458,9 @@ def copy_abs(self, a): def copy_decimal(self, a): """Returns a copy of the decimal object. - >>> ExtendedContext.copy_decimal(Decimal('2.1')) + >>> ExtendedContext.copy_decimal(Decimal("2.1")) Decimal('2.1') - >>> ExtendedContext.copy_decimal(Decimal('-1.00')) + >>> ExtendedContext.copy_decimal(Decimal("-1.00")) Decimal('-1.00') >>> ExtendedContext.copy_decimal(1) Decimal('1') @@ -4473,9 +4471,9 @@ def copy_decimal(self, a): def copy_negate(self, a): """Returns a copy of the operand with the sign inverted. - >>> ExtendedContext.copy_negate(Decimal('101.5')) + >>> ExtendedContext.copy_negate(Decimal("101.5")) Decimal('-101.5') - >>> ExtendedContext.copy_negate(Decimal('-101.5')) + >>> ExtendedContext.copy_negate(Decimal("-101.5")) Decimal('101.5') >>> ExtendedContext.copy_negate(1) Decimal('-1') @@ -4489,13 +4487,13 @@ def copy_sign(self, a, b): In detail, it returns a copy of the first operand with the sign equal to the sign of the second operand. - >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('7.33')) + >>> ExtendedContext.copy_sign(Decimal("1.50"), Decimal("7.33")) Decimal('1.50') - >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('7.33')) + >>> ExtendedContext.copy_sign(Decimal("-1.50"), Decimal("7.33")) Decimal('1.50') - >>> ExtendedContext.copy_sign(Decimal( '1.50'), Decimal('-7.33')) + >>> ExtendedContext.copy_sign(Decimal("1.50"), Decimal("-7.33")) Decimal('-1.50') - >>> ExtendedContext.copy_sign(Decimal('-1.50'), Decimal('-7.33')) + >>> ExtendedContext.copy_sign(Decimal("-1.50"), Decimal("-7.33")) Decimal('-1.50') >>> ExtendedContext.copy_sign(1, -2) Decimal('-1') @@ -4510,25 +4508,25 @@ def copy_sign(self, a, b): def divide(self, a, b): """Decimal division in a specified context. - >>> ExtendedContext.divide(Decimal('1'), Decimal('3')) + >>> ExtendedContext.divide(Decimal("1"), Decimal("3")) Decimal('0.333333333') - >>> ExtendedContext.divide(Decimal('2'), Decimal('3')) + >>> ExtendedContext.divide(Decimal("2"), Decimal("3")) Decimal('0.666666667') - >>> ExtendedContext.divide(Decimal('5'), Decimal('2')) + >>> ExtendedContext.divide(Decimal("5"), Decimal("2")) Decimal('2.5') - >>> ExtendedContext.divide(Decimal('1'), Decimal('10')) + >>> ExtendedContext.divide(Decimal("1"), Decimal("10")) Decimal('0.1') - >>> ExtendedContext.divide(Decimal('12'), Decimal('12')) + >>> ExtendedContext.divide(Decimal("12"), Decimal("12")) Decimal('1') - >>> ExtendedContext.divide(Decimal('8.00'), Decimal('2')) + >>> ExtendedContext.divide(Decimal("8.00"), Decimal("2")) Decimal('4.00') - >>> ExtendedContext.divide(Decimal('2.400'), Decimal('2.0')) + >>> ExtendedContext.divide(Decimal("2.400"), Decimal("2.0")) Decimal('1.20') - >>> ExtendedContext.divide(Decimal('1000'), Decimal('100')) + >>> ExtendedContext.divide(Decimal("1000"), Decimal("100")) Decimal('10') - >>> ExtendedContext.divide(Decimal('1000'), Decimal('1')) + >>> ExtendedContext.divide(Decimal("1000"), Decimal("1")) Decimal('1000') - >>> ExtendedContext.divide(Decimal('2.40E+6'), Decimal('2')) + >>> ExtendedContext.divide(Decimal("2.40E+6"), Decimal("2")) Decimal('1.20E+6') >>> ExtendedContext.divide(5, 5) Decimal('1') @@ -4547,11 +4545,11 @@ def divide(self, a, b): def divide_int(self, a, b): """Divides two numbers and returns the integer part of the result. - >>> ExtendedContext.divide_int(Decimal('2'), Decimal('3')) + >>> ExtendedContext.divide_int(Decimal("2"), Decimal("3")) Decimal('0') - >>> ExtendedContext.divide_int(Decimal('10'), Decimal('3')) + >>> ExtendedContext.divide_int(Decimal("10"), Decimal("3")) Decimal('3') - >>> ExtendedContext.divide_int(Decimal('1'), Decimal('0.3')) + >>> ExtendedContext.divide_int(Decimal("1"), Decimal("0.3")) Decimal('3') >>> ExtendedContext.divide_int(10, 3) Decimal('3') @@ -4594,17 +4592,17 @@ def exp(self, a): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> c.exp(Decimal('-Infinity')) + >>> c.exp(Decimal("-Infinity")) Decimal('0') - >>> c.exp(Decimal('-1')) + >>> c.exp(Decimal("-1")) Decimal('0.367879441') - >>> c.exp(Decimal('0')) + >>> c.exp(Decimal("0")) Decimal('1') - >>> c.exp(Decimal('1')) + >>> c.exp(Decimal("1")) Decimal('2.71828183') - >>> c.exp(Decimal('0.693147181')) + >>> c.exp(Decimal("0.693147181")) Decimal('2.00000000') - >>> c.exp(Decimal('+Infinity')) + >>> c.exp(Decimal("+Infinity")) Decimal('Infinity') >>> c.exp(10) Decimal('22026.4658') @@ -4619,11 +4617,11 @@ def fma(self, a, b, c): the third operand is then added to the result of that multiplication, using add, all with only one final rounding. - >>> ExtendedContext.fma(Decimal('3'), Decimal('5'), Decimal('7')) + >>> ExtendedContext.fma(Decimal("3"), Decimal("5"), Decimal("7")) Decimal('22') - >>> ExtendedContext.fma(Decimal('3'), Decimal('-5'), Decimal('7')) + >>> ExtendedContext.fma(Decimal("3"), Decimal("-5"), Decimal("7")) Decimal('-8') - >>> ExtendedContext.fma(Decimal('888565290'), Decimal('1557.96930'), Decimal('-86087.7578')) + >>> ExtendedContext.fma(Decimal("888565290"), Decimal("1557.96930"), Decimal("-86087.7578")) Decimal('1.38435736E+12') >>> ExtendedContext.fma(1, 3, 4) Decimal('7') @@ -4641,7 +4639,7 @@ def is_canonical(self, a): Currently, the encoding of a Decimal instance is always canonical, so this method returns True for any Decimal. - >>> ExtendedContext.is_canonical(Decimal('2.50')) + >>> ExtendedContext.is_canonical(Decimal("2.50")) True """ if not isinstance(a, Decimal): @@ -4654,15 +4652,15 @@ def is_finite(self, a): A Decimal instance is considered finite if it is neither infinite nor a NaN. - >>> ExtendedContext.is_finite(Decimal('2.50')) + >>> ExtendedContext.is_finite(Decimal("2.50")) True - >>> ExtendedContext.is_finite(Decimal('-0.3')) + >>> ExtendedContext.is_finite(Decimal("-0.3")) True - >>> ExtendedContext.is_finite(Decimal('0')) + >>> ExtendedContext.is_finite(Decimal("0")) True - >>> ExtendedContext.is_finite(Decimal('Inf')) + >>> ExtendedContext.is_finite(Decimal("Inf")) False - >>> ExtendedContext.is_finite(Decimal('NaN')) + >>> ExtendedContext.is_finite(Decimal("NaN")) False >>> ExtendedContext.is_finite(1) True @@ -4673,11 +4671,11 @@ def is_finite(self, a): def is_infinite(self, a): """Return True if the operand is infinite; otherwise return False. - >>> ExtendedContext.is_infinite(Decimal('2.50')) + >>> ExtendedContext.is_infinite(Decimal("2.50")) False - >>> ExtendedContext.is_infinite(Decimal('-Inf')) + >>> ExtendedContext.is_infinite(Decimal("-Inf")) True - >>> ExtendedContext.is_infinite(Decimal('NaN')) + >>> ExtendedContext.is_infinite(Decimal("NaN")) False >>> ExtendedContext.is_infinite(1) False @@ -4689,11 +4687,11 @@ def is_nan(self, a): """Return True if the operand is a qNaN or sNaN; otherwise return False. - >>> ExtendedContext.is_nan(Decimal('2.50')) + >>> ExtendedContext.is_nan(Decimal("2.50")) False - >>> ExtendedContext.is_nan(Decimal('NaN')) + >>> ExtendedContext.is_nan(Decimal("NaN")) True - >>> ExtendedContext.is_nan(Decimal('-sNaN')) + >>> ExtendedContext.is_nan(Decimal("-sNaN")) True >>> ExtendedContext.is_nan(1) False @@ -4708,15 +4706,15 @@ def is_normal(self, a): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> c.is_normal(Decimal('2.50')) + >>> c.is_normal(Decimal("2.50")) True - >>> c.is_normal(Decimal('0.1E-999')) + >>> c.is_normal(Decimal("0.1E-999")) False - >>> c.is_normal(Decimal('0.00')) + >>> c.is_normal(Decimal("0.00")) False - >>> c.is_normal(Decimal('-Inf')) + >>> c.is_normal(Decimal("-Inf")) False - >>> c.is_normal(Decimal('NaN')) + >>> c.is_normal(Decimal("NaN")) False >>> c.is_normal(1) True @@ -4727,11 +4725,11 @@ def is_normal(self, a): def is_qnan(self, a): """Return True if the operand is a quiet NaN; otherwise return False. - >>> ExtendedContext.is_qnan(Decimal('2.50')) + >>> ExtendedContext.is_qnan(Decimal("2.50")) False - >>> ExtendedContext.is_qnan(Decimal('NaN')) + >>> ExtendedContext.is_qnan(Decimal("NaN")) True - >>> ExtendedContext.is_qnan(Decimal('sNaN')) + >>> ExtendedContext.is_qnan(Decimal("sNaN")) False >>> ExtendedContext.is_qnan(1) False @@ -4742,11 +4740,11 @@ def is_qnan(self, a): def is_signed(self, a): """Return True if the operand is negative; otherwise return False. - >>> ExtendedContext.is_signed(Decimal('2.50')) + >>> ExtendedContext.is_signed(Decimal("2.50")) False - >>> ExtendedContext.is_signed(Decimal('-12')) + >>> ExtendedContext.is_signed(Decimal("-12")) True - >>> ExtendedContext.is_signed(Decimal('-0')) + >>> ExtendedContext.is_signed(Decimal("-0")) True >>> ExtendedContext.is_signed(8) False @@ -4760,11 +4758,11 @@ def is_snan(self, a): """Return True if the operand is a signaling NaN; otherwise return False. - >>> ExtendedContext.is_snan(Decimal('2.50')) + >>> ExtendedContext.is_snan(Decimal("2.50")) False - >>> ExtendedContext.is_snan(Decimal('NaN')) + >>> ExtendedContext.is_snan(Decimal("NaN")) False - >>> ExtendedContext.is_snan(Decimal('sNaN')) + >>> ExtendedContext.is_snan(Decimal("sNaN")) True >>> ExtendedContext.is_snan(1) False @@ -4778,15 +4776,15 @@ def is_subnormal(self, a): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> c.is_subnormal(Decimal('2.50')) + >>> c.is_subnormal(Decimal("2.50")) False - >>> c.is_subnormal(Decimal('0.1E-999')) + >>> c.is_subnormal(Decimal("0.1E-999")) True - >>> c.is_subnormal(Decimal('0.00')) + >>> c.is_subnormal(Decimal("0.00")) False - >>> c.is_subnormal(Decimal('-Inf')) + >>> c.is_subnormal(Decimal("-Inf")) False - >>> c.is_subnormal(Decimal('NaN')) + >>> c.is_subnormal(Decimal("NaN")) False >>> c.is_subnormal(1) False @@ -4797,11 +4795,11 @@ def is_subnormal(self, a): def is_zero(self, a): """Return True if the operand is a zero; otherwise return False. - >>> ExtendedContext.is_zero(Decimal('0')) + >>> ExtendedContext.is_zero(Decimal("0")) True - >>> ExtendedContext.is_zero(Decimal('2.50')) + >>> ExtendedContext.is_zero(Decimal("2.50")) False - >>> ExtendedContext.is_zero(Decimal('-0E+2')) + >>> ExtendedContext.is_zero(Decimal("-0E+2")) True >>> ExtendedContext.is_zero(1) False @@ -4817,15 +4815,15 @@ def ln(self, a): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> c.ln(Decimal('0')) + >>> c.ln(Decimal("0")) Decimal('-Infinity') - >>> c.ln(Decimal('1.000')) + >>> c.ln(Decimal("1.000")) Decimal('0') - >>> c.ln(Decimal('2.71828183')) + >>> c.ln(Decimal("2.71828183")) Decimal('1.00000000') - >>> c.ln(Decimal('10')) + >>> c.ln(Decimal("10")) Decimal('2.30258509') - >>> c.ln(Decimal('+Infinity')) + >>> c.ln(Decimal("+Infinity")) Decimal('Infinity') >>> c.ln(1) Decimal('0') @@ -4839,19 +4837,19 @@ def log10(self, a): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> c.log10(Decimal('0')) + >>> c.log10(Decimal("0")) Decimal('-Infinity') - >>> c.log10(Decimal('0.001')) + >>> c.log10(Decimal("0.001")) Decimal('-3') - >>> c.log10(Decimal('1.000')) + >>> c.log10(Decimal("1.000")) Decimal('0') - >>> c.log10(Decimal('2')) + >>> c.log10(Decimal("2")) Decimal('0.301029996') - >>> c.log10(Decimal('10')) + >>> c.log10(Decimal("10")) Decimal('1') - >>> c.log10(Decimal('70')) + >>> c.log10(Decimal("70")) Decimal('1.84509804') - >>> c.log10(Decimal('+Infinity')) + >>> c.log10(Decimal("+Infinity")) Decimal('Infinity') >>> c.log10(0) Decimal('-Infinity') @@ -4869,13 +4867,13 @@ def logb(self, a): operand were truncated to a single digit while maintaining the value of that digit and without limiting the resulting exponent). - >>> ExtendedContext.logb(Decimal('250')) + >>> ExtendedContext.logb(Decimal("250")) Decimal('2') - >>> ExtendedContext.logb(Decimal('2.50')) + >>> ExtendedContext.logb(Decimal("2.50")) Decimal('0') - >>> ExtendedContext.logb(Decimal('0.03')) + >>> ExtendedContext.logb(Decimal("0.03")) Decimal('-2') - >>> ExtendedContext.logb(Decimal('0')) + >>> ExtendedContext.logb(Decimal("0")) Decimal('-Infinity') >>> ExtendedContext.logb(1) Decimal('0') @@ -4892,17 +4890,17 @@ def logical_and(self, a, b): The operands must be both logical numbers. - >>> ExtendedContext.logical_and(Decimal('0'), Decimal('0')) + >>> ExtendedContext.logical_and(Decimal("0"), Decimal("0")) Decimal('0') - >>> ExtendedContext.logical_and(Decimal('0'), Decimal('1')) + >>> ExtendedContext.logical_and(Decimal("0"), Decimal("1")) Decimal('0') - >>> ExtendedContext.logical_and(Decimal('1'), Decimal('0')) + >>> ExtendedContext.logical_and(Decimal("1"), Decimal("0")) Decimal('0') - >>> ExtendedContext.logical_and(Decimal('1'), Decimal('1')) + >>> ExtendedContext.logical_and(Decimal("1"), Decimal("1")) Decimal('1') - >>> ExtendedContext.logical_and(Decimal('1100'), Decimal('1010')) + >>> ExtendedContext.logical_and(Decimal("1100"), Decimal("1010")) Decimal('1000') - >>> ExtendedContext.logical_and(Decimal('1111'), Decimal('10')) + >>> ExtendedContext.logical_and(Decimal("1111"), Decimal("10")) Decimal('10') >>> ExtendedContext.logical_and(110, 1101) Decimal('100') @@ -4919,13 +4917,13 @@ def logical_invert(self, a): The operand must be a logical number. - >>> ExtendedContext.logical_invert(Decimal('0')) + >>> ExtendedContext.logical_invert(Decimal("0")) Decimal('111111111') - >>> ExtendedContext.logical_invert(Decimal('1')) + >>> ExtendedContext.logical_invert(Decimal("1")) Decimal('111111110') - >>> ExtendedContext.logical_invert(Decimal('111111111')) + >>> ExtendedContext.logical_invert(Decimal("111111111")) Decimal('0') - >>> ExtendedContext.logical_invert(Decimal('101010101')) + >>> ExtendedContext.logical_invert(Decimal("101010101")) Decimal('10101010') >>> ExtendedContext.logical_invert(1101) Decimal('111110010') @@ -4938,17 +4936,17 @@ def logical_or(self, a, b): The operands must be both logical numbers. - >>> ExtendedContext.logical_or(Decimal('0'), Decimal('0')) + >>> ExtendedContext.logical_or(Decimal("0"), Decimal("0")) Decimal('0') - >>> ExtendedContext.logical_or(Decimal('0'), Decimal('1')) + >>> ExtendedContext.logical_or(Decimal("0"), Decimal("1")) Decimal('1') - >>> ExtendedContext.logical_or(Decimal('1'), Decimal('0')) + >>> ExtendedContext.logical_or(Decimal("1"), Decimal("0")) Decimal('1') - >>> ExtendedContext.logical_or(Decimal('1'), Decimal('1')) + >>> ExtendedContext.logical_or(Decimal("1"), Decimal("1")) Decimal('1') - >>> ExtendedContext.logical_or(Decimal('1100'), Decimal('1010')) + >>> ExtendedContext.logical_or(Decimal("1100"), Decimal("1010")) Decimal('1110') - >>> ExtendedContext.logical_or(Decimal('1110'), Decimal('10')) + >>> ExtendedContext.logical_or(Decimal("1110"), Decimal("10")) Decimal('1110') >>> ExtendedContext.logical_or(110, 1101) Decimal('1111') @@ -4965,17 +4963,17 @@ def logical_xor(self, a, b): The operands must be both logical numbers. - >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('0')) + >>> ExtendedContext.logical_xor(Decimal("0"), Decimal("0")) Decimal('0') - >>> ExtendedContext.logical_xor(Decimal('0'), Decimal('1')) + >>> ExtendedContext.logical_xor(Decimal("0"), Decimal("1")) Decimal('1') - >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('0')) + >>> ExtendedContext.logical_xor(Decimal("1"), Decimal("0")) Decimal('1') - >>> ExtendedContext.logical_xor(Decimal('1'), Decimal('1')) + >>> ExtendedContext.logical_xor(Decimal("1"), Decimal("1")) Decimal('0') - >>> ExtendedContext.logical_xor(Decimal('1100'), Decimal('1010')) + >>> ExtendedContext.logical_xor(Decimal("1100"), Decimal("1010")) Decimal('110') - >>> ExtendedContext.logical_xor(Decimal('1111'), Decimal('10')) + >>> ExtendedContext.logical_xor(Decimal("1111"), Decimal("10")) Decimal('1101') >>> ExtendedContext.logical_xor(110, 1101) Decimal('1011') @@ -4996,13 +4994,13 @@ def max(self, a, b): is chosen as the result. Otherwise the maximum (closer to positive infinity) of the two operands is chosen as the result. - >>> ExtendedContext.max(Decimal('3'), Decimal('2')) + >>> ExtendedContext.max(Decimal("3"), Decimal("2")) Decimal('3') - >>> ExtendedContext.max(Decimal('-10'), Decimal('3')) + >>> ExtendedContext.max(Decimal("-10"), Decimal("3")) Decimal('3') - >>> ExtendedContext.max(Decimal('1.0'), Decimal('1')) + >>> ExtendedContext.max(Decimal("1.0"), Decimal("1")) Decimal('1') - >>> ExtendedContext.max(Decimal('7'), Decimal('NaN')) + >>> ExtendedContext.max(Decimal("7"), Decimal("NaN")) Decimal('7') >>> ExtendedContext.max(1, 2) Decimal('2') @@ -5017,9 +5015,9 @@ def max(self, a, b): def max_mag(self, a, b): """Compares the values numerically with their sign ignored. - >>> ExtendedContext.max_mag(Decimal('7'), Decimal('NaN')) + >>> ExtendedContext.max_mag(Decimal("7"), Decimal("NaN")) Decimal('7') - >>> ExtendedContext.max_mag(Decimal('7'), Decimal('-10')) + >>> ExtendedContext.max_mag(Decimal("7"), Decimal("-10")) Decimal('-10') >>> ExtendedContext.max_mag(1, -2) Decimal('-2') @@ -5040,13 +5038,13 @@ def min(self, a, b): is chosen as the result. Otherwise the minimum (closer to negative infinity) of the two operands is chosen as the result. - >>> ExtendedContext.min(Decimal('3'), Decimal('2')) + >>> ExtendedContext.min(Decimal("3"), Decimal("2")) Decimal('2') - >>> ExtendedContext.min(Decimal('-10'), Decimal('3')) + >>> ExtendedContext.min(Decimal("-10"), Decimal("3")) Decimal('-10') - >>> ExtendedContext.min(Decimal('1.0'), Decimal('1')) + >>> ExtendedContext.min(Decimal("1.0"), Decimal("1")) Decimal('1.0') - >>> ExtendedContext.min(Decimal('7'), Decimal('NaN')) + >>> ExtendedContext.min(Decimal("7"), Decimal("NaN")) Decimal('7') >>> ExtendedContext.min(1, 2) Decimal('1') @@ -5061,9 +5059,9 @@ def min(self, a, b): def min_mag(self, a, b): """Compares the values numerically with their sign ignored. - >>> ExtendedContext.min_mag(Decimal('3'), Decimal('-2')) + >>> ExtendedContext.min_mag(Decimal("3"), Decimal("-2")) Decimal('-2') - >>> ExtendedContext.min_mag(Decimal('-3'), Decimal('NaN')) + >>> ExtendedContext.min_mag(Decimal("-3"), Decimal("NaN")) Decimal('-3') >>> ExtendedContext.min_mag(1, -2) Decimal('1') @@ -5082,9 +5080,9 @@ def minus(self, a): operation minus(a) is calculated as subtract('0', a) where the '0' has the same exponent as the operand. - >>> ExtendedContext.minus(Decimal('1.3')) + >>> ExtendedContext.minus(Decimal("1.3")) Decimal('-1.3') - >>> ExtendedContext.minus(Decimal('-1.3')) + >>> ExtendedContext.minus(Decimal("-1.3")) Decimal('1.3') >>> ExtendedContext.minus(1) Decimal('-1') @@ -5100,15 +5098,15 @@ def multiply(self, a, b): ('long multiplication'), resulting in a number which may be as long as the sum of the lengths of the two operands. - >>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3')) + >>> ExtendedContext.multiply(Decimal("1.20"), Decimal("3")) Decimal('3.60') - >>> ExtendedContext.multiply(Decimal('7'), Decimal('3')) + >>> ExtendedContext.multiply(Decimal("7"), Decimal("3")) Decimal('21') - >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('0.8')) + >>> ExtendedContext.multiply(Decimal("0.9"), Decimal("0.8")) Decimal('0.72') - >>> ExtendedContext.multiply(Decimal('0.9'), Decimal('-0')) + >>> ExtendedContext.multiply(Decimal("0.9"), Decimal("-0")) Decimal('-0.0') - >>> ExtendedContext.multiply(Decimal('654321'), Decimal('654321')) + >>> ExtendedContext.multiply(Decimal("654321"), Decimal("654321")) Decimal('4.28135971E+11') >>> ExtendedContext.multiply(7, 7) Decimal('49') @@ -5130,13 +5128,13 @@ def next_minus(self, a): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> ExtendedContext.next_minus(Decimal('1')) + >>> ExtendedContext.next_minus(Decimal("1")) Decimal('0.999999999') - >>> c.next_minus(Decimal('1E-1007')) + >>> c.next_minus(Decimal("1E-1007")) Decimal('0E-1007') - >>> ExtendedContext.next_minus(Decimal('-1.00000003')) + >>> ExtendedContext.next_minus(Decimal("-1.00000003")) Decimal('-1.00000004') - >>> c.next_minus(Decimal('Infinity')) + >>> c.next_minus(Decimal("Infinity")) Decimal('9.99999999E+999') >>> c.next_minus(1) Decimal('0.999999999') @@ -5150,13 +5148,13 @@ def next_plus(self, a): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> ExtendedContext.next_plus(Decimal('1')) + >>> ExtendedContext.next_plus(Decimal("1")) Decimal('1.00000001') - >>> c.next_plus(Decimal('-1E-1007')) + >>> c.next_plus(Decimal("-1E-1007")) Decimal('-0E-1007') - >>> ExtendedContext.next_plus(Decimal('-1.00000003')) + >>> ExtendedContext.next_plus(Decimal("-1.00000003")) Decimal('-1.00000002') - >>> c.next_plus(Decimal('-Infinity')) + >>> c.next_plus(Decimal("-Infinity")) Decimal('-9.99999999E+999') >>> c.next_plus(1) Decimal('1.00000001') @@ -5175,19 +5173,19 @@ def next_toward(self, a, b): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> c.next_toward(Decimal('1'), Decimal('2')) + >>> c.next_toward(Decimal("1"), Decimal("2")) Decimal('1.00000001') - >>> c.next_toward(Decimal('-1E-1007'), Decimal('1')) + >>> c.next_toward(Decimal("-1E-1007"), Decimal("1")) Decimal('-0E-1007') - >>> c.next_toward(Decimal('-1.00000003'), Decimal('0')) + >>> c.next_toward(Decimal("-1.00000003"), Decimal("0")) Decimal('-1.00000002') - >>> c.next_toward(Decimal('1'), Decimal('0')) + >>> c.next_toward(Decimal("1"), Decimal("0")) Decimal('0.999999999') - >>> c.next_toward(Decimal('1E-1007'), Decimal('-100')) + >>> c.next_toward(Decimal("1E-1007"), Decimal("-100")) Decimal('0E-1007') - >>> c.next_toward(Decimal('-1.00000003'), Decimal('-10')) + >>> c.next_toward(Decimal("-1.00000003"), Decimal("-10")) Decimal('-1.00000004') - >>> c.next_toward(Decimal('0.00'), Decimal('-0.0000')) + >>> c.next_toward(Decimal("0.00"), Decimal("-0.0000")) Decimal('-0.00') >>> c.next_toward(0, 1) Decimal('1E-1007') @@ -5205,17 +5203,17 @@ def normalize(self, a): Essentially a plus operation with all trailing zeros removed from the result. - >>> ExtendedContext.normalize(Decimal('2.1')) + >>> ExtendedContext.normalize(Decimal("2.1")) Decimal('2.1') - >>> ExtendedContext.normalize(Decimal('-2.0')) + >>> ExtendedContext.normalize(Decimal("-2.0")) Decimal('-2') - >>> ExtendedContext.normalize(Decimal('1.200')) + >>> ExtendedContext.normalize(Decimal("1.200")) Decimal('1.2') - >>> ExtendedContext.normalize(Decimal('-120')) + >>> ExtendedContext.normalize(Decimal("-120")) Decimal('-1.2E+2') - >>> ExtendedContext.normalize(Decimal('120.00')) + >>> ExtendedContext.normalize(Decimal("120.00")) Decimal('1.2E+2') - >>> ExtendedContext.normalize(Decimal('0.00')) + >>> ExtendedContext.normalize(Decimal("0.00")) Decimal('0') >>> ExtendedContext.normalize(6) Decimal('6') @@ -5241,31 +5239,31 @@ def number_class(self, a): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> c.number_class(Decimal('Infinity')) + >>> c.number_class(Decimal("Infinity")) '+Infinity' - >>> c.number_class(Decimal('1E-10')) + >>> c.number_class(Decimal("1E-10")) '+Normal' - >>> c.number_class(Decimal('2.50')) + >>> c.number_class(Decimal("2.50")) '+Normal' - >>> c.number_class(Decimal('0.1E-999')) + >>> c.number_class(Decimal("0.1E-999")) '+Subnormal' - >>> c.number_class(Decimal('0')) + >>> c.number_class(Decimal("0")) '+Zero' - >>> c.number_class(Decimal('-0')) + >>> c.number_class(Decimal("-0")) '-Zero' - >>> c.number_class(Decimal('-0.1E-999')) + >>> c.number_class(Decimal("-0.1E-999")) '-Subnormal' - >>> c.number_class(Decimal('-1E-10')) + >>> c.number_class(Decimal("-1E-10")) '-Normal' - >>> c.number_class(Decimal('-2.50')) + >>> c.number_class(Decimal("-2.50")) '-Normal' - >>> c.number_class(Decimal('-Infinity')) + >>> c.number_class(Decimal("-Infinity")) '-Infinity' - >>> c.number_class(Decimal('NaN')) + >>> c.number_class(Decimal("NaN")) 'NaN' - >>> c.number_class(Decimal('-NaN')) + >>> c.number_class(Decimal("-NaN")) 'NaN' - >>> c.number_class(Decimal('sNaN')) + >>> c.number_class(Decimal("sNaN")) 'sNaN' >>> c.number_class(123) '+Normal' @@ -5280,9 +5278,9 @@ def plus(self, a): operation plus(a) is calculated as add('0', a) where the '0' has the same exponent as the operand. - >>> ExtendedContext.plus(Decimal('1.3')) + >>> ExtendedContext.plus(Decimal("1.3")) Decimal('1.3') - >>> ExtendedContext.plus(Decimal('-1.3')) + >>> ExtendedContext.plus(Decimal("-1.3")) Decimal('-1.3') >>> ExtendedContext.plus(-1) Decimal('-1') @@ -5315,46 +5313,46 @@ def power(self, a, b, modulo=None): >>> c = ExtendedContext.copy() >>> c.Emin = -999 >>> c.Emax = 999 - >>> c.power(Decimal('2'), Decimal('3')) + >>> c.power(Decimal("2"), Decimal("3")) Decimal('8') - >>> c.power(Decimal('-2'), Decimal('3')) + >>> c.power(Decimal("-2"), Decimal("3")) Decimal('-8') - >>> c.power(Decimal('2'), Decimal('-3')) + >>> c.power(Decimal("2"), Decimal("-3")) Decimal('0.125') - >>> c.power(Decimal('1.7'), Decimal('8')) + >>> c.power(Decimal("1.7"), Decimal("8")) Decimal('69.7575744') - >>> c.power(Decimal('10'), Decimal('0.301029996')) + >>> c.power(Decimal("10"), Decimal("0.301029996")) Decimal('2.00000000') - >>> c.power(Decimal('Infinity'), Decimal('-1')) + >>> c.power(Decimal("Infinity"), Decimal("-1")) Decimal('0') - >>> c.power(Decimal('Infinity'), Decimal('0')) + >>> c.power(Decimal("Infinity"), Decimal("0")) Decimal('1') - >>> c.power(Decimal('Infinity'), Decimal('1')) + >>> c.power(Decimal("Infinity"), Decimal("1")) Decimal('Infinity') - >>> c.power(Decimal('-Infinity'), Decimal('-1')) + >>> c.power(Decimal("-Infinity"), Decimal("-1")) Decimal('-0') - >>> c.power(Decimal('-Infinity'), Decimal('0')) + >>> c.power(Decimal("-Infinity"), Decimal("0")) Decimal('1') - >>> c.power(Decimal('-Infinity'), Decimal('1')) + >>> c.power(Decimal("-Infinity"), Decimal("1")) Decimal('-Infinity') - >>> c.power(Decimal('-Infinity'), Decimal('2')) + >>> c.power(Decimal("-Infinity"), Decimal("2")) Decimal('Infinity') - >>> c.power(Decimal('0'), Decimal('0')) + >>> c.power(Decimal("0"), Decimal("0")) Decimal('NaN') - >>> c.power(Decimal('3'), Decimal('7'), Decimal('16')) + >>> c.power(Decimal("3"), Decimal("7"), Decimal("16")) Decimal('11') - >>> c.power(Decimal('-3'), Decimal('7'), Decimal('16')) + >>> c.power(Decimal("-3"), Decimal("7"), Decimal("16")) Decimal('-11') - >>> c.power(Decimal('-3'), Decimal('8'), Decimal('16')) + >>> c.power(Decimal("-3"), Decimal("8"), Decimal("16")) Decimal('1') - >>> c.power(Decimal('3'), Decimal('7'), Decimal('-16')) + >>> c.power(Decimal("3"), Decimal("7"), Decimal("-16")) Decimal('11') - >>> c.power(Decimal('23E12345'), Decimal('67E189'), Decimal('123456789')) + >>> c.power(Decimal("23E12345"), Decimal("67E189"), Decimal("123456789")) Decimal('11729830') - >>> c.power(Decimal('-0'), Decimal('17'), Decimal('1729')) + >>> c.power(Decimal("-0"), Decimal("17"), Decimal("1729")) Decimal('-0') - >>> c.power(Decimal('-23'), Decimal('0'), Decimal('65537')) + >>> c.power(Decimal("-23"), Decimal("0"), Decimal("65537")) Decimal('1') >>> ExtendedContext.power(7, 7) Decimal('823543') @@ -5388,35 +5386,35 @@ def quantize(self, a, b): Also unlike other operations, quantize will never raise Underflow, even if the result is subnormal and inexact. - >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.001')) + >>> ExtendedContext.quantize(Decimal("2.17"), Decimal("0.001")) Decimal('2.170') - >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.01')) + >>> ExtendedContext.quantize(Decimal("2.17"), Decimal("0.01")) Decimal('2.17') - >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('0.1')) + >>> ExtendedContext.quantize(Decimal("2.17"), Decimal("0.1")) Decimal('2.2') - >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+0')) + >>> ExtendedContext.quantize(Decimal("2.17"), Decimal("1e+0")) Decimal('2') - >>> ExtendedContext.quantize(Decimal('2.17'), Decimal('1e+1')) + >>> ExtendedContext.quantize(Decimal("2.17"), Decimal("1e+1")) Decimal('0E+1') - >>> ExtendedContext.quantize(Decimal('-Inf'), Decimal('Infinity')) + >>> ExtendedContext.quantize(Decimal("-Inf"), Decimal("Infinity")) Decimal('-Infinity') - >>> ExtendedContext.quantize(Decimal('2'), Decimal('Infinity')) + >>> ExtendedContext.quantize(Decimal("2"), Decimal("Infinity")) Decimal('NaN') - >>> ExtendedContext.quantize(Decimal('-0.1'), Decimal('1')) + >>> ExtendedContext.quantize(Decimal("-0.1"), Decimal("1")) Decimal('-0') - >>> ExtendedContext.quantize(Decimal('-0'), Decimal('1e+5')) + >>> ExtendedContext.quantize(Decimal("-0"), Decimal("1e+5")) Decimal('-0E+5') - >>> ExtendedContext.quantize(Decimal('+35236450.6'), Decimal('1e-2')) + >>> ExtendedContext.quantize(Decimal("+35236450.6"), Decimal("1e-2")) Decimal('NaN') - >>> ExtendedContext.quantize(Decimal('-35236450.6'), Decimal('1e-2')) + >>> ExtendedContext.quantize(Decimal("-35236450.6"), Decimal("1e-2")) Decimal('NaN') - >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-1')) + >>> ExtendedContext.quantize(Decimal("217"), Decimal("1e-1")) Decimal('217.0') - >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e-0')) + >>> ExtendedContext.quantize(Decimal("217"), Decimal("1e-0")) Decimal('217') - >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+1')) + >>> ExtendedContext.quantize(Decimal("217"), Decimal("1e+1")) Decimal('2.2E+2') - >>> ExtendedContext.quantize(Decimal('217'), Decimal('1e+2')) + >>> ExtendedContext.quantize(Decimal("217"), Decimal("1e+2")) Decimal('2E+2') >>> ExtendedContext.quantize(1, 2) Decimal('1') @@ -5448,17 +5446,17 @@ def remainder(self, a, b): (that is, if integer division on the same two operands would fail, the remainder cannot be calculated). - >>> ExtendedContext.remainder(Decimal('2.1'), Decimal('3')) + >>> ExtendedContext.remainder(Decimal("2.1"), Decimal("3")) Decimal('2.1') - >>> ExtendedContext.remainder(Decimal('10'), Decimal('3')) + >>> ExtendedContext.remainder(Decimal("10"), Decimal("3")) Decimal('1') - >>> ExtendedContext.remainder(Decimal('-10'), Decimal('3')) + >>> ExtendedContext.remainder(Decimal("-10"), Decimal("3")) Decimal('-1') - >>> ExtendedContext.remainder(Decimal('10.2'), Decimal('1')) + >>> ExtendedContext.remainder(Decimal("10.2"), Decimal("1")) Decimal('0.2') - >>> ExtendedContext.remainder(Decimal('10'), Decimal('0.3')) + >>> ExtendedContext.remainder(Decimal("10"), Decimal("0.3")) Decimal('0.1') - >>> ExtendedContext.remainder(Decimal('3.6'), Decimal('1.3')) + >>> ExtendedContext.remainder(Decimal("3.6"), Decimal("1.3")) Decimal('1.0') >>> ExtendedContext.remainder(22, 6) Decimal('4') @@ -5484,19 +5482,19 @@ def remainder_near(self, a, b): (that is, if integer division on the same two operands would fail, the remainder cannot be calculated). - >>> ExtendedContext.remainder_near(Decimal('2.1'), Decimal('3')) + >>> ExtendedContext.remainder_near(Decimal("2.1"), Decimal("3")) Decimal('-0.9') - >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('6')) + >>> ExtendedContext.remainder_near(Decimal("10"), Decimal("6")) Decimal('-2') - >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('3')) + >>> ExtendedContext.remainder_near(Decimal("10"), Decimal("3")) Decimal('1') - >>> ExtendedContext.remainder_near(Decimal('-10'), Decimal('3')) + >>> ExtendedContext.remainder_near(Decimal("-10"), Decimal("3")) Decimal('-1') - >>> ExtendedContext.remainder_near(Decimal('10.2'), Decimal('1')) + >>> ExtendedContext.remainder_near(Decimal("10.2"), Decimal("1")) Decimal('0.2') - >>> ExtendedContext.remainder_near(Decimal('10'), Decimal('0.3')) + >>> ExtendedContext.remainder_near(Decimal("10"), Decimal("0.3")) Decimal('0.1') - >>> ExtendedContext.remainder_near(Decimal('3.6'), Decimal('1.3')) + >>> ExtendedContext.remainder_near(Decimal("3.6"), Decimal("1.3")) Decimal('-0.3') >>> ExtendedContext.remainder_near(3, 11) Decimal('3') @@ -5517,15 +5515,15 @@ def rotate(self, a, b): with the rotation being to the left if the second operand is positive or to the right otherwise. - >>> ExtendedContext.rotate(Decimal('34'), Decimal('8')) + >>> ExtendedContext.rotate(Decimal("34"), Decimal("8")) Decimal('400000003') - >>> ExtendedContext.rotate(Decimal('12'), Decimal('9')) + >>> ExtendedContext.rotate(Decimal("12"), Decimal("9")) Decimal('12') - >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('-2')) + >>> ExtendedContext.rotate(Decimal("123456789"), Decimal("-2")) Decimal('891234567') - >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('0')) + >>> ExtendedContext.rotate(Decimal("123456789"), Decimal("0")) Decimal('123456789') - >>> ExtendedContext.rotate(Decimal('123456789'), Decimal('+2')) + >>> ExtendedContext.rotate(Decimal("123456789"), Decimal("+2")) Decimal('345678912') >>> ExtendedContext.rotate(1333333, 1) Decimal('13333330') @@ -5543,13 +5541,13 @@ def same_quantum(self, a, b): The result is never affected by either the sign or the coefficient of either operand. - >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.001')) + >>> ExtendedContext.same_quantum(Decimal("2.17"), Decimal("0.001")) False - >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('0.01')) + >>> ExtendedContext.same_quantum(Decimal("2.17"), Decimal("0.01")) True - >>> ExtendedContext.same_quantum(Decimal('2.17'), Decimal('1')) + >>> ExtendedContext.same_quantum(Decimal("2.17"), Decimal("1")) False - >>> ExtendedContext.same_quantum(Decimal('Inf'), Decimal('-Inf')) + >>> ExtendedContext.same_quantum(Decimal("Inf"), Decimal("-Inf")) True >>> ExtendedContext.same_quantum(10000, -1) True @@ -5564,11 +5562,11 @@ def same_quantum(self, a, b): def scaleb(self, a, b): """Returns the first operand after adding the second value its exp. - >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('-2')) + >>> ExtendedContext.scaleb(Decimal("7.50"), Decimal("-2")) Decimal('0.0750') - >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('0')) + >>> ExtendedContext.scaleb(Decimal("7.50"), Decimal("0")) Decimal('7.50') - >>> ExtendedContext.scaleb(Decimal('7.50'), Decimal('3')) + >>> ExtendedContext.scaleb(Decimal("7.50"), Decimal("3")) Decimal('7.50E+3') >>> ExtendedContext.scaleb(1, 4) Decimal('1E+4') @@ -5590,15 +5588,15 @@ def shift(self, a, b): positive or to the right otherwise. Digits shifted into the coefficient are zeros. - >>> ExtendedContext.shift(Decimal('34'), Decimal('8')) + >>> ExtendedContext.shift(Decimal("34"), Decimal("8")) Decimal('400000000') - >>> ExtendedContext.shift(Decimal('12'), Decimal('9')) + >>> ExtendedContext.shift(Decimal("12"), Decimal("9")) Decimal('0') - >>> ExtendedContext.shift(Decimal('123456789'), Decimal('-2')) + >>> ExtendedContext.shift(Decimal("123456789"), Decimal("-2")) Decimal('1234567') - >>> ExtendedContext.shift(Decimal('123456789'), Decimal('0')) + >>> ExtendedContext.shift(Decimal("123456789"), Decimal("0")) Decimal('123456789') - >>> ExtendedContext.shift(Decimal('123456789'), Decimal('+2')) + >>> ExtendedContext.shift(Decimal("123456789"), Decimal("+2")) Decimal('345678900') >>> ExtendedContext.shift(88888888, 2) Decimal('888888800') @@ -5616,23 +5614,23 @@ def sqrt(self, a): If the result must be inexact, it is rounded using the round-half-even algorithm. - >>> ExtendedContext.sqrt(Decimal('0')) + >>> ExtendedContext.sqrt(Decimal("0")) Decimal('0') - >>> ExtendedContext.sqrt(Decimal('-0')) + >>> ExtendedContext.sqrt(Decimal("-0")) Decimal('-0') - >>> ExtendedContext.sqrt(Decimal('0.39')) + >>> ExtendedContext.sqrt(Decimal("0.39")) Decimal('0.624499800') - >>> ExtendedContext.sqrt(Decimal('100')) + >>> ExtendedContext.sqrt(Decimal("100")) Decimal('10') - >>> ExtendedContext.sqrt(Decimal('1')) + >>> ExtendedContext.sqrt(Decimal("1")) Decimal('1') - >>> ExtendedContext.sqrt(Decimal('1.0')) + >>> ExtendedContext.sqrt(Decimal("1.0")) Decimal('1.0') - >>> ExtendedContext.sqrt(Decimal('1.00')) + >>> ExtendedContext.sqrt(Decimal("1.00")) Decimal('1.0') - >>> ExtendedContext.sqrt(Decimal('7')) + >>> ExtendedContext.sqrt(Decimal("7")) Decimal('2.64575131') - >>> ExtendedContext.sqrt(Decimal('10')) + >>> ExtendedContext.sqrt(Decimal("10")) Decimal('3.16227766') >>> ExtendedContext.sqrt(2) Decimal('1.41421356') @@ -5645,11 +5643,11 @@ def sqrt(self, a): def subtract(self, a, b): """Return the difference between the two operands. - >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.07')) + >>> ExtendedContext.subtract(Decimal("1.3"), Decimal("1.07")) Decimal('0.23') - >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('1.30')) + >>> ExtendedContext.subtract(Decimal("1.3"), Decimal("1.30")) Decimal('0.00') - >>> ExtendedContext.subtract(Decimal('1.3'), Decimal('2.07')) + >>> ExtendedContext.subtract(Decimal("1.3"), Decimal("2.07")) Decimal('-0.77') >>> ExtendedContext.subtract(8, 5) Decimal('3') @@ -5674,19 +5672,19 @@ def to_eng_string(self, a): The operation is not affected by the context. - >>> ExtendedContext.to_eng_string(Decimal('123E+1')) + >>> ExtendedContext.to_eng_string(Decimal("123E+1")) '1.23E+3' - >>> ExtendedContext.to_eng_string(Decimal('123E+3')) + >>> ExtendedContext.to_eng_string(Decimal("123E+3")) '123E+3' - >>> ExtendedContext.to_eng_string(Decimal('123E-10')) + >>> ExtendedContext.to_eng_string(Decimal("123E-10")) '12.3E-9' - >>> ExtendedContext.to_eng_string(Decimal('-123E-12')) + >>> ExtendedContext.to_eng_string(Decimal("-123E-12")) '-123E-12' - >>> ExtendedContext.to_eng_string(Decimal('7E-7')) + >>> ExtendedContext.to_eng_string(Decimal("7E-7")) '700E-9' - >>> ExtendedContext.to_eng_string(Decimal('7E+1')) + >>> ExtendedContext.to_eng_string(Decimal("7E+1")) '70' - >>> ExtendedContext.to_eng_string(Decimal('0E+1')) + >>> ExtendedContext.to_eng_string(Decimal("0E+1")) '0.00E+3' """ @@ -5711,21 +5709,21 @@ def to_integral_exact(self, a): are allowed in this operation. The rounding mode is taken from the context. - >>> ExtendedContext.to_integral_exact(Decimal('2.1')) + >>> ExtendedContext.to_integral_exact(Decimal("2.1")) Decimal('2') - >>> ExtendedContext.to_integral_exact(Decimal('100')) + >>> ExtendedContext.to_integral_exact(Decimal("100")) Decimal('100') - >>> ExtendedContext.to_integral_exact(Decimal('100.0')) + >>> ExtendedContext.to_integral_exact(Decimal("100.0")) Decimal('100') - >>> ExtendedContext.to_integral_exact(Decimal('101.5')) + >>> ExtendedContext.to_integral_exact(Decimal("101.5")) Decimal('102') - >>> ExtendedContext.to_integral_exact(Decimal('-101.5')) + >>> ExtendedContext.to_integral_exact(Decimal("-101.5")) Decimal('-102') - >>> ExtendedContext.to_integral_exact(Decimal('10E+5')) + >>> ExtendedContext.to_integral_exact(Decimal("10E+5")) Decimal('1.0E+6') - >>> ExtendedContext.to_integral_exact(Decimal('7.89E+77')) + >>> ExtendedContext.to_integral_exact(Decimal("7.89E+77")) Decimal('7.89E+77') - >>> ExtendedContext.to_integral_exact(Decimal('-Inf')) + >>> ExtendedContext.to_integral_exact(Decimal("-Inf")) Decimal('-Infinity') """ a = _convert_other(a, raiseit=True) @@ -5740,21 +5738,21 @@ def to_integral_value(self, a): of the operand as the precision setting, except that no flags will be set. The rounding mode is taken from the context. - >>> ExtendedContext.to_integral_value(Decimal('2.1')) + >>> ExtendedContext.to_integral_value(Decimal("2.1")) Decimal('2') - >>> ExtendedContext.to_integral_value(Decimal('100')) + >>> ExtendedContext.to_integral_value(Decimal("100")) Decimal('100') - >>> ExtendedContext.to_integral_value(Decimal('100.0')) + >>> ExtendedContext.to_integral_value(Decimal("100.0")) Decimal('100') - >>> ExtendedContext.to_integral_value(Decimal('101.5')) + >>> ExtendedContext.to_integral_value(Decimal("101.5")) Decimal('102') - >>> ExtendedContext.to_integral_value(Decimal('-101.5')) + >>> ExtendedContext.to_integral_value(Decimal("-101.5")) Decimal('-102') - >>> ExtendedContext.to_integral_value(Decimal('10E+5')) + >>> ExtendedContext.to_integral_value(Decimal("10E+5")) Decimal('1.0E+6') - >>> ExtendedContext.to_integral_value(Decimal('7.89E+77')) + >>> ExtendedContext.to_integral_value(Decimal("7.89E+77")) Decimal('7.89E+77') - >>> ExtendedContext.to_integral_value(Decimal('-Inf')) + >>> ExtendedContext.to_integral_value(Decimal("-Inf")) Decimal('-Infinity') """ a = _convert_other(a, raiseit=True) diff --git a/Lib/antigravity.py b/Lib/antigravity.py index 91b1a9134697ab..2221c221425337 100644 --- a/Lib/antigravity.py +++ b/Lib/antigravity.py @@ -7,7 +7,7 @@ def geohash(latitude, longitude, datedow): """Compute geohash() using the Munroe algorithm. - >>> geohash(37.421542, -122.085589, b'2005-05-26-10458.68') + >>> geohash(37.421542, -122.085589, b"2005-05-26-10458.68") 37.857713 -122.544543 """ diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index e720cbffda0642..c2f4c5ce31e6b8 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -359,23 +359,23 @@ def __ror__(self, other): def namedtuple(typename, field_names, *, rename=False, defaults=None, module=None): """Returns a new subclass of tuple with named fields. - >>> Point = namedtuple('Point', ['x', 'y']) - >>> Point.__doc__ # docstring for the new class + >>> Point = namedtuple("Point", ["x", "y"]) + >>> Point.__doc__ # docstring for the new class 'Point(x, y)' - >>> p = Point(11, y=22) # instantiate with positional args or keywords - >>> p[0] + p[1] # indexable like a plain tuple + >>> p = Point(11, y=22) # instantiate with positional args or keywords + >>> p[0] + p[1] # indexable like a plain tuple 33 - >>> x, y = p # unpack like a regular tuple + >>> x, y = p # unpack like a regular tuple >>> x, y (11, 22) - >>> p.x + p.y # fields also accessible by name + >>> p.x + p.y # fields also accessible by name 33 - >>> d = p._asdict() # convert to a dictionary - >>> d['x'] + >>> d = p._asdict() # convert to a dictionary + >>> d["x"] 11 - >>> Point(**d) # convert from a dictionary + >>> Point(**d) # convert from a dictionary Point(x=11, y=22) - >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields + >>> p._replace(x=100) # _replace() is like str.replace() but targets named fields Point(x=100, y=22) """ @@ -562,42 +562,42 @@ class Counter(dict): or multiset. Elements are stored as dictionary keys and their counts are stored as dictionary values. - >>> c = Counter('abcdeabcdabcaba') # count elements from a string + >>> c = Counter("abcdeabcdabcaba") # count elements from a string - >>> c.most_common(3) # three most common elements + >>> c.most_common(3) # three most common elements [('a', 5), ('b', 4), ('c', 3)] - >>> sorted(c) # list all unique elements + >>> sorted(c) # list all unique elements ['a', 'b', 'c', 'd', 'e'] - >>> ''.join(sorted(c.elements())) # list elements with repetitions + >>> "".join(sorted(c.elements())) # list elements with repetitions 'aaaaabbbbcccdde' - >>> sum(c.values()) # total of all counts + >>> sum(c.values()) # total of all counts 15 - >>> c['a'] # count of letter 'a' + >>> c["a"] # count of letter 'a' 5 - >>> for elem in 'shazam': # update counts from an iterable - ... c[elem] += 1 # by adding 1 to each element's count - >>> c['a'] # now there are seven 'a' + >>> for elem in "shazam": # update counts from an iterable + ... c[elem] += 1 # by adding 1 to each element's count + >>> c["a"] # now there are seven 'a' 7 - >>> del c['b'] # remove all 'b' - >>> c['b'] # now there are zero 'b' + >>> del c["b"] # remove all 'b' + >>> c["b"] # now there are zero 'b' 0 - >>> d = Counter('simsalabim') # make another counter - >>> c.update(d) # add in the second counter - >>> c['a'] # now there are nine 'a' + >>> d = Counter("simsalabim") # make another counter + >>> c.update(d) # add in the second counter + >>> c["a"] # now there are nine 'a' 9 - >>> c.clear() # empty the counter + >>> c.clear() # empty the counter >>> c Counter() Note: If a count is set to zero or reduced to zero, it will remain in the counter until the entry is deleted or the counter is cleared: - >>> c = Counter('aaabbc') - >>> c['b'] -= 2 # reduce the count of 'b' by two - >>> c.most_common() # 'b' is still in, but its count is zero + >>> c = Counter("aaabbc") + >>> c["b"] -= 2 # reduce the count of 'b' by two + >>> c.most_common() # 'b' is still in, but its count is zero [('a', 3), ('c', 1), ('b', 0)] """ @@ -614,10 +614,10 @@ def __init__(self, iterable=None, /, **kwds): from an input iterable. Or, initialize the count from another mapping of elements to their counts. - >>> c = Counter() # a new, empty counter - >>> c = Counter('gallahad') # a new counter from an iterable - >>> c = Counter({'a': 4, 'b': 2}) # a new counter from a mapping - >>> c = Counter(a=4, b=2) # a new counter from keyword args + >>> c = Counter() # a new, empty counter + >>> c = Counter("gallahad") # a new counter from an iterable + >>> c = Counter({"a": 4, "b": 2}) # a new counter from a mapping + >>> c = Counter(a=4, b=2) # a new counter from keyword args """ super().__init__() @@ -636,7 +636,7 @@ def most_common(self, n=None): """List the n most common elements and their counts from the most common to the least. If n is None, then list all element counts. - >>> Counter('abracadabra').most_common(3) + >>> Counter("abracadabra").most_common(3) [('a', 5), ('b', 2), ('r', 2)] """ @@ -652,7 +652,7 @@ def most_common(self, n=None): def elements(self): """Iterator over elements repeating each as many times as its count. - >>> c = Counter('ABCABC') + >>> c = Counter("ABCABC") >>> sorted(c.elements()) ['A', 'A', 'B', 'B', 'C', 'C'] @@ -689,11 +689,11 @@ def update(self, iterable=None, /, **kwds): Source can be an iterable, a dictionary, or another Counter instance. - >>> c = Counter('which') - >>> c.update('witch') # add elements from another iterable - >>> d = Counter('watch') - >>> c.update(d) # add elements from another counter - >>> c['h'] # four 'h' in which, witch, and watch + >>> c = Counter("which") + >>> c.update("witch") # add elements from another iterable + >>> d = Counter("watch") + >>> c.update(d) # add elements from another counter + >>> c["h"] # four 'h' in which, witch, and watch 4 """ @@ -725,12 +725,12 @@ def subtract(self, iterable=None, /, **kwds): Source can be an iterable, a dictionary, or another Counter instance. - >>> c = Counter('which') - >>> c.subtract('witch') # subtract elements from another iterable - >>> c.subtract(Counter('watch')) # subtract elements from another counter - >>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch + >>> c = Counter("which") + >>> c.subtract("witch") # subtract elements from another iterable + >>> c.subtract(Counter("watch")) # subtract elements from another counter + >>> c["h"] # 2 in which, minus 1 in witch, minus 1 in watch 0 - >>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch + >>> c["w"] # 1 in which, minus 1 in witch, minus 1 in watch -1 """ @@ -841,7 +841,7 @@ def __gt__(self, other): def __add__(self, other): """Add counts from two counters. - >>> Counter('abbb') + Counter('bcc') + >>> Counter("abbb") + Counter("bcc") Counter({'b': 4, 'c': 2, 'a': 1}) """ @@ -860,7 +860,7 @@ def __add__(self, other): def __sub__(self, other): """Subtract count, but keep only results with positive counts. - >>> Counter('abbbc') - Counter('bccd') + >>> Counter("abbbc") - Counter("bccd") Counter({'b': 2, 'a': 1}) """ @@ -879,7 +879,7 @@ def __sub__(self, other): def __or__(self, other): """Union is the maximum of value in either of the input counters. - >>> Counter('abbb') | Counter('bcc') + >>> Counter("abbb") | Counter("bcc") Counter({'b': 3, 'c': 2, 'a': 1}) """ @@ -899,7 +899,7 @@ def __or__(self, other): def __and__(self, other): """Intersection is the minimum of corresponding counts. - >>> Counter('abbb') & Counter('bcc') + >>> Counter("abbb") & Counter("bcc") Counter({'b': 1}) """ @@ -942,8 +942,8 @@ def _keep_positive(self): def __iadd__(self, other): """Inplace add from another counter, keeping only positive counts. - >>> c = Counter('abbb') - >>> c += Counter('bcc') + >>> c = Counter("abbb") + >>> c += Counter("bcc") >>> c Counter({'b': 4, 'c': 2, 'a': 1}) @@ -955,8 +955,8 @@ def __iadd__(self, other): def __isub__(self, other): """Inplace subtract counter, but keep only results with positive counts. - >>> c = Counter('abbbc') - >>> c -= Counter('bccd') + >>> c = Counter("abbbc") + >>> c -= Counter("bccd") >>> c Counter({'b': 2, 'a': 1}) @@ -968,8 +968,8 @@ def __isub__(self, other): def __ior__(self, other): """Inplace union is the maximum of value from either counter. - >>> c = Counter('abbb') - >>> c |= Counter('bcc') + >>> c = Counter("abbb") + >>> c |= Counter("bcc") >>> c Counter({'b': 3, 'c': 2, 'a': 1}) @@ -983,8 +983,8 @@ def __ior__(self, other): def __iand__(self, other): """Inplace intersection is the minimum of corresponding counts. - >>> c = Counter('abbb') - >>> c &= Counter('bcc') + >>> c = Counter("abbb") + >>> c &= Counter("bcc") >>> c Counter({'b': 1}) diff --git a/Lib/difflib.py b/Lib/difflib.py index f548e412598bc3..9c81998e6cf6e7 100644 --- a/Lib/difflib.py +++ b/Lib/difflib.py @@ -82,9 +82,11 @@ class SequenceMatcher: Example, comparing two strings, and considering blanks to be "junk": - >>> s = SequenceMatcher(lambda x: x == " ", - ... "private Thread currentThread;", - ... "private volatile Thread currentThread;") + >>> s = SequenceMatcher( + ... lambda x: x == " ", + ... "private Thread currentThread;", + ... "private volatile Thread currentThread;", + ... ) >>> .ratio() returns a float in [0, 1], measuring the "similarity" of the @@ -350,7 +352,7 @@ def find_longest_match(self, alo=0, ahi=None, blo=0, bhi=None): end of the second sequence directly. Instead only the "abcd" can match, and matches the leftmost "abcd" in the second sequence: - >>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd") + >>> s = SequenceMatcher(lambda x: x == " ", " abcd", "abcd abcd") >>> s.find_longest_match(0, 5, 0, 9) Match(a=1, b=0, size=4) @@ -534,8 +536,9 @@ def get_opcodes(self): >>> b = "abycdf" >>> s = SequenceMatcher(None, a, b) >>> for tag, i1, i2, j1, j2 in s.get_opcodes(): - ... print(("%7s a[%d:%d] (%s) b[%d:%d] (%s)" % - ... (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2]))) + ... print( + ... ("%7s a[%d:%d] (%s) b[%d:%d] (%s)" % (tag, i1, i2, a[i1:i2], j1, j2, b[j1:j2])) + ... ) delete a[0:1] (q) b[0:0] () equal a[1:3] (ab) b[0:2] (ab) replace a[3:4] (x) b[2:3] (y) @@ -576,13 +579,13 @@ def get_grouped_opcodes(self, n=3): Each group is in the same format as returned by get_opcodes(). >>> from pprint import pprint - >>> a = list(map(str, range(1,40))) + >>> a = list(map(str, range(1, 40))) >>> b = a[:] - >>> b[8:8] = ['i'] # Make an insertion - >>> b[20] += 'x' # Make a replacement - >>> b[23:28] = [] # Make a deletion - >>> b[30] += 'y' # Make another replacement - >>> pprint(list(SequenceMatcher(None,a,b).get_grouped_opcodes())) + >>> b[8:8] = ["i"] # Make an insertion + >>> b[20] += "x" # Make a replacement + >>> b[23:28] = [] # Make a deletion + >>> b[30] += "y" # Make another replacement + >>> pprint(list(SequenceMatcher(None, a, b).get_grouped_opcodes())) [[('equal', 5, 8, 5, 8), ('insert', 8, 8, 8, 9), ('equal', 8, 11, 9, 12)], [('equal', 16, 19, 17, 20), ('replace', 19, 20, 20, 21), @@ -819,7 +822,7 @@ class Differ: As a single multi-line string it looks like this: - >>> print(''.join(result), end="") + >>> print("".join(result), end="") 1. Beautiful is better than ugly. - 2. Explicit is better than implicit. - 3. Simple is better than complex. @@ -867,9 +870,14 @@ def compare(self, a, b): Example: - >>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True), - ... 'ore\ntree\nemu\n'.splitlines(True))), - ... end="") + >>> print( + ... "".join( + ... Differ().compare( + ... "one\ntwo\nthree\n".splitlines(True), "ore\ntree\nemu\n".splitlines(True) + ... ) + ... ), + ... end="", + ... ) - one ? ^ + ore @@ -925,9 +933,8 @@ def _fancy_replace(self, a, alo, ahi, b, blo, bhi): Example: >>> d = Differ() - >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1, - ... ['abcdefGhijkl\n'], 0, 1) - >>> print(''.join(results), end="") + >>> results = d._fancy_replace(["abcDefghiJkl\n"], 0, 1, ["abcdefGhijkl\n"], 0, 1) + >>> print("".join(results), end="") - abcDefghiJkl ? ^ ^ ^ + abcdefGhijkl @@ -1030,10 +1037,11 @@ def _qformat(self, aline, bline, atags, btags): Example: >>> d = Differ() - >>> results = d._qformat('\tabcDefghiJkl\n', '\tabcdefGhijkl\n', - ... ' ^ ^ ^ ', ' ^ ^ ^ ') - >>> for line in results: print(repr(line)) - ... + >>> results = d._qformat( + ... "\tabcDefghiJkl\n", "\tabcdefGhijkl\n", " ^ ^ ^ ", " ^ ^ ^ " + ... ) + >>> for line in results: + ... print(repr(line)) '- \tabcDefghiJkl\n' '? \t ^ ^ ^\n' '+ \tabcdefGhijkl\n' @@ -1077,11 +1085,11 @@ def IS_LINE_JUNK(line, pat=re.compile(r"\s*(?:#\s*)?$").match): Examples: - >>> IS_LINE_JUNK('\n') + >>> IS_LINE_JUNK("\n") True - >>> IS_LINE_JUNK(' # \n') + >>> IS_LINE_JUNK(" # \n") True - >>> IS_LINE_JUNK('hello\n') + >>> IS_LINE_JUNK("hello\n") False """ @@ -1094,13 +1102,13 @@ def IS_CHARACTER_JUNK(ch, ws=" \t"): Examples: - >>> IS_CHARACTER_JUNK(' ') + >>> IS_CHARACTER_JUNK(" ") True - >>> IS_CHARACTER_JUNK('\t') + >>> IS_CHARACTER_JUNK("\t") True - >>> IS_CHARACTER_JUNK('\n') + >>> IS_CHARACTER_JUNK("\n") False - >>> IS_CHARACTER_JUNK('x') + >>> IS_CHARACTER_JUNK("x") False """ @@ -1150,11 +1158,16 @@ def unified_diff( Example: - >>> for line in unified_diff('one two three four'.split(), - ... 'zero one tree four'.split(), 'Original', 'Current', - ... '2005-01-26 23:30:50', '2010-04-02 10:20:52', - ... lineterm=''): - ... print(line) # doctest: +NORMALIZE_WHITESPACE + >>> for line in unified_diff( + ... "one two three four".split(), + ... "zero one tree four".split(), + ... "Original", + ... "Current", + ... "2005-01-26 23:30:50", + ... "2010-04-02 10:20:52", + ... lineterm="", + ... ): + ... print(line) # doctest: +NORMALIZE_WHITESPACE --- Original 2005-01-26 23:30:50 +++ Current 2010-04-02 10:20:52 @@ -1,4 +1,4 @@ @@ -1239,9 +1252,17 @@ def context_diff( Example: - >>> print(''.join(context_diff('one\ntwo\nthree\nfour\n'.splitlines(True), - ... 'zero\none\ntree\nfour\n'.splitlines(True), 'Original', 'Current')), - ... end="") + >>> print( + ... "".join( + ... context_diff( + ... "one\ntwo\nthree\nfour\n".splitlines(True), + ... "zero\none\ntree\nfour\n".splitlines(True), + ... "Original", + ... "Current", + ... ) + ... ), + ... end="", + ... ) *** Original --- Current *************** @@ -1373,9 +1394,11 @@ def ndiff(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK): Example: - >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True), - ... 'ore\ntree\nemu\n'.splitlines(keepends=True)) - >>> print(''.join(diff), end="") + >>> diff = ndiff( + ... "one\ntwo\nthree\n".splitlines(keepends=True), + ... "ore\ntree\nemu\n".splitlines(keepends=True), + ... ) + >>> print("".join(diff), end="") - one ? ^ + ore @@ -2125,14 +2148,16 @@ def restore(delta, which): Examples: - >>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True), - ... 'ore\ntree\nemu\n'.splitlines(keepends=True)) + >>> diff = ndiff( + ... "one\ntwo\nthree\n".splitlines(keepends=True), + ... "ore\ntree\nemu\n".splitlines(keepends=True), + ... ) >>> diff = list(diff) - >>> print(''.join(restore(diff, 1)), end="") + >>> print("".join(restore(diff, 1)), end="") one two three - >>> print(''.join(restore(diff, 2)), end="") + >>> print("".join(restore(diff, 2)), end="") ore tree emu diff --git a/Lib/doctest.py b/Lib/doctest.py index fe51966111eb6d..f1331698c77d52 100644 --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -306,7 +306,7 @@ def truncate(self, size=None): def _ellipsis_match(want, got): """ Essentially the only subtle case: - >>> _ellipsis_match('aa...aa', 'aaa') + >>> _ellipsis_match("aa...aa", "aaa") False """ if ELLIPSIS_MARKER not in want: @@ -1234,9 +1234,9 @@ class DocTestRunner: >>> tests = DocTestFinder().find(_TestClass) >>> runner = DocTestRunner(verbose=False) - >>> tests.sort(key = lambda test: test.name) + >>> tests.sort(key=lambda test: test.name) >>> for test in tests: - ... print(test.name, '->', runner.run(test)) + ... print(test.name, "->", runner.run(test)) _TestClass -> TestResults(failed=0, attempted=2) _TestClass.__init__ -> TestResults(failed=0, attempted=2) _TestClass.get -> TestResults(failed=0, attempted=2) @@ -1892,8 +1892,7 @@ class DebugRunner(DocTestRunner): It contains the test, the example, and the original exception: >>> runner = DebugRunner(verbose=False) - >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', - ... {}, 'foo', 'foo.py', 0) + >>> test = DocTestParser().get_doctest(">>> raise KeyError\n42", {}, "foo", "foo.py", 0) >>> try: ... runner.run(test) ... except UnexpectedException as f: @@ -1906,7 +1905,7 @@ class DebugRunner(DocTestRunner): '42\n' >>> exc_info = failure.exc_info - >>> raise exc_info[1] # Already has the traceback + >>> raise exc_info[1] # Already has the traceback Traceback (most recent call last): ... KeyError @@ -1916,16 +1915,22 @@ class DebugRunner(DocTestRunner): If the output doesn't match, then a DocTestFailure is raised: - >>> test = DocTestParser().get_doctest(''' + >>> test = DocTestParser().get_doctest( + ... ''' ... >>> x = 1 ... >>> x ... 2 - ... ''', {}, 'foo', 'foo.py', 0) + ... ''', + ... {}, + ... "foo", + ... "foo.py", + ... 0, + ... ) >>> try: - ... runner.run(test) + ... runner.run(test) ... except DocTestFailure as f: - ... failure = f + ... failure = f DocTestFailure objects provide access to the test: @@ -1944,29 +1949,41 @@ class DebugRunner(DocTestRunner): If a failure or error occurs, the globals are left intact: - >>> del test.globs['__builtins__'] + >>> del test.globs["__builtins__"] >>> test.globs {'x': 1} - >>> test = DocTestParser().get_doctest(''' + >>> test = DocTestParser().get_doctest( + ... ''' ... >>> x = 2 ... >>> raise KeyError - ... ''', {}, 'foo', 'foo.py', 0) + ... ''', + ... {}, + ... "foo", + ... "foo.py", + ... 0, + ... ) >>> runner.run(test) Traceback (most recent call last): ... doctest.UnexpectedException: - >>> del test.globs['__builtins__'] + >>> del test.globs["__builtins__"] >>> test.globs {'x': 2} But the globals are cleared if there is no error: - >>> test = DocTestParser().get_doctest(''' + >>> test = DocTestParser().get_doctest( + ... ''' ... >>> x = 2 - ... ''', {}, 'foo', 'foo.py', 0) + ... ''', + ... {}, + ... "foo", + ... "foo.py", + ... 0, + ... ) >>> runner.run(test) TestResults(failed=0, attempted=1) @@ -2286,12 +2303,10 @@ def set_unittest_reportflags(flags): >>> import doctest >>> old = doctest._unittest_reportflags - >>> doctest.set_unittest_reportflags(REPORT_NDIFF | - ... REPORT_ONLY_FIRST_FAILURE) == old + >>> doctest.set_unittest_reportflags(REPORT_NDIFF | REPORT_ONLY_FIRST_FAILURE) == old True - >>> doctest._unittest_reportflags == (REPORT_NDIFF | - ... REPORT_ONLY_FIRST_FAILURE) + >>> doctest._unittest_reportflags == (REPORT_NDIFF | REPORT_ONLY_FIRST_FAILURE) True Only reporting flags can be set: @@ -2301,8 +2316,7 @@ def set_unittest_reportflags(flags): ... ValueError: ('Only reporting flags allowed', 8) - >>> doctest.set_unittest_reportflags(old) == (REPORT_NDIFF | - ... REPORT_ONLY_FIRST_FAILURE) + >>> doctest.set_unittest_reportflags(old) == (REPORT_NDIFF | REPORT_ONLY_FIRST_FAILURE) True """ global _unittest_reportflags @@ -2391,8 +2405,7 @@ def debug(self): UnexpectedException errors if there is an unexpected exception: - >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42', - ... {}, 'foo', 'foo.py', 0) + >>> test = DocTestParser().get_doctest(">>> raise KeyError\n42", {}, "foo", "foo.py", 0) >>> case = DocTestCase(test) >>> try: ... case.debug() @@ -2409,24 +2422,30 @@ def debug(self): '42\n' >>> exc_info = failure.exc_info - >>> raise exc_info[1] # Already has the traceback + >>> raise exc_info[1] # Already has the traceback Traceback (most recent call last): ... KeyError If the output doesn't match, then a DocTestFailure is raised: - >>> test = DocTestParser().get_doctest(''' + >>> test = DocTestParser().get_doctest( + ... ''' ... >>> x = 1 ... >>> x ... 2 - ... ''', {}, 'foo', 'foo.py', 0) + ... ''', + ... {}, + ... "foo", + ... "foo.py", + ... 0, + ... ) >>> case = DocTestCase(test) >>> try: - ... case.debug() + ... case.debug() ... except DocTestFailure as f: - ... failure = f + ... failure = f DocTestFailure objects provide access to the test: diff --git a/Lib/enum.py b/Lib/enum.py index ef96f1e310a3e4..aadceaeed04727 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -170,7 +170,7 @@ def bin(num, max_bits=None): >>> bin(10) '0b0 1010' - >>> bin(~10) # ~10 is -11 + >>> bin(~10) # ~10 is -11 '0b1 0101' """ @@ -1166,7 +1166,7 @@ class Enum(metaclass=EnumType): - name lookup: - >>> Color['RED'] + >>> Color["RED"] Enumerations can be iterated over, and know how many members they have: diff --git a/Lib/fractions.py b/Lib/fractions.py index f92f26b0fed35d..17ea799c33e7b8 100644 --- a/Lib/fractions.py +++ b/Lib/fractions.py @@ -206,19 +206,19 @@ def __new__(cls, numerator=0, denominator=None): Fraction(1, 35) >>> Fraction(Fraction(1, 7), Fraction(2, 3)) Fraction(3, 14) - >>> Fraction('314') + >>> Fraction("314") Fraction(314, 1) - >>> Fraction('-35/4') + >>> Fraction("-35/4") Fraction(-35, 4) - >>> Fraction('3.1415') # conversion from numeric string + >>> Fraction("3.1415") # conversion from numeric string Fraction(6283, 2000) - >>> Fraction('-47e-2') # string may include a decimal exponent + >>> Fraction("-47e-2") # string may include a decimal exponent Fraction(-47, 100) >>> Fraction(1.47) # direct construction from float (exact conversion) Fraction(6620291452234629, 4503599627370496) >>> Fraction(2.25) Fraction(9, 4) - >>> Fraction(Decimal('1.47')) + >>> Fraction(Decimal("1.47")) Fraction(147, 100) """ @@ -350,9 +350,9 @@ def as_integer_ratio(self): def limit_denominator(self, max_denominator=1000000): """Closest Fraction to self with denominator at most max_denominator. - >>> Fraction('3.141592653589793').limit_denominator(10) + >>> Fraction("3.141592653589793").limit_denominator(10) Fraction(22, 7) - >>> Fraction('3.141592653589793').limit_denominator(100) + >>> Fraction("3.141592653589793").limit_denominator(100) Fraction(311, 99) >>> Fraction(4321, 8765).limit_denominator(10000) Fraction(4321, 8765) diff --git a/Lib/ftplib.py b/Lib/ftplib.py index d1dbdf52e73037..abcd4f4f640387 100644 --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -720,12 +720,12 @@ class FTP_TLS(FTP): Usage example: >>> from ftplib import FTP_TLS - >>> ftps = FTP_TLS('ftp.python.org') + >>> ftps = FTP_TLS("ftp.python.org") >>> ftps.login() # login anonymously previously securing control channel '230 Guest login ok, access restrictions apply.' >>> ftps.prot_p() # switch to secure data connection '200 Protection level set to P' - >>> ftps.retrlines('LIST') # list directory content securely + >>> ftps.retrlines("LIST") # list directory content securely total 9 drwxr-xr-x 8 root wheel 1024 Jan 3 1994 . drwxr-xr-x 8 root wheel 1024 Jan 3 1994 .. diff --git a/Lib/heapq.py b/Lib/heapq.py index 074b7ffd6582d1..d5d074dc6cbac5 100644 --- a/Lib/heapq.py +++ b/Lib/heapq.py @@ -342,13 +342,13 @@ def merge(*iterables, key=None, reverse=False): does not pull the data into memory all at once, and assumes that each of the input streams is already sorted (smallest to largest). - >>> list(merge([1,3,5,7], [0,2,4,8], [5,10,15,20], [], [25])) + >>> list(merge([1, 3, 5, 7], [0, 2, 4, 8], [5, 10, 15, 20], [], [25])) [0, 1, 2, 3, 4, 5, 5, 7, 8, 10, 15, 20, 25] If *key* is not None, applies a key function to each element to determine its sort order. - >>> list(merge(['dog', 'horse'], ['cat', 'fish', 'kangaroo'], key=len)) + >>> list(merge(["dog", "horse"], ["cat", "fish", "kangaroo"], key=len)) ['dog', 'cat', 'fish', 'horse', 'kangaroo'] """ diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 3439c2e806f2dc..93a210422bca2f 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -123,7 +123,7 @@ class ParseMap(dict): Anything not specifically mapped otherwise becomes 'x'. Example: replace everything except whitespace with 'x'. - >>> keepwhite = ParseMap((ord(c), ord(c)) for c in ' \t\n\r') + >>> keepwhite = ParseMap((ord(c), ord(c)) for c in " \t\n\r") >>> "a + b\tc\nd".translate(keepwhite) 'x x x\tx\nx' """ diff --git a/Lib/importlib/metadata/__init__.py b/Lib/importlib/metadata/__init__.py index cbbd019d4675b4..237248a1b427f3 100644 --- a/Lib/importlib/metadata/__init__.py +++ b/Lib/importlib/metadata/__init__.py @@ -125,8 +125,8 @@ class DeprecatedTuple: """ Provide subscript item access for backward compatibility. - >>> recwarn = getfixture('recwarn') - >>> ep = EntryPoint(name='name', value='value', group='group') + >>> recwarn = getfixture("recwarn") + >>> ep = EntryPoint(name="name", value="value", group="group") >>> ep[:] ('name', 'value', 'group') >>> ep[0] @@ -155,8 +155,7 @@ class EntryPoint(DeprecatedTuple): `_ for more information. - >>> ep = EntryPoint( - ... name=None, group=None, value='package.module:attr [extra1, extra2]') + >>> ep = EntryPoint(name=None, group=None, value="package.module:attr [extra1, extra2]") >>> ep.module 'package.module' >>> ep.attr @@ -228,20 +227,20 @@ def matches(self, **params): """ EntryPoint matches the given parameters. - >>> ep = EntryPoint(group='foo', name='bar', value='bing:bong [extra1, extra2]') - >>> ep.matches(group='foo') + >>> ep = EntryPoint(group="foo", name="bar", value="bing:bong [extra1, extra2]") + >>> ep.matches(group="foo") True - >>> ep.matches(name='bar', value='bing:bong [extra1, extra2]') + >>> ep.matches(name="bar", value="bing:bong [extra1, extra2]") True - >>> ep.matches(group='foo', name='other') + >>> ep.matches(group="foo", name="other") False >>> ep.matches() True - >>> ep.matches(extras=['extra1', 'extra2']) + >>> ep.matches(extras=["extra1", "extra2"]) True - >>> ep.matches(module='bing') + >>> ep.matches(module="bing") True - >>> ep.matches(attr='bong') + >>> ep.matches(attr="bong") True """ attrs = (getattr(self, param) for param in params) @@ -660,7 +659,7 @@ class FastPath: Micro-optimized class for searching a path for children. - >>> FastPath('').children() + >>> FastPath("").children() ['...'] """ @@ -836,13 +835,13 @@ def _normalized_name(self): @staticmethod def _name_from_stem(stem): """ - >>> PathDistribution._name_from_stem('foo-3.0.egg-info') + >>> PathDistribution._name_from_stem("foo-3.0.egg-info") 'foo' - >>> PathDistribution._name_from_stem('CherryPy-3.0.dist-info') + >>> PathDistribution._name_from_stem("CherryPy-3.0.dist-info") 'CherryPy' - >>> PathDistribution._name_from_stem('face.egg-info') + >>> PathDistribution._name_from_stem("face.egg-info") 'face' - >>> PathDistribution._name_from_stem('foo.bar') + >>> PathDistribution._name_from_stem("foo.bar") """ filename, ext = os.path.splitext(stem) if ext not in (".dist-info", ".egg-info"): diff --git a/Lib/importlib/metadata/_collections.py b/Lib/importlib/metadata/_collections.py index 895678a23c308d..a6a8e83beb6afa 100644 --- a/Lib/importlib/metadata/_collections.py +++ b/Lib/importlib/metadata/_collections.py @@ -9,7 +9,7 @@ class FreezableDefaultDict(collections.defaultdict): as to prevent mutation during iteration. >>> dd = FreezableDefaultDict(list) - >>> dd[0].append('1') + >>> dd[0].append("1") >>> dd.freeze() >>> dd[1] [] diff --git a/Lib/importlib/metadata/_functools.py b/Lib/importlib/metadata/_functools.py index 71f66bd03cb713..96a3a63195e6ab 100644 --- a/Lib/importlib/metadata/_functools.py +++ b/Lib/importlib/metadata/_functools.py @@ -91,7 +91,7 @@ def pass_none(func): Wrap func so it's not called if its first param is None >>> print_text = pass_none(print) - >>> print_text('text') + >>> print_text("text") text >>> print_text(None) """ diff --git a/Lib/importlib/metadata/_itertools.py b/Lib/importlib/metadata/_itertools.py index d4ca9b9140e3f0..4c5a2acc159fbd 100644 --- a/Lib/importlib/metadata/_itertools.py +++ b/Lib/importlib/metadata/_itertools.py @@ -41,14 +41,14 @@ def always_iterable(obj, base_type=(str, bytes)): By default, binary and text strings are not considered iterable:: - >>> obj = 'foo' + >>> obj = "foo" >>> list(always_iterable(obj)) ['foo'] If *base_type* is set, objects for which ``isinstance(obj, base_type)`` returns ``True`` won't be considered iterable. - >>> obj = {'a': 1} + >>> obj = {"a": 1} >>> list(always_iterable(obj)) # Iterate over the dict's keys ['a'] >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit @@ -57,7 +57,7 @@ def always_iterable(obj, base_type=(str, bytes)): Set *base_type* to ``None`` to avoid any special handling and treat objects Python considers iterable as iterable: - >>> obj = 'foo' + >>> obj = "foo" >>> list(always_iterable(obj, base_type=None)) ['f', 'o', 'o'] """ diff --git a/Lib/importlib/metadata/_text.py b/Lib/importlib/metadata/_text.py index 376210d7096978..5a0b39dac16a19 100644 --- a/Lib/importlib/metadata/_text.py +++ b/Lib/importlib/metadata/_text.py @@ -9,24 +9,24 @@ class FoldedCase(str): A case insensitive string class; behaves just like str except compares equal when the only variation is case. - >>> s = FoldedCase('hello world') + >>> s = FoldedCase("hello world") - >>> s == 'Hello World' + >>> s == "Hello World" True - >>> 'Hello World' == s + >>> "Hello World" == s True - >>> s != 'Hello World' + >>> s != "Hello World" False - >>> s.index('O') + >>> s.index("O") 4 - >>> s.split('O') + >>> s.split("O") ['hell', ' w', 'rld'] - >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) + >>> sorted(map(FoldedCase, ["GAMMA", "alpha", "Beta"])) ['alpha', 'Beta', 'GAMMA'] Sequence membership is straightforward. @@ -52,15 +52,15 @@ class FoldedCase(str): But not if the FoldedCase object is on the left: - >>> FoldedCase('hello') in 'Hello World' + >>> FoldedCase("hello") in "Hello World" False In that case, use in_: - >>> FoldedCase('hello').in_('Hello World') + >>> FoldedCase("hello").in_("Hello World") True - >>> FoldedCase('hello') > FoldedCase('Hello') + >>> FoldedCase("hello") > FoldedCase("Hello") False """ diff --git a/Lib/importlib/resources/_common.py b/Lib/importlib/resources/_common.py index dd7a674077501f..252e02722ea367 100644 --- a/Lib/importlib/resources/_common.py +++ b/Lib/importlib/resources/_common.py @@ -24,7 +24,7 @@ def package_to_anchor(func): Other errors should fall through. - >>> files('a', 'b') + >>> files("a", "b") Traceback (most recent call last): TypeError: files() takes from 0 to 1 positional arguments but 2 were given """ diff --git a/Lib/importlib/resources/_itertools.py b/Lib/importlib/resources/_itertools.py index ba10c6b9449a2e..0cc997d5ce38f1 100644 --- a/Lib/importlib/resources/_itertools.py +++ b/Lib/importlib/resources/_itertools.py @@ -4,7 +4,7 @@ def only(iterable, default=None, too_long=None): If it has zero items, return *default*. If it has more than one item, raise the exception given by *too_long*, which is ``ValueError`` by default. - >>> only([], default='missing') + >>> only([], default="missing") 'missing' >>> only([1]) 1 diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index ab80b2c3181fb2..8a5aa23406e6ee 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -201,9 +201,8 @@ def summarize_address_range(first, last): """Summarize a network range given the first and last IP addresses. Example: - >>> list(summarize_address_range(IPv4Address('192.0.2.0'), - ... IPv4Address('192.0.2.130'))) - ... #doctest: +NORMALIZE_WHITESPACE + >>> list(summarize_address_range(IPv4Address("192.0.2.0"), IPv4Address("192.0.2.130"))) + ... # doctest: +NORMALIZE_WHITESPACE [IPv4Network('192.0.2.0/25'), IPv4Network('192.0.2.128/31'), IPv4Network('192.0.2.130/32')] diff --git a/Lib/pickle.py b/Lib/pickle.py index 9c38b5c8ff3853..e6f427928f1f29 100644 --- a/Lib/pickle.py +++ b/Lib/pickle.py @@ -401,7 +401,7 @@ def encode_long(x): def decode_long(data): r"""Decode a long from a two's complement little-endian binary string. - >>> decode_long(b'') + >>> decode_long(b"") 0 >>> decode_long(b"\xff\x00") 255 diff --git a/Lib/pickletools.py b/Lib/pickletools.py index c0f8c545de3a4b..3c4fdd9bafd9bc 100644 --- a/Lib/pickletools.py +++ b/Lib/pickletools.py @@ -217,7 +217,7 @@ def __init__(self, name, n, reader, doc): def read_uint1(f): r""" >>> import io - >>> read_uint1(io.BytesIO(b'\xff')) + >>> read_uint1(io.BytesIO(b"\xff")) 255 """ @@ -235,9 +235,9 @@ def read_uint1(f): def read_uint2(f): r""" >>> import io - >>> read_uint2(io.BytesIO(b'\xff\x00')) + >>> read_uint2(io.BytesIO(b"\xff\x00")) 255 - >>> read_uint2(io.BytesIO(b'\xff\xff')) + >>> read_uint2(io.BytesIO(b"\xff\xff")) 65535 """ @@ -258,9 +258,9 @@ def read_uint2(f): def read_int4(f): r""" >>> import io - >>> read_int4(io.BytesIO(b'\xff\x00\x00\x00')) + >>> read_int4(io.BytesIO(b"\xff\x00\x00\x00")) 255 - >>> read_int4(io.BytesIO(b'\x00\x00\x00\x80')) == -(2**31) + >>> read_int4(io.BytesIO(b"\x00\x00\x00\x80")) == -(2**31) True """ @@ -281,9 +281,9 @@ def read_int4(f): def read_uint4(f): r""" >>> import io - >>> read_uint4(io.BytesIO(b'\xff\x00\x00\x00')) + >>> read_uint4(io.BytesIO(b"\xff\x00\x00\x00")) 255 - >>> read_uint4(io.BytesIO(b'\x00\x00\x00\x80')) == 2**31 + >>> read_uint4(io.BytesIO(b"\x00\x00\x00\x80")) == 2**31 True """ @@ -304,9 +304,9 @@ def read_uint4(f): def read_uint8(f): r""" >>> import io - >>> read_uint8(io.BytesIO(b'\xff\x00\x00\x00\x00\x00\x00\x00')) + >>> read_uint8(io.BytesIO(b"\xff\x00\x00\x00\x00\x00\x00\x00")) 255 - >>> read_uint8(io.BytesIO(b'\xff' * 8)) == 2**64-1 + >>> read_uint8(io.BytesIO(b"\xff" * 8)) == 2**64 - 1 True """ @@ -347,7 +347,7 @@ def read_stringnl(f, decode=True, stripquotes=True): ValueError: no newline found when trying to read stringnl Embedded escapes are undone in the result. - >>> read_stringnl(io.BytesIO(br"'a\n\\b\x00c\td'" + b"\n'e'")) + >>> read_stringnl(io.BytesIO(rb"'a\n\\b\x00c\td'" + b"\n'e'")) 'a\n\\b\x00c\td' """ @@ -571,8 +571,8 @@ def read_bytes8(f): b'' >>> read_bytes8(io.BytesIO(b"\x03\x00\x00\x00\x00\x00\x00\x00abcdef")) b'abc' - >>> bigsize8 = struct.pack(">> read_bytes8(io.BytesIO(bigsize8 + b"abcdef")) #doctest: +ELLIPSIS + >>> bigsize8 = struct.pack(">> read_bytes8(io.BytesIO(bigsize8 + b"abcdef")) # doctest: +ELLIPSIS Traceback (most recent call last): ... ValueError: expected ... bytes in a bytes8, but only 6 remain @@ -609,8 +609,8 @@ def read_bytearray8(f): bytearray(b'') >>> read_bytearray8(io.BytesIO(b"\x03\x00\x00\x00\x00\x00\x00\x00abcdef")) bytearray(b'abc') - >>> bigsize8 = struct.pack(">> read_bytearray8(io.BytesIO(bigsize8 + b"abcdef")) #doctest: +ELLIPSIS + >>> bigsize8 = struct.pack(">> read_bytearray8(io.BytesIO(bigsize8 + b"abcdef")) # doctest: +ELLIPSIS Traceback (most recent call last): ... ValueError: expected ... bytes in a bytearray8, but only 6 remain @@ -643,7 +643,7 @@ def read_bytearray8(f): def read_unicodestringnl(f): r""" >>> import io - >>> read_unicodestringnl(io.BytesIO(b"abc\\uabcd\njunk")) == 'abc\uabcd' + >>> read_unicodestringnl(io.BytesIO(b"abc\\uabcd\njunk")) == "abc\uabcd" True """ @@ -670,12 +670,12 @@ def read_unicodestringnl(f): def read_unicodestring1(f): r""" >>> import io - >>> s = 'abcd\uabcd' - >>> enc = s.encode('utf-8') + >>> s = "abcd\uabcd" + >>> enc = s.encode("utf-8") >>> enc b'abcd\xea\xaf\x8d' >>> n = bytes([len(enc)]) # little-endian 1-byte length - >>> t = read_unicodestring1(io.BytesIO(n + enc + b'junk')) + >>> t = read_unicodestring1(io.BytesIO(n + enc + b"junk")) >>> s == t True @@ -712,12 +712,12 @@ def read_unicodestring1(f): def read_unicodestring4(f): r""" >>> import io - >>> s = 'abcd\uabcd' - >>> enc = s.encode('utf-8') + >>> s = "abcd\uabcd" + >>> enc = s.encode("utf-8") >>> enc b'abcd\xea\xaf\x8d' >>> n = bytes([len(enc), 0, 0, 0]) # little-endian 4-byte length - >>> t = read_unicodestring4(io.BytesIO(n + enc + b'junk')) + >>> t = read_unicodestring4(io.BytesIO(n + enc + b"junk")) >>> s == t True @@ -756,12 +756,12 @@ def read_unicodestring4(f): def read_unicodestring8(f): r""" >>> import io - >>> s = 'abcd\uabcd' - >>> enc = s.encode('utf-8') + >>> s = "abcd\uabcd" + >>> enc = s.encode("utf-8") >>> enc b'abcd\xea\xaf\x8d' - >>> n = bytes([len(enc)]) + b'\0' * 7 # little-endian 8-byte length - >>> t = read_unicodestring8(io.BytesIO(n + enc + b'junk')) + >>> n = bytes([len(enc)]) + b"\0" * 7 # little-endian 8-byte length + >>> t = read_unicodestring8(io.BytesIO(n + enc + b"junk")) >>> s == t True diff --git a/Lib/poplib.py b/Lib/poplib.py index 903886a206b6c8..ad39a55da025eb 100644 --- a/Lib/poplib.py +++ b/Lib/poplib.py @@ -354,7 +354,7 @@ def utf8(self): def capa(self): """Return server capabilities (RFC 2449) as a dictionary - >>> c=poplib.POP3('localhost') + >>> c = poplib.POP3("localhost") >>> c.capa() {'IMPLEMENTATION': ['Cyrus', 'POP3', 'server', 'v2.2.12'], 'TOP': [], 'LOGIN-DELAY': ['0'], 'AUTH-RESP-CODE': [], diff --git a/Lib/pydoc.py b/Lib/pydoc.py index bf2902f508e7a2..8b4272e5731c1e 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -2611,7 +2611,7 @@ def _start_server(urlhandler, hostname, port): Then get or generate some text or HTML code and return it. >>> def my_url_handler(url, content_type): - ... text = 'the URL sent was: (%s, %s)' % (url, content_type) + ... text = "the URL sent was: (%s, %s)" % (url, content_type) ... return text Start server thread on port 0. @@ -2625,7 +2625,7 @@ def _start_server(urlhandler, hostname, port): and get first page. Use serverthread.url as the starting page. >>> if serverthread.serving: - ... import webbrowser + ... import webbrowser The next two lines are commented out so a browser doesn't open if doctest is run on this module. @@ -2637,15 +2637,15 @@ def _start_server(urlhandler, hostname, port): Use time.sleep so the loop doesn't hog the CPU. >>> starttime = time.monotonic() - >>> timeout = 1 #seconds + >>> timeout = 1 # seconds This is a short timeout for testing purposes. >>> while serverthread.serving: - ... time.sleep(.01) + ... time.sleep(0.01) ... if serverthread.serving and time.monotonic() - starttime > timeout: - ... serverthread.stop() - ... break + ... serverthread.stop() + ... break Print any errors that may have occurred. diff --git a/Lib/secrets.py b/Lib/secrets.py index 0ea390d3d334d7..dd814ac35d9b59 100644 --- a/Lib/secrets.py +++ b/Lib/secrets.py @@ -45,7 +45,7 @@ def token_bytes(nbytes=None): If *nbytes* is ``None`` or not supplied, a reasonable default is used. - >>> token_bytes(16) #doctest:+SKIP + >>> token_bytes(16) # doctest:+SKIP b'\\xebr\\x17D*t\\xae\\xd4\\xe3S\\xb6\\xe2\\xebP1\\x8b' """ @@ -61,7 +61,7 @@ def token_hex(nbytes=None): hex digits. If *nbytes* is ``None`` or not supplied, a reasonable default is used. - >>> token_hex(16) #doctest:+SKIP + >>> token_hex(16) # doctest:+SKIP 'f9bf78b9a18ce6d46a0cd2b0b86df9da' """ @@ -74,7 +74,7 @@ def token_urlsafe(nbytes=None): The string has *nbytes* random bytes. If *nbytes* is ``None`` or not supplied, a reasonable default is used. - >>> token_urlsafe(16) #doctest:+SKIP + >>> token_urlsafe(16) # doctest:+SKIP 'Drmhze6EPcv0fN_81Bj-nA' """ diff --git a/Lib/shutil.py b/Lib/shutil.py index 0279d8c760eea8..306bc3f50cae45 100644 --- a/Lib/shutil.py +++ b/Lib/shutil.py @@ -910,11 +910,11 @@ def _basename(path): path: Union[PathLike, str] e.g. - >>> os.path.basename('/bar/foo') + >>> os.path.basename("/bar/foo") 'foo' - >>> os.path.basename('/bar/foo/') + >>> os.path.basename("/bar/foo/") '' - >>> _basename('/bar/foo/') + >>> _basename("/bar/foo/") 'foo' """ path = os.fspath(path) diff --git a/Lib/socket.py b/Lib/socket.py index eb9ea3a9dce222..864db40240277c 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -908,7 +908,7 @@ def create_server( connections. When false it will explicitly disable this option on platforms that enable it by default (e.g. Linux). - >>> with create_server(('', 8000)) as server: + >>> with create_server(("", 8000)) as server: ... while True: ... conn, addr = server.accept() ... # handle new connection diff --git a/Lib/statistics.py b/Lib/statistics.py index 7e04317f1506dc..613d599c6352a8 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -384,14 +384,14 @@ def _rank(data, /, *, key=None, reverse=False, ties="average", start=1) -> list[ highest value has rank 1. Also, a key-function can extract the field to be ranked: - >>> goals = [('eagles', 45), ('bears', 48), ('lions', 44)] + >>> goals = [("eagles", 45), ("bears", 48), ("lions", 44)] >>> _rank(goals, key=itemgetter(1), reverse=True) [2.0, 1.0, 3.0] Ranks are conventionally numbered starting from one; however, setting *start* to zero allows the ranks to be used as array indices: - >>> prize = ['Gold', 'Silver', 'Bronze', 'Certificate'] + >>> prize = ["Gold", "Silver", "Bronze", "Certificate"] >>> scores = [8.1, 7.3, 9.4, 8.3] >>> [prize[int(i)] for i in _rank(scores, start=0, reverse=True)] ['Bronze', 'Certificate', 'Gold', 'Silver'] @@ -691,13 +691,15 @@ def median_grouped(data, interval=1.0): consecutive ten-year age groups with each group being represented by the 5-year midpoints of the intervals: - >>> demographics = Counter({ - ... 25: 172, # 20 to 30 years old - ... 35: 484, # 30 to 40 years old - ... 45: 387, # 40 to 50 years old - ... 55: 22, # 50 to 60 years old - ... 65: 6, # 60 to 70 years old - ... }) + >>> demographics = Counter( + ... { + ... 25: 172, # 20 to 30 years old + ... 35: 484, # 30 to 40 years old + ... 45: 387, # 40 to 50 years old + ... 55: 22, # 50 to 60 years old + ... 65: 6, # 60 to 70 years old + ... } + ... ) The 50th percentile (median) is the 536th person out of the 1071 member cohort. That person is in the 30 to 40 year old age group. @@ -767,7 +769,7 @@ def mode(data): If there are multiple modes with same frequency, return the first one encountered: - >>> mode(['red', 'red', 'green', 'blue', 'blue']) + >>> mode(["red", "red", "green", "blue", "blue"]) 'red' If *data* is empty, ``mode``, raises StatisticsError. @@ -786,11 +788,11 @@ def multimode(data): Will return more than one result if there are multiple modes or an empty list if *data* is empty. - >>> multimode('aabbbbbbbbcc') + >>> multimode("aabbbbbbbbcc") ['b'] - >>> multimode('aabbbbccddddeeffffgg') + >>> multimode("aabbbbccddddeeffffgg") ['b', 'd', 'f'] - >>> multimode('') + >>> multimode("") [] """ counts = Counter(iter(data)) @@ -1156,7 +1158,7 @@ def linear_regression(x, y, /, *, proportional=False): >>> x = [1, 2, 3, 4, 5] >>> noise = NormalDist().samples(5, seed=42) >>> y = [3 * x[i] + 2 + noise[i] for i in range(5)] - >>> linear_regression(x, y) #doctest: +ELLIPSIS + >>> linear_regression(x, y) # doctest: +ELLIPSIS LinearRegression(slope=3.17495..., intercept=1.00925...) If *proportional* is true, the independent variable *x* and the @@ -1169,7 +1171,7 @@ def linear_regression(x, y, /, *, proportional=False): y = slope * x + noise >>> y = [3 * x[i] + noise[i] for i in range(5)] - >>> linear_regression(x, y, proportional=True) #doctest: +ELLIPSIS + >>> linear_regression(x, y, proportional=True) # doctest: +ELLIPSIS LinearRegression(slope=2.90475..., intercept=0.0) """ diff --git a/Lib/subprocess.py b/Lib/subprocess.py index e052b24f130c6b..6cad5df2246529 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -492,9 +492,7 @@ def check_output(*popenargs, timeout=None, **kwargs): The stdout argument is not allowed as it is used internally. To capture standard error in the result, use stderr=STDOUT. - >>> check_output(["/bin/sh", "-c", - ... "ls -l non_existent_file ; exit 0"], - ... stderr=STDOUT) + >>> check_output(["/bin/sh", "-c", "ls -l non_existent_file ; exit 0"], stderr=STDOUT) b'ls: non_existent_file: No such file or directory\n' There is an additional optional argument, "input", allowing you to @@ -502,8 +500,9 @@ def check_output(*popenargs, timeout=None, **kwargs): you may not also use the Popen constructor's "stdin" argument, as it too will be used internally. Example: - >>> check_output(["sed", "-e", "s/foo/bar/"], - ... input=b"when in the course of fooman events\n") + >>> check_output( + ... ["sed", "-e", "s/foo/bar/"], input=b"when in the course of fooman events\n" + ... ) b'when in the course of barman events\n' By default, all communication is in bytes, and therefore any "input" @@ -731,13 +730,13 @@ def getstatusoutput(cmd, *, encoding=None, errors=None): according to the rules for the function 'wait'. Example: >>> import subprocess - >>> subprocess.getstatusoutput('ls /bin/ls') + >>> subprocess.getstatusoutput("ls /bin/ls") (0, '/bin/ls') - >>> subprocess.getstatusoutput('cat /bin/junk') + >>> subprocess.getstatusoutput("cat /bin/junk") (1, 'cat: /bin/junk: No such file or directory') - >>> subprocess.getstatusoutput('/bin/junk') + >>> subprocess.getstatusoutput("/bin/junk") (127, 'sh: /bin/junk: not found') - >>> subprocess.getstatusoutput('/bin/kill $$') + >>> subprocess.getstatusoutput("/bin/kill $$") (-15, '') """ try: @@ -760,7 +759,7 @@ def getoutput(cmd, *, encoding=None, errors=None): value is a string containing the command's output. Example: >>> import subprocess - >>> subprocess.getoutput('ls /bin/ls') + >>> subprocess.getoutput("ls /bin/ls") '/bin/ls' """ return getstatusoutput(cmd, encoding=encoding, errors=errors)[1] diff --git a/Lib/test/sample_doctest.py b/Lib/test/sample_doctest.py index 2a27edd90208bb..4dba7dc29caa54 100644 --- a/Lib/test/sample_doctest.py +++ b/Lib/test/sample_doctest.py @@ -15,10 +15,10 @@ def foo(): """ - >>> 2+2 + >>> 2 + 2 5 - >>> 2+2 + >>> 2 + 2 4 """ @@ -26,7 +26,7 @@ def foo(): def bar(): """ - >>> 2+2 + >>> 2 + 2 4 """ @@ -43,9 +43,9 @@ def test_silly_setup(): def w_blank(): """ >>> if 1: - ... print('a') - ... print() - ... print('b') + ... print("a") + ... print() + ... print("b") a b diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 72a06d6af450e3..8a0c06a27c366f 100644 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -42,8 +42,7 @@ ctypes = None try: - with os_helper.EnvironmentVarGuard() as os.environ, \ - warnings.catch_warnings(): + with os_helper.EnvironmentVarGuard() as os.environ, warnings.catch_warnings(): from numpy import ndarray as numpy_array except ImportError: numpy_array = None @@ -63,72 +62,93 @@ # Native format chars and their ranges. NATIVE = { - '?':0, 'c':0, 'b':0, 'B':0, - 'h':0, 'H':0, 'i':0, 'I':0, - 'l':0, 'L':0, 'n':0, 'N':0, - 'e':0, 'f':0, 'd':0, 'P':0 + "?": 0, + "c": 0, + "b": 0, + "B": 0, + "h": 0, + "H": 0, + "i": 0, + "I": 0, + "l": 0, + "L": 0, + "n": 0, + "N": 0, + "e": 0, + "f": 0, + "d": 0, + "P": 0, } # NumPy does not have 'n' or 'N': if numpy_array: - del NATIVE['n'] - del NATIVE['N'] + del NATIVE["n"] + del NATIVE["N"] if struct: try: # Add "qQ" if present in native mode. - struct.pack('Q', 2**64-1) - NATIVE['q'] = 0 - NATIVE['Q'] = 0 + struct.pack("Q", 2**64 - 1) + NATIVE["q"] = 0 + NATIVE["Q"] = 0 except struct.error: pass # Standard format chars and their ranges. STANDARD = { - '?':(0, 2), 'c':(0, 1<<8), - 'b':(-(1<<7), 1<<7), 'B':(0, 1<<8), - 'h':(-(1<<15), 1<<15), 'H':(0, 1<<16), - 'i':(-(1<<31), 1<<31), 'I':(0, 1<<32), - 'l':(-(1<<31), 1<<31), 'L':(0, 1<<32), - 'q':(-(1<<63), 1<<63), 'Q':(0, 1<<64), - 'e':(-65519, 65520), 'f':(-(1<<63), 1<<63), - 'd':(-(1<<1023), 1<<1023) + "?": (0, 2), + "c": (0, 1 << 8), + "b": (-(1 << 7), 1 << 7), + "B": (0, 1 << 8), + "h": (-(1 << 15), 1 << 15), + "H": (0, 1 << 16), + "i": (-(1 << 31), 1 << 31), + "I": (0, 1 << 32), + "l": (-(1 << 31), 1 << 31), + "L": (0, 1 << 32), + "q": (-(1 << 63), 1 << 63), + "Q": (0, 1 << 64), + "e": (-65519, 65520), + "f": (-(1 << 63), 1 << 63), + "d": (-(1 << 1023), 1 << 1023), } + def native_type_range(fmt): """Return range of a native type.""" - if fmt == 'c': + if fmt == "c": lh = (0, 256) - elif fmt == '?': + elif fmt == "?": lh = (0, 2) - elif fmt == 'e': + elif fmt == "e": lh = (-65519, 65520) - elif fmt == 'f': - lh = (-(1<<63), 1<<63) - elif fmt == 'd': - lh = (-(1<<1023), 1<<1023) + elif fmt == "f": + lh = (-(1 << 63), 1 << 63) + elif fmt == "d": + lh = (-(1 << 1023), 1 << 1023) else: for exp in (128, 127, 64, 63, 32, 31, 16, 15, 8, 7): try: - struct.pack(fmt, (1<':STANDARD, - '=':STANDARD, - '!':STANDARD + "": NATIVE, + "@": NATIVE, + "<": STANDARD, + ">": STANDARD, + "=": STANDARD, + "!": STANDARD, } if struct: - for fmt in fmtdict['@']: - fmtdict['@'][fmt] = native_type_range(fmt) + for fmt in fmtdict["@"]: + fmtdict["@"][fmt] = native_type_range(fmt) # Format codes suppported by the memoryview object MEMORYVIEW = NATIVE.copy() @@ -144,47 +164,50 @@ def native_type_range(fmt): if not k in "Bbc": del BYTEFMT[k] -fmtdict['m'] = MEMORYVIEW -fmtdict['@m'] = MEMORYVIEW -fmtdict['a'] = ARRAY -fmtdict['b'] = BYTEFMT -fmtdict['@b'] = BYTEFMT +fmtdict["m"] = MEMORYVIEW +fmtdict["@m"] = MEMORYVIEW +fmtdict["a"] = ARRAY +fmtdict["b"] = BYTEFMT +fmtdict["@b"] = BYTEFMT # Capabilities of the test objects: MODE = 0 MULT = 1 -cap = { # format chars # multiplier - 'ndarray': (['', '@', '<', '>', '=', '!'], ['', '1', '2', '3']), - 'array': (['a'], ['']), - 'numpy': ([''], ['']), - 'memoryview': (['@m', 'm'], ['']), - 'bytefmt': (['@b', 'b'], ['']), +cap = { # format chars # multiplier + "ndarray": (["", "@", "<", ">", "=", "!"], ["", "1", "2", "3"]), + "array": (["a"], [""]), + "numpy": ([""], [""]), + "memoryview": (["@m", "m"], [""]), + "bytefmt": (["@b", "b"], [""]), } + def randrange_fmt(mode, char, obj): """Return random item for a type specified by a mode and a single - format character.""" + format character.""" x = randrange(*fmtdict[mode][char]) - if char == 'c': + if char == "c": x = bytes([x]) - if obj == 'numpy' and x == b'\x00': + if obj == "numpy" and x == b"\x00": # http://projects.scipy.org/numpy/ticket/1925 - x = b'\x01' - if char == '?': + x = b"\x01" + if char == "?": x = bool(x) - if char in 'efd': + if char in "efd": x = struct.pack(char, x) x = struct.unpack(char, x)[0] return x + def gen_item(fmt, obj): """Return single random item.""" - mode, chars = fmt.split('#') + mode, chars = fmt.split("#") x = [] for c in chars: x.append(randrange_fmt(mode, c, obj)) return x[0] if len(x) == 1 else tuple(x) + def gen_items(n, fmt, obj): """Return a list of random items (or a scalar).""" if n == 0: @@ -194,72 +217,80 @@ def gen_items(n, fmt, obj): lst[i] = gen_item(fmt, obj) return lst + def struct_items(n, obj): mode = choice(cap[obj][MODE]) - xfmt = mode + '#' - fmt = mode.strip('amb') - nmemb = randrange(2, 10) # number of struct members + xfmt = mode + "#" + fmt = mode.strip("amb") + nmemb = randrange(2, 10) # number of struct members for _ in range(nmemb): char = choice(tuple(fmtdict[mode])) multiplier = choice(cap[obj][MULT]) - xfmt += (char * int(multiplier if multiplier else 1)) - fmt += (multiplier + char) + xfmt += char * int(multiplier if multiplier else 1) + fmt += multiplier + char items = gen_items(n, xfmt, obj) item = gen_item(xfmt, obj) return fmt, items, item -def randitems(n, obj='ndarray', mode=None, char=None): + +def randitems(n, obj="ndarray", mode=None, char=None): """Return random format, items, item.""" if mode is None: mode = choice(cap[obj][MODE]) if char is None: char = choice(tuple(fmtdict[mode])) multiplier = choice(cap[obj][MULT]) - fmt = mode + '#' + char * int(multiplier if multiplier else 1) + fmt = mode + "#" + char * int(multiplier if multiplier else 1) items = gen_items(n, fmt, obj) item = gen_item(fmt, obj) - fmt = mode.strip('amb') + multiplier + char + fmt = mode.strip("amb") + multiplier + char return fmt, items, item -def iter_mode(n, obj='ndarray'): + +def iter_mode(n, obj="ndarray"): """Iterate through supported mode/char combinations.""" for mode in cap[obj][MODE]: for char in fmtdict[mode]: yield randitems(n, obj, mode, char) -def iter_format(nitems, testobj='ndarray'): + +def iter_format(nitems, testobj="ndarray"): """Yield (format, items, item) for all possible modes and format - characters plus one random compound format string.""" + characters plus one random compound format string.""" for t in iter_mode(nitems, testobj): yield t - if testobj != 'ndarray': + if testobj != "ndarray": return yield struct_items(nitems, testobj) def is_byte_format(fmt): - return 'c' in fmt or 'b' in fmt or 'B' in fmt + return "c" in fmt or "b" in fmt or "B" in fmt + def is_memoryview_format(fmt): """format suitable for memoryview""" x = len(fmt) - return ((x == 1 or (x == 2 and fmt[0] == '@')) and - fmt[x-1] in MEMORYVIEW) + return (x == 1 or (x == 2 and fmt[0] == "@")) and fmt[x - 1] in MEMORYVIEW -NON_BYTE_FORMAT = [c for c in fmtdict['@'] if not is_byte_format(c)] + +NON_BYTE_FORMAT = [c for c in fmtdict["@"] if not is_byte_format(c)] # ====================================================================== # Multi-dimensional tolist(), slicing and slice assignments # ====================================================================== + def atomp(lst): """Tuple items (representing structs) are regarded as atoms.""" return not isinstance(lst, list) + def listp(lst): return isinstance(lst, list) + def prod(lst): """Product of list elements.""" if len(lst) == 0: @@ -269,24 +300,26 @@ def prod(lst): x *= v return x + def strides_from_shape(ndim, shape, itemsize, layout): """Calculate strides of a contiguous array. Layout is 'C' or - 'F' (Fortran).""" + 'F' (Fortran).""" if ndim == 0: return () - if layout == 'C': + if layout == "C": strides = list(shape[1:]) + [itemsize] - for i in range(ndim-2, -1, -1): - strides[i] *= strides[i+1] + for i in range(ndim - 2, -1, -1): + strides[i] *= strides[i + 1] else: strides = [itemsize] + list(shape[:-1]) for i in range(1, ndim): - strides[i] *= strides[i-1] + strides[i] *= strides[i - 1] return strides + def _ca(items, s): """Convert flat item list to the nested list representation of a - multidimensional C array with shape 's'.""" + multidimensional C array with shape 's'.""" if atomp(items): return items if len(s) == 0: @@ -294,13 +327,14 @@ def _ca(items, s): lst = [0] * s[0] stride = len(items) // s[0] if s[0] else 0 for i in range(s[0]): - start = i*stride - lst[i] = _ca(items[start:start+stride], s[1:]) + start = i * stride + lst[i] = _ca(items[start : start + stride], s[1:]) return lst + def _fa(items, s): """Convert flat item list to the nested list representation of a - multidimensional Fortran array with shape 's'.""" + multidimensional Fortran array with shape 's'.""" if atomp(items): return items if len(s) == 0: @@ -311,21 +345,25 @@ def _fa(items, s): lst[i] = _fa(items[i::stride], s[1:]) return lst + def carray(items, shape): if listp(items) and not 0 in shape and prod(shape) != len(items): raise ValueError("prod(shape) != len(items)") return _ca(items, shape) + def farray(items, shape): if listp(items) and not 0 in shape and prod(shape) != len(items): raise ValueError("prod(shape) != len(items)") return _fa(items, shape) + def indices(shape): """Generate all possible tuples of indices.""" iterables = [range(v) for v in shape] return product(*iterables) + def getindex(ndim, ind, strides): """Convert multi-dimensional index to the position in the flat list.""" ret = 0 @@ -333,14 +371,15 @@ def getindex(ndim, ind, strides): ret += strides[i] * ind[i] return ret + def transpose(src, shape): """Transpose flat item list that is regarded as a multi-dimensional - matrix defined by shape: dest...[k][j][i] = src[i][j][k]... """ + matrix defined by shape: dest...[k][j][i] = src[i][j][k]...""" if not shape: return src ndim = len(shape) - sstrides = strides_from_shape(ndim, shape, 1, 'C') - dstrides = strides_from_shape(ndim, shape[::-1], 1, 'C') + sstrides = strides_from_shape(ndim, shape, 1, "C") + dstrides = strides_from_shape(ndim, shape[::-1], 1, "C") dest = [0] * len(src) for ind in indices(shape): fr = getindex(ndim, ind, sstrides) @@ -348,6 +387,7 @@ def transpose(src, shape): dest[to] = src[fr] return dest + def _flatten(lst): """flatten list""" if lst == []: @@ -356,52 +396,59 @@ def _flatten(lst): return [lst] return _flatten(lst[0]) + _flatten(lst[1:]) + def flatten(lst): """flatten list or return scalar""" - if atomp(lst): # scalar + if atomp(lst): # scalar return lst return _flatten(lst) + def slice_shape(lst, slices): """Get the shape of lst after slicing: slices is a list of slice - objects.""" + objects.""" if atomp(lst): return [] return [len(lst[slices[0]])] + slice_shape(lst[0], slices[1:]) + def multislice(lst, slices): """Multi-dimensional slicing: slices is a list of slice objects.""" if atomp(lst): return lst return [multislice(sublst, slices[1:]) for sublst in lst[slices[0]]] + def m_assign(llst, rlst, lslices, rslices): """Multi-dimensional slice assignment: llst and rlst are the operands, - lslices and rslices are lists of slice objects. llst and rlst must - have the same structure. + lslices and rslices are lists of slice objects. llst and rlst must + have the same structure. - For a two-dimensional example, this is not implemented in Python: + For a two-dimensional example, this is not implemented in Python: - llst[0:3:2, 0:3:2] = rlst[1:3:1, 1:3:1] + llst[0:3:2, 0:3:2] = rlst[1:3:1, 1:3:1] - Instead we write: + Instead we write: - lslices = [slice(0,3,2), slice(0,3,2)] - rslices = [slice(1,3,1), slice(1,3,1)] - multislice_assign(llst, rlst, lslices, rslices) + lslices = [slice(0,3,2), slice(0,3,2)] + rslices = [slice(1,3,1), slice(1,3,1)] + multislice_assign(llst, rlst, lslices, rslices) """ if atomp(rlst): return rlst - rlst = [m_assign(l, r, lslices[1:], rslices[1:]) - for l, r in zip(llst[lslices[0]], rlst[rslices[0]])] + rlst = [ + m_assign(l, r, lslices[1:], rslices[1:]) + for l, r in zip(llst[lslices[0]], rlst[rslices[0]]) + ] llst[lslices[0]] = rlst return llst + def cmp_structure(llst, rlst, lslices, rslices): """Compare the structure of llst[lslices] and rlst[rslices].""" lshape = slice_shape(llst, lslices) rshape = slice_shape(rlst, rslices) - if (len(lshape) != len(rshape)): + if len(lshape) != len(rshape): return -1 for i in range(len(lshape)): if lshape[i] != rshape[i]: @@ -410,6 +457,7 @@ def cmp_structure(llst, rlst, lslices, rslices): return 0 return 0 + def multislice_assign(llst, rlst, lslices, rslices): """Return llst after assigning: llst[lslices] = rlst[rslices]""" if cmp_structure(llst, rlst, lslices, rslices) < 0: @@ -440,16 +488,17 @@ def multislice_assign(llst, rlst, lslices, rslices): # t = (memlen, itemsize, ndim, shape, strides, offset) # + def verify_structure(memlen, itemsize, ndim, shape, strides, offset): """Verify that the parameters represent a valid array within - the bounds of the allocated memory: - char *mem: start of the physical memory block - memlen: length of the physical memory block - offset: (char *)buf - mem + the bounds of the allocated memory: + char *mem: start of the physical memory block + memlen: length of the physical memory block + offset: (char *)buf - mem """ if offset % itemsize: return False - if offset < 0 or offset+itemsize > memlen: + if offset < 0 or offset + itemsize > memlen: return False if any(v % itemsize for v in strides): return False @@ -459,53 +508,55 @@ def verify_structure(memlen, itemsize, ndim, shape, strides, offset): if 0 in shape: return True - imin = sum(strides[j]*(shape[j]-1) for j in range(ndim) - if strides[j] <= 0) - imax = sum(strides[j]*(shape[j]-1) for j in range(ndim) - if strides[j] > 0) + imin = sum(strides[j] * (shape[j] - 1) for j in range(ndim) if strides[j] <= 0) + imax = sum(strides[j] * (shape[j] - 1) for j in range(ndim) if strides[j] > 0) + + return 0 <= offset + imin and offset + imax + itemsize <= memlen - return 0 <= offset+imin and offset+imax+itemsize <= memlen def get_item(lst, indices): for i in indices: lst = lst[i] return lst + def memory_index(indices, t): """Location of an item in the underlying memory.""" memlen, itemsize, ndim, shape, strides, offset = t p = offset for i in range(ndim): - p += strides[i]*indices[i] + p += strides[i] * indices[i] return p + def is_overlapping(t): """The structure 't' is overlapping if at least one memory location - is visited twice while iterating through all possible tuples of - indices.""" + is visited twice while iterating through all possible tuples of + indices.""" memlen, itemsize, ndim, shape, strides, offset = t - visited = 1<= 95 and n & 1 else False strides = [0] * ndim - strides[ndim-1] = itemsize * randrange(-maxstride, maxstride+1) - if not zero_stride and strides[ndim-1] == 0: - strides[ndim-1] = itemsize + strides[ndim - 1] = itemsize * randrange(-maxstride, maxstride + 1) + if not zero_stride and strides[ndim - 1] == 0: + strides[ndim - 1] = itemsize - for i in range(ndim-2, -1, -1): - maxstride *= shape[i+1] if shape[i+1] else 1 + for i in range(ndim - 2, -1, -1): + maxstride *= shape[i + 1] if shape[i + 1] else 1 if zero_stride: - strides[i] = itemsize * randrange(-maxstride, maxstride+1) + strides[i] = itemsize * randrange(-maxstride, maxstride + 1) else: - strides[i] = ((1,-1)[randrange(2)] * - itemsize * randrange(1, maxstride+1)) + strides[i] = (1, -1)[randrange(2)] * itemsize * randrange(1, maxstride + 1) imin = imax = 0 if not 0 in shape: - imin = sum(strides[j]*(shape[j]-1) for j in range(ndim) - if strides[j] <= 0) - imax = sum(strides[j]*(shape[j]-1) for j in range(ndim) - if strides[j] > 0) + imin = sum(strides[j] * (shape[j] - 1) for j in range(ndim) if strides[j] <= 0) + imax = sum(strides[j] * (shape[j] - 1) for j in range(ndim) if strides[j] > 0) nitems = imax - imin if valid: offset = -imin * itemsize - memlen = offset + (imax+1) * itemsize + memlen = offset + (imax + 1) * itemsize else: memlen = (-imin + imax) * itemsize - offset = -imin-itemsize if randrange(2) == 0 else memlen + offset = -imin - itemsize if randrange(2) == 0 else memlen return memlen, itemsize, ndim, shape, strides, offset + def randslice_from_slicelen(slicelen, listlen): """Create a random slice of len slicelen that fits into listlen.""" maxstart = listlen - slicelen - start = randrange(maxstart+1) + start = randrange(maxstart + 1) maxstep = (listlen - start) // slicelen if slicelen else 1 - step = randrange(1, maxstep+1) + step = randrange(1, maxstep + 1) stop = start + slicelen * step s = slice(start, stop, step) _, _, _, control = slice_indices(s, listlen) @@ -569,23 +618,25 @@ def randslice_from_slicelen(slicelen, listlen): raise RuntimeError return s + def randslice_from_shape(ndim, shape): """Create two sets of slices for an array x with shape 'shape' - such that shapeof(x[lslices]) == shapeof(x[rslices]).""" + such that shapeof(x[lslices]) == shapeof(x[rslices]).""" lslices = [0] * ndim rslices = [0] * ndim for n in range(ndim): l = shape[n] - slicelen = randrange(1, l+1) if l > 0 else 0 + slicelen = randrange(1, l + 1) if l > 0 else 0 lslices[n] = randslice_from_slicelen(slicelen, l) rslices[n] = randslice_from_slicelen(slicelen, l) return tuple(lslices), tuple(rslices) + def rand_aligned_slices(maxdim=5, maxshape=16): """Create (lshape, rshape, tuple(lslices), tuple(rslices)) such that - shapeof(x[lslices]) == shapeof(y[rslices]), where x is an array - with shape 'lshape' and y is an array with shape 'rshape'.""" - ndim = randrange(1, maxdim+1) + shapeof(x[lslices]) == shapeof(y[rslices]), where x is an array + with shape 'lshape' and y is an array with shape 'rshape'.""" + ndim = randrange(1, maxdim + 1) minshape = 2 n = randrange(100) if n >= 95: @@ -593,24 +644,26 @@ def rand_aligned_slices(maxdim=5, maxshape=16): elif n >= 90: minshape = 1 all_random = True if randrange(100) >= 80 else False - lshape = [0]*ndim; rshape = [0]*ndim - lslices = [0]*ndim; rslices = [0]*ndim + lshape = [0] * ndim + rshape = [0] * ndim + lslices = [0] * ndim + rslices = [0] * ndim for n in range(ndim): - small = randrange(minshape, maxshape+1) - big = randrange(minshape, maxshape+1) + small = randrange(minshape, maxshape + 1) + big = randrange(minshape, maxshape + 1) if big < small: big, small = small, big # Create a slice that fits the smaller value. if all_random: - start = randrange(-small, small+1) - stop = randrange(-small, small+1) - step = (1,-1)[randrange(2)] * randrange(1, small+2) + start = randrange(-small, small + 1) + stop = randrange(-small, small + 1) + step = (1, -1)[randrange(2)] * randrange(1, small + 2) s_small = slice(start, stop, step) _, _, _, slicelen = slice_indices(s_small, small) else: - slicelen = randrange(1, small+1) if small > 0 else 0 + slicelen = randrange(1, small + 1) if small > 0 else 0 s_small = randslice_from_slicelen(slicelen, small) # Create a slice of the same length for the bigger value. @@ -624,40 +677,51 @@ def rand_aligned_slices(maxdim=5, maxshape=16): return lshape, rshape, tuple(lslices), tuple(rslices) + def randitems_from_structure(fmt, t): """Return a list of random items for structure 't' with format - 'fmtchar'.""" + 'fmtchar'.""" memlen, itemsize, _, _, _, _ = t - return gen_items(memlen//itemsize, '#'+fmt, 'numpy') + return gen_items(memlen // itemsize, "#" + fmt, "numpy") + def ndarray_from_structure(items, fmt, t, flags=0): """Return ndarray from the tuple returned by rand_structure()""" memlen, itemsize, ndim, shape, strides, offset = t - return ndarray(items, shape=shape, strides=strides, format=fmt, - offset=offset, flags=ND_WRITABLE|flags) + return ndarray( + items, + shape=shape, + strides=strides, + format=fmt, + offset=offset, + flags=ND_WRITABLE | flags, + ) + def numpy_array_from_structure(items, fmt, t): """Return numpy_array from the tuple returned by rand_structure()""" memlen, itemsize, ndim, shape, strides, offset = t buf = bytearray(memlen) for j, v in enumerate(items): - struct.pack_into(fmt, buf, j*itemsize, v) - return numpy_array(buffer=buf, shape=shape, strides=strides, - dtype=fmt, offset=offset) + struct.pack_into(fmt, buf, j * itemsize, v) + return numpy_array( + buffer=buf, shape=shape, strides=strides, dtype=fmt, offset=offset + ) # ====================================================================== # memoryview casts # ====================================================================== + def cast_items(exporter, fmt, itemsize, shape=None): """Interpret the raw memory of 'exporter' as a list of items with - size 'itemsize'. If shape=None, the new structure is assumed to - be 1-D with n * itemsize = bytelen. If shape is given, the usual - constraint for contiguous arrays prod(shape) * itemsize = bytelen - applies. On success, return (items, shape). If the constraints - cannot be met, return (None, None). If a chunk of bytes is interpreted - as NaN as a result of float conversion, return ('nan', None).""" + size 'itemsize'. If shape=None, the new structure is assumed to + be 1-D with n * itemsize = bytelen. If shape is given, the usual + constraint for contiguous arrays prod(shape) * itemsize = bytelen + applies. On success, return (items, shape). If the constraints + cannot be met, return (None, None). If a chunk of bytes is interpreted + as NaN as a result of float conversion, return ('nan', None).""" bytelen = exporter.nbytes if shape: if prod(shape) * itemsize != bytelen: @@ -672,17 +736,18 @@ def cast_items(exporter, fmt, itemsize, shape=None): return None, shape mem = exporter.tobytes() - byteitems = [mem[i:i+itemsize] for i in range(0, len(mem), itemsize)] + byteitems = [mem[i : i + itemsize] for i in range(0, len(mem), itemsize)] items = [] for v in byteitems: item = struct.unpack(fmt, v)[0] if item != item: - return 'nan', shape + return "nan", shape items.append(item) return (items, shape) if shape != [] else (items[0], shape) + def gencastshapes(): """Generate shapes to test casting.""" for n in range(32): @@ -699,28 +764,33 @@ def gencastshapes(): # Actual tests # ====================================================================== + def genslices(n): """Generate all possible slices for a single dimension.""" - return product(range(-n, n+1), range(-n, n+1), range(-n, n+1)) + return product(range(-n, n + 1), range(-n, n + 1), range(-n, n + 1)) + def genslices_ndim(ndim, shape): """Generate all possible slice tuples for 'shape'.""" iterables = [genslices(shape[n]) for n in range(ndim)] return product(*iterables) + def rslice(n, allow_empty=False): """Generate random slice for a single dimension of length n. - If zero=True, the slices may be empty, otherwise they will - be non-empty.""" + If zero=True, the slices may be empty, otherwise they will + be non-empty.""" minlen = 0 if allow_empty or n == 0 else 1 - slicelen = randrange(minlen, n+1) + slicelen = randrange(minlen, n + 1) return randslice_from_slicelen(slicelen, n) + def rslices(n, allow_empty=False): """Generate random slices for a single dimension.""" for _ in range(5): yield rslice(n, allow_empty) + def rslices_ndim(ndim, shape, iterations=5): """Generate random slice tuples for 'shape'.""" # non-empty slices @@ -730,13 +800,15 @@ def rslices_ndim(ndim, shape, iterations=5): for _ in range(iterations): yield tuple(rslice(shape[n], allow_empty=True) for n in range(ndim)) # invalid slices - yield tuple(slice(0,1,0) for _ in range(ndim)) + yield tuple(slice(0, 1, 0) for _ in range(ndim)) + def rpermutation(iterable, r=None): pool = tuple(iterable) r = len(pool) if r is None else r yield tuple(sample(pool, r)) + def ndarray_print(nd): """Print ndarray for debugging.""" try: @@ -747,12 +819,22 @@ def ndarray_print(nd): offset = nd.offset flags = nd.flags else: - offset = 'unknown' - flags = 'unknown' - print("ndarray(%s, shape=%s, strides=%s, suboffsets=%s, offset=%s, " - "format='%s', itemsize=%s, flags=%s)" % - (x, nd.shape, nd.strides, nd.suboffsets, offset, - nd.format, nd.itemsize, flags)) + offset = "unknown" + flags = "unknown" + print( + "ndarray(%s, shape=%s, strides=%s, suboffsets=%s, offset=%s, " + "format='%s', itemsize=%s, flags=%s)" + % ( + x, + nd.shape, + nd.strides, + nd.suboffsets, + offset, + nd.format, + nd.itemsize, + flags, + ) + ) sys.stdout.flush() @@ -769,25 +851,35 @@ def ndarray_print(nd): permutations = rpermutation -@unittest.skipUnless(struct, 'struct module required for this test.') -@unittest.skipUnless(ndarray, 'ndarray object required for this test') +@unittest.skipUnless(struct, "struct module required for this test.") +@unittest.skipUnless(ndarray, "ndarray object required for this test") class TestBufferProtocol(unittest.TestCase): - def setUp(self): # The suboffsets tests need sizeof(void *). self.sizeof_void_p = get_sizeof_void_p() - def verify(self, result, *, obj, - itemsize, fmt, readonly, - ndim, shape, strides, - lst, sliced=False, cast=False): + def verify( + self, + result, + *, + obj, + itemsize, + fmt, + readonly, + ndim, + shape, + strides, + lst, + sliced=False, + cast=False, + ): # Verify buffer contents against expected values. if shape: - expected_len = prod(shape)*itemsize + expected_len = prod(shape) * itemsize else: - if not fmt: # array has been implicitly cast to unsigned bytes + if not fmt: # array has been implicitly cast to unsigned bytes expected_len = len(lst) - else: # ndim = 0 + else: # ndim = 0 expected_len = itemsize # Reconstruct suboffsets from strides. Support for slicing @@ -801,9 +893,9 @@ def verify(self, result, *, obj, if shape[n] == 0: break if strides[n] <= 0: - suboffset0 += -strides[n] * (shape[n]-1) + suboffset0 += -strides[n] * (shape[n] - 1) - suboffsets = [suboffset0] + [-1 for v in range(ndim-1)] + suboffsets = [suboffset0] + [-1 for v in range(ndim - 1)] # Not correct if slicing has occurred in the first dimension. stride0 = self.sizeof_void_p @@ -826,7 +918,7 @@ def verify(self, result, *, obj, rep = result.tolist() if fmt else result.tobytes() self.assertEqual(rep, lst) - if not fmt: # array has been cast to unsigned bytes, + if not fmt: # array has been cast to unsigned bytes, return # the remaining tests won't work. # PyBuffer_GetPointer() is the definition how to access an item. @@ -835,7 +927,7 @@ def verify(self, result, *, obj, # # Also test tobytes() against the flattened 'lst', with all items # packed to bytes. - if not cast: # casts chop up 'lst' in different ways + if not cast: # casts chop up 'lst' in different ways b = bytearray() buf_err = None for ind in indices(shape): @@ -848,7 +940,7 @@ def verify(self, result, *, obj, x = struct.pack(fmt, item2) b.extend(x) except BufferError: - buf_err = True # re-exporter does not provide full buffer + buf_err = True # re-exporter does not provide full buffer break self.assertEqual(item1, item2) @@ -863,25 +955,28 @@ def verify(self, result, *, obj, # lst := expected multi-dimensional logical representation # flatten(lst) := elements in C-order - ff = fmt if fmt else 'B' + ff = fmt if fmt else "B" flattened = flatten(lst) # Rules for 'A': if the array is already contiguous, return # the array unaltered. Otherwise, return a contiguous 'C' # representation. - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: expected = result - if order == 'F': - if not is_contiguous(result, 'A') or \ - is_contiguous(result, 'C'): + if order == "F": + if not is_contiguous(result, "A") or is_contiguous(result, "C"): # For constructing the ndarray, convert the # flattened logical representation to Fortran order. trans = transpose(flattened, shape) - expected = ndarray(trans, shape=shape, format=ff, - flags=ND_FORTRAN) - else: # 'C', 'A' - if not is_contiguous(result, 'A') or \ - is_contiguous(result, 'F') and order == 'C': + expected = ndarray( + trans, shape=shape, format=ff, flags=ND_FORTRAN + ) + else: # 'C', 'A' + if ( + not is_contiguous(result, "A") + or is_contiguous(result, "F") + and order == "C" + ): # The flattened list is already in C-order. expected = ndarray(flattened, shape=shape, format=ff) @@ -899,10 +994,12 @@ def verify(self, result, *, obj, ### explanation why these tests are valid. # To 'C' - contig = py_buffer_to_contiguous(result, 'C', PyBUF_FULL_RO) + contig = py_buffer_to_contiguous(result, "C", PyBUF_FULL_RO) self.assertEqual(len(contig), nmemb * itemsize) - initlst = [struct.unpack_from(fmt, contig, n*itemsize) - for n in range(nmemb)] + initlst = [ + struct.unpack_from(fmt, contig, n * itemsize) + for n in range(nmemb) + ] if len(initlst[0]) == 1: initlst = [v[0] for v in initlst] @@ -915,43 +1012,46 @@ def verify(self, result, *, obj, contig_bytes = memoryview(result).tobytes(order=None) self.assertEqual(contig_bytes, contig) - contig_bytes = memoryview(result).tobytes(order='C') + contig_bytes = memoryview(result).tobytes(order="C") self.assertEqual(contig_bytes, contig) # To 'F' - contig = py_buffer_to_contiguous(result, 'F', PyBUF_FULL_RO) + contig = py_buffer_to_contiguous(result, "F", PyBUF_FULL_RO) self.assertEqual(len(contig), nmemb * itemsize) - initlst = [struct.unpack_from(fmt, contig, n*itemsize) - for n in range(nmemb)] + initlst = [ + struct.unpack_from(fmt, contig, n * itemsize) + for n in range(nmemb) + ] if len(initlst[0]) == 1: initlst = [v[0] for v in initlst] - y = ndarray(initlst, shape=shape, flags=ro|ND_FORTRAN, - format=fmt) + y = ndarray(initlst, shape=shape, flags=ro | ND_FORTRAN, format=fmt) self.assertEqual(memoryview(y), memoryview(result)) - contig_bytes = memoryview(result).tobytes(order='F') + contig_bytes = memoryview(result).tobytes(order="F") self.assertEqual(contig_bytes, contig) # To 'A' - contig = py_buffer_to_contiguous(result, 'A', PyBUF_FULL_RO) + contig = py_buffer_to_contiguous(result, "A", PyBUF_FULL_RO) self.assertEqual(len(contig), nmemb * itemsize) - initlst = [struct.unpack_from(fmt, contig, n*itemsize) - for n in range(nmemb)] + initlst = [ + struct.unpack_from(fmt, contig, n * itemsize) + for n in range(nmemb) + ] if len(initlst[0]) == 1: initlst = [v[0] for v in initlst] - f = ND_FORTRAN if is_contiguous(result, 'F') else 0 - y = ndarray(initlst, shape=shape, flags=f|ro, format=fmt) + f = ND_FORTRAN if is_contiguous(result, "F") else 0 + y = ndarray(initlst, shape=shape, flags=f | ro, format=fmt) self.assertEqual(memoryview(y), memoryview(result)) - contig_bytes = memoryview(result).tobytes(order='A') + contig_bytes = memoryview(result).tobytes(order="A") self.assertEqual(contig_bytes, contig) if is_memoryview_format(fmt): try: m = memoryview(result) - except BufferError: # re-exporter does not provide full information + except BufferError: # re-exporter does not provide full information return ex = result.obj if isinstance(result, memoryview) else result @@ -983,21 +1083,25 @@ def check_memoryview(m, expected_readonly=readonly): def verify_getbuf(self, orig_ex, ex, req, sliced=False): def match(req, flag): - return ((req&flag) == flag) + return (req & flag) == flag - if (# writable request to read-only exporter - (ex.readonly and match(req, PyBUF_WRITABLE)) or + if ( # writable request to read-only exporter + (ex.readonly and match(req, PyBUF_WRITABLE)) + or # cannot match explicit contiguity request - (match(req, PyBUF_C_CONTIGUOUS) and not ex.c_contiguous) or - (match(req, PyBUF_F_CONTIGUOUS) and not ex.f_contiguous) or - (match(req, PyBUF_ANY_CONTIGUOUS) and not ex.contiguous) or + (match(req, PyBUF_C_CONTIGUOUS) and not ex.c_contiguous) + or (match(req, PyBUF_F_CONTIGUOUS) and not ex.f_contiguous) + or (match(req, PyBUF_ANY_CONTIGUOUS) and not ex.contiguous) + or # buffer needs suboffsets - (not match(req, PyBUF_INDIRECT) and ex.suboffsets) or + (not match(req, PyBUF_INDIRECT) and ex.suboffsets) + or # buffer without strides must be C-contiguous - (not match(req, PyBUF_STRIDES) and not ex.c_contiguous) or + (not match(req, PyBUF_STRIDES) and not ex.c_contiguous) + or # PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT - (not match(req, PyBUF_ND) and match(req, PyBUF_FORMAT))): - + (not match(req, PyBUF_ND) and match(req, PyBUF_FORMAT)) + ): self.assertRaises(BufferError, ndarray, ex, getbuf=req) return @@ -1016,42 +1120,59 @@ def match(req, flag): # itemsize refers to the original itemsize before the cast. # The equality product(shape) * itemsize = len still holds. # The equality calcsize(format) = itemsize does _not_ hold. - fmt = '' - lst = orig_ex.tobytes() # Issue 12834 + fmt = "" + lst = orig_ex.tobytes() # Issue 12834 if not match(req, PyBUF_ND): ndim = 1 shape = orig_ex.shape if match(req, PyBUF_ND) else () strides = orig_ex.strides if match(req, PyBUF_STRIDES) else () nd = ndarray(ex, getbuf=req) - self.verify(nd, obj=ex, - itemsize=itemsize, fmt=fmt, readonly=ro, - ndim=ndim, shape=shape, strides=strides, - lst=lst, sliced=sliced) + self.verify( + nd, + obj=ex, + itemsize=itemsize, + fmt=fmt, + readonly=ro, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + sliced=sliced, + ) - @support.requires_resource('cpu') + @support.requires_resource("cpu") def test_ndarray_getbuf(self): requests = ( # distinct flags - PyBUF_INDIRECT, PyBUF_STRIDES, PyBUF_ND, PyBUF_SIMPLE, - PyBUF_C_CONTIGUOUS, PyBUF_F_CONTIGUOUS, PyBUF_ANY_CONTIGUOUS, + PyBUF_INDIRECT, + PyBUF_STRIDES, + PyBUF_ND, + PyBUF_SIMPLE, + PyBUF_C_CONTIGUOUS, + PyBUF_F_CONTIGUOUS, + PyBUF_ANY_CONTIGUOUS, # compound requests - PyBUF_FULL, PyBUF_FULL_RO, - PyBUF_RECORDS, PyBUF_RECORDS_RO, - PyBUF_STRIDED, PyBUF_STRIDED_RO, - PyBUF_CONTIG, PyBUF_CONTIG_RO, + PyBUF_FULL, + PyBUF_FULL_RO, + PyBUF_RECORDS, + PyBUF_RECORDS_RO, + PyBUF_STRIDED, + PyBUF_STRIDED_RO, + PyBUF_CONTIG, + PyBUF_CONTIG_RO, ) # items and format items_fmt = ( - ([True if x % 2 else False for x in range(12)], '?'), - ([1,2,3,4,5,6,7,8,9,10,11,12], 'b'), - ([1,2,3,4,5,6,7,8,9,10,11,12], 'B'), - ([(2**31-x) if x % 2 else (-2**31+x) for x in range(12)], 'l') + ([True if x % 2 else False for x in range(12)], "?"), + ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], "b"), + ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], "B"), + ([(2**31 - x) if x % 2 else (-(2**31) + x) for x in range(12)], "l"), ) # shape, strides, offset structure = ( ([], [], 0), - ([1,3,1], [], 0), + ([1, 3, 1], [], 0), ([12], [], 0), ([12], [-1], 11), ([6], [2], 0), @@ -1059,16 +1180,19 @@ def test_ndarray_getbuf(self): ([3, 4], [], 0), ([3, 4], [-4, -1], 11), ([2, 2], [4, 1], 4), - ([2, 2], [-4, -1], 8) + ([2, 2], [-4, -1], 8), ) # ndarray creation flags ndflags = ( - 0, ND_WRITABLE, ND_FORTRAN, ND_FORTRAN|ND_WRITABLE, - ND_PIL, ND_PIL|ND_WRITABLE + 0, + ND_WRITABLE, + ND_FORTRAN, + ND_FORTRAN | ND_WRITABLE, + ND_PIL, + ND_PIL | ND_WRITABLE, ) # flags that can actually be used as flags - real_flags = (0, PyBUF_WRITABLE, PyBUF_FORMAT, - PyBUF_WRITABLE|PyBUF_FORMAT) + real_flags = (0, PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_WRITABLE | PyBUF_FORMAT) for items, fmt in items_fmt: itemsize = struct.calcsize(fmt) @@ -1076,15 +1200,20 @@ def test_ndarray_getbuf(self): strides = [v * itemsize for v in strides] offset *= itemsize for flags in ndflags: - - if strides and (flags&ND_FORTRAN): + if strides and (flags & ND_FORTRAN): continue - if not shape and (flags&ND_PIL): + if not shape and (flags & ND_PIL): continue _items = items if shape else items[0] - ex1 = ndarray(_items, format=fmt, flags=flags, - shape=shape, strides=strides, offset=offset) + ex1 = ndarray( + _items, + format=fmt, + flags=flags, + shape=shape, + strides=strides, + offset=offset, + ) ex2 = ex1[::-2] if shape else None m1 = memoryview(ex1) @@ -1097,15 +1226,13 @@ def test_ndarray_getbuf(self): for req in requests: for bits in real_flags: - self.verify_getbuf(ex1, ex1, req|bits) - self.verify_getbuf(ex1, m1, req|bits) + self.verify_getbuf(ex1, ex1, req | bits) + self.verify_getbuf(ex1, m1, req | bits) if ex2: - self.verify_getbuf(ex2, ex2, req|bits, - sliced=True) - self.verify_getbuf(ex2, m2, req|bits, - sliced=True) + self.verify_getbuf(ex2, ex2, req | bits, sliced=True) + self.verify_getbuf(ex2, m2, req | bits, sliced=True) - items = [1,2,3,4,5,6,7,8,9,10,11,12] + items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] # ND_GETBUF_FAIL ex = ndarray(items, shape=[12], flags=ND_GETBUF_FAIL) @@ -1124,16 +1251,16 @@ def test_ndarray_getbuf(self): nd = ndarray(ex, getbuf=PyBUF_SIMPLE) # Issue #22445: New precise contiguity definition. - for shape in [1,12,1], [7,0,7]: + for shape in [1, 12, 1], [7, 0, 7]: for order in 0, ND_FORTRAN: - ex = ndarray(items, shape=shape, flags=order|ND_WRITABLE) - self.assertTrue(is_contiguous(ex, 'F')) - self.assertTrue(is_contiguous(ex, 'C')) + ex = ndarray(items, shape=shape, flags=order | ND_WRITABLE) + self.assertTrue(is_contiguous(ex, "F")) + self.assertTrue(is_contiguous(ex, "C")) for flags in requests: nd = ndarray(ex, getbuf=flags) - self.assertTrue(is_contiguous(nd, 'F')) - self.assertTrue(is_contiguous(nd, 'C')) + self.assertTrue(is_contiguous(nd, "F")) + self.assertTrue(is_contiguous(nd, "C")) def test_ndarray_exceptions(self): nd = ndarray([9], [1]) @@ -1142,67 +1269,67 @@ def test_ndarray_exceptions(self): # Initialization of a new ndarray or mutation of an existing array. for c in (ndarray, nd.push, ndm.push): # Invalid types. - self.assertRaises(TypeError, c, {1,2,3}) - self.assertRaises(TypeError, c, [1,2,'3']) - self.assertRaises(TypeError, c, [1,2,(3,4)]) - self.assertRaises(TypeError, c, [1,2,3], shape={3}) - self.assertRaises(TypeError, c, [1,2,3], shape=[3], strides={1}) - self.assertRaises(TypeError, c, [1,2,3], shape=[3], offset=[]) + self.assertRaises(TypeError, c, {1, 2, 3}) + self.assertRaises(TypeError, c, [1, 2, "3"]) + self.assertRaises(TypeError, c, [1, 2, (3, 4)]) + self.assertRaises(TypeError, c, [1, 2, 3], shape={3}) + self.assertRaises(TypeError, c, [1, 2, 3], shape=[3], strides={1}) + self.assertRaises(TypeError, c, [1, 2, 3], shape=[3], offset=[]) self.assertRaises(TypeError, c, [1], shape=[1], format={}) self.assertRaises(TypeError, c, [1], shape=[1], flags={}) self.assertRaises(TypeError, c, [1], shape=[1], getbuf={}) # ND_FORTRAN flag is only valid without strides. - self.assertRaises(TypeError, c, [1], shape=[1], strides=[1], - flags=ND_FORTRAN) + self.assertRaises( + TypeError, c, [1], shape=[1], strides=[1], flags=ND_FORTRAN + ) # ND_PIL flag is only valid with ndim > 0. self.assertRaises(TypeError, c, [1], shape=[], flags=ND_PIL) # Invalid items. self.assertRaises(ValueError, c, [], shape=[1]) - self.assertRaises(ValueError, c, ['XXX'], shape=[1], format="L") + self.assertRaises(ValueError, c, ["XXX"], shape=[1], format="L") # Invalid combination of items and format. self.assertRaises(struct.error, c, [1000], shape=[1], format="B") - self.assertRaises(ValueError, c, [1,(2,3)], shape=[2], format="B") - self.assertRaises(ValueError, c, [1,2,3], shape=[3], format="QL") + self.assertRaises(ValueError, c, [1, (2, 3)], shape=[2], format="B") + self.assertRaises(ValueError, c, [1, 2, 3], shape=[3], format="QL") # Invalid ndim. - n = ND_MAX_NDIM+1 - self.assertRaises(ValueError, c, [1]*n, shape=[1]*n) + n = ND_MAX_NDIM + 1 + self.assertRaises(ValueError, c, [1] * n, shape=[1] * n) # Invalid shape. self.assertRaises(ValueError, c, [1], shape=[-1]) - self.assertRaises(ValueError, c, [1,2,3], shape=['3']) + self.assertRaises(ValueError, c, [1, 2, 3], shape=["3"]) self.assertRaises(OverflowError, c, [1], shape=[2**128]) # prod(shape) * itemsize != len(items) - self.assertRaises(ValueError, c, [1,2,3,4,5], shape=[2,2], offset=3) + self.assertRaises(ValueError, c, [1, 2, 3, 4, 5], shape=[2, 2], offset=3) # Invalid strides. - self.assertRaises(ValueError, c, [1,2,3], shape=[3], strides=['1']) - self.assertRaises(OverflowError, c, [1], shape=[1], - strides=[2**128]) + self.assertRaises(ValueError, c, [1, 2, 3], shape=[3], strides=["1"]) + self.assertRaises(OverflowError, c, [1], shape=[1], strides=[2**128]) # Invalid combination of strides and shape. - self.assertRaises(ValueError, c, [1,2], shape=[2,1], strides=[1]) + self.assertRaises(ValueError, c, [1, 2], shape=[2, 1], strides=[1]) # Invalid combination of strides and format. - self.assertRaises(ValueError, c, [1,2,3,4], shape=[2], strides=[3], - format="L") + self.assertRaises( + ValueError, c, [1, 2, 3, 4], shape=[2], strides=[3], format="L" + ) # Invalid offset. - self.assertRaises(ValueError, c, [1,2,3], shape=[3], offset=4) - self.assertRaises(ValueError, c, [1,2,3], shape=[1], offset=3, - format="L") + self.assertRaises(ValueError, c, [1, 2, 3], shape=[3], offset=4) + self.assertRaises(ValueError, c, [1, 2, 3], shape=[1], offset=3, format="L") # Invalid format. - self.assertRaises(ValueError, c, [1,2,3], shape=[3], format="") - self.assertRaises(struct.error, c, [(1,2,3)], shape=[1], - format="@#$") + self.assertRaises(ValueError, c, [1, 2, 3], shape=[3], format="") + self.assertRaises(struct.error, c, [(1, 2, 3)], shape=[1], format="@#$") # Striding out of the memory bounds. - items = [1,2,3,4,5,6,7,8,9,10] - self.assertRaises(ValueError, c, items, shape=[2,3], - strides=[-3, -2], offset=5) + items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + self.assertRaises( + ValueError, c, items, shape=[2, 3], strides=[-3, -2], offset=5 + ) # Constructing consumer: format argument invalid. self.assertRaises(TypeError, c, bytearray(), format="Q") @@ -1213,16 +1340,15 @@ def test_ndarray_exceptions(self): # Shape argument is mandatory for original base objects. self.assertRaises(TypeError, c, [1]) - # PyBUF_WRITABLE request to read-only provider. - self.assertRaises(BufferError, ndarray, b'123', getbuf=PyBUF_WRITABLE) + self.assertRaises(BufferError, ndarray, b"123", getbuf=PyBUF_WRITABLE) # ND_VAREXPORT can only be specified during construction. nd = ndarray([9], [1], flags=ND_VAREXPORT) self.assertRaises(ValueError, nd.push, [1], [1], flags=ND_VAREXPORT) # Invalid operation for consumers: push/pop - nd = ndarray(b'123') + nd = ndarray(b"123") self.assertRaises(BufferError, nd.push, [1], [1]) self.assertRaises(BufferError, nd.pop) @@ -1240,46 +1366,45 @@ def test_ndarray_exceptions(self): del nd # get_pointer() - self.assertRaises(TypeError, get_pointer, {}, [1,2,3]) - self.assertRaises(TypeError, get_pointer, b'123', {}) + self.assertRaises(TypeError, get_pointer, {}, [1, 2, 3]) + self.assertRaises(TypeError, get_pointer, b"123", {}) - nd = ndarray(list(range(100)), shape=[1]*100) + nd = ndarray(list(range(100)), shape=[1] * 100) self.assertRaises(ValueError, get_pointer, nd, [5]) - nd = ndarray(list(range(12)), shape=[3,4]) - self.assertRaises(ValueError, get_pointer, nd, [2,3,4]) - self.assertRaises(ValueError, get_pointer, nd, [3,3]) - self.assertRaises(ValueError, get_pointer, nd, [-3,3]) - self.assertRaises(OverflowError, get_pointer, nd, [1<<64,3]) + nd = ndarray(list(range(12)), shape=[3, 4]) + self.assertRaises(ValueError, get_pointer, nd, [2, 3, 4]) + self.assertRaises(ValueError, get_pointer, nd, [3, 3]) + self.assertRaises(ValueError, get_pointer, nd, [-3, 3]) + self.assertRaises(OverflowError, get_pointer, nd, [1 << 64, 3]) # tolist() needs format - ex = ndarray([1,2,3], shape=[3], format='L') + ex = ndarray([1, 2, 3], shape=[3], format="L") nd = ndarray(ex, getbuf=PyBUF_SIMPLE) self.assertRaises(ValueError, nd.tolist) # memoryview_from_buffer() - ex1 = ndarray([1,2,3], shape=[3], format='L') + ex1 = ndarray([1, 2, 3], shape=[3], format="L") ex2 = ndarray(ex1) nd = ndarray(ex2) self.assertRaises(TypeError, nd.memoryview_from_buffer) - nd = ndarray([(1,)*200], shape=[1], format='L'*200) + nd = ndarray([(1,) * 200], shape=[1], format="L" * 200) self.assertRaises(TypeError, nd.memoryview_from_buffer) n = ND_MAX_NDIM - nd = ndarray(list(range(n)), shape=[1]*n) + nd = ndarray(list(range(n)), shape=[1] * n) self.assertRaises(ValueError, nd.memoryview_from_buffer) # get_contiguous() nd = ndarray([1], shape=[1]) self.assertRaises(TypeError, get_contiguous, 1, 2, 3, 4, 5) - self.assertRaises(TypeError, get_contiguous, nd, "xyz", 'C') - self.assertRaises(OverflowError, get_contiguous, nd, 2**64, 'C') + self.assertRaises(TypeError, get_contiguous, nd, "xyz", "C") + self.assertRaises(OverflowError, get_contiguous, nd, 2**64, "C") self.assertRaises(TypeError, get_contiguous, nd, PyBUF_READ, 961) - self.assertRaises(UnicodeEncodeError, get_contiguous, nd, PyBUF_READ, - '\u2007') - self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'Z') - self.assertRaises(ValueError, get_contiguous, nd, 255, 'A') + self.assertRaises(UnicodeEncodeError, get_contiguous, nd, PyBUF_READ, "\u2007") + self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, "Z") + self.assertRaises(ValueError, get_contiguous, nd, 255, "A") # cmp_contig() nd = ndarray([1], shape=[1]) @@ -1290,17 +1415,17 @@ def test_ndarray_exceptions(self): # is_contiguous() nd = ndarray([1], shape=[1]) self.assertRaises(TypeError, is_contiguous, 1, 2, 3, 4, 5) - self.assertRaises(TypeError, is_contiguous, {}, 'A') + self.assertRaises(TypeError, is_contiguous, {}, "A") self.assertRaises(TypeError, is_contiguous, nd, 201) def test_ndarray_linked_list(self): for perm in permutations(range(5)): - m = [0]*5 - nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT) + m = [0] * 5 + nd = ndarray([1, 2, 3], shape=[3], flags=ND_VAREXPORT) m[0] = memoryview(nd) for i in range(1, 5): - nd.push([1,2,3], shape=[3]) + nd.push([1, 2, 3], shape=[3]) m[i] = memoryview(nd) for i in range(5): @@ -1314,22 +1439,36 @@ def test_ndarray_format_scalar(self): for fmt, scalar, _ in iter_format(0): itemsize = struct.calcsize(fmt) nd = ndarray(scalar, shape=(), format=fmt) - self.verify(nd, obj=None, - itemsize=itemsize, fmt=fmt, readonly=True, - ndim=0, shape=(), strides=(), - lst=scalar) + self.verify( + nd, + obj=None, + itemsize=itemsize, + fmt=fmt, + readonly=True, + ndim=0, + shape=(), + strides=(), + lst=scalar, + ) def test_ndarray_format_shape(self): # ndim = 1, shape = [n] - nitems = randrange(1, 10) + nitems = randrange(1, 10) for fmt, items, _ in iter_format(nitems): itemsize = struct.calcsize(fmt) for flags in (0, ND_PIL): nd = ndarray(items, shape=[nitems], format=fmt, flags=flags) - self.verify(nd, obj=None, - itemsize=itemsize, fmt=fmt, readonly=True, - ndim=1, shape=(nitems,), strides=(itemsize,), - lst=items) + self.verify( + nd, + obj=None, + itemsize=itemsize, + fmt=fmt, + readonly=True, + ndim=1, + shape=(nitems,), + strides=(itemsize,), + lst=items, + ) def test_ndarray_format_strides(self): # ndim = 1, strides @@ -1341,21 +1480,34 @@ def test_ndarray_format_strides(self): continue shape = [len(items[::step])] - strides = [step*itemsize] - offset = itemsize*(nitems-1) if step < 0 else 0 + strides = [step * itemsize] + offset = itemsize * (nitems - 1) if step < 0 else 0 for flags in (0, ND_PIL): - nd = ndarray(items, shape=shape, strides=strides, - format=fmt, offset=offset, flags=flags) - self.verify(nd, obj=None, - itemsize=itemsize, fmt=fmt, readonly=True, - ndim=1, shape=shape, strides=strides, - lst=items[::step]) + nd = ndarray( + items, + shape=shape, + strides=strides, + format=fmt, + offset=offset, + flags=flags, + ) + self.verify( + nd, + obj=None, + itemsize=itemsize, + fmt=fmt, + readonly=True, + ndim=1, + shape=shape, + strides=strides, + lst=items[::step], + ) def test_ndarray_fortran(self): - items = [1,2,3,4,5,6,7,8,9,10,11,12] + items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] ex = ndarray(items, shape=(3, 4), strides=(1, 3)) - nd = ndarray(ex, getbuf=PyBUF_F_CONTIGUOUS|PyBUF_FORMAT) + nd = ndarray(ex, getbuf=PyBUF_F_CONTIGUOUS | PyBUF_FORMAT) self.assertEqual(nd.tolist(), farray(items, (3, 4))) def test_ndarray_multidim(self): @@ -1363,7 +1515,6 @@ def test_ndarray_multidim(self): shape_t = [randrange(2, 10) for _ in range(ndim)] nitems = prod(shape_t) for shape in permutations(shape_t): - fmt, items, _ = randitems(nitems) itemsize = struct.calcsize(fmt) @@ -1374,34 +1525,56 @@ def test_ndarray_multidim(self): # C array nd = ndarray(items, shape=shape, format=fmt, flags=flags) - strides = strides_from_shape(ndim, shape, itemsize, 'C') + strides = strides_from_shape(ndim, shape, itemsize, "C") lst = carray(items, shape) - self.verify(nd, obj=None, - itemsize=itemsize, fmt=fmt, readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst) + self.verify( + nd, + obj=None, + itemsize=itemsize, + fmt=fmt, + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + ) if is_memoryview_format(fmt): # memoryview: reconstruct strides ex = ndarray(items, shape=shape, format=fmt) - nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT) + nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO | PyBUF_FORMAT) self.assertTrue(nd.strides == ()) mv = nd.memoryview_from_buffer() - self.verify(mv, obj=None, - itemsize=itemsize, fmt=fmt, readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst) + self.verify( + mv, + obj=None, + itemsize=itemsize, + fmt=fmt, + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + ) # Fortran array - nd = ndarray(items, shape=shape, format=fmt, - flags=flags|ND_FORTRAN) + nd = ndarray( + items, shape=shape, format=fmt, flags=flags | ND_FORTRAN + ) - strides = strides_from_shape(ndim, shape, itemsize, 'F') + strides = strides_from_shape(ndim, shape, itemsize, "F") lst = farray(items, shape) - self.verify(nd, obj=None, - itemsize=itemsize, fmt=fmt, readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst) + self.verify( + nd, + obj=None, + itemsize=itemsize, + fmt=fmt, + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + ) def test_ndarray_index_invalid(self): # not writable @@ -1420,15 +1593,15 @@ def test_ndarray_index_invalid(self): # overflow nd = ndarray([1], shape=[1], flags=ND_WRITABLE) - self.assertRaises(OverflowError, nd.__getitem__, 1<<64) - self.assertRaises(OverflowError, nd.__setitem__, 1<<64, 8) + self.assertRaises(OverflowError, nd.__getitem__, 1 << 64) + self.assertRaises(OverflowError, nd.__setitem__, 1 << 64, 8) mv = memoryview(nd) self.assertEqual(mv, nd) - self.assertRaises(IndexError, mv.__getitem__, 1<<64) - self.assertRaises(IndexError, mv.__setitem__, 1<<64, 8) + self.assertRaises(IndexError, mv.__getitem__, 1 << 64) + self.assertRaises(IndexError, mv.__setitem__, 1 << 64, 8) # format - items = [1,2,3,4,5,6,7,8] + items = [1, 2, 3, 4, 5, 6, 7, 8] nd = ndarray(items, shape=[len(items)], format="B", flags=ND_WRITABLE) self.assertRaises(struct.error, nd.__setitem__, 2, 300) self.assertRaises(ValueError, nd.__setitem__, 1, (100, 200)) @@ -1437,10 +1610,10 @@ def test_ndarray_index_invalid(self): self.assertRaises(ValueError, mv.__setitem__, 2, 300) self.assertRaises(TypeError, mv.__setitem__, 1, (100, 200)) - items = [(1,2), (3,4), (5,6)] + items = [(1, 2), (3, 4), (5, 6)] nd = ndarray(items, shape=[len(items)], format="LQ", flags=ND_WRITABLE) self.assertRaises(ValueError, nd.__setitem__, 2, 300) - self.assertRaises(struct.error, nd.__setitem__, 1, (b'\x001', 200)) + self.assertRaises(struct.error, nd.__setitem__, 1, (b"\x001", 200)) def test_ndarray_index_scalar(self): # scalar @@ -1448,11 +1621,15 @@ def test_ndarray_index_scalar(self): mv = memoryview(nd) self.assertEqual(mv, nd) - x = nd[()]; self.assertEqual(x, 1) - x = nd[...]; self.assertEqual(x.tolist(), nd.tolist()) + x = nd[()] + self.assertEqual(x, 1) + x = nd[...] + self.assertEqual(x.tolist(), nd.tolist()) - x = mv[()]; self.assertEqual(x, 1) - x = mv[...]; self.assertEqual(x.tolist(), nd.tolist()) + x = mv[()] + self.assertEqual(x, 1) + x = mv[...] + self.assertEqual(x.tolist(), nd.tolist()) self.assertRaises(TypeError, nd.__getitem__, 0) self.assertRaises(TypeError, mv.__getitem__, 0) @@ -1462,20 +1639,24 @@ def test_ndarray_index_scalar(self): self.assertEqual(nd.tolist(), 1) self.assertEqual(mv.tolist(), 1) - nd[()] = 9; self.assertEqual(nd.tolist(), 9) - mv[()] = 9; self.assertEqual(mv.tolist(), 9) + nd[()] = 9 + self.assertEqual(nd.tolist(), 9) + mv[()] = 9 + self.assertEqual(mv.tolist(), 9) - nd[...] = 5; self.assertEqual(nd.tolist(), 5) - mv[...] = 5; self.assertEqual(mv.tolist(), 5) + nd[...] = 5 + self.assertEqual(nd.tolist(), 5) + mv[...] = 5 + self.assertEqual(mv.tolist(), 5) def test_ndarray_index_null_strides(self): - ex = ndarray(list(range(2*4)), shape=[2, 4], flags=ND_WRITABLE) + ex = ndarray(list(range(2 * 4)), shape=[2, 4], flags=ND_WRITABLE) nd = ndarray(ex, getbuf=PyBUF_CONTIG) # Sub-views are only possible for full exporters. self.assertRaises(BufferError, nd.__getitem__, 1) # Same for slices. - self.assertRaises(BufferError, nd.__getitem__, slice(3,5,1)) + self.assertRaises(BufferError, nd.__getitem__, slice(3, 5, 1)) def test_ndarray_index_getitem_single(self): # getitem @@ -1499,7 +1680,7 @@ def test_ndarray_index_getitem_single(self): # getitem with null strides for fmt, items, _ in iter_format(5): ex = ndarray(items, shape=[5], flags=ND_WRITABLE, format=fmt) - nd = ndarray(ex, getbuf=PyBUF_CONTIG|PyBUF_FORMAT) + nd = ndarray(ex, getbuf=PyBUF_CONTIG | PyBUF_FORMAT) for i in range(-5, 5): self.assertEqual(nd[i], items[i]) @@ -1511,14 +1692,14 @@ def test_ndarray_index_getitem_single(self): self.assertEqual(mv[i], items[i]) # getitem with null format - items = [1,2,3,4,5] + items = [1, 2, 3, 4, 5] ex = ndarray(items, shape=[5]) nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO) for i in range(-5, 5): self.assertEqual(nd[i], items[i]) # getitem with null shape/strides/format - items = [1,2,3,4,5] + items = [1, 2, 3, 4, 5] ex = ndarray(items, shape=[5]) nd = ndarray(ex, getbuf=PyBUF_SIMPLE) @@ -1551,13 +1732,12 @@ def test_ndarray_index_setitem_single(self): self.assertRaises(IndexError, mv.__setitem__, -6, single_item) self.assertRaises(IndexError, mv.__setitem__, 5, single_item) - # assign single value: lobject = robject for fmt, items, single_item in iter_format(5): nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE) for i in range(-5, 4): - items[i] = items[i+1] - nd[i] = nd[i+1] + items[i] = items[i + 1] + nd[i] = nd[i + 1] self.assertEqual(nd.tolist(), items) if not is_memoryview_format(fmt): @@ -1567,15 +1747,14 @@ def test_ndarray_index_setitem_single(self): mv = memoryview(nd) self.assertEqual(mv, nd) for i in range(-5, 4): - items[i] = items[i+1] - mv[i] = mv[i+1] + items[i] = items[i + 1] + mv[i] = mv[i + 1] self.assertEqual(mv.tolist(), items) def test_ndarray_index_getitem_multidim(self): shape_t = (2, 3, 5) nitems = prod(shape_t) for shape in permutations(shape_t): - fmt, items, _ = randitems(nitems) for flags in (0, ND_PIL): @@ -1591,8 +1770,7 @@ def test_ndarray_index_getitem_multidim(self): self.assertEqual(lst[i][j][k], nd[i][j][k]) # Fortran array - nd = ndarray(items, shape=shape, format=fmt, - flags=flags|ND_FORTRAN) + nd = ndarray(items, shape=shape, format=fmt, flags=flags | ND_FORTRAN) lst = farray(items, shape) for i in range(-shape[0], shape[0]): @@ -1622,40 +1800,39 @@ def test_ndarray_sequence(self): self.assertTrue(v in mv) def test_ndarray_slice_invalid(self): - items = [1,2,3,4,5,6,7,8] + items = [1, 2, 3, 4, 5, 6, 7, 8] # rvalue is not an exporter xl = ndarray(items, shape=[8], flags=ND_WRITABLE) ml = memoryview(xl) - self.assertRaises(TypeError, xl.__setitem__, slice(0,8,1), items) - self.assertRaises(TypeError, ml.__setitem__, slice(0,8,1), items) + self.assertRaises(TypeError, xl.__setitem__, slice(0, 8, 1), items) + self.assertRaises(TypeError, ml.__setitem__, slice(0, 8, 1), items) # rvalue is not a full exporter xl = ndarray(items, shape=[8], flags=ND_WRITABLE) ex = ndarray(items, shape=[8], flags=ND_WRITABLE) xr = ndarray(ex, getbuf=PyBUF_ND) - self.assertRaises(BufferError, xl.__setitem__, slice(0,8,1), xr) + self.assertRaises(BufferError, xl.__setitem__, slice(0, 8, 1), xr) # zero step nd = ndarray(items, shape=[8], format="L", flags=ND_WRITABLE) mv = memoryview(nd) - self.assertRaises(ValueError, nd.__getitem__, slice(0,1,0)) - self.assertRaises(ValueError, mv.__getitem__, slice(0,1,0)) + self.assertRaises(ValueError, nd.__getitem__, slice(0, 1, 0)) + self.assertRaises(ValueError, mv.__getitem__, slice(0, 1, 0)) - nd = ndarray(items, shape=[2,4], format="L", flags=ND_WRITABLE) + nd = ndarray(items, shape=[2, 4], format="L", flags=ND_WRITABLE) mv = memoryview(nd) - self.assertRaises(ValueError, nd.__getitem__, - (slice(0,1,1), slice(0,1,0))) - self.assertRaises(ValueError, nd.__getitem__, - (slice(0,1,0), slice(0,1,1))) + self.assertRaises(ValueError, nd.__getitem__, (slice(0, 1, 1), slice(0, 1, 0))) + self.assertRaises(ValueError, nd.__getitem__, (slice(0, 1, 0), slice(0, 1, 1))) self.assertRaises(TypeError, nd.__getitem__, "@%$") - self.assertRaises(TypeError, nd.__getitem__, ("@%$", slice(0,1,1))) - self.assertRaises(TypeError, nd.__getitem__, (slice(0,1,1), {})) + self.assertRaises(TypeError, nd.__getitem__, ("@%$", slice(0, 1, 1))) + self.assertRaises(TypeError, nd.__getitem__, (slice(0, 1, 1), {})) # memoryview: not implemented - self.assertRaises(NotImplementedError, mv.__getitem__, - (slice(0,1,1), slice(0,1,0))) + self.assertRaises( + NotImplementedError, mv.__getitem__, (slice(0, 1, 1), slice(0, 1, 0)) + ) self.assertRaises(TypeError, mv.__getitem__, "@%$") # differing format @@ -1663,9 +1840,9 @@ def test_ndarray_slice_invalid(self): xr = ndarray(items, shape=[8], format="b") ml = memoryview(xl) mr = memoryview(xr) - self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8]) + self.assertRaises(ValueError, xl.__setitem__, slice(0, 1, 1), xr[7:8]) self.assertEqual(xl.tolist(), items) - self.assertRaises(ValueError, ml.__setitem__, slice(0,1,1), mr[7:8]) + self.assertRaises(ValueError, ml.__setitem__, slice(0, 1, 1), mr[7:8]) self.assertEqual(ml.tolist(), items) # differing itemsize @@ -1673,9 +1850,9 @@ def test_ndarray_slice_invalid(self): yr = ndarray(items, shape=[8], format="L") ml = memoryview(xl) mr = memoryview(xr) - self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8]) + self.assertRaises(ValueError, xl.__setitem__, slice(0, 1, 1), xr[7:8]) self.assertEqual(xl.tolist(), items) - self.assertRaises(ValueError, ml.__setitem__, slice(0,1,1), mr[7:8]) + self.assertRaises(ValueError, ml.__setitem__, slice(0, 1, 1), mr[7:8]) self.assertEqual(ml.tolist(), items) # differing ndim @@ -1683,25 +1860,24 @@ def test_ndarray_slice_invalid(self): xr = ndarray(items, shape=[8], format="b") ml = memoryview(xl) mr = memoryview(xr) - self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8]) - self.assertEqual(xl.tolist(), [[1,2,3,4], [5,6,7,8]]) - self.assertRaises(NotImplementedError, ml.__setitem__, slice(0,1,1), - mr[7:8]) + self.assertRaises(ValueError, xl.__setitem__, slice(0, 1, 1), xr[7:8]) + self.assertEqual(xl.tolist(), [[1, 2, 3, 4], [5, 6, 7, 8]]) + self.assertRaises(NotImplementedError, ml.__setitem__, slice(0, 1, 1), mr[7:8]) # differing shape xl = ndarray(items, shape=[8], format="b", flags=ND_WRITABLE) xr = ndarray(items, shape=[8], format="b") ml = memoryview(xl) mr = memoryview(xr) - self.assertRaises(ValueError, xl.__setitem__, slice(0,2,1), xr[7:8]) + self.assertRaises(ValueError, xl.__setitem__, slice(0, 2, 1), xr[7:8]) self.assertEqual(xl.tolist(), items) - self.assertRaises(ValueError, ml.__setitem__, slice(0,2,1), mr[7:8]) + self.assertRaises(ValueError, ml.__setitem__, slice(0, 2, 1), mr[7:8]) self.assertEqual(ml.tolist(), items) # _testbuffer.c module functions - self.assertRaises(TypeError, slice_indices, slice(0,1,2), {}) + self.assertRaises(TypeError, slice_indices, slice(0, 1, 2), {}) self.assertRaises(TypeError, slice_indices, "###########", 1) - self.assertRaises(ValueError, slice_indices, slice(0,1,0), 4) + self.assertRaises(ValueError, slice_indices, slice(0, 1, 0), 4) x = ndarray(items, shape=[8], format="b", flags=ND_PIL) self.assertRaises(TypeError, x.add_suboffsets) @@ -1711,7 +1887,7 @@ def test_ndarray_slice_invalid(self): self.assertRaises(TypeError, x.add_suboffsets) def test_ndarray_slice_zero_shape(self): - items = [1,2,3,4,5,6,7,8,9,10,11,12] + items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] x = ndarray(items, shape=[12], format="L", flags=ND_WRITABLE) y = ndarray(items, shape=[12], format="L") @@ -1735,7 +1911,6 @@ def test_ndarray_slice_multidim(self): ndim = len(shape_t) nitems = prod(shape_t) for shape in permutations(shape_t): - fmt, items, _ = randitems(nitems) itemsize = struct.calcsize(fmt) @@ -1744,7 +1919,6 @@ def test_ndarray_slice_multidim(self): lst = carray(items, shape) for slices in rslices_ndim(ndim, shape): - listerr = None try: sliced = multislice(lst, slices) @@ -1767,7 +1941,6 @@ def test_ndarray_slice_redundant_suboffsets(self): ndim = len(shape_t) nitems = prod(shape_t) for shape in permutations(shape_t): - fmt, items, _ = randitems(nitems) itemsize = struct.calcsize(fmt) @@ -1779,7 +1952,6 @@ def test_ndarray_slice_redundant_suboffsets(self): lst = carray(items, shape) for slices in rslices_ndim(ndim, shape): - listerr = None try: sliced = multislice(lst, slices) @@ -1802,8 +1974,7 @@ def test_ndarray_slice_assign_single(self): for lslice in genslices(5): for rslice in genslices(5): for flags in (0, ND_PIL): - - f = flags|ND_WRITABLE + f = flags | ND_WRITABLE nd = ndarray(items, shape=[5], format=fmt, flags=f) ex = ndarray(items, shape=[5], format=fmt, flags=f) mv = memoryview(ex) @@ -1825,7 +1996,7 @@ def test_ndarray_slice_assign_single(self): except Exception as e: nderr = e.__class__ - if diff_structure: # ndarray cannot change shape + if diff_structure: # ndarray cannot change shape self.assertIs(nderr, ValueError) else: self.assertEqual(nd.tolist(), lst) @@ -1840,31 +2011,38 @@ def test_ndarray_slice_assign_single(self): except Exception as e: mverr = e.__class__ - if diff_structure: # memoryview cannot change shape + if diff_structure: # memoryview cannot change shape self.assertIs(mverr, ValueError) else: self.assertEqual(mv.tolist(), lst) self.assertEqual(mv, nd) self.assertIs(mverr, lsterr) - self.verify(mv, obj=ex, - itemsize=nd.itemsize, fmt=fmt, readonly=False, - ndim=nd.ndim, shape=nd.shape, strides=nd.strides, - lst=nd.tolist()) + self.verify( + mv, + obj=ex, + itemsize=nd.itemsize, + fmt=fmt, + readonly=False, + ndim=nd.ndim, + shape=nd.shape, + strides=nd.strides, + lst=nd.tolist(), + ) def test_ndarray_slice_assign_multidim(self): shape_t = (2, 3, 5) ndim = len(shape_t) nitems = prod(shape_t) for shape in permutations(shape_t): - fmt, items, _ = randitems(nitems) for flags in (0, ND_PIL): for _ in range(ITERATIONS): lslices, rslices = randslice_from_shape(ndim, shape) - nd = ndarray(items, shape=shape, format=fmt, - flags=flags|ND_WRITABLE) + nd = ndarray( + items, shape=shape, format=fmt, flags=flags | ND_WRITABLE + ) lst = carray(items, shape) listerr = None @@ -1887,11 +2065,10 @@ def test_ndarray_slice_assign_multidim(self): def test_ndarray_random(self): # construction of valid arrays for _ in range(ITERATIONS): - for fmt in fmtdict['@']: + for fmt in fmtdict["@"]: itemsize = struct.calcsize(fmt) - t = rand_structure(itemsize, True, maxdim=MAXDIM, - maxshape=MAXSHAPE) + t = rand_structure(itemsize, True, maxdim=MAXDIM, maxshape=MAXSHAPE) self.assertTrue(verify_structure(*t)) items = randitems_from_structure(fmt, t) @@ -1918,21 +2095,27 @@ def test_ndarray_random(self): if numpy_array: shape = t[3] if 0 in shape: - continue # http://projects.scipy.org/numpy/ticket/1910 + continue # http://projects.scipy.org/numpy/ticket/1910 z = numpy_array_from_structure(items, fmt, t) - self.verify(x, obj=None, - itemsize=z.itemsize, fmt=fmt, readonly=False, - ndim=z.ndim, shape=z.shape, strides=z.strides, - lst=z.tolist()) + self.verify( + x, + obj=None, + itemsize=z.itemsize, + fmt=fmt, + readonly=False, + ndim=z.ndim, + shape=z.shape, + strides=z.strides, + lst=z.tolist(), + ) def test_ndarray_random_invalid(self): # exceptions during construction of invalid arrays for _ in range(ITERATIONS): - for fmt in fmtdict['@']: + for fmt in fmtdict["@"]: itemsize = struct.calcsize(fmt) - t = rand_structure(itemsize, False, maxdim=MAXDIM, - maxshape=MAXSHAPE) + t = rand_structure(itemsize, False, maxdim=MAXDIM, maxshape=MAXSHAPE) self.assertFalse(verify_structure(*t)) items = randitems_from_structure(fmt, t) @@ -1950,17 +2133,18 @@ def test_ndarray_random_invalid(self): except Exception as e: numpy_err = e.__class__ - if 0: # http://projects.scipy.org/numpy/ticket/1910 + if 0: # http://projects.scipy.org/numpy/ticket/1910 self.assertTrue(numpy_err) def test_ndarray_random_slice_assign(self): # valid slice assignments for _ in range(ITERATIONS): - for fmt in fmtdict['@']: + for fmt in fmtdict["@"]: itemsize = struct.calcsize(fmt) - lshape, rshape, lslices, rslices = \ - rand_aligned_slices(maxdim=MAXDIM, maxshape=MAXSHAPE) + lshape, rshape, lslices, rslices = rand_aligned_slices( + maxdim=MAXDIM, maxshape=MAXSHAPE + ) tl = rand_structure(itemsize, True, shape=lshape) tr = rand_structure(itemsize, True, shape=rshape) self.assertTrue(verify_structure(*tl)) @@ -1996,7 +2180,7 @@ def test_ndarray_random_slice_assign(self): if numpy_array: if 0 in lshape or 0 in rshape: - continue # http://projects.scipy.org/numpy/ticket/1910 + continue # http://projects.scipy.org/numpy/ticket/1910 zl = numpy_array_from_structure(litems, fmt, tl) zr = numpy_array_from_structure(ritems, fmt, tr) @@ -2005,20 +2189,34 @@ def test_ndarray_random_slice_assign(self): if not is_overlapping(tl) and not is_overlapping(tr): # Slice assignment of overlapping structures # is undefined in NumPy. - self.verify(xl, obj=None, - itemsize=zl.itemsize, fmt=fmt, readonly=False, - ndim=zl.ndim, shape=zl.shape, - strides=zl.strides, lst=zl.tolist()) - - self.verify(xr, obj=None, - itemsize=zr.itemsize, fmt=fmt, readonly=False, - ndim=zr.ndim, shape=zr.shape, - strides=zr.strides, lst=zr.tolist()) + self.verify( + xl, + obj=None, + itemsize=zl.itemsize, + fmt=fmt, + readonly=False, + ndim=zl.ndim, + shape=zl.shape, + strides=zl.strides, + lst=zl.tolist(), + ) + + self.verify( + xr, + obj=None, + itemsize=zr.itemsize, + fmt=fmt, + readonly=False, + ndim=zr.ndim, + shape=zr.shape, + strides=zr.strides, + lst=zr.tolist(), + ) def test_ndarray_re_export(self): - items = [1,2,3,4,5,6,7,8,9,10,11,12] + items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - nd = ndarray(items, shape=[3,4], flags=ND_PIL) + nd = ndarray(items, shape=[3, 4], flags=ND_PIL) ex = ndarray(nd) self.assertTrue(ex.flags & ND_PIL) @@ -2031,21 +2229,20 @@ def test_ndarray_re_export(self): def test_ndarray_zero_shape(self): # zeros in shape for flags in (0, ND_PIL): - nd = ndarray([1,2,3], shape=[0], flags=flags) + nd = ndarray([1, 2, 3], shape=[0], flags=flags) mv = memoryview(nd) self.assertEqual(mv, nd) self.assertEqual(nd.tolist(), []) self.assertEqual(mv.tolist(), []) - nd = ndarray([1,2,3], shape=[0,3,3], flags=flags) + nd = ndarray([1, 2, 3], shape=[0, 3, 3], flags=flags) self.assertEqual(nd.tolist(), []) - nd = ndarray([1,2,3], shape=[3,0,3], flags=flags) + nd = ndarray([1, 2, 3], shape=[3, 0, 3], flags=flags) self.assertEqual(nd.tolist(), [[], [], []]) - nd = ndarray([1,2,3], shape=[3,3,0], flags=flags) - self.assertEqual(nd.tolist(), - [[[], [], []], [[], [], []], [[], [], []]]) + nd = ndarray([1, 2, 3], shape=[3, 3, 0], flags=flags) + self.assertEqual(nd.tolist(), [[[], [], []], [[], [], []], [[], [], []]]) def test_ndarray_zero_strides(self): # zero strides @@ -2059,7 +2256,7 @@ def test_ndarray_zero_strides(self): def test_ndarray_offset(self): nd = ndarray(list(range(20)), shape=[3], offset=7) self.assertEqual(nd.offset, 7) - self.assertEqual(nd.tolist(), [7,8,9]) + self.assertEqual(nd.tolist(), [7, 8, 9]) def test_ndarray_memoryview_from_buffer(self): for flags in (0, ND_PIL): @@ -2074,29 +2271,27 @@ def test_ndarray_get_pointer(self): self.assertEqual(nd[i], get_pointer(nd, [i])) def test_ndarray_tolist_null_strides(self): - ex = ndarray(list(range(20)), shape=[2,2,5]) + ex = ndarray(list(range(20)), shape=[2, 2, 5]) - nd = ndarray(ex, getbuf=PyBUF_ND|PyBUF_FORMAT) + nd = ndarray(ex, getbuf=PyBUF_ND | PyBUF_FORMAT) self.assertEqual(nd.tolist(), ex.tolist()) m = memoryview(ex) self.assertEqual(m.tolist(), ex.tolist()) def test_ndarray_cmp_contig(self): - self.assertFalse(cmp_contig(b"123", b"456")) - x = ndarray(list(range(12)), shape=[3,4]) - y = ndarray(list(range(12)), shape=[4,3]) + x = ndarray(list(range(12)), shape=[3, 4]) + y = ndarray(list(range(12)), shape=[4, 3]) self.assertFalse(cmp_contig(x, y)) x = ndarray([1], shape=[1], format="B") - self.assertTrue(cmp_contig(x, b'\x01')) - self.assertTrue(cmp_contig(b'\x01', x)) + self.assertTrue(cmp_contig(x, b"\x01")) + self.assertTrue(cmp_contig(b"\x01", x)) def test_ndarray_hash(self): - - a = array.array('L', [1,2,3]) + a = array.array("L", [1, 2, 3]) nd = ndarray(a) self.assertRaises(ValueError, hash, nd) @@ -2107,84 +2302,88 @@ def test_ndarray_hash(self): self.assertEqual(hash(nd), hash(b)) # C-contiguous - nd = ndarray(list(range(12)), shape=[3,4]) + nd = ndarray(list(range(12)), shape=[3, 4]) self.assertEqual(hash(nd), hash(b)) - nd = ndarray(list(range(12)), shape=[3,2,2]) + nd = ndarray(list(range(12)), shape=[3, 2, 2]) self.assertEqual(hash(nd), hash(b)) # Fortran contiguous - b = bytes(transpose(list(range(12)), shape=[4,3])) - nd = ndarray(list(range(12)), shape=[3,4], flags=ND_FORTRAN) + b = bytes(transpose(list(range(12)), shape=[4, 3])) + nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_FORTRAN) self.assertEqual(hash(nd), hash(b)) - b = bytes(transpose(list(range(12)), shape=[2,3,2])) - nd = ndarray(list(range(12)), shape=[2,3,2], flags=ND_FORTRAN) + b = bytes(transpose(list(range(12)), shape=[2, 3, 2])) + nd = ndarray(list(range(12)), shape=[2, 3, 2], flags=ND_FORTRAN) self.assertEqual(hash(nd), hash(b)) # suboffsets b = bytes(list(range(12))) - nd = ndarray(list(range(12)), shape=[2,2,3], flags=ND_PIL) + nd = ndarray(list(range(12)), shape=[2, 2, 3], flags=ND_PIL) self.assertEqual(hash(nd), hash(b)) # non-byte formats - nd = ndarray(list(range(12)), shape=[2,2,3], format='L') + nd = ndarray(list(range(12)), shape=[2, 2, 3], format="L") self.assertEqual(hash(nd), hash(nd.tobytes())) def test_py_buffer_to_contiguous(self): - # The requests are used in _testbuffer.c:py_buffer_to_contiguous # to generate buffers without full information for testing. requests = ( # distinct flags - PyBUF_INDIRECT, PyBUF_STRIDES, PyBUF_ND, PyBUF_SIMPLE, + PyBUF_INDIRECT, + PyBUF_STRIDES, + PyBUF_ND, + PyBUF_SIMPLE, # compound requests - PyBUF_FULL, PyBUF_FULL_RO, - PyBUF_RECORDS, PyBUF_RECORDS_RO, - PyBUF_STRIDED, PyBUF_STRIDED_RO, - PyBUF_CONTIG, PyBUF_CONTIG_RO, + PyBUF_FULL, + PyBUF_FULL_RO, + PyBUF_RECORDS, + PyBUF_RECORDS_RO, + PyBUF_STRIDED, + PyBUF_STRIDED_RO, + PyBUF_CONTIG, + PyBUF_CONTIG_RO, ) # no buffer interface - self.assertRaises(TypeError, py_buffer_to_contiguous, {}, 'F', - PyBUF_FULL_RO) + self.assertRaises(TypeError, py_buffer_to_contiguous, {}, "F", PyBUF_FULL_RO) # scalar, read-only request nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: for request in requests: b = py_buffer_to_contiguous(nd, order, request) self.assertEqual(b, nd.tobytes()) # zeros in shape nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: for request in requests: b = py_buffer_to_contiguous(nd, order, request) - self.assertEqual(b, b'') + self.assertEqual(b, b"") - nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L", - flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L", flags=ND_WRITABLE) + for order in ["C", "F", "A"]: for request in requests: b = py_buffer_to_contiguous(nd, order, request) - self.assertEqual(b, b'') + self.assertEqual(b, b"") ### One-dimensional arrays are trivial, since Fortran and C order ### are the same. # one-dimensional for f in [0, ND_FORTRAN]: - nd = ndarray([1], shape=[1], format="h", flags=f|ND_WRITABLE) + nd = ndarray([1], shape=[1], format="h", flags=f | ND_WRITABLE) ndbytes = nd.tobytes() - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: for request in requests: b = py_buffer_to_contiguous(nd, order, request) self.assertEqual(b, ndbytes) - nd = ndarray([1, 2, 3], shape=[3], format="b", flags=f|ND_WRITABLE) + nd = ndarray([1, 2, 3], shape=[3], format="b", flags=f | ND_WRITABLE) ndbytes = nd.tobytes() - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: for request in requests: b = py_buffer_to_contiguous(nd, order, request) self.assertEqual(b, ndbytes) @@ -2192,14 +2391,14 @@ def test_py_buffer_to_contiguous(self): # one-dimensional, non-contiguous input nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE) ndbytes = nd.tobytes() - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: for request in [PyBUF_STRIDES, PyBUF_FULL]: b = py_buffer_to_contiguous(nd, order, request) self.assertEqual(b, ndbytes) nd = nd[::-1] ndbytes = nd.tobytes() - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: for request in requests: try: b = py_buffer_to_contiguous(nd, order, request) @@ -2273,22 +2472,24 @@ def test_py_buffer_to_contiguous(self): # multi-dimensional, contiguous input lst = list(range(12)) for f in [0, ND_FORTRAN]: - nd = ndarray(lst, shape=[3, 4], flags=f|ND_WRITABLE) + nd = ndarray(lst, shape=[3, 4], flags=f | ND_WRITABLE) if numpy_array: - na = numpy_array(buffer=bytearray(lst), - shape=[3, 4], dtype='B', - order='C' if f == 0 else 'F') + na = numpy_array( + buffer=bytearray(lst), + shape=[3, 4], + dtype="B", + order="C" if f == 0 else "F", + ) # 'C' request - if f == ND_FORTRAN: # 'F' to 'C' - x = ndarray(transpose(lst, [4, 3]), shape=[3, 4], - flags=ND_WRITABLE) + if f == ND_FORTRAN: # 'F' to 'C' + x = ndarray(transpose(lst, [4, 3]), shape=[3, 4], flags=ND_WRITABLE) expected = x.tobytes() else: expected = nd.tobytes() for request in requests: try: - b = py_buffer_to_contiguous(nd, 'C', request) + b = py_buffer_to_contiguous(nd, "C", request) except BufferError: continue @@ -2300,30 +2501,36 @@ def test_py_buffer_to_contiguous(self): self.assertEqual(memoryview(y), memoryview(nd)) if numpy_array: - self.assertEqual(b, na.tobytes(order='C')) + self.assertEqual(b, na.tobytes(order="C")) # 'F' request - if f == 0: # 'C' to 'F' - x = ndarray(transpose(lst, [3, 4]), shape=[4, 3], - flags=ND_WRITABLE) + if f == 0: # 'C' to 'F' + x = ndarray(transpose(lst, [3, 4]), shape=[4, 3], flags=ND_WRITABLE) else: x = ndarray(lst, shape=[3, 4], flags=ND_WRITABLE) expected = x.tobytes() - for request in [PyBUF_FULL, PyBUF_FULL_RO, PyBUF_INDIRECT, - PyBUF_STRIDES, PyBUF_ND]: + for request in [ + PyBUF_FULL, + PyBUF_FULL_RO, + PyBUF_INDIRECT, + PyBUF_STRIDES, + PyBUF_ND, + ]: try: - b = py_buffer_to_contiguous(nd, 'F', request) + b = py_buffer_to_contiguous(nd, "F", request) except BufferError: continue self.assertEqual(b, expected) # Check that output can be used as the basis for constructing # a Fortran array that is logically identical to the input array. - y = ndarray([v for v in b], shape=[3, 4], flags=ND_FORTRAN|ND_WRITABLE) + y = ndarray( + [v for v in b], shape=[3, 4], flags=ND_FORTRAN | ND_WRITABLE + ) self.assertEqual(memoryview(y), memoryview(nd)) if numpy_array: - self.assertEqual(b, na.tobytes(order='F')) + self.assertEqual(b, na.tobytes(order="F")) # 'A' request if f == ND_FORTRAN: @@ -2331,10 +2538,15 @@ def test_py_buffer_to_contiguous(self): expected = x.tobytes() else: expected = nd.tobytes() - for request in [PyBUF_FULL, PyBUF_FULL_RO, PyBUF_INDIRECT, - PyBUF_STRIDES, PyBUF_ND]: + for request in [ + PyBUF_FULL, + PyBUF_FULL_RO, + PyBUF_INDIRECT, + PyBUF_STRIDES, + PyBUF_ND, + ]: try: - b = py_buffer_to_contiguous(nd, 'A', request) + b = py_buffer_to_contiguous(nd, "A", request) except BufferError: continue @@ -2343,41 +2555,39 @@ def test_py_buffer_to_contiguous(self): # Check that output can be used as the basis for constructing # an array with order=f that is logically identical to the input # array. - y = ndarray([v for v in b], shape=[3, 4], flags=f|ND_WRITABLE) + y = ndarray([v for v in b], shape=[3, 4], flags=f | ND_WRITABLE) self.assertEqual(memoryview(y), memoryview(nd)) if numpy_array: - self.assertEqual(b, na.tobytes(order='A')) + self.assertEqual(b, na.tobytes(order="A")) # multi-dimensional, non-contiguous input - nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL) + nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE | ND_PIL) # 'C' - b = py_buffer_to_contiguous(nd, 'C', PyBUF_FULL_RO) + b = py_buffer_to_contiguous(nd, "C", PyBUF_FULL_RO) self.assertEqual(b, nd.tobytes()) y = ndarray([v for v in b], shape=[3, 4], flags=ND_WRITABLE) self.assertEqual(memoryview(y), memoryview(nd)) # 'F' - b = py_buffer_to_contiguous(nd, 'F', PyBUF_FULL_RO) + b = py_buffer_to_contiguous(nd, "F", PyBUF_FULL_RO) x = ndarray(transpose(lst, [3, 4]), shape=[4, 3], flags=ND_WRITABLE) self.assertEqual(b, x.tobytes()) - y = ndarray([v for v in b], shape=[3, 4], flags=ND_FORTRAN|ND_WRITABLE) + y = ndarray([v for v in b], shape=[3, 4], flags=ND_FORTRAN | ND_WRITABLE) self.assertEqual(memoryview(y), memoryview(nd)) # 'A' - b = py_buffer_to_contiguous(nd, 'A', PyBUF_FULL_RO) + b = py_buffer_to_contiguous(nd, "A", PyBUF_FULL_RO) self.assertEqual(b, nd.tobytes()) y = ndarray([v for v in b], shape=[3, 4], flags=ND_WRITABLE) self.assertEqual(memoryview(y), memoryview(nd)) def test_memoryview_construction(self): - - items_shape = [(9, []), ([1,2,3], [3]), (list(range(2*3*5)), [2,3,5])] + items_shape = [(9, []), ([1, 2, 3], [3]), (list(range(2 * 3 * 5)), [2, 3, 5])] # NumPy style, C-contiguous: for items, shape in items_shape: - # From PEP-3118 compliant exporter: ex = ndarray(items, shape=shape) m = memoryview(ex) @@ -2385,46 +2595,73 @@ def test_memoryview_construction(self): self.assertTrue(m.contiguous) ndim = len(shape) - strides = strides_from_shape(ndim, shape, 1, 'C') + strides = strides_from_shape(ndim, shape, 1, "C") lst = carray(items, shape) - self.verify(m, obj=ex, - itemsize=1, fmt='B', readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst) + self.verify( + m, + obj=ex, + itemsize=1, + fmt="B", + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + ) # From memoryview: m2 = memoryview(m) - self.verify(m2, obj=ex, - itemsize=1, fmt='B', readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst) + self.verify( + m2, + obj=ex, + itemsize=1, + fmt="B", + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + ) # PyMemoryView_FromBuffer(): no strides - nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT) + nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO | PyBUF_FORMAT) self.assertEqual(nd.strides, ()) m = nd.memoryview_from_buffer() - self.verify(m, obj=None, - itemsize=1, fmt='B', readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst) + self.verify( + m, + obj=None, + itemsize=1, + fmt="B", + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + ) # PyMemoryView_FromBuffer(): no format, shape, strides nd = ndarray(ex, getbuf=PyBUF_SIMPLE) - self.assertEqual(nd.format, '') + self.assertEqual(nd.format, "") self.assertEqual(nd.shape, ()) self.assertEqual(nd.strides, ()) m = nd.memoryview_from_buffer() lst = [items] if ndim == 0 else items - self.verify(m, obj=None, - itemsize=1, fmt='B', readonly=True, - ndim=1, shape=[ex.nbytes], strides=(1,), - lst=lst) + self.verify( + m, + obj=None, + itemsize=1, + fmt="B", + readonly=True, + ndim=1, + shape=[ex.nbytes], + strides=(1,), + lst=lst, + ) # NumPy style, Fortran contiguous: for items, shape in items_shape: - # From PEP-3118 compliant exporter: ex = ndarray(items, shape=shape, flags=ND_FORTRAN) m = memoryview(ex) @@ -2432,24 +2669,37 @@ def test_memoryview_construction(self): self.assertTrue(m.contiguous) ndim = len(shape) - strides = strides_from_shape(ndim, shape, 1, 'F') + strides = strides_from_shape(ndim, shape, 1, "F") lst = farray(items, shape) - self.verify(m, obj=ex, - itemsize=1, fmt='B', readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst) + self.verify( + m, + obj=ex, + itemsize=1, + fmt="B", + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + ) # From memoryview: m2 = memoryview(m) - self.verify(m2, obj=ex, - itemsize=1, fmt='B', readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst) + self.verify( + m2, + obj=ex, + itemsize=1, + fmt="B", + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + ) # PIL style: for items, shape in items_shape[1:]: - # From PEP-3118 compliant exporter: ex = ndarray(items, shape=shape, flags=ND_PIL) m = memoryview(ex) @@ -2457,53 +2707,67 @@ def test_memoryview_construction(self): ndim = len(shape) lst = carray(items, shape) - self.verify(m, obj=ex, - itemsize=1, fmt='B', readonly=True, - ndim=ndim, shape=shape, strides=ex.strides, - lst=lst) + self.verify( + m, + obj=ex, + itemsize=1, + fmt="B", + readonly=True, + ndim=ndim, + shape=shape, + strides=ex.strides, + lst=lst, + ) # From memoryview: m2 = memoryview(m) - self.verify(m2, obj=ex, - itemsize=1, fmt='B', readonly=True, - ndim=ndim, shape=shape, strides=ex.strides, - lst=lst) + self.verify( + m2, + obj=ex, + itemsize=1, + fmt="B", + readonly=True, + ndim=ndim, + shape=shape, + strides=ex.strides, + lst=lst, + ) # Invalid number of arguments: - self.assertRaises(TypeError, memoryview, b'9', 'x') + self.assertRaises(TypeError, memoryview, b"9", "x") # Not a buffer provider: self.assertRaises(TypeError, memoryview, {}) # Non-compliant buffer provider: - ex = ndarray([1,2,3], shape=[3]) + ex = ndarray([1, 2, 3], shape=[3]) nd = ndarray(ex, getbuf=PyBUF_SIMPLE) self.assertRaises(BufferError, memoryview, nd) - nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT) + nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO | PyBUF_FORMAT) self.assertRaises(BufferError, memoryview, nd) # ndim > 64 - nd = ndarray([1]*128, shape=[1]*128, format='L') + nd = ndarray([1] * 128, shape=[1] * 128, format="L") self.assertRaises(ValueError, memoryview, nd) self.assertRaises(ValueError, nd.memoryview_from_buffer) - self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'C') - self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'F') - self.assertRaises(ValueError, get_contiguous, nd[::-1], PyBUF_READ, 'C') + self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, "C") + self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, "F") + self.assertRaises(ValueError, get_contiguous, nd[::-1], PyBUF_READ, "C") def test_memoryview_cast_zero_shape(self): # Casts are undefined if buffer is multidimensional and shape # contains zeros. These arrays are regarded as C-contiguous by # Numpy and PyBuffer_GetContiguous(), so they are not caught by # the test for C-contiguity in memory_cast(). - items = [1,2,3] - for shape in ([0,3,3], [3,0,3], [0,3,3]): + items = [1, 2, 3] + for shape in ([0, 3, 3], [3, 0, 3], [0, 3, 3]): ex = ndarray(items, shape=shape) self.assertTrue(ex.c_contiguous) msrc = memoryview(ex) - self.assertRaises(TypeError, msrc.cast, 'c') + self.assertRaises(TypeError, msrc.cast, "c") # Monodimensional empty view can be cast (issue #19014). - for fmt, _, _ in iter_format(1, 'memoryview'): - msrc = memoryview(b'') + for fmt, _, _ in iter_format(1, "memoryview"): + msrc = memoryview(b"") m = msrc.cast(fmt) - self.assertEqual(m.tobytes(), b'') + self.assertEqual(m.tobytes(), b"") self.assertEqual(m.tolist(), []) check_sizeof = support.check_sizeof @@ -2511,41 +2775,63 @@ def test_memoryview_cast_zero_shape(self): def test_memoryview_sizeof(self): check = self.check_sizeof vsize = support.calcvobjsize - base_struct = 'Pnin 2P2n2i5P P' - per_dim = '3n' + base_struct = "Pnin 2P2n2i5P P" + per_dim = "3n" items = list(range(8)) - check(memoryview(b''), vsize(base_struct + 1 * per_dim)) + check(memoryview(b""), vsize(base_struct + 1 * per_dim)) a = ndarray(items, shape=[2, 4], format="b") check(memoryview(a), vsize(base_struct + 2 * per_dim)) a = ndarray(items, shape=[2, 2, 2], format="b") check(memoryview(a), vsize(base_struct + 3 * per_dim)) def test_memoryview_struct_module(self): - class INT(object): def __init__(self, val): self.val = val + def __int__(self): return self.val class IDX(object): def __init__(self, val): self.val = val + def __index__(self): return self.val - def f(): return 7 - - values = [INT(9), IDX(9), - 2.2+3j, Decimal("-21.1"), 12.2, Fraction(5, 2), - [1,2,3], {4,5,6}, {7:8}, (), (9,), - True, False, None, Ellipsis, - b'a', b'abc', bytearray(b'a'), bytearray(b'abc'), - 'a', 'abc', r'a', r'abc', - f, lambda x: x] - - for fmt, items, item in iter_format(10, 'memoryview'): + def f(): + return 7 + + values = [ + INT(9), + IDX(9), + 2.2 + 3j, + Decimal("-21.1"), + 12.2, + Fraction(5, 2), + [1, 2, 3], + {4, 5, 6}, + {7: 8}, + (), + (9,), + True, + False, + None, + Ellipsis, + b"a", + b"abc", + bytearray(b"a"), + bytearray(b"abc"), + "a", + "abc", + r"a", + r"abc", + f, + lambda x: x, + ] + + for fmt, items, item in iter_format(10, "memoryview"): ex = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE) nd = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE) m = memoryview(ex) @@ -2555,7 +2841,7 @@ def f(): return 7 self.assertEqual(m[0], nd[0]) itemsize = struct.calcsize(fmt) - if 'P' in fmt: + if "P" in fmt: continue for v in values: @@ -2581,43 +2867,41 @@ def test_memoryview_cast_zero_strides(self): # Casts are undefined if strides contains zeros. These arrays are # (sometimes!) regarded as C-contiguous by Numpy, but not by # PyBuffer_GetContiguous(). - ex = ndarray([1,2,3], shape=[3], strides=[0]) + ex = ndarray([1, 2, 3], shape=[3], strides=[0]) self.assertFalse(ex.c_contiguous) msrc = memoryview(ex) - self.assertRaises(TypeError, msrc.cast, 'c') + self.assertRaises(TypeError, msrc.cast, "c") def test_memoryview_cast_invalid(self): # invalid format for sfmt in NON_BYTE_FORMAT: - sformat = '@' + sfmt if randrange(2) else sfmt + sformat = "@" + sfmt if randrange(2) else sfmt ssize = struct.calcsize(sformat) for dfmt in NON_BYTE_FORMAT: - dformat = '@' + dfmt if randrange(2) else dfmt + dformat = "@" + dfmt if randrange(2) else dfmt dsize = struct.calcsize(dformat) - ex = ndarray(list(range(32)), shape=[32//ssize], format=sformat) + ex = ndarray(list(range(32)), shape=[32 // ssize], format=sformat) msrc = memoryview(ex) - self.assertRaises(TypeError, msrc.cast, dfmt, [32//dsize]) + self.assertRaises(TypeError, msrc.cast, dfmt, [32 // dsize]) for sfmt, sitems, _ in iter_format(1): ex = ndarray(sitems, shape=[1], format=sfmt) msrc = memoryview(ex) for dfmt, _, _ in iter_format(1): if not is_memoryview_format(dfmt): - self.assertRaises(ValueError, msrc.cast, dfmt, - [32//dsize]) + self.assertRaises(ValueError, msrc.cast, dfmt, [32 // dsize]) else: if not is_byte_format(sfmt) and not is_byte_format(dfmt): - self.assertRaises(TypeError, msrc.cast, dfmt, - [32//dsize]) + self.assertRaises(TypeError, msrc.cast, dfmt, [32 // dsize]) # invalid shape - size_h = struct.calcsize('h') - size_d = struct.calcsize('d') - ex = ndarray(list(range(2*2*size_d)), shape=[2,2,size_d], format='h') + size_h = struct.calcsize("h") + size_d = struct.calcsize("d") + ex = ndarray(list(range(2 * 2 * size_d)), shape=[2, 2, size_d], format="h") msrc = memoryview(ex) - self.assertRaises(TypeError, msrc.cast, shape=[2,2,size_h], format='d') + self.assertRaises(TypeError, msrc.cast, shape=[2, 2, size_h], format="d") - ex = ndarray(list(range(120)), shape=[1,2,3,4,5]) + ex = ndarray(list(range(120)), shape=[1, 2, 3, 4, 5]) m = memoryview(ex) # incorrect number of args @@ -2641,140 +2925,175 @@ def test_memoryview_cast_invalid(self): self.assertRaises(ValueError, m.cast, "xBI") # src format not implemented - ex = ndarray([(1,2), (3,4)], shape=[2], format="II") + ex = ndarray([(1, 2), (3, 4)], shape=[2], format="II") m = memoryview(ex) self.assertRaises(NotImplementedError, m.__getitem__, 0) self.assertRaises(NotImplementedError, m.__setitem__, 0, 8) self.assertRaises(NotImplementedError, m.tolist) # incorrect shape type - ex = ndarray(list(range(120)), shape=[1,2,3,4,5]) + ex = ndarray(list(range(120)), shape=[1, 2, 3, 4, 5]) m = memoryview(ex) self.assertRaises(TypeError, m.cast, "B", shape={}) # incorrect shape elements - ex = ndarray(list(range(120)), shape=[2*3*4*5]) + ex = ndarray(list(range(120)), shape=[2 * 3 * 4 * 5]) m = memoryview(ex) self.assertRaises(OverflowError, m.cast, "B", shape=[2**64]) self.assertRaises(ValueError, m.cast, "B", shape=[-1]) - self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,-1]) - self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,0]) - self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5,6,7,'x']) + self.assertRaises(ValueError, m.cast, "B", shape=[2, 3, 4, 5, 6, 7, -1]) + self.assertRaises(ValueError, m.cast, "B", shape=[2, 3, 4, 5, 6, 7, 0]) + self.assertRaises(TypeError, m.cast, "B", shape=[2, 3, 4, 5, 6, 7, "x"]) # N-D -> N-D cast - ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3,5,7,11]) + ex = ndarray(list([9 for _ in range(3 * 5 * 7 * 11)]), shape=[3, 5, 7, 11]) m = memoryview(ex) - self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5]) + self.assertRaises(TypeError, m.cast, "I", shape=[2, 3, 4, 5]) # cast with ndim > 64 - nd = ndarray(list(range(128)), shape=[128], format='I') + nd = ndarray(list(range(128)), shape=[128], format="I") m = memoryview(nd) - self.assertRaises(ValueError, m.cast, 'I', [1]*128) + self.assertRaises(ValueError, m.cast, "I", [1] * 128) # view->len not a multiple of itemsize - ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11]) + ex = ndarray(list([9 for _ in range(3 * 5 * 7 * 11)]), shape=[3 * 5 * 7 * 11]) m = memoryview(ex) - self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5]) + self.assertRaises(TypeError, m.cast, "I", shape=[2, 3, 4, 5]) # product(shape) * itemsize != buffer size - ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11]) + ex = ndarray(list([9 for _ in range(3 * 5 * 7 * 11)]), shape=[3 * 5 * 7 * 11]) m = memoryview(ex) - self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5]) + self.assertRaises(TypeError, m.cast, "B", shape=[2, 3, 4, 5]) # product(shape) * itemsize overflow - nd = ndarray(list(range(128)), shape=[128], format='I') + nd = ndarray(list(range(128)), shape=[128], format="I") m1 = memoryview(nd) - nd = ndarray(list(range(128)), shape=[128], format='B') + nd = ndarray(list(range(128)), shape=[128], format="B") m2 = memoryview(nd) - if sys.maxsize == 2**63-1: - self.assertRaises(TypeError, m1.cast, 'B', - [7, 7, 73, 127, 337, 92737, 649657]) - self.assertRaises(ValueError, m1.cast, 'B', - [2**20, 2**20, 2**10, 2**10, 2**3]) - self.assertRaises(ValueError, m2.cast, 'I', - [2**20, 2**20, 2**10, 2**10, 2**1]) + if sys.maxsize == 2**63 - 1: + self.assertRaises( + TypeError, m1.cast, "B", [7, 7, 73, 127, 337, 92737, 649657] + ) + self.assertRaises( + ValueError, m1.cast, "B", [2**20, 2**20, 2**10, 2**10, 2**3] + ) + self.assertRaises( + ValueError, m2.cast, "I", [2**20, 2**20, 2**10, 2**10, 2**1] + ) else: - self.assertRaises(TypeError, m1.cast, 'B', - [1, 2147483647]) - self.assertRaises(ValueError, m1.cast, 'B', - [2**10, 2**10, 2**5, 2**5, 2**1]) - self.assertRaises(ValueError, m2.cast, 'I', - [2**10, 2**10, 2**5, 2**3, 2**1]) + self.assertRaises(TypeError, m1.cast, "B", [1, 2147483647]) + self.assertRaises( + ValueError, m1.cast, "B", [2**10, 2**10, 2**5, 2**5, 2**1] + ) + self.assertRaises( + ValueError, m2.cast, "I", [2**10, 2**10, 2**5, 2**3, 2**1] + ) def test_memoryview_cast(self): bytespec = ( - ('B', lambda ex: list(ex.tobytes())), - ('b', lambda ex: [x-256 if x > 127 else x for x in list(ex.tobytes())]), - ('c', lambda ex: [bytes(chr(x), 'latin-1') for x in list(ex.tobytes())]), + ("B", lambda ex: list(ex.tobytes())), + ("b", lambda ex: [x - 256 if x > 127 else x for x in list(ex.tobytes())]), + ("c", lambda ex: [bytes(chr(x), "latin-1") for x in list(ex.tobytes())]), ) def iter_roundtrip(ex, m, items, fmt): srcsize = struct.calcsize(fmt) for bytefmt, to_bytelist in bytespec: - m2 = m.cast(bytefmt) lst = to_bytelist(ex) - self.verify(m2, obj=ex, - itemsize=1, fmt=bytefmt, readonly=False, - ndim=1, shape=[31*srcsize], strides=(1,), - lst=lst, cast=True) + self.verify( + m2, + obj=ex, + itemsize=1, + fmt=bytefmt, + readonly=False, + ndim=1, + shape=[31 * srcsize], + strides=(1,), + lst=lst, + cast=True, + ) m3 = m2.cast(fmt) self.assertEqual(m3, ex) lst = ex.tolist() - self.verify(m3, obj=ex, - itemsize=srcsize, fmt=fmt, readonly=False, - ndim=1, shape=[31], strides=(srcsize,), - lst=lst, cast=True) + self.verify( + m3, + obj=ex, + itemsize=srcsize, + fmt=fmt, + readonly=False, + ndim=1, + shape=[31], + strides=(srcsize,), + lst=lst, + cast=True, + ) # cast from ndim = 0 to ndim = 1 - srcsize = struct.calcsize('I') - ex = ndarray(9, shape=[], format='I') - destitems, destshape = cast_items(ex, 'B', 1) + srcsize = struct.calcsize("I") + ex = ndarray(9, shape=[], format="I") + destitems, destshape = cast_items(ex, "B", 1) m = memoryview(ex) - m2 = m.cast('B') - self.verify(m2, obj=ex, - itemsize=1, fmt='B', readonly=True, - ndim=1, shape=destshape, strides=(1,), - lst=destitems, cast=True) + m2 = m.cast("B") + self.verify( + m2, + obj=ex, + itemsize=1, + fmt="B", + readonly=True, + ndim=1, + shape=destshape, + strides=(1,), + lst=destitems, + cast=True, + ) # cast from ndim = 1 to ndim = 0 - destsize = struct.calcsize('I') - ex = ndarray([9]*destsize, shape=[destsize], format='B') - destitems, destshape = cast_items(ex, 'I', destsize, shape=[]) + destsize = struct.calcsize("I") + ex = ndarray([9] * destsize, shape=[destsize], format="B") + destitems, destshape = cast_items(ex, "I", destsize, shape=[]) m = memoryview(ex) - m2 = m.cast('I', shape=[]) - self.verify(m2, obj=ex, - itemsize=destsize, fmt='I', readonly=True, - ndim=0, shape=(), strides=(), - lst=destitems, cast=True) + m2 = m.cast("I", shape=[]) + self.verify( + m2, + obj=ex, + itemsize=destsize, + fmt="I", + readonly=True, + ndim=0, + shape=(), + strides=(), + lst=destitems, + cast=True, + ) # array.array: roundtrip to/from bytes - for fmt, items, _ in iter_format(31, 'array'): + for fmt, items, _ in iter_format(31, "array"): ex = array.array(fmt, items) m = memoryview(ex) iter_roundtrip(ex, m, items, fmt) # ndarray: roundtrip to/from bytes - for fmt, items, _ in iter_format(31, 'memoryview'): + for fmt, items, _ in iter_format(31, "memoryview"): ex = ndarray(items, shape=[31], format=fmt, flags=ND_WRITABLE) m = memoryview(ex) iter_roundtrip(ex, m, items, fmt) - @support.requires_resource('cpu') + @support.requires_resource("cpu") def test_memoryview_cast_1D_ND(self): # Cast between C-contiguous buffers. At least one buffer must # be 1D, at least one format must be 'c', 'b' or 'B'. for _tshape in gencastshapes(): - for char in fmtdict['@']: + for char in fmtdict["@"]: # Casts to _Bool are undefined if the source contains values # other than 0 or 1. if char == "?": continue - tfmt = ('', '@')[randrange(2)] + char + tfmt = ("", "@")[randrange(2)] + char tsize = struct.calcsize(tfmt) n = prod(_tshape) * tsize - obj = 'memoryview' if is_byte_format(tfmt) else 'bytefmt' + obj = "memoryview" if is_byte_format(tfmt) else "bytefmt" for fmt, items, _ in iter_format(n, obj): size = struct.calcsize(fmt) shape = [n] if n > 0 else [] @@ -2788,8 +3107,8 @@ def test_memoryview_cast_1D_ND(self): if titems is None: self.assertRaises(TypeError, m.cast, tfmt, tshape) continue - if titems == 'nan': - continue # NaNs in lists are a recipe for trouble. + if titems == "nan": + continue # NaNs in lists are a recipe for trouble. # 1D -> ND nd = ndarray(titems, shape=tshape, format=tfmt) @@ -2798,10 +3117,18 @@ def test_memoryview_cast_1D_ND(self): ndim = len(tshape) strides = nd.strides lst = nd.tolist() - self.verify(m2, obj=ex, - itemsize=tsize, fmt=tfmt, readonly=True, - ndim=ndim, shape=tshape, strides=strides, - lst=lst, cast=True) + self.verify( + m2, + obj=ex, + itemsize=tsize, + fmt=tfmt, + readonly=True, + ndim=ndim, + shape=tshape, + strides=strides, + lst=lst, + cast=True, + ) # ND -> 1D m3 = m2.cast(fmt) @@ -2810,23 +3137,40 @@ def test_memoryview_cast_1D_ND(self): strides = ex.strides lst = ex.tolist() - self.verify(m3, obj=ex, - itemsize=size, fmt=fmt, readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst, cast=True) - - self.verify(m4, obj=ex, - itemsize=size, fmt=fmt, readonly=True, - ndim=ndim, shape=shape, strides=strides, - lst=lst, cast=True) + self.verify( + m3, + obj=ex, + itemsize=size, + fmt=fmt, + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + cast=True, + ) + + self.verify( + m4, + obj=ex, + itemsize=size, + fmt=fmt, + readonly=True, + ndim=ndim, + shape=shape, + strides=strides, + lst=lst, + cast=True, + ) if ctypes: # format: "T{>l:x:>d:y:}" class BEPoint(ctypes.BigEndianStructure): _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_double)] + point = BEPoint(100, 200.1) m1 = memoryview(point) - m2 = m1.cast('B') + m2 = m1.cast("B") self.assertEqual(m2.obj, point) self.assertEqual(m2.itemsize, 1) self.assertIs(m2.readonly, False) @@ -2837,7 +3181,7 @@ class BEPoint(ctypes.BigEndianStructure): x = ctypes.c_double(1.2) m1 = memoryview(x) - m2 = m1.cast('c') + m2 = m1.cast("c") self.assertEqual(m2.obj, x) self.assertEqual(m2.itemsize, 1) self.assertIs(m2.readonly, False) @@ -2847,10 +3191,9 @@ class BEPoint(ctypes.BigEndianStructure): self.assertEqual(m2.suboffsets, ()) def test_memoryview_tolist(self): - # Most tolist() tests are in self.verify() etc. - a = array.array('h', list(range(-6, 6))) + a = array.array("h", list(range(-6, 6))) m = memoryview(a) self.assertEqual(m, a) self.assertEqual(m.tolist(), a.tolist()) @@ -2860,19 +3203,21 @@ def test_memoryview_tolist(self): self.assertEqual(m, a) self.assertEqual(m.tolist(), a.tolist()) - ex = ndarray(list(range(2*3*5*7*11)), shape=[11,2,7,3,5], format='L') + ex = ndarray( + list(range(2 * 3 * 5 * 7 * 11)), shape=[11, 2, 7, 3, 5], format="L" + ) m = memoryview(ex) self.assertEqual(m.tolist(), ex.tolist()) - ex = ndarray([(2, 5), (7, 11)], shape=[2], format='lh') + ex = ndarray([(2, 5), (7, 11)], shape=[2], format="lh") m = memoryview(ex) self.assertRaises(NotImplementedError, m.tolist) - ex = ndarray([b'12345'], shape=[1], format="s") + ex = ndarray([b"12345"], shape=[1], format="s") m = memoryview(ex) self.assertRaises(NotImplementedError, m.tolist) - ex = ndarray([b"a",b"b",b"c",b"d",b"e",b"f"], shape=[2,3], format='s') + ex = ndarray([b"a", b"b", b"c", b"d", b"e", b"f"], shape=[2, 3], format="s") m = memoryview(ex) self.assertRaises(NotImplementedError, m.tolist) @@ -2886,8 +3231,7 @@ def test_memoryview_repr(self): self.assertTrue(r.startswith("l:x:>l:y:}" class BEPoint(ctypes.BigEndianStructure): _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)] + point = BEPoint(100, 200) a = memoryview(point) b = memoryview(point) @@ -3235,17 +3583,15 @@ class BEPoint(ctypes.BigEndianStructure): @warnings_helper.ignore_warnings(category=DeprecationWarning) # gh-80480 array('u') def test_memoryview_compare_special_cases_deprecated_u_type_code(self): - # Depends on issue #15625: the struct module does not understand 'u'. - a = array.array('u', 'xyz') + a = array.array("u", "xyz") v = memoryview(a) self.assertNotEqual(a, v) self.assertNotEqual(v, a) def test_memoryview_compare_ndim_zero(self): - - nd1 = ndarray(1729, shape=[], format='@L') - nd2 = ndarray(1729, shape=[], format='L', flags=ND_WRITABLE) + nd1 = ndarray(1729, shape=[], format="@L") + nd2 = ndarray(1729, shape=[], format="L", flags=ND_WRITABLE) v = memoryview(nd1) w = memoryview(nd2) self.assertEqual(v, w) @@ -3269,8 +3615,8 @@ def test_memoryview_compare_ndim_zero(self): self.assertFalse(v.__eq__(w)) self.assertFalse(w.__eq__(v)) - nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL) - ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL) + nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE | ND_PIL) + ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE | ND_PIL) m = memoryview(ex) self.assertEqual(m, nd) @@ -3278,9 +3624,8 @@ def test_memoryview_compare_ndim_zero(self): self.assertNotEqual(m, nd) # struct module: equal - nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s') - nd2 = ndarray((1729, 1.2, b'12345'), shape=[], format='hf5s', - flags=ND_WRITABLE) + nd1 = ndarray((1729, 1.2, b"12345"), shape=[], format="Lf5s") + nd2 = ndarray((1729, 1.2, b"12345"), shape=[], format="hf5s", flags=ND_WRITABLE) v = memoryview(nd1) w = memoryview(nd2) self.assertEqual(v, w) @@ -3291,9 +3636,10 @@ def test_memoryview_compare_ndim_zero(self): self.assertEqual(nd1, w) # struct module: not equal - nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s') - nd2 = ndarray((-1729, 1.2, b'12345'), shape=[], format='hf5s', - flags=ND_WRITABLE) + nd1 = ndarray((1729, 1.2, b"12345"), shape=[], format="Lf5s") + nd2 = ndarray( + (-1729, 1.2, b"12345"), shape=[], format="hf5s", flags=ND_WRITABLE + ) v = memoryview(nd1) w = memoryview(nd2) self.assertNotEqual(v, w) @@ -3306,10 +3652,9 @@ def test_memoryview_compare_ndim_zero(self): self.assertEqual(w, nd2) def test_memoryview_compare_ndim_one(self): - # contiguous - nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h') - nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='@h') + nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format="@h") + nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format="@h") v = memoryview(nd1) w = memoryview(nd2) @@ -3320,8 +3665,8 @@ def test_memoryview_compare_ndim_one(self): self.assertNotEqual(v, w) # contiguous, struct module - nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='', '!']: - x = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q') - y = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q', - flags=ND_WRITABLE|ND_FORTRAN) + for byteorder in ["=", "<", ">", "!"]: + x = ndarray([2**63] * 120, shape=[3, 5, 2, 2, 2], format=byteorder + "Q") + y = ndarray( + [2**63] * 120, + shape=[3, 5, 2, 2, 2], + format=byteorder + "Q", + flags=ND_WRITABLE | ND_FORTRAN, + ) y[2][3][1][1][1] = 1 a = memoryview(x) b = memoryview(y) @@ -3886,10 +4250,17 @@ def test_memoryview_compare_not_equal(self): self.assertNotEqual(a, y) self.assertNotEqual(b, x) - x = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2], - format=byteorder+'QLH') - y = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2], - format=byteorder+'QLH', flags=ND_WRITABLE|ND_FORTRAN) + x = ndarray( + [(2**63, 2**31, 2**15)] * 120, + shape=[3, 5, 2, 2, 2], + format=byteorder + "QLH", + ) + y = ndarray( + [(2**63, 2**31, 2**15)] * 120, + shape=[3, 5, 2, 2, 2], + format=byteorder + "QLH", + flags=ND_WRITABLE | ND_FORTRAN, + ) y[2][3][1][1][1] = (1, 1, 1) a = memoryview(x) b = memoryview(y) @@ -3900,8 +4271,7 @@ def test_memoryview_compare_not_equal(self): self.assertNotEqual(b, x) def test_memoryview_check_released(self): - - a = array.array('d', [1.1, 2.2, 3.3]) + a = array.array("d", [1.1, 2.2, 3.3]) m = memoryview(a) m.release() @@ -3909,7 +4279,7 @@ def test_memoryview_check_released(self): # PyMemoryView_FromObject() self.assertRaises(ValueError, memoryview, m) # memoryview.cast() - self.assertRaises(ValueError, m.cast, 'c') + self.assertRaises(ValueError, m.cast, "c") # getbuffer() self.assertRaises(ValueError, ndarray, m) # memoryview.tolist() @@ -3923,13 +4293,24 @@ def test_memoryview_check_released(self): # assignment self.assertRaises(ValueError, m.__setitem__, 0, 1) - for attr in ('obj', 'nbytes', 'readonly', 'itemsize', 'format', 'ndim', - 'shape', 'strides', 'suboffsets', 'c_contiguous', - 'f_contiguous', 'contiguous'): + for attr in ( + "obj", + "nbytes", + "readonly", + "itemsize", + "format", + "ndim", + "shape", + "strides", + "suboffsets", + "c_contiguous", + "f_contiguous", + "contiguous", + ): self.assertRaises(ValueError, m.__getattribute__, attr) # richcompare - b = array.array('d', [1.1, 2.2, 3.3]) + b = array.array("d", [1.1, 2.2, 3.3]) m1 = memoryview(a) m2 = memoryview(b) @@ -3944,23 +4325,22 @@ def test_memoryview_tobytes(self): t = (-529, 576, -625, 676, -729) - nd = ndarray(t, shape=[5], format='@h') + nd = ndarray(t, shape=[5], format="@h") m = memoryview(nd) self.assertEqual(m, nd) self.assertEqual(m.tobytes(), nd.tobytes()) - nd = ndarray([t], shape=[1], format='>hQiLl') + nd = ndarray([t], shape=[1], format=">hQiLl") m = memoryview(nd) self.assertEqual(m, nd) self.assertEqual(m.tobytes(), nd.tobytes()) - nd = ndarray([t for _ in range(12)], shape=[2,2,3], format='=hQiLl') + nd = ndarray([t for _ in range(12)], shape=[2, 2, 3], format="=hQiLl") m = memoryview(nd) self.assertEqual(m, nd) self.assertEqual(m.tobytes(), nd.tobytes()) - nd = ndarray([t for _ in range(120)], shape=[5,2,2,3,2], - format='l:x:>l:y:}" class BEPoint(ctypes.BigEndianStructure): _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)] + point = BEPoint(100, 200) a = memoryview(point) self.assertEqual(a.tobytes(), bytes(point)) @@ -3978,31 +4359,31 @@ def test_memoryview_get_contiguous(self): # Many implicit tests are already in self.verify(). # no buffer interface - self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, 'F') + self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, "F") # writable request to read-only object - self.assertRaises(BufferError, get_contiguous, b'x', PyBUF_WRITE, 'C') + self.assertRaises(BufferError, get_contiguous, b"x", PyBUF_WRITE, "C") # writable request to non-contiguous object nd = ndarray([1, 2, 3], shape=[2], strides=[2]) - self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'A') + self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, "A") # scalar, read-only request from read-only exporter nd = ndarray(9, shape=(), format="L") - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: m = get_contiguous(nd, PyBUF_READ, order) self.assertEqual(m, nd) self.assertEqual(m[()], 9) # scalar, read-only request from writable exporter nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: m = get_contiguous(nd, PyBUF_READ, order) self.assertEqual(m, nd) self.assertEqual(m[()], 9) # scalar, writable request - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: nd[()] = 9 m = get_contiguous(nd, PyBUF_WRITE, order) self.assertEqual(m, nd) @@ -4014,34 +4395,33 @@ def test_memoryview_get_contiguous(self): # zeros in shape nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: m = get_contiguous(nd, PyBUF_READ, order) self.assertRaises(IndexError, m.__getitem__, 0) self.assertEqual(m, nd) self.assertEqual(m.tolist(), []) - nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L", - flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L", flags=ND_WRITABLE) + for order in ["C", "F", "A"]: m = get_contiguous(nd, PyBUF_READ, order) self.assertEqual(ndarray(m).tolist(), [[], []]) # one-dimensional nd = ndarray([1], shape=[1], format="h", flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: m = get_contiguous(nd, PyBUF_WRITE, order) self.assertEqual(m, nd) self.assertEqual(m.tolist(), nd.tolist()) nd = ndarray([1, 2, 3], shape=[3], format="b", flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: m = get_contiguous(nd, PyBUF_WRITE, order) self.assertEqual(m, nd) self.assertEqual(m.tolist(), nd.tolist()) # one-dimensional, non-contiguous nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE) - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: m = get_contiguous(nd, PyBUF_READ, order) self.assertEqual(m, nd) self.assertEqual(m.tolist(), nd.tolist()) @@ -4050,7 +4430,7 @@ def test_memoryview_get_contiguous(self): self.assertEqual(nd[1], 3) nd = nd[::-1] - for order in ['C', 'F', 'A']: + for order in ["C", "F", "A"]: m = get_contiguous(nd, PyBUF_READ, order) self.assertEqual(m, nd) self.assertEqual(m.tolist(), nd.tolist()) @@ -4060,76 +4440,72 @@ def test_memoryview_get_contiguous(self): # multi-dimensional, contiguous input nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE) - for order in ['C', 'A']: + for order in ["C", "A"]: m = get_contiguous(nd, PyBUF_WRITE, order) self.assertEqual(ndarray(m).tolist(), nd.tolist()) - self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'F') + self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, "F") m = get_contiguous(nd, PyBUF_READ, order) self.assertEqual(ndarray(m).tolist(), nd.tolist()) - nd = ndarray(list(range(12)), shape=[3, 4], - flags=ND_WRITABLE|ND_FORTRAN) - for order in ['F', 'A']: + nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE | ND_FORTRAN) + for order in ["F", "A"]: m = get_contiguous(nd, PyBUF_WRITE, order) self.assertEqual(ndarray(m).tolist(), nd.tolist()) - self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'C') + self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, "C") m = get_contiguous(nd, PyBUF_READ, order) self.assertEqual(ndarray(m).tolist(), nd.tolist()) # multi-dimensional, non-contiguous input - nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL) - for order in ['C', 'F', 'A']: - self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, - order) + nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE | ND_PIL) + for order in ["C", "F", "A"]: + self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, order) m = get_contiguous(nd, PyBUF_READ, order) self.assertEqual(ndarray(m).tolist(), nd.tolist()) # flags - nd = ndarray([1,2,3,4,5], shape=[3], strides=[2]) - m = get_contiguous(nd, PyBUF_READ, 'C') + nd = ndarray([1, 2, 3, 4, 5], shape=[3], strides=[2]) + m = get_contiguous(nd, PyBUF_READ, "C") self.assertTrue(m.c_contiguous) def test_memoryview_serializing(self): - # C-contiguous - size = struct.calcsize('i') - a = array.array('i', [1,2,3,4,5]) + size = struct.calcsize("i") + a = array.array("i", [1, 2, 3, 4, 5]) m = memoryview(a) buf = io.BytesIO(m) - b = bytearray(5*size) + b = bytearray(5 * size) buf.readinto(b) self.assertEqual(m.tobytes(), b) # C-contiguous, multi-dimensional - size = struct.calcsize('L') - nd = ndarray(list(range(12)), shape=[2,3,2], format="L") + size = struct.calcsize("L") + nd = ndarray(list(range(12)), shape=[2, 3, 2], format="L") m = memoryview(nd) buf = io.BytesIO(m) - b = bytearray(2*3*2*size) + b = bytearray(2 * 3 * 2 * size) buf.readinto(b) self.assertEqual(m.tobytes(), b) # Fortran contiguous, multi-dimensional - #size = struct.calcsize('L') - #nd = ndarray(list(range(12)), shape=[2,3,2], format="L", + # size = struct.calcsize('L') + # nd = ndarray(list(range(12)), shape=[2,3,2], format="L", # flags=ND_FORTRAN) - #m = memoryview(nd) - #buf = io.BytesIO(m) - #b = bytearray(2*3*2*size) - #buf.readinto(b) - #self.assertEqual(m.tobytes(), b) + # m = memoryview(nd) + # buf = io.BytesIO(m) + # b = bytearray(2*3*2*size) + # buf.readinto(b) + # self.assertEqual(m.tobytes(), b) def test_memoryview_hash(self): - # bytes exporter b = bytes(list(range(12))) m = memoryview(b) self.assertEqual(hash(b), hash(m)) # C-contiguous - mc = m.cast('c', shape=[3,4]) + mc = m.cast("c", shape=[3, 4]) self.assertEqual(hash(mc), hash(b)) # non-contiguous @@ -4138,60 +4514,59 @@ def test_memoryview_hash(self): self.assertEqual(hash(mx), hash(b)) # Fortran contiguous - nd = ndarray(list(range(30)), shape=[3,2,5], flags=ND_FORTRAN) + nd = ndarray(list(range(30)), shape=[3, 2, 5], flags=ND_FORTRAN) m = memoryview(nd) self.assertEqual(hash(m), hash(nd)) # multi-dimensional slice - nd = ndarray(list(range(30)), shape=[3,2,5]) + nd = ndarray(list(range(30)), shape=[3, 2, 5]) x = nd[::2, ::, ::-1] m = memoryview(x) self.assertEqual(hash(m), hash(x)) # multi-dimensional slice with suboffsets - nd = ndarray(list(range(30)), shape=[2,5,3], flags=ND_PIL) + nd = ndarray(list(range(30)), shape=[2, 5, 3], flags=ND_PIL) x = nd[::2, ::, ::-1] m = memoryview(x) self.assertEqual(hash(m), hash(x)) # equality-hash invariant - x = ndarray(list(range(12)), shape=[12], format='B') + x = ndarray(list(range(12)), shape=[12], format="B") a = memoryview(x) - y = ndarray(list(range(12)), shape=[12], format='b') + y = ndarray(list(range(12)), shape=[12], format="b") b = memoryview(y) self.assertEqual(a, b) self.assertEqual(hash(a), hash(b)) # non-byte formats - nd = ndarray(list(range(12)), shape=[2,2,3], format='L') + nd = ndarray(list(range(12)), shape=[2, 2, 3], format="L") m = memoryview(nd) self.assertRaises(ValueError, m.__hash__) - nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h') + nd = ndarray(list(range(-6, 6)), shape=[2, 2, 3], format="h") m = memoryview(nd) self.assertRaises(ValueError, m.__hash__) - nd = ndarray(list(range(12)), shape=[2,2,3], format='= L') + nd = ndarray(list(range(12)), shape=[2, 2, 3], format="= L") m = memoryview(nd) self.assertRaises(ValueError, m.__hash__) - nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h') + nd = ndarray(list(range(-6, 6)), shape=[2, 2, 3], format="< h") m = memoryview(nd) self.assertRaises(ValueError, m.__hash__) def test_memoryview_release(self): - # Create re-exporter from getbuffer(memoryview), then release the view. - a = bytearray([1,2,3]) + a = bytearray([1, 2, 3]) m = memoryview(a) - nd = ndarray(m) # re-exporter + nd = ndarray(m) # re-exporter self.assertRaises(BufferError, m.release) del nd m.release() - a = bytearray([1,2,3]) + a = bytearray([1, 2, 3]) m = memoryview(a) nd1 = ndarray(m, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT) nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT) @@ -4201,16 +4576,16 @@ def test_memoryview_release(self): m.release() # chained views - a = bytearray([1,2,3]) + a = bytearray([1, 2, 3]) m1 = memoryview(a) m2 = memoryview(m1) - nd = ndarray(m2) # re-exporter + nd = ndarray(m2) # re-exporter m1.release() self.assertRaises(BufferError, m2.release) del nd m2.release() - a = bytearray([1,2,3]) + a = bytearray([1, 2, 3]) m1 = memoryview(a) m2 = memoryview(m1) nd1 = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT) @@ -4222,10 +4597,10 @@ def test_memoryview_release(self): m2.release() # Allow changing layout while buffers are exported. - nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT) + nd = ndarray([1, 2, 3], shape=[3], flags=ND_VAREXPORT) m1 = memoryview(nd) - nd.push([4,5,6,7,8], shape=[5]) # mutate nd + nd.push([4, 5, 6, 7, 8], shape=[5]) # mutate nd m2 = memoryview(nd) x = memoryview(m1) @@ -4237,7 +4612,7 @@ def test_memoryview_release(self): m2.release() y.release() - nd.pop() # pop the current view + nd.pop() # pop the current view self.assertEqual(x.tolist(), nd.tolist()) del nd @@ -4251,12 +4626,12 @@ def catch22(b): with memoryview(b) as m2: pass - x = bytearray(b'123') + x = bytearray(b"123") with memoryview(x) as m1: catch22(m1) - self.assertEqual(m1[0], ord(b'1')) + self.assertEqual(m1[0], ord(b"1")) - x = ndarray(list(range(12)), shape=[2,2,3], format='l') + x = ndarray(list(range(12)), shape=[2, 2, 3], format="l") y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT) z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT) self.assertIs(z.obj, x) @@ -4266,7 +4641,7 @@ def catch22(b): # Test garbage collection. for flags in (0, ND_REDIRECT): - x = bytearray(b'123') + x = bytearray(b"123") with memoryview(x) as m1: del x y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags) @@ -4278,14 +4653,14 @@ def catch22(b): catch22(m3) catch22(m2) catch22(m1) - self.assertEqual(m1[0], ord(b'1')) - self.assertEqual(m2[1], ord(b'2')) - self.assertEqual(m3[2], ord(b'3')) + self.assertEqual(m1[0], ord(b"1")) + self.assertEqual(m2[1], ord(b"2")) + self.assertEqual(m3[2], ord(b"3")) del m3 del m2 del m1 - x = bytearray(b'123') + x = bytearray(b"123") with memoryview(x) as m1: del x y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags) @@ -4297,22 +4672,21 @@ def catch22(b): catch22(m1) catch22(m2) catch22(m3) - self.assertEqual(m1[0], ord(b'1')) - self.assertEqual(m2[1], ord(b'2')) - self.assertEqual(m3[2], ord(b'3')) + self.assertEqual(m1[0], ord(b"1")) + self.assertEqual(m2[1], ord(b"2")) + self.assertEqual(m3[2], ord(b"3")) del m1, m2, m3 # memoryview.release() fails if the view has exported buffers. - x = bytearray(b'123') + x = bytearray(b"123") with self.assertRaises(BufferError): with memoryview(x) as m: ex = ndarray(m) - m[0] == ord(b'1') + m[0] == ord(b"1") def test_memoryview_redirect(self): - - nd = ndarray([1.0 * x for x in range(12)], shape=[12], format='d') - a = array.array('d', [1.0 * x for x in range(12)]) + nd = ndarray([1.0 * x for x in range(12)], shape=[12], format="d") + a = array.array("d", [1.0 * x for x in range(12)]) for x in (nd, a): y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT) @@ -4334,9 +4708,8 @@ def test_memoryview_redirect(self): self.assertEqual(m[1:3], x[1:3]) def test_memoryview_from_static_exporter(self): - - fmt = 'B' - lst = [0,1,2,3,4,5,6,7,8,9,10,11] + fmt = "B" + lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] # exceptions self.assertRaises(TypeError, staticarray, 1, 2, 3) @@ -4344,10 +4717,17 @@ def test_memoryview_from_static_exporter(self): # view.obj==x x = staticarray() y = memoryview(x) - self.verify(y, obj=x, - itemsize=1, fmt=fmt, readonly=True, - ndim=1, shape=[12], strides=[1], - lst=lst) + self.verify( + y, + obj=x, + itemsize=1, + fmt=fmt, + readonly=True, + ndim=1, + shape=[12], + strides=[1], + lst=lst, + ) for i in range(12): self.assertEqual(y[i], i) del x @@ -4364,10 +4744,17 @@ def test_memoryview_from_static_exporter(self): m = memoryview(z) self.assertIs(y.obj, x) self.assertIs(m.obj, z) - self.verify(m, obj=z, - itemsize=1, fmt=fmt, readonly=True, - ndim=1, shape=[12], strides=[1], - lst=lst) + self.verify( + m, + obj=z, + itemsize=1, + fmt=fmt, + readonly=True, + ndim=1, + shape=[12], + strides=[1], + lst=lst, + ) del x, y, z, m x = staticarray() @@ -4377,19 +4764,33 @@ def test_memoryview_from_static_exporter(self): self.assertIs(y.obj, x) self.assertIs(z.obj, x) self.assertIs(m.obj, x) - self.verify(m, obj=x, - itemsize=1, fmt=fmt, readonly=True, - ndim=1, shape=[12], strides=[1], - lst=lst) + self.verify( + m, + obj=x, + itemsize=1, + fmt=fmt, + readonly=True, + ndim=1, + shape=[12], + strides=[1], + lst=lst, + ) del x, y, z, m # view.obj==NULL x = staticarray(legacy_mode=True) y = memoryview(x) - self.verify(y, obj=None, - itemsize=1, fmt=fmt, readonly=True, - ndim=1, shape=[12], strides=[1], - lst=lst) + self.verify( + y, + obj=None, + itemsize=1, + fmt=fmt, + readonly=True, + ndim=1, + shape=[12], + strides=[1], + lst=lst, + ) for i in range(12): self.assertEqual(y[i], i) del x @@ -4406,10 +4807,17 @@ def test_memoryview_from_static_exporter(self): m = memoryview(z) self.assertIs(y.obj, None) self.assertIs(m.obj, z) - self.verify(m, obj=z, - itemsize=1, fmt=fmt, readonly=True, - ndim=1, shape=[12], strides=[1], - lst=lst) + self.verify( + m, + obj=z, + itemsize=1, + fmt=fmt, + readonly=True, + ndim=1, + shape=[12], + strides=[1], + lst=lst, + ) del x, y, z, m x = staticarray(legacy_mode=True) @@ -4421,28 +4829,35 @@ def test_memoryview_from_static_exporter(self): self.assertIs(y.obj, None) self.assertIs(z.obj, y) self.assertIs(m.obj, y) - self.verify(m, obj=y, - itemsize=1, fmt=fmt, readonly=True, - ndim=1, shape=[12], strides=[1], - lst=lst) + self.verify( + m, + obj=y, + itemsize=1, + fmt=fmt, + readonly=True, + ndim=1, + shape=[12], + strides=[1], + lst=lst, + ) del x, y, z, m def test_memoryview_getbuffer_undefined(self): - # getbufferproc does not adhere to the new documentation - nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED) + nd = ndarray([1, 2, 3], [3], flags=ND_GETBUF_FAIL | ND_GETBUF_UNDEFINED) self.assertRaises(BufferError, memoryview, nd) def test_issue_7385(self): - x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL) + x = ndarray([1, 2, 3], shape=[3], flags=ND_GETBUF_FAIL) self.assertRaises(BufferError, memoryview, x) @support.cpython_only def test_pybuffer_size_from_format(self): # basic tests - for format in ('', 'ii', '3s'): - self.assertEqual(_testcapi.PyBuffer_SizeFromFormat(format), - struct.calcsize(format)) + for format in ("", "ii", "3s"): + self.assertEqual( + _testcapi.PyBuffer_SizeFromFormat(format), struct.calcsize(format) + ) class TestPythonBufferProtocol(unittest.TestCase): @@ -4539,17 +4954,17 @@ def __buffer__(self, flags): immutable = PossiblyMutable(b"hello", False) with memoryview._from_flags(mutable, inspect.BufferFlags.WRITABLE) as mv: self.assertEqual(mv.tobytes(), b"hello") - mv[0] = ord(b'x') + mv[0] = ord(b"x") self.assertEqual(mv.tobytes(), b"xello") with memoryview._from_flags(mutable, inspect.BufferFlags.SIMPLE) as mv: self.assertEqual(mv.tobytes(), b"xello") with self.assertRaises(TypeError): - mv[0] = ord(b'h') + mv[0] = ord(b"h") self.assertEqual(mv.tobytes(), b"xello") with memoryview._from_flags(immutable, inspect.BufferFlags.SIMPLE) as mv: self.assertEqual(mv.tobytes(), b"hello") with self.assertRaises(TypeError): - mv[0] = ord(b'x') + mv[0] = ord(b"x") self.assertEqual(mv.tobytes(), b"hello") with self.assertRaises(RuntimeError): @@ -4557,7 +4972,7 @@ def __buffer__(self, flags): with memoryview(immutable) as mv: self.assertEqual(mv.tobytes(), b"hello") with self.assertRaises(TypeError): - mv[0] = ord(b'x') + mv[0] = ord(b"x") self.assertEqual(mv.tobytes(), b"hello") def test_call_builtins(self): @@ -4596,9 +5011,11 @@ def __buffer__(self, flags): def test_inheritance_releasebuffer(self): rb_call_count = 0 + class B(bytearray): def __buffer__(self, flags): return super().__buffer__(flags) + def __release_buffer__(self, view): nonlocal rb_call_count rb_call_count += 1 @@ -4621,9 +5038,11 @@ def __buffer__(self, flags): rb_call_count = 0 rb_raised = False + class B(bytearray): def __buffer__(self, flags): return memoryview(b"hello") + def __release_buffer__(self, view): nonlocal rb_call_count rb_call_count += 1 @@ -4742,6 +5161,7 @@ def __buffer__(self, flags): class Releaser: buffer = None + def __release_buffer__(self, buffer): self.buffer = buffer @@ -4759,6 +5179,7 @@ def test_release_buffer_with_exception_set(self): class A: def __buffer__(self, flags): return memoryview(bytes(8)) + def __release_buffer__(self, view): pass diff --git a/Lib/test/test_clinic.py b/Lib/test/test_clinic.py index da957fcebaa296..abd0dbc54d8512 100644 --- a/Lib/test/test_clinic.py +++ b/Lib/test/test_clinic.py @@ -15,21 +15,22 @@ import sys import unittest -test_tools.skip_if_missing('clinic') -with test_tools.imports_under_tool('clinic'): +test_tools.skip_if_missing("clinic") +with test_tools.imports_under_tool("clinic"): import clinic from clinic import DSLParser -def _make_clinic(*, filename='clinic_tests'): +def _make_clinic(*, filename="clinic_tests"): clang = clinic.CLanguage(None) c = clinic.Clinic(clang, filename=filename, limited_capi=False) - c.block_parser = clinic.BlockParser('', clang) + c.block_parser = clinic.BlockParser("", clang) return c -def _expect_failure(tc, parser, code, errmsg, *, filename=None, lineno=None, - strip=True): +def _expect_failure( + tc, parser, code, errmsg, *, filename=None, lineno=None, strip=True +): """Helper for the parser tests. tc: unittest.TestCase; passed self in the wrapper @@ -56,8 +57,9 @@ class ClinicWholeFileTest(TestCase): maxDiff = None def expect_failure(self, raw, errmsg, *, filename=None, lineno=None): - _expect_failure(self, self.clinic.parse, raw, errmsg, - filename=filename, lineno=lineno) + _expect_failure( + self, self.clinic.parse, raw, errmsg, filename=filename, lineno=lineno + ) def setUp(self): self.clinic = _make_clinic(filename="test.c") @@ -97,8 +99,10 @@ def test_checksum_mismatch(self): [clinic start generated code]*/ /*[clinic end generated code: output=0123456789abcdef input=fedcba9876543210]*/ """ - err = ("Checksum mismatch! " - "Expected '0123456789abcdef', computed 'da39a3ee5e6b4b0d'") + err = ( + "Checksum mismatch! " + "Expected '0123456789abcdef', computed 'da39a3ee5e6b4b0d'" + ) self.expect_failure(raw, err, filename="test.c", lineno=3) def test_garbage_after_stop_line(self): @@ -126,19 +130,23 @@ def test_parse_with_body_prefix(self): clang.start_line = "//[{dsl_name} start]" clang.stop_line = "//[{dsl_name} stop]" cl = clinic.Clinic(clang, filename="test.c", limited_capi=False) - raw = dedent(""" + raw = dedent( + """ //[clinic start] //module test //[clinic stop] - """).strip() + """ + ).strip() out = cl.parse(raw) - expected = dedent(""" + expected = dedent( + """ //[clinic start] //module test // //[clinic stop] /*[clinic end generated code: output=da39a3ee5e6b4b0d input=65fab8adff58cf08]*/ - """).lstrip() # Note, lstrip() because of the newline + """ + ).lstrip() # Note, lstrip() because of the newline self.assertEqual(out, expected) def test_cpp_monitor_fail_nested_block_comment(self): @@ -148,7 +156,7 @@ def test_cpp_monitor_fail_nested_block_comment(self): */ */ """ - err = 'Nested block comment!' + err = "Nested block comment!" self.expect_failure(raw, err, filename="test.c", lineno=2) def test_cpp_monitor_fail_invalid_format_noarg(self): @@ -157,7 +165,7 @@ def test_cpp_monitor_fail_invalid_format_noarg(self): a() #endif """ - err = 'Invalid format for #if line: no argument!' + err = "Invalid format for #if line: no argument!" self.expect_failure(raw, err, filename="test.c", lineno=1) def test_cpp_monitor_fail_invalid_format_toomanyargs(self): @@ -166,12 +174,12 @@ def test_cpp_monitor_fail_invalid_format_toomanyargs(self): a() #endif """ - err = 'Invalid format for #ifdef line: should be exactly one argument!' + err = "Invalid format for #ifdef line: should be exactly one argument!" self.expect_failure(raw, err, filename="test.c", lineno=1) def test_cpp_monitor_fail_no_matching_if(self): - raw = '#else' - err = '#else without matching #if / #ifdef / #ifndef!' + raw = "#else" + err = "#else without matching #if / #ifdef / #ifndef!" self.expect_failure(raw, err, filename="test.c", lineno=1) def test_directive_output_unknown_preset(self): @@ -193,20 +201,28 @@ def test_directive_output_cant_pop(self): self.expect_failure(raw, err) def test_directive_output_print(self): - raw = dedent(""" + raw = dedent( + """ /*[clinic input] output print 'I told you once.' [clinic start generated code]*/ - """) + """ + ) out = self.clinic.parse(raw) # The generated output will differ for every run, but we can check that # it starts with the clinic block, we check that it contains all the # expected fields, and we check that it contains the checksum line. - self.assertTrue(out.startswith(dedent(""" + self.assertTrue( + out.startswith( + dedent( + """ /*[clinic input] output print 'I told you once.' [clinic start generated code]*/ - """))) + """ + ) + ) + ) fields = { "cpp_endif", "cpp_if", @@ -223,16 +239,16 @@ def test_directive_output_print(self): with self.subTest(field=field): self.assertIn(field, out) last_line = out.rstrip().split("\n")[-1] - self.assertTrue( - last_line.startswith("/*[clinic end generated code: output=") - ) + self.assertTrue(last_line.startswith("/*[clinic end generated code: output=")) def test_directive_wrong_arg_number(self): - raw = dedent(""" + raw = dedent( + """ /*[clinic input] preserve foo bar baz eggs spam ham mushrooms [clinic start generated code]*/ - """) + """ + ) err = "takes 1 positional argument but 8 were given" self.expect_failure(raw, err) @@ -259,9 +275,7 @@ def converter_init(self): a: Custom [clinic start generated code]*/ """ - err = ( - "accessing self.function inside converter_init is disallowed!" - ) + err = "accessing self.function inside converter_init is disallowed!" self.expect_failure(raw, err) @staticmethod @@ -278,31 +292,30 @@ def _clinic_version(new_version): def test_version_directive(self): dataset = ( # (clinic version, required version) - ('3', '2'), # required version < clinic version - ('3.1', '3.0'), # required version < clinic version - ('1.2b0', '1.2a7'), # required version < clinic version - ('5', '5'), # required version == clinic version - ('6.1', '6.1'), # required version == clinic version - ('1.2b3', '1.2b3'), # required version == clinic version + ("3", "2"), # required version < clinic version + ("3.1", "3.0"), # required version < clinic version + ("1.2b0", "1.2a7"), # required version < clinic version + ("5", "5"), # required version == clinic version + ("6.1", "6.1"), # required version == clinic version + ("1.2b3", "1.2b3"), # required version == clinic version ) for clinic_version, required_version in dataset: - with self.subTest(clinic_version=clinic_version, - required_version=required_version): + with self.subTest( + clinic_version=clinic_version, required_version=required_version + ): with self._clinic_version(clinic_version): - block = dedent(f""" + block = dedent( + f""" /*[clinic input] version {required_version} [clinic start generated code]*/ - """) + """ + ) self.clinic.parse(block) def test_version_directive_insufficient_version(self): - with self._clinic_version('4'): - err = ( - "Insufficient Clinic version!\n" - " Version: 4\n" - " Required: 5" - ) + with self._clinic_version("4"): + err = "Insufficient Clinic version!\n" " Version: 4\n" " Required: 5" block = """ /*[clinic input] version 5 @@ -423,9 +436,11 @@ class C "" "" self.expect_failure(block, err, lineno=3) def test_dest_buffer_not_empty_at_eof(self): - expected_warning = ("Destination buffer 'buffer' not empty at " - "end of file, emptying.") - expected_generated = dedent(""" + expected_warning = ( + "Destination buffer 'buffer' not empty at " "end of file, emptying." + ) + expected_generated = dedent( + """ /*[clinic input] output everything buffer fn @@ -451,15 +466,18 @@ def test_dest_buffer_not_empty_at_eof(self): static PyObject * fn(PyObject *module, PyObject *a) /*[clinic end generated code: output=be6798b148ab4e53 input=524ce2e021e4eba6]*/ - """) - block = dedent(""" + """ + ) + block = dedent( + """ /*[clinic input] output everything buffer fn a: object / [clinic start generated code]*/ - """) + """ + ) with support.captured_stdout() as stdout: generated = self.clinic.parse(block) self.assertIn(expected_warning, stdout.getvalue()) @@ -484,7 +502,8 @@ def test_directive_set_misuse(self): self.expect_failure(block, err, lineno=2) def test_directive_set_prefix(self): - block = dedent(""" + block = dedent( + """ /*[clinic input] set line_prefix '// ' output everything suppress @@ -498,13 +517,15 @@ def test_directive_set_prefix(self): /*[clinic input] dump buffer [clinic start generated code]*/ - """) + """ + ) generated = self.clinic.parse(block) expected_docstring_prototype = "// PyDoc_VAR(fn__doc__);" self.assertIn(expected_docstring_prototype, generated) def test_directive_set_suffix(self): - block = dedent(""" + block = dedent( + """ /*[clinic input] set line_suffix ' // test' output everything suppress @@ -518,13 +539,15 @@ def test_directive_set_suffix(self): /*[clinic input] dump buffer [clinic start generated code]*/ - """) + """ + ) generated = self.clinic.parse(block) expected_docstring_prototype = "PyDoc_VAR(fn__doc__); // test" self.assertIn(expected_docstring_prototype, generated) def test_directive_set_prefix_and_suffix(self): - block = dedent(""" + block = dedent( + """ /*[clinic input] set line_prefix '{block comment start} ' set line_suffix ' {block comment end}' @@ -539,26 +562,31 @@ def test_directive_set_prefix_and_suffix(self): /*[clinic input] dump buffer [clinic start generated code]*/ - """) + """ + ) generated = self.clinic.parse(block) expected_docstring_prototype = "/* PyDoc_VAR(fn__doc__); */" self.assertIn(expected_docstring_prototype, generated) def test_directive_printout(self): - block = dedent(""" + block = dedent( + """ /*[clinic input] output everything buffer printout test [clinic start generated code]*/ - """) - expected = dedent(""" + """ + ) + expected = dedent( + """ /*[clinic input] output everything buffer printout test [clinic start generated code]*/ test /*[clinic end generated code: output=4e1243bd22c66e76 input=898f1a32965d44ca]*/ - """) + """ + ) generated = self.clinic.parse(block) self.assertEqual(generated, expected) @@ -585,7 +613,8 @@ def test_directive_preserve_input(self): self.expect_failure(block, err, lineno=6) def test_directive_preserve_output(self): - block = dedent(""" + block = dedent( + """ /*[clinic input] output everything buffer preserve @@ -596,12 +625,14 @@ def test_directive_preserve_output(self): dump buffer [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ - """) + """ + ) generated = self.clinic.parse(block) self.assertEqual(generated, block) def test_directive_output_invalid_command(self): - err = dedent(""" + err = dedent( + """ Invalid command or destination name 'cmd'. Must be one of: - 'preset' - 'push' @@ -618,7 +649,8 @@ def test_directive_output_invalid_command(self): - 'cpp_endif' - 'methoddef_ifndef' - 'impl_definition' - """).strip() + """ + ).strip() block = """ /*[clinic input] output cmd buffer @@ -668,7 +700,8 @@ def test_no_c_basename_cloned(self): self.expect_failure(block, err, lineno=5) def test_cloned_with_custom_c_basename(self): - raw = dedent(""" + raw = dedent( + """ /*[clinic input] # Make sure we don't create spurious clinic/ directories. output everything suppress @@ -678,7 +711,8 @@ def test_cloned_with_custom_c_basename(self): /*[clinic input] foo as foo1 = foo2 [clinic start generated code]*/ - """) + """ + ) self.clinic.parse(raw) funcs = self.clinic.functions self.assertEqual(len(funcs), 2) @@ -710,8 +744,7 @@ def expect_parsing_failure( def test_parse_file_no_extension(self) -> None: self.expect_parsing_failure( - filename="foo", - expected_error="Can't extract file type for file 'foo'" + filename="foo", expected_error="Can't extract file type for file 'foo'" ) def test_parse_file_strange_extension(self) -> None: @@ -731,45 +764,65 @@ def _test(self, l, m, r, output): self.assertEqual(output, computed) def test_range(self): - self._test([['start']], ['stop'], [['step']], - ( - ('stop',), - ('start', 'stop',), - ('start', 'stop', 'step',), - )) + self._test( + [["start"]], + ["stop"], + [["step"]], + ( + ("stop",), + ( + "start", + "stop", + ), + ( + "start", + "stop", + "step", + ), + ), + ) def test_add_window(self): - self._test([['x', 'y']], ['ch'], [['attr']], - ( - ('ch',), - ('ch', 'attr'), - ('x', 'y', 'ch',), - ('x', 'y', 'ch', 'attr'), - )) + self._test( + [["x", "y"]], + ["ch"], + [["attr"]], + ( + ("ch",), + ("ch", "attr"), + ( + "x", + "y", + "ch", + ), + ("x", "y", "ch", "attr"), + ), + ) def test_ludicrous(self): - self._test([['a1', 'a2', 'a3'], ['b1', 'b2']], ['c1'], [['d1', 'd2'], ['e1', 'e2', 'e3']], - ( - ('c1',), - ('b1', 'b2', 'c1'), - ('b1', 'b2', 'c1', 'd1', 'd2'), - ('a1', 'a2', 'a3', 'b1', 'b2', 'c1'), - ('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2'), - ('a1', 'a2', 'a3', 'b1', 'b2', 'c1', 'd1', 'd2', 'e1', 'e2', 'e3'), - )) + self._test( + [["a1", "a2", "a3"], ["b1", "b2"]], + ["c1"], + [["d1", "d2"], ["e1", "e2", "e3"]], + ( + ("c1",), + ("b1", "b2", "c1"), + ("b1", "b2", "c1", "d1", "d2"), + ("a1", "a2", "a3", "b1", "b2", "c1"), + ("a1", "a2", "a3", "b1", "b2", "c1", "d1", "d2"), + ("a1", "a2", "a3", "b1", "b2", "c1", "d1", "d2", "e1", "e2", "e3"), + ), + ) def test_right_only(self): - self._test([], [], [['a'],['b'],['c']], - ( - (), - ('a',), - ('a', 'b'), - ('a', 'b', 'c') - )) + self._test( + [], [], [["a"], ["b"], ["c"]], ((), ("a",), ("a", "b"), ("a", "b", "c")) + ) def test_have_left_options_but_required_is_empty(self): def fn(): - clinic.permute_optional_groups(['a'], [], []) + clinic.permute_optional_groups(["a"], [], []) + self.assertRaises(ValueError, fn) @@ -779,51 +832,67 @@ def _test(self, input, output, **kwargs): self.assertEqual(output, computed) def test_empty_strings(self): - self._test('', '') + self._test("", "") def test_solo_newline(self): - self._test('\n', '\n') + self._test("\n", "\n") def test_no_substitution(self): - self._test(""" + self._test( + """ abc - """, """ + """, + """ abc - """) + """, + ) def test_empty_substitution(self): - self._test(""" + self._test( + """ abc {name} def - """, """ + """, + """ abc def - """, name='') + """, + name="", + ) def test_single_line_substitution(self): - self._test(""" + self._test( + """ abc {name} def - """, """ + """, + """ abc GARGLE def - """, name='GARGLE') + """, + name="GARGLE", + ) def test_multiline_substitution(self): - self._test(""" + self._test( + """ abc {name} def - """, """ + """, + """ abc bingle bungle def - """, name='bingle\nbungle\n') + """, + name="bingle\nbungle\n", + ) + class InertParser: def __init__(self, clinic): @@ -832,6 +901,7 @@ def __init__(self, clinic): def parse(self, block): pass + class CopyParser: def __init__(self, clinic): pass @@ -848,20 +918,28 @@ def _test(self, input, output): writer = clinic.BlockPrinter(language) c = _make_clinic() for block in blocks: - writer.print_block(block, limited_capi=c.limited_capi, header_includes=c.includes) + writer.print_block( + block, limited_capi=c.limited_capi, header_includes=c.includes + ) output = writer.f.getvalue() - assert output == input, "output != input!\n\noutput " + repr(output) + "\n\n input " + repr(input) + assert output == input, ( + "output != input!\n\noutput " + repr(output) + "\n\n input " + repr(input) + ) def round_trip(self, input): return self._test(input, input) def test_round_trip_1(self): - self.round_trip(""" + self.round_trip( + """ verbatim text here lah dee dah - """) + """ + ) + def test_round_trip_2(self): - self.round_trip(""" + self.round_trip( + """ verbatim text here lah dee dah /*[inert] @@ -870,18 +948,20 @@ def test_round_trip_2(self): def /*[inert checksum: 7b18d017f89f61cf17d47f92749ea6930a3f1deb]*/ xyz -""") +""" + ) def _test_clinic(self, input, output): language = clinic.CLanguage(None) c = clinic.Clinic(language, filename="file", limited_capi=False) - c.parsers['inert'] = InertParser(c) - c.parsers['copy'] = CopyParser(c) + c.parsers["inert"] = InertParser(c) + c.parsers["copy"] = CopyParser(c) computed = c.parse(input) self.assertEqual(output, computed) def test_clinic_1(self): - self._test_clinic(""" + self._test_clinic( + """ verbatim text here lah dee dah /*[copy input] @@ -890,7 +970,8 @@ def test_clinic_1(self): abc /*[copy end generated code: output=03cfd743661f0797 input=7b18d017f89f61cf]*/ xyz -""", """ +""", + """ verbatim text here lah dee dah /*[copy input] @@ -899,11 +980,11 @@ def test_clinic_1(self): def /*[copy end generated code: output=7b18d017f89f61cf input=7b18d017f89f61cf]*/ xyz -""") +""", + ) class ClinicParserTest(TestCase): - def parse(self, text): c = _make_clinic() parser = DSLParser(c) @@ -919,77 +1000,96 @@ def parse_function(self, text, signatures_in_block=2, function_index=1): assert isinstance(s[function_index], clinic.Function) return s[function_index] - def expect_failure(self, block, err, *, - filename=None, lineno=None, strip=True): - return _expect_failure(self, self.parse_function, block, err, - filename=filename, lineno=lineno, strip=strip) + def expect_failure(self, block, err, *, filename=None, lineno=None, strip=True): + return _expect_failure( + self, + self.parse_function, + block, + err, + filename=filename, + lineno=lineno, + strip=strip, + ) def checkDocstring(self, fn, expected): self.assertTrue(hasattr(fn, "docstring")) - self.assertEqual(dedent(expected).strip(), - fn.docstring.strip()) + self.assertEqual(dedent(expected).strip(), fn.docstring.strip()) def test_trivial(self): parser = DSLParser(_make_clinic()) - block = clinic.Block(""" + block = clinic.Block( + """ module os os.access - """) + """ + ) parser.parse(block) module, function = block.signatures self.assertEqual("access", function.name) self.assertEqual("os", module.name) def test_ignore_line(self): - block = self.parse(dedent(""" + block = self.parse( + dedent( + """ # module os os.access - """)) + """ + ) + ) module, function = block.signatures self.assertEqual("access", function.name) self.assertEqual("os", module.name) def test_param(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.access path: int - """) + """ + ) self.assertEqual("access", function.name) self.assertEqual(2, len(function.parameters)) - p = function.parameters['path'] - self.assertEqual('path', p.name) + p = function.parameters["path"] + self.assertEqual("path", p.name) self.assertIsInstance(p.converter, clinic.int_converter) def test_param_default(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.access follow_symlinks: bool = True - """) - p = function.parameters['follow_symlinks'] + """ + ) + p = function.parameters["follow_symlinks"] self.assertEqual(True, p.default) def test_param_with_continuations(self): - function = self.parse_function(r""" + function = self.parse_function( + r""" module os os.access follow_symlinks: \ bool \ = \ True - """) - p = function.parameters['follow_symlinks'] + """ + ) + p = function.parameters["follow_symlinks"] self.assertEqual(True, p.default) def test_param_default_expr_named_constant(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.access follow_symlinks: int(c_default='MAXSIZE') = sys.maxsize - """) - p = function.parameters['follow_symlinks'] + """ + ) + p = function.parameters["follow_symlinks"] self.assertEqual(sys.maxsize, p.default) self.assertEqual("MAXSIZE", p.converter.c_default) @@ -1014,7 +1114,7 @@ def test_param_with_bizarre_default_fails_correctly(self): for bad_default_value in ( "{1, 2, 3}", "3 if bool() else 4", - "[x for x in range(42)]" + "[x for x in range(42)]", ): with self.subTest(bad_default=bad_default_value): block = template.format(default=bad_default_value) @@ -1028,7 +1128,7 @@ def test_unspecified_not_allowed_as_default_value(self): """ err = "'unspecified' is not a legal default value!" exc = self.expect_failure(block, err, lineno=2) - self.assertNotIn('Malformed expression given as default value', str(exc)) + self.assertNotIn("Malformed expression given as default value", str(exc)) def test_malformed_expression_as_default_value(self): block = """ @@ -1051,14 +1151,16 @@ def test_param_default_expr_binop(self): self.expect_failure(block, err, lineno=1) def test_param_no_docstring(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.access follow_symlinks: bool = True something_else: str = '' - """) + """ + ) self.assertEqual(3, len(function.parameters)) - conv = function.parameters['something_else'].converter + conv = function.parameters["something_else"].converter self.assertIsInstance(conv, clinic.str_converter) def test_param_default_parameters_out_of_order(self): @@ -1075,16 +1177,19 @@ def test_param_default_parameters_out_of_order(self): self.expect_failure(block, err, lineno=3) def disabled_test_converter_arguments(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.access path: path_t(allow_fd=1) - """) - p = function.parameters['path'] - self.assertEqual(1, p.converter.args['allow_fd']) + """ + ) + p = function.parameters["path"] + self.assertEqual(1, p.converter.args["allow_fd"]) def test_function_docstring(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.stat as os_stat_fn @@ -1096,8 +1201,11 @@ def test_function_docstring(self): Ensure that multiple lines are indented correctly. Ensure that multiple lines are indented correctly. - """) - self.checkDocstring(function, """ + """ + ) + self.checkDocstring( + function, + """ stat($module, /, path) -- @@ -1109,7 +1217,8 @@ def test_function_docstring(self): Ensure that multiple lines are indented correctly. Ensure that multiple lines are indented correctly. - """) + """, + ) def test_docstring_trailing_whitespace(self): function = self.parse_function( @@ -1121,7 +1230,9 @@ def test_docstring_trailing_whitespace(self): " \n" "Func docstring body with trailing whitespace \n" ) - self.checkDocstring(function, """ + self.checkDocstring( + function, + """ s($module, /, a) -- @@ -1131,10 +1242,13 @@ def test_docstring_trailing_whitespace(self): Param docstring with trailing whitespace Func docstring body with trailing whitespace - """) + """, + ) def test_explicit_parameters_in_docstring(self): - function = self.parse_function(dedent(""" + function = self.parse_function( + dedent( + """ module foo foo.bar x: int @@ -1144,8 +1258,12 @@ def test_explicit_parameters_in_docstring(self): This is the documentation for foo. Okay, we're done here. - """)) - self.checkDocstring(function, """ + """ + ) + ) + self.checkDocstring( + function, + """ bar($module, /, x, y) -- @@ -1155,10 +1273,13 @@ def test_explicit_parameters_in_docstring(self): Documentation for x. Okay, we're done here. - """) + """, + ) def test_docstring_with_comments(self): - function = self.parse_function(dedent(""" + function = self.parse_function( + dedent( + """ module foo foo.bar x: int @@ -1176,8 +1297,12 @@ def test_docstring_with_comments(self): # the documentation for foo. Okay, we're done here. - """)) - self.checkDocstring(function, """ + """ + ) + ) + self.checkDocstring( + function, + """ bar($module, /, x, y) -- @@ -1187,27 +1312,39 @@ def test_docstring_with_comments(self): Documentation for x. Okay, we're done here. - """) + """, + ) - def test_parser_regression_special_character_in_parameter_column_of_docstring_first_line(self): - function = self.parse_function(dedent(""" + def test_parser_regression_special_character_in_parameter_column_of_docstring_first_line( + self + ): + function = self.parse_function( + dedent( + """ module os os.stat path: str This/used to break Clinic! - """)) - self.checkDocstring(function, """ + """ + ) + ) + self.checkDocstring( + function, + """ stat($module, /, path) -- This/used to break Clinic! - """) + """, + ) def test_c_name(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.stat as os_stat_fn - """) + """ + ) self.assertEqual("os_stat_fn", function.c_basename) def test_base_invalid_syntax(self): @@ -1216,10 +1353,12 @@ def test_base_invalid_syntax(self): os.stat invalid syntax: int = 42 """ - err = dedent(r""" + err = dedent( + r""" Function 'stat' has an invalid parameter declaration: \s+'invalid syntax: int = 42' - """).strip() + """ + ).strip() with self.assertRaisesRegex(clinic.ClinicError, err): self.parse_function(block) @@ -1240,18 +1379,22 @@ def test_cloning_nonexistent_function_correctly_fails(self): err = "Couldn't find existing function 'fooooooooooooooooo'!" with support.captured_stderr() as stderr: self.expect_failure(block, err, lineno=0) - expected_debug_print = dedent("""\ + expected_debug_print = dedent( + """\ cls=None, module=, existing='fooooooooooooooooo' (cls or module).functions=[] - """) + """ + ) stderr = stderr.getvalue() self.assertIn(expected_debug_print, stderr) def test_return_converter(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.stat -> int - """) + """ + ) self.assertIsInstance(function.return_converter, clinic.int_return_converter) def test_return_converter_invalid_syntax(self): @@ -1279,30 +1422,35 @@ def test_unknown_return_converter(self): self.expect_failure(block, err) def test_star(self): - function = self.parse_function(""" + function = self.parse_function( + """ module os os.access * follow_symlinks: bool = True - """) - p = function.parameters['follow_symlinks'] + """ + ) + p = function.parameters["follow_symlinks"] self.assertEqual(inspect.Parameter.KEYWORD_ONLY, p.kind) self.assertEqual(0, p.group) def test_group(self): - function = self.parse_function(""" + function = self.parse_function( + """ module window window.border [ ls: int ] / - """) - p = function.parameters['ls'] + """ + ) + p = function.parameters["ls"] self.assertEqual(1, p.group) def test_left_group(self): - function = self.parse_function(""" + function = self.parse_function( + """ module curses curses.addch [ @@ -1318,18 +1466,22 @@ def test_left_group(self): Attributes for the character. ] / - """) + """ + ) dataset = ( - ('y', -1), ('x', -1), - ('ch', 0), - ('attr', 1), + ("y", -1), + ("x", -1), + ("ch", 0), + ("attr", 1), ) for name, group in dataset: with self.subTest(name=name, group=group): p = function.parameters[name] self.assertEqual(p.group, group) self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) - self.checkDocstring(function, """ + self.checkDocstring( + function, + """ addch([y, x,] ch, [attr]) @@ -1341,10 +1493,12 @@ def test_left_group(self): Character to add. attr Attributes for the character. - """) + """, + ) def test_nested_groups(self): - function = self.parse_function(""" + function = self.parse_function( + """ module curses curses.imaginary [ @@ -1378,13 +1532,20 @@ def test_nested_groups(self): ] ] / - """) + """ + ) dataset = ( - ('y1', -2), ('y2', -2), - ('x1', -1), ('x2', -1), - ('ch', 0), - ('attr1', 1), ('attr2', 1), ('attr3', 1), - ('attr4', 2), ('attr5', 2), ('attr6', 2), + ("y1", -2), + ("y2", -2), + ("x1", -1), + ("x2", -1), + ("ch", 0), + ("attr1", 1), + ("attr2", 1), + ("attr3", 1), + ("attr4", 2), + ("attr5", 2), + ("attr6", 2), ) for name, group in dataset: with self.subTest(name=name, group=group): @@ -1392,7 +1553,9 @@ def test_nested_groups(self): self.assertEqual(p.group, group) self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) - self.checkDocstring(function, """ + self.checkDocstring( + function, + """ imaginary([[y1, y2,] x1, x2,] ch, [attr1, attr2, attr3, [attr4, attr5, attr6]]) @@ -1419,7 +1582,8 @@ def test_nested_groups(self): Attributes for the character. attr6 Attributes for the character. - """) + """, + ) def test_disallowed_grouping__two_top_groups_on_left(self): err = ( @@ -1540,18 +1704,21 @@ def test_disallowed_grouping__no_matching_bracket(self): self.expect_failure(block, err) def test_disallowed_grouping__must_be_position_only(self): - dataset = (""" + dataset = ( + """ with_kwds [ * a: object ] - """, """ + """, + """ with_kwds [ a: object ] - """) + """, + ) err = ( "You cannot use optional groups ('[' and ']') unless all " "parameters are positional-only ('/')" @@ -1561,25 +1728,31 @@ def test_disallowed_grouping__must_be_position_only(self): self.expect_failure(block, err) def test_no_parameters(self): - function = self.parse_function(""" + function = self.parse_function( + """ module foo foo.bar Docstring - """) + """ + ) self.assertEqual("bar($module, /)\n--\n\nDocstring", function.docstring) - self.assertEqual(1, len(function.parameters)) # self! + self.assertEqual(1, len(function.parameters)) # self! def test_init_with_no_parameters(self): - function = self.parse_function(""" + function = self.parse_function( + """ module foo class foo.Bar "unused" "notneeded" foo.Bar.__init__ Docstring - """, signatures_in_block=3, function_index=2) + """, + signatures_in_block=3, + function_index=2, + ) # self is not in the signature self.assertEqual("Bar()\n--\n\nDocstring", function.docstring) @@ -1633,22 +1806,31 @@ def test_parameters_required_after_star(self): def test_fulldisplayname_class(self): dataset = ( - ("T", """ + ( + "T", + """ class T "void *" "" T.__init__ - """), - ("m.T", """ + """, + ), + ( + "m.T", + """ module m class m.T "void *" "" @classmethod m.T.__new__ - """), - ("m.T.C", """ + """, + ), + ( + "m.T.C", + """ module m class m.T "void *" "" class m.T.C "void *" "" m.T.C.__init__ - """), + """, + ), ) for name, code in dataset: with self.subTest(name=name, code=code): @@ -1659,25 +1841,37 @@ class m.T.C "void *" "" def test_fulldisplayname_meth(self): dataset = ( ("func", "func"), - ("m.func", """ + ( + "m.func", + """ module m m.func - """), - ("T.meth", """ + """, + ), + ( + "T.meth", + """ class T "void *" "" T.meth - """), - ("m.T.meth", """ + """, + ), + ( + "m.T.meth", + """ module m class m.T "void *" "" m.T.meth - """), - ("m.T.C.meth", """ + """, + ), + ( + "m.T.C.meth", + """ module m class m.T "void *" "" class m.T.C "void *" "" m.T.C.meth - """), + """, + ), ) for name, code in dataset: with self.subTest(name=name, code=code): @@ -1735,10 +1929,7 @@ def test_parameters_required_after_depr_star(self): * [from 3.14] Docstring. """ - err = ( - "Function 'bar' specifies '* [from ...]' without " - "following parameters." - ) + err = "Function 'bar' specifies '* [from ...]' without " "following parameters." self.expect_failure(block, err, lineno=4) def test_parameters_required_after_depr_star2(self): @@ -1751,10 +1942,7 @@ def test_parameters_required_after_depr_star2(self): b: int Docstring. """ - err = ( - "Function 'bar' specifies '* [from ...]' without " - "following parameters." - ) + err = "Function 'bar' specifies '* [from ...]' without " "following parameters." self.expect_failure(block, err, lineno=4) def test_depr_star_must_come_before_star(self): @@ -1845,10 +2033,7 @@ def test_parameters_required_before_depr_slash(self): / [from 3.14] Docstring. """ - err = ( - "Function 'bar' specifies '/ [from ...]' without " - "preceding parameters." - ) + err = "Function 'bar' specifies '/ [from ...]' without " "preceding parameters." self.expect_failure(block, err, lineno=2) def test_parameters_required_before_depr_slash2(self): @@ -1860,10 +2045,7 @@ def test_parameters_required_before_depr_slash2(self): / [from 3.14] Docstring. """ - err = ( - "Function 'bar' specifies '/ [from ...]' without " - "preceding parameters." - ) + err = "Function 'bar' specifies '/ [from ...]' without " "preceding parameters." self.expect_failure(block, err, lineno=4) def test_double_slash(self): @@ -1967,7 +2149,8 @@ def test_parameters_no_more_than_one_vararg(self): self.expect_failure(block, err, lineno=0) def test_function_not_at_column_0(self): - function = self.parse_function(""" + function = self.parse_function( + """ module foo foo.bar x: int @@ -1975,8 +2158,11 @@ def test_function_not_at_column_0(self): * y: str Not at column 0! - """) - self.checkDocstring(function, """ + """ + ) + self.checkDocstring( + function, + """ bar($module, /, x, *, y) -- @@ -1984,35 +2170,47 @@ def test_function_not_at_column_0(self): x Nested docstring here, goeth. - """) + """, + ) def test_docstring_only_summary(self): - function = self.parse_function(""" + function = self.parse_function( + """ module m m.f summary - """) - self.checkDocstring(function, """ + """ + ) + self.checkDocstring( + function, + """ f($module, /) -- summary - """) + """, + ) def test_docstring_empty_lines(self): - function = self.parse_function(""" + function = self.parse_function( + """ module m m.f - """) - self.checkDocstring(function, """ + """ + ) + self.checkDocstring( + function, + """ f($module, /) -- - """) + """, + ) def test_docstring_explicit_params_placement(self): - function = self.parse_function(""" + function = self.parse_function( + """ module m m.f a: int @@ -2026,8 +2224,11 @@ def test_docstring_explicit_params_placement(self): {parameters} And now for something completely different! (Note the added newline) - """) - self.checkDocstring(function, """ + """ + ) + self.checkDocstring( + function, + """ f($module, /, a, b, c) -- @@ -2041,7 +2242,8 @@ def test_docstring_explicit_params_placement(self): And now for something completely different! (Note the added newline) - """) + """, + ) def test_indent_stack_no_tabs(self): block = """ @@ -2050,8 +2252,7 @@ def test_indent_stack_no_tabs(self): *vararg1: object \t*vararg2: object """ - err = ("Tab characters are illegal in the Clinic DSL: " - r"'\t*vararg2: object'") + err = "Tab characters are illegal in the Clinic DSL: " r"'\t*vararg2: object'" self.expect_failure(block, err) def test_indent_stack_illegal_outdent(self): @@ -2067,7 +2268,7 @@ def test_indent_stack_illegal_outdent(self): def test_directive(self): parser = DSLParser(_make_clinic()) parser.flag = False - parser.directives['setflag'] = lambda : setattr(parser, 'flag', True) + parser.directives["setflag"] = lambda: setattr(parser, "flag", True) block = clinic.Block("setflag") parser.parse(block) self.assertTrue(parser.flag) @@ -2075,15 +2276,15 @@ def test_directive(self): def test_legacy_converters(self): block = self.parse('module os\nos.access\n path: "s"') module, function = block.signatures - conv = (function.parameters['path']).converter + conv = (function.parameters["path"]).converter self.assertIsInstance(conv, clinic.str_converter) def test_legacy_converters_non_string_constant_annotation(self): err = "Annotations must be either a name, a function call, or a string" dataset = ( - 'module os\nos.access\n path: 42', - 'module os\nos.access\n path: 42.42', - 'module os\nos.access\n path: 42j', + "module os\nos.access\n path: 42", + "module os\nos.access\n path: 42.42", + "module os\nos.access\n path: 42j", 'module os\nos.access\n path: b"42"', ) for block in dataset: @@ -2095,7 +2296,7 @@ def test_other_bizarre_things_in_annotations_fail(self): dataset = ( 'module os\nos.access\n path: {"some": "dictionary"}', 'module os\nos.access\n path: ["list", "of", "strings"]', - 'module os\nos.access\n path: (x for x in range(42))', + "module os\nos.access\n path: (x for x in range(42))", ) for block in dataset: with self.subTest(block=block): @@ -2200,7 +2401,8 @@ def test_duplicate_coexist(self): self.expect_failure(block, err, lineno=2) def test_unused_param(self): - block = self.parse(""" + block = self.parse( + """ module foo foo.func fn: object @@ -2209,7 +2411,8 @@ def test_unused_param(self): / * flag: bool(unused=True) = False - """) + """ + ) sig = block.signatures[1] # Function index == 1 params = sig.parameters conv = lambda fn: params[fn].converter @@ -2239,16 +2442,16 @@ def test_unused_param(self): def test_scaffolding(self): # test repr on special values - self.assertEqual(repr(clinic.unspecified), '') - self.assertEqual(repr(clinic.NULL), '') + self.assertEqual(repr(clinic.unspecified), "") + self.assertEqual(repr(clinic.NULL), "") # test that fail fails with support.captured_stdout() as stdout: - errmsg = 'The igloos are melting' + errmsg = "The igloos are melting" with self.assertRaisesRegex(clinic.ClinicError, errmsg) as cm: - clinic.fail(errmsg, filename='clown.txt', line_number=69) + clinic.fail(errmsg, filename="clown.txt", line_number=69) exc = cm.exception - self.assertEqual(exc.filename, 'clown.txt') + self.assertEqual(exc.filename, "clown.txt") self.assertEqual(exc.lineno, 69) self.assertEqual(stdout.getvalue(), "") @@ -2263,14 +2466,16 @@ def test_non_ascii_character_in_docstring(self): with support.captured_stdout() as stdout: self.parse(block) # The line numbers are off; this is a known limitation. - expected = dedent("""\ + expected = dedent( + """\ Warning in file 'clinic_tests' on line 0: Non-ascii characters are not allowed in docstrings: 'á' Warning in file 'clinic_tests' on line 0: Non-ascii characters are not allowed in docstrings: 'ü', 'á', 'ß' - """) + """ + ) self.assertEqual(stdout.getvalue(), expected) def test_illegal_c_identifier(self): @@ -2307,8 +2512,7 @@ def test_vararg_cannot_take_default_value(self): self.expect_failure(block, err, lineno=1) def test_default_is_not_of_correct_type(self): - err = ("int_converter: default value 2.5 for field 'a' " - "is not of type 'int'") + err = "int_converter: default value 2.5 for field 'a' " "is not of type 'int'" block = """ fn a: int = 2.5 @@ -2392,7 +2596,7 @@ def run_clinic(self, *args): with ( support.captured_stdout() as out, support.captured_stderr() as err, - self.assertRaises(SystemExit) as cm + self.assertRaises(SystemExit) as cm, ): clinic.main(args) return out.getvalue(), err.getvalue(), cm.exception.code @@ -2410,9 +2614,9 @@ def expect_failure(self, *args): return out, err def test_external(self): - CLINIC_TEST = 'clinic.test.c' + CLINIC_TEST = "clinic.test.c" source = support.findfile(CLINIC_TEST) - with open(source, encoding='utf-8') as f: + with open(source, encoding="utf-8") as f: orig_contents = f.read() # Run clinic CLI and verify that it does not complain. @@ -2420,7 +2624,7 @@ def test_external(self): out = self.expect_success("-f", "-o", TESTFN, source) self.assertEqual(out, "") - with open(TESTFN, encoding='utf-8') as f: + with open(TESTFN, encoding="utf-8") as f: new_contents = f.read() self.assertEqual(new_contents, orig_contents) @@ -2429,11 +2633,13 @@ def test_no_change(self): # bpo-42398: Test that the destination file is left unchanged if the # content does not change. Moreover, check also that the file # modification time does not change in this case. - code = dedent(""" + code = dedent( + """ /*[clinic input] [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=da39a3ee5e6b4b0d]*/ - """) + """ + ) with os_helper.temp_dir() as tmp_dir: fn = os.path.join(tmp_dir, "test.c") with open(fn, "w", encoding="utf-8") as f: @@ -2446,7 +2652,8 @@ def test_no_change(self): self.assertEqual(pre_mtime, post_mtime) def test_cli_force(self): - invalid_input = dedent(""" + invalid_input = dedent( + """ /*[clinic input] output preset block module test @@ -2456,7 +2663,8 @@ def test_cli_force(self): const char *hand_edited = "output block is overwritten"; /*[clinic end generated code: output=bogus input=bogus]*/ - """) + """ + ) fail_msg = ( "Checksum mismatch! Expected 'bogus', computed '2ed19'. " "Suggested fix: remove all generated code including the end marker, " @@ -2470,8 +2678,9 @@ def test_cli_force(self): # Note, we cannot check the entire fail msg, because the path to # the tmp file will change for every run. _, err = self.expect_failure(fn) - self.assertTrue(err.endswith(fail_msg), - f"{err!r} does not end with {fail_msg!r}") + self.assertTrue( + err.endswith(fail_msg), f"{err!r} does not end with {fail_msg!r}" + ) # Then, force regeneration; success expected. out = self.expect_success("-f", fn) self.assertEqual(out, "") @@ -2480,16 +2689,17 @@ def test_cli_force(self): "/*[clinic end generated code: " "output=c16447c01510dfb3 input=9543a8d2da235301]*/\n" ) - with open(fn, encoding='utf-8') as f: + with open(fn, encoding="utf-8") as f: generated = f.read() - self.assertTrue(generated.endswith(checksum), - (generated, checksum)) + self.assertTrue(generated.endswith(checksum), (generated, checksum)) def test_cli_make(self): - c_code = dedent(""" + c_code = dedent( + """ /*[clinic input] [clinic start generated code]*/ - """) + """ + ) py_code = "pass" c_files = "file1.c", "file2.c" py_files = "file1.py", "file2.py" @@ -2529,10 +2739,12 @@ def create_files(files, srcdir, code): self.assertNotIn(path, out) def test_cli_make_exclude(self): - code = dedent(""" + code = dedent( + """ /*[clinic input] [clinic start generated code]*/ - """) + """ + ) with os_helper.temp_dir(quiet=False) as tmp_dir: # add some folders, some C files and a Python file for fn in "file1.c", "file2.c", "file3.c", "file4.c": @@ -2543,12 +2755,18 @@ def test_cli_make_exclude(self): # Run clinic in verbose mode with --make on tmpdir. # Exclude file2.c and file3.c. out = self.expect_success( - "-v", "--make", "--srcdir", tmp_dir, - "--exclude", os.path.join(tmp_dir, "file2.c"), + "-v", + "--make", + "--srcdir", + tmp_dir, + "--exclude", + os.path.join(tmp_dir, "file2.c"), # The added ./ should be normalised away. - "--exclude", os.path.join(tmp_dir, "./file3.c"), + "--exclude", + os.path.join(tmp_dir, "./file3.c"), # Relative paths should also work. - "--exclude", "file4.c" + "--exclude", + "file4.c", ) # expect verbose mode to only mention the C files in tmp_dir @@ -2570,13 +2788,15 @@ def test_cli_help(self): self.assertIn("usage: clinic.py", out) def test_cli_converters(self): - prelude = dedent(""" + prelude = dedent( + """ Legacy converters: B C D L O S U Y Z Z# b c d f h i l p s s# s* u u# w* y y# y* z z# z* Converters: - """) + """ + ) expected_converters = ( "bool", "byte", @@ -2607,7 +2827,8 @@ def test_cli_converters(self): "unsigned_long_long", "unsigned_short", ) - finale = dedent(""" + finale = dedent( + """ Return converters: bool() double() @@ -2622,7 +2843,8 @@ def test_cli_converters(self): All converters also accept (c_default=None, py_default=None, annotation=None). All return converters also accept (py_default=None). - """) + """ + ) out = self.expect_success("--converters") # We cannot simply compare the output, because the repr of the *accept* # param may change (it's a set, thus unordered). So, let's compare the @@ -2639,7 +2861,7 @@ def test_cli_converters(self): with self.subTest(converter=converter): self.assertTrue( line.startswith(converter), - f"expected converter {converter!r}, got {line!r}" + f"expected converter {converter!r}, got {line!r}", ) def test_cli_fail_converters_and_filename(self): @@ -2669,7 +2891,8 @@ def test_cli_fail_make_without_srcdir(self): self.assertIn(msg, err) def test_file_dest(self): - block = dedent(""" + block = dedent( + """ /*[clinic input] destination test new file {path}.h output everything test @@ -2677,12 +2900,14 @@ def test_file_dest(self): a: object / [clinic start generated code]*/ - """) + """ + ) expected_checksum_line = ( "/*[clinic end generated code: " "output=da39a3ee5e6b4b0d input=b602ab8e173ac3bd]*/\n" ) - expected_output = dedent("""\ + expected_output = dedent( + """\ /*[clinic input] preserve [clinic start generated code]*/ @@ -2700,7 +2925,8 @@ def test_file_dest(self): static PyObject * func(PyObject *module, PyObject *a) /*[clinic end generated code: output=3dde2d13002165b9 input=a9049054013a1b77]*/ - """) + """ + ) with os_helper.temp_dir() as tmp_dir: in_fn = os.path.join(tmp_dir, "test.c") out_fn = os.path.join(tmp_dir, "test.c.h") @@ -2710,8 +2936,7 @@ def test_file_dest(self): f.write("") # Write an empty output file! # Clinic should complain about the empty output file. _, err = self.expect_failure(in_fn) - expected_err = (f"Modified destination file {out_fn!r}; " - "not overwriting!") + expected_err = f"Modified destination file {out_fn!r}; " "not overwriting!" self.assertIn(expected_err, err) # Run clinic again, this time with the -f option. _ = self.expect_success("-f", in_fn) @@ -2724,15 +2949,20 @@ def test_file_dest(self): data = f.read() self.assertEqual(data, expected_output) + try: import _testclinic as ac_tester except ImportError: ac_tester = None + @unittest.skipIf(ac_tester is None, "_testclinic is missing") class ClinicFunctionalTest(unittest.TestCase): - locals().update((name, getattr(ac_tester, name)) - for name in dir(ac_tester) if name.startswith('test_')) + locals().update( + (name, getattr(ac_tester, name)) + for name in dir(ac_tester) + if name.startswith("test_") + ) def check_depr(self, regex, fn, /, *args, **kwds): with self.assertWarnsRegex(DeprecationWarning, regex) as cm: @@ -2746,11 +2976,11 @@ def check_depr_star(self, pnames, fn, /, *args, name=None, **kwds): if name is None: name = fn.__qualname__ if isinstance(fn, type): - name = f'{fn.__module__}.{name}' + name = f"{fn.__module__}.{name}" regex = ( - fr"Passing( more than)?( [0-9]+)? positional argument(s)? to " - fr"{re.escape(name)}\(\) is deprecated. Parameters? {pnames} will " - fr"become( a)? keyword-only parameters? in Python 3\.14" + rf"Passing( more than)?( [0-9]+)? positional argument(s)? to " + rf"{re.escape(name)}\(\) is deprecated. Parameters? {pnames} will " + rf"become( a)? keyword-only parameters? in Python 3\.14" ) self.check_depr(regex, fn, *args, **kwds) @@ -2758,12 +2988,12 @@ def check_depr_kwd(self, pnames, fn, *args, name=None, **kwds): if name is None: name = fn.__qualname__ if isinstance(fn, type): - name = f'{fn.__module__}.{name}' - pl = 's' if ' ' in pnames else '' + name = f"{fn.__module__}.{name}" + pl = "s" if " " in pnames else "" regex = ( - fr"Passing keyword argument{pl} {pnames} to " - fr"{re.escape(name)}\(\) is deprecated. Parameter{pl} {pnames} " - fr"will become positional-only in Python 3\.14." + rf"Passing keyword argument{pl} {pnames} to " + rf"{re.escape(name)}\(\) is deprecated. Parameter{pl} {pnames} " + rf"will become positional-only in Python 3\.14." ) self.check_depr(regex, fn, *args, **kwds) @@ -2771,46 +3001,83 @@ def test_objects_converter(self): with self.assertRaises(TypeError): ac_tester.objects_converter() self.assertEqual(ac_tester.objects_converter(1, 2), (1, 2)) - self.assertEqual(ac_tester.objects_converter([], 'whatever class'), ([], 'whatever class')) + self.assertEqual( + ac_tester.objects_converter([], "whatever class"), ([], "whatever class") + ) self.assertEqual(ac_tester.objects_converter(1), (1, None)) def test_bytes_object_converter(self): with self.assertRaises(TypeError): ac_tester.bytes_object_converter(1) - self.assertEqual(ac_tester.bytes_object_converter(b'BytesObject'), (b'BytesObject',)) + self.assertEqual( + ac_tester.bytes_object_converter(b"BytesObject"), (b"BytesObject",) + ) def test_byte_array_object_converter(self): with self.assertRaises(TypeError): ac_tester.byte_array_object_converter(1) - byte_arr = bytearray(b'ByteArrayObject') + byte_arr = bytearray(b"ByteArrayObject") self.assertEqual(ac_tester.byte_array_object_converter(byte_arr), (byte_arr,)) def test_unicode_converter(self): with self.assertRaises(TypeError): ac_tester.unicode_converter(1) - self.assertEqual(ac_tester.unicode_converter('unicode'), ('unicode',)) + self.assertEqual(ac_tester.unicode_converter("unicode"), ("unicode",)) def test_bool_converter(self): with self.assertRaises(TypeError): - ac_tester.bool_converter(False, False, 'not a int') + ac_tester.bool_converter(False, False, "not a int") self.assertEqual(ac_tester.bool_converter(), (True, True, True)) - self.assertEqual(ac_tester.bool_converter('', [], 5), (False, False, True)) - self.assertEqual(ac_tester.bool_converter(('not empty',), {1: 2}, 0), (True, True, False)) + self.assertEqual(ac_tester.bool_converter("", [], 5), (False, False, True)) + self.assertEqual( + ac_tester.bool_converter(("not empty",), {1: 2}, 0), (True, True, False) + ) def test_char_converter(self): with self.assertRaises(TypeError): ac_tester.char_converter(1) with self.assertRaises(TypeError): - ac_tester.char_converter(b'ab') - chars = [b'A', b'\a', b'\b', b'\t', b'\n', b'\v', b'\f', b'\r', b'"', b"'", b'?', b'\\', b'\000', b'\377'] + ac_tester.char_converter(b"ab") + chars = [ + b"A", + b"\a", + b"\b", + b"\t", + b"\n", + b"\v", + b"\f", + b"\r", + b'"', + b"'", + b"?", + b"\\", + b"\000", + b"\377", + ] expected = tuple(ord(c) for c in chars) self.assertEqual(ac_tester.char_converter(), expected) - chars = [b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'0', b'a', b'b', b'c', b'd'] + chars = [ + b"1", + b"2", + b"3", + b"4", + b"5", + b"6", + b"7", + b"8", + b"9", + b"0", + b"a", + b"b", + b"c", + b"d", + ] expected = tuple(ord(c) for c in chars) self.assertEqual(ac_tester.char_converter(*chars), expected) def test_unsigned_char_converter(self): from _testcapi import UCHAR_MAX + with self.assertRaises(OverflowError): ac_tester.unsigned_char_converter(-1) with self.assertRaises(OverflowError): @@ -2820,11 +3087,17 @@ def test_unsigned_char_converter(self): with self.assertRaises(TypeError): ac_tester.unsigned_char_converter([]) self.assertEqual(ac_tester.unsigned_char_converter(), (12, 34, 56)) - self.assertEqual(ac_tester.unsigned_char_converter(0, 0, UCHAR_MAX + 1), (0, 0, 0)) - self.assertEqual(ac_tester.unsigned_char_converter(0, 0, (UCHAR_MAX + 1) * 3 + 123), (0, 0, 123)) + self.assertEqual( + ac_tester.unsigned_char_converter(0, 0, UCHAR_MAX + 1), (0, 0, 0) + ) + self.assertEqual( + ac_tester.unsigned_char_converter(0, 0, (UCHAR_MAX + 1) * 3 + 123), + (0, 0, 123), + ) def test_short_converter(self): from _testcapi import SHRT_MIN, SHRT_MAX + with self.assertRaises(OverflowError): ac_tester.short_converter(SHRT_MIN - 1) with self.assertRaises(OverflowError): @@ -2836,6 +3109,7 @@ def test_short_converter(self): def test_unsigned_short_converter(self): from _testcapi import USHRT_MAX + with self.assertRaises(ValueError): ac_tester.unsigned_short_converter(-1) with self.assertRaises(OverflowError): @@ -2845,11 +3119,17 @@ def test_unsigned_short_converter(self): with self.assertRaises(TypeError): ac_tester.unsigned_short_converter([]) self.assertEqual(ac_tester.unsigned_short_converter(), (12, 34, 56)) - self.assertEqual(ac_tester.unsigned_short_converter(0, 0, USHRT_MAX + 1), (0, 0, 0)) - self.assertEqual(ac_tester.unsigned_short_converter(0, 0, (USHRT_MAX + 1) * 3 + 123), (0, 0, 123)) + self.assertEqual( + ac_tester.unsigned_short_converter(0, 0, USHRT_MAX + 1), (0, 0, 0) + ) + self.assertEqual( + ac_tester.unsigned_short_converter(0, 0, (USHRT_MAX + 1) * 3 + 123), + (0, 0, 123), + ) def test_int_converter(self): from _testcapi import INT_MIN, INT_MAX + with self.assertRaises(OverflowError): ac_tester.int_converter(INT_MIN - 1) with self.assertRaises(OverflowError): @@ -2859,10 +3139,11 @@ def test_int_converter(self): with self.assertRaises(TypeError): ac_tester.int_converter([]) self.assertEqual(ac_tester.int_converter(), (12, 34, 45)) - self.assertEqual(ac_tester.int_converter(1, 2, '3'), (1, 2, ord('3'))) + self.assertEqual(ac_tester.int_converter(1, 2, "3"), (1, 2, ord("3"))) def test_unsigned_int_converter(self): from _testcapi import UINT_MAX + with self.assertRaises(ValueError): ac_tester.unsigned_int_converter(-1) with self.assertRaises(OverflowError): @@ -2872,11 +3153,17 @@ def test_unsigned_int_converter(self): with self.assertRaises(TypeError): ac_tester.unsigned_int_converter([]) self.assertEqual(ac_tester.unsigned_int_converter(), (12, 34, 56)) - self.assertEqual(ac_tester.unsigned_int_converter(0, 0, UINT_MAX + 1), (0, 0, 0)) - self.assertEqual(ac_tester.unsigned_int_converter(0, 0, (UINT_MAX + 1) * 3 + 123), (0, 0, 123)) + self.assertEqual( + ac_tester.unsigned_int_converter(0, 0, UINT_MAX + 1), (0, 0, 0) + ) + self.assertEqual( + ac_tester.unsigned_int_converter(0, 0, (UINT_MAX + 1) * 3 + 123), + (0, 0, 123), + ) def test_long_converter(self): from _testcapi import LONG_MIN, LONG_MAX + with self.assertRaises(OverflowError): ac_tester.long_converter(LONG_MIN - 1) with self.assertRaises(OverflowError): @@ -2888,6 +3175,7 @@ def test_long_converter(self): def test_unsigned_long_converter(self): from _testcapi import ULONG_MAX + with self.assertRaises(ValueError): ac_tester.unsigned_long_converter(-1) with self.assertRaises(OverflowError): @@ -2897,11 +3185,17 @@ def test_unsigned_long_converter(self): with self.assertRaises(TypeError): ac_tester.unsigned_long_converter([]) self.assertEqual(ac_tester.unsigned_long_converter(), (12, 34, 56)) - self.assertEqual(ac_tester.unsigned_long_converter(0, 0, ULONG_MAX + 1), (0, 0, 0)) - self.assertEqual(ac_tester.unsigned_long_converter(0, 0, (ULONG_MAX + 1) * 3 + 123), (0, 0, 123)) + self.assertEqual( + ac_tester.unsigned_long_converter(0, 0, ULONG_MAX + 1), (0, 0, 0) + ) + self.assertEqual( + ac_tester.unsigned_long_converter(0, 0, (ULONG_MAX + 1) * 3 + 123), + (0, 0, 123), + ) def test_long_long_converter(self): from _testcapi import LLONG_MIN, LLONG_MAX + with self.assertRaises(OverflowError): ac_tester.long_long_converter(LLONG_MIN - 1) with self.assertRaises(OverflowError): @@ -2913,6 +3207,7 @@ def test_long_long_converter(self): def test_unsigned_long_long_converter(self): from _testcapi import ULLONG_MAX + with self.assertRaises(ValueError): ac_tester.unsigned_long_long_converter(-1) with self.assertRaises(OverflowError): @@ -2922,11 +3217,17 @@ def test_unsigned_long_long_converter(self): with self.assertRaises(TypeError): ac_tester.unsigned_long_long_converter([]) self.assertEqual(ac_tester.unsigned_long_long_converter(), (12, 34, 56)) - self.assertEqual(ac_tester.unsigned_long_long_converter(0, 0, ULLONG_MAX + 1), (0, 0, 0)) - self.assertEqual(ac_tester.unsigned_long_long_converter(0, 0, (ULLONG_MAX + 1) * 3 + 123), (0, 0, 123)) + self.assertEqual( + ac_tester.unsigned_long_long_converter(0, 0, ULLONG_MAX + 1), (0, 0, 0) + ) + self.assertEqual( + ac_tester.unsigned_long_long_converter(0, 0, (ULLONG_MAX + 1) * 3 + 123), + (0, 0, 123), + ) def test_py_ssize_t_converter(self): from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + with self.assertRaises(OverflowError): ac_tester.py_ssize_t_converter(PY_SSIZE_T_MIN - 1) with self.assertRaises(OverflowError): @@ -2938,14 +3239,23 @@ def test_py_ssize_t_converter(self): def test_slice_index_converter(self): from _testcapi import PY_SSIZE_T_MIN, PY_SSIZE_T_MAX + with self.assertRaises(TypeError): ac_tester.slice_index_converter([]) self.assertEqual(ac_tester.slice_index_converter(), (12, 34, 56)) self.assertEqual(ac_tester.slice_index_converter(1, 2, None), (1, 2, 56)) - self.assertEqual(ac_tester.slice_index_converter(PY_SSIZE_T_MAX, PY_SSIZE_T_MAX + 1, PY_SSIZE_T_MAX + 1234), - (PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX)) - self.assertEqual(ac_tester.slice_index_converter(PY_SSIZE_T_MIN, PY_SSIZE_T_MIN - 1, PY_SSIZE_T_MIN - 1234), - (PY_SSIZE_T_MIN, PY_SSIZE_T_MIN, PY_SSIZE_T_MIN)) + self.assertEqual( + ac_tester.slice_index_converter( + PY_SSIZE_T_MAX, PY_SSIZE_T_MAX + 1, PY_SSIZE_T_MAX + 1234 + ), + (PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX), + ) + self.assertEqual( + ac_tester.slice_index_converter( + PY_SSIZE_T_MIN, PY_SSIZE_T_MIN - 1, PY_SSIZE_T_MIN - 1234 + ), + (PY_SSIZE_T_MIN, PY_SSIZE_T_MIN, PY_SSIZE_T_MIN), + ) def test_size_t_converter(self): with self.assertRaises(ValueError): @@ -2969,8 +3279,12 @@ def test_double_converter(self): def test_py_complex_converter(self): with self.assertRaises(TypeError): ac_tester.py_complex_converter([]) - self.assertEqual(ac_tester.py_complex_converter(complex(1, 2)), (complex(1, 2),)) - self.assertEqual(ac_tester.py_complex_converter(complex('-1-2j')), (complex('-1-2j'),)) + self.assertEqual( + ac_tester.py_complex_converter(complex(1, 2)), (complex(1, 2),) + ) + self.assertEqual( + ac_tester.py_complex_converter(complex("-1-2j")), (complex("-1-2j"),) + ) self.assertEqual(ac_tester.py_complex_converter(-0.5), (-0.5,)) self.assertEqual(ac_tester.py_complex_converter(10), (10,)) @@ -2978,28 +3292,42 @@ def test_str_converter(self): with self.assertRaises(TypeError): ac_tester.str_converter(1) with self.assertRaises(TypeError): - ac_tester.str_converter('a', 'b', 'c') + ac_tester.str_converter("a", "b", "c") with self.assertRaises(ValueError): - ac_tester.str_converter('a', b'b\0b', 'c') - self.assertEqual(ac_tester.str_converter('a', b'b', 'c'), ('a', 'b', 'c')) - self.assertEqual(ac_tester.str_converter('a', b'b', b'c'), ('a', 'b', 'c')) - self.assertEqual(ac_tester.str_converter('a', b'b', 'c\0c'), ('a', 'b', 'c\0c')) + ac_tester.str_converter("a", b"b\0b", "c") + self.assertEqual(ac_tester.str_converter("a", b"b", "c"), ("a", "b", "c")) + self.assertEqual(ac_tester.str_converter("a", b"b", b"c"), ("a", "b", "c")) + self.assertEqual(ac_tester.str_converter("a", b"b", "c\0c"), ("a", "b", "c\0c")) def test_str_converter_encoding(self): with self.assertRaises(TypeError): ac_tester.str_converter_encoding(1) - self.assertEqual(ac_tester.str_converter_encoding('a', 'b', 'c'), ('a', 'b', 'c')) + self.assertEqual( + ac_tester.str_converter_encoding("a", "b", "c"), ("a", "b", "c") + ) with self.assertRaises(TypeError): - ac_tester.str_converter_encoding('a', b'b\0b', 'c') - self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c')])), ('a', 'b', 'c')) - self.assertEqual(ac_tester.str_converter_encoding('a', b'b', bytearray([ord('c'), 0, ord('c')])), - ('a', 'b', 'c\x00c')) - self.assertEqual(ac_tester.str_converter_encoding('a', b'b', b'c\x00c'), ('a', 'b', 'c\x00c')) + ac_tester.str_converter_encoding("a", b"b\0b", "c") + self.assertEqual( + ac_tester.str_converter_encoding("a", b"b", bytearray([ord("c")])), + ("a", "b", "c"), + ) + self.assertEqual( + ac_tester.str_converter_encoding( + "a", b"b", bytearray([ord("c"), 0, ord("c")]) + ), + ("a", "b", "c\x00c"), + ) + self.assertEqual( + ac_tester.str_converter_encoding("a", b"b", b"c\x00c"), ("a", "b", "c\x00c") + ) def test_py_buffer_converter(self): with self.assertRaises(TypeError): - ac_tester.py_buffer_converter('a', 'b') - self.assertEqual(ac_tester.py_buffer_converter('abc', bytearray([1, 2, 3])), (b'abc', b'\x01\x02\x03')) + ac_tester.py_buffer_converter("a", "b") + self.assertEqual( + ac_tester.py_buffer_converter("abc", bytearray([1, 2, 3])), + (b"abc", b"\x01\x02\x03"), + ) def test_keywords(self): self.assertEqual(ac_tester.keywords(1, 2), (1, 2)) @@ -3029,7 +3357,9 @@ def test_keywords_opt_kwonly(self): self.assertEqual(ac_tester.keywords_opt_kwonly(1, b=2), (1, 2, None, None)) self.assertEqual(ac_tester.keywords_opt_kwonly(1, 2, c=3), (1, 2, 3, None)) self.assertEqual(ac_tester.keywords_opt_kwonly(a=1, c=3), (1, None, 3, None)) - self.assertEqual(ac_tester.keywords_opt_kwonly(a=1, b=2, c=3, d=4), (1, 2, 3, 4)) + self.assertEqual( + ac_tester.keywords_opt_kwonly(a=1, b=2, c=3, d=4), (1, 2, 3, 4) + ) def test_keywords_kwonly_opt(self): self.assertEqual(ac_tester.keywords_kwonly_opt(1), (1, None, None)) @@ -3086,7 +3416,9 @@ def test_posonly_opt_keywords_opt(self): with self.assertRaises(TypeError): ac_tester.posonly_opt_keywords_opt(1, b=2) self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, c=3), (1, 2, 3, None)) - self.assertEqual(ac_tester.posonly_opt_keywords_opt(1, 2, c=3, d=4), (1, 2, 3, 4)) + self.assertEqual( + ac_tester.posonly_opt_keywords_opt(1, 2, c=3, d=4), (1, 2, 3, 4) + ) with self.assertRaises(TypeError): ac_tester.posonly_opt_keywords_opt(a=1, b=2, c=3, d=4) @@ -3122,36 +3454,76 @@ def test_posonly_keywords_kwonly_opt(self): ac_tester.posonly_keywords_kwonly_opt(1, 2, 3) with self.assertRaises(TypeError): ac_tester.posonly_keywords_kwonly_opt(a=1, b=2, c=3) - self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None)) - self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None)) - self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None)) - self.assertEqual(ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5)) + self.assertEqual( + ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None) + ) + self.assertEqual( + ac_tester.posonly_keywords_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None) + ) + self.assertEqual( + ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None) + ) + self.assertEqual( + ac_tester.posonly_keywords_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5) + ) def test_posonly_keywords_opt_kwonly_opt(self): with self.assertRaises(TypeError): ac_tester.posonly_keywords_opt_kwonly_opt(1) - self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None, None)) - self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2), (1, 2, None, None, None)) + self.assertEqual( + ac_tester.posonly_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None, None) + ) + self.assertEqual( + ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2), (1, 2, None, None, None) + ) with self.assertRaises(TypeError): ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, 4) with self.assertRaises(TypeError): ac_tester.posonly_keywords_opt_kwonly_opt(a=1, b=2) - self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None)) - self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2, c=3), (1, 2, 3, None, None)) - self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4, None)) - self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4, None)) - self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4, e=5), (1, 2, 3, 4, 5)) - self.assertEqual(ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4, e=5), (1, 2, 3, 4, 5)) + self.assertEqual( + ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None, None) + ) + self.assertEqual( + ac_tester.posonly_keywords_opt_kwonly_opt(1, b=2, c=3), + (1, 2, 3, None, None), + ) + self.assertEqual( + ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4, None) + ) + self.assertEqual( + ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4), + (1, 2, 3, 4, None), + ) + self.assertEqual( + ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, 3, d=4, e=5), + (1, 2, 3, 4, 5), + ) + self.assertEqual( + ac_tester.posonly_keywords_opt_kwonly_opt(1, 2, c=3, d=4, e=5), + (1, 2, 3, 4, 5), + ) def test_posonly_opt_keywords_opt_kwonly_opt(self): - self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1), (1, None, None, None)) - self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None)) + self.assertEqual( + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1), (1, None, None, None) + ) + self.assertEqual( + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2), (1, 2, None, None) + ) with self.assertRaises(TypeError): ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, b=2) - self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3), (1, 2, 3, None)) - self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None)) - self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4)) - self.assertEqual(ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4)) + self.assertEqual( + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3), (1, 2, 3, None) + ) + self.assertEqual( + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3), (1, 2, 3, None) + ) + self.assertEqual( + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, d=4), (1, 2, 3, 4) + ) + self.assertEqual( + ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, c=3, d=4), (1, 2, 3, 4) + ) with self.assertRaises(TypeError): ac_tester.posonly_opt_keywords_opt_kwonly_opt(1, 2, 3, 4) @@ -3191,15 +3563,23 @@ def test_vararg_with_default(self): with self.assertRaises(TypeError): ac_tester.vararg_with_default() self.assertEqual(ac_tester.vararg_with_default(1, b=False), (1, (), False)) - self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4), (1, (2, 3, 4), False)) - self.assertEqual(ac_tester.vararg_with_default(1, 2, 3, 4, b=True), (1, (2, 3, 4), True)) + self.assertEqual( + ac_tester.vararg_with_default(1, 2, 3, 4), (1, (2, 3, 4), False) + ) + self.assertEqual( + ac_tester.vararg_with_default(1, 2, 3, 4, b=True), (1, (2, 3, 4), True) + ) def test_vararg_with_only_defaults(self): self.assertEqual(ac_tester.vararg_with_only_defaults(), ((), None)) self.assertEqual(ac_tester.vararg_with_only_defaults(b=2), ((), 2)) - self.assertEqual(ac_tester.vararg_with_only_defaults(1, b=2), ((1, ), 2)) - self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4), ((1, 2, 3, 4), None)) - self.assertEqual(ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5)) + self.assertEqual(ac_tester.vararg_with_only_defaults(1, b=2), ((1,), 2)) + self.assertEqual( + ac_tester.vararg_with_only_defaults(1, 2, 3, 4), ((1, 2, 3, 4), None) + ) + self.assertEqual( + ac_tester.vararg_with_only_defaults(1, 2, 3, 4, b=5), ((1, 2, 3, 4), 5) + ) def test_gh_32092_oob(self): ac_tester.gh_32092_oob(1, 2, 3, 4, kw1=5, kw2=6) @@ -3208,7 +3588,7 @@ def test_gh_32092_kw_pass(self): ac_tester.gh_32092_kw_pass(1, 2, 3) def test_gh_99233_refcount(self): - arg = '*A unique string is not referenced by anywhere else.*' + arg = "*A unique string is not referenced by anywhere else.*" arg_refcount_origin = sys.getrefcount(arg) ac_tester.gh_99233_refcount(arg) arg_refcount_after = sys.getrefcount(arg) @@ -3220,21 +3600,16 @@ def test_gh_99240_double_free(self): "without null bytes, not str" ) with self.assertRaisesRegex(TypeError, err): - ac_tester.gh_99240_double_free('a', '\0b') + ac_tester.gh_99240_double_free("a", "\0b") def test_null_or_tuple_for_varargs(self): # All of these should not crash: valid_args_for_test = [ - (('a',), {}, - ('a', (), False)), - (('a', 1, 2, 3), {'covariant': True}, - ('a', (1, 2, 3), True)), - ((), {'name': 'a'}, - ('a', (), False)), - ((), {'name': 'a', 'covariant': True}, - ('a', (), True)), - ((), {'covariant': True, 'name': 'a'}, - ('a', (), True)), + (("a",), {}, ("a", (), False)), + (("a", 1, 2, 3), {"covariant": True}, ("a", (1, 2, 3), True)), + ((), {"name": "a"}, ("a", (), False)), + ((), {"name": "a", "covariant": True}, ("a", (), True)), + ((), {"covariant": True, "name": "a"}, ("a", (), True)), ] for args, kwargs, expected in valid_args_for_test: with self.subTest(args=args, kwargs=kwargs): @@ -3247,11 +3622,11 @@ def test_null_or_tuple_for_varargs_error(self): with self.assertRaises(TypeError): ac_tester.null_or_tuple_for_varargs(covariant=True) with self.assertRaises(TypeError): - ac_tester.null_or_tuple_for_varargs(1, name='a') + ac_tester.null_or_tuple_for_varargs(1, name="a") with self.assertRaises(TypeError): - ac_tester.null_or_tuple_for_varargs(1, 2, 3, name='a', covariant=True) + ac_tester.null_or_tuple_for_varargs(1, 2, 3, name="a", covariant=True) with self.assertRaises(TypeError): - ac_tester.null_or_tuple_for_varargs(1, 2, 3, covariant=True, name='a') + ac_tester.null_or_tuple_for_varargs(1, 2, 3, covariant=True, name="a") def test_cloned_func_exception_message(self): incorrect_arg = -1 # f1() and f2() accept a single str @@ -3276,7 +3651,7 @@ def test_depr_star_new_cloned(self): fn = ac_tester.DeprStarNew().cloned fn() fn(a=None) - self.check_depr_star("'a'", fn, None, name='_testclinic.DeprStarNew.cloned') + self.check_depr_star("'a'", fn, None, name="_testclinic.DeprStarNew.cloned") def test_depr_star_init(self): cls = ac_tester.DeprStarInit @@ -3288,7 +3663,7 @@ def test_depr_star_init_cloned(self): fn = ac_tester.DeprStarInit().cloned fn() fn(a=None) - self.check_depr_star("'a'", fn, None, name='_testclinic.DeprStarInit.cloned') + self.check_depr_star("'a'", fn, None, name="_testclinic.DeprStarInit.cloned") def test_depr_star_init_noinline(self): cls = ac_tester.DeprStarInitNoInline @@ -3366,11 +3741,11 @@ def test_depr_star_pos1_len1(self): def test_depr_star_pos1_len2_with_kwd(self): fn = ac_tester.depr_star_pos1_len2_with_kwd - fn(a=0, b=0, c=0, d=0), - fn("a", b=0, c=0, d=0), + (fn(a=0, b=0, c=0, d=0),) + (fn("a", b=0, c=0, d=0),) check = partial(self.check_depr_star, "'b' and 'c'", fn) - check("a", "b", c=0, d=0), - check("a", "b", "c", d=0), + (check("a", "b", c=0, d=0),) + (check("a", "b", "c", d=0),) def test_depr_star_pos2_len1(self): fn = ac_tester.depr_star_pos2_len1 @@ -3419,7 +3794,8 @@ def test_depr_star_multi(self): "Passing more than 1 positional argument to depr_star_multi() is deprecated. " "Parameter 'b' will become a keyword-only parameter in Python 3.16. " "Parameters 'c' and 'd' will become keyword-only parameters in Python 3.15. " - "Parameters 'e', 'f' and 'g' will become keyword-only parameters in Python 3.14.") + "Parameters 'e', 'f' and 'g' will become keyword-only parameters in Python 3.14." + ) check = partial(self.check_depr, re.escape(errmsg), fn) check("a", "b", c="c", d="d", e="e", f="f", g="g", h="h") check("a", "b", "c", d="d", e="e", f="f", g="g", h="h") @@ -3520,7 +3896,8 @@ def test_depr_kwd_multi(self): "Passing keyword arguments 'b', 'c', 'd', 'e', 'f' and 'g' to depr_kwd_multi() is deprecated. " "Parameter 'b' will become positional-only in Python 3.14. " "Parameters 'c' and 'd' will become positional-only in Python 3.15. " - "Parameters 'e', 'f' and 'g' will become positional-only in Python 3.16.") + "Parameters 'e', 'f' and 'g' will become positional-only in Python 3.16." + ) check = partial(self.check_depr, re.escape(errmsg), fn) check("a", "b", "c", "d", "e", "f", g="g", h="h") check("a", "b", "c", "d", "e", f="f", g="g", h="h") @@ -3528,7 +3905,9 @@ def test_depr_kwd_multi(self): check("a", "b", "c", d="d", e="e", f="f", g="g", h="h") check("a", "b", c="c", d="d", e="e", f="f", g="g", h="h") check("a", b="b", c="c", d="d", e="e", f="f", g="g", h="h") - self.assertRaises(TypeError, fn, a="a", b="b", c="c", d="d", e="e", f="f", g="g", h="h") + self.assertRaises( + TypeError, fn, a="a", b="b", c="c", d="d", e="e", f="f", g="g", h="h" + ) def test_depr_multi(self): fn = ac_tester.depr_multi @@ -3536,7 +3915,8 @@ def test_depr_multi(self): errmsg = ( "Passing more than 4 positional arguments to depr_multi() is deprecated. " "Parameter 'e' will become a keyword-only parameter in Python 3.15. " - "Parameter 'f' will become a keyword-only parameter in Python 3.14.") + "Parameter 'f' will become a keyword-only parameter in Python 3.14." + ) check = partial(self.check_depr, re.escape(errmsg), fn) check("a", "b", "c", "d", "e", "f", g="g") check("a", "b", "c", "d", "e", f="f", g="g") @@ -3545,11 +3925,14 @@ def test_depr_multi(self): errmsg = ( "Passing keyword arguments 'b' and 'c' to depr_multi() is deprecated. " "Parameter 'b' will become positional-only in Python 3.14. " - "Parameter 'c' will become positional-only in Python 3.15.") + "Parameter 'c' will become positional-only in Python 3.15." + ) check = partial(self.check_depr, re.escape(errmsg), fn) check("a", "b", c="c", d="d", e="e", f="f", g="g") check("a", b="b", c="c", d="d", e="e", f="f", g="g") - self.assertRaises(TypeError, fn, a="a", b="b", c="c", d="d", e="e", f="f", g="g") + self.assertRaises( + TypeError, fn, a="a", b="b", c="c", d="d", e="e", f="f", g="g" + ) try: @@ -3557,10 +3940,14 @@ def test_depr_multi(self): except ImportError: _testclinic_limited = None + @unittest.skipIf(_testclinic_limited is None, "_testclinic_limited is missing") class LimitedCAPIFunctionalTest(unittest.TestCase): - locals().update((name, getattr(_testclinic_limited, name)) - for name in dir(_testclinic_limited) if name.startswith('test_')) + locals().update( + (name, getattr(_testclinic_limited, name)) + for name in dir(_testclinic_limited) + if name.startswith("test_") + ) def test_my_int_func(self): with self.assertRaises(TypeError): @@ -3583,7 +3970,6 @@ def test_my_int_sum(self): _testclinic_limited.my_int_sum(1, "str") - class PermutationTests(unittest.TestCase): """Test permutation support functions.""" @@ -3611,25 +3997,39 @@ def test_permute_right_option_groups(self): def test_permute_optional_groups(self): empty = { - "left": (), "required": (), "right": (), + "left": (), + "required": (), + "right": (), "expected": ((),), } noleft1 = { - "left": (), "required": ("b",), "right": ("c",), + "left": (), + "required": ("b",), + "right": ("c",), "expected": ( ("b",), ("b", "c"), ), } noleft2 = { - "left": (), "required": ("b", "c",), "right": ("d",), + "left": (), + "required": ( + "b", + "c", + ), + "right": ("d",), "expected": ( ("b", "c"), ("b", "c", "d"), ), } noleft3 = { - "left": (), "required": ("b", "c",), "right": ("d", "e"), + "left": (), + "required": ( + "b", + "c", + ), + "right": ("d", "e"), "expected": ( ("b", "c"), ("b", "c", "d"), @@ -3637,21 +4037,27 @@ def test_permute_optional_groups(self): ), } noright1 = { - "left": ("a",), "required": ("b",), "right": (), + "left": ("a",), + "required": ("b",), + "right": (), "expected": ( ("b",), ("a", "b"), ), } noright2 = { - "left": ("a",), "required": ("b", "c"), "right": (), + "left": ("a",), + "required": ("b", "c"), + "right": (), "expected": ( ("b", "c"), ("a", "b", "c"), ), } noright3 = { - "left": ("a", "b"), "required": ("c",), "right": (), + "left": ("a", "b"), + "required": ("c",), + "right": (), "expected": ( ("c",), ("b", "c"), @@ -3659,7 +4065,9 @@ def test_permute_optional_groups(self): ), } leftandright1 = { - "left": ("a",), "required": ("b",), "right": ("c",), + "left": ("a",), + "required": ("b",), + "right": ("c",), "expected": ( ("b",), ("a", "b"), # Prefer left. @@ -3667,10 +4075,12 @@ def test_permute_optional_groups(self): ), } leftandright2 = { - "left": ("a", "b"), "required": ("c", "d"), "right": ("e", "f"), + "left": ("a", "b"), + "required": ("c", "d"), + "right": ("e", "f"), "expected": ( ("c", "d"), - ("b", "c", "d"), # Prefer left. + ("b", "c", "d"), # Prefer left. ("a", "b", "c", "d"), # Prefer left. ("a", "b", "c", "d", "e"), ("a", "b", "c", "d", "e", "f"), @@ -3678,9 +4088,14 @@ def test_permute_optional_groups(self): } dataset = ( empty, - noleft1, noleft2, noleft3, - noright1, noright2, noright3, - leftandright1, leftandright2, + noleft1, + noleft2, + noleft3, + noright1, + noright2, + noright3, + leftandright1, + leftandright2, ) for params in dataset: with self.subTest(**params): @@ -3691,20 +4106,19 @@ def test_permute_optional_groups(self): class FormatHelperTests(unittest.TestCase): - def test_strip_leading_and_trailing_blank_lines(self): dataset = ( # Input lines, expected output. - ("a\nb", "a\nb"), - ("a\nb\n", "a\nb"), - ("a\nb ", "a\nb"), - ("\na\nb\n\n", "a\nb"), - ("\n\na\nb\n\n", "a\nb"), - ("\n\na\n\nb\n\n", "a\n\nb"), + ("a\nb", "a\nb"), + ("a\nb\n", "a\nb"), + ("a\nb ", "a\nb"), + ("\na\nb\n\n", "a\nb"), + ("\n\na\nb\n\n", "a\nb"), + ("\n\na\n\nb\n\n", "a\n\nb"), # Note, leading whitespace is preserved: - (" a\nb", " a\nb"), - (" a\nb ", " a\nb"), - (" \n \n a\nb \n \n ", " a\nb"), + (" a\nb", " a\nb"), + (" a\nb ", " a\nb"), + (" \n \n a\nb \n \n ", " a\nb"), ) for lines, expected in dataset: with self.subTest(lines=lines, expected=expected): @@ -3719,21 +4133,9 @@ def test_normalize_snippet(self): """ # Expected outputs: - zero_indent = ( - "one\n" - "two\n" - "three" - ) - four_indent = ( - " one\n" - " two\n" - " three" - ) - eight_indent = ( - " one\n" - " two\n" - " three" - ) + zero_indent = "one\n" "two\n" "three" + four_indent = " one\n" " two\n" " three" + eight_indent = " one\n" " two\n" " three" expected_outputs = {0: zero_indent, 4: four_indent, 8: eight_indent} for indent, expected in expected_outputs.items(): with self.subTest(indent=indent): @@ -3757,12 +4159,12 @@ def test_accumulator(self): def test_quoted_for_c_string(self): dataset = ( # input, expected - (r"abc", r"abc"), - (r"\abc", r"\\abc"), - (r"\a\bc", r"\\a\\bc"), + (r"abc", r"abc"), + (r"\abc", r"\\abc"), + (r"\a\bc", r"\\a\\bc"), (r"\a\\bc", r"\\a\\\\bc"), - (r'"abc"', r'\"abc\"'), - (r"'a'", r"\'a\'"), + (r'"abc"', r"\"abc\""), + (r"'a'", r"\'a\'"), ) for line, expected in dataset: with self.subTest(line=line, expected=expected): @@ -3770,18 +4172,8 @@ def test_quoted_for_c_string(self): self.assertEqual(out, expected) def test_rstrip_lines(self): - lines = ( - "a \n" - "b\n" - " c\n" - " d \n" - ) - expected = ( - "a\n" - "b\n" - " c\n" - " d\n" - ) + lines = "a \n" "b\n" " c\n" " d \n" + expected = "a\n" "b\n" " c\n" " d\n" out = clinic.rstrip_lines(lines) self.assertEqual(out, expected) @@ -3796,29 +4188,15 @@ def test_indent_all_lines(self): self.assertEqual(clinic.indent_all_lines("", prefix="bar"), "") lines = ( - "one\n" - "two" # The missing newline is deliberate. - ) - expected = ( - "barone\n" - "bartwo" + "one\n" "two" # The missing newline is deliberate. ) + expected = "barone\n" "bartwo" out = clinic.indent_all_lines(lines, prefix="bar") self.assertEqual(out, expected) # If last line is empty, expect it to be unchanged. - lines = ( - "\n" - "one\n" - "two\n" - "" - ) - expected = ( - "bar\n" - "barone\n" - "bartwo\n" - "" - ) + lines = "\n" "one\n" "two\n" "" + expected = "bar\n" "barone\n" "bartwo\n" "" out = clinic.indent_all_lines(lines, prefix="bar") self.assertEqual(out, expected) @@ -3827,29 +4205,15 @@ def test_suffix_all_lines(self): self.assertEqual(clinic.suffix_all_lines("", suffix="foo"), "") lines = ( - "one\n" - "two" # The missing newline is deliberate. - ) - expected = ( - "onefoo\n" - "twofoo" + "one\n" "two" # The missing newline is deliberate. ) + expected = "onefoo\n" "twofoo" out = clinic.suffix_all_lines(lines, suffix="foo") self.assertEqual(out, expected) # If last line is empty, expect it to be unchanged. - lines = ( - "\n" - "one\n" - "two\n" - "" - ) - expected = ( - "foo\n" - "onefoo\n" - "twofoo\n" - "" - ) + lines = "\n" "one\n" "two\n" "" + expected = "foo\n" "onefoo\n" "twofoo\n" "" out = clinic.suffix_all_lines(lines, suffix="foo") self.assertEqual(out, expected) @@ -3869,19 +4233,15 @@ def test_Block_repr(self): dsl_name="wow_so_long", signatures=[], output="very_long_" * 100, - indent="" - ) - expected_repr_3 = ( - "" + indent="", ) + expected_repr_3 = "" self.assertEqual(repr(block3), expected_repr_3) def test_Destination_repr(self): c = _make_clinic() - destination = clinic.Destination( - "foo", type="file", clinic=c, args=("eggs",) - ) + destination = clinic.Destination("foo", type="file", clinic=c, args=("eggs",)) self.assertEqual( repr(destination), "" ) @@ -3894,7 +4254,9 @@ def test_Module_repr(self): self.assertRegex(repr(module), r"") def test_Class_repr(self): - cls = clinic.Class("foo", _make_clinic(), None, 'some_typedef', 'some_type_object') + cls = clinic.Class( + "foo", _make_clinic(), None, "some_typedef", "some_type_object" + ) self.assertRegex(repr(cls), r"") def test_FunctionKind_repr(self): @@ -3907,23 +4269,23 @@ def test_FunctionKind_repr(self): def test_Function_and_Parameter_reprs(self): function = clinic.Function( - name='foo', + name="foo", module=_make_clinic(), cls=None, c_basename=None, - full_name='foofoo', + full_name="foofoo", return_converter=clinic.init_return_converter(), kind=clinic.FunctionKind.METHOD_INIT, - coexist=False + coexist=False, ) self.assertEqual(repr(function), "") - converter = clinic.self_converter('bar', 'bar', function) + converter = clinic.self_converter("bar", "bar", function) parameter = clinic.Parameter( "bar", kind=inspect.Parameter.POSITIONAL_OR_KEYWORD, function=function, - converter=converter + converter=converter, ) self.assertEqual(repr(parameter), "") @@ -3940,7 +4302,7 @@ def test_Monitor_repr(self): monitor.stack.append(("token2", "condition2")) self.assertRegex( repr(monitor), - r"" + r"", ) diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py index cbedf810131743..ab310e96223185 100644 --- a/Lib/test/test_cmd.py +++ b/Lib/test/test_cmd.py @@ -100,7 +100,7 @@ class samplecmdclass(cmd.Cmd): Test for the function print_topics(): - >>> mycmd.print_topics("header", ["command1", "command2"], 2 ,10) + >>> mycmd.print_topics("header", ["command1", "command2"], 2, 10) header ====== command1 @@ -123,9 +123,9 @@ class samplecmdclass(cmd.Cmd): and let it execute This test includes the preloop(), postloop(), default(), emptyline(), parseline(), do_help() functions - >>> mycmd.use_rawinput=0 + >>> mycmd.use_rawinput = 0 - >>> mycmd.cmdqueue=["add", "add 4 5", "", "help", "help add", "exit"] + >>> mycmd.cmdqueue = ["add", "add 4 5", "", "help", "help add", "exit"] >>> mycmd.cmdloop() # doctest: +REPORT_NDIFF Hello from preloop *** invalid number of arguments diff --git a/Lib/test/test_dataclasses/__init__.py b/Lib/test/test_dataclasses/__init__.py index 272d427875ae40..b8294bab6df666 100644 --- a/Lib/test/test_dataclasses/__init__.py +++ b/Lib/test/test_dataclasses/__init__.py @@ -14,16 +14,31 @@ import traceback import unittest from unittest.mock import Mock -from typing import ClassVar, Any, List, Union, Tuple, Dict, Generic, TypeVar, Optional, Protocol, DefaultDict +from typing import ( + ClassVar, + Any, + List, + Union, + Tuple, + Dict, + Generic, + TypeVar, + Optional, + Protocol, + DefaultDict, +) from typing import get_type_hints from collections import deque, OrderedDict, namedtuple, defaultdict from functools import total_ordering -import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation. +import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation. import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation. + # Just any custom exception we can catch. -class CustomError(Exception): pass +class CustomError(Exception): + pass + class TestCase(unittest.TestCase): def test_no_fields(self): @@ -53,6 +68,7 @@ class C: def test_field_default_default_factory_error(self): msg = "cannot specify both default and default_factory" with self.assertRaisesRegex(ValueError, msg): + @dataclass class C: x: int = field(default=1, default_factory=int) @@ -61,12 +77,14 @@ def test_field_repr(self): int_field = field(default=1, init=True, repr=False) int_field.name = "id" repr_output = repr(int_field) - expected_output = "Field(name='id',type=None," \ - f"default=1,default_factory={MISSING!r}," \ - "init=True,repr=False,hash=None," \ - "compare=True,metadata=mappingproxy({})," \ - f"kw_only={MISSING!r}," \ - "_field_type=None)" + expected_output = ( + "Field(name='id',type=None," + f"default=1,default_factory={MISSING!r}," + "init=True,repr=False,hash=None," + "compare=True,metadata=mappingproxy({})," + f"kw_only={MISSING!r}," + "_field_type=None)" + ) self.assertEqual(repr_output, expected_output) @@ -93,13 +111,16 @@ def test_dataclass_params_repr(self): # it's testing a feature we want to make sure is correctly implemented # for the sake of dataclasses itself @dataclass(slots=True, frozen=True) - class Some: pass + class Some: + pass repr_output = repr(Some.__dataclass_params__) - expected_output = "_DataclassParams(init=True,repr=True," \ - "eq=True,order=False,unsafe_hash=False,frozen=True," \ - "match_args=True,kw_only=False," \ - "slots=True,weakref_slot=False)" + expected_output = ( + "_DataclassParams(init=True,repr=True," + "eq=True,order=False,unsafe_hash=False,frozen=True," + "match_args=True,kw_only=False," + "slots=True,weakref_slot=False)" + ) self.assertEqual(repr_output, expected_output) def test_dataclass_params_signature(self): @@ -107,10 +128,11 @@ def test_dataclass_params_signature(self): # it's testing a feature we want to make sure is correctly implemented # for the sake of dataclasses itself @dataclass - class Some: pass + class Some: + pass for param in inspect.signature(dataclass).parameters: - if param == 'cls': + if param == "cls": continue self.assertTrue(hasattr(Some.__dataclass_params__, param), msg=param) @@ -132,18 +154,20 @@ class C: self.assertEqual((o.x, o.y), (3, 0)) # Non-defaults following defaults. - with self.assertRaisesRegex(TypeError, - "non-default argument 'y' follows " - "default argument 'x'"): + with self.assertRaisesRegex( + TypeError, "non-default argument 'y' follows " "default argument 'x'" + ): + @dataclass class C: x: int = 0 y: int # A derived class adds a non-default field after a default one. - with self.assertRaisesRegex(TypeError, - "non-default argument 'y' follows " - "default argument 'x'"): + with self.assertRaisesRegex( + TypeError, "non-default argument 'y' follows " "default argument 'x'" + ): + @dataclass class B: x: int = 0 @@ -154,9 +178,10 @@ class C(B): # Override a base class field and add a default to # a field which didn't use to have a default. - with self.assertRaisesRegex(TypeError, - "non-default argument 'y' follows " - "default argument 'x'"): + with self.assertRaisesRegex( + TypeError, "non-default argument 'y' follows " "default argument 'x'" + ): + @dataclass class B: x: int @@ -172,8 +197,10 @@ def test_overwrite_hash(self): @dataclass(frozen=True) class C: x: int + def __hash__(self): return 301 + self.assertEqual(hash(C(100)), 301) # Test that declaring this class isn't an error. It should @@ -181,14 +208,16 @@ def __hash__(self): @dataclass(frozen=True) class C: x: int + def __eq__(self, other): return False + self.assertEqual(hash(C(100)), hash((100,))) # But this one should generate an exception, because with # unsafe_hash=True, it's an error to have a __hash__ defined. - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __hash__'): + with self.assertRaisesRegex(TypeError, "Cannot overwrite attribute __hash__"): + @dataclass(unsafe_hash=True) class C: def __hash__(self): @@ -201,21 +230,25 @@ def __hash__(self): @dataclass(unsafe_hash=True) class C: x: int + def __eq__(self): pass + # The generated hash function works as we'd expect. self.assertEqual(hash(C(10)), hash((10,))) # Creating this class should generate an exception, because # __hash__ exists and is not None, which it would be if it # had been auto-generated due to __eq__ being defined. - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __hash__'): + with self.assertRaisesRegex(TypeError, "Cannot overwrite attribute __hash__"): + @dataclass(unsafe_hash=True) class C: x: int + def __eq__(self): pass + def __hash__(self): pass @@ -233,25 +266,35 @@ class C1(Base): x: int = 15 o = Base() - self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..Base(x=15.0, y=0)') + self.assertEqual( + repr(o), + "TestCase.test_overwrite_fields_in_derived_class..Base(x=15.0, y=0)", + ) o = C1() - self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=15, y=0, z=10)') + self.assertEqual( + repr(o), + "TestCase.test_overwrite_fields_in_derived_class..C1(x=15, y=0, z=10)", + ) o = C1(x=5) - self.assertEqual(repr(o), 'TestCase.test_overwrite_fields_in_derived_class..C1(x=5, y=0, z=10)') + self.assertEqual( + repr(o), + "TestCase.test_overwrite_fields_in_derived_class..C1(x=5, y=0, z=10)", + ) def test_field_named_self(self): @dataclass class C: self: str - c=C('foo') - self.assertEqual(c.self, 'foo') + + c = C("foo") + self.assertEqual(c.self, "foo") # Make sure the first parameter is not named 'self'. sig = inspect.signature(C.__init__) first = next(iter(sig.parameters)) - self.assertNotEqual('self', first) + self.assertNotEqual("self", first) # But we do use 'self' if no field named self. @dataclass @@ -261,27 +304,30 @@ class C: # Make sure the first parameter is named 'self'. sig = inspect.signature(C.__init__) first = next(iter(sig.parameters)) - self.assertEqual('self', first) + self.assertEqual("self", first) def test_field_named_object(self): @dataclass class C: object: str - c = C('foo') - self.assertEqual(c.object, 'foo') + + c = C("foo") + self.assertEqual(c.object, "foo") def test_field_named_object_frozen(self): @dataclass(frozen=True) class C: object: str - c = C('foo') - self.assertEqual(c.object, 'foo') + + c = C("foo") + self.assertEqual(c.object, "foo") def test_field_named_BUILTINS_frozen(self): # gh-96151 @dataclass(frozen=True) class C: BUILTINS: int + c = C(5) self.assertEqual(c.BUILTINS, 5) @@ -306,13 +352,14 @@ def test_field_named_like_builtin(self): # Attribute names can shadow built-in names # since code generation is used. # Ensure that this is not happening. - exclusions = {'None', 'True', 'False'} + exclusions = {"None", "True", "False"} builtins_names = sorted( - b for b in builtins.__dict__.keys() - if not b.startswith('__') and b not in exclusions + b + for b in builtins.__dict__.keys() + if not b.startswith("__") and b not in exclusions ) attributes = [(name, str) for name in builtins_names] - C = make_dataclass('C', attributes) + C = make_dataclass("C", attributes) c = C(*[name for name in builtins_names]) @@ -324,13 +371,14 @@ def test_field_named_like_builtin_frozen(self): # since code generation is used. # Ensure that this is not happening # for frozen data classes. - exclusions = {'None', 'True', 'False'} + exclusions = {"None", "True", "False"} builtins_names = sorted( - b for b in builtins.__dict__.keys() - if not b.startswith('__') and b not in exclusions + b + for b in builtins.__dict__.keys() + if not b.startswith("__") and b not in exclusions ) attributes = [(name, str) for name in builtins_names] - C = make_dataclass('C', attributes, frozen=True) + C = make_dataclass("C", attributes, frozen=True) c = C(*[name for name in builtins_names]) @@ -350,18 +398,25 @@ class C1: for cls in [C0, C1]: with self.subTest(cls=cls): self.assertEqual(cls(), cls()) - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a > b, - lambda a, b: a >= b]): + for idx, fn in enumerate( + [ + lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b, + ] + ): with self.subTest(idx=idx): - with self.assertRaisesRegex(TypeError, - f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + with self.assertRaisesRegex( + TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'", + ): fn(cls(), cls()) @dataclass(order=True) class C: pass + self.assertLessEqual(C(), C()) self.assertGreaterEqual(C(), C()) @@ -379,18 +434,25 @@ class C1: with self.subTest(cls=cls): self.assertEqual(cls(1), cls(1)) self.assertNotEqual(cls(0), cls(1)) - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a > b, - lambda a, b: a >= b]): + for idx, fn in enumerate( + [ + lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b, + ] + ): with self.subTest(idx=idx): - with self.assertRaisesRegex(TypeError, - f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + with self.assertRaisesRegex( + TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'", + ): fn(cls(0), cls(0)) @dataclass(order=True) class C: x: int + self.assertLess(C(0), C(1)) self.assertLessEqual(C(0), C(1)) self.assertLessEqual(C(1), C(1)) @@ -416,13 +478,19 @@ class C1: self.assertEqual(cls(1, 2), cls(1, 2)) self.assertNotEqual(cls(1, 0), cls(0, 0)) self.assertNotEqual(cls(1, 0), cls(1, 1)) - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a > b, - lambda a, b: a >= b]): + for idx, fn in enumerate( + [ + lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b, + ] + ): with self.subTest(idx=idx): - with self.assertRaisesRegex(TypeError, - f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'"): + with self.assertRaisesRegex( + TypeError, + f"not supported between instances of '{cls.__name__}' and '{cls.__name__}'", + ): fn(cls(0, 0), cls(0, 0)) @dataclass(order=True) @@ -430,23 +498,23 @@ class C: x: int y: int - for idx, fn in enumerate([lambda a, b: a == b, - lambda a, b: a <= b, - lambda a, b: a >= b]): + for idx, fn in enumerate( + [lambda a, b: a == b, lambda a, b: a <= b, lambda a, b: a >= b] + ): with self.subTest(idx=idx): self.assertTrue(fn(C(0, 0), C(0, 0))) - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a != b]): + for idx, fn in enumerate( + [lambda a, b: a < b, lambda a, b: a <= b, lambda a, b: a != b] + ): with self.subTest(idx=idx): self.assertTrue(fn(C(0, 0), C(0, 1))) self.assertTrue(fn(C(0, 1), C(1, 0))) self.assertTrue(fn(C(1, 0), C(1, 1))) - for idx, fn in enumerate([lambda a, b: a > b, - lambda a, b: a >= b, - lambda a, b: a != b]): + for idx, fn in enumerate( + [lambda a, b: a > b, lambda a, b: a >= b, lambda a, b: a != b] + ): with self.subTest(idx=idx): self.assertTrue(fn(C(0, 1), C(0, 0))) self.assertTrue(fn(C(1, 0), C(0, 1))) @@ -463,59 +531,69 @@ class B: class C(B): pass - for idx, (fn, expected) in enumerate([(lambda a, b: a == b, False), - (lambda a, b: a != b, True)]): + for idx, (fn, expected) in enumerate( + [(lambda a, b: a == b, False), (lambda a, b: a != b, True)] + ): with self.subTest(idx=idx): self.assertEqual(fn(B(0), C(0)), expected) - for idx, fn in enumerate([lambda a, b: a < b, - lambda a, b: a <= b, - lambda a, b: a > b, - lambda a, b: a >= b]): + for idx, fn in enumerate( + [ + lambda a, b: a < b, + lambda a, b: a <= b, + lambda a, b: a > b, + lambda a, b: a >= b, + ] + ): with self.subTest(idx=idx): - with self.assertRaisesRegex(TypeError, - "not supported between instances of 'B' and 'C'"): + with self.assertRaisesRegex( + TypeError, "not supported between instances of 'B' and 'C'" + ): fn(B(0), C(0)) def test_eq_order(self): # Test combining eq and order. - for (eq, order, result ) in [ - (False, False, 'neither'), - (False, True, 'exception'), - (True, False, 'eq_only'), - (True, True, 'both'), + for eq, order, result in [ + (False, False, "neither"), + (False, True, "exception"), + (True, False, "eq_only"), + (True, True, "both"), ]: with self.subTest(eq=eq, order=order): - if result == 'exception': - with self.assertRaisesRegex(ValueError, 'eq must be true if order is true'): + if result == "exception": + with self.assertRaisesRegex( + ValueError, "eq must be true if order is true" + ): + @dataclass(eq=eq, order=order) class C: pass else: + @dataclass(eq=eq, order=order) class C: pass - if result == 'neither': - self.assertNotIn('__eq__', C.__dict__) - self.assertNotIn('__lt__', C.__dict__) - self.assertNotIn('__le__', C.__dict__) - self.assertNotIn('__gt__', C.__dict__) - self.assertNotIn('__ge__', C.__dict__) - elif result == 'both': - self.assertIn('__eq__', C.__dict__) - self.assertIn('__lt__', C.__dict__) - self.assertIn('__le__', C.__dict__) - self.assertIn('__gt__', C.__dict__) - self.assertIn('__ge__', C.__dict__) - elif result == 'eq_only': - self.assertIn('__eq__', C.__dict__) - self.assertNotIn('__lt__', C.__dict__) - self.assertNotIn('__le__', C.__dict__) - self.assertNotIn('__gt__', C.__dict__) - self.assertNotIn('__ge__', C.__dict__) + if result == "neither": + self.assertNotIn("__eq__", C.__dict__) + self.assertNotIn("__lt__", C.__dict__) + self.assertNotIn("__le__", C.__dict__) + self.assertNotIn("__gt__", C.__dict__) + self.assertNotIn("__ge__", C.__dict__) + elif result == "both": + self.assertIn("__eq__", C.__dict__) + self.assertIn("__lt__", C.__dict__) + self.assertIn("__le__", C.__dict__) + self.assertIn("__gt__", C.__dict__) + self.assertIn("__ge__", C.__dict__) + elif result == "eq_only": + self.assertIn("__eq__", C.__dict__) + self.assertNotIn("__lt__", C.__dict__) + self.assertNotIn("__le__", C.__dict__) + self.assertNotIn("__gt__", C.__dict__) + self.assertNotIn("__ge__", C.__dict__) else: - assert False, f'unknown result {result!r}' + assert False, f"unknown result {result!r}" def test_field_no_default(self): @dataclass @@ -524,13 +602,14 @@ class C: self.assertEqual(C(5).x, 5) - with self.assertRaisesRegex(TypeError, - r"__init__\(\) missing 1 required " - "positional argument: 'x'"): + with self.assertRaisesRegex( + TypeError, r"__init__\(\) missing 1 required " "positional argument: 'x'" + ): C() def test_field_default(self): default = object() + @dataclass class C: x: object = field(default=default) @@ -550,17 +629,19 @@ def test_not_in_repr(self): @dataclass class C: x: int = field(repr=False) + with self.assertRaises(TypeError): C() c = C(10) - self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C()') + self.assertEqual(repr(c), "TestCase.test_not_in_repr..C()") @dataclass class C: x: int = field(repr=False) y: int + c = C(10, 20) - self.assertEqual(repr(c), 'TestCase.test_not_in_repr..C(y=20)') + self.assertEqual(repr(c), "TestCase.test_not_in_repr..C(y=20)") def test_not_in_compare(self): @dataclass @@ -578,13 +659,15 @@ def test_no_unhashable_default(self): class Unhashable: __hash__ = None - unhashable_re = 'mutable default .* for field a is not allowed' + unhashable_re = "mutable default .* for field a is not allowed" with self.assertRaisesRegex(ValueError, unhashable_re): + @dataclass class A: a: dict = {} with self.assertRaisesRegex(ValueError, unhashable_re): + @dataclass class A: a: Any = Unhashable() @@ -595,6 +678,7 @@ class A: unhashable = Unhashable() # This shouldn't make the variable hashable. unhashable.__hash__ = lambda: 0 + @dataclass class A: a: Any = unhashable @@ -603,27 +687,28 @@ def test_hash_field_rules(self): # Test all 6 cases of: # hash=True/False/None # compare=True/False - for (hash_, compare, result ) in [ - (True, False, 'field' ), - (True, True, 'field' ), - (False, False, 'absent'), - (False, True, 'absent'), - (None, False, 'absent'), - (None, True, 'field' ), - ]: + for hash_, compare, result in [ + (True, False, "field"), + (True, True, "field"), + (False, False, "absent"), + (False, True, "absent"), + (None, False, "absent"), + (None, True, "field"), + ]: with self.subTest(hash=hash_, compare=compare): + @dataclass(unsafe_hash=True) class C: x: int = field(compare=compare, hash=hash_, default=5) - if result == 'field': + if result == "field": # __hash__ contains the field. self.assertEqual(hash(C(5)), hash((5,))) - elif result == 'absent': + elif result == "absent": # The field is not present in the hash. self.assertEqual(hash(C(5)), hash(())) else: - assert False, f'unknown result {result!r}' + assert False, f"unknown result {result!r}" def test_init_false_no_default(self): # If init=False and no default value, then the field won't be @@ -632,7 +717,7 @@ def test_init_false_no_default(self): class C: x: int = field(init=False) - self.assertNotIn('x', C().__dict__) + self.assertNotIn("x", C().__dict__) @dataclass class C: @@ -641,8 +726,8 @@ class C: z: int = field(init=False) t: int = 10 - self.assertNotIn('z', C(0).__dict__) - self.assertEqual(vars(C(5)), {'t': 10, 'x': 5, 'y': 0}) + self.assertNotIn("z", C(0).__dict__) + self.assertEqual(vars(C(5)), {"t": 10, "x": 5, "y": 0}) def test_class_marker(self): @dataclass @@ -661,62 +746,62 @@ class C: self.assertEqual(len(the_fields), 3) - self.assertEqual(the_fields[0].name, 'x') + self.assertEqual(the_fields[0].name, "x") self.assertEqual(the_fields[0].type, int) - self.assertFalse(hasattr(C, 'x')) - self.assertTrue (the_fields[0].init) - self.assertTrue (the_fields[0].repr) - self.assertEqual(the_fields[1].name, 'y') + self.assertFalse(hasattr(C, "x")) + self.assertTrue(the_fields[0].init) + self.assertTrue(the_fields[0].repr) + self.assertEqual(the_fields[1].name, "y") self.assertEqual(the_fields[1].type, str) - self.assertIsNone(getattr(C, 'y')) + self.assertIsNone(getattr(C, "y")) self.assertFalse(the_fields[1].init) - self.assertTrue (the_fields[1].repr) - self.assertEqual(the_fields[2].name, 'z') + self.assertTrue(the_fields[1].repr) + self.assertEqual(the_fields[2].name, "z") self.assertEqual(the_fields[2].type, str) - self.assertFalse(hasattr(C, 'z')) - self.assertTrue (the_fields[2].init) + self.assertFalse(hasattr(C, "z")) + self.assertTrue(the_fields[2].init) self.assertFalse(the_fields[2].repr) def test_field_order(self): @dataclass class B: - a: str = 'B:a' - b: str = 'B:b' - c: str = 'B:c' + a: str = "B:a" + b: str = "B:b" + c: str = "B:c" @dataclass class C(B): - b: str = 'C:b' + b: str = "C:b" - self.assertEqual([(f.name, f.default) for f in fields(C)], - [('a', 'B:a'), - ('b', 'C:b'), - ('c', 'B:c')]) + self.assertEqual( + [(f.name, f.default) for f in fields(C)], + [("a", "B:a"), ("b", "C:b"), ("c", "B:c")], + ) @dataclass class D(B): - c: str = 'D:c' + c: str = "D:c" - self.assertEqual([(f.name, f.default) for f in fields(D)], - [('a', 'B:a'), - ('b', 'B:b'), - ('c', 'D:c')]) + self.assertEqual( + [(f.name, f.default) for f in fields(D)], + [("a", "B:a"), ("b", "B:b"), ("c", "D:c")], + ) @dataclass class E(D): - a: str = 'E:a' - d: str = 'E:d' + a: str = "E:a" + d: str = "E:d" - self.assertEqual([(f.name, f.default) for f in fields(E)], - [('a', 'E:a'), - ('b', 'B:b'), - ('c', 'D:c'), - ('d', 'E:d')]) + self.assertEqual( + [(f.name, f.default) for f in fields(E)], + [("a", "E:a"), ("b", "B:b"), ("c", "D:c"), ("d", "E:d")], + ) def test_class_attrs(self): # We only have a class attribute if a default value is # specified, either directly or via a field with a default. default = object() + @dataclass class C: x: int @@ -724,42 +809,46 @@ class C: z: object = default t: int = field(default=100) - self.assertFalse(hasattr(C, 'x')) - self.assertFalse(hasattr(C, 'y')) - self.assertIs (C.z, default) + self.assertFalse(hasattr(C, "x")) + self.assertFalse(hasattr(C, "y")) + self.assertIs(C.z, default) self.assertEqual(C.t, 100) def test_disallowed_mutable_defaults(self): # For the known types, don't allow mutable default values. - for typ, empty, non_empty in [(list, [], [1]), - (dict, {}, {0:1}), - (set, set(), set([1])), - ]: + for typ, empty, non_empty in [ + (list, [], [1]), + (dict, {}, {0: 1}), + (set, set(), set([1])), + ]: with self.subTest(typ=typ): # Can't use a zero-length value. - with self.assertRaisesRegex(ValueError, - f'mutable default {typ} for field ' - 'x is not allowed'): + with self.assertRaisesRegex( + ValueError, f"mutable default {typ} for field " "x is not allowed" + ): + @dataclass class Point: x: typ = empty - # Nor a non-zero-length value - with self.assertRaisesRegex(ValueError, - f'mutable default {typ} for field ' - 'y is not allowed'): + with self.assertRaisesRegex( + ValueError, f"mutable default {typ} for field " "y is not allowed" + ): + @dataclass class Point: y: typ = non_empty # Check subtypes also fail. - class Subclass(typ): pass + class Subclass(typ): + pass + + with self.assertRaisesRegex( + ValueError, + "mutable default .*Subclass'>" " for field z is not allowed", + ): - with self.assertRaisesRegex(ValueError, - "mutable default .*Subclass'>" - " for field z is not allowed" - ): @dataclass class Point: z: typ = Subclass() @@ -809,6 +898,7 @@ def test_not_tuple(self): class Point: x: int y: int + self.assertNotEqual(Point(1, 2), (1, 2)) # And that we can't compare to another unrelated dataclass. @@ -816,6 +906,7 @@ class Point: class C: x: int y: int + self.assertNotEqual(Point(1, 3), C(1, 3)) def test_not_other_dataclass(self): @@ -837,7 +928,7 @@ class Date: self.assertNotEqual(Point3D(1, 2, 3), (1, 2, 3)) # Make sure we can't unpack. - with self.assertRaisesRegex(TypeError, 'unpack'): + with self.assertRaisesRegex(TypeError, "unpack"): x, y, z = Point3D(4, 5, 6) # Make sure another class with the same field names isn't @@ -847,22 +938,24 @@ class Point3Dv1: x: int = 0 y: int = 0 z: int = 0 + self.assertNotEqual(Point3D(0, 0, 0), Point3Dv1()) def test_function_annotations(self): # Some dummy class and instance to use as a default. class F: pass + f = F() def validate_class(cls): # First, check __annotations__, even though they're not # function annotations. - self.assertEqual(cls.__annotations__['i'], int) - self.assertEqual(cls.__annotations__['j'], str) - self.assertEqual(cls.__annotations__['k'], F) - self.assertEqual(cls.__annotations__['l'], float) - self.assertEqual(cls.__annotations__['z'], complex) + self.assertEqual(cls.__annotations__["i"], int) + self.assertEqual(cls.__annotations__["j"], str) + self.assertEqual(cls.__annotations__["k"], F) + self.assertEqual(cls.__annotations__["l"], float) + self.assertEqual(cls.__annotations__["z"], complex) # Verify __init__. @@ -874,37 +967,36 @@ def validate_class(cls): params = iter(signature.parameters.values()) param = next(params) # This is testing an internal name, and probably shouldn't be tested. - self.assertEqual(param.name, 'self') + self.assertEqual(param.name, "self") param = next(params) - self.assertEqual(param.name, 'i') - self.assertIs (param.annotation, int) + self.assertEqual(param.name, "i") + self.assertIs(param.annotation, int) self.assertEqual(param.default, inspect.Parameter.empty) self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) param = next(params) - self.assertEqual(param.name, 'j') - self.assertIs (param.annotation, str) + self.assertEqual(param.name, "j") + self.assertIs(param.annotation, str) self.assertEqual(param.default, inspect.Parameter.empty) self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) param = next(params) - self.assertEqual(param.name, 'k') - self.assertIs (param.annotation, F) + self.assertEqual(param.name, "k") + self.assertIs(param.annotation, F) # Don't test for the default, since it's set to MISSING. self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) param = next(params) - self.assertEqual(param.name, 'l') - self.assertIs (param.annotation, float) + self.assertEqual(param.name, "l") + self.assertIs(param.annotation, float) # Don't test for the default, since it's set to MISSING. self.assertEqual(param.kind, inspect.Parameter.POSITIONAL_OR_KEYWORD) self.assertRaises(StopIteration, next, params) - @dataclass class C: i: int j: str k: F = f - l: float=field(default=None) - z: complex=field(default=3+4j, init=False) + l: float = field(default=None) + z: complex = field(default=3 + 4j, init=False) validate_class(C) @@ -914,8 +1006,8 @@ class C: i: int j: str k: F = f - l: float=field(default=None) - z: complex=field(default=3+4j, init=False) + l: float = field(default=None) + z: complex = field(default=3 + 4j, init=False) validate_class(C) @@ -924,21 +1016,23 @@ def test_missing_default(self): # specified. @dataclass class C: - x: int=field(default=MISSING) - with self.assertRaisesRegex(TypeError, - r'__init__\(\) missing 1 required ' - 'positional argument'): + x: int = field(default=MISSING) + + with self.assertRaisesRegex( + TypeError, r"__init__\(\) missing 1 required " "positional argument" + ): C() - self.assertNotIn('x', C.__dict__) + self.assertNotIn("x", C.__dict__) @dataclass class D: x: int - with self.assertRaisesRegex(TypeError, - r'__init__\(\) missing 1 required ' - 'positional argument'): + + with self.assertRaisesRegex( + TypeError, r"__init__\(\) missing 1 required " "positional argument" + ): D() - self.assertNotIn('x', D.__dict__) + self.assertNotIn("x", D.__dict__) def test_missing_default_factory(self): # Test that MISSING works the same as a default factory not @@ -946,35 +1040,40 @@ def test_missing_default_factory(self): # being specified, too). @dataclass class C: - x: int=field(default_factory=MISSING) - with self.assertRaisesRegex(TypeError, - r'__init__\(\) missing 1 required ' - 'positional argument'): + x: int = field(default_factory=MISSING) + + with self.assertRaisesRegex( + TypeError, r"__init__\(\) missing 1 required " "positional argument" + ): C() - self.assertNotIn('x', C.__dict__) + self.assertNotIn("x", C.__dict__) @dataclass class D: - x: int=field(default=MISSING, default_factory=MISSING) - with self.assertRaisesRegex(TypeError, - r'__init__\(\) missing 1 required ' - 'positional argument'): + x: int = field(default=MISSING, default_factory=MISSING) + + with self.assertRaisesRegex( + TypeError, r"__init__\(\) missing 1 required " "positional argument" + ): D() - self.assertNotIn('x', D.__dict__) + self.assertNotIn("x", D.__dict__) def test_missing_repr(self): - self.assertIn('MISSING_TYPE object', repr(MISSING)) + self.assertIn("MISSING_TYPE object", repr(MISSING)) def test_dont_include_other_annotations(self): @dataclass class C: i: int + def foo(self) -> int: return 4 + @property def bar(self) -> int: return 5 - self.assertEqual(list(C.__annotations__), ['i']) + + self.assertEqual(list(C.__annotations__), ["i"]) self.assertEqual(C(10).foo(), 4) self.assertEqual(C(10).bar, 5) self.assertEqual(C(10).i, 10) @@ -985,15 +1084,18 @@ def test_post_init(self): class C: def __post_init__(self): raise CustomError() + with self.assertRaises(CustomError): C() @dataclass class C: i: int = 10 + def __post_init__(self): if self.i == 10: raise CustomError() + with self.assertRaises(CustomError): C() # post-init gets called, but doesn't raise. This is just @@ -1005,14 +1107,17 @@ def __post_init__(self): class C: def __post_init__(self): raise CustomError() + # Creating the class won't raise C() @dataclass class C: x: int = 0 + def __post_init__(self): self.x *= 2 + self.assertEqual(C().x, 0) self.assertEqual(C(2).x, 4) @@ -1021,8 +1126,10 @@ def __post_init__(self): @dataclass(frozen=True) class C: x: int = 0 + def __post_init__(self): self.x *= 2 + with self.assertRaises(FrozenInstanceError): C() @@ -1059,10 +1166,12 @@ class C(B): def test_post_init_staticmethod(self): flag = False + @dataclass class C: x: int y: int + @staticmethod def __post_init__(): nonlocal flag @@ -1079,6 +1188,7 @@ class C: flag = False x: int y: int + @classmethod def __post_init__(cls): cls.flag = True @@ -1100,12 +1210,14 @@ class A0: @dataclass class B0: b_called: bool = False + def __post_init__(self): self.b_called = True @dataclass class C0(A0, B0): c_called: bool = False + def __post_init__(self): super().__post_init__() self.c_called = True @@ -1128,12 +1240,14 @@ def __post_init__(self): @dataclass class B1: b_called: bool = False + def __post_init__(self): self.b_called = True @dataclass class C1(A1, B1): c_called: bool = False + def __post_init__(self): super().__post_init__() self.c_called = True @@ -1156,12 +1270,12 @@ class C: z: ClassVar[int] = 1000 w: ClassVar[int] = 2000 t: ClassVar[int] = 3000 - s: ClassVar = 4000 + s: ClassVar = 4000 c = C(5) - self.assertEqual(repr(c), 'TestCase.test_class_var..C(x=5, y=10)') - self.assertEqual(len(fields(C)), 2) # We have 2 fields. - self.assertEqual(len(C.__annotations__), 6) # And 4 ClassVars. + self.assertEqual(repr(c), "TestCase.test_class_var..C(x=5, y=10)") + self.assertEqual(len(fields(C)), 2) # We have 2 fields. + self.assertEqual(len(C.__annotations__), 6) # And 4 ClassVars. self.assertEqual(c.z, 1000) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) @@ -1181,29 +1295,31 @@ def test_class_var_no_default(self): class C: x: ClassVar[int] - self.assertNotIn('x', C.__dict__) + self.assertNotIn("x", C.__dict__) def test_class_var_default_factory(self): # It makes no sense for a ClassVar to have a default factory. When # would it be called? Call it yourself, since it's class-wide. - with self.assertRaisesRegex(TypeError, - 'cannot have a default factory'): + with self.assertRaisesRegex(TypeError, "cannot have a default factory"): + @dataclass class C: x: ClassVar[int] = field(default_factory=int) - self.assertNotIn('x', C.__dict__) + self.assertNotIn("x", C.__dict__) def test_class_var_with_default(self): # If a ClassVar has a default value, it should be set on the class. @dataclass class C: x: ClassVar[int] = 10 + self.assertEqual(C.x, 10) @dataclass class C: x: ClassVar[int] = field(default=10) + self.assertEqual(C.x, 10) def test_class_var_frozen(self): @@ -1217,9 +1333,11 @@ class C: t: ClassVar[int] = 3000 c = C(5) - self.assertEqual(repr(C(5)), 'TestCase.test_class_var_frozen..C(x=5, y=10)') - self.assertEqual(len(fields(C)), 2) # We have 2 fields - self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars + self.assertEqual( + repr(C(5)), "TestCase.test_class_var_frozen..C(x=5, y=10)" + ) + self.assertEqual(len(fields(C)), 2) # We have 2 fields + self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars self.assertEqual(c.z, 1000) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) @@ -1239,29 +1357,31 @@ def test_init_var_no_default(self): class C: x: InitVar[int] - self.assertNotIn('x', C.__dict__) + self.assertNotIn("x", C.__dict__) def test_init_var_default_factory(self): # It makes no sense for an InitVar to have a default factory. When # would it be called? Call it yourself, since it's class-wide. - with self.assertRaisesRegex(TypeError, - 'cannot have a default factory'): + with self.assertRaisesRegex(TypeError, "cannot have a default factory"): + @dataclass class C: x: InitVar[int] = field(default_factory=int) - self.assertNotIn('x', C.__dict__) + self.assertNotIn("x", C.__dict__) def test_init_var_with_default(self): # If an InitVar has a default value, it should be set on the class. @dataclass class C: x: InitVar[int] = 10 + self.assertEqual(C.x, 10) @dataclass class C: x: InitVar[int] = field(default=10) + self.assertEqual(C.x, 10) def test_init_var(self): @@ -1272,7 +1392,7 @@ class C: def __post_init__(self, init_param): if self.x is None: - self.x = init_param*2 + self.x = init_param * 2 c = C(init_param=10) self.assertEqual(c.x, 20) @@ -1281,13 +1401,12 @@ def test_init_var_preserve_type(self): self.assertEqual(InitVar[int].type, int) # Make sure the repr is correct. - self.assertEqual(repr(InitVar[int]), 'dataclasses.InitVar[int]') - self.assertEqual(repr(InitVar[List[int]]), - 'dataclasses.InitVar[typing.List[int]]') - self.assertEqual(repr(InitVar[list[int]]), - 'dataclasses.InitVar[list[int]]') - self.assertEqual(repr(InitVar[int|str]), - 'dataclasses.InitVar[int | str]') + self.assertEqual(repr(InitVar[int]), "dataclasses.InitVar[int]") + self.assertEqual( + repr(InitVar[List[int]]), "dataclasses.InitVar[typing.List[int]]" + ) + self.assertEqual(repr(InitVar[list[int]]), "dataclasses.InitVar[list[int]]") + self.assertEqual(repr(InitVar[int | str]), "dataclasses.InitVar[int | str]") def test_init_var_inheritance(self): # Note that this deliberately tests that a dataclass need not @@ -1301,7 +1420,7 @@ class Base: # We can instantiate by passing the InitVar, even though # it's not used. b = Base(0, 10) - self.assertEqual(vars(b), {'x': 0}) + self.assertEqual(vars(b), {"x": 0}) @dataclass class C(Base): @@ -1313,7 +1432,7 @@ def __post_init__(self, init_base, init_derived): self.y = self.y + init_derived c = C(10, 11, 50, 51) - self.assertEqual(vars(c), {'x': 21, 'y': 101}) + self.assertEqual(vars(c), {"x": 21, "y": 101}) def test_default_factory(self): # Test a factory that returns a new list. @@ -1332,6 +1451,7 @@ class C: # Test a factory that returns a shared list. l = [] + @dataclass class C: x: int @@ -1350,13 +1470,15 @@ class C: @dataclass class C: x: list = field(default_factory=list, repr=False) - self.assertEqual(repr(C()), 'TestCase.test_default_factory..C()') + + self.assertEqual(repr(C()), "TestCase.test_default_factory..C()") self.assertEqual(C().x, []) # hash @dataclass(unsafe_hash=True) class C: x: list = field(default_factory=list, hash=False) + self.assertEqual(astuple(C()), ([],)) self.assertEqual(hash(C()), hash(())) @@ -1364,12 +1486,14 @@ class C: @dataclass class C: x: list = field(default_factory=list, init=False) + self.assertEqual(astuple(C()), ([],)) # compare @dataclass class C: x: list = field(default_factory=list, compare=False) + self.assertEqual(C(), C([1])) def test_default_factory_with_no_init(self): @@ -1420,6 +1544,7 @@ class Bar(Foo): @dataclass class Baz(Foo): pass + self.assertEqual(Baz().x, {}) def test_intermediate_non_dataclass(self): @@ -1441,20 +1566,20 @@ class C(B): self.assertEqual((c.x, c.z), (1, 3)) # .y was not initialized. - with self.assertRaisesRegex(AttributeError, - 'object has no attribute'): + with self.assertRaisesRegex(AttributeError, "object has no attribute"): c.y # And if we again derive a non-dataclass, no fields are added. class D(C): t: int + d = D(4, 5) self.assertEqual((d.x, d.z), (4, 5)) def test_classvar_default_factory(self): # It's an error for a ClassVar to have a factory function. - with self.assertRaisesRegex(TypeError, - 'cannot have a default factory'): + with self.assertRaisesRegex(TypeError, "cannot have a default factory"): + @dataclass class C: x: ClassVar[int] = field(default_factory=int) @@ -1491,12 +1616,14 @@ def test_is_dataclass_when_getattr_always_returns(self): class A: def __getattr__(self, key): return 0 + self.assertFalse(is_dataclass(A)) a = A() # Also test for an instance attribute. class B: pass + b = B() b.__dataclass_fields__ = [] @@ -1505,11 +1632,17 @@ class B: self.assertFalse(is_dataclass(obj)) # Indirect tests for _is_dataclass_instance(). - with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + with self.assertRaisesRegex( + TypeError, "should be called on dataclass instances" + ): asdict(obj) - with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + with self.assertRaisesRegex( + TypeError, "should be called on dataclass instances" + ): astuple(obj) - with self.assertRaisesRegex(TypeError, 'should be called on dataclass instances'): + with self.assertRaisesRegex( + TypeError, "should be called on dataclass instances" + ): replace(obj, x=0) def test_is_dataclass_genericalias(self): @@ -1517,12 +1650,12 @@ def test_is_dataclass_genericalias(self): class A(types.GenericAlias): origin: type args: type + self.assertTrue(is_dataclass(A)) a = A(list, int) self.assertTrue(is_dataclass(type(a))) self.assertTrue(is_dataclass(a)) - def test_helper_fields_with_class_instance(self): # Check that we can call fields() on either a class or instance, # and get back the same thing. @@ -1536,13 +1669,15 @@ class C: def test_helper_fields_exception(self): # Check that TypeError is raised if not passed a dataclass or # instance. - with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + with self.assertRaisesRegex(TypeError, "dataclass type or instance"): fields(0) - class C: pass - with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + class C: + pass + + with self.assertRaisesRegex(TypeError, "dataclass type or instance"): fields(C) - with self.assertRaisesRegex(TypeError, 'dataclass type or instance'): + with self.assertRaisesRegex(TypeError, "dataclass type or instance"): fields(C()) def test_clean_traceback_from_fields_exception(self): @@ -1561,13 +1696,14 @@ def test_helper_asdict(self): class C: x: int y: int + c = C(1, 2) - self.assertEqual(asdict(c), {'x': 1, 'y': 2}) + self.assertEqual(asdict(c), {"x": 1, "y": 2}) self.assertEqual(asdict(c), asdict(c)) self.assertIsNot(asdict(c), asdict(c)) c.x = 42 - self.assertEqual(asdict(c), {'x': 42, 'y': 2}) + self.assertEqual(asdict(c), {"x": 42, "y": 2}) self.assertIs(type(asdict(c)), dict) def test_helper_asdict_raises_on_classes(self): @@ -1576,9 +1712,10 @@ def test_helper_asdict_raises_on_classes(self): class C: x: int y: int - with self.assertRaisesRegex(TypeError, 'dataclass instance'): + + with self.assertRaisesRegex(TypeError, "dataclass instance"): asdict(C) - with self.assertRaisesRegex(TypeError, 'dataclass instance'): + with self.assertRaisesRegex(TypeError, "dataclass instance"): asdict(int) def test_helper_asdict_copy_values(self): @@ -1586,14 +1723,15 @@ def test_helper_asdict_copy_values(self): class C: x: int y: List[int] = field(default_factory=list) + initial = [] c = C(1, initial) d = asdict(c) - self.assertEqual(d['y'], initial) - self.assertIsNot(d['y'], initial) + self.assertEqual(d["y"], initial) + self.assertIsNot(d["y"], initial) c = C(1) d = asdict(c) - d['y'].append(1) + d["y"].append(1) self.assertEqual(c.y, []) def test_helper_asdict_nested(self): @@ -1601,46 +1739,63 @@ def test_helper_asdict_nested(self): class UserId: token: int group: int + @dataclass class User: name: str id: UserId - u = User('Joe', UserId(123, 1)) + + u = User("Joe", UserId(123, 1)) d = asdict(u) - self.assertEqual(d, {'name': 'Joe', 'id': {'token': 123, 'group': 1}}) + self.assertEqual(d, {"name": "Joe", "id": {"token": 123, "group": 1}}) self.assertIsNot(asdict(u), asdict(u)) u.id.group = 2 - self.assertEqual(asdict(u), {'name': 'Joe', - 'id': {'token': 123, 'group': 2}}) + self.assertEqual(asdict(u), {"name": "Joe", "id": {"token": 123, "group": 2}}) def test_helper_asdict_builtin_containers(self): @dataclass class User: name: str id: int + @dataclass class GroupList: id: int users: List[User] + @dataclass class GroupTuple: id: int users: Tuple[User, ...] + @dataclass class GroupDict: id: int users: Dict[str, User] - a = User('Alice', 1) - b = User('Bob', 2) + + a = User("Alice", 1) + b = User("Bob", 2) gl = GroupList(0, [a, b]) gt = GroupTuple(0, (a, b)) - gd = GroupDict(0, {'first': a, 'second': b}) - self.assertEqual(asdict(gl), {'id': 0, 'users': [{'name': 'Alice', 'id': 1}, - {'name': 'Bob', 'id': 2}]}) - self.assertEqual(asdict(gt), {'id': 0, 'users': ({'name': 'Alice', 'id': 1}, - {'name': 'Bob', 'id': 2})}) - self.assertEqual(asdict(gd), {'id': 0, 'users': {'first': {'name': 'Alice', 'id': 1}, - 'second': {'name': 'Bob', 'id': 2}}}) + gd = GroupDict(0, {"first": a, "second": b}) + self.assertEqual( + asdict(gl), + {"id": 0, "users": [{"name": "Alice", "id": 1}, {"name": "Bob", "id": 2}]}, + ) + self.assertEqual( + asdict(gt), + {"id": 0, "users": ({"name": "Alice", "id": 1}, {"name": "Bob", "id": 2})}, + ) + self.assertEqual( + asdict(gd), + { + "id": 0, + "users": { + "first": {"name": "Alice", "id": 1}, + "second": {"name": "Bob", "id": 2}, + }, + }, + ) def test_helper_asdict_builtin_object_containers(self): @dataclass @@ -1651,55 +1806,58 @@ class Child: class Parent: child: Child - self.assertEqual(asdict(Parent(Child([1]))), {'child': {'d': [1]}}) - self.assertEqual(asdict(Parent(Child({1: 2}))), {'child': {'d': {1: 2}}}) + self.assertEqual(asdict(Parent(Child([1]))), {"child": {"d": [1]}}) + self.assertEqual(asdict(Parent(Child({1: 2}))), {"child": {"d": {1: 2}}}) def test_helper_asdict_factory(self): @dataclass class C: x: int y: int + c = C(1, 2) d = asdict(c, dict_factory=OrderedDict) - self.assertEqual(d, OrderedDict([('x', 1), ('y', 2)])) + self.assertEqual(d, OrderedDict([("x", 1), ("y", 2)])) self.assertIsNot(d, asdict(c, dict_factory=OrderedDict)) c.x = 42 d = asdict(c, dict_factory=OrderedDict) - self.assertEqual(d, OrderedDict([('x', 42), ('y', 2)])) + self.assertEqual(d, OrderedDict([("x", 42), ("y", 2)])) self.assertIs(type(d), OrderedDict) def test_helper_asdict_namedtuple(self): - T = namedtuple('T', 'a b c') + T = namedtuple("T", "a b c") + @dataclass class C: x: str y: T - c = C('outer', T(1, C('inner', T(11, 12, 13)), 2)) + + c = C("outer", T(1, C("inner", T(11, 12, 13)), 2)) d = asdict(c) - self.assertEqual(d, {'x': 'outer', - 'y': T(1, - {'x': 'inner', - 'y': T(11, 12, 13)}, - 2), - } - ) + self.assertEqual( + d, + { + "x": "outer", + "y": T(1, {"x": "inner", "y": T(11, 12, 13)}, 2), + }, + ) # Now with a dict_factory. OrderedDict is convenient, but # since it compares to dicts, we also need to have separate # assertIs tests. d = asdict(c, dict_factory=OrderedDict) - self.assertEqual(d, {'x': 'outer', - 'y': T(1, - {'x': 'inner', - 'y': T(11, 12, 13)}, - 2), - } - ) + self.assertEqual( + d, + { + "x": "outer", + "y": T(1, {"x": "inner", "y": T(11, 12, 13)}, 2), + }, + ) # Make sure that the returned dicts are actually OrderedDicts. self.assertIs(type(d), OrderedDict) - self.assertIs(type(d['y'][1]), OrderedDict) + self.assertIs(type(d["y"][1]), OrderedDict) def test_helper_asdict_namedtuple_key(self): # Ensure that a field that contains a dict which has a @@ -1708,14 +1866,15 @@ def test_helper_asdict_namedtuple_key(self): @dataclass class C: f: dict - T = namedtuple('T', 'a') - c = C({T('an a'): 0}) + T = namedtuple("T", "a") + + c = C({T("an a"): 0}) - self.assertEqual(asdict(c), {'f': {T(a='an a'): 0}}) + self.assertEqual(asdict(c), {"f": {T(a="an a"): 0}}) def test_helper_asdict_namedtuple_derived(self): - class T(namedtuple('Tbase', 'a')): + class T(namedtuple("Tbase", "a")): def my_a(self): return self.a @@ -1727,10 +1886,10 @@ class C: c = C(t) d = asdict(c) - self.assertEqual(d, {'f': T(a=6)}) + self.assertEqual(d, {"f": T(a=6)}) # Make sure that t has been copied, not used directly. - self.assertIsNot(d['f'], t) - self.assertEqual(d['f'].my_a(), 6) + self.assertIsNot(d["f"], t) + self.assertEqual(d["f"].my_a(), 6) def test_helper_asdict_defaultdict(self): # Ensure asdict() does not throw exceptions when a @@ -1753,6 +1912,7 @@ def test_helper_astuple(self): class C: x: int y: int = 0 + c = C(1) self.assertEqual(astuple(c), (1, 0)) @@ -1768,9 +1928,10 @@ def test_helper_astuple_raises_on_classes(self): class C: x: int y: int - with self.assertRaisesRegex(TypeError, 'dataclass instance'): + + with self.assertRaisesRegex(TypeError, "dataclass instance"): astuple(C) - with self.assertRaisesRegex(TypeError, 'dataclass instance'): + with self.assertRaisesRegex(TypeError, "dataclass instance"): astuple(int) def test_helper_astuple_copy_values(self): @@ -1778,6 +1939,7 @@ def test_helper_astuple_copy_values(self): class C: x: int y: List[int] = field(default_factory=list) + initial = [] c = C(1, initial) t = astuple(c) @@ -1793,42 +1955,50 @@ def test_helper_astuple_nested(self): class UserId: token: int group: int + @dataclass class User: name: str id: UserId - u = User('Joe', UserId(123, 1)) + + u = User("Joe", UserId(123, 1)) t = astuple(u) - self.assertEqual(t, ('Joe', (123, 1))) + self.assertEqual(t, ("Joe", (123, 1))) self.assertIsNot(astuple(u), astuple(u)) u.id.group = 2 - self.assertEqual(astuple(u), ('Joe', (123, 2))) + self.assertEqual(astuple(u), ("Joe", (123, 2))) def test_helper_astuple_builtin_containers(self): @dataclass class User: name: str id: int + @dataclass class GroupList: id: int users: List[User] + @dataclass class GroupTuple: id: int users: Tuple[User, ...] + @dataclass class GroupDict: id: int users: Dict[str, User] - a = User('Alice', 1) - b = User('Bob', 2) + + a = User("Alice", 1) + b = User("Bob", 2) gl = GroupList(0, [a, b]) gt = GroupTuple(0, (a, b)) - gd = GroupDict(0, {'first': a, 'second': b}) - self.assertEqual(astuple(gl), (0, [('Alice', 1), ('Bob', 2)])) - self.assertEqual(astuple(gt), (0, (('Alice', 1), ('Bob', 2)))) - self.assertEqual(astuple(gd), (0, {'first': ('Alice', 1), 'second': ('Bob', 2)})) + gd = GroupDict(0, {"first": a, "second": b}) + self.assertEqual(astuple(gl), (0, [("Alice", 1), ("Bob", 2)])) + self.assertEqual(astuple(gt), (0, (("Alice", 1), ("Bob", 2)))) + self.assertEqual( + astuple(gd), (0, {"first": ("Alice", 1), "second": ("Bob", 2)}) + ) def test_helper_astuple_builtin_object_containers(self): @dataclass @@ -1847,9 +2017,12 @@ def test_helper_astuple_factory(self): class C: x: int y: int - NT = namedtuple('NT', 'x y') + + NT = namedtuple("NT", "x y") + def nt(lst): return NT(*lst) + c = C(1, 2) t = astuple(c, tuple_factory=nt) self.assertEqual(t, NT(1, 2)) @@ -1860,19 +2033,21 @@ def nt(lst): self.assertIs(type(t), NT) def test_helper_astuple_namedtuple(self): - T = namedtuple('T', 'a b c') + T = namedtuple("T", "a b c") + @dataclass class C: x: str y: T - c = C('outer', T(1, C('inner', T(11, 12, 13)), 2)) + + c = C("outer", T(1, C("inner", T(11, 12, 13)), 2)) t = astuple(c) - self.assertEqual(t, ('outer', T(1, ('inner', (11, 12, 13)), 2))) + self.assertEqual(t, ("outer", T(1, ("inner", (11, 12, 13)), 2))) # Now, using a tuple_factory. list is convenient here. t = astuple(c, tuple_factory=list) - self.assertEqual(t, ['outer', T(1, ['inner', T(11, 12, 13)], 2)]) + self.assertEqual(t, ["outer", T(1, ["inner", T(11, 12, 13)], 2)]) def test_helper_astuple_defaultdict(self): # Ensure astuple() does not throw exceptions when a @@ -1887,34 +2062,36 @@ class C: t = astuple(c) self.assertEqual(t, ({"x": [12]},)) - self.assertTrue(t[0] is not dd) # make sure defaultdict is copied + self.assertTrue(t[0] is not dd) # make sure defaultdict is copied def test_dynamic_class_creation(self): - cls_dict = {'__annotations__': {'x': int, 'y': int}, - } + cls_dict = { + "__annotations__": {"x": int, "y": int}, + } # Create the class. - cls = type('C', (), cls_dict) + cls = type("C", (), cls_dict) # Make it a dataclass. cls1 = dataclass(cls) self.assertEqual(cls1, cls) - self.assertEqual(asdict(cls(1, 2)), {'x': 1, 'y': 2}) + self.assertEqual(asdict(cls(1, 2)), {"x": 1, "y": 2}) def test_dynamic_class_creation_using_field(self): - cls_dict = {'__annotations__': {'x': int, 'y': int}, - 'y': field(default=5), - } + cls_dict = { + "__annotations__": {"x": int, "y": int}, + "y": field(default=5), + } # Create the class. - cls = type('C', (), cls_dict) + cls = type("C", (), cls_dict) # Make it a dataclass. cls1 = dataclass(cls) self.assertEqual(cls1, cls) - self.assertEqual(asdict(cls1(1)), {'x': 1, 'y': 5}) + self.assertEqual(asdict(cls1(1)), {"x": 1, "y": 5}) def test_init_in_order(self): @dataclass @@ -1927,17 +2104,18 @@ class C: f: int = 4 calls = [] + def setattr(self, name, value): calls.append((name, value)) C.__setattr__ = setattr c = C(0, 1) - self.assertEqual(('a', 0), calls[0]) - self.assertEqual(('b', 1), calls[1]) - self.assertEqual(('c', []), calls[2]) - self.assertEqual(('d', []), calls[3]) - self.assertNotIn(('e', 4), calls) - self.assertEqual(('f', 4), calls[4]) + self.assertEqual(("a", 0), calls[0]) + self.assertEqual(("b", 1), calls[1]) + self.assertEqual(("c", []), calls[2]) + self.assertEqual(("d", []), calls[3]) + self.assertNotIn(("e", 4), calls) + self.assertEqual(("f", 4), calls[4]) def test_items_in_dicts(self): @dataclass @@ -1950,22 +2128,22 @@ class C: c = C(0) # Class dict - self.assertNotIn('a', C.__dict__) - self.assertNotIn('b', C.__dict__) - self.assertNotIn('c', C.__dict__) - self.assertIn('d', C.__dict__) + self.assertNotIn("a", C.__dict__) + self.assertNotIn("b", C.__dict__) + self.assertNotIn("c", C.__dict__) + self.assertIn("d", C.__dict__) self.assertEqual(C.d, 4) - self.assertIn('e', C.__dict__) + self.assertIn("e", C.__dict__) self.assertEqual(C.e, 0) # Instance dict - self.assertIn('a', c.__dict__) + self.assertIn("a", c.__dict__) self.assertEqual(c.a, 0) - self.assertIn('b', c.__dict__) + self.assertIn("b", c.__dict__) self.assertEqual(c.b, []) - self.assertIn('c', c.__dict__) + self.assertIn("c", c.__dict__) self.assertEqual(c.c, []) - self.assertNotIn('d', c.__dict__) - self.assertIn('e', c.__dict__) + self.assertNotIn("d", c.__dict__) + self.assertIn("e", c.__dict__) self.assertEqual(c.e, 0) def test_alternate_classmethod_constructor(self): @@ -1975,6 +2153,7 @@ def test_alternate_classmethod_constructor(self): @dataclass class C: x: int + @classmethod def from_file(cls, filename): # In a real example, create a new instance @@ -1982,7 +2161,7 @@ def from_file(cls, filename): value_in_file = 20 return cls(value_in_file) - self.assertEqual(C.from_file('filename').x, 20) + self.assertEqual(C.from_file("filename").x, 20) def test_field_metadata_default(self): # Make sure the default metadata is read-only and of @@ -1993,52 +2172,54 @@ class C: self.assertFalse(fields(C)[0].metadata) self.assertEqual(len(fields(C)[0].metadata), 0) - with self.assertRaisesRegex(TypeError, - 'does not support item assignment'): - fields(C)[0].metadata['test'] = 3 + with self.assertRaisesRegex(TypeError, "does not support item assignment"): + fields(C)[0].metadata["test"] = 3 def test_field_metadata_mapping(self): # Make sure only a mapping can be passed as metadata # zero length. with self.assertRaises(TypeError): + @dataclass class C: i: int = field(metadata=0) # Make sure an empty dict works. d = {} + @dataclass class C: i: int = field(metadata=d) + self.assertFalse(fields(C)[0].metadata) self.assertEqual(len(fields(C)[0].metadata), 0) # Update should work (see bpo-35960). - d['foo'] = 1 + d["foo"] = 1 self.assertEqual(len(fields(C)[0].metadata), 1) - self.assertEqual(fields(C)[0].metadata['foo'], 1) - with self.assertRaisesRegex(TypeError, - 'does not support item assignment'): - fields(C)[0].metadata['test'] = 3 + self.assertEqual(fields(C)[0].metadata["foo"], 1) + with self.assertRaisesRegex(TypeError, "does not support item assignment"): + fields(C)[0].metadata["test"] = 3 # Make sure a non-empty dict works. - d = {'test': 10, 'bar': '42', 3: 'three'} + d = {"test": 10, "bar": "42", 3: "three"} + @dataclass class C: i: int = field(metadata=d) + self.assertEqual(len(fields(C)[0].metadata), 3) - self.assertEqual(fields(C)[0].metadata['test'], 10) - self.assertEqual(fields(C)[0].metadata['bar'], '42') - self.assertEqual(fields(C)[0].metadata[3], 'three') + self.assertEqual(fields(C)[0].metadata["test"], 10) + self.assertEqual(fields(C)[0].metadata["bar"], "42") + self.assertEqual(fields(C)[0].metadata[3], "three") # Update should work. - d['foo'] = 1 + d["foo"] = 1 self.assertEqual(len(fields(C)[0].metadata), 4) - self.assertEqual(fields(C)[0].metadata['foo'], 1) + self.assertEqual(fields(C)[0].metadata["foo"], 1) with self.assertRaises(KeyError): # Non-existent key. - fields(C)[0].metadata['baz'] - with self.assertRaisesRegex(TypeError, - 'does not support item assignment'): - fields(C)[0].metadata['test'] = 3 + fields(C)[0].metadata["baz"] + with self.assertRaisesRegex(TypeError, "does not support item assignment"): + fields(C)[0].metadata["test"] = 3 def test_field_metadata_custom_mapping(self): # Try a custom mapping. @@ -2047,8 +2228,8 @@ def __init__(self, **kw): self.__dict__.update(kw) def __getitem__(self, item): - if item == 'xyzzy': - return 'plugh' + if item == "xyzzy": + return "plugh" return getattr(self, item) def __len__(self): @@ -2059,30 +2240,30 @@ class C: i: int = field(metadata=SimpleNameSpace(a=10)) self.assertEqual(len(fields(C)[0].metadata), 1) - self.assertEqual(fields(C)[0].metadata['a'], 10) + self.assertEqual(fields(C)[0].metadata["a"], 10) with self.assertRaises(AttributeError): - fields(C)[0].metadata['b'] + fields(C)[0].metadata["b"] # Make sure we're still talking to our custom mapping. - self.assertEqual(fields(C)[0].metadata['xyzzy'], 'plugh') + self.assertEqual(fields(C)[0].metadata["xyzzy"], "plugh") def test_generic_dataclasses(self): - T = TypeVar('T') + T = TypeVar("T") @dataclass class LabeledBox(Generic[T]): content: T - label: str = '' + label: str = "" box = LabeledBox(42) self.assertEqual(box.content, 42) - self.assertEqual(box.label, '') + self.assertEqual(box.label, "") # Subscripting the resulting class should work, etc. Alias = List[LabeledBox[int]] def test_generic_extending(self): - S = TypeVar('S') - T = TypeVar('T') + S = TypeVar("S") + T = TypeVar("T") @dataclass class Base(Generic[T, S]): @@ -2092,25 +2273,32 @@ class Base(Generic[T, S]): @dataclass class DataDerived(Base[int, T]): new_field: str + Alias = DataDerived[str] - c = Alias(0, 'test1', 'test2') - self.assertEqual(astuple(c), (0, 'test1', 'test2')) + c = Alias(0, "test1", "test2") + self.assertEqual(astuple(c), (0, "test1", "test2")) class NonDataDerived(Base[int, T]): def new_method(self): return self.y + Alias = NonDataDerived[float] c = Alias(10, 1.0) self.assertEqual(c.new_method(), 1.0) def test_generic_dynamic(self): - T = TypeVar('T') + T = TypeVar("T") @dataclass class Parent(Generic[T]): x: T - Child = make_dataclass('Child', [('y', T), ('z', Optional[T], None)], - bases=(Parent[int], Generic[T]), namespace={'other': 42}) + + Child = make_dataclass( + "Child", + [("y", T), ("z", Optional[T], None)], + bases=(Parent[int], Generic[T]), + namespace={"other": 42}, + ) self.assertIs(Child[int](1, 2).z, None) self.assertEqual(Child[int](1, 2, 3).z, 3) self.assertEqual(Child[int](1, 2, 3).other, 42) @@ -2122,18 +2310,22 @@ class Parent(Generic[T]): def test_dataclasses_pickleable(self): global P, Q, R + @dataclass class P: x: int y: int = 0 + @dataclass class Q: x: int y: int = field(default=0, init=False) + @dataclass class R: x: int y: List[int] = field(default_factory=list) + q = Q(1) q.y = 2 samples = [P(1), P(1, 2), Q(1), q, R(1), R(1, [2, 3, 4])] @@ -2157,18 +2349,21 @@ class A: self.assertEqual(A.__init__.__name__, "__init__") for function in ( - '__eq__', - '__lt__', - '__le__', - '__gt__', - '__ge__', - '__hash__', - '__init__', - '__repr__', - '__setattr__', - '__delattr__', + "__eq__", + "__lt__", + "__le__", + "__gt__", + "__ge__", + "__hash__", + "__init__", + "__repr__", + "__setattr__", + "__delattr__", ): - self.assertEqual(getattr(A, function).__qualname__, f"TestCase.test_dataclasses_qualnames..A.{function}") + self.assertEqual( + getattr(A, function).__qualname__, + f"TestCase.test_dataclasses_qualnames..A.{function}", + ) with self.assertRaisesRegex(TypeError, r"A\.__init__\(\) missing"): A() @@ -2176,8 +2371,10 @@ class A: class TestFieldNoAnnotation(unittest.TestCase): def test_field_without_annotation(self): - with self.assertRaisesRegex(TypeError, - "'f' is a field but has no type annotation"): + with self.assertRaisesRegex( + TypeError, "'f' is a field but has no type annotation" + ): + @dataclass class C: f = field() @@ -2187,8 +2384,9 @@ def test_field_without_annotation_but_annotation_in_base(self): class B: f: int - with self.assertRaisesRegex(TypeError, - "'f' is a field but has no type annotation"): + with self.assertRaisesRegex( + TypeError, "'f' is a field but has no type annotation" + ): # This is still an error: make sure we don't pick up the # type annotation in the base class. @dataclass @@ -2200,8 +2398,9 @@ def test_field_without_annotation_but_annotation_in_base_not_dataclass(self): class B: f: int - with self.assertRaisesRegex(TypeError, - "'f' is a field but has no type annotation"): + with self.assertRaisesRegex( + TypeError, "'f' is a field but has no type annotation" + ): # This is still an error: make sure we don't pick up the # type annotation in the base class. @dataclass @@ -2214,12 +2413,13 @@ def assertDocStrEqual(self, a, b): # Because 3.6 and 3.7 differ in how inspect.signature work # (see bpo #32108), for the time being just compare them with # whitespace stripped. - self.assertEqual(a.replace(' ', ''), b.replace(' ', '')) + self.assertEqual(a.replace(" ", ""), b.replace(" ", "")) def test_existing_docstring_not_overridden(self): @dataclass class C: """Lorem ipsum""" + x: int self.assertEqual(C.__doc__, "Lorem ipsum") @@ -2301,6 +2501,7 @@ def test_docstring_with_no_signature(self): # See https://github.com/python/cpython/issues/103449 class Meta(type): __call__ = dict + class Base(metaclass=Meta): pass @@ -2324,15 +2525,17 @@ def __init__(self): @dataclass class C(B): x: int = 0 + c = C(10) self.assertEqual(c.x, 10) - self.assertNotIn('z', vars(c)) + self.assertNotIn("z", vars(c)) # Make sure that if we don't add an init, the base __init__ # gets called. @dataclass(init=False) class C(B): x: int = 10 + c = C() self.assertEqual(c.x, 10) self.assertEqual(c.z, 100) @@ -2341,13 +2544,16 @@ def test_no_init(self): @dataclass(init=False) class C: i: int = 0 + self.assertEqual(C().i, 0) @dataclass(init=False) class C: i: int = 2 + def __init__(self): self.i = 3 + self.assertEqual(C().i, 3) def test_overwriting_init(self): @@ -2357,22 +2563,28 @@ def test_overwriting_init(self): @dataclass class C: x: int + def __init__(self, x): self.x = 2 * x + self.assertEqual(C(3).x, 6) @dataclass(init=True) class C: x: int + def __init__(self, x): self.x = 2 * x + self.assertEqual(C(4).x, 8) @dataclass(init=False) class C: x: int + def __init__(self, x): self.x = 2 * x + self.assertEqual(C(5).x, 10) def test_inherit_from_protocol(self): @@ -2407,39 +2619,46 @@ class C(B): y: int = 10 o = C(4) - self.assertEqual(repr(o), 'TestRepr.test_repr..C(x=4, y=10)') + self.assertEqual(repr(o), "TestRepr.test_repr..C(x=4, y=10)") @dataclass class D(C): x: int = 20 - self.assertEqual(repr(D()), 'TestRepr.test_repr..D(x=20, y=10)') + + self.assertEqual(repr(D()), "TestRepr.test_repr..D(x=20, y=10)") @dataclass class C: @dataclass class D: i: int + @dataclass class E: pass - self.assertEqual(repr(C.D(0)), 'TestRepr.test_repr..C.D(i=0)') - self.assertEqual(repr(C.E()), 'TestRepr.test_repr..C.E()') + + self.assertEqual(repr(C.D(0)), "TestRepr.test_repr..C.D(i=0)") + self.assertEqual(repr(C.E()), "TestRepr.test_repr..C.E()") def test_no_repr(self): # Test a class with no __repr__ and repr=False. @dataclass(repr=False) class C: x: int - self.assertIn(f'{__name__}.TestRepr.test_no_repr..C object at', - repr(C(3))) + + self.assertIn( + f"{__name__}.TestRepr.test_no_repr..C object at", repr(C(3)) + ) # Test a class with a __repr__ and repr=False. @dataclass(repr=False) class C: x: int + def __repr__(self): - return 'C-class' - self.assertEqual(repr(C(3)), 'C-class') + return "C-class" + + self.assertEqual(repr(C(3)), "C-class") def test_overwriting_repr(self): # If the class has __repr__, use it no matter the value of @@ -2448,23 +2667,29 @@ def test_overwriting_repr(self): @dataclass class C: x: int + def __repr__(self): - return 'x' - self.assertEqual(repr(C(0)), 'x') + return "x" + + self.assertEqual(repr(C(0)), "x") @dataclass(repr=True) class C: x: int + def __repr__(self): - return 'x' - self.assertEqual(repr(C(0)), 'x') + return "x" + + self.assertEqual(repr(C(0)), "x") @dataclass(repr=False) class C: x: int + def __repr__(self): - return 'x' - self.assertEqual(repr(C(0)), 'x') + return "x" + + self.assertEqual(repr(C(0)), "x") class TestEq(unittest.TestCase): @@ -2473,6 +2698,7 @@ def test_no_eq(self): @dataclass(eq=False) class C: x: int + self.assertNotEqual(C(0), C(0)) c = C(3) self.assertEqual(c, c) @@ -2481,8 +2707,10 @@ class C: @dataclass(eq=False) class C: x: int + def __eq__(self, other): return other == 10 + self.assertEqual(C(3), 10) def test_overwriting_eq(self): @@ -2492,24 +2720,30 @@ def test_overwriting_eq(self): @dataclass class C: x: int + def __eq__(self, other): return other == 3 + self.assertEqual(C(1), 3) self.assertNotEqual(C(1), 1) @dataclass(eq=True) class C: x: int + def __eq__(self, other): return other == 4 + self.assertEqual(C(1), 4) self.assertNotEqual(C(1), 1) @dataclass(eq=False) class C: x: int + def __eq__(self, other): return other == 5 + self.assertEqual(C(1), 5) self.assertNotEqual(C(1), 1) @@ -2521,6 +2755,7 @@ def test_functools_total_ordering(self): @dataclass class C: x: int + def __lt__(self, other): # Perform the test "backward", just to make # sure this is being called. @@ -2536,67 +2771,84 @@ def test_no_order(self): @dataclass(order=False) class C: x: int + # Make sure no order methods are added. - self.assertNotIn('__le__', C.__dict__) - self.assertNotIn('__lt__', C.__dict__) - self.assertNotIn('__ge__', C.__dict__) - self.assertNotIn('__gt__', C.__dict__) + self.assertNotIn("__le__", C.__dict__) + self.assertNotIn("__lt__", C.__dict__) + self.assertNotIn("__ge__", C.__dict__) + self.assertNotIn("__gt__", C.__dict__) # Test that __lt__ is still called @dataclass(order=False) class C: x: int + def __lt__(self, other): return False + # Make sure other methods aren't added. - self.assertNotIn('__le__', C.__dict__) - self.assertNotIn('__ge__', C.__dict__) - self.assertNotIn('__gt__', C.__dict__) + self.assertNotIn("__le__", C.__dict__) + self.assertNotIn("__ge__", C.__dict__) + self.assertNotIn("__gt__", C.__dict__) def test_overwriting_order(self): - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __lt__' - '.*using functools.total_ordering'): + with self.assertRaisesRegex( + TypeError, + "Cannot overwrite attribute __lt__" ".*using functools.total_ordering", + ): + @dataclass(order=True) class C: x: int + def __lt__(self): pass - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __le__' - '.*using functools.total_ordering'): + with self.assertRaisesRegex( + TypeError, + "Cannot overwrite attribute __le__" ".*using functools.total_ordering", + ): + @dataclass(order=True) class C: x: int + def __le__(self): pass - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __gt__' - '.*using functools.total_ordering'): + with self.assertRaisesRegex( + TypeError, + "Cannot overwrite attribute __gt__" ".*using functools.total_ordering", + ): + @dataclass(order=True) class C: x: int + def __gt__(self): pass - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __ge__' - '.*using functools.total_ordering'): + with self.assertRaisesRegex( + TypeError, + "Cannot overwrite attribute __ge__" ".*using functools.total_ordering", + ): + @dataclass(order=True) class C: x: int + def __ge__(self): pass + class TestHash(unittest.TestCase): def test_unsafe_hash(self): @dataclass(unsafe_hash=True) class C: x: int y: str - self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo'))) + + self.assertEqual(hash(C(1, "foo")), hash((1, "foo"))) def test_hash_rules(self): def non_bool(value): @@ -2608,47 +2860,51 @@ def non_bool(value): return 0 def test(case, unsafe_hash, eq, frozen, with_hash, result): - with self.subTest(case=case, unsafe_hash=unsafe_hash, eq=eq, - frozen=frozen): - if result != 'exception': + with self.subTest(case=case, unsafe_hash=unsafe_hash, eq=eq, frozen=frozen): + if result != "exception": if with_hash: + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) class C: def __hash__(self): return 0 else: + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) class C: pass # See if the result matches what's expected. - if result == 'fn': + if result == "fn": # __hash__ contains the function we generated. - self.assertIn('__hash__', C.__dict__) - self.assertIsNotNone(C.__dict__['__hash__']) + self.assertIn("__hash__", C.__dict__) + self.assertIsNotNone(C.__dict__["__hash__"]) - elif result == '': + elif result == "": # __hash__ is not present in our class. if not with_hash: - self.assertNotIn('__hash__', C.__dict__) + self.assertNotIn("__hash__", C.__dict__) - elif result == 'none': + elif result == "none": # __hash__ is set to None. - self.assertIn('__hash__', C.__dict__) - self.assertIsNone(C.__dict__['__hash__']) + self.assertIn("__hash__", C.__dict__) + self.assertIsNone(C.__dict__["__hash__"]) - elif result == 'exception': + elif result == "exception": # Creating the class should cause an exception. # This only happens with with_hash==True. - assert(with_hash) - with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'): + assert with_hash + with self.assertRaisesRegex( + TypeError, "Cannot overwrite attribute __hash__" + ): + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) class C: def __hash__(self): return 0 else: - assert False, f'unknown result {result!r}' + assert False, f"unknown result {result!r}" # There are 8 cases of: # unsafe_hash=True/False @@ -2656,25 +2912,47 @@ def __hash__(self): # frozen=True/False # And for each of these, a different result if # __hash__ is defined or not. - for case, (unsafe_hash, eq, frozen, res_no_defined_hash, res_defined_hash) in enumerate([ - (False, False, False, '', ''), - (False, False, True, '', ''), - (False, True, False, 'none', ''), - (False, True, True, 'fn', ''), - (True, False, False, 'fn', 'exception'), - (True, False, True, 'fn', 'exception'), - (True, True, False, 'fn', 'exception'), - (True, True, True, 'fn', 'exception'), - ], 1): + for case, ( + unsafe_hash, + eq, + frozen, + res_no_defined_hash, + res_defined_hash, + ) in enumerate( + [ + (False, False, False, "", ""), + (False, False, True, "", ""), + (False, True, False, "none", ""), + (False, True, True, "fn", ""), + (True, False, False, "fn", "exception"), + (True, False, True, "fn", "exception"), + (True, True, False, "fn", "exception"), + (True, True, True, "fn", "exception"), + ], + 1, + ): test(case, unsafe_hash, eq, frozen, False, res_no_defined_hash) - test(case, unsafe_hash, eq, frozen, True, res_defined_hash) + test(case, unsafe_hash, eq, frozen, True, res_defined_hash) # Test non-bool truth values, too. This is just to # make sure the data-driven table in the decorator # handles non-bool values. - test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), False, res_no_defined_hash) - test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), True, res_defined_hash) - + test( + case, + non_bool(unsafe_hash), + non_bool(eq), + non_bool(frozen), + False, + res_no_defined_hash, + ) + test( + case, + non_bool(unsafe_hash), + non_bool(eq), + non_bool(frozen), + True, + res_defined_hash, + ) def test_eq_only(self): # If a class defines __eq__, __hash__ is automatically added @@ -2685,8 +2963,10 @@ def test_eq_only(self): @dataclass class C: i: int + def __eq__(self, other): return self.i == other.i + self.assertEqual(C(1), C(1)) self.assertNotEqual(C(1), C(4)) @@ -2695,8 +2975,10 @@ def __eq__(self, other): @dataclass(unsafe_hash=True) class C: i: int + def __eq__(self, other): return self.i == other.i + self.assertEqual(C(1), C(1.0)) self.assertEqual(hash(C(1)), hash(C(1.0))) @@ -2705,8 +2987,10 @@ def __eq__(self, other): @dataclass(unsafe_hash=True, eq=True) class C: i: int + def __eq__(self, other): return self.i == 3 and self.i == other.i + self.assertEqual(C(3), C(3)) self.assertNotEqual(C(1), C(1)) self.assertEqual(hash(C(1)), hash(C(1.0))) @@ -2715,23 +2999,27 @@ def test_0_field_hash(self): @dataclass(frozen=True) class C: pass + self.assertEqual(hash(C()), hash(())) @dataclass(unsafe_hash=True) class C: pass + self.assertEqual(hash(C()), hash(())) def test_1_field_hash(self): @dataclass(frozen=True) class C: x: int + self.assertEqual(hash(C(4)), hash((4,))) self.assertEqual(hash(C(42)), hash((42,))) @dataclass(unsafe_hash=True) class C: x: int + self.assertEqual(hash(C(4)), hash((4,))) self.assertEqual(hash(C(42)), hash((42,))) @@ -2747,67 +3035,70 @@ def __hash__(self): # If frozen or eq is None, then use the default value (do not # specify any value in the decorator). - for frozen, eq, base, expected in [ - (None, None, object, 'unhashable'), - (None, None, Base, 'unhashable'), - (None, False, object, 'object'), - (None, False, Base, 'base'), - (None, True, object, 'unhashable'), - (None, True, Base, 'unhashable'), - (False, None, object, 'unhashable'), - (False, None, Base, 'unhashable'), - (False, False, object, 'object'), - (False, False, Base, 'base'), - (False, True, object, 'unhashable'), - (False, True, Base, 'unhashable'), - (True, None, object, 'tuple'), - (True, None, Base, 'tuple'), - (True, False, object, 'object'), - (True, False, Base, 'base'), - (True, True, object, 'tuple'), - (True, True, Base, 'tuple'), - ]: - + for frozen, eq, base, expected in [ + (None, None, object, "unhashable"), + (None, None, Base, "unhashable"), + (None, False, object, "object"), + (None, False, Base, "base"), + (None, True, object, "unhashable"), + (None, True, Base, "unhashable"), + (False, None, object, "unhashable"), + (False, None, Base, "unhashable"), + (False, False, object, "object"), + (False, False, Base, "base"), + (False, True, object, "unhashable"), + (False, True, Base, "unhashable"), + (True, None, object, "tuple"), + (True, None, Base, "tuple"), + (True, False, object, "object"), + (True, False, Base, "base"), + (True, True, object, "tuple"), + (True, True, Base, "tuple"), + ]: with self.subTest(frozen=frozen, eq=eq, base=base, expected=expected): # First, create the class. if frozen is None and eq is None: + @dataclass class C(base): i: int elif frozen is None: + @dataclass(eq=eq) class C(base): i: int elif eq is None: + @dataclass(frozen=frozen) class C(base): i: int else: + @dataclass(frozen=frozen, eq=eq) class C(base): i: int # Now, make sure it hashes as expected. - if expected == 'unhashable': + if expected == "unhashable": c = C(10) - with self.assertRaisesRegex(TypeError, 'unhashable type'): + with self.assertRaisesRegex(TypeError, "unhashable type"): hash(c) - elif expected == 'base': + elif expected == "base": self.assertEqual(hash(C(10)), 301) - elif expected == 'object': + elif expected == "object": # I'm not sure what test to use here. object's # hash isn't based on id(), so calling hash() # won't tell us much. So, just check the # function used is object's. self.assertIs(C.__hash__, object.__hash__) - elif expected == 'tuple': + elif expected == "tuple": self.assertEqual(hash(C(42)), hash((42,))) else: - assert False, f'unknown value for expected={expected!r}' + assert False, f"unknown value for expected={expected!r}" class TestFrozen(unittest.TestCase): @@ -2828,10 +3119,10 @@ class C: pass c = C() - self.assertFalse(hasattr(c, 'i')) + self.assertFalse(hasattr(c, "i")) with self.assertRaises(FrozenInstanceError): c.i = 5 - self.assertFalse(hasattr(c, 'i')) + self.assertFalse(hasattr(c, "i")) with self.assertRaises(FrozenInstanceError): del c.i @@ -2857,8 +3148,10 @@ def test_inherit_nonfrozen_from_empty_frozen(self): class C: pass - with self.assertRaisesRegex(TypeError, - 'cannot inherit non-frozen dataclass from a frozen one'): + with self.assertRaisesRegex( + TypeError, "cannot inherit non-frozen dataclass from a frozen one" + ): + @dataclass class D(C): j: int @@ -2884,8 +3177,9 @@ class NotDataclass: with self.subTest(bases=bases): with self.assertRaisesRegex( TypeError, - 'cannot inherit non-frozen dataclass from a frozen one', + "cannot inherit non-frozen dataclass from a frozen one", ): + @dataclass class NotFrozenChild(*bases): pass @@ -2899,8 +3193,9 @@ class NotFrozenChild(*bases): with self.subTest(bases=bases): with self.assertRaisesRegex( TypeError, - 'cannot inherit frozen dataclass from a non-frozen one', + "cannot inherit frozen dataclass from a non-frozen one", ): + @dataclass(frozen=True) class FrozenChild(*bases): pass @@ -2915,20 +3210,24 @@ class NotDataclass: class C1(Frozen, NotDataclass): pass + self.assertEqual(C1.__mro__, (C1, Frozen, NotDataclass, object)) class C2(NotDataclass, Frozen): pass + self.assertEqual(C2.__mro__, (C2, NotDataclass, Frozen, object)) @dataclass(frozen=True) class C3(Frozen, NotDataclass): pass + self.assertEqual(C3.__mro__, (C3, Frozen, NotDataclass, object)) @dataclass(frozen=True) class C4(NotDataclass, Frozen): pass + self.assertEqual(C4.__mro__, (C4, NotDataclass, Frozen, object)) def test_multiple_frozen_dataclasses_inheritance(self): @@ -2942,20 +3241,24 @@ class FrozenB: class C1(FrozenA, FrozenB): pass + self.assertEqual(C1.__mro__, (C1, FrozenA, FrozenB, object)) class C2(FrozenB, FrozenA): pass + self.assertEqual(C2.__mro__, (C2, FrozenB, FrozenA, object)) @dataclass(frozen=True) class C3(FrozenA, FrozenB): pass + self.assertEqual(C3.__mro__, (C3, FrozenA, FrozenB, object)) @dataclass(frozen=True) class C4(FrozenB, FrozenA): pass + self.assertEqual(C4.__mro__, (C4, FrozenB, FrozenA, object)) def test_inherit_nonfrozen_from_empty(self): @@ -2976,17 +3279,22 @@ class D(C): def test_inherit_nonfrozen_from_frozen(self): for intermediate_class in [True, False]: with self.subTest(intermediate_class=intermediate_class): + @dataclass(frozen=True) class C: i: int if intermediate_class: - class I(C): pass + + class I(C): + pass else: I = C - with self.assertRaisesRegex(TypeError, - 'cannot inherit non-frozen dataclass from a frozen one'): + with self.assertRaisesRegex( + TypeError, "cannot inherit non-frozen dataclass from a frozen one" + ): + @dataclass class D(I): pass @@ -2994,17 +3302,22 @@ class D(I): def test_inherit_frozen_from_nonfrozen(self): for intermediate_class in [True, False]: with self.subTest(intermediate_class=intermediate_class): + @dataclass class C: i: int if intermediate_class: - class I(C): pass + + class I(C): + pass else: I = C - with self.assertRaisesRegex(TypeError, - 'cannot inherit frozen dataclass from a non-frozen one'): + with self.assertRaisesRegex( + TypeError, "cannot inherit frozen dataclass from a non-frozen one" + ): + @dataclass(frozen=True) class D(I): pass @@ -3012,11 +3325,14 @@ class D(I): def test_inherit_from_normal_class(self): for intermediate_class in [True, False]: with self.subTest(intermediate_class=intermediate_class): + class C: pass if intermediate_class: - class I(C): pass + + class I(C): + pass else: I = C @@ -3060,7 +3376,7 @@ class S(D): del s.y self.assertEqual(s.y, 10) del s.cached - self.assertFalse(hasattr(s, 'cached')) + self.assertFalse(hasattr(s, "cached")) with self.assertRaises(AttributeError) as cm: del s.cached self.assertNotIsInstance(cm.exception, FrozenInstanceError) @@ -3074,39 +3390,47 @@ class S(D): pass s = S() - self.assertFalse(hasattr(s, 'x')) + self.assertFalse(hasattr(s, "x")) s.x = 5 self.assertEqual(s.x, 5) del s.x - self.assertFalse(hasattr(s, 'x')) + self.assertFalse(hasattr(s, "x")) with self.assertRaises(AttributeError) as cm: del s.x self.assertNotIsInstance(cm.exception, FrozenInstanceError) def test_overwriting_frozen(self): # frozen uses __setattr__ and __delattr__. - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __setattr__'): + with self.assertRaisesRegex( + TypeError, "Cannot overwrite attribute __setattr__" + ): + @dataclass(frozen=True) class C: x: int + def __setattr__(self): pass - with self.assertRaisesRegex(TypeError, - 'Cannot overwrite attribute __delattr__'): + with self.assertRaisesRegex( + TypeError, "Cannot overwrite attribute __delattr__" + ): + @dataclass(frozen=True) class C: x: int + def __delattr__(self): pass @dataclass(frozen=False) class C: x: int + def __setattr__(self, name, value): - self.__dict__['x'] = value * 2 + self.__dict__["x"] = value * 2 + self.assertEqual(C(10).x, 20) def test_frozen_hash(self): @@ -3119,7 +3443,7 @@ class C: hash(C(3)) # If x is mutable, computing the hash is an error. - with self.assertRaisesRegex(TypeError, 'unhashable type'): + with self.assertRaisesRegex(TypeError, "unhashable type"): hash(C({})) @@ -3127,14 +3451,15 @@ class TestSlots(unittest.TestCase): def test_simple(self): @dataclass class C: - __slots__ = ('x',) + __slots__ = ("x",) x: Any # There was a bug where a variable in a slot was assumed to # also have a default value (of type # types.MemberDescriptorType). - with self.assertRaisesRegex(TypeError, - r"__init__\(\) missing 1 required positional argument: 'x'"): + with self.assertRaisesRegex( + TypeError, r"__init__\(\) missing 1 required positional argument: 'x'" + ): C() # We can create an instance, and assign to x. @@ -3151,7 +3476,7 @@ def test_derived_added_field(self): # See bpo-33100. @dataclass class Base: - __slots__ = ('x',) + __slots__ = ("x",) x: Any @dataclass @@ -3182,25 +3507,25 @@ class C: c.z = 5 def test_add_slots_when_slots_exists(self): - with self.assertRaisesRegex(TypeError, '^C already specifies __slots__$'): + with self.assertRaisesRegex(TypeError, "^C already specifies __slots__$"): + @dataclass(slots=True) class C: - __slots__ = ('x',) + __slots__ = ("x",) x: int def test_generated_slots_value(self): - class Root: - __slots__ = {'x'} + __slots__ = {"x"} class Root2(Root): - __slots__ = {'k': '...', 'j': ''} + __slots__ = {"k": "...", "j": ""} class Root3(Root2): - __slots__ = ['h'] + __slots__ = ["h"] class Root4(Root3): - __slots__ = 'aa' + __slots__ = "aa" @dataclass(slots=True) class Base(Root4): @@ -3208,7 +3533,7 @@ class Base(Root4): j: str h: str - self.assertEqual(Base.__slots__, ('y', )) + self.assertEqual(Base.__slots__, ("y",)) @dataclass(slots=True) class Derived(Base): @@ -3218,26 +3543,23 @@ class Derived(Base): k: str h: str - self.assertEqual(Derived.__slots__, ('z', )) + self.assertEqual(Derived.__slots__, ("z",)) @dataclass class AnotherDerived(Base): z: int - self.assertNotIn('__slots__', AnotherDerived.__dict__) + self.assertNotIn("__slots__", AnotherDerived.__dict__) def test_cant_inherit_from_iterator_slots(self): - class Root: - __slots__ = iter(['a']) + __slots__ = iter(["a"]) class Root2(Root): - __slots__ = ('b', ) + __slots__ = ("b",) + + with self.assertRaisesRegex(TypeError, "^Slots of 'Root' cannot be determined"): - with self.assertRaisesRegex( - TypeError, - "^Slots of 'Root' cannot be determined" - ): @dataclass(slots=True) class C(Root2): x: int @@ -3287,7 +3609,7 @@ class FrozenSlotsGetStateClass: getstate_called: bool = field(default=False, compare=False) def __getstate__(self): - object.__setattr__(self, 'getstate_called', True) + object.__setattr__(self, "getstate_called", True) return [self.foo, self.bar] @dataclass(frozen=True, slots=True) @@ -3298,9 +3620,9 @@ class FrozenSlotsSetStateClass: setstate_called: bool = field(default=False, compare=False) def __setstate__(self, state): - object.__setattr__(self, 'setstate_called', True) - object.__setattr__(self, 'foo', state[0]) - object.__setattr__(self, 'bar', state[1]) + object.__setattr__(self, "setstate_called", True) + object.__setattr__(self, "foo", state[0]) + object.__setattr__(self, "bar", state[1]) @dataclass(frozen=True, slots=True) class FrozenSlotsAllStateClass: @@ -3311,18 +3633,18 @@ class FrozenSlotsAllStateClass: setstate_called: bool = field(default=False, compare=False) def __getstate__(self): - object.__setattr__(self, 'getstate_called', True) + object.__setattr__(self, "getstate_called", True) return [self.foo, self.bar] def __setstate__(self, state): - object.__setattr__(self, 'setstate_called', True) - object.__setattr__(self, 'foo', state[0]) - object.__setattr__(self, 'bar', state[1]) + object.__setattr__(self, "setstate_called", True) + object.__setattr__(self, "foo", state[0]) + object.__setattr__(self, "bar", state[1]) def test_frozen_slots_pickle_custom_state(self): for proto in range(pickle.HIGHEST_PROTOCOL + 1): with self.subTest(proto=proto): - obj = self.FrozenSlotsGetStateClass('a', 1) + obj = self.FrozenSlotsGetStateClass("a", 1) dumped = pickle.dumps(obj, protocol=proto) self.assertTrue(obj.getstate_called) @@ -3330,7 +3652,7 @@ def test_frozen_slots_pickle_custom_state(self): for proto in range(pickle.HIGHEST_PROTOCOL + 1): with self.subTest(proto=proto): - obj = self.FrozenSlotsSetStateClass('a', 1) + obj = self.FrozenSlotsSetStateClass("a", 1) obj2 = pickle.loads(pickle.dumps(obj, protocol=proto)) self.assertTrue(obj2.setstate_called) @@ -3338,7 +3660,7 @@ def test_frozen_slots_pickle_custom_state(self): for proto in range(pickle.HIGHEST_PROTOCOL + 1): with self.subTest(proto=proto): - obj = self.FrozenSlotsAllStateClass('a', 1) + obj = self.FrozenSlotsAllStateClass("a", 1) dumped = pickle.dumps(obj, protocol=proto) self.assertTrue(obj.getstate_called) @@ -3352,22 +3674,22 @@ def test_slots_with_default_no_init(self): @dataclass(slots=True) class A: a: str - b: str = field(default='b', init=False) + b: str = field(default="b", init=False) obj = A("a") - self.assertEqual(obj.a, 'a') - self.assertEqual(obj.b, 'b') + self.assertEqual(obj.a, "a") + self.assertEqual(obj.b, "b") def test_slots_with_default_factory_no_init(self): # Originally reported in bpo-44649. @dataclass(slots=True) class A: a: str - b: str = field(default_factory=lambda:'b', init=False) + b: str = field(default_factory=lambda: "b", init=False) obj = A("a") - self.assertEqual(obj.a, 'a') - self.assertEqual(obj.b, 'b') + self.assertEqual(obj.a, "a") + self.assertEqual(obj.b, "b") def test_slots_no_weakref(self): @dataclass(slots=True) @@ -3377,8 +3699,7 @@ class A: self.assertNotIn("__weakref__", A.__slots__) a = A() - with self.assertRaisesRegex(TypeError, - "cannot create weak reference"): + with self.assertRaisesRegex(TypeError, "cannot create weak reference"): weakref.ref(a) with self.assertRaises(AttributeError): a.__weakref__ @@ -3396,7 +3717,7 @@ class A: def test_slots_weakref_base_str(self): class Base: - __slots__ = '__weakref__' + __slots__ = "__weakref__" @dataclass(slots=True) class A(Base): @@ -3412,7 +3733,7 @@ def test_slots_weakref_base_tuple(self): # Same as test_slots_weakref_base, but use a tuple instead of a string # in the base class. class Base: - __slots__ = ('__weakref__',) + __slots__ = ("__weakref__",) @dataclass(slots=True) class A(Base): @@ -3426,22 +3747,38 @@ class A(Base): weakref.ref(a) def test_weakref_slot_without_slot(self): - with self.assertRaisesRegex(TypeError, - "weakref_slot is True but slots is False"): + with self.assertRaisesRegex( + TypeError, "weakref_slot is True but slots is False" + ): + @dataclass(weakref_slot=True) class A: a: int def test_weakref_slot_make_dataclass(self): - A = make_dataclass('A', [('a', int),], slots=True, weakref_slot=True) + A = make_dataclass( + "A", + [ + ("a", int), + ], + slots=True, + weakref_slot=True, + ) self.assertIn("__weakref__", A.__slots__) a = A(1) weakref.ref(a) # And make sure if raises if slots=True is not given. - with self.assertRaisesRegex(TypeError, - "weakref_slot is True but slots is False"): - B = make_dataclass('B', [('a', int),], weakref_slot=True) + with self.assertRaisesRegex( + TypeError, "weakref_slot is True but slots is False" + ): + B = make_dataclass( + "B", + [ + ("a", int), + ], + weakref_slot=True, + ) def test_weakref_slot_subclass_weakref_slot(self): @dataclass(slots=True, weakref_slot=True) @@ -3480,7 +3817,7 @@ class A(Base): def test_weakref_slot_normal_base_weakref_slot(self): class Base: - __slots__ = ('__weakref__',) + __slots__ = ("__weakref__",) @dataclass(slots=True, weakref_slot=True) class A(Base): @@ -3502,7 +3839,8 @@ def test_set_name(self): # Create a descriptor. class D: def __set_name__(self, owner, name): - self.name = name + 'x' + self.name = name + "x" + def __get__(self, instance, owner): if instance is not None: return 1 @@ -3512,16 +3850,18 @@ def __get__(self, instance, owner): # dataclass code is involved in initializing the descriptor. @dataclass class C: - c: int=D() - self.assertEqual(C.c.name, 'cx') + c: int = D() + + self.assertEqual(C.c.name, "cx") # Now test with a default value and init=False, which is the # only time this is really meaningful. If not using # init=False, then the descriptor will be overwritten, anyway. @dataclass class C: - c: int=field(default=D(), init=False) - self.assertEqual(C.c.name, 'cx') + c: int = field(default=D(), init=False) + + self.assertEqual(C.c.name, "cx") self.assertEqual(C().c, 1) def test_non_descriptor(self): @@ -3530,12 +3870,13 @@ def test_non_descriptor(self): class D: def __set_name__(self, owner, name): - self.name = name + 'x' + self.name = name + "x" @dataclass class C: - c: int=field(default=D(), init=False) - self.assertEqual(C.c.name, 'cx') + c: int = field(default=D(), init=False) + + self.assertEqual(C.c.name, "cx") def test_lookup_on_instance(self): # See bpo-33175. @@ -3549,7 +3890,7 @@ class D: # Make sure d.__set_name__ is not called. @dataclass class C: - i: int=field(default=d, init=False) + i: int = field(default=d, init=False) self.assertEqual(d.__set_name__.call_count, 0) @@ -3557,12 +3898,13 @@ def test_lookup_on_class(self): # See bpo-33175. class D: pass + D.__set_name__ = Mock() # Make sure D.__set_name__ is called. @dataclass class C: - i: int=field(default=D(), init=False) + i: int = field(default=D(), init=False) self.assertEqual(D.__set_name__.call_count, 1) @@ -3673,9 +4015,12 @@ def __set__(self, instance: Any, value: int) -> None: class C: i: D = D() - with self.assertRaisesRegex(TypeError, 'missing 1 required positional argument'): + with self.assertRaisesRegex( + TypeError, "missing 1 required positional argument" + ): c = C() + class TestStringAnnotations(unittest.TestCase): def test_classvar(self): # Some expressions recognized as ClassVar really aren't. But @@ -3683,25 +4028,26 @@ def test_classvar(self): # science. # These tests assume that both "import typing" and "from # typing import *" have been run in this file. - for typestr in ('ClassVar[int]', - 'ClassVar [int]', - ' ClassVar [int]', - 'ClassVar', - ' ClassVar ', - 'typing.ClassVar[int]', - 'typing.ClassVar[str]', - ' typing.ClassVar[str]', - 'typing .ClassVar[str]', - 'typing. ClassVar[str]', - 'typing.ClassVar [str]', - 'typing.ClassVar [ str]', - - # Not syntactically valid, but these will - # be treated as ClassVars. - 'typing.ClassVar.[int]', - 'typing.ClassVar+', - ): + for typestr in ( + "ClassVar[int]", + "ClassVar [int]", + " ClassVar [int]", + "ClassVar", + " ClassVar ", + "typing.ClassVar[int]", + "typing.ClassVar[str]", + " typing.ClassVar[str]", + "typing .ClassVar[str]", + "typing. ClassVar[str]", + "typing.ClassVar [str]", + "typing.ClassVar [ str]", + # Not syntactically valid, but these will + # be treated as ClassVars. + "typing.ClassVar.[int]", + "typing.ClassVar+", + ): with self.subTest(typestr=typestr): + @dataclass class C: x: typestr @@ -3711,21 +4057,23 @@ class C: # And it won't appear in the class's dict because it doesn't # have a default. - self.assertNotIn('x', C.__dict__) + self.assertNotIn("x", C.__dict__) def test_isnt_classvar(self): - for typestr in ('CV', - 't.ClassVar', - 't.ClassVar[int]', - 'typing..ClassVar[int]', - 'Classvar', - 'Classvar[int]', - 'typing.ClassVarx[int]', - 'typong.ClassVar[int]', - 'dataclasses.ClassVar[int]', - 'typingxClassVar[str]', - ): + for typestr in ( + "CV", + "t.ClassVar", + "t.ClassVar[int]", + "typing..ClassVar[int]", + "Classvar", + "Classvar[int]", + "typing.ClassVarx[int]", + "typong.ClassVar[int]", + "dataclasses.ClassVar[int]", + "typingxClassVar[str]", + ): with self.subTest(typestr=typestr): + @dataclass class C: x: typestr @@ -3736,41 +4084,44 @@ class C: def test_initvar(self): # These tests assume that both "import dataclasses" and "from # dataclasses import *" have been run in this file. - for typestr in ('InitVar[int]', - 'InitVar [int]' - ' InitVar [int]', - 'InitVar', - ' InitVar ', - 'dataclasses.InitVar[int]', - 'dataclasses.InitVar[str]', - ' dataclasses.InitVar[str]', - 'dataclasses .InitVar[str]', - 'dataclasses. InitVar[str]', - 'dataclasses.InitVar [str]', - 'dataclasses.InitVar [ str]', - - # Not syntactically valid, but these will - # be treated as InitVars. - 'dataclasses.InitVar.[int]', - 'dataclasses.InitVar+', - ): + for typestr in ( + "InitVar[int]", + "InitVar [int]" " InitVar [int]", + "InitVar", + " InitVar ", + "dataclasses.InitVar[int]", + "dataclasses.InitVar[str]", + " dataclasses.InitVar[str]", + "dataclasses .InitVar[str]", + "dataclasses. InitVar[str]", + "dataclasses.InitVar [str]", + "dataclasses.InitVar [ str]", + # Not syntactically valid, but these will + # be treated as InitVars. + "dataclasses.InitVar.[int]", + "dataclasses.InitVar+", + ): with self.subTest(typestr=typestr): + @dataclass class C: x: typestr # x is an InitVar, so doesn't create a member. - with self.assertRaisesRegex(AttributeError, - "object has no attribute 'x'"): + with self.assertRaisesRegex( + AttributeError, "object has no attribute 'x'" + ): C(1).x def test_isnt_initvar(self): - for typestr in ('IV', - 'dc.InitVar', - 'xdataclasses.xInitVar', - 'typing.xInitVar[int]', - ): + for typestr in ( + "IV", + "dc.InitVar", + "xdataclasses.xInitVar", + "typing.xInitVar[int]", + ): with self.subTest(typestr=typestr): + @dataclass class C: x: typestr @@ -3784,9 +4135,12 @@ def test_classvar_module_level_import(self): from test.test_dataclasses import dataclass_module_2 from test.test_dataclasses import dataclass_module_2_str - for m in (dataclass_module_1, dataclass_module_1_str, - dataclass_module_2, dataclass_module_2_str, - ): + for m in ( + dataclass_module_1, + dataclass_module_1_str, + dataclass_module_2, + dataclass_module_2_str, + ): with self.subTest(m=m): # There's a difference in how the ClassVars are # interpreted when using string annotations or @@ -3797,77 +4151,78 @@ def test_classvar_module_level_import(self): c = m.CV() self.assertEqual(c.cv0, 20) - # There's a difference in how the InitVars are # interpreted when using string annotations or # not. See the imported modules for details. c = m.IV(0, 1, 2, 3, 4) - for field_name in ('iv0', 'iv1', 'iv2', 'iv3'): + for field_name in ("iv0", "iv1", "iv2", "iv3"): with self.subTest(field_name=field_name): - with self.assertRaisesRegex(AttributeError, f"object has no attribute '{field_name}'"): + with self.assertRaisesRegex( + AttributeError, f"object has no attribute '{field_name}'" + ): # Since field_name is an InitVar, it's # not an instance field. getattr(c, field_name) if m.USING_STRINGS: # iv4 is interpreted as a normal field. - self.assertIn('not_iv4', c.__dict__) + self.assertIn("not_iv4", c.__dict__) self.assertEqual(c.not_iv4, 4) else: # iv4 is interpreted as an InitVar, so it # won't exist on the instance. - self.assertNotIn('not_iv4', c.__dict__) + self.assertNotIn("not_iv4", c.__dict__) def test_text_annotations(self): from test.test_dataclasses import dataclass_textanno self.assertEqual( - get_type_hints(dataclass_textanno.Bar), - {'foo': dataclass_textanno.Foo}) + get_type_hints(dataclass_textanno.Bar), {"foo": dataclass_textanno.Foo} + ) self.assertEqual( get_type_hints(dataclass_textanno.Bar.__init__), - {'foo': dataclass_textanno.Foo, - 'return': type(None)}) + {"foo": dataclass_textanno.Foo, "return": type(None)}, + ) + +ByMakeDataClass = make_dataclass("ByMakeDataClass", [("x", int)]) +ManualModuleMakeDataClass = make_dataclass( + "ManualModuleMakeDataClass", [("x", int)], module=__name__ +) +WrongNameMakeDataclass = make_dataclass("Wrong", [("x", int)]) +WrongModuleMakeDataclass = make_dataclass( + "WrongModuleMakeDataclass", [("x", int)], module="custom" +) -ByMakeDataClass = make_dataclass('ByMakeDataClass', [('x', int)]) -ManualModuleMakeDataClass = make_dataclass('ManualModuleMakeDataClass', - [('x', int)], - module=__name__) -WrongNameMakeDataclass = make_dataclass('Wrong', [('x', int)]) -WrongModuleMakeDataclass = make_dataclass('WrongModuleMakeDataclass', - [('x', int)], - module='custom') class TestMakeDataclass(unittest.TestCase): def test_simple(self): - C = make_dataclass('C', - [('x', int), - ('y', int, field(default=5))], - namespace={'add_one': lambda self: self.x + 1}) + C = make_dataclass( + "C", + [("x", int), ("y", int, field(default=5))], + namespace={"add_one": lambda self: self.x + 1}, + ) c = C(10) self.assertEqual((c.x, c.y), (10, 5)) self.assertEqual(c.add_one(), 11) - def test_no_mutate_namespace(self): # Make sure a provided namespace isn't mutated. ns = {} - C = make_dataclass('C', - [('x', int), - ('y', int, field(default=5))], - namespace=ns) + C = make_dataclass( + "C", [("x", int), ("y", int, field(default=5))], namespace=ns + ) self.assertEqual(ns, {}) def test_base(self): class Base1: pass + class Base2: pass - C = make_dataclass('C', - [('x', int)], - bases=(Base1, Base2)) + + C = make_dataclass("C", [("x", int)], bases=(Base1, Base2)) c = C(2) self.assertIsInstance(c, C) self.assertIsInstance(c, Base1) @@ -3877,12 +4232,12 @@ def test_base_dataclass(self): @dataclass class Base1: x: int + class Base2: pass - C = make_dataclass('C', - [('y', int)], - bases=(Base1, Base2)) - with self.assertRaisesRegex(TypeError, 'required positional'): + + C = make_dataclass("C", [("y", int)], bases=(Base1, Base2)) + with self.assertRaisesRegex(TypeError, "required positional"): c = C(2) c = C(1, 2) self.assertIsInstance(c, C) @@ -3895,65 +4250,71 @@ def test_init_var(self): def post_init(self, y): self.x *= y - C = make_dataclass('C', - [('x', int), - ('y', InitVar[int]), - ], - namespace={'__post_init__': post_init}, - ) + C = make_dataclass( + "C", + [ + ("x", int), + ("y", InitVar[int]), + ], + namespace={"__post_init__": post_init}, + ) c = C(2, 3) - self.assertEqual(vars(c), {'x': 6}) + self.assertEqual(vars(c), {"x": 6}) self.assertEqual(len(fields(c)), 1) def test_class_var(self): - C = make_dataclass('C', - [('x', int), - ('y', ClassVar[int], 10), - ('z', ClassVar[int], field(default=20)), - ]) + C = make_dataclass( + "C", + [ + ("x", int), + ("y", ClassVar[int], 10), + ("z", ClassVar[int], field(default=20)), + ], + ) c = C(1) - self.assertEqual(vars(c), {'x': 1}) + self.assertEqual(vars(c), {"x": 1}) self.assertEqual(len(fields(c)), 1) self.assertEqual(C.y, 10) self.assertEqual(C.z, 20) def test_other_params(self): - C = make_dataclass('C', - [('x', int), - ('y', ClassVar[int], 10), - ('z', ClassVar[int], field(default=20)), - ], - init=False) + C = make_dataclass( + "C", + [ + ("x", int), + ("y", ClassVar[int], 10), + ("z", ClassVar[int], field(default=20)), + ], + init=False, + ) # Make sure we have a repr, but no init. - self.assertNotIn('__init__', vars(C)) - self.assertIn('__repr__', vars(C)) + self.assertNotIn("__init__", vars(C)) + self.assertIn("__repr__", vars(C)) # Make sure random other params don't work. - with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): - C = make_dataclass('C', - [], - xxinit=False) + with self.assertRaisesRegex(TypeError, "unexpected keyword argument"): + C = make_dataclass("C", [], xxinit=False) def test_no_types(self): - C = make_dataclass('Point', ['x', 'y', 'z']) + C = make_dataclass("Point", ["x", "y", "z"]) c = C(1, 2, 3) - self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) - self.assertEqual(C.__annotations__, {'x': 'typing.Any', - 'y': 'typing.Any', - 'z': 'typing.Any'}) + self.assertEqual(vars(c), {"x": 1, "y": 2, "z": 3}) + self.assertEqual( + C.__annotations__, {"x": "typing.Any", "y": "typing.Any", "z": "typing.Any"} + ) - C = make_dataclass('Point', ['x', ('y', int), 'z']) + C = make_dataclass("Point", ["x", ("y", int), "z"]) c = C(1, 2, 3) - self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) - self.assertEqual(C.__annotations__, {'x': 'typing.Any', - 'y': int, - 'z': 'typing.Any'}) + self.assertEqual(vars(c), {"x": 1, "y": 2, "z": 3}) + self.assertEqual( + C.__annotations__, {"x": "typing.Any", "y": int, "z": "typing.Any"} + ) def test_module_attr(self): self.assertEqual(ByMakeDataClass.__module__, __name__) self.assertEqual(ByMakeDataClass(1).__module__, __name__) self.assertEqual(WrongModuleMakeDataclass.__module__, "custom") - Nested = make_dataclass('Nested', []) + Nested = make_dataclass("Nested", []) self.assertEqual(Nested.__module__, __name__) self.assertEqual(Nested().__module__, __name__) @@ -3980,60 +4341,63 @@ def test_cannot_be_pickled(self): pickle.dumps(klass(1), proto) def test_invalid_type_specification(self): - for bad_field in [(), - (1, 2, 3, 4), - ]: + for bad_field in [ + (), + (1, 2, 3, 4), + ]: with self.subTest(bad_field=bad_field): - with self.assertRaisesRegex(TypeError, r'Invalid field: '): - make_dataclass('C', ['a', bad_field]) + with self.assertRaisesRegex(TypeError, r"Invalid field: "): + make_dataclass("C", ["a", bad_field]) # And test for things with no len(). - for bad_field in [float, - lambda x:x, - ]: + for bad_field in [ + float, + lambda x: x, + ]: with self.subTest(bad_field=bad_field): - with self.assertRaisesRegex(TypeError, r'has no len\(\)'): - make_dataclass('C', ['a', bad_field]) + with self.assertRaisesRegex(TypeError, r"has no len\(\)"): + make_dataclass("C", ["a", bad_field]) def test_duplicate_field_names(self): - for field in ['a', 'ab']: + for field in ["a", "ab"]: with self.subTest(field=field): - with self.assertRaisesRegex(TypeError, 'Field name duplicated'): - make_dataclass('C', [field, 'a', field]) + with self.assertRaisesRegex(TypeError, "Field name duplicated"): + make_dataclass("C", [field, "a", field]) def test_keyword_field_names(self): - for field in ['for', 'async', 'await', 'as']: + for field in ["for", "async", "await", "as"]: with self.subTest(field=field): - with self.assertRaisesRegex(TypeError, 'must not be keywords'): - make_dataclass('C', ['a', field]) - with self.assertRaisesRegex(TypeError, 'must not be keywords'): - make_dataclass('C', [field]) - with self.assertRaisesRegex(TypeError, 'must not be keywords'): - make_dataclass('C', [field, 'a']) + with self.assertRaisesRegex(TypeError, "must not be keywords"): + make_dataclass("C", ["a", field]) + with self.assertRaisesRegex(TypeError, "must not be keywords"): + make_dataclass("C", [field]) + with self.assertRaisesRegex(TypeError, "must not be keywords"): + make_dataclass("C", [field, "a"]) def test_non_identifier_field_names(self): - for field in ['()', 'x,y', '*', '2@3', '', 'little johnny tables']: + for field in ["()", "x,y", "*", "2@3", "", "little johnny tables"]: with self.subTest(field=field): - with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): - make_dataclass('C', ['a', field]) - with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): - make_dataclass('C', [field]) - with self.assertRaisesRegex(TypeError, 'must be valid identifiers'): - make_dataclass('C', [field, 'a']) + with self.assertRaisesRegex(TypeError, "must be valid identifiers"): + make_dataclass("C", ["a", field]) + with self.assertRaisesRegex(TypeError, "must be valid identifiers"): + make_dataclass("C", [field]) + with self.assertRaisesRegex(TypeError, "must be valid identifiers"): + make_dataclass("C", [field, "a"]) def test_underscore_field_names(self): # Unlike namedtuple, it's okay if dataclass field names have # an underscore. - make_dataclass('C', ['_', '_a', 'a_a', 'a_']) + make_dataclass("C", ["_", "_a", "a_a", "a_"]) def test_funny_class_names_names(self): # No reason to prevent weird class names, since # types.new_class allows them. - for classname in ['()', 'x,y', '*', '2@3', '']: + for classname in ["()", "x,y", "*", "2@3", ""]: with self.subTest(classname=classname): - C = make_dataclass(classname, ['a', 'b']) + C = make_dataclass(classname, ["a", "b"]) self.assertEqual(C.__name__, classname) + class TestReplace(unittest.TestCase): def test(self): @dataclass(frozen=True) @@ -4059,10 +4423,9 @@ class C: self.assertEqual((c.x, c.y, c.z, c.t), (1, 2, 10, 100)) self.assertEqual((c1.x, c1.y, c1.z, c1.t), (3, 2, 10, 100)) - - with self.assertRaisesRegex(TypeError, 'init=False'): + with self.assertRaisesRegex(TypeError, "init=False"): replace(c, x=3, z=20, t=50) - with self.assertRaisesRegex(TypeError, 'init=False'): + with self.assertRaisesRegex(TypeError, "init=False"): replace(c, z=20) replace(c, x=3, z=20, t=50) @@ -4074,8 +4437,9 @@ class C: # if we're also replacing one that does exist. Test this # here, because setting attributes on frozen instances is # handled slightly differently from non-frozen ones. - with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " - "keyword argument 'a'"): + with self.assertRaisesRegex( + TypeError, r"__init__\(\) got an unexpected " "keyword argument 'a'" + ): c1 = replace(c, x=20, a=5) def test_invalid_field_name(self): @@ -4085,8 +4449,9 @@ class C: y: int c = C(1, 2) - with self.assertRaisesRegex(TypeError, r"__init__\(\) got an unexpected " - "keyword argument 'z'"): + with self.assertRaisesRegex( + TypeError, r"__init__\(\) got an unexpected " "keyword argument 'z'" + ): c1 = replace(c, z=3) def test_invalid_object(self): @@ -4095,10 +4460,10 @@ class C: x: int y: int - with self.assertRaisesRegex(TypeError, 'dataclass instance'): + with self.assertRaisesRegex(TypeError, "dataclass instance"): replace(C, x=3) - with self.assertRaisesRegex(TypeError, 'dataclass instance'): + with self.assertRaisesRegex(TypeError, "dataclass instance"): replace(0, x=3) def test_no_init(self): @@ -4115,10 +4480,10 @@ class C: self.assertEqual((c1.x, c1.y), (5, 10)) # Trying to replace y is an error. - with self.assertRaisesRegex(TypeError, 'init=False'): + with self.assertRaisesRegex(TypeError, "init=False"): replace(c, x=2, y=30) - with self.assertRaisesRegex(TypeError, 'init=False'): + with self.assertRaisesRegex(TypeError, "init=False"): replace(c, y=30) def test_classvar(self): @@ -4134,8 +4499,9 @@ class C: self.assertEqual(c.y, 1000) # Trying to replace y is an error: can't replace ClassVars. - with self.assertRaisesRegex(TypeError, r"__init__\(\) got an " - "unexpected keyword argument 'y'"): + with self.assertRaisesRegex( + TypeError, r"__init__\(\) got an " "unexpected keyword argument 'y'" + ): replace(c, y=30) replace(c, x=5) @@ -4151,8 +4517,9 @@ def __post_init__(self, y): c = C(1, 10) self.assertEqual(c.x, 10) - with self.assertRaisesRegex(TypeError, r"InitVar 'y' must be " - r"specified with replace\(\)"): + with self.assertRaisesRegex( + TypeError, r"InitVar 'y' must be " r"specified with replace\(\)" + ): replace(c, x=3) c = replace(c, x=3, y=5) self.assertEqual(c.x, 15) @@ -4193,8 +4560,10 @@ class C: c = C(None, None) c.f = c c.g = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_two_attrs" - "..C(f=..., g=...)") + self.assertEqual( + repr(c), + "TestReplace.test_recursive_repr_two_attrs" "..C(f=..., g=...)", + ) def test_recursive_repr_indirection(self): @dataclass @@ -4209,9 +4578,12 @@ class D: d = D(None) c.f = d d.f = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection" - "..C(f=TestReplace.test_recursive_repr_indirection" - "..D(f=...))") + self.assertEqual( + repr(c), + "TestReplace.test_recursive_repr_indirection" + "..C(f=TestReplace.test_recursive_repr_indirection" + "..D(f=...))", + ) def test_recursive_repr_indirection_two(self): @dataclass @@ -4232,10 +4604,13 @@ class E: c.f = d d.f = e e.f = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_indirection_two" - "..C(f=TestReplace.test_recursive_repr_indirection_two" - "..D(f=TestReplace.test_recursive_repr_indirection_two" - "..E(f=...)))") + self.assertEqual( + repr(c), + "TestReplace.test_recursive_repr_indirection_two" + "..C(f=TestReplace.test_recursive_repr_indirection_two" + "..D(f=TestReplace.test_recursive_repr_indirection_two" + "..E(f=...)))", + ) def test_recursive_repr_misc_attrs(self): @dataclass @@ -4245,8 +4620,10 @@ class C: c = C(None, 1) c.f = c - self.assertEqual(repr(c), "TestReplace.test_recursive_repr_misc_attrs" - "..C(f=..., g=1)") + self.assertEqual( + repr(c), + "TestReplace.test_recursive_repr_misc_attrs" "..C(f=..., g=1)", + ) ## def test_initvar(self): ## @dataclass @@ -4262,6 +4639,7 @@ class C: ## replace(c, x=5) + class TestAbstract(unittest.TestCase): def test_abc_implementation(self): class Ordered(abc.ABC): @@ -4276,11 +4654,11 @@ def __le__(self, other): @dataclass(order=True) class Date(Ordered): year: int - month: 'Month' - day: 'int' + month: "Month" + day: "int" self.assertFalse(inspect.isabstract(Date)) - self.assertGreater(Date(2020,12,25), Date(2020,8,31)) + self.assertGreater(Date(2020, 12, 25), Date(2020, 8, 31)) def test_maintain_abc(self): class A(abc.ABC): @@ -4291,8 +4669,8 @@ def foo(self): @dataclass class Date(A): year: int - month: 'Month' - day: 'int' + month: "Month" + day: "int" self.assertTrue(inspect.isabstract(Date)) msg = "class Date without an implementation for abstract method 'foo'" @@ -4304,14 +4682,17 @@ def test_match_args(self): @dataclass class C: a: int - self.assertEqual(C(42).__match_args__, ('a',)) + + self.assertEqual(C(42).__match_args__, ("a",)) def test_explicit_match_args(self): ma = () + @dataclass class C: a: int __match_args__ = ma + self.assertIs(C(42).__match_args__, ma) def test_bpo_43764(self): @@ -4320,24 +4701,28 @@ class X: a: int b: int c: int + self.assertEqual(X.__match_args__, ("a", "b", "c")) def test_match_args_argument(self): @dataclass(match_args=False) class X: a: int - self.assertNotIn('__match_args__', X.__dict__) + + self.assertNotIn("__match_args__", X.__dict__) @dataclass(match_args=False) class Y: a: int - __match_args__ = ('b',) - self.assertEqual(Y.__match_args__, ('b',)) + __match_args__ = ("b",) + + self.assertEqual(Y.__match_args__, ("b",)) @dataclass(match_args=False) class Z(Y): z: int - self.assertEqual(Z.__match_args__, ('b',)) + + self.assertEqual(Z.__match_args__, ("b",)) # Ensure parent dataclass __match_args__ is seen, if child class # specifies match_args=False. @@ -4345,39 +4730,46 @@ class Z(Y): class A: a: int z: int + @dataclass(match_args=False) class B(A): b: int - self.assertEqual(B.__match_args__, ('a', 'z')) + + self.assertEqual(B.__match_args__, ("a", "z")) def test_make_dataclasses(self): - C = make_dataclass('C', [('x', int), ('y', int)]) - self.assertEqual(C.__match_args__, ('x', 'y')) + C = make_dataclass("C", [("x", int), ("y", int)]) + self.assertEqual(C.__match_args__, ("x", "y")) - C = make_dataclass('C', [('x', int), ('y', int)], match_args=True) - self.assertEqual(C.__match_args__, ('x', 'y')) + C = make_dataclass("C", [("x", int), ("y", int)], match_args=True) + self.assertEqual(C.__match_args__, ("x", "y")) - C = make_dataclass('C', [('x', int), ('y', int)], match_args=False) - self.assertNotIn('__match__args__', C.__dict__) + C = make_dataclass("C", [("x", int), ("y", int)], match_args=False) + self.assertNotIn("__match__args__", C.__dict__) - C = make_dataclass('C', [('x', int), ('y', int)], namespace={'__match_args__': ('z',)}) - self.assertEqual(C.__match_args__, ('z',)) + C = make_dataclass( + "C", [("x", int), ("y", int)], namespace={"__match_args__": ("z",)} + ) + self.assertEqual(C.__match_args__, ("z",)) class TestKeywordArgs(unittest.TestCase): def test_no_classvar_kwarg(self): - msg = 'field a is a ClassVar but specifies kw_only' + msg = "field a is a ClassVar but specifies kw_only" with self.assertRaisesRegex(TypeError, msg): + @dataclass class A: a: ClassVar[int] = field(kw_only=True) with self.assertRaisesRegex(TypeError, msg): + @dataclass class A: a: ClassVar[int] = field(kw_only=False) with self.assertRaisesRegex(TypeError, msg): + @dataclass(kw_only=True) class A: a: ClassVar[int] = field(kw_only=False) @@ -4388,16 +4780,19 @@ def test_field_marked_as_kwonly(self): @dataclass(kw_only=True) class A: a: int + self.assertTrue(fields(A)[0].kw_only) @dataclass(kw_only=True) class A: a: int = field(kw_only=True) + self.assertTrue(fields(A)[0].kw_only) @dataclass(kw_only=True) class A: a: int = field(kw_only=False) + self.assertFalse(fields(A)[0].kw_only) ####################### @@ -4405,16 +4800,19 @@ class A: @dataclass(kw_only=False) class A: a: int + self.assertFalse(fields(A)[0].kw_only) @dataclass(kw_only=False) class A: a: int = field(kw_only=True) + self.assertTrue(fields(A)[0].kw_only) @dataclass(kw_only=False) class A: a: int = field(kw_only=False) + self.assertFalse(fields(A)[0].kw_only) ####################### @@ -4422,16 +4820,19 @@ class A: @dataclass class A: a: int + self.assertFalse(fields(A)[0].kw_only) @dataclass class A: a: int = field(kw_only=True) + self.assertTrue(fields(A)[0].kw_only) @dataclass class A: a: int = field(kw_only=False) + self.assertFalse(fields(A)[0].kw_only) def test_match_args(self): @@ -4439,13 +4840,15 @@ def test_match_args(self): @dataclass(kw_only=True) class C: a: int + self.assertEqual(C(a=42).__match_args__, ()) @dataclass class C: a: int b: int = field(kw_only=True) - self.assertEqual(C(42, b=10).__match_args__, ('a',)) + + self.assertEqual(C(42, b=10).__match_args__, ("a",)) def test_KW_ONLY(self): @dataclass @@ -4454,18 +4857,19 @@ class A: _: KW_ONLY b: int c: int + A(3, c=5, b=4) msg = "takes 2 positional arguments but 4 were given" with self.assertRaisesRegex(TypeError, msg): A(3, 4, 5) - @dataclass(kw_only=True) class B: a: int _: KW_ONLY b: int c: int + B(a=3, b=4, c=5) msg = "takes 1 positional argument but 4 were given" with self.assertRaisesRegex(TypeError, msg): @@ -4478,6 +4882,7 @@ class C: _: KW_ONLY b: int c: int = field(kw_only=False) + c = C(1, 2, b=3) self.assertEqual(c.a, 1) self.assertEqual(c.b, 3) @@ -4499,9 +4904,10 @@ def test_KW_ONLY_as_string(self): @dataclass class A: a: int - _: 'dataclasses.KW_ONLY' + _: "dataclasses.KW_ONLY" b: int c: int + A(3, c=5, b=4) msg = "takes 2 positional arguments but 4 were given" with self.assertRaisesRegex(TypeError, msg): @@ -4511,6 +4917,7 @@ def test_KW_ONLY_twice(self): msg = "'Y' is KW_ONLY, but KW_ONLY has already been specified" with self.assertRaisesRegex(TypeError, msg): + @dataclass class A: a: int @@ -4520,6 +4927,7 @@ class A: c: int with self.assertRaisesRegex(TypeError, msg): + @dataclass class A: a: int @@ -4529,6 +4937,7 @@ class A: c: int with self.assertRaisesRegex(TypeError, msg): + @dataclass class A: a: int @@ -4552,6 +4961,7 @@ class A: _: KW_ONLY b: int c: int + @dataclass class B(A): _: KW_ONLY @@ -4559,19 +4969,20 @@ class B(A): # Make sure the error is raised in a derived class. with self.assertRaisesRegex(TypeError, msg): + @dataclass class A: a: int _: KW_ONLY b: int c: int + @dataclass class B(A): X: KW_ONLY d: int Y: KW_ONLY - def test_post_init(self): @dataclass class A: @@ -4580,9 +4991,11 @@ class A: b: InitVar[int] c: int d: InitVar[int] + def __post_init__(self, b, d): - raise CustomError(f'{b=} {d=}') - with self.assertRaisesRegex(CustomError, 'b=3 d=4'): + raise CustomError(f"{b=} {d=}") + + with self.assertRaisesRegex(CustomError, "b=3 d=4"): A(1, c=2, b=3, d=4) @dataclass @@ -4592,11 +5005,13 @@ class B: b: InitVar[int] c: int d: InitVar[int] + def __post_init__(self, b, d): self.a = b self.c = d + b = B(1, c=2, b=3, d=4) - self.assertEqual(asdict(b), {'a': 3, 'c': 4}) + self.assertEqual(asdict(b), {"a": 3, "c": 4}) def test_defaults(self): # For kwargs, make sure we can have defaults after non-defaults. @@ -4618,6 +5033,7 @@ class A: # defaults. err_regex = "non-default argument 'z' follows default argument 'a'" with self.assertRaisesRegex(TypeError, err_regex): + @dataclass class A: a: int = 0 @@ -4628,15 +5044,13 @@ class A: d: int def test_make_dataclass(self): - A = make_dataclass("A", ['a'], kw_only=True) + A = make_dataclass("A", ["a"], kw_only=True) self.assertTrue(fields(A)[0].kw_only) - B = make_dataclass("B", - ['a', ('b', int, field(kw_only=False))], - kw_only=True) + B = make_dataclass("B", ["a", ("b", int, field(kw_only=False))], kw_only=True) self.assertTrue(fields(B)[0].kw_only) self.assertFalse(fields(B)[1].kw_only) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 4a3db80ca43c27..28fa48b598abbc 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -28,57 +28,56 @@ class OperatorsTest(unittest.TestCase): - def __init__(self, *args, **kwargs): unittest.TestCase.__init__(self, *args, **kwargs) self.binops = { - 'add': '+', - 'sub': '-', - 'mul': '*', - 'matmul': '@', - 'truediv': '/', - 'floordiv': '//', - 'divmod': 'divmod', - 'pow': '**', - 'lshift': '<<', - 'rshift': '>>', - 'and': '&', - 'xor': '^', - 'or': '|', - 'cmp': 'cmp', - 'lt': '<', - 'le': '<=', - 'eq': '==', - 'ne': '!=', - 'gt': '>', - 'ge': '>=', + "add": "+", + "sub": "-", + "mul": "*", + "matmul": "@", + "truediv": "/", + "floordiv": "//", + "divmod": "divmod", + "pow": "**", + "lshift": "<<", + "rshift": ">>", + "and": "&", + "xor": "^", + "or": "|", + "cmp": "cmp", + "lt": "<", + "le": "<=", + "eq": "==", + "ne": "!=", + "gt": ">", + "ge": ">=", } for name, expr in list(self.binops.items()): if expr.islower(): expr = expr + "(a, b)" else: - expr = 'a %s b' % expr + expr = "a %s b" % expr self.binops[name] = expr self.unops = { - 'pos': '+', - 'neg': '-', - 'abs': 'abs', - 'invert': '~', - 'int': 'int', - 'float': 'float', + "pos": "+", + "neg": "-", + "abs": "abs", + "invert": "~", + "int": "int", + "float": "float", } for name, expr in list(self.unops.items()): if expr.islower(): expr = expr + "(a)" else: - expr = '%s a' % expr + expr = "%s a" % expr self.unops[name] = expr def unop_test(self, a, res, expr="len(a)", meth="__len__"): - d = {'a': a} + d = {"a": a} self.assertEqual(eval(expr, d), res) t = type(a) m = getattr(t, meth) @@ -88,13 +87,13 @@ def unop_test(self, a, res, expr="len(a)", meth="__len__"): t = t.__bases__[0] # in some implementations (e.g. PyPy), 'm' can be a regular unbound # method object; the getattr() below obtains its underlying function. - self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) + self.assertEqual(getattr(m, "im_func", m), t.__dict__[meth]) self.assertEqual(m(a), res) bm = getattr(a, meth) self.assertEqual(bm(), res) def binop_test(self, a, b, res, expr="a+b", meth="__add__"): - d = {'a': a, 'b': b} + d = {"a": a, "b": b} self.assertEqual(eval(expr, d), res) t = type(a) @@ -103,13 +102,13 @@ def binop_test(self, a, b, res, expr="a+b", meth="__add__"): t = t.__bases__[0] # in some implementations (e.g. PyPy), 'm' can be a regular unbound # method object; the getattr() below obtains its underlying function. - self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) + self.assertEqual(getattr(m, "im_func", m), t.__dict__[meth]) self.assertEqual(m(a, b), res) bm = getattr(a, meth) self.assertEqual(bm(b), res) def sliceop_test(self, a, b, c, res, expr="a[b:c]", meth="__getitem__"): - d = {'a': a, 'b': b, 'c': c} + d = {"a": a, "b": b, "c": c} self.assertEqual(eval(expr, d), res) t = type(a) m = getattr(t, meth) @@ -117,92 +116,93 @@ def sliceop_test(self, a, b, c, res, expr="a[b:c]", meth="__getitem__"): t = t.__bases__[0] # in some implementations (e.g. PyPy), 'm' can be a regular unbound # method object; the getattr() below obtains its underlying function. - self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) + self.assertEqual(getattr(m, "im_func", m), t.__dict__[meth]) self.assertEqual(m(a, slice(b, c)), res) bm = getattr(a, meth) self.assertEqual(bm(slice(b, c)), res) def setop_test(self, a, b, res, stmt="a+=b", meth="__iadd__"): - d = {'a': deepcopy(a), 'b': b} + d = {"a": deepcopy(a), "b": b} exec(stmt, d) - self.assertEqual(d['a'], res) + self.assertEqual(d["a"], res) t = type(a) m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] # in some implementations (e.g. PyPy), 'm' can be a regular unbound # method object; the getattr() below obtains its underlying function. - self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) - d['a'] = deepcopy(a) - m(d['a'], b) - self.assertEqual(d['a'], res) - d['a'] = deepcopy(a) - bm = getattr(d['a'], meth) + self.assertEqual(getattr(m, "im_func", m), t.__dict__[meth]) + d["a"] = deepcopy(a) + m(d["a"], b) + self.assertEqual(d["a"], res) + d["a"] = deepcopy(a) + bm = getattr(d["a"], meth) bm(b) - self.assertEqual(d['a'], res) + self.assertEqual(d["a"], res) def set2op_test(self, a, b, c, res, stmt="a[b]=c", meth="__setitem__"): - d = {'a': deepcopy(a), 'b': b, 'c': c} + d = {"a": deepcopy(a), "b": b, "c": c} exec(stmt, d) - self.assertEqual(d['a'], res) + self.assertEqual(d["a"], res) t = type(a) m = getattr(t, meth) while meth not in t.__dict__: t = t.__bases__[0] # in some implementations (e.g. PyPy), 'm' can be a regular unbound # method object; the getattr() below obtains its underlying function. - self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) - d['a'] = deepcopy(a) - m(d['a'], b, c) - self.assertEqual(d['a'], res) - d['a'] = deepcopy(a) - bm = getattr(d['a'], meth) + self.assertEqual(getattr(m, "im_func", m), t.__dict__[meth]) + d["a"] = deepcopy(a) + m(d["a"], b, c) + self.assertEqual(d["a"], res) + d["a"] = deepcopy(a) + bm = getattr(d["a"], meth) bm(b, c) - self.assertEqual(d['a'], res) + self.assertEqual(d["a"], res) def setsliceop_test(self, a, b, c, d, res, stmt="a[b:c]=d", meth="__setitem__"): - dictionary = {'a': deepcopy(a), 'b': b, 'c': c, 'd': d} + dictionary = {"a": deepcopy(a), "b": b, "c": c, "d": d} exec(stmt, dictionary) - self.assertEqual(dictionary['a'], res) + self.assertEqual(dictionary["a"], res) t = type(a) while meth not in t.__dict__: t = t.__bases__[0] m = getattr(t, meth) # in some implementations (e.g. PyPy), 'm' can be a regular unbound # method object; the getattr() below obtains its underlying function. - self.assertEqual(getattr(m, 'im_func', m), t.__dict__[meth]) - dictionary['a'] = deepcopy(a) - m(dictionary['a'], slice(b, c), d) - self.assertEqual(dictionary['a'], res) - dictionary['a'] = deepcopy(a) - bm = getattr(dictionary['a'], meth) + self.assertEqual(getattr(m, "im_func", m), t.__dict__[meth]) + dictionary["a"] = deepcopy(a) + m(dictionary["a"], slice(b, c), d) + self.assertEqual(dictionary["a"], res) + dictionary["a"] = deepcopy(a) + bm = getattr(dictionary["a"], meth) bm(slice(b, c), d) - self.assertEqual(dictionary['a'], res) + self.assertEqual(dictionary["a"], res) def test_lists(self): # Testing list operations... # Asserts are within individual test methods - self.binop_test([1], [2], [1,2], "a+b", "__add__") - self.binop_test([1,2,3], 2, 1, "b in a", "__contains__") - self.binop_test([1,2,3], 4, 0, "b in a", "__contains__") - self.binop_test([1,2,3], 1, 2, "a[b]", "__getitem__") - self.sliceop_test([1,2,3], 0, 2, [1,2], "a[b:c]", "__getitem__") - self.setop_test([1], [2], [1,2], "a+=b", "__iadd__") - self.setop_test([1,2], 3, [1,2,1,2,1,2], "a*=b", "__imul__") - self.unop_test([1,2,3], 3, "len(a)", "__len__") - self.binop_test([1,2], 3, [1,2,1,2,1,2], "a*b", "__mul__") - self.binop_test([1,2], 3, [1,2,1,2,1,2], "b*a", "__rmul__") - self.set2op_test([1,2], 1, 3, [1,3], "a[b]=c", "__setitem__") - self.setsliceop_test([1,2,3,4], 1, 3, [5,6], [1,5,6,4], "a[b:c]=d", - "__setitem__") + self.binop_test([1], [2], [1, 2], "a+b", "__add__") + self.binop_test([1, 2, 3], 2, 1, "b in a", "__contains__") + self.binop_test([1, 2, 3], 4, 0, "b in a", "__contains__") + self.binop_test([1, 2, 3], 1, 2, "a[b]", "__getitem__") + self.sliceop_test([1, 2, 3], 0, 2, [1, 2], "a[b:c]", "__getitem__") + self.setop_test([1], [2], [1, 2], "a+=b", "__iadd__") + self.setop_test([1, 2], 3, [1, 2, 1, 2, 1, 2], "a*=b", "__imul__") + self.unop_test([1, 2, 3], 3, "len(a)", "__len__") + self.binop_test([1, 2], 3, [1, 2, 1, 2, 1, 2], "a*b", "__mul__") + self.binop_test([1, 2], 3, [1, 2, 1, 2, 1, 2], "b*a", "__rmul__") + self.set2op_test([1, 2], 1, 3, [1, 3], "a[b]=c", "__setitem__") + self.setsliceop_test( + [1, 2, 3, 4], 1, 3, [5, 6], [1, 5, 6, 4], "a[b:c]=d", "__setitem__" + ) def test_dicts(self): # Testing dict operations... - self.binop_test({1:2,3:4}, 1, 1, "b in a", "__contains__") - self.binop_test({1:2,3:4}, 2, 0, "b in a", "__contains__") - self.binop_test({1:2,3:4}, 1, 2, "a[b]", "__getitem__") + self.binop_test({1: 2, 3: 4}, 1, 1, "b in a", "__contains__") + self.binop_test({1: 2, 3: 4}, 2, 0, "b in a", "__contains__") + self.binop_test({1: 2, 3: 4}, 1, 2, "a[b]", "__getitem__") - d = {1:2, 3:4} + d = {1: 2, 3: 4} l1 = [] for i in list(d.keys()): l1.append(i) @@ -218,16 +218,17 @@ def test_dicts(self): for i in dict.__iter__(d): l.append(i) self.assertEqual(l, l1) - d = {1:2, 3:4} + d = {1: 2, 3: 4} self.unop_test(d, 2, "len(a)", "__len__") self.assertEqual(eval(repr(d), {}), d) self.assertEqual(eval(d.__repr__(), {}), d) - self.set2op_test({1:2,3:4}, 2, 3, {1:2,2:3,3:4}, "a[b]=c", - "__setitem__") + self.set2op_test( + {1: 2, 3: 4}, 2, 3, {1: 2, 2: 3, 3: 4}, "a[b]=c", "__setitem__" + ) # Tests for unary and binary operators def number_operators(self, a, b, skip=[]): - dict = {'a': a, 'b': b} + dict = {"a": a, "b": b} for name, expr in self.binops.items(): if name not in skip: @@ -249,10 +250,12 @@ def test_ints(self): # The following crashes in Python 2.2 self.assertEqual((1).__bool__(), 1) self.assertEqual((0).__bool__(), 0) + # This returns 'NotImplemented' in Python 2.2 class C(int): def __add__(self, other): return NotImplemented + self.assertEqual(C(5), 5) try: C() + "" @@ -267,16 +270,20 @@ def test_floats(self): def test_complexes(self): # Testing complex operations... - self.number_operators(100.0j, 3.0j, skip=['lt', 'le', 'gt', 'ge', - 'int', 'float', - 'floordiv', 'divmod', 'mod']) + self.number_operators( + 100.0j, + 3.0j, + skip=["lt", "le", "gt", "ge", "int", "float", "floordiv", "divmod", "mod"], + ) class Number(complex): - __slots__ = ['prec'] + __slots__ = ["prec"] + def __new__(cls, *args, **kwds): result = complex.__new__(cls, *args) - result.prec = kwds.get('prec', 12) + result.prec = kwds.get("prec", 12) return result + def __repr__(self): prec = self.prec if self.imag == 0.0: @@ -284,6 +291,7 @@ def __repr__(self): if self.real == 0.0: return "%.*gj" % (prec, self.imag) return "(%.*g+%.*gj)" % (prec, self.real, prec, self.imag) + __str__ = __repr__ a = Number(3.14, prec=6) @@ -311,34 +319,52 @@ def test_spam_lists(self): def spamlist(l, memo=None): import xxsubtype as spam + return spam.spamlist(l) # This is an ugly hack: copy._deepcopy_dispatch[spam.spamlist] = spamlist - self.binop_test(spamlist([1]), spamlist([2]), spamlist([1,2]), "a+b", - "__add__") - self.binop_test(spamlist([1,2,3]), 2, 1, "b in a", "__contains__") - self.binop_test(spamlist([1,2,3]), 4, 0, "b in a", "__contains__") - self.binop_test(spamlist([1,2,3]), 1, 2, "a[b]", "__getitem__") - self.sliceop_test(spamlist([1,2,3]), 0, 2, spamlist([1,2]), "a[b:c]", - "__getitem__") - self.setop_test(spamlist([1]), spamlist([2]), spamlist([1,2]), "a+=b", - "__iadd__") - self.setop_test(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "a*=b", - "__imul__") - self.unop_test(spamlist([1,2,3]), 3, "len(a)", "__len__") - self.binop_test(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "a*b", - "__mul__") - self.binop_test(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "b*a", - "__rmul__") - self.set2op_test(spamlist([1,2]), 1, 3, spamlist([1,3]), "a[b]=c", - "__setitem__") - self.setsliceop_test(spamlist([1,2,3,4]), 1, 3, spamlist([5,6]), - spamlist([1,5,6,4]), "a[b:c]=d", "__setitem__") + self.binop_test( + spamlist([1]), spamlist([2]), spamlist([1, 2]), "a+b", "__add__" + ) + self.binop_test(spamlist([1, 2, 3]), 2, 1, "b in a", "__contains__") + self.binop_test(spamlist([1, 2, 3]), 4, 0, "b in a", "__contains__") + self.binop_test(spamlist([1, 2, 3]), 1, 2, "a[b]", "__getitem__") + self.sliceop_test( + spamlist([1, 2, 3]), 0, 2, spamlist([1, 2]), "a[b:c]", "__getitem__" + ) + self.setop_test( + spamlist([1]), spamlist([2]), spamlist([1, 2]), "a+=b", "__iadd__" + ) + self.setop_test( + spamlist([1, 2]), 3, spamlist([1, 2, 1, 2, 1, 2]), "a*=b", "__imul__" + ) + self.unop_test(spamlist([1, 2, 3]), 3, "len(a)", "__len__") + self.binop_test( + spamlist([1, 2]), 3, spamlist([1, 2, 1, 2, 1, 2]), "a*b", "__mul__" + ) + self.binop_test( + spamlist([1, 2]), 3, spamlist([1, 2, 1, 2, 1, 2]), "b*a", "__rmul__" + ) + self.set2op_test( + spamlist([1, 2]), 1, 3, spamlist([1, 3]), "a[b]=c", "__setitem__" + ) + self.setsliceop_test( + spamlist([1, 2, 3, 4]), + 1, + 3, + spamlist([5, 6]), + spamlist([1, 5, 6, 4]), + "a[b:c]=d", + "__setitem__", + ) + # Test subclassing class C(spam.spamlist): - def foo(self): return 1 + def foo(self): + return 1 + a = C() self.assertEqual(a, []) self.assertEqual(a.foo(), 1) @@ -353,19 +379,22 @@ def foo(self): return 1 def test_spam_dicts(self): # Testing spamdict operations... import copy, xxsubtype as spam + def spamdict(d, memo=None): import xxsubtype as spam + sd = spam.spamdict() for k, v in list(d.items()): sd[k] = v return sd + # This is an ugly hack: copy._deepcopy_dispatch[spam.spamdict] = spamdict - self.binop_test(spamdict({1:2,3:4}), 1, 1, "b in a", "__contains__") - self.binop_test(spamdict({1:2,3:4}), 2, 0, "b in a", "__contains__") - self.binop_test(spamdict({1:2,3:4}), 1, 2, "a[b]", "__getitem__") - d = spamdict({1:2,3:4}) + self.binop_test(spamdict({1: 2, 3: 4}), 1, 1, "b in a", "__contains__") + self.binop_test(spamdict({1: 2, 3: 4}), 2, 0, "b in a", "__contains__") + self.binop_test(spamdict({1: 2, 3: 4}), 1, 2, "a[b]", "__getitem__") + d = spamdict({1: 2, 3: 4}) l1 = [] for i in list(d.keys()): l1.append(i) @@ -381,20 +410,29 @@ def spamdict(d, memo=None): for i in type(spamdict({})).__iter__(d): l.append(i) self.assertEqual(l, l1) - straightd = {1:2, 3:4} + straightd = {1: 2, 3: 4} spamd = spamdict(straightd) self.unop_test(spamd, 2, "len(a)", "__len__") self.unop_test(spamd, repr(straightd), "repr(a)", "__repr__") - self.set2op_test(spamdict({1:2,3:4}), 2, 3, spamdict({1:2,2:3,3:4}), - "a[b]=c", "__setitem__") + self.set2op_test( + spamdict({1: 2, 3: 4}), + 2, + 3, + spamdict({1: 2, 2: 3, 3: 4}), + "a[b]=c", + "__setitem__", + ) + # Test subclassing class C(spam.spamdict): - def foo(self): return 1 + def foo(self): + return 1 + a = C() self.assertEqual(list(a.items()), []) self.assertEqual(a.foo(), 1) - a['foo'] = 'bar' - self.assertEqual(list(a.items()), [('foo', 'bar')]) + a["foo"] = "bar" + self.assertEqual(list(a.items()), [("foo", "bar")]) self.assertEqual(a.getstate(), 0) a.setstate(100) self.assertEqual(a.getstate(), 100) @@ -404,14 +442,13 @@ def test_wrap_lenfunc_bad_cast(self): class ClassPropertiesAndMethods(unittest.TestCase): - def assertHasAttr(self, obj, name): - self.assertTrue(hasattr(obj, name), - '%r has no attribute %r' % (obj, name)) + self.assertTrue(hasattr(obj, name), "%r has no attribute %r" % (obj, name)) def assertNotHasAttr(self, obj, name): - self.assertFalse(hasattr(obj, name), - '%r has unexpected attribute %r' % (obj, name)) + self.assertFalse( + hasattr(obj, name), "%r has unexpected attribute %r" % (obj, name) + ) def test_python_dicts(self): # Testing Python subclass of dict... @@ -421,8 +458,10 @@ def test_python_dicts(self): self.assertEqual(d, {}) self.assertIs(d.__class__, dict) self.assertIsInstance(d, dict) + class C(dict): state = -1 + def __init__(self_local, *a, **kw): if a: self.assertEqual(len(a), 1) @@ -430,20 +469,25 @@ def __init__(self_local, *a, **kw): if kw: for k, v in list(kw.items()): self_local[v] = k + def __getitem__(self, key): return self.get(key, 0) + def __setitem__(self_local, key, value): self.assertIsInstance(key, int) dict.__setitem__(self_local, key, value) + def setstate(self, state): self.state = state + def getstate(self): return self.state + self.assertTrue(issubclass(C, dict)) a1 = C(12) self.assertEqual(a1.state, 12) a2 = C(foo=1, bar=2) - self.assertEqual(a2[1] == 'foo' and a2[2], 'bar') + self.assertEqual(a2[1] == "foo" and a2[2], "bar") a = C() self.assertEqual(a.state, -1) self.assertEqual(a.getstate(), -1) @@ -460,10 +504,10 @@ def getstate(self): for i in range(N): a[i] = C() for j in range(N): - a[i][j] = i*j + a[i][j] = i * j for i in range(N): for j in range(N): - self.assertEqual(a[i][j], i*j) + self.assertEqual(a[i][j], i * j) def test_python_lists(self): # Testing Python subclass of list... @@ -472,45 +516,57 @@ def __getitem__(self, i): if isinstance(i, slice): return i.start, i.stop return list.__getitem__(self, i) + 100 + a = C() - a.extend([0,1,2]) + a.extend([0, 1, 2]) self.assertEqual(a[0], 100) self.assertEqual(a[1], 101) self.assertEqual(a[2], 102) - self.assertEqual(a[100:200], (100,200)) + self.assertEqual(a[100:200], (100, 200)) def test_metaclass(self): # Testing metaclasses... class C(metaclass=type): def __init__(self): self.__state = 0 + def getstate(self): return self.__state + def setstate(self, state): self.__state = state + a = C() self.assertEqual(a.getstate(), 0) a.setstate(10) self.assertEqual(a.getstate(), 10) + class _metaclass(type): - def myself(cls): return cls + def myself(cls): + return cls + class D(metaclass=_metaclass): pass + self.assertEqual(D.myself(), D) d = D() self.assertEqual(d.__class__, D) + class M1(type): def __new__(cls, name, bases, dict): - dict['__spam__'] = 1 + dict["__spam__"] = 1 return type.__new__(cls, name, bases, dict) + class C(metaclass=M1): pass + self.assertEqual(C.__spam__, 1) c = C() self.assertEqual(c.__spam__, 1) class _instance(object): pass + class M2(object): @staticmethod def __new__(cls, name, bases, dict): @@ -519,6 +575,7 @@ def __new__(cls, name, bases, dict): self.bases = bases self.dict = dict return self + def __call__(self): it = _instance() # Early binding of methods @@ -527,12 +584,14 @@ def __call__(self): continue setattr(it, key, self.dict[key].__get__(it, self)) return it + class C(metaclass=M2): def spam(self): return 42 - self.assertEqual(C.name, 'C') + + self.assertEqual(C.name, "C") self.assertEqual(C.bases, ()) - self.assertIn('spam', C.dict) + self.assertIn("spam", C.dict) c = C() self.assertEqual(c.spam(), 42) @@ -542,8 +601,7 @@ class autosuper(type): # Automatically add __super to the class # This trick only works for dynamic classes def __new__(metaclass, name, bases, dict): - cls = super(autosuper, metaclass).__new__(metaclass, - name, bases, dict) + cls = super(autosuper, metaclass).__new__(metaclass, name, bases, dict) # Name mangling for __super removes leading underscores while name[:1] == "_": name = name[1:] @@ -553,22 +611,29 @@ def __new__(metaclass, name, bases, dict): name = "__super" setattr(cls, name, super(cls)) return cls + class A(metaclass=autosuper): def meth(self): return "A" + class B(A): def meth(self): return "B" + self.__super.meth() + class C(A): def meth(self): return "C" + self.__super.meth() + class D(C, B): def meth(self): return "D" + self.__super.meth() + self.assertEqual(D().meth(), "DCBA") + class E(B, C): def meth(self): return "E" + self.__super.meth() + self.assertEqual(E().meth(), "EBCA") class autoproperty(type): @@ -589,13 +654,17 @@ def __new__(metaclass, name, bases, dict): hits[key] = get, set for key, (get, set) in hits.items(): dict[key] = property(get, set) - return super(autoproperty, metaclass).__new__(metaclass, - name, bases, dict) + return super(autoproperty, metaclass).__new__( + metaclass, name, bases, dict + ) + class A(metaclass=autoproperty): def _get_x(self): return -self.__x + def _set_x(self, x): self.__x = -x + a = A() self.assertNotHasAttr(a, "x") a.x = 12 @@ -605,38 +674,50 @@ def _set_x(self, x): class multimetaclass(autoproperty, autosuper): # Merge of multiple cooperating metaclasses pass + class A(metaclass=multimetaclass): def _get_x(self): return "A" + class B(A): def _get_x(self): return "B" + self.__super._get_x() + class C(A): def _get_x(self): return "C" + self.__super._get_x() + class D(C, B): def _get_x(self): return "D" + self.__super._get_x() + self.assertEqual(D().x, "DCBA") # Make sure type(x) doesn't call x.__class__.__init__ class T(type): counter = 0 + def __init__(self, *args): T.counter += 1 + class C(metaclass=T): pass + self.assertEqual(T.counter, 1) a = C() self.assertEqual(type(a), C) self.assertEqual(T.counter, 1) - class C(object): pass + class C(object): + pass + c = C() - try: c() - except TypeError: pass - else: self.fail("calling object w/o call method should raise " - "TypeError") + try: + c() + except TypeError: + pass + else: + self.fail("calling object w/o call method should raise " "TypeError") # Testing code to find most derived baseclass class A(type): @@ -652,15 +733,18 @@ class C(object, metaclass=A): # The most derived metaclass of D is A rather than type. class D(B, C): pass + self.assertIs(A, type(D)) # issue1294232: correct metaclass calculation new_calls = [] # to check the order of __new__ calls + class AMeta(type): @staticmethod def __new__(mcls, name, bases, ns): - new_calls.append('AMeta') + new_calls.append("AMeta") return super().__new__(mcls, name, bases, ns) + @classmethod def __prepare__(mcls, name, bases): return {} @@ -668,64 +752,76 @@ def __prepare__(mcls, name, bases): class BMeta(AMeta): @staticmethod def __new__(mcls, name, bases, ns): - new_calls.append('BMeta') + new_calls.append("BMeta") return super().__new__(mcls, name, bases, ns) + @classmethod def __prepare__(mcls, name, bases): ns = super().__prepare__(name, bases) - ns['BMeta_was_here'] = True + ns["BMeta_was_here"] = True return ns class A(metaclass=AMeta): pass - self.assertEqual(['AMeta'], new_calls) + + self.assertEqual(["AMeta"], new_calls) new_calls.clear() class B(metaclass=BMeta): pass + # BMeta.__new__ calls AMeta.__new__ with super: - self.assertEqual(['BMeta', 'AMeta'], new_calls) + self.assertEqual(["BMeta", "AMeta"], new_calls) new_calls.clear() class C(A, B): pass + # The most derived metaclass is BMeta: - self.assertEqual(['BMeta', 'AMeta'], new_calls) + self.assertEqual(["BMeta", "AMeta"], new_calls) new_calls.clear() # BMeta.__prepare__ should've been called: - self.assertIn('BMeta_was_here', C.__dict__) + self.assertIn("BMeta_was_here", C.__dict__) # The order of the bases shouldn't matter: class C2(B, A): pass - self.assertEqual(['BMeta', 'AMeta'], new_calls) + + self.assertEqual(["BMeta", "AMeta"], new_calls) new_calls.clear() - self.assertIn('BMeta_was_here', C2.__dict__) + self.assertIn("BMeta_was_here", C2.__dict__) # Check correct metaclass calculation when a metaclass is declared: class D(C, metaclass=type): pass - self.assertEqual(['BMeta', 'AMeta'], new_calls) + + self.assertEqual(["BMeta", "AMeta"], new_calls) new_calls.clear() - self.assertIn('BMeta_was_here', D.__dict__) + self.assertIn("BMeta_was_here", D.__dict__) class E(C, metaclass=AMeta): pass - self.assertEqual(['BMeta', 'AMeta'], new_calls) + + self.assertEqual(["BMeta", "AMeta"], new_calls) new_calls.clear() - self.assertIn('BMeta_was_here', E.__dict__) + self.assertIn("BMeta_was_here", E.__dict__) # Special case: the given metaclass isn't a class, # so there is no metaclass calculation. marker = object() + def func(*args, **kwargs): return marker + class X(metaclass=func): pass + class Y(object, metaclass=func): pass + class Z(D, metaclass=func): pass + self.assertIs(marker, X) self.assertIs(marker, Y) self.assertIs(marker, Z) @@ -733,91 +829,106 @@ class Z(D, metaclass=func): # The given metaclass is a class, # but not a descendant of type. prepare_calls = [] # to track __prepare__ calls + class ANotMeta: def __new__(mcls, *args, **kwargs): - new_calls.append('ANotMeta') + new_calls.append("ANotMeta") return super().__new__(mcls) + @classmethod def __prepare__(mcls, name, bases): - prepare_calls.append('ANotMeta') + prepare_calls.append("ANotMeta") return {} + class BNotMeta(ANotMeta): def __new__(mcls, *args, **kwargs): - new_calls.append('BNotMeta') + new_calls.append("BNotMeta") return super().__new__(mcls) + @classmethod def __prepare__(mcls, name, bases): - prepare_calls.append('BNotMeta') + prepare_calls.append("BNotMeta") return super().__prepare__(name, bases) class A(metaclass=ANotMeta): pass + self.assertIs(ANotMeta, type(A)) - self.assertEqual(['ANotMeta'], prepare_calls) + self.assertEqual(["ANotMeta"], prepare_calls) prepare_calls.clear() - self.assertEqual(['ANotMeta'], new_calls) + self.assertEqual(["ANotMeta"], new_calls) new_calls.clear() class B(metaclass=BNotMeta): pass + self.assertIs(BNotMeta, type(B)) - self.assertEqual(['BNotMeta', 'ANotMeta'], prepare_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], prepare_calls) prepare_calls.clear() - self.assertEqual(['BNotMeta', 'ANotMeta'], new_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], new_calls) new_calls.clear() class C(A, B): pass + self.assertIs(BNotMeta, type(C)) - self.assertEqual(['BNotMeta', 'ANotMeta'], new_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], new_calls) new_calls.clear() - self.assertEqual(['BNotMeta', 'ANotMeta'], prepare_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], prepare_calls) prepare_calls.clear() class C2(B, A): pass + self.assertIs(BNotMeta, type(C2)) - self.assertEqual(['BNotMeta', 'ANotMeta'], new_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], new_calls) new_calls.clear() - self.assertEqual(['BNotMeta', 'ANotMeta'], prepare_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], prepare_calls) prepare_calls.clear() # This is a TypeError, because of a metaclass conflict: # BNotMeta is neither a subclass, nor a superclass of type with self.assertRaises(TypeError): + class D(C, metaclass=type): pass class E(C, metaclass=ANotMeta): pass + self.assertIs(BNotMeta, type(E)) - self.assertEqual(['BNotMeta', 'ANotMeta'], new_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], new_calls) new_calls.clear() - self.assertEqual(['BNotMeta', 'ANotMeta'], prepare_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], prepare_calls) prepare_calls.clear() class F(object(), C): pass + self.assertIs(BNotMeta, type(F)) - self.assertEqual(['BNotMeta', 'ANotMeta'], new_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], new_calls) new_calls.clear() - self.assertEqual(['BNotMeta', 'ANotMeta'], prepare_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], prepare_calls) prepare_calls.clear() class F2(C, object()): pass + self.assertIs(BNotMeta, type(F2)) - self.assertEqual(['BNotMeta', 'ANotMeta'], new_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], new_calls) new_calls.clear() - self.assertEqual(['BNotMeta', 'ANotMeta'], prepare_calls) + self.assertEqual(["BNotMeta", "ANotMeta"], prepare_calls) prepare_calls.clear() # TypeError: BNotMeta is neither a # subclass, nor a superclass of int with self.assertRaises(TypeError): + class X(C, int()): pass + with self.assertRaises(TypeError): + class X(int(), C): pass @@ -825,41 +936,50 @@ def test_module_subclasses(self): # Testing Python subclass of module... log = [] MT = type(sys) + class MM(MT): def __init__(self, name): MT.__init__(self, name) + def __getattribute__(self, name): log.append(("getattr", name)) return MT.__getattribute__(self, name) + def __setattr__(self, name, value): log.append(("setattr", name, value)) MT.__setattr__(self, name, value) + def __delattr__(self, name): log.append(("delattr", name)) MT.__delattr__(self, name) + a = MM("a") a.foo = 12 x = a.foo del a.foo - self.assertEqual(log, [("setattr", "foo", 12), - ("getattr", "foo"), - ("delattr", "foo")]) + self.assertEqual( + log, [("setattr", "foo", 12), ("getattr", "foo"), ("delattr", "foo")] + ) # https://bugs.python.org/issue1174712 try: + class Module(types.ModuleType, str): pass except TypeError: pass else: - self.fail("inheriting from ModuleType and str at the same time " - "should fail") + self.fail( + "inheriting from ModuleType and str at the same time " "should fail" + ) # Issue 34805: Verify that definition order is retained def random_name(): - return ''.join(random.choices(string.ascii_letters, k=10)) + return "".join(random.choices(string.ascii_letters, k=10)) + class A: pass + subclasses = [type(random_name(), (A,), {}) for i in range(100)] self.assertEqual(A.__subclasses__(), subclasses) @@ -868,18 +988,23 @@ def test_multiple_inheritance(self): class C(object): def __init__(self): self.__state = 0 + def getstate(self): return self.__state + def setstate(self, state): self.__state = state + a = C() self.assertEqual(a.getstate(), 0) a.setstate(10) self.assertEqual(a.getstate(), 10) + class D(dict, C): def __init__(self): dict.__init__(self) C.__init__(self) + d = D() self.assertEqual(list(d.keys()), []) d["hello"] = "world" @@ -894,11 +1019,14 @@ def __init__(self): class Node(object): def __int__(self): return int(self.foo()) + def foo(self): return "23" + class Frag(Node, list): def foo(self): return "42" + self.assertEqual(Node().__int__(), 23) self.assertEqual(int(Node()), 23) self.assertEqual(Frag().__int__(), 42) @@ -907,34 +1035,54 @@ def foo(self): def test_diamond_inheritance(self): # Testing multiple inheritance special cases... class A(object): - def spam(self): return "A" + def spam(self): + return "A" + self.assertEqual(A().spam(), "A") + class B(A): - def boo(self): return "B" - def spam(self): return "B" + def boo(self): + return "B" + + def spam(self): + return "B" + self.assertEqual(B().spam(), "B") self.assertEqual(B().boo(), "B") + class C(A): - def boo(self): return "C" + def boo(self): + return "C" + self.assertEqual(C().spam(), "A") self.assertEqual(C().boo(), "C") - class D(B, C): pass + + class D(B, C): + pass + self.assertEqual(D().spam(), "B") self.assertEqual(D().boo(), "B") self.assertEqual(D.__mro__, (D, B, C, A, object)) - class E(C, B): pass + + class E(C, B): + pass + self.assertEqual(E().spam(), "B") self.assertEqual(E().boo(), "C") self.assertEqual(E.__mro__, (E, C, B, A, object)) # MRO order disagreement try: - class F(D, E): pass + + class F(D, E): + pass except TypeError: pass else: self.fail("expected MRO order disagreement (F)") try: - class G(E, D): pass + + class G(E, D): + pass except TypeError: pass else: @@ -943,54 +1091,117 @@ class G(E, D): pass # see thread python-dev/2002-October/029035.html def test_ex5_from_c3_switch(self): # Testing ex5 from C3 switch discussion... - class A(object): pass - class B(object): pass - class C(object): pass - class X(A): pass - class Y(A): pass - class Z(X,B,Y,C): pass + class A(object): + pass + + class B(object): + pass + + class C(object): + pass + + class X(A): + pass + + class Y(A): + pass + + class Z(X, B, Y, C): + pass + self.assertEqual(Z.__mro__, (Z, X, B, Y, A, C, object)) # see "A Monotonic Superclass Linearization for Dylan", # by Kim Barrett et al. (OOPSLA 1996) def test_monotonicity(self): # Testing MRO monotonicity... - class Boat(object): pass - class DayBoat(Boat): pass - class WheelBoat(Boat): pass - class EngineLess(DayBoat): pass - class SmallMultihull(DayBoat): pass - class PedalWheelBoat(EngineLess,WheelBoat): pass - class SmallCatamaran(SmallMultihull): pass - class Pedalo(PedalWheelBoat,SmallCatamaran): pass - - self.assertEqual(PedalWheelBoat.__mro__, - (PedalWheelBoat, EngineLess, DayBoat, WheelBoat, Boat, object)) - self.assertEqual(SmallCatamaran.__mro__, - (SmallCatamaran, SmallMultihull, DayBoat, Boat, object)) - self.assertEqual(Pedalo.__mro__, - (Pedalo, PedalWheelBoat, EngineLess, SmallCatamaran, - SmallMultihull, DayBoat, WheelBoat, Boat, object)) + class Boat(object): + pass + + class DayBoat(Boat): + pass + + class WheelBoat(Boat): + pass + + class EngineLess(DayBoat): + pass + + class SmallMultihull(DayBoat): + pass + + class PedalWheelBoat(EngineLess, WheelBoat): + pass + + class SmallCatamaran(SmallMultihull): + pass + + class Pedalo(PedalWheelBoat, SmallCatamaran): + pass + + self.assertEqual( + PedalWheelBoat.__mro__, + (PedalWheelBoat, EngineLess, DayBoat, WheelBoat, Boat, object), + ) + self.assertEqual( + SmallCatamaran.__mro__, + (SmallCatamaran, SmallMultihull, DayBoat, Boat, object), + ) + self.assertEqual( + Pedalo.__mro__, + ( + Pedalo, + PedalWheelBoat, + EngineLess, + SmallCatamaran, + SmallMultihull, + DayBoat, + WheelBoat, + Boat, + object, + ), + ) # see "A Monotonic Superclass Linearization for Dylan", # by Kim Barrett et al. (OOPSLA 1996) def test_consistency_with_epg(self): # Testing consistency with EPG... - class Pane(object): pass - class ScrollingMixin(object): pass - class EditingMixin(object): pass - class ScrollablePane(Pane,ScrollingMixin): pass - class EditablePane(Pane,EditingMixin): pass - class EditableScrollablePane(ScrollablePane,EditablePane): pass + class Pane(object): + pass + + class ScrollingMixin(object): + pass + + class EditingMixin(object): + pass - self.assertEqual(EditableScrollablePane.__mro__, - (EditableScrollablePane, ScrollablePane, EditablePane, Pane, - ScrollingMixin, EditingMixin, object)) + class ScrollablePane(Pane, ScrollingMixin): + pass + + class EditablePane(Pane, EditingMixin): + pass + + class EditableScrollablePane(ScrollablePane, EditablePane): + pass + + self.assertEqual( + EditableScrollablePane.__mro__, + ( + EditableScrollablePane, + ScrollablePane, + EditablePane, + Pane, + ScrollingMixin, + EditingMixin, + object, + ), + ) def test_mro_disagreement(self): # Testing error messages for MRO disagreement... - mro_err_msg = ("Cannot create a consistent method resolution " - "order (MRO) for bases ") + mro_err_msg = ( + "Cannot create a consistent method resolution " "order (MRO) for bases " + ) def raises(exc, expected, callable, *args): try: @@ -999,30 +1210,41 @@ def raises(exc, expected, callable, *args): # the exact msg is generally considered an impl detail if support.check_impl_detail(): if not str(msg).startswith(expected): - self.fail("Message %r, expected %r" % - (str(msg), expected)) + self.fail("Message %r, expected %r" % (str(msg), expected)) else: self.fail("Expected %s" % exc) - class A(object): pass - class B(A): pass - class C(object): pass + class A(object): + pass + + class B(A): + pass + + class C(object): + pass # Test some very simple errors - raises(TypeError, "duplicate base class A", - type, "X", (A, A), {}) - raises(TypeError, mro_err_msg, - type, "X", (A, B), {}) - raises(TypeError, mro_err_msg, - type, "X", (A, C, B), {}) + raises(TypeError, "duplicate base class A", type, "X", (A, A), {}) + raises(TypeError, mro_err_msg, type, "X", (A, B), {}) + raises(TypeError, mro_err_msg, type, "X", (A, C, B), {}) + # Test a slightly more complex error - class GridLayout(object): pass - class HorizontalGrid(GridLayout): pass - class VerticalGrid(GridLayout): pass - class HVGrid(HorizontalGrid, VerticalGrid): pass - class VHGrid(VerticalGrid, HorizontalGrid): pass - raises(TypeError, mro_err_msg, - type, "ConfusedGrid", (HVGrid, VHGrid), {}) + class GridLayout(object): + pass + + class HorizontalGrid(GridLayout): + pass + + class VerticalGrid(GridLayout): + pass + + class HVGrid(HorizontalGrid, VerticalGrid): + pass + + class VHGrid(VerticalGrid, HorizontalGrid): + pass + + raises(TypeError, mro_err_msg, type, "ConfusedGrid", (HVGrid, VHGrid), {}) def test_object_class(self): # Testing object class... @@ -1042,11 +1264,12 @@ def test_object_class(self): class Cdict(object): pass + x = Cdict() self.assertEqual(x.__dict__, {}) x.foo = 1 self.assertEqual(x.foo, 1) - self.assertEqual(x.__dict__, {'foo': 1}) + self.assertEqual(x.__dict__, {"foo": 1}) def test_object_class_assignment_between_heaptypes_and_nonheaptypes(self): class SubType(types.ModuleType): @@ -1076,36 +1299,43 @@ class SubType(types.ModuleType): class MyInt(int): __slots__ = () + with self.assertRaises(TypeError): (1).__class__ = MyInt class MyFloat(float): __slots__ = () + with self.assertRaises(TypeError): (1.0).__class__ = MyFloat class MyComplex(complex): __slots__ = () + with self.assertRaises(TypeError): (1 + 2j).__class__ = MyComplex class MyStr(str): __slots__ = () + with self.assertRaises(TypeError): "a".__class__ = MyStr class MyBytes(bytes): __slots__ = () + with self.assertRaises(TypeError): b"a".__class__ = MyBytes class MyTuple(tuple): __slots__ = () + with self.assertRaises(TypeError): ().__class__ = MyTuple class MyFrozenSet(frozenset): __slots__ = () + with self.assertRaises(TypeError): frozenset().__class__ = MyFrozenSet @@ -1113,12 +1343,14 @@ def test_slots(self): # Testing __slots__... class C0(object): __slots__ = [] + x = C0() self.assertNotHasAttr(x, "__dict__") self.assertNotHasAttr(x, "foo") class C1(object): - __slots__ = ['a'] + __slots__ = ["a"] + x = C1() self.assertNotHasAttr(x, "__dict__") self.assertNotHasAttr(x, "a") @@ -1130,12 +1362,13 @@ class C1(object): self.assertNotHasAttr(x, "a") class C3(object): - __slots__ = ['a', 'b', 'c'] + __slots__ = ["a", "b", "c"] + x = C3() self.assertNotHasAttr(x, "__dict__") - self.assertNotHasAttr(x, 'a') - self.assertNotHasAttr(x, 'b') - self.assertNotHasAttr(x, 'c') + self.assertNotHasAttr(x, "a") + self.assertNotHasAttr(x, "b") + self.assertNotHasAttr(x, "c") x.a = 1 x.b = 2 x.c = 3 @@ -1145,14 +1378,18 @@ class C3(object): class C4(object): """Validate name mangling""" - __slots__ = ['__a'] + + __slots__ = ["__a"] + def __init__(self, value): self.__a = value + def get(self): return self.__a + x = C4(5) - self.assertNotHasAttr(x, '__dict__') - self.assertNotHasAttr(x, '__a') + self.assertNotHasAttr(x, "__dict__") + self.assertNotHasAttr(x, "__a") self.assertEqual(x.get(), 5) try: x.__a = 6 @@ -1163,6 +1400,7 @@ def get(self): # Make sure slot names are proper identifiers try: + class C(object): __slots__ = [None] except TypeError: @@ -1170,6 +1408,7 @@ class C(object): else: self.fail("[None] slots not caught") try: + class C(object): __slots__ = ["foo bar"] except TypeError: @@ -1177,6 +1416,7 @@ class C(object): else: self.fail("['foo bar'] slots not caught") try: + class C(object): __slots__ = ["foo\0bar"] except TypeError: @@ -1184,6 +1424,7 @@ class C(object): else: self.fail("['foo\\0bar'] slots not caught") try: + class C(object): __slots__ = ["1"] except TypeError: @@ -1191,20 +1432,24 @@ class C(object): else: self.fail("['1'] slots not caught") try: + class C(object): __slots__ = [""] except TypeError: pass else: self.fail("[''] slots not caught") + class C(object): __slots__ = ["a", "a_b", "_a", "A0123456789Z"] + # XXX(nnorwitz): was there supposed to be something tested # from the class above? # Test a single string is not expanded as a sequence. class C(object): __slots__ = "abc" + c = C() c.abc = 5 self.assertEqual(c.abc, 5) @@ -1213,20 +1458,24 @@ class C(object): # Test a single unicode string is not expanded as a sequence. class C(object): __slots__ = "abc" + c = C() c.abc = 5 self.assertEqual(c.abc, 5) # _unicode_to_string used to modify slots in certain circumstances slots = ("foo", "bar") + class C(object): __slots__ = slots + x = C() x.foo = 5 self.assertEqual(x.foo, 5) self.assertIs(type(slots[0]), str) # this used to leak references try: + class C(object): __slots__ = [chr(128)] except (TypeError, UnicodeEncodeError): @@ -1236,13 +1485,17 @@ class C(object): # Test leaks class Counted(object): - counter = 0 # counts the number of instances alive + counter = 0 # counts the number of instances alive + def __init__(self): Counted.counter += 1 + def __del__(self): Counted.counter -= 1 + class C(object): - __slots__ = ['a', 'b', 'c'] + __slots__ = ["a", "b", "c"] + x = C() x.a = Counted() x.b = Counted() @@ -1251,8 +1504,10 @@ class C(object): del x support.gc_collect() self.assertEqual(Counted.counter, 0) + class D(C): pass + x = D() x.a = Counted() x.z = Counted() @@ -1260,8 +1515,10 @@ class D(C): del x support.gc_collect() self.assertEqual(Counted.counter, 0) + class E(D): - __slots__ = ['e'] + __slots__ = ["e"] + x = E() x.a = Counted() x.z = Counted() @@ -1273,7 +1530,8 @@ class E(D): # Test cyclical leaks [SF bug 519621] class F(object): - __slots__ = ['a', 'b'] + __slots__ = ["a", "b"] + s = F() s.a = [Counted(), s] self.assertEqual(Counted.counter, 1) @@ -1282,46 +1540,55 @@ class F(object): self.assertEqual(Counted.counter, 0) # Test lookup leaks [SF bug 572567] - if hasattr(gc, 'get_objects'): + if hasattr(gc, "get_objects"): + class G(object): def __eq__(self, other): return False + g = G() orig_objects = len(gc.get_objects()) for i in range(10): - g==g + g == g new_objects = len(gc.get_objects()) self.assertEqual(orig_objects, new_objects) class H(object): - __slots__ = ['a', 'b'] + __slots__ = ["a", "b"] + def __init__(self): self.a = 1 self.b = 2 + def __del__(self_): self.assertEqual(self_.a, 1) self.assertEqual(self_.b, 2) - with support.captured_output('stderr') as s: + + with support.captured_output("stderr") as s: h = H() del h - self.assertEqual(s.getvalue(), '') + self.assertEqual(s.getvalue(), "") class X(object): __slots__ = "a" + with self.assertRaises(AttributeError): del X().a # Inherit from object on purpose to check some backwards compatibility paths class X(object): __slots__ = "a" + with self.assertRaisesRegex(AttributeError, "'X' object has no attribute 'a'"): X().a # Test string subclass in `__slots__`, see gh-98783 class SubStr(str): pass + class X(object): - __slots__ = (SubStr('x'),) + __slots__ = (SubStr("x"),) + X().x = 1 with self.assertRaisesRegex(AttributeError, "'X' object has no attribute 'a'"): X().a @@ -1330,6 +1597,7 @@ def test_slots_special(self): # Testing __dict__ and __weakref__ in __slots__... class D(object): __slots__ = ["__dict__"] + a = D() self.assertHasAttr(a, "__dict__") self.assertNotHasAttr(a, "__weakref__") @@ -1338,6 +1606,7 @@ class D(object): class W(object): __slots__ = ["__weakref__"] + a = W() self.assertHasAttr(a, "__weakref__") self.assertNotHasAttr(a, "__dict__") @@ -1350,6 +1619,7 @@ class W(object): class C1(W, D): __slots__ = [] + a = C1() self.assertHasAttr(a, "__dict__") self.assertHasAttr(a, "__weakref__") @@ -1358,6 +1628,7 @@ class C1(W, D): class C2(D, W): __slots__ = [] + a = C2() self.assertHasAttr(a, "__dict__") self.assertHasAttr(a, "__weakref__") @@ -1374,32 +1645,36 @@ def __new__(cls, name, bases, namespace, attr): class C1: def __init__(self): self.b = 42 + class C2(C1, metaclass=Meta, attr="__classcell__"): __slots__ = ["__classcell__"] + def __init__(self): super().__init__() - self.assertIsInstance(C2.__dict__["__classcell__"], - types.MemberDescriptorType) + + self.assertIsInstance(C2.__dict__["__classcell__"], types.MemberDescriptorType) c = C2() self.assertEqual(c.b, 42) self.assertNotHasAttr(c, "__classcell__") c.__classcell__ = 42 self.assertEqual(c.__classcell__, 42) with self.assertRaises(TypeError): + class C3: __classcell__ = 42 __slots__ = ["__classcell__"] class Q1(metaclass=Meta, attr="__qualname__"): __slots__ = ["__qualname__"] + self.assertEqual(Q1.__qualname__, C1.__qualname__[:-2] + "Q1") - self.assertIsInstance(Q1.__dict__["__qualname__"], - types.MemberDescriptorType) + self.assertIsInstance(Q1.__dict__["__qualname__"], types.MemberDescriptorType) q = Q1() self.assertNotHasAttr(q, "__qualname__") q.__qualname__ = "q" self.assertEqual(q.__qualname__, "q") with self.assertRaises(TypeError): + class Q2: __qualname__ = object() __slots__ = ["__qualname__"] @@ -1408,11 +1683,13 @@ def test_slots_descriptor(self): # Issue2115: slot descriptors did not correctly check # the type of the given object import abc + class MyABC(metaclass=abc.ABCMeta): __slots__ = "a" class Unrelated(object): pass + MyABC.register(Unrelated) u = Unrelated() @@ -1425,18 +1702,23 @@ def test_dynamics(self): # Testing class attribute propagation... class D(object): pass + class E(D): pass + class F(D): pass + D.foo = 1 self.assertEqual(D.foo, 1) # Test that dynamic attributes are inherited self.assertEqual(E.foo, 1) self.assertEqual(F.foo, 1) + # Test dynamic instances class C(object): pass + a = C() self.assertNotHasAttr(a, "foobar") C.foobar = 2 @@ -1449,25 +1731,31 @@ class C(object): self.assertEqual(int(a), 100) self.assertEqual(a.foobar, 2) self.assertNotHasAttr(a, "spam") + def mygetattr(self, name): if name == "spam": return "spam" raise AttributeError + C.__getattr__ = mygetattr self.assertEqual(a.spam, "spam") a.new = 12 self.assertEqual(a.new, 12) + def mysetattr(self, name, value): if name == "spam": raise AttributeError return object.__setattr__(self, name, value) + C.__setattr__ = mysetattr with self.assertRaises(AttributeError): a.spam = "not spam" self.assertEqual(a.spam, "spam") + class D(C): pass + d = D() d.foo = 1 self.assertEqual(d.foo, 1) @@ -1475,22 +1763,26 @@ class D(C): # Test handling of int*seq and seq*int class I(int): pass - self.assertEqual("a"*I(2), "aa") - self.assertEqual(I(2)*"a", "aa") - self.assertEqual(2*I(3), 6) - self.assertEqual(I(3)*2, 6) - self.assertEqual(I(3)*I(2), 6) + + self.assertEqual("a" * I(2), "aa") + self.assertEqual(I(2) * "a", "aa") + self.assertEqual(2 * I(3), 6) + self.assertEqual(I(3) * 2, 6) + self.assertEqual(I(3) * I(2), 6) # Test comparison of classes with dynamic metaclasses class dynamicmetaclass(type): pass + class someclass(metaclass=dynamicmetaclass): pass + self.assertNotEqual(someclass, object) def test_errors(self): # Testing errors... try: + class C(list, dict): pass except TypeError: @@ -1499,16 +1791,19 @@ class C(list, dict): self.fail("inheritance from both list and dict should be illegal") try: + class C(object, None): pass except TypeError: pass else: self.fail("inheritance from non-type should be illegal") + class Classic: pass try: + class C(type(len)): pass except TypeError: @@ -1517,6 +1812,7 @@ class C(type(len)): self.fail("inheritance from CFunction should be illegal") try: + class C(object): __slots__ = 1 except TypeError: @@ -1525,6 +1821,7 @@ class C(object): self.fail("__slots__ = 1 should be illegal") try: + class C(object): __slots__ = [1] except TypeError: @@ -1534,13 +1831,18 @@ class C(object): class M1(type): pass + class M2(type): pass + class A1(object, metaclass=M1): pass + class A2(object, metaclass=M2): pass + try: + class B(A1, A2): pass except TypeError: @@ -1551,23 +1853,30 @@ class B(A1, A2): def test_classmethods(self): # Testing class methods... class C(object): - def foo(*a): return a + def foo(*a): + return a + goo = classmethod(foo) + c = C() self.assertEqual(C.goo(1), (C, 1)) self.assertEqual(c.goo(1), (C, 1)) self.assertEqual(c.foo(1), (c, 1)) + class D(C): pass + d = D() self.assertEqual(D.goo(1), (D, 1)) self.assertEqual(d.goo(1), (D, 1)) self.assertEqual(d.foo(1), (d, 1)) self.assertEqual(D.foo(d, 1), (d, 1)) + # Test for a specific crash (SF bug 528132) def f(cls, arg): "f docstring" return (cls, arg) + ff = classmethod(f) self.assertEqual(ff.__get__(0, int)(42), (int, 42)) self.assertEqual(ff.__get__(0)(42), (int, 42)) @@ -1575,10 +1884,10 @@ def f(cls, arg): # Test super() with classmethods (SF bug 535444) self.assertEqual(C.goo.__self__, C) self.assertEqual(D.goo.__self__, D) - self.assertEqual(super(D,D).goo.__self__, D) - self.assertEqual(super(D,d).goo.__self__, D) - self.assertEqual(super(D,D).goo(), (D,)) - self.assertEqual(super(D,d).goo(), (D,)) + self.assertEqual(super(D, D).goo.__self__, D) + self.assertEqual(super(D, d).goo.__self__, D) + self.assertEqual(super(D, D).goo(), (D,)) + self.assertEqual(super(D, d).goo(), (D,)) # Verify that a non-callable will raise meth = classmethod(1).__get__(1) @@ -1593,22 +1902,24 @@ def f(cls, arg): self.fail("classmethod shouldn't accept keyword args") cm = classmethod(f) - cm_dict = {'__annotations__': {}, - '__doc__': "f docstring", - '__module__': __name__, - '__name__': 'f', - '__qualname__': f.__qualname__} + cm_dict = { + "__annotations__": {}, + "__doc__": "f docstring", + "__module__": __name__, + "__name__": "f", + "__qualname__": f.__qualname__, + } self.assertEqual(cm.__dict__, cm_dict) cm.x = 42 self.assertEqual(cm.x, 42) - self.assertEqual(cm.__dict__, {"x" : 42, **cm_dict}) + self.assertEqual(cm.__dict__, {"x": 42, **cm_dict}) del cm.x self.assertNotHasAttr(cm, "x") @support.refcount_test def test_refleaks_in_classmethod___init__(self): - gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + gettotalrefcount = support.get_attribute(sys, "gettotalrefcount") cm = classmethod(None) refs_before = gettotalrefcount() for i in range(100): @@ -1620,8 +1931,9 @@ def test_refleaks_in_classmethod___init__(self): def test_classmethods_in_c(self): # Testing C-based class methods... import xxsubtype as spam + a = (1, 2, 3) - d = {'abc': 123} + d = {"abc": 123} x, a1, d1 = spam.spamlist.classmeth(*a, **d) self.assertEqual(x, spam.spamlist) self.assertEqual(a, a1) @@ -1630,12 +1942,15 @@ def test_classmethods_in_c(self): self.assertEqual(x, spam.spamlist) self.assertEqual(a, a1) self.assertEqual(d, d1) - spam_cm = spam.spamlist.__dict__['classmeth'] + spam_cm = spam.spamlist.__dict__["classmeth"] x2, a2, d2 = spam_cm(spam.spamlist, *a, **d) self.assertEqual(x2, spam.spamlist) self.assertEqual(a2, a1) self.assertEqual(d2, d1) - class SubSpam(spam.spamlist): pass + + class SubSpam(spam.spamlist): + pass + x2, a2, d2 = spam_cm(SubSpam, *a, **d) self.assertEqual(x2, SubSpam) self.assertEqual(a2, a1) @@ -1646,20 +1961,23 @@ class SubSpam(spam.spamlist): pass self.assertEqual( str(cm.exception), "descriptor 'classmeth' of 'xxsubtype.spamlist' " - "object needs an argument") + "object needs an argument", + ) with self.assertRaises(TypeError) as cm: spam_cm(spam.spamlist()) self.assertEqual( str(cm.exception), "descriptor 'classmeth' for type 'xxsubtype.spamlist' " - "needs a type, not a 'xxsubtype.spamlist' as arg 2") + "needs a type, not a 'xxsubtype.spamlist' as arg 2", + ) with self.assertRaises(TypeError) as cm: spam_cm(list) expected_errmsg = ( "descriptor 'classmeth' requires a subtype of 'xxsubtype.spamlist' " - "but received 'list'") + "but received 'list'" + ) self.assertEqual(str(cm.exception), expected_errmsg) with self.assertRaises(TypeError) as cm: @@ -1669,30 +1987,41 @@ class SubSpam(spam.spamlist): pass def test_staticmethods(self): # Testing static methods... class C(object): - def foo(*a): return a + def foo(*a): + return a + goo = staticmethod(foo) + c = C() self.assertEqual(C.goo(1), (1,)) self.assertEqual(c.goo(1), (1,)) - self.assertEqual(c.foo(1), (c, 1,)) + self.assertEqual( + c.foo(1), + ( + c, + 1, + ), + ) + class D(C): pass + d = D() self.assertEqual(D.goo(1), (1,)) self.assertEqual(d.goo(1), (1,)) self.assertEqual(d.foo(1), (d, 1)) self.assertEqual(D.foo(d, 1), (d, 1)) sm = staticmethod(None) - self.assertEqual(sm.__dict__, {'__doc__': None}) + self.assertEqual(sm.__dict__, {"__doc__": None}) sm.x = 42 self.assertEqual(sm.x, 42) - self.assertEqual(sm.__dict__, {"x" : 42, '__doc__': None}) + self.assertEqual(sm.__dict__, {"x": 42, "__doc__": None}) del sm.x self.assertNotHasAttr(sm, "x") @support.refcount_test def test_refleaks_in_staticmethod___init__(self): - gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + gettotalrefcount = support.get_attribute(sys, "gettotalrefcount") sm = staticmethod(None) refs_before = gettotalrefcount() for i in range(100): @@ -1704,6 +2033,7 @@ def test_refleaks_in_staticmethod___init__(self): def test_staticmethods_in_c(self): # Testing C-based static methods... import xxsubtype as spam + a = (1, 2, 3) d = {"abc": 123} x, a1, d1 = spam.spamlist.staticmeth(*a, **d) @@ -1718,22 +2048,29 @@ def test_staticmethods_in_c(self): def test_classic(self): # Testing classic classes... class C: - def foo(*a): return a + def foo(*a): + return a + goo = classmethod(foo) + c = C() self.assertEqual(C.goo(1), (C, 1)) self.assertEqual(c.goo(1), (C, 1)) self.assertEqual(c.foo(1), (c, 1)) + class D(C): pass + d = D() self.assertEqual(D.goo(1), (D, 1)) self.assertEqual(d.goo(1), (D, 1)) self.assertEqual(d.foo(1), (d, 1)) self.assertEqual(D.foo(d, 1), (d, 1)) - class E: # *not* subclassing from C + + class E: # *not* subclassing from C foo = C.foo - self.assertEqual(E().foo.__func__, C.foo) # i.e., unbound + + self.assertEqual(E().foo.__func__, C.foo) # i.e., unbound self.assertTrue(repr(C.foo.__get__(C())).startswith("= other + def __gt__(self, other): return self.x > other + def __le__(self, other): return self.x <= other + def __lt__(self, other): return self.x < other + def __str__(self): return "Proxy:%s" % self.x + def __repr__(self): return "Proxy(%r)" % self.x + def __contains__(self, value): return value in self.x + p0 = Proxy(0) p1 = Proxy(1) p_1 = Proxy(-1) @@ -2242,8 +2679,10 @@ def __contains__(self, value): def test_weakrefs(self): # Testing weak references... import weakref + class C(object): pass + c = C() r = weakref.ref(c) self.assertEqual(r(), c) @@ -2251,8 +2690,10 @@ class C(object): support.gc_collect() self.assertEqual(r(), None) del r + class NoWeak(object): - __slots__ = ['foo'] + __slots__ = ["foo"] + no = NoWeak() try: weakref.ref(no) @@ -2260,8 +2701,10 @@ class NoWeak(object): self.assertIn("weak reference", str(msg)) else: self.fail("weakref.ref(no) should be illegal") + class Weak(object): - __slots__ = ['foo', '__weakref__'] + __slots__ = ["foo", "__weakref__"] + yes = Weak() r = weakref.ref(yes) self.assertEqual(r(), yes) @@ -2275,11 +2718,15 @@ def test_properties(self): class C(object): def getx(self): return self.__x + def setx(self, value): self.__x = value + def delx(self): del self.__x + x = property(getx, setx, delx, doc="I'm the x property.") + a = C() self.assertNotHasAttr(a, "x") a.x = 42 @@ -2293,7 +2740,7 @@ def delx(self): C.x.__delete__(a) self.assertNotHasAttr(a, "x") - raw = C.__dict__['x'] + raw = C.__dict__["x"] self.assertIsInstance(raw, property) attrs = dir(raw) @@ -2303,26 +2750,30 @@ def delx(self): self.assertIn("fdel", attrs) self.assertEqual(raw.__doc__, "I'm the x property.") - self.assertIs(raw.fget, C.__dict__['getx']) - self.assertIs(raw.fset, C.__dict__['setx']) - self.assertIs(raw.fdel, C.__dict__['delx']) + self.assertIs(raw.fget, C.__dict__["getx"]) + self.assertIs(raw.fset, C.__dict__["setx"]) + self.assertIs(raw.fdel, C.__dict__["delx"]) for attr in "fget", "fset", "fdel": try: setattr(raw, attr, 42) except AttributeError as msg: - if str(msg).find('readonly') < 0: - self.fail("when setting readonly attr %r on a property, " - "got unexpected AttributeError msg %r" % (attr, str(msg))) + if str(msg).find("readonly") < 0: + self.fail( + "when setting readonly attr %r on a property, " + "got unexpected AttributeError msg %r" % (attr, str(msg)) + ) else: - self.fail("expected AttributeError from trying to set readonly %r " - "attr on a property" % attr) + self.fail( + "expected AttributeError from trying to set readonly %r " + "attr on a property" % attr + ) raw.__doc__ = 42 self.assertEqual(raw.__doc__, 42) class D(object): - __getitem__ = property(lambda s: 1/0) + __getitem__ = property(lambda s: 1 / 0) d = D() try: @@ -2333,16 +2784,19 @@ class D(object): else: self.fail("expected ZeroDivisionError from bad property") - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") + @unittest.skipIf( + sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above" + ) def test_properties_doc_attrib(self): class E(object): def getter(self): "getter method" return 0 + def setter(self_, value): "setter method" pass + prop = property(getter) self.assertEqual(prop.__doc__, "getter method") prop2 = property(fset=setter) @@ -2356,30 +2810,35 @@ def test_testcapi_no_segfault(self): except ImportError: pass else: + class X(object): p = property(_testcapi.test_with_docstring) def test_properties_plus(self): class C(object): foo = property(doc="hello") + @foo.getter def foo(self): return self._foo + @foo.setter def foo(self, value): self._foo = abs(value) + @foo.deleter def foo(self): del self._foo + c = C() self.assertEqual(C.foo.__doc__, "hello") self.assertNotHasAttr(c, "foo") c.foo = -42 - self.assertHasAttr(c, '_foo') + self.assertHasAttr(c, "_foo") self.assertEqual(c._foo, 42) self.assertEqual(c.foo, 42) del c.foo - self.assertNotHasAttr(c, '_foo') + self.assertNotHasAttr(c, "_foo") self.assertNotHasAttr(c, "foo") class D(C): @@ -2389,6 +2848,7 @@ def foo(self): del self._foo except AttributeError: pass + d = D() d.foo = 24 self.assertEqual(d.foo, 24) @@ -2399,12 +2859,15 @@ class E(object): @property def foo(self): return self._foo + @foo.setter def foo(self, value): raise RuntimeError + @foo.setter def foo(self, value): self._foo = abs(value) + @foo.deleter def foo(self, value=None): del self._foo @@ -2418,9 +2881,11 @@ class F(E): @E.foo.deleter def foo(self): del self._foo + @foo.setter def foo(self, value): self._foo = max(0, value) + f = F() f.foo = -10 self.assertEqual(f.foo, 0) @@ -2432,11 +2897,11 @@ def test_dict_constructors(self): self.assertEqual(d, {}) d = dict({}) self.assertEqual(d, {}) - d = dict({1: 2, 'a': 'b'}) - self.assertEqual(d, {1: 2, 'a': 'b'}) + d = dict({1: 2, "a": "b"}) + self.assertEqual(d, {1: 2, "a": "b"}) self.assertEqual(d, dict(list(d.items()))) self.assertEqual(d, dict(iter(d.items()))) - d = dict({'one':1, 'two':2}) + d = dict({"one": 1, "two": 2}) self.assertEqual(d, dict(one=1, two=2)) self.assertEqual(d, dict(**d)) self.assertEqual(d, dict({"one": 1}, two=2)) @@ -2465,7 +2930,7 @@ def test_dict_constructors(self): class Mapping: # Lacks a .keys() method; will be added later. - dict = {1:2, 3:4, 'a':1j} + dict = {1: 2, 3: 4, "a": 1j} try: dict(Mapping()) @@ -2484,20 +2949,25 @@ class AddressBookEntry: def __init__(self, first, last): self.first = first self.last = last + def __iter__(self): return iter([self.first, self.last]) - d = dict([AddressBookEntry('Tim', 'Warsaw'), - AddressBookEntry('Barry', 'Peters'), - AddressBookEntry('Tim', 'Peters'), - AddressBookEntry('Barry', 'Warsaw')]) - self.assertEqual(d, {'Barry': 'Warsaw', 'Tim': 'Peters'}) + d = dict( + [ + AddressBookEntry("Tim", "Warsaw"), + AddressBookEntry("Barry", "Peters"), + AddressBookEntry("Tim", "Peters"), + AddressBookEntry("Barry", "Warsaw"), + ] + ) + self.assertEqual(d, {"Barry": "Warsaw", "Tim": "Peters"}) d = dict(zip(range(4), range(1, 5))) - self.assertEqual(d, dict([(i, i+1) for i in range(4)])) + self.assertEqual(d, dict([(i, i + 1) for i in range(4)])) # Bad sequence lengths. - for bad in [('tooshort',)], [('too', 'long', 'by 1')]: + for bad in [("tooshort",)], [("too", "long", "by 1")]: try: dict(bad) except ValueError: @@ -2508,23 +2978,25 @@ def __iter__(self): def test_dir(self): # Testing dir() ... junk = 12 - self.assertEqual(dir(), ['junk', 'self']) + self.assertEqual(dir(), ["junk", "self"]) del junk # Just make sure these don't blow up! - for arg in 2, 2, 2j, 2e0, [2], "2", b"2", (2,), {2:2}, type, self.test_dir: + for arg in 2, 2, 2j, 2e0, [2], "2", b"2", (2,), {2: 2}, type, self.test_dir: dir(arg) # Test dir on new-style classes. Since these have object as a # base class, a lot more gets sucked in. def interesting(strings): - return [s for s in strings if not s.startswith('_')] + return [s for s in strings if not s.startswith("_")] class C(object): Cdata = 1 - def Cmethod(self): pass - cstuff = ['Cdata', 'Cmethod'] + def Cmethod(self): + pass + + cstuff = ["Cdata", "Cmethod"] self.assertEqual(interesting(dir(C)), cstuff) c = C() @@ -2533,37 +3005,46 @@ def Cmethod(self): pass c.cdata = 2 c.cmethod = lambda self: 0 - self.assertEqual(interesting(dir(c)), cstuff + ['cdata', 'cmethod']) + self.assertEqual(interesting(dir(c)), cstuff + ["cdata", "cmethod"]) ## self.assertIn('__self__', dir(c.Cmethod)) class A(C): Adata = 1 - def Amethod(self): pass - astuff = ['Adata', 'Amethod'] + cstuff + def Amethod(self): + pass + + astuff = ["Adata", "Amethod"] + cstuff self.assertEqual(interesting(dir(A)), astuff) ## self.assertIn('__self__', dir(A.Amethod)) a = A() self.assertEqual(interesting(dir(a)), astuff) a.adata = 42 a.amethod = lambda self: 3 - self.assertEqual(interesting(dir(a)), astuff + ['adata', 'amethod']) + self.assertEqual(interesting(dir(a)), astuff + ["adata", "amethod"]) ## self.assertIn('__self__', dir(a.Amethod)) # Try a module subclass. class M(type(sys)): pass + minstance = M("m") minstance.b = 2 minstance.a = 1 - default_attributes = ['__name__', '__doc__', '__package__', - '__loader__', '__spec__'] + default_attributes = [ + "__name__", + "__doc__", + "__package__", + "__loader__", + "__spec__", + ] names = [x for x in dir(minstance) if x not in default_attributes] - self.assertEqual(names, ['a', 'b']) + self.assertEqual(names, ["a", "b"]) class M2(M): def getdict(self): return "Not a dict!" + __dict__ = property(getdict) m2instance = M2("m2") @@ -2581,21 +3062,26 @@ def getdict(self): class Wrapper(object): def __init__(self, obj): self.__obj = obj + def __repr__(self): return "Wrapper(%s)" % repr(self.__obj) + def __getitem__(self, key): return Wrapper(self.__obj[key]) + def __len__(self): return len(self.__obj) + def __getattr__(self, name): return Wrapper(getattr(self.__obj, name)) class C(object): def __getclass(self): return Wrapper(type(self)) + __class__ = property(__getclass) - dir(C()) # This used to segfault + dir(C()) # This used to segfault def test_supers(self): # Testing super... @@ -2609,6 +3095,7 @@ def meth(self, a): class B(A): def __init__(self): self.__super = super(B, self) + def meth(self, a): return "B(%r)" % a + self.__super.meth(a) @@ -2617,6 +3104,7 @@ def meth(self, a): class C(A): def meth(self, a): return "C(%r)" % a + self.__super.meth(a) + C._C__super = super(C) self.assertEqual(C().meth(3), "C(3)A(3)") @@ -2641,8 +3129,9 @@ def meth(self, a): class F(E): def meth(self, a): - s = self.__super # == mysuper(F, self) + s = self.__super # == mysuper(F, self) return "F(%r)[%s]" % (a, s.__class__.__name__) + s.meth(a) + F._F__super = mysuper(F) self.assertEqual(F().meth(6), "F(6)[mysuper]E(6)D(6)C(6)B(6)A(6)") @@ -2681,11 +3170,15 @@ def meth(self, a): # (new feature in Python 2.3) class DDbase(object): - def getx(self): return 42 + def getx(self): + return 42 + x = property(getx) class DDsub(DDbase): - def getx(self): return "hello" + def getx(self): + return "hello" + x = property(getx) dd = DDsub() @@ -2701,7 +3194,7 @@ class Base(object): class Sub(Base): @classmethod def test(klass): - return super(Sub,klass).aProp + return super(Sub, klass).aProp self.assertEqual(Sub.test(), Base.aProp) @@ -2715,10 +3208,13 @@ def test_basic_inheritance(self): class hexint(int): def __repr__(self): return hex(self) + def __add__(self, other): return hexint(int.__add__(self, other)) + # (Note that overriding __radd__ doesn't work, # because the int type gets first dibs.) + self.assertEqual(repr(hexint(7) + 9), "0x10") self.assertEqual(repr(hexint(1000) + 7), "0x3ef") a = hexint(12345) @@ -2734,11 +3230,15 @@ def __add__(self, other): class octlong(int): __slots__ = [] + def __str__(self): return oct(self) + def __add__(self, other): return self.__class__(super(octlong, self).__add__(other)) + __radd__ = __add__ + self.assertEqual(str(octlong(3) + 5), "0o10") # (Note that overriding __radd__ here only seems to work # because the example uses a short int left argument.) @@ -2755,7 +3255,7 @@ def __add__(self, other): self.assertIs((a << 0).__class__, int) self.assertIs((a - 0).__class__, int) self.assertIs((a * 1).__class__, int) - self.assertIs((a ** 1).__class__, int) + self.assertIs((a**1).__class__, int) self.assertIs((a // 1).__class__, int) self.assertIs((1 * a).__class__, int) self.assertIs((a | 0).__class__, int) @@ -2769,6 +3269,7 @@ def __add__(self, other): # optimizations using octlong. class longclone(int): pass + a = longclone(1) self.assertIs((a + 0).__class__, int) self.assertIs((0 + a).__class__, int) @@ -2776,14 +3277,19 @@ class longclone(int): # Check that negative clones don't segfault a = longclone(-1) self.assertEqual(a.__dict__, {}) - self.assertEqual(int(a), -1) # self.assertTrue PyNumber_Long() copies the sign bit + self.assertEqual( + int(a), -1 + ) # self.assertTrue PyNumber_Long() copies the sign bit class precfloat(float): - __slots__ = ['prec'] + __slots__ = ["prec"] + def __init__(self, value=0.0, prec=12): self.prec = int(prec) + def __repr__(self): return "%.*g" % (self.prec, self) + self.assertEqual(repr(precfloat(1.1)), "1.1") a = precfloat(12345) self.assertEqual(a, 12345.0) @@ -2795,6 +3301,7 @@ def __repr__(self): class madcomplex(complex): def __repr__(self): return "%.17gj%+.17g" % (self.imag, self.real) + a = madcomplex(-3, 4) self.assertEqual(repr(a), "4j-3") base = complex(-3, 4) @@ -2820,6 +3327,7 @@ def __repr__(self): class madtuple(tuple): _rev = None + def rev(self): if self._rev is not None: return self._rev @@ -2827,19 +3335,20 @@ def rev(self): L.reverse() self._rev = self.__class__(L) return self._rev - a = madtuple((1,2,3,4,5,6,7,8,9,0)) - self.assertEqual(a, (1,2,3,4,5,6,7,8,9,0)) - self.assertEqual(a.rev(), madtuple((0,9,8,7,6,5,4,3,2,1))) - self.assertEqual(a.rev().rev(), madtuple((1,2,3,4,5,6,7,8,9,0))) + + a = madtuple((1, 2, 3, 4, 5, 6, 7, 8, 9, 0)) + self.assertEqual(a, (1, 2, 3, 4, 5, 6, 7, 8, 9, 0)) + self.assertEqual(a.rev(), madtuple((0, 9, 8, 7, 6, 5, 4, 3, 2, 1))) + self.assertEqual(a.rev().rev(), madtuple((1, 2, 3, 4, 5, 6, 7, 8, 9, 0))) for i in range(512): t = madtuple(range(i)) u = t.rev() v = u.rev() self.assertEqual(v, t) - a = madtuple((1,2,3,4,5)) - self.assertEqual(tuple(a), (1,2,3,4,5)) + a = madtuple((1, 2, 3, 4, 5)) + self.assertEqual(tuple(a), (1, 2, 3, 4, 5)) self.assertIs(tuple(a).__class__, tuple) - self.assertEqual(hash(a), hash((1,2,3,4,5))) + self.assertEqual(hash(a), hash((1, 2, 3, 4, 5))) self.assertIs(a[:].__class__, tuple) self.assertIs((a * 1).__class__, tuple) self.assertIs((a * 0).__class__, tuple) @@ -2855,6 +3364,7 @@ def rev(self): class madstring(str): _rev = None + def rev(self): if self._rev is not None: return self._rev @@ -2862,6 +3372,7 @@ def rev(self): L.reverse() self._rev = self.__class__("".join(L)) return self._rev + s = madstring("abcdefghijklmnopqrstuvwxyz") self.assertEqual(s, "abcdefghijklmnopqrstuvwxyz") self.assertEqual(s.rev(), madstring("zyxwvutsrqponmlkjihgfedcba")) @@ -2919,6 +3430,7 @@ def rev(self): class madunicode(str): _rev = None + def rev(self): if self._rev is not None: return self._rev @@ -2926,6 +3438,7 @@ def rev(self): L.reverse() self._rev = self.__class__("".join(L)) return self._rev + u = madunicode("ABCDEF") self.assertEqual(u, "ABCDEF") self.assertEqual(u.rev(), madunicode("FEDCBA")) @@ -2978,6 +3491,7 @@ def rev(self): class sublist(list): pass + a = sublist(range(5)) self.assertEqual(a, list(range(5))) a.append("hello") @@ -3043,30 +3557,30 @@ class sublist(list): def test_keywords(self): # Testing keyword args to basic type constructors ... - with self.assertRaisesRegex(TypeError, 'keyword argument'): + with self.assertRaisesRegex(TypeError, "keyword argument"): int(x=1) - with self.assertRaisesRegex(TypeError, 'keyword argument'): + with self.assertRaisesRegex(TypeError, "keyword argument"): float(x=2) - with self.assertRaisesRegex(TypeError, 'keyword argument'): + with self.assertRaisesRegex(TypeError, "keyword argument"): bool(x=2) self.assertEqual(complex(imag=42, real=666), complex(666, 42)) - self.assertEqual(str(object=500), '500') - self.assertEqual(str(object=b'abc', errors='strict'), 'abc') - with self.assertRaisesRegex(TypeError, 'keyword argument'): + self.assertEqual(str(object=500), "500") + self.assertEqual(str(object=b"abc", errors="strict"), "abc") + with self.assertRaisesRegex(TypeError, "keyword argument"): tuple(sequence=range(3)) - with self.assertRaisesRegex(TypeError, 'keyword argument'): + with self.assertRaisesRegex(TypeError, "keyword argument"): list(sequence=(0, 1, 2)) # note: as of Python 2.3, dict() no longer has an "items" keyword arg - for constructor in (int, float, int, complex, str, str, - tuple, list): + for constructor in (int, float, int, complex, str, str, tuple, list): try: constructor(bogus_keyword_arg=1) except TypeError: pass else: - self.fail("expected TypeError from bogus keyword argument to %r" - % constructor) + self.fail( + "expected TypeError from bogus keyword argument to %r" % constructor + ) def test_str_subclass_as_dict_key(self): # Testing a str subclass used as dict key .. @@ -3089,16 +3603,16 @@ def __eq__(self, other): def __hash__(self): return self.hashcode - self.assertEqual(cistr('ABC'), 'abc') - self.assertEqual('aBc', cistr('ABC')) - self.assertEqual(str(cistr('ABC')), 'ABC') + self.assertEqual(cistr("ABC"), "abc") + self.assertEqual("aBc", cistr("ABC")) + self.assertEqual(str(cistr("ABC")), "ABC") - d = {cistr('one'): 1, cistr('two'): 2, cistr('tHree'): 3} - self.assertEqual(d[cistr('one')], 1) - self.assertEqual(d[cistr('tWo')], 2) - self.assertEqual(d[cistr('THrEE')], 3) - self.assertIn(cistr('ONe'), d) - self.assertEqual(d.get(cistr('thrEE')), 3) + d = {cistr("one"): 1, cistr("two"): 2, cistr("tHree"): 3} + self.assertEqual(d[cistr("one")], 1) + self.assertEqual(d[cistr("tWo")], 2) + self.assertEqual(d[cistr("THrEE")], 3) + self.assertIn(cistr("ONe"), d) + self.assertEqual(d.get(cistr("thrEE")), 3) def test_classic_comparisons(self): # Testing classic comparisons... @@ -3106,39 +3620,46 @@ class classic: pass for base in (classic, int, object): + class C(base): def __init__(self, value): self.value = int(value) + def __eq__(self, other): if isinstance(other, C): return self.value == other.value if isinstance(other, int) or isinstance(other, int): return self.value == other return NotImplemented + def __ne__(self, other): if isinstance(other, C): return self.value != other.value if isinstance(other, int) or isinstance(other, int): return self.value != other return NotImplemented + def __lt__(self, other): if isinstance(other, C): return self.value < other.value if isinstance(other, int) or isinstance(other, int): return self.value < other return NotImplemented + def __le__(self, other): if isinstance(other, C): return self.value <= other.value if isinstance(other, int) or isinstance(other, int): return self.value <= other return NotImplemented + def __gt__(self, other): if isinstance(other, C): return self.value > other.value if isinstance(other, int) or isinstance(other, int): return self.value > other return NotImplemented + def __ge__(self, other): if isinstance(other, C): return self.value >= other.value @@ -3154,77 +3675,96 @@ def __ge__(self, other): for x in 1, 2, 3: for y in 1, 2, 3: for op in "<", "<=", "==", "!=", ">", ">=": - self.assertEqual(eval("c[x] %s c[y]" % op), - eval("x %s y" % op), - "x=%d, y=%d" % (x, y)) - self.assertEqual(eval("c[x] %s y" % op), - eval("x %s y" % op), - "x=%d, y=%d" % (x, y)) - self.assertEqual(eval("x %s c[y]" % op), - eval("x %s y" % op), - "x=%d, y=%d" % (x, y)) + self.assertEqual( + eval("c[x] %s c[y]" % op), + eval("x %s y" % op), + "x=%d, y=%d" % (x, y), + ) + self.assertEqual( + eval("c[x] %s y" % op), + eval("x %s y" % op), + "x=%d, y=%d" % (x, y), + ) + self.assertEqual( + eval("x %s c[y]" % op), + eval("x %s y" % op), + "x=%d, y=%d" % (x, y), + ) def test_rich_comparisons(self): # Testing rich comparisons... class Z(complex): pass + z = Z(1) - self.assertEqual(z, 1+0j) - self.assertEqual(1+0j, z) + self.assertEqual(z, 1 + 0j) + self.assertEqual(1 + 0j, z) + class ZZ(complex): def __eq__(self, other): try: return abs(self - other) <= 1e-6 except: return NotImplemented + zz = ZZ(1.0000003) - self.assertEqual(zz, 1+0j) - self.assertEqual(1+0j, zz) + self.assertEqual(zz, 1 + 0j) + self.assertEqual(1 + 0j, zz) class classic: pass + for base in (classic, int, object, list): + class C(base): def __init__(self, value): self.value = int(value) + def __cmp__(self_, other): self.fail("shouldn't call __cmp__") + def __eq__(self, other): if isinstance(other, C): return self.value == other.value if isinstance(other, int) or isinstance(other, int): return self.value == other return NotImplemented + def __ne__(self, other): if isinstance(other, C): return self.value != other.value if isinstance(other, int) or isinstance(other, int): return self.value != other return NotImplemented + def __lt__(self, other): if isinstance(other, C): return self.value < other.value if isinstance(other, int) or isinstance(other, int): return self.value < other return NotImplemented + def __le__(self, other): if isinstance(other, C): return self.value <= other.value if isinstance(other, int) or isinstance(other, int): return self.value <= other return NotImplemented + def __gt__(self, other): if isinstance(other, C): return self.value > other.value if isinstance(other, int) or isinstance(other, int): return self.value > other return NotImplemented + def __ge__(self, other): if isinstance(other, C): return self.value >= other.value if isinstance(other, int) or isinstance(other, int): return self.value >= other return NotImplemented + c1 = C(1) c2 = C(2) c3 = C(3) @@ -3233,23 +3773,31 @@ def __ge__(self, other): for x in 1, 2, 3: for y in 1, 2, 3: for op in "<", "<=", "==", "!=", ">", ">=": - self.assertEqual(eval("c[x] %s c[y]" % op), - eval("x %s y" % op), - "x=%d, y=%d" % (x, y)) - self.assertEqual(eval("c[x] %s y" % op), - eval("x %s y" % op), - "x=%d, y=%d" % (x, y)) - self.assertEqual(eval("x %s c[y]" % op), - eval("x %s y" % op), - "x=%d, y=%d" % (x, y)) + self.assertEqual( + eval("c[x] %s c[y]" % op), + eval("x %s y" % op), + "x=%d, y=%d" % (x, y), + ) + self.assertEqual( + eval("c[x] %s y" % op), + eval("x %s y" % op), + "x=%d, y=%d" % (x, y), + ) + self.assertEqual( + eval("x %s c[y]" % op), + eval("x %s y" % op), + "x=%d, y=%d" % (x, y), + ) def test_descrdoc(self): # Testing descriptor doc strings... from _io import FileIO + def check(descr, what): self.assertEqual(descr.__doc__, what) - check(FileIO.closed, "True if the file is closed") # getset descriptor - check(complex.real, "the real part of a complex number") # member descriptor + + check(FileIO.closed, "True if the file is closed") # getset descriptor + check(complex.real, "the real part of a complex number") # member descriptor def test_doc_descriptor(self): # Testing __doc__ descriptor... @@ -3257,21 +3805,31 @@ def test_doc_descriptor(self): class DocDescr(object): def __get__(self, object, otype): if object: - object = object.__class__.__name__ + ' instance' + object = object.__class__.__name__ + " instance" if otype: otype = otype.__name__ - return 'object=%s; type=%s' % (object, otype) + return "object=%s; type=%s" % (object, otype) + class NewClass: __doc__ = DocDescr() - self.assertEqual(NewClass.__doc__, 'object=None; type=NewClass') - self.assertEqual(NewClass().__doc__, 'object=NewClass instance; type=NewClass') + + self.assertEqual(NewClass.__doc__, "object=None; type=NewClass") + self.assertEqual(NewClass().__doc__, "object=NewClass instance; type=NewClass") def test_set_class(self): # Testing __class__ assignment... - class C(object): pass - class D(object): pass - class E(object): pass - class F(D, E): pass + class C(object): + pass + + class D(object): + pass + + class E(object): + pass + + class F(D, E): + pass + for cls in C, D, E, F: for cls2 in C, D, E, F: x = cls() @@ -3279,6 +3837,7 @@ class F(D, E): pass self.assertIs(x.__class__, cls2) x.__class__ = cls self.assertIs(x.__class__, cls) + def cant(x, C): try: x.__class__ = C @@ -3292,39 +3851,54 @@ def cant(x, C): pass else: self.fail("shouldn't allow del %r.__class__" % x) + cant(C(), list) cant(list(), C) cant(C(), 1) cant(C(), object) cant(object(), list) cant(list(), object) - class Int(int): __slots__ = [] + + class Int(int): + __slots__ = [] + cant(True, int) cant(2, bool) o = object() cant(o, int) cant(o, type(None)) del o + class G(object): __slots__ = ["a", "b"] + class H(object): __slots__ = ["b", "a"] + class I(object): __slots__ = ["a", "b"] + class J(object): __slots__ = ["c", "b"] + class K(object): __slots__ = ["a", "b", "d"] + class L(H): __slots__ = ["e"] + class M(I): __slots__ = ["e"] + class N(J): __slots__ = ["__weakref__"] + class P(J): __slots__ = ["__dict__"] + class Q(J): pass + class R(J): __slots__ = ["__dict__", "__weakref__"] @@ -3332,12 +3906,18 @@ class R(J): x = cls() x.a = 1 x.__class__ = cls2 - self.assertIs(x.__class__, cls2, - "assigning %r as __class__ for %r silently failed" % (cls2, x)) + self.assertIs( + x.__class__, + cls2, + "assigning %r as __class__ for %r silently failed" % (cls2, x), + ) self.assertEqual(x.a, 1) x.__class__ = cls - self.assertIs(x.__class__, cls, - "assigning %r as __class__ for %r silently failed" % (cls, x)) + self.assertIs( + x.__class__, + cls, + "assigning %r as __class__ for %r silently failed" % (cls, x), + ) self.assertEqual(x.a, 1) for cls in G, J, K, L, M, N, P, R, list, Int: for cls2 in G, J, K, L, M, N, P, R, list, Int: @@ -3349,18 +3929,23 @@ class R(J): # type gets DECREF'd. class O(object): pass + class A(object): def __del__(self): self.__class__ = O + l = [A() for x in range(100)] del l def test_set_dict(self): # Testing __dict__ assignment... - class C(object): pass + class C(object): + pass + a = C() - a.__dict__ = {'b': 1} + a.__dict__ = {"b": 1} self.assertEqual(a.b, 1) + def cant(x, dict): try: x.__dict__ = dict @@ -3368,13 +3953,15 @@ def cant(x, dict): pass else: self.fail("shouldn't allow %r.__dict__ = %r" % (x, dict)) + cant(a, None) cant(a, []) cant(a, 1) - del a.__dict__ # Deleting __dict__ is allowed + del a.__dict__ # Deleting __dict__ is allowed class Base(object): pass + def verify_dict_readonly(x): """ x has to be an instance of a class inheriting from Base. @@ -3397,12 +3984,16 @@ def verify_dict_readonly(x): # Classes don't allow __dict__ assignment and have readonly dicts class Meta1(type, Base): pass + class Meta2(Base, type): pass + class D(object, metaclass=Meta1): pass + class E(object, metaclass=Meta2): pass + for cls in C, D, E: verify_dict_readonly(cls) class_dict = cls.__dict__ @@ -3416,8 +4007,10 @@ class E(object, metaclass=Meta2): # Modules also disallow __dict__ assignment class Module1(types.ModuleType, Base): pass + class Module2(Base, types.ModuleType): pass + for ModuleType in Module1, Module2: mod = ModuleType("spam") verify_dict_readonly(mod) @@ -3434,10 +4027,13 @@ def can_delete_dict(e): return False else: return True + class Exception1(Exception, Base): pass + class Exception2(Base, Exception): pass + for ExceptionType in Exception, Exception1, Exception2: e = ExceptionType() e.__dict__ = {"a": 1} @@ -3449,14 +4045,18 @@ def test_binary_operator_override(self): class I(int): def __repr__(self): return "I(%r)" % int(self) + def __add__(self, other): return I(int(self) + int(other)) + __radd__ = __add__ + def __pow__(self, other, mod=None): if mod is None: return I(pow(int(self), int(other))) else: return I(pow(int(self), int(other), int(mod))) + def __rpow__(self, other, mod=None): if mod is None: return I(pow(int(other), int(self), mod)) @@ -3470,6 +4070,7 @@ def __rpow__(self, other, mod=None): self.assertEqual(repr(2 ** I(3)), "I(8)") self.assertEqual(repr(I(2) ** 3), "I(8)") self.assertEqual(repr(pow(I(2), I(3), I(5))), "I(3)") + class S(str): def __eq__(self, other): return self.lower() == other.lower() @@ -3478,14 +4079,18 @@ def test_subclass_propagation(self): # Testing propagation of slot functions to subclasses... class A(object): pass + class B(A): pass + class C(A): pass + class D(B, C): pass + d = D() - orig_hash = hash(d) # related to id(d) in platform-dependent ways + orig_hash = hash(d) # related to id(d) in platform-dependent ways A.__hash__ = lambda self: 42 self.assertEqual(hash(d), 42) C.__hash__ = lambda self: 314 @@ -3514,17 +4119,21 @@ class D(B, C): d.bar = 42 self.assertEqual(d.foo, 42) self.assertEqual(d.bar, 42) + def __getattribute__(self, name): if name == "foo": return 24 return object.__getattribute__(self, name) + A.__getattribute__ = __getattribute__ self.assertEqual(d.foo, 24) self.assertEqual(d.bar, 42) + def __getattr__(self, name): if name in ("spam", "foo", "bar"): return "hello" raise AttributeError(name) + B.__getattr__ = __getattr__ self.assertEqual(d.spam, "hello") self.assertEqual(d.foo, 24) @@ -3545,11 +4154,13 @@ def __getattr__(self, name): # Test a nasty bug in recurse_down_subclasses() class A(object): pass + class B(A): pass + del B support.gc_collect() - A.__setitem__ = lambda *a: None # crash + A.__setitem__ = lambda *a: None # crash def test_buffer_inheritance(self): # Testing that buffer interface is inherited ... @@ -3559,7 +4170,8 @@ def test_buffer_inheritance(self): class MyBytes(bytes): pass - base = b'abc' + + base = b"abc" m = MyBytes(base) # b2a_hex uses the buffer interface to get its argument's value, via # PyArg_ParseTuple 't#' code. @@ -3567,10 +4179,11 @@ class MyBytes(bytes): class MyInt(int): pass + m = MyInt(42) try: binascii.b2a_hex(m) - self.fail('subclass of int should not have a buffer interface') + self.fail("subclass of int should not have a buffer interface") except TypeError: pass @@ -3580,38 +4193,42 @@ def test_str_of_str_subclass(self): class octetstring(str): def __str__(self): - return binascii.b2a_hex(self.encode('ascii')).decode("ascii") + return binascii.b2a_hex(self.encode("ascii")).decode("ascii") + def __repr__(self): return self + " repr" - o = octetstring('A') + o = octetstring("A") self.assertEqual(type(o), octetstring) self.assertEqual(type(str(o)), str) self.assertEqual(type(repr(o)), str) self.assertEqual(ord(o), 0x41) - self.assertEqual(str(o), '41') - self.assertEqual(repr(o), 'A repr') - self.assertEqual(o.__str__(), '41') - self.assertEqual(o.__repr__(), 'A repr') + self.assertEqual(str(o), "41") + self.assertEqual(repr(o), "A repr") + self.assertEqual(o.__str__(), "41") + self.assertEqual(o.__repr__(), "A repr") def test_repr_with_module_str_subclass(self): # gh-98783 class StrSub(str): pass + class Some: pass - Some.__module__ = StrSub('example') + + Some.__module__ = StrSub("example") self.assertIsInstance(repr(Some), str) # should not crash self.assertIsInstance(repr(Some()), str) # should not crash def test_keyword_arguments(self): # Testing keyword arguments to __init__, __call__... - def f(a): return a + def f(a): + return a + self.assertEqual(f.__call__(a=42), 42) ba = bytearray() - bytearray.__init__(ba, 'abc\xbd\u20ac', - encoding='latin1', errors='replace') - self.assertEqual(ba, b'abc\xbd?') + bytearray.__init__(ba, "abc\xbd\u20ac", encoding="latin1", errors="replace") + self.assertEqual(ba, b"abc\xbd?") def test_recursive_call(self): # Testing recursive __call__() by setting to instance of class... @@ -3625,26 +4242,34 @@ class A(object): def test_delete_hook(self): # Testing __del__ hook... log = [] + class C(object): def __del__(self): log.append(1) + c = C() self.assertEqual(log, []) del c support.gc_collect() self.assertEqual(log, [1]) - class D(object): pass + class D(object): + pass + d = D() - try: del d[0] - except TypeError: pass - else: self.fail("invalid del() didn't raise TypeError") + try: + del d[0] + except TypeError: + pass + else: + self.fail("invalid del() didn't raise TypeError") def test_hash_inheritance(self): # Testing hash of mutable subclasses... class mydict(dict): pass + d = mydict() try: hash(d) @@ -3655,6 +4280,7 @@ class mydict(dict): class mylist(list): pass + d = mylist() try: hash(d) @@ -3664,70 +4290,102 @@ class mylist(list): self.fail("hash() of list subclass should fail") def test_str_operations(self): - try: 'a' + 5 - except TypeError: pass - else: self.fail("'' + 5 doesn't raise TypeError") + try: + "a" + 5 + except TypeError: + pass + else: + self.fail("'' + 5 doesn't raise TypeError") - try: ''.split('') - except ValueError: pass - else: self.fail("''.split('') doesn't raise ValueError") + try: + "".split("") + except ValueError: + pass + else: + self.fail("''.split('') doesn't raise ValueError") - try: ''.join([0]) - except TypeError: pass - else: self.fail("''.join([0]) doesn't raise TypeError") + try: + "".join([0]) + except TypeError: + pass + else: + self.fail("''.join([0]) doesn't raise TypeError") - try: ''.rindex('5') - except ValueError: pass - else: self.fail("''.rindex('5') doesn't raise ValueError") + try: + "".rindex("5") + except ValueError: + pass + else: + self.fail("''.rindex('5') doesn't raise ValueError") - try: '%(n)s' % None - except TypeError: pass - else: self.fail("'%(n)s' % None doesn't raise TypeError") + try: + "%(n)s" % None + except TypeError: + pass + else: + self.fail("'%(n)s' % None doesn't raise TypeError") - try: '%(n' % {} - except ValueError: pass - else: self.fail("'%(n' % {} '' doesn't raise ValueError") + try: + "%(n" % {} + except ValueError: + pass + else: + self.fail("'%(n' % {} '' doesn't raise ValueError") - try: '%*s' % ('abc') - except TypeError: pass - else: self.fail("'%*s' % ('abc') doesn't raise TypeError") + try: + "%*s" % ("abc") + except TypeError: + pass + else: + self.fail("'%*s' % ('abc') doesn't raise TypeError") - try: '%*.*s' % ('abc', 5) - except TypeError: pass - else: self.fail("'%*.*s' % ('abc', 5) doesn't raise TypeError") + try: + "%*.*s" % ("abc", 5) + except TypeError: + pass + else: + self.fail("'%*.*s' % ('abc', 5) doesn't raise TypeError") - try: '%s' % (1, 2) - except TypeError: pass - else: self.fail("'%s' % (1, 2) doesn't raise TypeError") + try: + "%s" % (1, 2) + except TypeError: + pass + else: + self.fail("'%s' % (1, 2) doesn't raise TypeError") - try: '%' % None - except ValueError: pass - else: self.fail("'%' % None doesn't raise ValueError") + try: + "%" % None + except ValueError: + pass + else: + self.fail("'%' % None doesn't raise ValueError") - self.assertEqual('534253'.isdigit(), 1) - self.assertEqual('534253x'.isdigit(), 0) - self.assertEqual('%c' % 5, '\x05') - self.assertEqual('%c' % '5', '5') + self.assertEqual("534253".isdigit(), 1) + self.assertEqual("534253x".isdigit(), 0) + self.assertEqual("%c" % 5, "\x05") + self.assertEqual("%c" % "5", "5") def test_deepcopy_recursive(self): # Testing deepcopy of recursive objects... class Node: pass + a = Node() b = Node() a.b = b b.a = a - z = deepcopy(a) # This blew up before + z = deepcopy(a) # This blew up before def test_uninitialized_modules(self): # Testing uninitialized module objects... from types import ModuleType as M + m = M.__new__(M) str(m) self.assertNotHasAttr(m, "__name__") self.assertNotHasAttr(m, "__file__") self.assertNotHasAttr(m, "foo") - self.assertFalse(m.__dict__) # None or {} are both reasonable answers + self.assertFalse(m.__dict__) # None or {} are both reasonable answers m.foo = 1 self.assertEqual(m.__dict__, {"foo": 1}) @@ -3735,12 +4393,17 @@ def test_funny_new(self): # Testing __new__ returning something unexpected... class C(object): def __new__(cls, arg): - if isinstance(arg, str): return [1, 2, 3] - elif isinstance(arg, int): return object.__new__(D) - else: return object.__new__(cls) + if isinstance(arg, str): + return [1, 2, 3] + elif isinstance(arg, int): + return object.__new__(D) + else: + return object.__new__(cls) + class D(C): def __init__(self, arg): self.foo = arg + self.assertEqual(C("1"), [1, 2, 3]) self.assertEqual(D("1"), [1, 2, 3]) d = D(None) @@ -3756,18 +4419,24 @@ class C(object): @staticmethod def __new__(*args): return args + self.assertEqual(C(1, 2), (C, 1, 2)) + class D(C): pass + self.assertEqual(D(1, 2), (D, 1, 2)) class C(object): @classmethod def __new__(*args): return args + self.assertEqual(C(1, 2), (C, C, 1, 2)) + class D(C): pass + self.assertEqual(D(1, 2), (D, D, 1, 2)) def test_imul_bug(self): @@ -3776,6 +4445,7 @@ def test_imul_bug(self): class C(object): def __imul__(self, other): return (self, other) + x = C() y = x y *= 1.0 @@ -3787,8 +4457,8 @@ def __imul__(self, other): y *= 3 self.assertEqual(y, (x, 3)) y = x - y *= 1<<100 - self.assertEqual(y, (x, 1<<100)) + y *= 1 << 100 + self.assertEqual(y, (x, 1 << 100)) y = x y *= None self.assertEqual(y, (x, None)) @@ -3799,19 +4469,25 @@ def __imul__(self, other): def test_copy_setstate(self): # Testing that copy.*copy() correctly uses __setstate__... import copy + class C(object): def __init__(self, foo=None): self.foo = foo self.__foo = foo + def setfoo(self, foo=None): self.foo = foo + def getfoo(self): return self.__foo + def __getstate__(self): return [self.foo] + def __setstate__(self_, lst): self.assertEqual(len(lst), 1) self_.__foo = self_.foo = lst[0] + a = C(42) a.setfoo(24) self.assertEqual(a.foo, 24) @@ -3830,42 +4506,48 @@ def test_slices(self): self.assertEqual("hello"[:4], "hell") self.assertEqual("hello"[slice(4)], "hell") self.assertEqual(str.__getitem__("hello", slice(4)), "hell") + class S(str): def __getitem__(self, x): return str.__getitem__(self, x) + self.assertEqual(S("hello")[:4], "hell") self.assertEqual(S("hello")[slice(4)], "hell") self.assertEqual(S("hello").__getitem__(slice(4)), "hell") # Tuples - self.assertEqual((1,2,3)[:2], (1,2)) - self.assertEqual((1,2,3)[slice(2)], (1,2)) - self.assertEqual(tuple.__getitem__((1,2,3), slice(2)), (1,2)) + self.assertEqual((1, 2, 3)[:2], (1, 2)) + self.assertEqual((1, 2, 3)[slice(2)], (1, 2)) + self.assertEqual(tuple.__getitem__((1, 2, 3), slice(2)), (1, 2)) + class T(tuple): def __getitem__(self, x): return tuple.__getitem__(self, x) - self.assertEqual(T((1,2,3))[:2], (1,2)) - self.assertEqual(T((1,2,3))[slice(2)], (1,2)) - self.assertEqual(T((1,2,3)).__getitem__(slice(2)), (1,2)) + + self.assertEqual(T((1, 2, 3))[:2], (1, 2)) + self.assertEqual(T((1, 2, 3))[slice(2)], (1, 2)) + self.assertEqual(T((1, 2, 3)).__getitem__(slice(2)), (1, 2)) # Lists - self.assertEqual([1,2,3][:2], [1,2]) - self.assertEqual([1,2,3][slice(2)], [1,2]) - self.assertEqual(list.__getitem__([1,2,3], slice(2)), [1,2]) + self.assertEqual([1, 2, 3][:2], [1, 2]) + self.assertEqual([1, 2, 3][slice(2)], [1, 2]) + self.assertEqual(list.__getitem__([1, 2, 3], slice(2)), [1, 2]) + class L(list): def __getitem__(self, x): return list.__getitem__(self, x) - self.assertEqual(L([1,2,3])[:2], [1,2]) - self.assertEqual(L([1,2,3])[slice(2)], [1,2]) - self.assertEqual(L([1,2,3]).__getitem__(slice(2)), [1,2]) + + self.assertEqual(L([1, 2, 3])[:2], [1, 2]) + self.assertEqual(L([1, 2, 3])[slice(2)], [1, 2]) + self.assertEqual(L([1, 2, 3]).__getitem__(slice(2)), [1, 2]) # Now do lists and __setitem__ - a = L([1,2,3]) - a[slice(1, 3)] = [3,2] - self.assertEqual(a, [1,3,2]) - a[slice(0, 2, 1)] = [3,1] - self.assertEqual(a, [3,1,2]) - a.__setitem__(slice(1, 3), [2,1]) - self.assertEqual(a, [3,2,1]) - a.__setitem__(slice(0, 2, 1), [2,3]) - self.assertEqual(a, [2,3,1]) + a = L([1, 2, 3]) + a[slice(1, 3)] = [3, 2] + self.assertEqual(a, [1, 3, 2]) + a[slice(0, 2, 1)] = [3, 1] + self.assertEqual(a, [3, 1, 2]) + a.__setitem__(slice(1, 3), [2, 1]) + self.assertEqual(a, [3, 2, 1]) + a.__setitem__(slice(0, 2, 1), [2, 3]) + self.assertEqual(a, [2, 3, 1]) def test_subtype_resurrection(self): # Testing resurrection of new-style instance... @@ -3896,9 +4578,11 @@ def test_slots_trash(self): # Testing slot trash... # Deallocating deeply nested slotted trash caused stack overflows class trash(object): - __slots__ = ['x'] + __slots__ = ["x"] + def __init__(self, x): self.x = x + o = None for i in range(50000): o = trash(o) @@ -3907,15 +4591,18 @@ def __init__(self, x): def test_slots_multiple_inheritance(self): # SF bug 575229, multiple inheritance w/ slots dumps core class A(object): - __slots__=() + __slots__ = () + class B(object): pass - class C(A,B) : - __slots__=() + + class C(A, B): + __slots__ = () + if support.check_impl_detail(): self.assertEqual(C.__basicsize__, B.__basicsize__) - self.assertHasAttr(C, '__dict__') - self.assertHasAttr(C, '__weakref__') + self.assertHasAttr(C, "__dict__") + self.assertHasAttr(C, "__weakref__") C().x = 2 def test_rmul(self): @@ -3924,13 +4611,15 @@ def test_rmul(self): class C(object): def __mul__(self, other): return "mul" + def __rmul__(self, other): return "rmul" + a = C() - self.assertEqual(a*2, "mul") - self.assertEqual(a*2.2, "mul") - self.assertEqual(2*a, "rmul") - self.assertEqual(2.2*a, "rmul") + self.assertEqual(a * 2, "mul") + self.assertEqual(a * 2.2, "mul") + self.assertEqual(2 * a, "rmul") + self.assertEqual(2.2 * a, "rmul") def test_ipow(self): # Testing correct invocation of __ipow__... @@ -3938,6 +4627,7 @@ def test_ipow(self): class C(object): def __ipow__(self, other): pass + a = C() a **= 2 @@ -3953,6 +4643,7 @@ def __rpow__(self, other): class C(A): def __pow__(self, other): return 2 + a = A() b = B() c = C() @@ -3977,11 +4668,11 @@ def test_ipow_exception_text(self): x = None with self.assertRaises(TypeError) as cm: x **= 2 - self.assertIn('unsupported operand type(s) for **=', str(cm.exception)) + self.assertIn("unsupported operand type(s) for **=", str(cm.exception)) with self.assertRaises(TypeError) as cm: - y = x ** 2 - self.assertIn('unsupported operand type(s) for **', str(cm.exception)) + y = x**2 + self.assertIn("unsupported operand type(s) for **", str(cm.exception)) def test_mutable_bases(self): # Testing mutable bases... @@ -3989,18 +4680,23 @@ def test_mutable_bases(self): # stuff that should work: class C(object): pass + class C2(object): def __getattribute__(self, attr): - if attr == 'a': + if attr == "a": return 2 else: return super(C2, self).__getattribute__(attr) + def meth(self): return 1 + class D(C): pass + class E(D): pass + d = D() e = E() D.__bases__ = (C,) @@ -4051,8 +4747,9 @@ class E(D): def test_builtin_bases(self): # Make sure all the builtin types can have their base queried without # segfaulting. See issue #5787. - builtin_types = [tp for tp in builtins.__dict__.values() - if isinstance(tp, type)] + builtin_types = [ + tp for tp in builtins.__dict__.values() if isinstance(tp, type) + ] for tp in builtin_types: object.__getattribute__(tp, "__bases__") if tp is not object: @@ -4094,27 +4791,38 @@ class D(C): def test_unsubclassable_types(self): with self.assertRaises(TypeError): + class X(type(None)): pass + with self.assertRaises(TypeError): + class X(object, type(None)): pass + with self.assertRaises(TypeError): + class X(type(None), object): pass + class O(object): pass + with self.assertRaises(TypeError): + class X(O, type(None)): pass + with self.assertRaises(TypeError): + class X(type(None), O): pass class X(object): pass + with self.assertRaises(TypeError): - X.__bases__ = type(None), + X.__bases__ = (type(None),) with self.assertRaises(TypeError): X.__bases__ = object, type(None) with self.assertRaises(TypeError): @@ -4130,6 +4838,7 @@ class WorkOnce(type): def __new__(self, name, bases, ns): self.flag = 0 return super(WorkOnce, self).__new__(WorkOnce, name, bases, ns) + def mro(self): if self.flag > 0: raise RuntimeError("bozo") @@ -4210,11 +4919,11 @@ class C(object): # C.__module__ could be 'test_descr' or '__main__' mod = C.__module__ - C.__name__ = 'D' - self.assertEqual((C.__module__, C.__name__), (mod, 'D')) + C.__name__ = "D" + self.assertEqual((C.__module__, C.__name__), (mod, "D")) - C.__name__ = 'D.E' - self.assertEqual((C.__module__, C.__name__), (mod, 'D.E')) + C.__name__ = "D.E" + self.assertEqual((C.__module__, C.__name__), (mod, "D.E")) def test_evil_type_name(self): # A badly placed Py_DECREF in type_set_name led to arbitrary code @@ -4241,6 +4950,7 @@ def test_subclass_right_op(self): class B(int): def __floordiv__(self, other): return "B.__floordiv__" + def __rfloordiv__(self, other): return "B.__rfloordiv__" @@ -4252,6 +4962,7 @@ def __rfloordiv__(self, other): class C(object): def __floordiv__(self, other): return "C.__floordiv__" + def __rfloordiv__(self, other): return "C.__rfloordiv__" @@ -4263,6 +4974,7 @@ def __rfloordiv__(self, other): class D(C): def __floordiv__(self, other): return "D.__floordiv__" + def __rfloordiv__(self, other): return "D.__rfloordiv__" @@ -4279,7 +4991,7 @@ class E(C): self.assertEqual(E() // 1, "C.__floordiv__") self.assertEqual(1 // E(), "C.__rfloordiv__") self.assertEqual(E() // C(), "C.__floordiv__") - self.assertEqual(C() // E(), "C.__floordiv__") # This one would fail + self.assertEqual(C() // E(), "C.__floordiv__") # This one would fail @support.impl_detail("testing an internal kind of method object") def test_meth_class_get(self): @@ -4330,45 +5042,55 @@ def test_isinst_isclass(self): class Proxy(object): def __init__(self, obj): self.__obj = obj + def __getattribute__(self, name): if name.startswith("_Proxy__"): return object.__getattribute__(self, name) else: return getattr(self.__obj, name) + # Test with a classic class class C: pass + a = C() pa = Proxy(a) self.assertIsInstance(a, C) # Baseline - self.assertIsInstance(pa, C) # Test + self.assertIsInstance(pa, C) # Test + # Test with a classic subclass class D(C): pass + a = D() pa = Proxy(a) self.assertIsInstance(a, C) # Baseline - self.assertIsInstance(pa, C) # Test + self.assertIsInstance(pa, C) # Test + # Test with a new-style class class C(object): pass + a = C() pa = Proxy(a) self.assertIsInstance(a, C) # Baseline - self.assertIsInstance(pa, C) # Test + self.assertIsInstance(pa, C) # Test + # Test with a new-style subclass class D(C): pass + a = D() pa = Proxy(a) self.assertIsInstance(a, C) # Baseline - self.assertIsInstance(pa, C) # Test + self.assertIsInstance(pa, C) # Test def test_proxy_super(self): # Testing super() for a proxy object... class Proxy(object): def __init__(self, obj): self.__obj = obj + def __getattribute__(self, name): if name.startswith("_Proxy__"): return object.__getattribute__(self, name) @@ -4413,7 +5135,7 @@ class B: class C(B, A): pass - obj = C('D', (object,), {}) + obj = C("D", (object,), {}) try: obj.test = True except TypeError: @@ -4430,7 +5152,7 @@ class B: class C(B, A): pass - obj = C('D', (object,), {}) + obj = C("D", (object,), {}) try: obj.test = True except TypeError: @@ -4457,10 +5179,10 @@ class Oops(object): o.whatever = Provoker(o) del o - @support.requires_resource('cpu') + @support.requires_resource("cpu") def test_wrapper_segfault(self): # SF 927248: deeply nested wrappers could cause stack overflow - f = lambda:None + f = lambda: None for i in range(1000000): f = f.__call__ f = None @@ -4485,7 +5207,8 @@ def test_vicious_descriptor_nonsense(self): class Evil(object): def __hash__(self): - return hash('attr') + return hash("attr") + def __eq__(self, other): try: del C.attr @@ -4507,13 +5230,14 @@ class C(object): self.assertEqual(c.attr, 1) # this makes a crash more likely: support.gc_collect() - self.assertNotHasAttr(c, 'attr') + self.assertNotHasAttr(c, "attr") def test_init(self): # SF 1155938 class Foo(object): def __init__(self): return 10 + try: Foo() except TypeError: @@ -4542,7 +5266,7 @@ def test_method_wrapper(self): self.assertFalse(l.__add__ == l.__mul__) self.assertTrue(l.__add__ != l.__mul__) self.assertNotOrderable(l.__add__, l.__add__) - self.assertEqual(l.__add__.__name__, '__add__') + self.assertEqual(l.__add__.__name__, "__add__") self.assertIs(l.__add__.__self__, l) self.assertIs(l.__add__.__objclass__, list) self.assertEqual(l.__add__.__doc__, list.__add__.__doc__) @@ -4561,7 +5285,7 @@ def test_builtin_function_or_method(self): self.assertFalse(l.append == l.pop) self.assertTrue(l.append != l.pop) self.assertNotOrderable(l.append, l.append) - self.assertEqual(l.append.__name__, 'append') + self.assertEqual(l.append.__name__, "append") self.assertIs(l.append.__self__, l) # self.assertIs(l.append.__objclass__, list) --- could be added? self.assertEqual(l.append.__doc__, list.append.__doc__) @@ -4575,7 +5299,7 @@ def test_special_unbound_method_types(self): self.assertFalse(list.__add__ == list.__mul__) self.assertTrue(list.__add__ != list.__mul__) self.assertNotOrderable(list.__add__, list.__add__) - self.assertEqual(list.__add__.__name__, '__add__') + self.assertEqual(list.__add__.__name__, "__add__") self.assertIs(list.__add__.__objclass__, list) # Testing objects of ... @@ -4584,7 +5308,7 @@ def test_special_unbound_method_types(self): self.assertFalse(list.append == list.pop) self.assertTrue(list.append != list.pop) self.assertNotOrderable(list.append, list.append) - self.assertEqual(list.append.__name__, 'append') + self.assertEqual(list.append.__name__, "append") self.assertIs(list.append.__objclass__, list) def test_not_implemented(self): @@ -4597,33 +5321,34 @@ def specialmethod(self, other): def check(expr, x, y): try: - exec(expr, {'x': x, 'y': y, 'operator': operator}) + exec(expr, {"x": x, "y": y, "operator": operator}) except TypeError: pass else: self.fail("no TypeError from %r" % (expr,)) - N1 = sys.maxsize + 1 # might trigger OverflowErrors instead of - # TypeErrors - N2 = sys.maxsize # if sizeof(int) < sizeof(long), might trigger - # ValueErrors instead of TypeErrors + N1 = sys.maxsize + 1 # might trigger OverflowErrors instead of + # TypeErrors + N2 = sys.maxsize # if sizeof(int) < sizeof(long), might trigger + # ValueErrors instead of TypeErrors for name, expr, iexpr in [ - ('__add__', 'x + y', 'x += y'), - ('__sub__', 'x - y', 'x -= y'), - ('__mul__', 'x * y', 'x *= y'), - ('__matmul__', 'x @ y', 'x @= y'), - ('__truediv__', 'x / y', 'x /= y'), - ('__floordiv__', 'x // y', 'x //= y'), - ('__mod__', 'x % y', 'x %= y'), - ('__divmod__', 'divmod(x, y)', None), - ('__pow__', 'x ** y', 'x **= y'), - ('__lshift__', 'x << y', 'x <<= y'), - ('__rshift__', 'x >> y', 'x >>= y'), - ('__and__', 'x & y', 'x &= y'), - ('__or__', 'x | y', 'x |= y'), - ('__xor__', 'x ^ y', 'x ^= y')]: - rname = '__r' + name[2:] - A = type('A', (), {name: specialmethod}) + ("__add__", "x + y", "x += y"), + ("__sub__", "x - y", "x -= y"), + ("__mul__", "x * y", "x *= y"), + ("__matmul__", "x @ y", "x @= y"), + ("__truediv__", "x / y", "x /= y"), + ("__floordiv__", "x // y", "x //= y"), + ("__mod__", "x % y", "x %= y"), + ("__divmod__", "divmod(x, y)", None), + ("__pow__", "x ** y", "x **= y"), + ("__lshift__", "x << y", "x <<= y"), + ("__rshift__", "x >> y", "x >>= y"), + ("__and__", "x & y", "x &= y"), + ("__or__", "x | y", "x |= y"), + ("__xor__", "x ^ y", "x ^= y"), + ]: + rname = "__r" + name[2:] + A = type("A", (), {name: specialmethod}) a = A() check(expr, a, a) check(expr, a, N1) @@ -4632,8 +5357,8 @@ def check(expr, x, y): check(iexpr, a, a) check(iexpr, a, N1) check(iexpr, a, N2) - iname = '__i' + name[2:] - C = type('C', (), {iname: specialmethod}) + iname = "__i" + name[2:] + C = type("C", (), {iname: specialmethod}) c = C() check(iexpr, c, a) check(iexpr, c, N1) @@ -4656,12 +5381,12 @@ def test_set_and_no_get(self): # See # http://mail.python.org/pipermail/python-dev/2010-January/095637.html class Descr(object): - def __init__(self, name): self.name = name def __set__(self, obj, value): obj.__dict__[self.name] = value + descr = Descr("a") class X(object): @@ -4675,8 +5400,10 @@ class X(object): # Also check type_getattro for correctness. class Meta(type): pass + class X(metaclass=Meta): pass + X.a = 42 Meta.a = Descr("a") self.assertEqual(X.a, 42) @@ -4686,17 +5413,22 @@ def test_getattr_hooks(self): class Descriptor(object): counter = 0 + def __get__(self, obj, objtype=None): def getter(name): self.counter += 1 raise AttributeError(name) + return getter descr = Descriptor() + class A(object): __getattribute__ = descr + class B(object): __getattr__ = descr + class C(object): __getattribute__ = descr __getattr__ = descr @@ -4712,6 +5444,7 @@ class EvilGetattribute(object): # This used to segfault def __getattr__(self, name): raise AttributeError(name) + def __getattribute__(self, name): del EvilGetattribute.__getattr__ for i in range(5): @@ -4726,11 +5459,15 @@ def test_type___getattribute__(self): def test_abstractmethods(self): # type pretends not to have __abstractmethods__. self.assertRaises(AttributeError, getattr, type, "__abstractmethods__") + class meta(type): pass + self.assertRaises(AttributeError, getattr, meta, "__abstractmethods__") + class X(object): pass + with self.assertRaises(AttributeError): del X.__abstractmethods__ @@ -4754,6 +5491,7 @@ def test_specialized_method_calls_check_types(self): # https://github.com/python/cpython/issues/92063 class Thing: pass + thing = Thing() for i in range(20): with self.assertRaises(TypeError): @@ -4772,6 +5510,7 @@ class Thing: # CALL_METHOD_DESCRIPTOR_FAST str.strip(thing) from collections import deque + for i in range(20): with self.assertRaises(TypeError): # CALL_METHOD_DESCRIPTOR_O @@ -4782,6 +5521,7 @@ def test_repr_as_str(self): # __repr__. class Foo: pass + Foo.__repr__ = Foo.__str__ foo = Foo() self.assertRaises(RecursionError, str, foo) @@ -4791,6 +5531,7 @@ def test_mixing_slot_wrappers(self): class X(dict): __setattr__ = dict.__setitem__ __neg__ = dict.copy + x = X() x.y = 42 self.assertEqual(x["y"], 42) @@ -4802,6 +5543,7 @@ def test_wrong_class_slot_wrapper(self): class A(int): __eq__ = str.__eq__ __add__ = str.__add__ + a = A() with self.assertRaises(TypeError): a == a @@ -4810,68 +5552,77 @@ class A(int): def test_slot_shadows_class_variable(self): with self.assertRaises(ValueError) as cm: + class X: __slots__ = ["foo"] foo = None + m = str(cm.exception) self.assertEqual("'foo' in __slots__ conflicts with class variable", m) def test_set_doc(self): class X: "elephant" + X.__doc__ = "banana" self.assertEqual(X.__doc__, "banana") with self.assertRaises(TypeError) as cm: type(list).__dict__["__doc__"].__set__(list, "blah") - self.assertIn("cannot set '__doc__' attribute of immutable type 'list'", str(cm.exception)) + self.assertIn( + "cannot set '__doc__' attribute of immutable type 'list'", str(cm.exception) + ) with self.assertRaises(TypeError) as cm: type(X).__dict__["__doc__"].__delete__(X) - self.assertIn("cannot delete '__doc__' attribute of immutable type 'X'", str(cm.exception)) + self.assertIn( + "cannot delete '__doc__' attribute of immutable type 'X'", str(cm.exception) + ) self.assertEqual(X.__doc__, "banana") def test_qualname(self): descriptors = [str.lower, complex.real, float.real, int.__add__] - types = ['method', 'member', 'getset', 'wrapper'] + types = ["method", "member", "getset", "wrapper"] # make sure we have an example of each type of descriptor for d, n in zip(descriptors, types): - self.assertEqual(type(d).__name__, n + '_descriptor') + self.assertEqual(type(d).__name__, n + "_descriptor") for d in descriptors: - qualname = d.__objclass__.__qualname__ + '.' + d.__name__ + qualname = d.__objclass__.__qualname__ + "." + d.__name__ self.assertEqual(d.__qualname__, qualname) - self.assertEqual(str.lower.__qualname__, 'str.lower') - self.assertEqual(complex.real.__qualname__, 'complex.real') - self.assertEqual(float.real.__qualname__, 'float.real') - self.assertEqual(int.__add__.__qualname__, 'int.__add__') + self.assertEqual(str.lower.__qualname__, "str.lower") + self.assertEqual(complex.real.__qualname__, "complex.real") + self.assertEqual(float.real.__qualname__, "float.real") + self.assertEqual(int.__add__.__qualname__, "int.__add__") class X: pass + with self.assertRaises(TypeError): del X.__qualname__ - self.assertRaises(TypeError, type.__dict__['__qualname__'].__set__, - str, 'Oink') + self.assertRaises(TypeError, type.__dict__["__qualname__"].__set__, str, "Oink") global Y + class Y: class Inside: pass - self.assertEqual(Y.__qualname__, 'Y') - self.assertEqual(Y.Inside.__qualname__, 'Y.Inside') + + self.assertEqual(Y.__qualname__, "Y") + self.assertEqual(Y.Inside.__qualname__, "Y.Inside") def test_qualname_dict(self): - ns = {'__qualname__': 'some.name'} - tp = type('Foo', (), ns) - self.assertEqual(tp.__qualname__, 'some.name') - self.assertNotIn('__qualname__', tp.__dict__) - self.assertEqual(ns, {'__qualname__': 'some.name'}) + ns = {"__qualname__": "some.name"} + tp = type("Foo", (), ns) + self.assertEqual(tp.__qualname__, "some.name") + self.assertNotIn("__qualname__", tp.__dict__) + self.assertEqual(ns, {"__qualname__": "some.name"}) - ns = {'__qualname__': 1} - self.assertRaises(TypeError, type, 'Foo', (), ns) + ns = {"__qualname__": 1} + self.assertRaises(TypeError, type, "Foo", (), ns) def test_cycle_through_dict(self): # See bug #1469629 @@ -4879,6 +5630,7 @@ class X(dict): def __init__(self): dict.__init__(self) self.__dict__ = self + x = X() x.attr = 42 wr = weakref.ref(x) @@ -4892,16 +5644,21 @@ def test_object_new_and_init_with_parameters(self): # See issue #1683368 class OverrideNeither: pass + self.assertRaises(TypeError, OverrideNeither, 1) self.assertRaises(TypeError, OverrideNeither, kw=1) + class OverrideNew: def __new__(cls, foo, kw=0, *args, **kwds): return object.__new__(cls, *args, **kwds) + class OverrideInit: def __init__(self, foo, kw=0, *args, **kwargs): return object.__init__(self, *args, **kwargs) + class OverrideBoth(OverrideNew, OverrideInit): pass + for case in OverrideNew, OverrideInit, OverrideBoth: case(1) case(1, kw=2) @@ -4911,8 +5668,10 @@ class OverrideBoth(OverrideNew, OverrideInit): def test_subclassing_does_not_duplicate_dict_descriptors(self): class Base: pass + class Sub(Base): pass + self.assertIn("__dict__", Base.__dict__) self.assertNotIn("__dict__", Sub.__dict__) @@ -4920,58 +5679,73 @@ def test_bound_method_repr(self): class Foo: def method(self): pass - self.assertRegex(repr(Foo().method), - r">") + self.assertRegex( + repr(Foo().method), r">" + ) class Base: def method(self): pass + class Derived1(Base): pass + class Derived2(Base): def method(self): pass + base = Base() derived1 = Derived1() derived2 = Derived2() super_d2 = super(Derived2, derived2) - self.assertRegex(repr(base.method), - r">") - self.assertRegex(repr(derived1.method), - r">") - self.assertRegex(repr(derived2.method), - r">") - self.assertRegex(repr(super_d2.method), - r">") + self.assertRegex( + repr(base.method), r">" + ) + self.assertRegex( + repr(derived1.method), + r">", + ) + self.assertRegex( + repr(derived2.method), + r">", + ) + self.assertRegex( + repr(super_d2.method), + r">", + ) class Foo: @classmethod def method(cls): pass - foo = Foo() - self.assertRegex(repr(foo.method), # access via instance - r">") - self.assertRegex(repr(Foo.method), # access via the class - r">") + foo = Foo() + self.assertRegex( + repr(foo.method), # access via instance + r">", + ) + self.assertRegex( + repr(Foo.method), # access via the class + r">", + ) class MyCallable: def __call__(self, arg): pass - func = MyCallable() # func has no __name__ or __qualname__ attributes + + func = MyCallable() # func has no __name__ or __qualname__ attributes instance = object() method = types.MethodType(func, instance) - self.assertRegex(repr(method), - r">") + self.assertRegex(repr(method), r">") func.__name__ = "name" - self.assertRegex(repr(method), - r">") + self.assertRegex(repr(method), r">") func.__qualname__ = "qualname" - self.assertRegex(repr(method), - r">") + self.assertRegex( + repr(method), r">" + ) - @unittest.skipIf(_testcapi is None, 'need the _testcapi module') + @unittest.skipIf(_testcapi is None, "need the _testcapi module") def test_bpo25750(self): # bpo-25750: calling a descriptor (implemented as built-in # function with METH_FASTCALL) should not crash CPython if the @@ -4981,10 +5755,12 @@ class Descr: class X: descr = Descr() + def __new__(cls): cls.descr = None # Create this large list to corrupt some unused memory cls.lst = [2**i for i in range(10000)] + X.descr def test_remove_subclass(self): @@ -4994,10 +5770,12 @@ def test_remove_subclass(self): # when a type is deallocated. class Parent: pass + self.assertEqual(Parent.__subclasses__(), []) class Child(Parent): pass + self.assertEqual(Parent.__subclasses__(), [Child]) del Child @@ -5036,21 +5814,27 @@ def setUp(self): class C(object): def meth(self): pass + self.C = C - @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), - 'trace function introduces __local__') + @unittest.skipIf( + hasattr(sys, "gettrace") and sys.gettrace(), + "trace function introduces __local__", + ) def test_iter_keys(self): # Testing dict-proxy keys... it = self.C.__dict__.keys() self.assertNotIsInstance(it, list) keys = list(it) keys.sort() - self.assertEqual(keys, ['__dict__', '__doc__', '__module__', - '__weakref__', 'meth']) + self.assertEqual( + keys, ["__dict__", "__doc__", "__module__", "__weakref__", "meth"] + ) - @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), - 'trace function introduces __local__') + @unittest.skipIf( + hasattr(sys, "gettrace") and sys.gettrace(), + "trace function introduces __local__", + ) def test_iter_values(self): # Testing dict-proxy values... it = self.C.__dict__.values() @@ -5058,26 +5842,32 @@ def test_iter_values(self): values = list(it) self.assertEqual(len(values), 5) - @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), - 'trace function introduces __local__') + @unittest.skipIf( + hasattr(sys, "gettrace") and sys.gettrace(), + "trace function introduces __local__", + ) def test_iter_items(self): # Testing dict-proxy iteritems... it = self.C.__dict__.items() self.assertNotIsInstance(it, list) keys = [item[0] for item in it] keys.sort() - self.assertEqual(keys, ['__dict__', '__doc__', '__module__', - '__weakref__', 'meth']) + self.assertEqual( + keys, ["__dict__", "__doc__", "__module__", "__weakref__", "meth"] + ) def test_dict_type_with_metaclass(self): # Testing type of __dict__ when metaclass set... class B(object): pass + class M(type): pass + class C(metaclass=M): # In 2.3a1, C.__dict__ was a real dict rather than a dict proxy pass + self.assertEqual(type(C.__dict__), type(B.__dict__)) def test_repr(self): @@ -5085,10 +5875,10 @@ def test_repr(self): # We can't blindly compare with the repr of another dict as ordering # of keys and values is arbitrary and may differ. r = repr(self.C.__dict__) - self.assertTrue(r.startswith('mappingproxy('), r) - self.assertTrue(r.endswith(')'), r) + self.assertTrue(r.startswith("mappingproxy("), r) + self.assertTrue(r.endswith(")"), r) for k, v in self.C.__dict__.items(): - self.assertIn('{!r}: {!r}'.format(k, v), r) + self.assertIn("{!r}: {!r}".format(k, v), r) class AAAPTypesLongInitTest(unittest.TestCase): @@ -5106,6 +5896,7 @@ def test_pytype_long_ready(self): class UserLong(object): def __pow__(self, *args): pass + try: pow(0, UserLong(), 0) except: @@ -5123,30 +5914,30 @@ def test_type_lookup_mro_reference(self): # __bases__ is set during the lookup for example. class MyKey(object): def __hash__(self): - return hash('mykey') + return hash("mykey") def __eq__(self, other): X.__bases__ = (Base2,) class Base(object): - mykey = 'from Base' - mykey2 = 'from Base' + mykey = "from Base" + mykey2 = "from Base" class Base2(object): - mykey = 'from Base2' - mykey2 = 'from Base2' + mykey = "from Base2" + mykey2 = "from Base2" - X = type('X', (Base,), {MyKey(): 5}) + X = type("X", (Base,), {MyKey(): 5}) # mykey is read from Base - self.assertEqual(X.mykey, 'from Base') + self.assertEqual(X.mykey, "from Base") # mykey2 is read from Base2 because MyKey.__eq__ has set __bases__ - self.assertEqual(X.mykey2, 'from Base2') + self.assertEqual(X.mykey2, "from Base2") class PicklingTests(unittest.TestCase): - - def _check_reduce(self, proto, obj, args=(), kwargs={}, state=None, - listitems=None, dictitems=None): + def _check_reduce( + self, proto, obj, args=(), kwargs={}, state=None, listitems=None, dictitems=None + ): if proto >= 2: reduce_value = obj.__reduce_ex__(proto) if kwargs: @@ -5166,10 +5957,10 @@ def _check_reduce(self, proto, obj, args=(), kwargs={}, state=None, self.assertIsNone(reduce_value[4]) else: base_type = type(obj).__base__ - reduce_value = (copyreg._reconstructor, - (type(obj), - base_type, - None if base_type is object else base_type(obj))) + reduce_value = ( + copyreg._reconstructor, + (type(obj), base_type, None if base_type is object else base_type(obj)), + ) if state is not None: reduce_value += (state,) self.assertEqual(obj.__reduce_ex__(proto), reduce_value) @@ -5178,12 +5969,13 @@ def _check_reduce(self, proto, obj, args=(), kwargs={}, state=None, def test_reduce(self): protocols = range(pickle.HIGHEST_PROTOCOL + 1) args = (-101, "spam") - kwargs = {'bacon': -201, 'fish': -301} - state = {'cheese': -401} + kwargs = {"bacon": -201, "fish": -301} + state = {"cheese": -401} class C1: def __getnewargs__(self): return args + obj = C1() for proto in protocols: self._check_reduce(proto, obj, args) @@ -5196,6 +5988,7 @@ def __getnewargs__(self): class C2: def __getnewargs__(self): return "bad args" + obj = C2() for proto in protocols: if proto >= 2: @@ -5205,6 +5998,7 @@ def __getnewargs__(self): class C3: def __getnewargs_ex__(self): return (args, kwargs) + obj = C3() for proto in protocols: if proto >= 2: @@ -5213,15 +6007,19 @@ def __getnewargs_ex__(self): class C4: def __getnewargs_ex__(self): return (args, "bad dict") + class C5: def __getnewargs_ex__(self): return ("bad tuple", kwargs) + class C6: def __getnewargs_ex__(self): return () + class C7: def __getnewargs_ex__(self): return "bad args" + for proto in protocols: for cls in C4, C5, C6, C7: obj = cls() @@ -5232,6 +6030,7 @@ def __getnewargs_ex__(self): class C9: def __getnewargs_ex__(self): return (args, {}) + obj = C9() for proto in protocols: self._check_reduce(proto, obj, args) @@ -5239,6 +6038,7 @@ def __getnewargs_ex__(self): class C10: def __getnewargs_ex__(self): raise IndexError + obj = C10() for proto in protocols: if proto >= 2: @@ -5248,6 +6048,7 @@ def __getnewargs_ex__(self): class C11: def __getstate__(self): return state + obj = C11() for proto in protocols: self._check_reduce(proto, obj, state=state) @@ -5255,6 +6056,7 @@ def __getstate__(self): class C12: def __getstate__(self): return "not dict" + obj = C12() for proto in protocols: self._check_reduce(proto, obj, state="not dict") @@ -5262,6 +6064,7 @@ def __getstate__(self): class C13: def __getstate__(self): raise IndexError + obj = C13() for proto in protocols: with self.assertRaises(IndexError): @@ -5272,6 +6075,7 @@ def __getstate__(self): class C14: __slots__ = tuple(state) + def __init__(self): for name, value in state.items(): setattr(self, name, value) @@ -5288,18 +6092,21 @@ def __init__(self): class C15(dict): pass + obj = C15({"quebec": -601}) for proto in protocols: self._check_reduce(proto, obj, dictitems=dict(obj)) class C16(list): pass + obj = C16(["yukon"]) for proto in protocols: self._check_reduce(proto, obj, listitems=list(obj)) def test_special_method_lookup(self): protocols = range(pickle.HIGHEST_PROTOCOL + 1) + class Picky: def __getstate__(self): return {} @@ -5308,13 +6115,13 @@ def __getattr__(self, attr): if attr in ("__getnewargs__", "__getnewargs_ex__"): raise AssertionError(attr) return None + for protocol in protocols: state = {} if protocol >= 2 else None self._check_reduce(protocol, Picky(), state=state) def _assert_is_copy(self, obj, objcopy, msg=None): - """Utility method to verify if two objects are copies of each others. - """ + """Utility method to verify if two objects are copies of each others.""" if msg is None: msg = "{!r} is not a copy of {!r}".format(obj, objcopy) if type(obj).__repr__ is object.__repr__: @@ -5322,46 +6129,59 @@ def _assert_is_copy(self, obj, objcopy, msg=None): # to help us verify that the two objects are copies. This allows # us to delegate the non-generic verification logic to the objects # themselves. - raise ValueError("object passed to _assert_is_copy must " + - "override the __repr__ method.") + raise ValueError( + "object passed to _assert_is_copy must " + + "override the __repr__ method." + ) self.assertIsNot(obj, objcopy, msg=msg) self.assertIs(type(obj), type(objcopy), msg=msg) - if hasattr(obj, '__dict__'): + if hasattr(obj, "__dict__"): self.assertDictEqual(obj.__dict__, objcopy.__dict__, msg=msg) self.assertIsNot(obj.__dict__, objcopy.__dict__, msg=msg) - if hasattr(obj, '__slots__'): + if hasattr(obj, "__slots__"): self.assertListEqual(obj.__slots__, objcopy.__slots__, msg=msg) for slot in obj.__slots__: + self.assertEqual(hasattr(obj, slot), hasattr(objcopy, slot), msg=msg) self.assertEqual( - hasattr(obj, slot), hasattr(objcopy, slot), msg=msg) - self.assertEqual(getattr(obj, slot, None), - getattr(objcopy, slot, None), msg=msg) + getattr(obj, slot, None), getattr(objcopy, slot, None), msg=msg + ) self.assertEqual(repr(obj), repr(objcopy), msg=msg) @staticmethod def _generate_pickle_copiers(): - """Utility method to generate the many possible pickle configurations. - """ + """Utility method to generate the many possible pickle configurations.""" + class PickleCopier: "This class copies object using pickle." + def __init__(self, proto, dumps, loads): self.proto = proto self.dumps = dumps self.loads = loads + def copy(self, obj): return self.loads(self.dumps(obj, self.proto)) + def __repr__(self): # We try to be as descriptive as possible here since this is # the string which we will allow us to tell the pickle # configuration we are using during debugging. - return ("PickleCopier(proto={}, dumps={}.{}, loads={}.{})" - .format(self.proto, - self.dumps.__module__, self.dumps.__qualname__, - self.loads.__module__, self.loads.__qualname__)) - return (PickleCopier(*args) for args in - itertools.product(range(pickle.HIGHEST_PROTOCOL + 1), - {pickle.dumps, pickle._dumps}, - {pickle.loads, pickle._loads})) + return "PickleCopier(proto={}, dumps={}.{}, loads={}.{})".format( + self.proto, + self.dumps.__module__, + self.dumps.__qualname__, + self.loads.__module__, + self.loads.__qualname__, + ) + + return ( + PickleCopier(*args) + for args in itertools.product( + range(pickle.HIGHEST_PROTOCOL + 1), + {pickle.dumps, pickle._dumps}, + {pickle.loads, pickle._loads}, + ) + ) def test_pickle_slots(self): # Tests pickling of classes with __slots__. @@ -5369,43 +6189,54 @@ def test_pickle_slots(self): # Pickling of classes with __slots__ but without __getstate__ should # fail (if using protocol 0 or 1) global C + class C: - __slots__ = ['a'] + __slots__ = ["a"] + with self.assertRaises(TypeError): pickle.dumps(C(), 0) global D + class D(C): pass + with self.assertRaises(TypeError): pickle.dumps(D(), 0) class C: "A class with __getstate__ and __setstate__ implemented." - __slots__ = ['a'] + + __slots__ = ["a"] + def __getstate__(self): - state = getattr(self, '__dict__', {}).copy() + state = getattr(self, "__dict__", {}).copy() for cls in type(self).__mro__: - for slot in cls.__dict__.get('__slots__', ()): + for slot in cls.__dict__.get("__slots__", ()): try: state[slot] = getattr(self, slot) except AttributeError: pass return state + def __setstate__(self, state): for k, v in state.items(): setattr(self, k, v) + def __repr__(self): return "%s()<%r>" % (type(self).__name__, self.__getstate__()) class D(C): "A subclass of a class with slots." + pass global E + class E(C): "A subclass with an extra slot." - __slots__ = ['b'] + + __slots__ = ["b"] # Now it should work for pickle_copier in self._generate_pickle_copiers(): @@ -5433,89 +6264,115 @@ class E(C): def test_reduce_copying(self): # Tests pickling and copying new-style classes and objects. global C1 + class C1: "The state of this class is copyable via its instance dict." + ARGS = (1, 2) NEED_DICT_COPYING = True + def __init__(self, a, b): super().__init__() self.a = a self.b = b + def __repr__(self): return "C1(%r, %r)" % (self.a, self.b) global C2 + class C2(list): "A list subclass copyable via __getnewargs__." + ARGS = (1, 2) NEED_DICT_COPYING = False + def __new__(cls, a, b): self = super().__new__(cls) self.a = a self.b = b return self + def __init__(self, *args): super().__init__() # This helps testing that __init__ is not called during the # unpickling process, which would cause extra appends. self.append("cheese") + @classmethod def __getnewargs__(cls): return cls.ARGS + def __repr__(self): return "C2(%r, %r)<%r>" % (self.a, self.b, list(self)) global C3 + class C3(list): "A list subclass copyable via __getstate__." + ARGS = (1, 2) NEED_DICT_COPYING = False + def __init__(self, a, b): self.a = a self.b = b # This helps testing that __init__ is not called during the # unpickling process, which would cause extra appends. self.append("cheese") + @classmethod def __getstate__(cls): return cls.ARGS + def __setstate__(self, state): a, b = state self.a = a self.b = b + def __repr__(self): return "C3(%r, %r)<%r>" % (self.a, self.b, list(self)) global C4 + class C4(int): "An int subclass copyable via __getnewargs__." + ARGS = ("hello", "world", 1) NEED_DICT_COPYING = False + def __new__(cls, a, b, value): self = super().__new__(cls, value) self.a = a self.b = b return self + @classmethod def __getnewargs__(cls): return cls.ARGS + def __repr__(self): return "C4(%r, %r)<%r>" % (self.a, self.b, int(self)) global C5 + class C5(int): "An int subclass copyable via __getnewargs_ex__." + ARGS = (1, 2) - KWARGS = {'value': 3} + KWARGS = {"value": 3} NEED_DICT_COPYING = False + def __new__(cls, a, b, *, value=0): self = super().__new__(cls, value) self.a = a self.b = b return self + @classmethod def __getnewargs_ex__(cls): return (cls.ARGS, cls.KWARGS) + def __repr__(self): return "C5(%r, %r)<%r>" % (self.a, self.b, int(self)) @@ -5524,7 +6381,7 @@ def __repr__(self): pickle_copiers = self._generate_pickle_copiers() for cls, pickle_copier in itertools.product(test_classes, pickle_copiers): with self.subTest(cls=cls, pickle_copier=pickle_copier): - kwargs = getattr(cls, 'KWARGS', {}) + kwargs = getattr(cls, "KWARGS", {}) obj = cls(*cls.ARGS, **kwargs) proto = pickle_copier.proto objcopy = pickle_copier.copy(obj) @@ -5541,7 +6398,7 @@ def __repr__(self): # Testing copying through copy.deepcopy() for cls in test_classes: with self.subTest(cls=cls): - kwargs = getattr(cls, 'KWARGS', {}) + kwargs = getattr(cls, "KWARGS", {}) obj = cls(*cls.ARGS, **kwargs) objcopy = deepcopy(obj) self._assert_is_copy(obj, objcopy) @@ -5558,17 +6415,20 @@ def test_issue24097(self): # Slot name is freed inside __getattr__ and is later used. class S(str): # Not interned pass + class A: - __slotnames__ = [S('spam')] + __slotnames__ = [S("spam")] + def __getattr__(self, attr): - if attr == 'spam': - A.__slotnames__[:] = [S('spam')] + if attr == "spam": + A.__slotnames__[:] = [S("spam")] return 42 else: raise AttributeError import copyreg - expected = (copyreg.__newobj__, (A,), (None, {'spam': 42}), None, None) + + expected = (copyreg.__newobj__, (A,), (None, {"spam": 42}), None, None) self.assertEqual(A().__reduce_ex__(2), expected) # Shouldn't crash def test_object_reduce(self): @@ -5586,39 +6446,41 @@ def test_object_reduce(self): class SharedKeyTests(unittest.TestCase): - @support.cpython_only def test_subclasses(self): # Verify that subclasses can share keys (per PEP 412) class A: pass + class B(A): pass - #Shrink keys by repeatedly creating instances + # Shrink keys by repeatedly creating instances [(A(), B()) for _ in range(30)] a, b = A(), B() self.assertEqual(sys.getsizeof(vars(a)), sys.getsizeof(vars(b))) - self.assertLess(sys.getsizeof(vars(a)), sys.getsizeof({"a":1})) + self.assertLess(sys.getsizeof(vars(a)), sys.getsizeof({"a": 1})) # Initial hash table can contain only one or two elements. # Set 6 attributes to cause internal resizing. a.x, a.y, a.z, a.w, a.v, a.u = range(6) self.assertNotEqual(sys.getsizeof(vars(a)), sys.getsizeof(vars(b))) a2 = A() self.assertGreater(sys.getsizeof(vars(a)), sys.getsizeof(vars(a2))) - self.assertLess(sys.getsizeof(vars(a2)), sys.getsizeof({"a":1})) - self.assertLess(sys.getsizeof(vars(b)), sys.getsizeof({"a":1})) + self.assertLess(sys.getsizeof(vars(a2)), sys.getsizeof({"a": 1})) + self.assertLess(sys.getsizeof(vars(b)), sys.getsizeof({"a": 1})) class DebugHelperMeta(type): """ Sets default __doc__ and simplifies repr() output. """ + def __new__(mcls, name, bases, attrs): - if attrs.get('__doc__') is None: - attrs['__doc__'] = name # helps when debugging with gdb + if attrs.get("__doc__") is None: + attrs["__doc__"] = name # helps when debugging with gdb return type.__new__(mcls, name, bases, attrs) + def __repr__(cls): return repr(cls.__name__) @@ -5635,7 +6497,7 @@ def setUp(self): self.ready = False def step_until(self, limit): - ret = (self.step < limit) + ret = self.step < limit if ret: self.step += 1 return ret @@ -5644,6 +6506,7 @@ def test_incomplete_set_bases_on_self(self): """ type_set_bases must be aware that type->tp_mro can be NULL. """ + class M(DebugHelperMeta): def mro(cls): if self.step_until(1): @@ -5659,9 +6522,10 @@ def test_reent_set_bases_on_base(self): """ Deep reentrancy must not over-decref old_mro. """ + class M(DebugHelperMeta): def mro(cls): - if cls.__mro__ is not None and cls.__name__ == 'B': + if cls.__mro__ is not None and cls.__name__ == "B": # 4-5 steps are usually enough to make it crash somewhere if self.step_until(10): A.__bases__ += () @@ -5670,14 +6534,17 @@ def mro(cls): class A(metaclass=M): pass + class B(A): pass + B.__bases__ += () def test_reent_set_bases_on_direct_base(self): """ Similar to test_reent_set_bases_on_base, but may crash differently. """ + class M(DebugHelperMeta): def mro(cls): base = cls.__bases__[0] @@ -5689,8 +6556,10 @@ def mro(cls): class A(metaclass=M): pass + class B(A): pass + class C(B): pass @@ -5710,19 +6579,22 @@ def test_reent_set_bases_tp_base_cycle(self): Functions that rely on tp_base (like solid_base and PyType_IsSubtype) would not be happy in that case, causing a stack overflow. """ + class M(DebugHelperMeta): def mro(cls): if self.ready: - if cls.__name__ == 'B1': + if cls.__name__ == "B1": B2.__bases__ = (B1,) - if cls.__name__ == 'B2': + if cls.__name__ == "B2": B1.__bases__ = (B2,) return type.mro(cls) class A(metaclass=M): pass + class B1(A): pass + class B2(A): pass @@ -5739,19 +6611,23 @@ def test_tp_subclasses_cycle_in_update_slots(self): (like recurse_down_subclasses and mro_hierarchy) eventually leading to a stack overflow. """ + class M(DebugHelperMeta): def mro(cls): - if self.ready and cls.__name__ == 'C': + if self.ready and cls.__name__ == "C": self.ready = False C.__bases__ = (B2,) return type.mro(cls) class A(metaclass=M): pass + class B1(A): pass + class B2(A): pass + class C(A): pass @@ -5771,11 +6647,13 @@ def test_tp_subclasses_cycle_error_return_path(self): The same as test_tp_subclasses_cycle_in_update_slots, but tests a code path executed on error (goto bail). """ + class E(Exception): pass + class M(DebugHelperMeta): def mro(cls): - if self.ready and cls.__name__ == 'C': + if self.ready and cls.__name__ == "C": if C.__bases__ == (B2,): self.ready = False else: @@ -5785,10 +6663,13 @@ def mro(cls): class A(metaclass=M): pass + class B1(A): pass + class B2(A): pass + class C(A): pass @@ -5806,10 +6687,12 @@ def test_incomplete_extend(self): throw a reasonable TypeError exception, instead of failing with PyErr_BadInternalCall. """ + class M(DebugHelperMeta): def mro(cls): - if cls.__mro__ is None and cls.__name__ != 'X': + if cls.__mro__ is None and cls.__name__ != "X": with self.assertRaises(TypeError): + class X(cls): pass @@ -5823,6 +6706,7 @@ def test_incomplete_super(self): Attribute lookup on a super object must be aware that its target type can be uninitialized (type->tp_mro == NULL). """ + class M(DebugHelperMeta): def mro(cls): if cls.__mro__ is None: @@ -5839,6 +6723,7 @@ def test_disappearing_custom_mro(self): gh-92112: A custom mro() returning a result conflicting with __bases__ and deleting itself caused a double free. """ + class B: pass @@ -5848,6 +6733,7 @@ def mro(cls): return (B,) with self.assertRaises(TypeError): + class A(metaclass=M): pass diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py index 2d771a99e0a86e..39a420517c9646 100644 --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -55,7 +55,7 @@ class SampleClass: >>> sc = SampleClass(3) >>> for i in range(10): ... sc = sc.double() - ... print(' ', sc.get(), sep='', end='') + ... print(" ", sc.get(), sep="", end="") 6 12 24 48 96 192 384 768 1536 3072 """ @@ -142,7 +142,7 @@ def get(self): class SampleNewStyleClass(object): r""" - >>> print('1\n2\n3') + >>> print("1\n2\n3") 1 2 3 @@ -214,60 +214,72 @@ def test_Example(): These attributes are set by the constructor. `source` and `want` are required; the other attributes all have default values: - >>> example = doctest.Example('print(1)', '1\n') - >>> (example.source, example.want, example.exc_msg, - ... example.lineno, example.indent, example.options) + >>> example = doctest.Example("print(1)", "1\n") + >>> ( + ... example.source, + ... example.want, + ... example.exc_msg, + ... example.lineno, + ... example.indent, + ... example.options, + ... ) ('print(1)\n', '1\n', None, 0, 0, {}) The first three attributes (`source`, `want`, and `exc_msg`) may be specified positionally; the remaining arguments should be specified as keyword arguments: - >>> exc_msg = 'IndexError: pop from an empty list' - >>> example = doctest.Example('[].pop()', '', exc_msg, - ... lineno=5, indent=4, - ... options={doctest.ELLIPSIS: True}) - >>> (example.source, example.want, example.exc_msg, - ... example.lineno, example.indent, example.options) + >>> exc_msg = "IndexError: pop from an empty list" + >>> example = doctest.Example( + ... "[].pop()", "", exc_msg, lineno=5, indent=4, options={doctest.ELLIPSIS: True} + ... ) + >>> ( + ... example.source, + ... example.want, + ... example.exc_msg, + ... example.lineno, + ... example.indent, + ... example.options, + ... ) ('[].pop()\n', '', 'IndexError: pop from an empty list\n', 5, 4, {8: True}) The constructor normalizes the `source` string to end in a newline: Source spans a single line: no terminating newline. - >>> e = doctest.Example('print(1)', '1\n') + >>> e = doctest.Example("print(1)", "1\n") >>> e.source, e.want ('print(1)\n', '1\n') - >>> e = doctest.Example('print(1)\n', '1\n') + >>> e = doctest.Example("print(1)\n", "1\n") >>> e.source, e.want ('print(1)\n', '1\n') Source spans multiple lines: require terminating newline. - >>> e = doctest.Example('print(1);\nprint(2)\n', '1\n2\n') + >>> e = doctest.Example("print(1);\nprint(2)\n", "1\n2\n") >>> e.source, e.want ('print(1);\nprint(2)\n', '1\n2\n') - >>> e = doctest.Example('print(1);\nprint(2)', '1\n2\n') + >>> e = doctest.Example("print(1);\nprint(2)", "1\n2\n") >>> e.source, e.want ('print(1);\nprint(2)\n', '1\n2\n') Empty source string (which should never appear in real examples) - >>> e = doctest.Example('', '') + >>> e = doctest.Example("", "") >>> e.source, e.want ('\n', '') The constructor normalizes the `want` string to end in a newline, unless it's the empty string: - >>> e = doctest.Example('print(1)', '1\n') + >>> e = doctest.Example("print(1)", "1\n") >>> e.source, e.want ('print(1)\n', '1\n') - >>> e = doctest.Example('print(1)', '1') + >>> e = doctest.Example("print(1)", "1") >>> e.source, e.want ('print(1)\n', '1\n') - >>> e = doctest.Example('print', '') + >>> e = doctest.Example("print", "") >>> e.source, e.want ('print\n', '') @@ -275,38 +287,38 @@ def test_Example(): unless it's `None`: Message spans one line - >>> exc_msg = 'IndexError: pop from an empty list' - >>> e = doctest.Example('[].pop()', '', exc_msg) + >>> exc_msg = "IndexError: pop from an empty list" + >>> e = doctest.Example("[].pop()", "", exc_msg) >>> e.exc_msg 'IndexError: pop from an empty list\n' - >>> exc_msg = 'IndexError: pop from an empty list\n' - >>> e = doctest.Example('[].pop()', '', exc_msg) + >>> exc_msg = "IndexError: pop from an empty list\n" + >>> e = doctest.Example("[].pop()", "", exc_msg) >>> e.exc_msg 'IndexError: pop from an empty list\n' Message spans multiple lines - >>> exc_msg = 'ValueError: 1\n 2' - >>> e = doctest.Example('raise ValueError("1\n 2")', '', exc_msg) + >>> exc_msg = "ValueError: 1\n 2" + >>> e = doctest.Example('raise ValueError("1\n 2")', "", exc_msg) >>> e.exc_msg 'ValueError: 1\n 2\n' - >>> exc_msg = 'ValueError: 1\n 2\n' - >>> e = doctest.Example('raise ValueError("1\n 2")', '', exc_msg) + >>> exc_msg = "ValueError: 1\n 2\n" + >>> e = doctest.Example('raise ValueError("1\n 2")', "", exc_msg) >>> e.exc_msg 'ValueError: 1\n 2\n' Empty (but non-None) exception message (which should never appear in real examples) - >>> exc_msg = '' - >>> e = doctest.Example('raise X()', '', exc_msg) + >>> exc_msg = "" + >>> e = doctest.Example("raise X()", "", exc_msg) >>> e.exc_msg '\n' Compare `Example`: - >>> example = doctest.Example('print 1', '1\n') - >>> same_example = doctest.Example('print 1', '1\n') - >>> other_example = doctest.Example('print 42', '42\n') + >>> example = doctest.Example("print 1", "1\n") + >>> same_example = doctest.Example("print 1", "1\n") + >>> other_example = doctest.Example("print 42", "42\n") >>> example == same_example True >>> example != same_example @@ -338,10 +350,9 @@ def test_DocTest(): ... another ... example ... ''' - >>> globs = {} # globals to run the test in. + >>> globs = {} # globals to run the test in. >>> parser = doctest.DocTestParser() - >>> test = parser.get_doctest(docstring, globs, 'some_test', - ... 'some_file', 20) + >>> test = parser.get_doctest(docstring, globs, "some_test", "some_file", 20) >>> print(test) >>> len(test.examples) @@ -375,7 +386,7 @@ def test_DocTest(): ... bad ... indentation ... ''' - >>> parser.get_doctest(docstring, globs, 'some_test', 'filename', 0) + >>> parser.get_doctest(docstring, globs, "some_test", "filename", 0) Traceback (most recent call last): ValueError: line 4 of the docstring for some_test has inconsistent leading whitespace: 'indentation' @@ -387,23 +398,23 @@ def test_DocTest(): ... ... 2)) ... ('bad', 'indentation') ... ''' - >>> parser.get_doctest(docstring, globs, 'some_test', 'filename', 0) + >>> parser.get_doctest(docstring, globs, "some_test", "filename", 0) Traceback (most recent call last): ValueError: line 2 of the docstring for some_test has inconsistent leading whitespace: '... 2))' If there's no blank space after a PS1 prompt ('>>>'), then `DocTest` will raise a ValueError: - >>> docstring = '>>>print(1)\n1' - >>> parser.get_doctest(docstring, globs, 'some_test', 'filename', 0) + >>> docstring = ">>>print(1)\n1" + >>> parser.get_doctest(docstring, globs, "some_test", "filename", 0) Traceback (most recent call last): ValueError: line 1 of the docstring for some_test lacks blank after >>>: '>>>print(1)' If there's no blank space after a PS2 prompt ('...'), then `DocTest` will raise a ValueError: - >>> docstring = '>>> if 1:\n...print(1)\n1' - >>> parser.get_doctest(docstring, globs, 'some_test', 'filename', 0) + >>> docstring = ">>> if 1:\n...print(1)\n1" + >>> parser.get_doctest(docstring, globs, "some_test", "filename", 0) Traceback (most recent call last): ValueError: line 2 of the docstring for some_test lacks blank after ...: '...print(1)' @@ -413,10 +424,8 @@ def test_DocTest(): ... >>> print 12 ... 12 ... ''' - >>> test = parser.get_doctest(docstring, globs, 'some_test', - ... 'some_test', 20) - >>> same_test = parser.get_doctest(docstring, globs, 'some_test', - ... 'some_test', 20) + >>> test = parser.get_doctest(docstring, globs, "some_test", "some_test", 20) + >>> same_test = parser.get_doctest(docstring, globs, "some_test", "some_test", 20) >>> test == same_test True >>> test != same_test @@ -427,8 +436,7 @@ def test_DocTest(): ... >>> print 42 ... 42 ... ''' - >>> other_test = parser.get_doctest(docstring, globs, 'other_test', - ... 'other_file', 10) + >>> other_test = parser.get_doctest(docstring, globs, "other_test", "other_file", 10) >>> test == other_test False >>> test != other_test @@ -474,7 +482,7 @@ def basics(): >>> import test.test_doctest >>> old = test.test_doctest.__file__ - >>> test.test_doctest.__file__ = 'test_doctest.pyc' + >>> test.test_doctest.__file__ = "test_doctest.pyc" >>> tests = finder.find(sample_func) @@ -484,7 +492,7 @@ def basics(): The exact name depends on how test_doctest was invoked, so allow for leading path components. - >>> tests[0].filename # doctest: +ELLIPSIS + >>> tests[0].filename # doctest: +ELLIPSIS '...test_doctest.py' >>> test.test_doctest.__file__ = old @@ -517,8 +525,8 @@ def basics(): an empty test also be created when there's no docstring?) >>> def no_examples(v): - ... ''' no doctest examples ''' - >>> finder.find(no_examples) # doctest: +ELLIPSIS + ... '''no doctest examples''' + >>> finder.find(no_examples) # doctest: +ELLIPSIS [] Finding Tests in Classes @@ -530,7 +538,7 @@ def basics(): >>> finder = doctest.DocTestFinder() >>> tests = finder.find(SampleClass) >>> for t in tests: - ... print('%2s %s' % (len(t.examples), t.name)) + ... print("%2s %s" % (len(t.examples), t.name)) 3 SampleClass 3 SampleClass.NestedClass 1 SampleClass.NestedClass.__init__ @@ -546,7 +554,7 @@ def basics(): >>> tests = finder.find(SampleNewStyleClass) >>> for t in tests: - ... print('%2s %s' % (len(t.examples), t.name)) + ... print("%2s %s" % (len(t.examples), t.name)) 1 SampleNewStyleClass 1 SampleNewStyleClass.__init__ 1 SampleNewStyleClass.double @@ -560,24 +568,25 @@ def basics(): >>> # A module >>> import types - >>> m = types.ModuleType('some_module') + >>> m = types.ModuleType("some_module") >>> def triple(val): ... ''' ... >>> print(triple(11)) ... 33 ... ''' - ... return val*3 - >>> m.__dict__.update({ - ... 'sample_func': sample_func, - ... 'SampleClass': SampleClass, - ... '__doc__': ''' + ... return val * 3 + >>> m.__dict__.update( + ... { + ... "sample_func": sample_func, + ... "SampleClass": SampleClass, + ... "__doc__": ''' ... Module docstring. ... >>> print('module') ... module ... ''', - ... '__test__': { - ... 'd': '>>> print(6)\n6\n>>> print(7)\n7\n', - ... 'c': triple}}) + ... "__test__": {"d": ">>> print(6)\n6\n>>> print(7)\n7\n", "c": triple}, + ... } + ... ) >>> finder = doctest.DocTestFinder() >>> # Use module=test.test_doctest, to prevent doctest from @@ -585,7 +594,7 @@ def basics(): >>> import test.test_doctest >>> tests = finder.find(m, module=test.test_doctest) >>> for t in tests: - ... print('%2s %s' % (len(t.examples), t.name)) + ... print("%2s %s" % (len(t.examples), t.name)) 1 some_module 3 some_module.SampleClass 3 some_module.SampleClass.NestedClass @@ -619,7 +628,7 @@ def basics(): We can't guess which will be found in doctest's traversal of TwoNames.__dict__ first, so we have to allow for either. - >>> tests[1].name.split('.')[-1] in ['f', 'g'] + >>> tests[1].name.split(".")[-1] in ["f", "g"] True Empty Tests @@ -628,7 +637,7 @@ def basics(): >>> tests = doctest.DocTestFinder().find(SampleClass) >>> for t in tests: - ... print('%2s %s' % (len(t.examples), t.name)) + ... print("%2s %s" % (len(t.examples), t.name)) 3 SampleClass 3 SampleClass.NestedClass 1 SampleClass.NestedClass.__init__ @@ -647,7 +656,7 @@ def basics(): >>> tests = doctest.DocTestFinder(exclude_empty=False).find(SampleClass) >>> for t in tests: - ... print('%2s %s' % (len(t.examples), t.name)) + ... print("%2s %s" % (len(t.examples), t.name)) 3 SampleClass 3 SampleClass.NestedClass 1 SampleClass.NestedClass.__init__ @@ -668,7 +677,7 @@ def basics(): >>> from test import doctest_lineno >>> tests = doctest.DocTestFinder(exclude_empty=False).find(doctest_lineno) >>> for t in tests: - ... print('%5s %s' % (t.lineno, t.name)) + ... print("%5s %s" % (t.lineno, t.name)) None test.doctest_lineno 22 test.doctest_lineno.ClassWithDocstring 30 test.doctest_lineno.ClassWithDoctest @@ -688,7 +697,7 @@ def basics(): >>> tests = doctest.DocTestFinder(recurse=False).find(SampleClass) >>> for t in tests: - ... print('%2s %s' % (len(t.examples), t.name)) + ... print("%2s %s" % (len(t.examples), t.name)) 3 SampleClass Line numbers @@ -728,14 +737,13 @@ def non_Python_modules(): >>> import builtins >>> tests = doctest.DocTestFinder().find(builtins) - >>> 830 < len(tests) < 860 # approximate number of objects with docstrings + >>> 830 < len(tests) < 860 # approximate number of objects with docstrings True >>> real_tests = [t for t in tests if len(t.examples) > 0] - >>> len(real_tests) # objects that actually have doctests + >>> len(real_tests) # objects that actually have doctests 14 >>> for t in real_tests: - ... print('{} {}'.format(len(t.examples), t.name)) - ... + ... print("{} {}".format(len(t.examples), t.name)) 1 builtins.bin 5 builtins.bytearray.hex 5 builtins.bytes.hex @@ -843,9 +851,9 @@ def test_DocTestParser(): >>> parser = doctest.DocTestParser() >>> for piece in parser.parse(s): ... if isinstance(piece, doctest.Example): - ... print('Example:', (piece.source, piece.want, piece.lineno)) + ... print("Example:", (piece.source, piece.want, piece.lineno)) ... else: - ... print(' Text:', repr(piece)) + ... print(" Text:", repr(piece)) Text: '\n' Example: ('x, y = 2, 3 # no output expected\n', '', 1) Text: '' @@ -865,7 +873,7 @@ def test_DocTestParser(): The `get_doctest` method creates a Test from the examples, along with the given arguments: - >>> test = parser.get_doctest(s, {}, 'name', 'filename', lineno=5) + >>> test = parser.get_doctest(s, {}, "name", "filename", lineno=5) >>> (test.name, test.filename, test.lineno) ('name', 'filename', 5) >>> for piece in test.examples: @@ -977,12 +985,12 @@ def verbose_flag(): >>> old_argv = sys.argv >>> # If -v does not appear in sys.argv, then output isn't verbose. - >>> sys.argv = ['test'] + >>> sys.argv = ["test"] >>> doctest.DocTestRunner().run(test) TestResults(failed=0, attempted=3) >>> # If -v does appear in sys.argv, then output is verbose. - >>> sys.argv = ['test', '-v'] + >>> sys.argv = ["test", "-v"] >>> doctest.DocTestRunner().run(test) Trying: x = 12 @@ -1253,7 +1261,7 @@ def displayhook(): >>> import sys >>> orig_displayhook = sys.displayhook >>> def my_displayhook(x): - ... print('hi!') + ... print("hi!") >>> sys.displayhook = my_displayhook >>> def f(): ... ''' @@ -1289,7 +1297,7 @@ def optionflags(): and 1/0: >>> def f(x): - ... '>>> True\n1\n' + ... ">>> True\n1\n" >>> # Without the flag: >>> test = doctest.DocTestFinder().find(f)[0] @@ -1345,7 +1353,7 @@ def optionflags(): treated as equal: >>> def f(x): - ... '\n>>> print(1, 2, 3)\n 1 2\n 3' + ... "\n>>> print(1, 2, 3)\n 1 2\n 3" >>> # Without the flag: >>> test = doctest.DocTestFinder().find(f)[0] @@ -1369,7 +1377,7 @@ def optionflags(): TestResults(failed=0, attempted=1) An example from the docs: - >>> print(list(range(20))) #doctest: +NORMALIZE_WHITESPACE + >>> print(list(range(20))) # doctest: +NORMALIZE_WHITESPACE [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] @@ -1377,7 +1385,7 @@ def optionflags(): output to match any substring in the actual output: >>> def f(x): - ... '>>> print(list(range(15)))\n[0, 1, 2, ..., 14]\n' + ... ">>> print(list(range(15)))\n[0, 1, 2, ..., 14]\n" >>> # Without the flag: >>> test = doctest.DocTestFinder().find(f)[0] @@ -1403,25 +1411,25 @@ def optionflags(): >>> if 1: ... for i in range(100): - ... print(i**2, end=' ') #doctest: +ELLIPSIS - ... print('!') + ... print(i**2, end=" ") # doctest: +ELLIPSIS + ... print("!") 0 1...4...9 16 ... 36 49 64 ... 9801 ! ... can be surprising; e.g., this test passes: - >>> if 1: #doctest: +ELLIPSIS + >>> if 1: # doctest: +ELLIPSIS ... for i in range(20): - ... print(i, end=' ') + ... print(i, end=" ") ... print(20) 0 1 2 ...1...2...0 Examples from the docs: - >>> print(list(range(20))) # doctest:+ELLIPSIS + >>> print(list(range(20))) # doctest:+ELLIPSIS [0, 1, ..., 18, 19] - >>> print(list(range(20))) # doctest: +ELLIPSIS - ... # doctest: +NORMALIZE_WHITESPACE + >>> print(list(range(20))) # doctest: +ELLIPSIS + ... # doctest: +NORMALIZE_WHITESPACE [0, 1, ..., 18, 19] The SKIP flag causes an example to be skipped entirely. I.e., the @@ -1432,15 +1440,15 @@ def optionflags(): which would be unavailable.) The SKIP flag can also be used for 'commenting out' broken examples. - >>> import unavailable_resource # doctest: +SKIP - >>> unavailable_resource.do_something() # doctest: +SKIP - >>> unavailable_resource.blow_up() # doctest: +SKIP + >>> import unavailable_resource # doctest: +SKIP + >>> unavailable_resource.do_something() # doctest: +SKIP + >>> unavailable_resource.blow_up() # doctest: +SKIP Traceback (most recent call last): ... UncheckedBlowUpError: Nobody checks me. >>> import random - >>> print(random.random()) # doctest: +SKIP + >>> print(random.random()) # doctest: +SKIP 0.721216923889 The REPORT_UDIFF flag causes failures that involve multi-line expected @@ -1718,7 +1726,8 @@ def option_directives(): single example. To turn an option on for an example, follow that example with a comment of the form ``# doctest: +OPTION``: - >>> def f(x): r''' + >>> def f(x): + ... r''' ... >>> print(list(range(10))) # should fail: no ellipsis ... [0, 1, ..., 9] ... @@ -1741,7 +1750,8 @@ def option_directives(): To turn an option off for an example, follow that example with a comment of the form ``# doctest: -OPTION``: - >>> def f(x): r''' + >>> def f(x): + ... r''' ... >>> print(list(range(10))) ... [0, 1, ..., 9] ... @@ -1750,8 +1760,7 @@ def option_directives(): ... [0, 1, ..., 9] ... ''' >>> test = doctest.DocTestFinder().find(f)[0] - >>> doctest.DocTestRunner(verbose=False, - ... optionflags=doctest.ELLIPSIS).run(test) + >>> doctest.DocTestRunner(verbose=False, optionflags=doctest.ELLIPSIS).run(test) ... # doctest: +ELLIPSIS ********************************************************************** File ..., line 6, in f @@ -1766,7 +1775,8 @@ def option_directives(): Option directives affect only the example that they appear with; they do not change the options for surrounding examples: - >>> def f(x): r''' + >>> def f(x): + ... r''' ... >>> print(list(range(10))) # Should fail: no ellipsis ... [0, 1, ..., 9] ... @@ -1800,7 +1810,8 @@ def option_directives(): Multiple options may be modified by a single option directive. They may be separated by whitespace, commas, or both: - >>> def f(x): r''' + >>> def f(x): + ... r''' ... >>> print(list(range(10))) # Should fail ... [0, 1, ..., 9] ... >>> print(list(range(10))) # Should succeed @@ -1820,7 +1831,8 @@ def option_directives(): [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] TestResults(failed=1, attempted=2) - >>> def f(x): r''' + >>> def f(x): + ... r''' ... >>> print(list(range(10))) # Should fail ... [0, 1, ..., 9] ... >>> print(list(range(10))) # Should succeed @@ -1840,7 +1852,8 @@ def option_directives(): [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] TestResults(failed=1, attempted=2) - >>> def f(x): r''' + >>> def f(x): + ... r''' ... >>> print(list(range(10))) # Should fail ... [0, 1, ..., 9] ... >>> print(list(range(10))) # Should succeed @@ -1863,7 +1876,8 @@ def option_directives(): The option directive may be put on the line following the source, as long as a continuation prompt is used: - >>> def f(x): r''' + >>> def f(x): + ... r''' ... >>> print(list(range(10))) ... ... # doctest: +ELLIPSIS ... [0, 1, ..., 9] @@ -1875,7 +1889,8 @@ def option_directives(): For examples with multi-line source, the option directive may appear at the end of any line: - >>> def f(x): r''' + >>> def f(x): + ... r''' ... >>> for x in range(10): # doctest: +ELLIPSIS ... ... print(' ', x, end='', sep='') ... 0 1 2 ... 9 @@ -1891,7 +1906,8 @@ def option_directives(): If more than one line of an example with multi-line source has an option directive, then they are combined: - >>> def f(x): r''' + >>> def f(x): + ... r''' ... Should fail (option directive not on the last line): ... >>> for x in range(10): # doctest: +ELLIPSIS ... ... print(x, end=' ') # doctest: +NORMALIZE_WHITESPACE @@ -1907,22 +1923,22 @@ def option_directives(): `register_option`: >>> # Error: Option not registered - >>> s = '>>> print(12) #doctest: +BADOPTION' - >>> test = doctest.DocTestParser().get_doctest(s, {}, 's', 's.py', 0) + >>> s = ">>> print(12) #doctest: +BADOPTION" + >>> test = doctest.DocTestParser().get_doctest(s, {}, "s", "s.py", 0) Traceback (most recent call last): ValueError: line 1 of the doctest for s has an invalid option: '+BADOPTION' >>> # Error: No + or - prefix - >>> s = '>>> print(12) #doctest: ELLIPSIS' - >>> test = doctest.DocTestParser().get_doctest(s, {}, 's', 's.py', 0) + >>> s = ">>> print(12) #doctest: ELLIPSIS" + >>> test = doctest.DocTestParser().get_doctest(s, {}, "s", "s.py", 0) Traceback (most recent call last): ValueError: line 1 of the doctest for s has an invalid option: 'ELLIPSIS' It is an error to use an option directive on a line that contains no source: - >>> s = '>>> # doctest: +ELLIPSIS' - >>> test = doctest.DocTestParser().get_doctest(s, {}, 's', 's.py', 0) + >>> s = ">>> # doctest: +ELLIPSIS" + >>> test = doctest.DocTestParser().get_doctest(s, {}, "s", "s.py", 0) Traceback (most recent call last): ValueError: line 0 of the doctest for s has an option directive on a line with no example: '# doctest: +ELLIPSIS'""" @@ -1937,7 +1953,7 @@ def test_testsource(): words and expected output are converted to comments: >>> import test.test_doctest - >>> name = 'test.test_doctest.sample_func' + >>> name = "test.test_doctest.sample_func" >>> print(doctest.testsource(test.test_doctest, name)) # Blah blah # @@ -1948,7 +1964,7 @@ def test_testsource(): # Yee ha! - >>> name = 'test.test_doctest.SampleNewStyleClass' + >>> name = "test.test_doctest.SampleNewStyleClass" >>> print(doctest.testsource(test.test_doctest, name)) print('1\n2\n3') # Expected: @@ -1957,7 +1973,7 @@ def test_testsource(): ## 3 - >>> name = 'test.test_doctest.SampleClass.a_classmethod' + >>> name = "test.test_doctest.SampleClass.a_classmethod" >>> print(doctest.testsource(test.test_doctest, name)) print(SampleClass.a_classmethod(10)) # Expected: @@ -1982,12 +1998,14 @@ def test_debug(): Create some fake stdin input, to feed to the debugger: >>> real_stdin = sys.stdin - >>> sys.stdin = _FakeInput(['next', 'print(x)', 'continue']) + >>> sys.stdin = _FakeInput(["next", "print(x)", "continue"]) Run the debugger on the docstring, and then restore sys.stdin. - >>> try: doctest.debug_src(s) - ... finally: sys.stdin = real_stdin + >>> try: + ... doctest.debug_src(s) + ... finally: + ... sys.stdin = real_stdin > (1)() (Pdb) next 12 @@ -2026,13 +2044,18 @@ def test_pdb_set_trace(): captures our debugger input: >>> real_stdin = sys.stdin - >>> sys.stdin = _FakeInput([ - ... 'print(x)', # print data defined by the example - ... 'continue', # stop debugging - ... '']) + >>> sys.stdin = _FakeInput( + ... [ + ... "print(x)", # print data defined by the example + ... "continue", # stop debugging + ... "", + ... ] + ... ) - >>> try: runner.run(test) - ... finally: sys.stdin = real_stdin + >>> try: + ... runner.run(test) + ... finally: + ... sys.stdin = real_stdin --Return-- > (1)()->None -> import pdb; pdb.set_trace() @@ -2044,8 +2067,10 @@ def test_pdb_set_trace(): You can also put pdb.set_trace in a function called from a test: >>> def calls_set_trace(): - ... y=2 - ... import pdb; pdb.set_trace() + ... y = 2 + ... import pdb + ... + ... pdb.set_trace() >>> doc = ''' ... >>> x=1 @@ -2053,12 +2078,15 @@ def test_pdb_set_trace(): ... ''' >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0) >>> real_stdin = sys.stdin - >>> sys.stdin = _FakeInput([ - ... 'print(y)', # print data defined in the function - ... 'up', # out of function - ... 'print(x)', # print data defined by the example - ... 'continue', # stop debugging - ... '']) + >>> sys.stdin = _FakeInput( + ... [ + ... "print(y)", # print data defined in the function + ... "up", # out of function + ... "print(x)", # print data defined by the example + ... "continue", # stop debugging + ... "", + ... ] + ... ) >>> try: ... runner.run(test) @@ -2090,16 +2118,21 @@ def test_pdb_set_trace(): ... ''' >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0) >>> real_stdin = sys.stdin - >>> sys.stdin = _FakeInput([ - ... 'list', # list source from example 2 - ... 'next', # return from g() - ... 'list', # list source from example 1 - ... 'next', # return from f() - ... 'list', # list source from example 3 - ... 'continue', # stop debugging - ... '']) - >>> try: runner.run(test) - ... finally: sys.stdin = real_stdin + >>> sys.stdin = _FakeInput( + ... [ + ... "list", # list source from example 2 + ... "next", # return from g() + ... "list", # list source from example 1 + ... "next", # return from f() + ... "list", # list source from example 3 + ... "continue", # stop debugging + ... "", + ... ] + ... ) + >>> try: + ... runner.run(test) + ... finally: + ... sys.stdin = real_stdin ... # doctest: +NORMALIZE_WHITESPACE --Return-- > (3)g()->None @@ -2141,13 +2174,17 @@ def test_pdb_set_trace_nested(): >>> class C(object): ... def calls_set_trace(self): ... y = 1 - ... import pdb; pdb.set_trace() + ... import pdb + ... + ... pdb.set_trace() ... self.f1() ... y = 2 + ... ... def f1(self): ... x = 1 ... self.f2() ... x = 2 + ... ... def f2(self): ... z = 1 ... z = 2 @@ -2162,14 +2199,26 @@ def test_pdb_set_trace_nested(): >>> runner = doctest.DocTestRunner(verbose=False) >>> test = parser.get_doctest(doc, globals(), "foo-bar@baz", "foo-bar@baz.py", 0) >>> real_stdin = sys.stdin - >>> sys.stdin = _FakeInput([ - ... 'print(y)', # print data defined in the function - ... 'step', 'step', 'step', 'step', 'step', 'step', 'print(z)', - ... 'up', 'print(x)', - ... 'up', 'print(y)', - ... 'up', 'print(foo)', - ... 'continue', # stop debugging - ... '']) + >>> sys.stdin = _FakeInput( + ... [ + ... "print(y)", # print data defined in the function + ... "step", + ... "step", + ... "step", + ... "step", + ... "step", + ... "step", + ... "print(z)", + ... "up", + ... "print(x)", + ... "up", + ... "print(y)", + ... "up", + ... "print(foo)", + ... "continue", # stop debugging + ... "", + ... ] + ... ) >>> try: ... runner.run(test) @@ -2236,19 +2285,19 @@ def test_DocTestSuite(): We can also supply the module by name: - >>> suite = doctest.DocTestSuite('test.sample_doctest') + >>> suite = doctest.DocTestSuite("test.sample_doctest") >>> suite.run(unittest.TestResult()) The module need not contain any doctest examples: - >>> suite = doctest.DocTestSuite('test.sample_doctest_no_doctests') + >>> suite = doctest.DocTestSuite("test.sample_doctest_no_doctests") >>> suite.run(unittest.TestResult()) The module need not contain any docstrings either: - >>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings') + >>> suite = doctest.DocTestSuite("test.sample_doctest_no_docstrings") >>> suite.run(unittest.TestResult()) @@ -2261,16 +2310,14 @@ def test_DocTestSuite(): We can also provide a DocTestFinder: >>> finder = doctest.DocTestFinder() - >>> suite = doctest.DocTestSuite('test.sample_doctest', - ... test_finder=finder) + >>> suite = doctest.DocTestSuite("test.sample_doctest", test_finder=finder) >>> suite.run(unittest.TestResult()) The DocTestFinder need not return any tests: >>> finder = doctest.DocTestFinder() - >>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings', - ... test_finder=finder) + >>> suite = doctest.DocTestSuite("test.sample_doctest_no_docstrings", test_finder=finder) >>> suite.run(unittest.TestResult()) @@ -2278,23 +2325,23 @@ def test_DocTestSuite(): used instead of the module globals. Here we'll pass an empty globals, triggering an extra error: - >>> suite = doctest.DocTestSuite('test.sample_doctest', globs={}) + >>> suite = doctest.DocTestSuite("test.sample_doctest", globs={}) >>> suite.run(unittest.TestResult()) Alternatively, we can provide extra globals. Here we'll make an error go away by providing an extra global variable: - >>> suite = doctest.DocTestSuite('test.sample_doctest', - ... extraglobs={'y': 1}) + >>> suite = doctest.DocTestSuite("test.sample_doctest", extraglobs={"y": 1}) >>> suite.run(unittest.TestResult()) You can pass option flags. Here we'll cause an extra error by disabling the blank-line feature: - >>> suite = doctest.DocTestSuite('test.sample_doctest', - ... optionflags=doctest.DONT_ACCEPT_BLANKLINE) + >>> suite = doctest.DocTestSuite( + ... "test.sample_doctest", optionflags=doctest.DONT_ACCEPT_BLANKLINE + ... ) >>> suite.run(unittest.TestResult()) @@ -2302,16 +2349,17 @@ def test_DocTestSuite(): >>> def setUp(t): ... import test.test_doctest + ... ... test.test_doctest.sillySetup = True >>> def tearDown(t): ... import test.test_doctest + ... ... del test.test_doctest.sillySetup Here, we installed a silly variable that the test expects: - >>> suite = doctest.DocTestSuite('test.sample_doctest', - ... setUp=setUp, tearDown=tearDown) + >>> suite = doctest.DocTestSuite("test.sample_doctest", setUp=setUp, tearDown=tearDown) >>> suite.run(unittest.TestResult()) @@ -2327,9 +2375,9 @@ def test_DocTestSuite(): we'll use the setUp function to supply the missing variable y: >>> def setUp(test): - ... test.globs['y'] = 1 + ... test.globs["y"] = 1 - >>> suite = doctest.DocTestSuite('test.sample_doctest', setUp=setUp) + >>> suite = doctest.DocTestSuite("test.sample_doctest", setUp=setUp) >>> suite.run(unittest.TestResult()) @@ -2347,9 +2395,9 @@ def test_DocFileSuite(): files that include examples: >>> import unittest - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... 'test_doctest2.txt', - ... 'test_doctest4.txt') + >>> suite = doctest.DocFileSuite( + ... "test_doctest.txt", "test_doctest2.txt", "test_doctest4.txt" + ... ) >>> suite.run(unittest.TestResult()) @@ -2358,10 +2406,9 @@ def test_DocFileSuite(): specify a different relative location. >>> import unittest - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... 'test_doctest2.txt', - ... 'test_doctest4.txt', - ... package='test') + >>> suite = doctest.DocFileSuite( + ... "test_doctest.txt", "test_doctest2.txt", "test_doctest4.txt", package="test" + ... ) >>> suite.run(unittest.TestResult()) @@ -2370,14 +2417,13 @@ def test_DocFileSuite(): >>> import unittest, pkgutil, test >>> added_loader = False - >>> if not hasattr(test, '__loader__'): + >>> if not hasattr(test, "__loader__"): ... test.__loader__ = pkgutil.get_loader(test) ... added_loader = True >>> try: - ... suite = doctest.DocFileSuite('test_doctest.txt', - ... 'test_doctest2.txt', - ... 'test_doctest4.txt', - ... package='test') + ... suite = doctest.DocFileSuite( + ... "test_doctest.txt", "test_doctest2.txt", "test_doctest4.txt", package="test" + ... ) ... suite.run(unittest.TestResult()) ... finally: ... if added_loader: @@ -2387,7 +2433,7 @@ def test_DocFileSuite(): '/' should be used as a path separator. It will be converted to a native separator at run time: - >>> suite = doctest.DocFileSuite('../test/test_doctest.txt') + >>> suite = doctest.DocFileSuite("../test/test_doctest.txt") >>> suite.run(unittest.TestResult()) @@ -2397,8 +2443,7 @@ def test_DocFileSuite(): >>> import types, os.path, test.test_doctest >>> save_argv = sys.argv >>> sys.argv = [test.test_doctest.__file__] - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... package=types.ModuleType('__main__')) + >>> suite = doctest.DocFileSuite("test_doctest.txt", package=types.ModuleType("__main__")) >>> sys.argv = save_argv By setting `module_relative=False`, os-specific paths may be @@ -2410,7 +2455,7 @@ def test_DocFileSuite(): >>> test_pkg_path = os.path.split(test_doctest_path)[0] >>> # Use it to find the absolute path of test_doctest.txt. - >>> test_file = os.path.join(test_pkg_path, 'test_doctest.txt') + >>> test_file = os.path.join(test_pkg_path, "test_doctest.txt") >>> suite = doctest.DocFileSuite(test_file, module_relative=False) >>> suite.run(unittest.TestResult()) @@ -2418,28 +2463,31 @@ def test_DocFileSuite(): It is an error to specify `package` when `module_relative=False`: - >>> suite = doctest.DocFileSuite(test_file, module_relative=False, - ... package='test') + >>> suite = doctest.DocFileSuite(test_file, module_relative=False, package="test") Traceback (most recent call last): ValueError: Package may only be specified for module-relative paths. You can specify initial global variables: - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... 'test_doctest2.txt', - ... 'test_doctest4.txt', - ... globs={'favorite_color': 'blue'}) + >>> suite = doctest.DocFileSuite( + ... "test_doctest.txt", + ... "test_doctest2.txt", + ... "test_doctest4.txt", + ... globs={"favorite_color": "blue"}, + ... ) >>> suite.run(unittest.TestResult()) In this case, we supplied a missing favorite color. You can provide doctest options: - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... 'test_doctest2.txt', - ... 'test_doctest4.txt', - ... optionflags=doctest.DONT_ACCEPT_BLANKLINE, - ... globs={'favorite_color': 'blue'}) + >>> suite = doctest.DocFileSuite( + ... "test_doctest.txt", + ... "test_doctest2.txt", + ... "test_doctest4.txt", + ... optionflags=doctest.DONT_ACCEPT_BLANKLINE, + ... globs={"favorite_color": "blue"}, + ... ) >>> suite.run(unittest.TestResult()) @@ -2447,18 +2495,23 @@ def test_DocFileSuite(): >>> def setUp(t): ... import test.test_doctest + ... ... test.test_doctest.sillySetup = True >>> def tearDown(t): ... import test.test_doctest + ... ... del test.test_doctest.sillySetup Here, we installed a silly variable that the test expects: - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... 'test_doctest2.txt', - ... 'test_doctest4.txt', - ... setUp=setUp, tearDown=tearDown) + >>> suite = doctest.DocFileSuite( + ... "test_doctest.txt", + ... "test_doctest2.txt", + ... "test_doctest4.txt", + ... setUp=setUp, + ... tearDown=tearDown, + ... ) >>> suite.run(unittest.TestResult()) @@ -2475,9 +2528,9 @@ def test_DocFileSuite(): test_doctest.txt: >>> def setUp(test): - ... test.globs['favorite_color'] = 'blue' + ... test.globs["favorite_color"] = "blue" - >>> suite = doctest.DocFileSuite('test_doctest.txt', setUp=setUp) + >>> suite = doctest.DocFileSuite("test_doctest.txt", setUp=setUp) >>> suite.run(unittest.TestResult()) @@ -2489,7 +2542,7 @@ def test_DocFileSuite(): `__file__` global, which is set to the name of the file containing the tests: - >>> suite = doctest.DocFileSuite('test_doctest3.txt') + >>> suite = doctest.DocFileSuite("test_doctest3.txt") >>> suite.run(unittest.TestResult()) @@ -2497,10 +2550,9 @@ def test_DocFileSuite(): encoding the file is encoded with. We do so by using the `encoding` parameter: - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... 'test_doctest2.txt', - ... 'test_doctest4.txt', - ... encoding='utf-8') + >>> suite = doctest.DocFileSuite( + ... "test_doctest.txt", "test_doctest2.txt", "test_doctest4.txt", encoding="utf-8" + ... ) >>> suite.run(unittest.TestResult()) @@ -2511,7 +2563,7 @@ def test_trailing_space_in_test(): """ Trailing spaces in expected output are significant: - >>> x, y = 'foo', '' + >>> x, y = "foo", "" >>> print(x, y) foo \n """ @@ -2531,7 +2583,7 @@ def test_look_in_unwrapped(): """ Docstrings in wrapped functions must be detected as well. - >>> 'one other test' + >>> "one other test" 'one other test' """ @@ -2544,11 +2596,12 @@ def test_unittest_reportflags(): output without the flag. The file test_doctest.txt file has two tests. They both fail if blank lines are disabled: - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... optionflags=doctest.DONT_ACCEPT_BLANKLINE) + >>> suite = doctest.DocFileSuite( + ... "test_doctest.txt", optionflags=doctest.DONT_ACCEPT_BLANKLINE + ... ) >>> import unittest >>> result = suite.run(unittest.TestResult()) - >>> print(result.failures[0][1]) # doctest: +ELLIPSIS + >>> print(result.failures[0][1]) # doctest: +ELLIPSIS Traceback ... Failed example: favorite_color @@ -2559,13 +2612,12 @@ def test_unittest_reportflags(): Note that we see both failures displayed. - >>> old = doctest.set_unittest_reportflags( - ... doctest.REPORT_ONLY_FIRST_FAILURE) + >>> old = doctest.set_unittest_reportflags(doctest.REPORT_ONLY_FIRST_FAILURE) Now, when we run the test: >>> result = suite.run(unittest.TestResult()) - >>> print(result.failures[0][1]) # doctest: +ELLIPSIS + >>> print(result.failures[0][1]) # doctest: +ELLIPSIS Traceback ... Failed example: favorite_color @@ -2580,8 +2632,9 @@ def test_unittest_reportflags(): If we give any reporting options when we set up the tests, however: - >>> suite = doctest.DocFileSuite('test_doctest.txt', - ... optionflags=doctest.DONT_ACCEPT_BLANKLINE | doctest.REPORT_NDIFF) + >>> suite = doctest.DocFileSuite( + ... "test_doctest.txt", optionflags=doctest.DONT_ACCEPT_BLANKLINE | doctest.REPORT_NDIFF + ... ) Then the default eporting options are ignored: @@ -2590,7 +2643,7 @@ def test_unittest_reportflags(): *NOTE*: These doctest are intentionally not placed in raw string to depict the trailing whitespace using `\x20` in the diff below. - >>> print(result.failures[0][1]) # doctest: +ELLIPSIS + >>> print(result.failures[0][1]) # doctest: +ELLIPSIS Traceback ... Failed example: favorite_color @@ -2626,11 +2679,11 @@ def test_testfile(): We don't want `-v` in sys.argv for these tests. >>> save_argv = sys.argv - >>> if '-v' in sys.argv: - ... sys.argv = [arg for arg in save_argv if arg != '-v'] + >>> if "-v" in sys.argv: + ... sys.argv = [arg for arg in save_argv if arg != "-v"] - >>> doctest.testfile('test_doctest.txt') # doctest: +ELLIPSIS + >>> doctest.testfile("test_doctest.txt") # doctest: +ELLIPSIS ********************************************************************** File "...", line 6, in test_doctest.txt Failed example: @@ -2651,14 +2704,15 @@ def test_testfile(): Globals may be specified with the `globs` and `extraglobs` parameters: - >>> globs = {'favorite_color': 'blue'} - >>> doctest.testfile('test_doctest.txt', globs=globs) + >>> globs = {"favorite_color": "blue"} + >>> doctest.testfile("test_doctest.txt", globs=globs) TestResults(failed=0, attempted=2) >>> doctest.master = None # Reset master. - >>> extraglobs = {'favorite_color': 'red'} - >>> doctest.testfile('test_doctest.txt', globs=globs, - ... extraglobs=extraglobs) # doctest: +ELLIPSIS + >>> extraglobs = {"favorite_color": "red"} + >>> doctest.testfile( + ... "test_doctest.txt", globs=globs, extraglobs=extraglobs + ... ) # doctest: +ELLIPSIS ********************************************************************** File "...", line 6, in test_doctest.txt Failed example: @@ -2677,14 +2731,13 @@ def test_testfile(): The file may be made relative to a given module or package, using the optional `module_relative` parameter: - >>> doctest.testfile('test_doctest.txt', globs=globs, - ... module_relative='test') + >>> doctest.testfile("test_doctest.txt", globs=globs, module_relative="test") TestResults(failed=0, attempted=2) >>> doctest.master = None # Reset master. Verbosity can be increased with the optional `verbose` parameter: - >>> doctest.testfile('test_doctest.txt', globs=globs, verbose=True) + >>> doctest.testfile("test_doctest.txt", globs=globs, verbose=True) Trying: favorite_color Expecting: @@ -2711,7 +2764,7 @@ def test_testfile(): The name of the test may be specified with the optional `name` parameter: - >>> doctest.testfile('test_doctest.txt', name='newname') + >>> doctest.testfile("test_doctest.txt", name="newname") ... # doctest: +ELLIPSIS ********************************************************************** File "...", line 6, in newname @@ -2722,7 +2775,7 @@ def test_testfile(): The summary report may be suppressed with the optional `report` parameter: - >>> doctest.testfile('test_doctest.txt', report=False) + >>> doctest.testfile("test_doctest.txt", report=False) ... # doctest: +ELLIPSIS ********************************************************************** File "...", line 6, in test_doctest.txt @@ -2738,7 +2791,7 @@ def test_testfile(): exception on the first error (which may be useful for postmortem debugging): - >>> doctest.testfile('test_doctest.txt', raise_on_error=True) + >>> doctest.testfile("test_doctest.txt", raise_on_error=True) ... # doctest: +ELLIPSIS Traceback (most recent call last): doctest.UnexpectedException: ... @@ -2748,7 +2801,7 @@ def test_testfile(): it's unknown which encoding is used. The encoding can be specified using the optional keyword argument `encoding`: - >>> doctest.testfile('test_doctest4.txt', encoding='latin-1') # doctest: +ELLIPSIS + >>> doctest.testfile("test_doctest4.txt", encoding="latin-1") # doctest: +ELLIPSIS ********************************************************************** File "...", line 7, in test_doctest4.txt Failed example: @@ -2766,13 +2819,13 @@ def test_testfile(): TestResults(failed=2, attempted=2) >>> doctest.master = None # Reset master. - >>> doctest.testfile('test_doctest4.txt', encoding='utf-8') + >>> doctest.testfile("test_doctest4.txt", encoding="utf-8") TestResults(failed=0, attempted=2) >>> doctest.master = None # Reset master. Test the verbose output: - >>> doctest.testfile('test_doctest4.txt', encoding='utf-8', verbose=True) + >>> doctest.testfile("test_doctest4.txt", encoding="utf-8", verbose=True) Trying: 'föö' Expecting: @@ -2790,7 +2843,7 @@ def test_testfile(): Test passed. TestResults(failed=0, attempted=2) >>> doctest.master = None # Reset master. - >>> sys.argv = save_argv""" + """ class TestImporter(importlib.abc.MetaPathFinder, importlib.abc.ResourceLoader): @@ -2844,8 +2897,8 @@ def test_lineendings(): >>> import tempfile, os >>> fn = tempfile.mktemp() - >>> with open(fn, 'wb') as f: - ... f.write(b'Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n') + >>> with open(fn, "wb") as f: + ... f.write(b"Test:\r\n\r\n >>> x = 1 + 1\r\n\r\nDone.\r\n") 35 >>> doctest.testfile(fn, module_relative=False, verbose=False) TestResults(failed=0, attempted=1) @@ -2854,8 +2907,8 @@ def test_lineendings(): And now *nix line endings: >>> fn = tempfile.mktemp() - >>> with open(fn, 'wb') as f: - ... f.write(b'Test:\n\n >>> x = 1 + 1\n\nDone.\n') + >>> with open(fn, "wb") as f: + ... f.write(b"Test:\n\n >>> x = 1 + 1\n\nDone.\n") 30 >>> doctest.testfile(fn, module_relative=False, verbose=False) TestResults(failed=0, attempted=1) @@ -2864,8 +2917,8 @@ def test_lineendings(): And finally old Mac line endings: >>> fn = tempfile.mktemp() - >>> with open(fn, 'wb') as f: - ... f.write(b'Test:\r\r >>> x = 1 + 1\r\rDone.\r') + >>> with open(fn, "wb") as f: + ... f.write(b"Test:\r\r >>> x = 1 + 1\r\rDone.\r") 30 >>> doctest.testfile(fn, module_relative=False, verbose=False) TestResults(failed=0, attempted=1) @@ -2886,17 +2939,17 @@ def test_lineendings(): >>> os.mkdir(pkg) >>> os_helper.create_empty_file(os.path.join(pkg, "__init__.py")) >>> fn = os.path.join(pkg, "doctest_testfile.txt") - >>> with open(fn, 'wb') as f: + >>> with open(fn, "wb") as f: ... f.write( - ... b'Test:\r\n\r\n' - ... b' >>> x = 1 + 1\r\n\r\n' - ... b'Done.\r\n' - ... b'Test:\n\n' - ... b' >>> x = 1 + 1\n\n' - ... b'Done.\n' - ... b'Test:\r\r' - ... b' >>> x = 1 + 1\r\r' - ... b'Done.\r' + ... b"Test:\r\n\r\n" + ... b" >>> x = 1 + 1\r\n\r\n" + ... b"Done.\r\n" + ... b"Test:\n\n" + ... b" >>> x = 1 + 1\n\n" + ... b"Done.\n" + ... b"Test:\r\r" + ... b" >>> x = 1 + 1\r\r" + ... b"Done.\r" ... ) 95 >>> with test_hook(dn): @@ -2934,13 +2987,12 @@ def test_unicode(): >>> doc = ''' ... >>> raise Exception('clé') ... ''' - ... >>> parser = doctest.DocTestParser() >>> test = parser.get_doctest(doc, {}, "foo-bär@baz", "foo-bär@baz.py", 0) >>> test >>> runner = doctest.DocTestRunner(verbose=False) - >>> runner.run(test) # doctest: +ELLIPSIS + >>> runner.run(test) # doctest: +ELLIPSIS ********************************************************************** File "foo-bär@baz.py", line 2, in foo-bär@baz Failed example: @@ -2967,7 +3019,7 @@ def test_CLI(): output into something we can doctest against: >>> def normalize(s): - ... return '\n'.join(s.decode().splitlines()) + ... return "\n".join(s.decode().splitlines()) With those preliminaries out of the way, we'll start with a file with two simple tests and no errors. We'll run both the unadorned doctest command, and @@ -2976,19 +3028,17 @@ def test_CLI(): >>> from test.support import script_helper >>> from test.support.os_helper import temp_dir >>> with temp_dir() as tmpdir: - ... fn = os.path.join(tmpdir, 'myfile.doc') - ... with open(fn, 'w', encoding='utf-8') as f: - ... _ = f.write('This is a very simple test file.\n') - ... _ = f.write(' >>> 1 + 1\n') - ... _ = f.write(' 2\n') + ... fn = os.path.join(tmpdir, "myfile.doc") + ... with open(fn, "w", encoding="utf-8") as f: + ... _ = f.write("This is a very simple test file.\n") + ... _ = f.write(" >>> 1 + 1\n") + ... _ = f.write(" 2\n") ... _ = f.write(' >>> "a"\n') ... _ = f.write(" 'a'\n") - ... _ = f.write('\n') - ... _ = f.write('And that is it.\n') - ... rc1, out1, err1 = script_helper.assert_python_ok( - ... '-m', 'doctest', fn) - ... rc2, out2, err2 = script_helper.assert_python_ok( - ... '-m', 'doctest', '-v', fn) + ... _ = f.write("\n") + ... _ = f.write("And that is it.\n") + ... rc1, out1, err1 = script_helper.assert_python_ok("-m", "doctest", fn) + ... rc2, out2, err2 = script_helper.assert_python_ok("-m", "doctest", "-v", fn) With no arguments and passing tests, we should get no output: @@ -3069,7 +3119,7 @@ def test_CLI(): >>> rc1, err1 (1, b'') - >>> print(normalize(out1)) # doctest: +ELLIPSIS + >>> print(normalize(out1)) # doctest: +ELLIPSIS ********************************************************************** File "...myfile.doc", line 4, in myfile.doc Failed example: @@ -3104,7 +3154,7 @@ def test_CLI(): >>> rc4, err4 (1, b'') - >>> print(normalize(out4)) # doctest: +ELLIPSIS + >>> print(normalize(out4)) # doctest: +ELLIPSIS ********************************************************************** File "...myfile.doc", line 4, in myfile.doc Failed example: @@ -3166,12 +3216,11 @@ def test_CLI(): Invalid file name: - >>> rc, out, err = script_helper.assert_python_failure( - ... '-m', 'doctest', 'nosuchfile') + >>> rc, out, err = script_helper.assert_python_failure("-m", "doctest", "nosuchfile") >>> rc, out (1, b'') >>> # The exact error message changes depending on the platform. - >>> print(normalize(err)) # doctest: +ELLIPSIS + >>> print(normalize(err)) # doctest: +ELLIPSIS Traceback (most recent call last): ... FileNotFoundError: [Errno ...] ...nosuchfile... @@ -3179,10 +3228,11 @@ def test_CLI(): Invalid doctest option: >>> rc, out, err = script_helper.assert_python_failure( - ... '-m', 'doctest', '-o', 'nosuchoption') + ... "-m", "doctest", "-o", "nosuchoption" + ... ) >>> rc, out (2, b'') - >>> print(normalize(err)) # doctest: +ELLIPSIS + >>> print(normalize(err)) # doctest: +ELLIPSIS usage...invalid...nosuchoption... """ @@ -3247,21 +3297,23 @@ def test_run_doctestsuite_multiple_times(): def test_exception_with_note(note): """ - >>> test_exception_with_note('Note') + >>> test_exception_with_note("Note") Traceback (most recent call last): ... ValueError: Text Note - >>> test_exception_with_note('Note') # doctest: +IGNORE_EXCEPTION_DETAIL + >>> test_exception_with_note("Note") # doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ... ValueError: Text Note - >>> test_exception_with_note('''Note + >>> test_exception_with_note( + ... '''Note ... multiline - ... example''') + ... example''' + ... ) Traceback (most recent call last): ValueError: Text Note diff --git a/Lib/test/test_doctest2.py b/Lib/test/test_doctest2.py index b62e7a1a939a9f..c7629108fab1f0 100644 --- a/Lib/test/test_doctest2.py +++ b/Lib/test/test_doctest2.py @@ -35,13 +35,13 @@ class C(object): def __init__(self): """C.__init__. - >>> print(C()) # 3 + >>> print(C()) # 3 42 """ def __str__(self): """ - >>> print(C()) # 4 + >>> print(C()) # 4 42 """ return "42" @@ -49,20 +49,20 @@ def __str__(self): class D(object): """A nested D class. - >>> print("In D!") # 5 + >>> print("In D!") # 5 In D! """ def nested(self): """ - >>> print(3) # 6 + >>> print(3) # 6 3 """ def getx(self): """ - >>> c = C() # 7 - >>> c.x = 12 # 8 + >>> c = C() # 7 + >>> c.x = 12 # 8 >>> print(c.x) # 9 -12 """ @@ -70,9 +70,9 @@ def getx(self): def setx(self, value): """ - >>> c = C() # 10 - >>> c.x = 12 # 11 - >>> print(c.x) # 12 + >>> c = C() # 10 + >>> c.x = 12 # 11 + >>> print(c.x) # 12 -12 """ self._x = value @@ -93,7 +93,7 @@ def statm(): """ A static method. - >>> print(C.statm()) # 16 + >>> print(C.statm()) # 16 666 >>> print(C().statm()) # 17 666 @@ -105,7 +105,7 @@ def clsm(cls, val): """ A class method. - >>> print(C.clsm(22)) # 18 + >>> print(C.clsm(22)) # 18 22 >>> print(C().clsm(23)) # 19 23 diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index c602913ca69277..6c0946da061ee3 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -24,49 +24,55 @@ python_version = sys.version_info[:2] + def load_tests(loader, tests, ignore): tests.addTests(doctest.DocTestSuite(enum)) - lib_tests = os.path.join(REPO_ROOT, 'Doc/library/enum.rst') + lib_tests = os.path.join(REPO_ROOT, "Doc/library/enum.rst") if os.path.exists(lib_tests): - tests.addTests(doctest.DocFileSuite( + tests.addTests( + doctest.DocFileSuite( lib_tests, module_relative=False, - optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE, - )) - howto_tests = os.path.join(REPO_ROOT, 'Doc/howto/enum.rst') + optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE, + ) + ) + howto_tests = os.path.join(REPO_ROOT, "Doc/howto/enum.rst") if os.path.exists(howto_tests): - tests.addTests(doctest.DocFileSuite( + tests.addTests( + doctest.DocFileSuite( howto_tests, module_relative=False, - optionflags=doctest.ELLIPSIS|doctest.NORMALIZE_WHITESPACE, - )) + optionflags=doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE, + ) + ) return tests + def reraise_if_not_enum(*enum_types_or_exceptions): from functools import wraps def decorator(func): @wraps(func) def inner(*args, **kwargs): - excs = [ - e - for e in enum_types_or_exceptions - if isinstance(e, Exception) - ] + excs = [e for e in enum_types_or_exceptions if isinstance(e, Exception)] if len(excs) == 1: raise excs[0] elif excs: - raise ExceptionGroup('Enum Exceptions', excs) + raise ExceptionGroup("Enum Exceptions", excs) return func(*args, **kwargs) + return inner + return decorator + MODULE = __name__ -SHORT_MODULE = MODULE.split('.')[-1] +SHORT_MODULE = MODULE.split(".")[-1] # for pickle tests try: + class Stooges(Enum): LARRY = 1 CURLY = 2 @@ -75,6 +81,7 @@ class Stooges(Enum): Stooges = exc try: + class IntStooges(int, Enum): LARRY = 1 CURLY = 2 @@ -83,6 +90,7 @@ class IntStooges(int, Enum): IntStooges = exc try: + class FloatStooges(float, Enum): LARRY = 1.39 CURLY = 2.72 @@ -91,6 +99,7 @@ class FloatStooges(float, Enum): FloatStooges = exc try: + class FlagStooges(Flag): LARRY = 1 CURLY = 2 @@ -100,6 +109,7 @@ class FlagStooges(Flag): FlagStooges = exc try: + class FlagStoogesWithZero(Flag): NOFLAG = 0 LARRY = 1 @@ -110,6 +120,7 @@ class FlagStoogesWithZero(Flag): FlagStoogesWithZero = exc try: + class IntFlagStooges(IntFlag): LARRY = 1 CURLY = 2 @@ -119,6 +130,7 @@ class IntFlagStooges(IntFlag): IntFlagStooges = exc try: + class IntFlagStoogesWithZero(IntFlag): NOFLAG = 0 LARRY = 1 @@ -130,29 +142,31 @@ class IntFlagStoogesWithZero(IntFlag): # for pickle test and subclass tests try: + class Name(StrEnum): - BDFL = 'Guido van Rossum' - FLUFL = 'Barry Warsaw' + BDFL = "Guido van Rossum" + FLUFL = "Barry Warsaw" except Exception as exc: Name = exc try: - Question = Enum('Question', 'who what when where why', module=__name__) + Question = Enum("Question", "who what when where why", module=__name__) except Exception as exc: Question = exc try: - Answer = Enum('Answer', 'him this then there because') + Answer = Enum("Answer", "him this then there because") except Exception as exc: Answer = exc try: - Theory = Enum('Theory', 'rule law supposition', qualname='spanish_inquisition') + Theory = Enum("Theory", "rule law supposition", qualname="spanish_inquisition") except Exception as exc: Theory = exc # for doctests try: + class Fruit(Enum): TOMATO = 1 BANANA = 2 @@ -160,30 +174,38 @@ class Fruit(Enum): except Exception: pass + def test_pickle_dump_load(assertion, source, target=None): if target is None: target = source for protocol in range(HIGHEST_PROTOCOL + 1): assertion(loads(dumps(source, protocol=protocol)), target) + def test_pickle_exception(assertion, exception, obj): for protocol in range(HIGHEST_PROTOCOL + 1): with assertion(exception): dumps(obj, protocol=protocol) + class TestHelpers(unittest.TestCase): # _is_descriptor, _is_sunder, _is_dunder - sunder_names = '_bad_', '_good_', '_what_ho_' - dunder_names = '__mal__', '__bien__', '__que_que__' - private_names = '_MyEnum__private', '_MyEnum__still_private', '_MyEnum___triple_private' - private_and_sunder_names = '_MyEnum__private_', '_MyEnum__also_private_' - random_names = 'okay', '_semi_private', '_weird__', '_MyEnum__' + sunder_names = "_bad_", "_good_", "_what_ho_" + dunder_names = "__mal__", "__bien__", "__que_que__" + private_names = ( + "_MyEnum__private", + "_MyEnum__still_private", + "_MyEnum___triple_private", + ) + private_and_sunder_names = "_MyEnum__private_", "_MyEnum__also_private_" + random_names = "okay", "_semi_private", "_weird__", "_MyEnum__" def test_is_descriptor(self): class foo: pass - for attr in ('__get__','__set__','__delete__'): + + for attr in ("__get__", "__set__", "__delete__"): obj = foo() self.assertFalse(enum._is_descriptor(obj)) setattr(obj, attr, 1) @@ -191,42 +213,76 @@ class foo: def test_sunder(self): for name in self.sunder_names + self.private_and_sunder_names: - self.assertTrue(enum._is_sunder(name), '%r is a not sunder name?' % name) + self.assertTrue(enum._is_sunder(name), "%r is a not sunder name?" % name) for name in self.dunder_names + self.private_names + self.random_names: - self.assertFalse(enum._is_sunder(name), '%r is a sunder name?' % name) - for s in ('_a_', '_aa_'): + self.assertFalse(enum._is_sunder(name), "%r is a sunder name?" % name) + for s in ("_a_", "_aa_"): self.assertTrue(enum._is_sunder(s)) - for s in ('a', 'a_', '_a', '__a', 'a__', '__a__', '_a__', '__a_', '_', - '__', '___', '____', '_____',): + for s in ( + "a", + "a_", + "_a", + "__a", + "a__", + "__a__", + "_a__", + "__a_", + "_", + "__", + "___", + "____", + "_____", + ): self.assertFalse(enum._is_sunder(s)) def test_dunder(self): for name in self.dunder_names: - self.assertTrue(enum._is_dunder(name), '%r is a not dunder name?' % name) - for name in self.sunder_names + self.private_names + self.private_and_sunder_names + self.random_names: - self.assertFalse(enum._is_dunder(name), '%r is a dunder name?' % name) - for s in ('__a__', '__aa__'): + self.assertTrue(enum._is_dunder(name), "%r is a not dunder name?" % name) + for name in ( + self.sunder_names + + self.private_names + + self.private_and_sunder_names + + self.random_names + ): + self.assertFalse(enum._is_dunder(name), "%r is a dunder name?" % name) + for s in ("__a__", "__aa__"): self.assertTrue(enum._is_dunder(s)) - for s in ('a', 'a_', '_a', '__a', 'a__', '_a_', '_a__', '__a_', '_', - '__', '___', '____', '_____',): + for s in ( + "a", + "a_", + "_a", + "__a", + "a__", + "_a_", + "_a__", + "__a_", + "_", + "__", + "___", + "____", + "_____", + ): self.assertFalse(enum._is_dunder(s)) - def test_is_private(self): for name in self.private_names + self.private_and_sunder_names: - self.assertTrue(enum._is_private('MyEnum', name), '%r is a not private name?') + self.assertTrue( + enum._is_private("MyEnum", name), "%r is a not private name?" + ) for name in self.sunder_names + self.dunder_names + self.random_names: - self.assertFalse(enum._is_private('MyEnum', name), '%r is a private name?') + self.assertFalse(enum._is_private("MyEnum", name), "%r is a private name?") def test_iter_bits_lsb(self): self.assertEqual(list(_iter_bits_lsb(7)), [1, 2, 4]) - self.assertRaisesRegex(ValueError, '-8 is not a positive integer', list, _iter_bits_lsb(-8)) + self.assertRaisesRegex( + ValueError, "-8 is not a positive integer", list, _iter_bits_lsb(-8) + ) # for subclassing tests -class classproperty: +class classproperty: def __init__(self, fget=None, fset=None, fdel=None, doc=None): self.fget = fget self.fset = fset @@ -238,9 +294,11 @@ def __init__(self, fget=None, fset=None, fdel=None, doc=None): def __get__(self, instance, ownerclass): return self.fget(ownerclass) + # for global repr tests try: + @enum.global_enum class HeadlightsK(IntFlag, boundary=enum.KEEP): OFF_K = 0 @@ -252,6 +310,7 @@ class HeadlightsK(IntFlag, boundary=enum.KEEP): try: + @enum.global_enum class HeadlightsC(IntFlag, boundary=enum.CONFORM): OFF_C = 0 @@ -263,6 +322,7 @@ class HeadlightsC(IntFlag, boundary=enum.CONFORM): try: + @enum.global_enum class NoName(Flag): ONE = 1 @@ -273,6 +333,7 @@ class NoName(Flag): # tests + class _EnumTests: """ Test for behavior that is the same across the different types of enumerations. @@ -281,11 +342,13 @@ class _EnumTests: values = None def setUp(self): - if self.__class__.__name__[-5:] == 'Class': + if self.__class__.__name__[-5:] == "Class": + class BaseEnum(self.enum_type): @enum.property def first(self): - return '%s is first!' % self.name + return "%s is first!" % self.name + class MainEnum(BaseEnum): first = auto() second = auto() @@ -294,55 +357,75 @@ class MainEnum(BaseEnum): dupe = 3 else: dupe = third + self.MainEnum = MainEnum + # class NewStrEnum(self.enum_type): def __str__(self): return self.name.upper() + first = auto() + self.NewStrEnum = NewStrEnum + # class NewFormatEnum(self.enum_type): def __format__(self, spec): return self.name.upper() + first = auto() + self.NewFormatEnum = NewFormatEnum + # class NewStrFormatEnum(self.enum_type): def __str__(self): return self.name.title() + def __format__(self, spec): - return ''.join(reversed(self.name)) + return "".join(reversed(self.name)) + first = auto() + self.NewStrFormatEnum = NewStrFormatEnum + # class NewBaseEnum(self.enum_type): def __str__(self): return self.name.title() + def __format__(self, spec): - return ''.join(reversed(self.name)) + return "".join(reversed(self.name)) + self.NewBaseEnum = NewBaseEnum + class NewSubEnum(NewBaseEnum): first = auto() + self.NewSubEnum = NewSubEnum + # class LazyGNV(self.enum_type): def _generate_next_value_(name, start, last, values): pass + self.LazyGNV = LazyGNV + # class BusyGNV(self.enum_type): @staticmethod def _generate_next_value_(name, start, last, values): pass + self.BusyGNV = BusyGNV # self.is_flag = False - self.names = ['first', 'second', 'third'] + self.names = ["first", "second", "third"] if issubclass(MainEnum, StrEnum): self.values = self.names elif MainEnum._member_type_ is str: - self.values = ['1', '2', '3'] + self.values = ["1", "2", "3"] elif issubclass(self.enum_type, Flag): self.values = [1, 2, 4] self.is_flag = True @@ -350,13 +433,15 @@ def _generate_next_value_(name, start, last, values): else: self.values = self.values or [1, 2, 3] # - if not getattr(self, 'source_values', False): + if not getattr(self, "source_values", False): self.source_values = self.values - elif self.__class__.__name__[-8:] == 'Function': + elif self.__class__.__name__[-8:] == "Function": + @enum.property def first(self): - return '%s is first!' % self.name - BaseEnum = self.enum_type('BaseEnum', {'first':first}) + return "%s is first!" % self.name + + BaseEnum = self.enum_type("BaseEnum", {"first": first}) # first = auto() second = auto() @@ -365,47 +450,76 @@ def first(self): dupe = 3 else: dupe = third - self.MainEnum = MainEnum = BaseEnum('MainEnum', dict(first=first, second=second, third=third, dupe=dupe)) + self.MainEnum = MainEnum = BaseEnum( + "MainEnum", dict(first=first, second=second, third=third, dupe=dupe) + ) + # def __str__(self): return self.name.upper() + first = auto() - self.NewStrEnum = self.enum_type('NewStrEnum', (('first',first),('__str__',__str__))) + self.NewStrEnum = self.enum_type( + "NewStrEnum", (("first", first), ("__str__", __str__)) + ) + # def __format__(self, spec): return self.name.upper() + first = auto() - self.NewFormatEnum = self.enum_type('NewFormatEnum', [('first',first),('__format__',__format__)]) + self.NewFormatEnum = self.enum_type( + "NewFormatEnum", [("first", first), ("__format__", __format__)] + ) + # def __str__(self): return self.name.title() + def __format__(self, spec): - return ''.join(reversed(self.name)) + return "".join(reversed(self.name)) + first = auto() - self.NewStrFormatEnum = self.enum_type('NewStrFormatEnum', dict(first=first, __format__=__format__, __str__=__str__)) + self.NewStrFormatEnum = self.enum_type( + "NewStrFormatEnum", + dict(first=first, __format__=__format__, __str__=__str__), + ) + # def __str__(self): return self.name.title() + def __format__(self, spec): - return ''.join(reversed(self.name)) - self.NewBaseEnum = self.enum_type('NewBaseEnum', dict(__format__=__format__, __str__=__str__)) - self.NewSubEnum = self.NewBaseEnum('NewSubEnum', 'first') + return "".join(reversed(self.name)) + + self.NewBaseEnum = self.enum_type( + "NewBaseEnum", dict(__format__=__format__, __str__=__str__) + ) + self.NewSubEnum = self.NewBaseEnum("NewSubEnum", "first") + # def _generate_next_value_(name, start, last, values): pass - self.LazyGNV = self.enum_type('LazyGNV', {'_generate_next_value_':_generate_next_value_}) + + self.LazyGNV = self.enum_type( + "LazyGNV", {"_generate_next_value_": _generate_next_value_} + ) + # @staticmethod def _generate_next_value_(name, start, last, values): pass - self.BusyGNV = self.enum_type('BusyGNV', {'_generate_next_value_':_generate_next_value_}) + + self.BusyGNV = self.enum_type( + "BusyGNV", {"_generate_next_value_": _generate_next_value_} + ) # self.is_flag = False - self.names = ['first', 'second', 'third'] + self.names = ["first", "second", "third"] if issubclass(MainEnum, StrEnum): self.values = self.names elif MainEnum._member_type_ is str: - self.values = ['1', '2', '3'] + self.values = ["1", "2", "3"] elif issubclass(self.enum_type, Flag): self.values = [1, 2, 4] self.is_flag = True @@ -413,10 +527,10 @@ def _generate_next_value_(name, start, last, values): else: self.values = self.values or [1, 2, 3] # - if not getattr(self, 'source_values', False): + if not getattr(self, "source_values", False): self.source_values = self.values else: - raise ValueError('unknown enum style: %r' % self.__class__.__name__) + raise ValueError("unknown enum style: %r" % self.__class__.__name__) def assertFormatIsValue(self, spec, member): self.assertEqual(spec.format(member), spec.format(member.value)) @@ -429,13 +543,15 @@ class Season(self.enum_type): SPRING = auto() SUMMER = auto() AUTUMN = auto() + # def spam(cls): pass + # - self.assertTrue(hasattr(Season, 'spam')) + self.assertTrue(hasattr(Season, "spam")) del Season.spam - self.assertFalse(hasattr(Season, 'spam')) + self.assertFalse(hasattr(Season, "spam")) # with self.assertRaises(AttributeError): del Season.SPRING @@ -446,13 +562,15 @@ def spam(cls): def test_bad_new_super(self): with self.assertRaisesRegex( - TypeError, - 'has no members defined', - ): + TypeError, + "has no members defined", + ): + class BadSuper(self.enum_type): def __new__(cls, value): obj = super().__new__(cls, value) return obj + failed = 1 def test_basics(self): @@ -468,33 +586,34 @@ def test_basics(self): self.assertEqual(format(TE), "") self.assertEqual(list(TE), [TE.first, TE.second, TE.third]) self.assertEqual( - [m.name for m in TE], - self.names, - ) + [m.name for m in TE], + self.names, + ) self.assertEqual( - [m.value for m in TE], - self.values, - ) + [m.value for m in TE], + self.values, + ) self.assertEqual( - [m.first for m in TE], - ['first is first!', 'second is first!', 'third is first!'] - ) + [m.first for m in TE], + ["first is first!", "second is first!", "third is first!"], + ) for member, name in zip(TE, self.names, strict=True): self.assertIs(TE[name], member) for member, value in zip(TE, self.values, strict=True): self.assertIs(TE(value), member) if issubclass(TE, StrEnum): - self.assertTrue(TE.dupe is TE('third') is TE['dupe']) + self.assertTrue(TE.dupe is TE("third") is TE["dupe"]) elif TE._member_type_ is str: - self.assertTrue(TE.dupe is TE('3') is TE['dupe']) + self.assertTrue(TE.dupe is TE("3") is TE["dupe"]) elif issubclass(TE, Flag): - self.assertTrue(TE.dupe is TE(3) is TE['dupe']) + self.assertTrue(TE.dupe is TE(3) is TE["dupe"]) else: - self.assertTrue(TE.dupe is TE(self.values[2]) is TE['dupe']) + self.assertTrue(TE.dupe is TE(self.values[2]) is TE["dupe"]) def test_bool_is_true(self): class Empty(self.enum_type): pass + self.assertTrue(Empty) # self.assertTrue(self.MainEnum) @@ -504,20 +623,22 @@ class Empty(self.enum_type): def test_changing_member_fails(self): MainEnum = self.MainEnum with self.assertRaises(AttributeError): - self.MainEnum.second = 'really first' + self.MainEnum.second = "really first" def test_contains_tf(self): MainEnum = self.MainEnum self.assertIn(MainEnum.first, MainEnum) self.assertTrue(self.values[0] in MainEnum) if type(self) not in (TestStrEnumClass, TestStrEnumFunction): - self.assertFalse('first' in MainEnum) + self.assertFalse("first" in MainEnum) val = MainEnum.dupe self.assertIn(val, MainEnum) + # class OtherEnum(Enum): one = auto() two = auto() + self.assertNotIn(OtherEnum.two, MainEnum) # if MainEnum._member_type_ is object: @@ -525,6 +646,7 @@ class OtherEnum(Enum): class NotEqualEnum(self.enum_type): this = self.source_values[0] that = self.source_values[1] + self.assertNotIn(NotEqualEnum.this, MainEnum) self.assertNotIn(NotEqualEnum.that, MainEnum) else: @@ -532,16 +654,19 @@ class NotEqualEnum(self.enum_type): class EqualEnum(self.enum_type): this = self.source_values[0] that = self.source_values[1] + self.assertIn(EqualEnum.this, MainEnum) self.assertIn(EqualEnum.that, MainEnum) def test_contains_same_name_diff_enum_diff_values(self): MainEnum = self.MainEnum + # class OtherEnum(Enum): first = "brand" second = "new" third = "values" + # self.assertIn(MainEnum.first, MainEnum) self.assertIn(MainEnum.second, MainEnum) @@ -569,20 +694,24 @@ def test_dir_with_added_behavior(self): class Test(self.enum_type): this = auto() these = auto() + def wowser(self): - return ("Wowser! I'm %s!" % self.name) - self.assertTrue('wowser' not in dir(Test)) - self.assertTrue('wowser' in dir(Test.this)) + return "Wowser! I'm %s!" % self.name + + self.assertTrue("wowser" not in dir(Test)) + self.assertTrue("wowser" in dir(Test.this)) def test_dir_on_sub_with_behavior_on_super(self): # see issue22506 class SuperEnum(self.enum_type): def invisible(self): return "did you see me?" + class SubEnum(SuperEnum): sample = auto() - self.assertTrue('invisible' not in dir(SubEnum)) - self.assertTrue('invisible' in dir(SubEnum.sample)) + + self.assertTrue("invisible" not in dir(SubEnum)) + self.assertTrue("invisible" in dir(SubEnum.sample)) def test_dir_on_sub_with_behavior_including_instance_dict_on_super(self): # see issue40084 @@ -593,17 +722,19 @@ def __new__(cls, *value, **kwds): obj = new(cls) else: if isinstance(value[0], tuple): - create_value ,= value[0] + (create_value,) = value[0] else: create_value = value obj = new(cls, *create_value) obj._value_ = value[0] if len(value) == 1 else value - obj.description = 'test description' + obj.description = "test description" return obj + class SubEnum(SuperEnum): sample = self.source_values[1] - self.assertTrue('description' not in dir(SubEnum)) - self.assertTrue('description' in dir(SubEnum.sample), dir(SubEnum.sample)) + + self.assertTrue("description" not in dir(SubEnum)) + self.assertTrue("description" in dir(SubEnum.sample), dir(SubEnum.sample)) def test_empty_enum_has_no_values(self): with self.assertRaisesRegex(TypeError, "<.... 'NewBaseEnum'> has no members"): @@ -616,42 +747,55 @@ def test_enum_in_enum_out(self): def test_gnv_is_static(self): lazy = self.LazyGNV busy = self.BusyGNV - self.assertTrue(type(lazy.__dict__['_generate_next_value_']) is staticmethod) - self.assertTrue(type(busy.__dict__['_generate_next_value_']) is staticmethod) + self.assertTrue(type(lazy.__dict__["_generate_next_value_"]) is staticmethod) + self.assertTrue(type(busy.__dict__["_generate_next_value_"]) is staticmethod) def test_hash(self): MainEnum = self.MainEnum mapping = {} - mapping[MainEnum.first] = '1225' - mapping[MainEnum.second] = '0315' - mapping[MainEnum.third] = '0704' - self.assertEqual(mapping[MainEnum.second], '0315') + mapping[MainEnum.first] = "1225" + mapping[MainEnum.second] = "0315" + mapping[MainEnum.third] = "0704" + self.assertEqual(mapping[MainEnum.second], "0315") def test_invalid_names(self): with self.assertRaises(ValueError): + class Wrong(self.enum_type): mro = 9 + with self.assertRaises(ValueError): + class Wrong(self.enum_type): - _create_= 11 + _create_ = 11 + with self.assertRaises(ValueError): + class Wrong(self.enum_type): _get_mixins_ = 9 + with self.assertRaises(ValueError): + class Wrong(self.enum_type): _find_new_ = 1 + with self.assertRaises(ValueError): + class Wrong(self.enum_type): _any_name_ = 9 def test_object_str_override(self): "check that setting __str__ to object's is not reset to Enum's" + class Generic(self.enum_type): item = self.source_values[2] + def __repr__(self): - return "%s.test" % (self._name_, ) + return "%s.test" % (self._name_,) + __str__ = object.__str__ - self.assertEqual(str(Generic.item), 'item.test') + + self.assertEqual(str(Generic.item), "item.test") def test_overridden_str(self): NS = self.NewStrEnum @@ -661,30 +805,32 @@ def test_overridden_str(self): def test_overridden_str_format(self): NSF = self.NewStrFormatEnum self.assertEqual(str(NSF.first), NSF.first.name.title()) - self.assertEqual(format(NSF.first), ''.join(reversed(NSF.first.name))) + self.assertEqual(format(NSF.first), "".join(reversed(NSF.first.name))) def test_overridden_str_format_inherited(self): NSE = self.NewSubEnum self.assertEqual(str(NSE.first), NSE.first.name.title()) - self.assertEqual(format(NSE.first), ''.join(reversed(NSE.first.name))) + self.assertEqual(format(NSE.first), "".join(reversed(NSE.first.name))) def test_programmatic_function_string(self): - MinorEnum = self.enum_type('MinorEnum', 'june july august') + MinorEnum = self.enum_type("MinorEnum", "june july august") lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) values = self.values if self.enum_type is StrEnum: - values = ['june','july','august'] - for month, av in zip('june july august'.split(), values): + values = ["june", "july", "august"] + for month, av in zip("june july august".split(), values): e = MinorEnum[month] self.assertEqual(e.value, av, list(MinorEnum)) self.assertEqual(e.name, month) - if MinorEnum._member_type_ is not object and issubclass(MinorEnum, MinorEnum._member_type_): + if MinorEnum._member_type_ is not object and issubclass( + MinorEnum, MinorEnum._member_type_ + ): self.assertEqual(e, av) else: self.assertNotEqual(e, av) @@ -693,22 +839,24 @@ def test_programmatic_function_string(self): self.assertIs(e, MinorEnum(av)) def test_programmatic_function_string_list(self): - MinorEnum = self.enum_type('MinorEnum', ['june', 'july', 'august']) + MinorEnum = self.enum_type("MinorEnum", ["june", "july", "august"]) lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) values = self.values if self.enum_type is StrEnum: - values = ['june','july','august'] - for month, av in zip('june july august'.split(), values): + values = ["june", "july", "august"] + for month, av in zip("june july august".split(), values): e = MinorEnum[month] self.assertEqual(e.value, av) self.assertEqual(e.name, month) - if MinorEnum._member_type_ is not object and issubclass(MinorEnum, MinorEnum._member_type_): + if MinorEnum._member_type_ is not object and issubclass( + MinorEnum, MinorEnum._member_type_ + ): self.assertEqual(e, av) else: self.assertNotEqual(e, av) @@ -718,21 +866,27 @@ def test_programmatic_function_string_list(self): def test_programmatic_function_iterable(self): MinorEnum = self.enum_type( - 'MinorEnum', - (('june', self.source_values[0]), ('july', self.source_values[1]), ('august', self.source_values[2])) - ) + "MinorEnum", + ( + ("june", self.source_values[0]), + ("july", self.source_values[1]), + ("august", self.source_values[2]), + ), + ) lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) - for month, av in zip('june july august'.split(), self.values): + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) + for month, av in zip("june july august".split(), self.values): e = MinorEnum[month] self.assertEqual(e.value, av) self.assertEqual(e.name, month) - if MinorEnum._member_type_ is not object and issubclass(MinorEnum, MinorEnum._member_type_): + if MinorEnum._member_type_ is not object and issubclass( + MinorEnum, MinorEnum._member_type_ + ): self.assertEqual(e, av) else: self.assertNotEqual(e, av) @@ -742,19 +896,27 @@ def test_programmatic_function_iterable(self): def test_programmatic_function_from_dict(self): MinorEnum = self.enum_type( - 'MinorEnum', - OrderedDict((('june', self.source_values[0]), ('july', self.source_values[1]), ('august', self.source_values[2]))) + "MinorEnum", + OrderedDict( + ( + ("june", self.source_values[0]), + ("july", self.source_values[1]), + ("august", self.source_values[2]), ) + ), + ) lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) - for month, av in zip('june july august'.split(), self.values): + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) + for month, av in zip("june july august".split(), self.values): e = MinorEnum[month] - if MinorEnum._member_type_ is not object and issubclass(MinorEnum, MinorEnum._member_type_): + if MinorEnum._member_type_ is not object and issubclass( + MinorEnum, MinorEnum._member_type_ + ): self.assertEqual(e, av) else: self.assertNotEqual(e, av) @@ -771,47 +933,59 @@ def test_repr(self): elif issubclass(TE, StrEnum): self.assertEqual(repr(TE.dupe), "") else: - self.assertEqual(repr(TE.dupe), "" % (self.values[2], ), TE._value_repr_) + self.assertEqual( + repr(TE.dupe), + "" % (self.values[2],), + TE._value_repr_, + ) for name, value, member in zip(self.names, self.values, TE, strict=True): - self.assertEqual(repr(member), "" % (member.name, member.value)) + self.assertEqual( + repr(member), "" % (member.name, member.value) + ) def test_repr_override(self): class Generic(self.enum_type): first = auto() second = auto() third = auto() + def __repr__(self): return "don't you just love shades of %s?" % self.name + self.assertEqual( - repr(Generic.third), - "don't you just love shades of third?", - ) + repr(Generic.third), + "don't you just love shades of third?", + ) def test_inherited_repr(self): class MyEnum(self.enum_type): def __repr__(self): return "My name is %s." % self.name + class MySubEnum(MyEnum): this = auto() that = auto() theother = auto() + self.assertEqual(repr(MySubEnum.that), "My name is that.") def test_multiple_superclasses_repr(self): class _EnumSuperClass(metaclass=EnumMeta): pass + class E(_EnumSuperClass, Enum): A = 1 + self.assertEqual(repr(E.A), "") def test_reversed_iteration_order(self): self.assertEqual( - list(reversed(self.MainEnum)), - [self.MainEnum.third, self.MainEnum.second, self.MainEnum.first], - ) + list(reversed(self.MainEnum)), + [self.MainEnum.third, self.MainEnum.second, self.MainEnum.first], + ) -class _PlainOutputTests: +class _PlainOutputTests: def test_str(self): TE = self.MainEnum if self.is_flag: @@ -821,7 +995,7 @@ def test_str(self): else: self.assertEqual(str(TE.dupe), "MainEnum.third") for name, value, member in zip(self.names, self.values, TE, strict=True): - self.assertEqual(str(member), "MainEnum.%s" % (member.name, )) + self.assertEqual(str(member), "MainEnum.%s" % (member.name,)) def test_format(self): TE = self.MainEnum @@ -831,26 +1005,27 @@ def test_format(self): else: self.assertEqual(format(TE.dupe), "MainEnum.third") for name, value, member in zip(self.names, self.values, TE, strict=True): - self.assertEqual(format(member), "MainEnum.%s" % (member.name, )) + self.assertEqual(format(member), "MainEnum.%s" % (member.name,)) def test_overridden_format(self): NF = self.NewFormatEnum - self.assertEqual(str(NF.first), "NewFormatEnum.first", '%s %r' % (NF.__str__, NF.first)) + self.assertEqual( + str(NF.first), "NewFormatEnum.first", "%s %r" % (NF.__str__, NF.first) + ) self.assertEqual(format(NF.first), "FIRST") def test_format_specs(self): TE = self.MainEnum - self.assertFormatIsStr('{}', TE.second) - self.assertFormatIsStr('{:}', TE.second) - self.assertFormatIsStr('{:20}', TE.second) - self.assertFormatIsStr('{:^20}', TE.second) - self.assertFormatIsStr('{:>20}', TE.second) - self.assertFormatIsStr('{:<20}', TE.second) - self.assertFormatIsStr('{:5.2}', TE.second) + self.assertFormatIsStr("{}", TE.second) + self.assertFormatIsStr("{:}", TE.second) + self.assertFormatIsStr("{:20}", TE.second) + self.assertFormatIsStr("{:^20}", TE.second) + self.assertFormatIsStr("{:>20}", TE.second) + self.assertFormatIsStr("{:<20}", TE.second) + self.assertFormatIsStr("{:5.2}", TE.second) class _MixedOutputTests: - def test_str(self): TE = self.MainEnum if self.is_flag: @@ -859,7 +1034,7 @@ def test_str(self): else: self.assertEqual(str(TE.dupe), "MainEnum.third") for name, value, member in zip(self.names, self.values, TE, strict=True): - self.assertEqual(str(member), "MainEnum.%s" % (member.name, )) + self.assertEqual(str(member), "MainEnum.%s" % (member.name,)) def test_format(self): TE = self.MainEnum @@ -869,7 +1044,7 @@ def test_format(self): else: self.assertEqual(format(TE.dupe), "MainEnum.third") for name, value, member in zip(self.names, self.values, TE, strict=True): - self.assertEqual(format(member), "MainEnum.%s" % (member.name, )) + self.assertEqual(format(member), "MainEnum.%s" % (member.name,)) def test_overridden_format(self): NF = self.NewFormatEnum @@ -878,17 +1053,16 @@ def test_overridden_format(self): def test_format_specs(self): TE = self.MainEnum - self.assertFormatIsStr('{}', TE.first) - self.assertFormatIsStr('{:}', TE.first) - self.assertFormatIsStr('{:20}', TE.first) - self.assertFormatIsStr('{:^20}', TE.first) - self.assertFormatIsStr('{:>20}', TE.first) - self.assertFormatIsStr('{:<20}', TE.first) - self.assertFormatIsStr('{:5.2}', TE.first) + self.assertFormatIsStr("{}", TE.first) + self.assertFormatIsStr("{:}", TE.first) + self.assertFormatIsStr("{:20}", TE.first) + self.assertFormatIsStr("{:^20}", TE.first) + self.assertFormatIsStr("{:>20}", TE.first) + self.assertFormatIsStr("{:<20}", TE.first) + self.assertFormatIsStr("{:5.2}", TE.first) class _MinimalOutputTests: - def test_str(self): TE = self.MainEnum if self.is_flag: @@ -916,16 +1090,16 @@ def test_overridden_format(self): def test_format_specs(self): TE = self.MainEnum - self.assertFormatIsValue('{}', TE.third) - self.assertFormatIsValue('{:}', TE.third) - self.assertFormatIsValue('{:20}', TE.third) - self.assertFormatIsValue('{:^20}', TE.third) - self.assertFormatIsValue('{:>20}', TE.third) - self.assertFormatIsValue('{:<20}', TE.third) + self.assertFormatIsValue("{}", TE.third) + self.assertFormatIsValue("{:}", TE.third) + self.assertFormatIsValue("{:20}", TE.third) + self.assertFormatIsValue("{:^20}", TE.third) + self.assertFormatIsValue("{:>20}", TE.third) + self.assertFormatIsValue("{:<20}", TE.third) if TE._member_type_ is float: - self.assertFormatIsValue('{:n}', TE.third) - self.assertFormatIsValue('{:5.2}', TE.third) - self.assertFormatIsValue('{:f}', TE.third) + self.assertFormatIsValue("{:n}", TE.third) + self.assertFormatIsValue("{:5.2}", TE.third) + self.assertFormatIsValue("{:f}", TE.third) def test_copy(self): TE = self.MainEnum @@ -943,14 +1117,14 @@ def test_copy_member(self): deep = copy.deepcopy(TE.first) self.assertIs(deep, TE.first) -class _FlagTests: +class _FlagTests: def test_default_missing_with_wrong_type_value(self): with self.assertRaisesRegex( ValueError, "'RED' is not a valid ", - ) as ctx: - self.MainEnum('RED') + ) as ctx: + self.MainEnum("RED") self.assertIs(ctx.exception.__context__, None) def test_closed_invert_expectations(self): @@ -958,59 +1132,65 @@ class ClosedAB(self.enum_type): A = 1 B = 2 MASK = 3 + A, B = ClosedAB AB_MASK = ClosedAB.MASK # self.assertIs(~A, B) self.assertIs(~B, A) - self.assertIs(~(A|B), ClosedAB(0)) + self.assertIs(~(A | B), ClosedAB(0)) self.assertIs(~AB_MASK, ClosedAB(0)) - self.assertIs(~ClosedAB(0), (A|B)) + self.assertIs(~ClosedAB(0), (A | B)) + # class ClosedXYZ(self.enum_type): X = 4 Y = 2 Z = 1 MASK = 7 + X, Y, Z = ClosedXYZ XYZ_MASK = ClosedXYZ.MASK # - self.assertIs(~X, Y|Z) - self.assertIs(~Y, X|Z) - self.assertIs(~Z, X|Y) - self.assertIs(~(X|Y), Z) - self.assertIs(~(X|Z), Y) - self.assertIs(~(Y|Z), X) - self.assertIs(~(X|Y|Z), ClosedXYZ(0)) + self.assertIs(~X, Y | Z) + self.assertIs(~Y, X | Z) + self.assertIs(~Z, X | Y) + self.assertIs(~(X | Y), Z) + self.assertIs(~(X | Z), Y) + self.assertIs(~(Y | Z), X) + self.assertIs(~(X | Y | Z), ClosedXYZ(0)) self.assertIs(~XYZ_MASK, ClosedXYZ(0)) - self.assertIs(~ClosedXYZ(0), (X|Y|Z)) + self.assertIs(~ClosedXYZ(0), (X | Y | Z)) def test_open_invert_expectations(self): class OpenAB(self.enum_type): A = 1 B = 2 MASK = 255 + A, B = OpenAB AB_MASK = OpenAB.MASK # if OpenAB._boundary_ in (EJECT, KEEP): self.assertIs(~A, OpenAB(254)) self.assertIs(~B, OpenAB(253)) - self.assertIs(~(A|B), OpenAB(252)) + self.assertIs(~(A | B), OpenAB(252)) self.assertIs(~AB_MASK, OpenAB(0)) self.assertIs(~OpenAB(0), AB_MASK) else: self.assertIs(~A, B) self.assertIs(~B, A) - self.assertIs(~(A|B), OpenAB(0)) + self.assertIs(~(A | B), OpenAB(0)) self.assertIs(~AB_MASK, OpenAB(0)) - self.assertIs(~OpenAB(0), (A|B)) + self.assertIs(~OpenAB(0), (A | B)) + # class OpenXYZ(self.enum_type): X = 4 Y = 2 Z = 1 MASK = 31 + X, Y, Z = OpenXYZ XYZ_MASK = OpenXYZ.MASK # @@ -1018,22 +1198,22 @@ class OpenXYZ(self.enum_type): self.assertIs(~X, OpenXYZ(27)) self.assertIs(~Y, OpenXYZ(29)) self.assertIs(~Z, OpenXYZ(30)) - self.assertIs(~(X|Y), OpenXYZ(25)) - self.assertIs(~(X|Z), OpenXYZ(26)) - self.assertIs(~(Y|Z), OpenXYZ(28)) - self.assertIs(~(X|Y|Z), OpenXYZ(24)) + self.assertIs(~(X | Y), OpenXYZ(25)) + self.assertIs(~(X | Z), OpenXYZ(26)) + self.assertIs(~(Y | Z), OpenXYZ(28)) + self.assertIs(~(X | Y | Z), OpenXYZ(24)) self.assertIs(~XYZ_MASK, OpenXYZ(0)) self.assertTrue(~OpenXYZ(0), XYZ_MASK) else: - self.assertIs(~X, Y|Z) - self.assertIs(~Y, X|Z) - self.assertIs(~Z, X|Y) - self.assertIs(~(X|Y), Z) - self.assertIs(~(X|Z), Y) - self.assertIs(~(Y|Z), X) - self.assertIs(~(X|Y|Z), OpenXYZ(0)) + self.assertIs(~X, Y | Z) + self.assertIs(~Y, X | Z) + self.assertIs(~Z, X | Y) + self.assertIs(~(X | Y), Z) + self.assertIs(~(X | Z), Y) + self.assertIs(~(Y | Z), X) + self.assertIs(~(X | Y | Z), OpenXYZ(0)) self.assertIs(~XYZ_MASK, OpenXYZ(0)) - self.assertTrue(~OpenXYZ(0), (X|Y|Z)) + self.assertTrue(~OpenXYZ(0), (X | Y | Z)) class TestPlainEnumClass(_EnumTests, _PlainOutputTests, unittest.TestCase): @@ -1048,17 +1228,21 @@ class TestPlainFlagClass(_EnumTests, _PlainOutputTests, _FlagTests, unittest.Tes enum_type = Flag -class TestPlainFlagFunction(_EnumTests, _PlainOutputTests, _FlagTests, unittest.TestCase): +class TestPlainFlagFunction( + _EnumTests, _PlainOutputTests, _FlagTests, unittest.TestCase +): enum_type = Flag class TestIntEnumClass(_EnumTests, _MinimalOutputTests, unittest.TestCase): enum_type = IntEnum + # def test_shadowed_attr(self): class Number(IntEnum): divisor = 1 numerator = 2 + # self.assertEqual(Number.divisor.numerator, 1) self.assertIs(Number.numerator.divisor, Number.divisor) @@ -1066,9 +1250,10 @@ class Number(IntEnum): class TestIntEnumFunction(_EnumTests, _MinimalOutputTests, unittest.TestCase): enum_type = IntEnum + # def test_shadowed_attr(self): - Number = IntEnum('Number', ('divisor', 'numerator')) + Number = IntEnum("Number", ("divisor", "numerator")) # self.assertEqual(Number.divisor.numerator, 1) self.assertIs(Number.numerator.divisor, Number.divisor) @@ -1076,25 +1261,28 @@ def test_shadowed_attr(self): class TestStrEnumClass(_EnumTests, _MinimalOutputTests, unittest.TestCase): enum_type = StrEnum + # def test_shadowed_attr(self): class Book(StrEnum): - author = 'author' - title = 'title' + author = "author" + title = "title" + # - self.assertEqual(Book.author.title(), 'Author') - self.assertEqual(Book.title.title(), 'Title') + self.assertEqual(Book.author.title(), "Author") + self.assertEqual(Book.title.title(), "Title") self.assertIs(Book.title.author, Book.author) class TestStrEnumFunction(_EnumTests, _MinimalOutputTests, unittest.TestCase): enum_type = StrEnum + # def test_shadowed_attr(self): - Book = StrEnum('Book', ('author', 'title')) + Book = StrEnum("Book", ("author", "title")) # - self.assertEqual(Book.author.title(), 'Author') - self.assertEqual(Book.title.title(), 'Title') + self.assertEqual(Book.author.title(), "Author") + self.assertEqual(Book.title.title(), "Title") self.assertIs(Book.title.author, Book.author) @@ -1102,38 +1290,48 @@ class TestIntFlagClass(_EnumTests, _MinimalOutputTests, _FlagTests, unittest.Tes enum_type = IntFlag -class TestIntFlagFunction(_EnumTests, _MinimalOutputTests, _FlagTests, unittest.TestCase): +class TestIntFlagFunction( + _EnumTests, _MinimalOutputTests, _FlagTests, unittest.TestCase +): enum_type = IntFlag class TestMixedIntClass(_EnumTests, _MixedOutputTests, unittest.TestCase): - class enum_type(int, Enum): pass + class enum_type(int, Enum): + pass class TestMixedIntFunction(_EnumTests, _MixedOutputTests, unittest.TestCase): - enum_type = Enum('enum_type', type=int) + enum_type = Enum("enum_type", type=int) class TestMixedStrClass(_EnumTests, _MixedOutputTests, unittest.TestCase): - class enum_type(str, Enum): pass + class enum_type(str, Enum): + pass class TestMixedStrFunction(_EnumTests, _MixedOutputTests, unittest.TestCase): - enum_type = Enum('enum_type', type=str) + enum_type = Enum("enum_type", type=str) -class TestMixedIntFlagClass(_EnumTests, _MixedOutputTests, _FlagTests, unittest.TestCase): - class enum_type(int, Flag): pass +class TestMixedIntFlagClass( + _EnumTests, _MixedOutputTests, _FlagTests, unittest.TestCase +): + class enum_type(int, Flag): + pass -class TestMixedIntFlagFunction(_EnumTests, _MixedOutputTests, _FlagTests, unittest.TestCase): - enum_type = Flag('enum_type', type=int) +class TestMixedIntFlagFunction( + _EnumTests, _MixedOutputTests, _FlagTests, unittest.TestCase +): + enum_type = Flag("enum_type", type=int) class TestMixedDateClass(_EnumTests, _MixedOutputTests, unittest.TestCase): # values = [date(2021, 12, 25), date(2020, 3, 15), date(2019, 11, 27)] source_values = [(2021, 12, 25), (2020, 3, 15), (2019, 11, 27)] + # class enum_type(date, Enum): @staticmethod @@ -1146,19 +1344,24 @@ class TestMixedDateFunction(_EnumTests, _MixedOutputTests, unittest.TestCase): # values = [date(2021, 12, 25), date(2020, 3, 15), date(2019, 11, 27)] source_values = [(2021, 12, 25), (2020, 3, 15), (2019, 11, 27)] + # # staticmethod decorator will be added by EnumType if not present def _generate_next_value_(name, start, count, last_values): values = [(2021, 12, 25), (2020, 3, 15), (2019, 11, 27)] return values[count] + # - enum_type = Enum('enum_type', {'_generate_next_value_':_generate_next_value_}, type=date) + enum_type = Enum( + "enum_type", {"_generate_next_value_": _generate_next_value_}, type=date + ) class TestMinimalDateClass(_EnumTests, _MinimalOutputTests, unittest.TestCase): # values = [date(2023, 12, 1), date(2016, 2, 29), date(2009, 1, 1)] source_values = [(2023, 12, 1), (2016, 2, 29), (2009, 1, 1)] + # class enum_type(date, ReprEnum): # staticmethod decorator will be added by EnumType if absent @@ -1171,18 +1374,23 @@ class TestMinimalDateFunction(_EnumTests, _MinimalOutputTests, unittest.TestCase # values = [date(2023, 12, 1), date(2016, 2, 29), date(2009, 1, 1)] source_values = [(2023, 12, 1), (2016, 2, 29), (2009, 1, 1)] + # @staticmethod def _generate_next_value_(name, start, count, last_values): values = [(2023, 12, 1), (2016, 2, 29), (2009, 1, 1)] return values[count] + # - enum_type = ReprEnum('enum_type', {'_generate_next_value_':_generate_next_value_}, type=date) + enum_type = ReprEnum( + "enum_type", {"_generate_next_value_": _generate_next_value_}, type=date + ) class TestMixedFloatClass(_EnumTests, _MixedOutputTests, unittest.TestCase): # values = [1.1, 2.2, 3.3] + # class enum_type(float, Enum): def _generate_next_value_(name, start, count, last_values): @@ -1193,17 +1401,22 @@ def _generate_next_value_(name, start, count, last_values): class TestMixedFloatFunction(_EnumTests, _MixedOutputTests, unittest.TestCase): # values = [1.1, 2.2, 3.3] + # def _generate_next_value_(name, start, count, last_values): values = [1.1, 2.2, 3.3] return values[count] + # - enum_type = Enum('enum_type', {'_generate_next_value_':_generate_next_value_}, type=float) + enum_type = Enum( + "enum_type", {"_generate_next_value_": _generate_next_value_}, type=float + ) class TestMinimalFloatClass(_EnumTests, _MinimalOutputTests, unittest.TestCase): # values = [4.4, 5.5, 6.6] + # class enum_type(float, ReprEnum): def _generate_next_value_(name, start, count, last_values): @@ -1214,12 +1427,16 @@ def _generate_next_value_(name, start, count, last_values): class TestMinimalFloatFunction(_EnumTests, _MinimalOutputTests, unittest.TestCase): # values = [4.4, 5.5, 6.6] + # def _generate_next_value_(name, start, count, last_values): values = [4.4, 5.5, 6.6] return values[count] + # - enum_type = ReprEnum('enum_type', {'_generate_next_value_':_generate_next_value_}, type=float) + enum_type = ReprEnum( + "enum_type", {"_generate_next_value_": _generate_next_value_}, type=float + ) class TestSpecial(unittest.TestCase): @@ -1233,7 +1450,9 @@ class Season(Enum): SUMMER = 2 AUTUMN = 3 WINTER = 4 + self.Season = Season + # class Grades(IntEnum): A = 5 @@ -1241,19 +1460,24 @@ class Grades(IntEnum): C = 3 D = 2 F = 0 + self.Grades = Grades + # class Directional(str, Enum): - EAST = 'east' - WEST = 'west' - NORTH = 'north' - SOUTH = 'south' + EAST = "east" + WEST = "west" + NORTH = "north" + SOUTH = "south" + self.Directional = Directional # from datetime import date + class Holiday(date, Enum): NEW_YEAR = 2013, 1, 1 IDES_OF_MARCH = 2013, 3, 15 + self.Holiday = Holiday def test_bool(self): @@ -1261,20 +1485,26 @@ def test_bool(self): class Logic(Enum): true = True false = False + self.assertTrue(Logic.true) self.assertTrue(Logic.false) + # unless overridden class RealLogic(Enum): true = True false = False + def __bool__(self): return bool(self._value_) + self.assertTrue(RealLogic.true) self.assertFalse(RealLogic.false) + # mixed Enums depend on mixed-in type class IntLogic(int, Enum): true = 1 false = 0 + self.assertTrue(IntLogic.true) self.assertFalse(IntLogic.false) @@ -1286,237 +1516,287 @@ def test_comparisons(self): Season.SPRING > 4 # self.assertNotEqual(Season.SPRING, 1) + # class Part(Enum): SPRING = 1 CLIP = 2 BARREL = 3 + # self.assertNotEqual(Season.SPRING, Part.SPRING) with self.assertRaises(TypeError): Season.SPRING < Part.CLIP - @unittest.skip('to-do list') + @unittest.skip("to-do list") def test_dir_with_custom_dunders(self): class PlainEnum(Enum): pass + cls_dir = dir(PlainEnum) - self.assertNotIn('__repr__', cls_dir) - self.assertNotIn('__str__', cls_dir) - self.assertNotIn('__format__', cls_dir) - self.assertNotIn('__init__', cls_dir) + self.assertNotIn("__repr__", cls_dir) + self.assertNotIn("__str__", cls_dir) + self.assertNotIn("__format__", cls_dir) + self.assertNotIn("__init__", cls_dir) + # class MyEnum(Enum): def __repr__(self): return object.__repr__(self) + def __str__(self): return object.__repr__(self) + def __format__(self): return object.__repr__(self) + def __init__(self): pass + cls_dir = dir(MyEnum) - self.assertIn('__repr__', cls_dir) - self.assertIn('__str__', cls_dir) - self.assertIn('__format__', cls_dir) - self.assertIn('__init__', cls_dir) + self.assertIn("__repr__", cls_dir) + self.assertIn("__str__", cls_dir) + self.assertIn("__format__", cls_dir) + self.assertIn("__init__", cls_dir) def test_duplicate_name_error(self): with self.assertRaises(TypeError): + class Color(Enum): red = 1 green = 2 blue = 3 red = 4 + # with self.assertRaises(TypeError): + class Color(Enum): red = 1 green = 2 blue = 3 + def red(self): - return 'red' + return "red" + # with self.assertRaises(TypeError): + class Color(Enum): @enum.property def red(self): - return 'redder' + return "redder" + red = 1 green = 2 blue = 3 @reraise_if_not_enum(Theory) def test_enum_function_with_qualname(self): - self.assertEqual(Theory.__qualname__, 'spanish_inquisition') + self.assertEqual(Theory.__qualname__, "spanish_inquisition") def test_enum_of_types(self): """Support using Enum to refer to types deliberately.""" + class MyTypes(Enum): i = int f = float s = str + self.assertEqual(MyTypes.i.value, int) self.assertEqual(MyTypes.f.value, float) self.assertEqual(MyTypes.s.value, str) + class Foo: pass + class Bar: pass + class MyTypes2(Enum): a = Foo b = Bar + self.assertEqual(MyTypes2.a.value, Foo) self.assertEqual(MyTypes2.b.value, Bar) + class SpamEnumNotInner: pass + class SpamEnum(Enum): spam = SpamEnumNotInner + self.assertEqual(SpamEnum.spam.value, SpamEnumNotInner) def test_enum_of_generic_aliases(self): class E(Enum): a = typing.List[int] b = list[int] + self.assertEqual(E.a.value, typing.List[int]) self.assertEqual(E.b.value, list[int]) - self.assertEqual(repr(E.a), '') - self.assertEqual(repr(E.b), '') + self.assertEqual(repr(E.a), "") + self.assertEqual(repr(E.b), "") @unittest.skipIf( - python_version >= (3, 13), - 'inner classes are not members', - ) + python_version >= (3, 13), + "inner classes are not members", + ) def test_nested_classes_in_enum_are_members(self): """ Check for warnings pre-3.13 """ - with self.assertWarnsRegex(DeprecationWarning, 'will not become a member'): + with self.assertWarnsRegex(DeprecationWarning, "will not become a member"): + class Outer(Enum): a = 1 b = 2 + class Inner(Enum): foo = 10 bar = 11 + self.assertTrue(isinstance(Outer.Inner, Outer)) self.assertEqual(Outer.a.value, 1) self.assertEqual(Outer.Inner.value.foo.value, 10) self.assertEqual( list(Outer.Inner.value), [Outer.Inner.value.foo, Outer.Inner.value.bar], - ) + ) self.assertEqual( list(Outer), [Outer.a, Outer.b, Outer.Inner], - ) + ) @unittest.skipIf( - python_version < (3, 13), - 'inner classes are still members', - ) + python_version < (3, 13), + "inner classes are still members", + ) def test_nested_classes_in_enum_are_not_members(self): """Support locally-defined nested classes.""" + class Outer(Enum): a = 1 b = 2 + class Inner(Enum): foo = 10 bar = 11 + self.assertTrue(isinstance(Outer.Inner, type)) self.assertEqual(Outer.a.value, 1) self.assertEqual(Outer.Inner.foo.value, 10) self.assertEqual( list(Outer.Inner), [Outer.Inner.foo, Outer.Inner.bar], - ) + ) self.assertEqual( list(Outer), [Outer.a, Outer.b], - ) + ) def test_nested_classes_in_enum_with_nonmember(self): class Outer(Enum): a = 1 b = 2 + @nonmember class Inner(Enum): foo = 10 bar = 11 + self.assertTrue(isinstance(Outer.Inner, type)) self.assertEqual(Outer.a.value, 1) self.assertEqual(Outer.Inner.foo.value, 10) self.assertEqual( list(Outer.Inner), [Outer.Inner.foo, Outer.Inner.bar], - ) + ) self.assertEqual( list(Outer), [Outer.a, Outer.b], - ) + ) def test_enum_of_types_with_nonmember(self): """Support using Enum to refer to types deliberately.""" + class MyTypes(Enum): i = int f = nonmember(float) s = str + self.assertEqual(MyTypes.i.value, int) self.assertTrue(MyTypes.f is float) self.assertEqual(MyTypes.s.value, str) + class Foo: pass + class Bar: pass + class MyTypes2(Enum): a = Foo b = nonmember(Bar) + self.assertEqual(MyTypes2.a.value, Foo) self.assertTrue(MyTypes2.b is Bar) + class SpamEnumIsInner: pass + class SpamEnum(Enum): spam = nonmember(SpamEnumIsInner) + self.assertTrue(SpamEnum.spam is SpamEnumIsInner) def test_nested_classes_in_enum_with_member(self): """Support locally-defined nested classes.""" + class Outer(Enum): a = 1 b = 2 + @member class Inner(Enum): foo = 10 bar = 11 + self.assertTrue(isinstance(Outer.Inner, Outer)) self.assertEqual(Outer.a.value, 1) self.assertEqual(Outer.Inner.value.foo.value, 10) self.assertEqual( list(Outer.Inner.value), [Outer.Inner.value.foo, Outer.Inner.value.bar], - ) + ) self.assertEqual( list(Outer), [Outer.a, Outer.b, Outer.Inner], - ) + ) def test_enum_with_value_name(self): class Huh(Enum): name = 1 value = 2 + self.assertEqual(list(Huh), [Huh.name, Huh.value]) self.assertIs(type(Huh.name), Huh) - self.assertEqual(Huh.name.name, 'name') + self.assertEqual(Huh.name.name, "name") self.assertEqual(Huh.name.value, 1) def test_contains_name_and_value_overlap(self): class IntEnum1(IntEnum): X = 1 + class IntEnum2(IntEnum): X = 1 + class IntEnum3(IntEnum): X = 2 + class IntEnum4(IntEnum): Y = 1 + self.assertIn(IntEnum1.X, IntEnum1) self.assertIn(IntEnum1.X, IntEnum2) self.assertNotIn(IntEnum1.X, IntEnum3) @@ -1525,54 +1805,66 @@ class IntEnum4(IntEnum): def test_contains_different_types_same_members(self): class IntEnum1(IntEnum): X = 1 + class IntFlag1(IntFlag): X = 1 + self.assertIn(IntEnum1.X, IntFlag1) self.assertIn(IntFlag1.X, IntEnum1) def test_inherited_data_type(self): class HexInt(int): - __qualname__ = 'HexInt' + __qualname__ = "HexInt" + def __repr__(self): return hex(self) + class MyEnum(HexInt, enum.Enum): - __qualname__ = 'MyEnum' + __qualname__ = "MyEnum" A = 1 B = 2 C = 3 - self.assertEqual(repr(MyEnum.A), '') - globals()['HexInt'] = HexInt - globals()['MyEnum'] = MyEnum + + self.assertEqual(repr(MyEnum.A), "") + globals()["HexInt"] = HexInt + globals()["MyEnum"] = MyEnum test_pickle_dump_load(self.assertIs, MyEnum.A) test_pickle_dump_load(self.assertIs, MyEnum) + # class SillyInt(HexInt): - __qualname__ = 'SillyInt' + __qualname__ = "SillyInt" + class MyOtherEnum(SillyInt, enum.Enum): - __qualname__ = 'MyOtherEnum' + __qualname__ = "MyOtherEnum" D = 4 E = 5 F = 6 + self.assertIs(MyOtherEnum._member_type_, SillyInt) - globals()['SillyInt'] = SillyInt - globals()['MyOtherEnum'] = MyOtherEnum + globals()["SillyInt"] = SillyInt + globals()["MyOtherEnum"] = MyOtherEnum test_pickle_dump_load(self.assertIs, MyOtherEnum.E) test_pickle_dump_load(self.assertIs, MyOtherEnum) + # # This did not work in 3.10, but does now with pickling by name class UnBrokenInt(int): - __qualname__ = 'UnBrokenInt' + __qualname__ = "UnBrokenInt" + def __new__(cls, value): return int.__new__(cls, value) + class MyUnBrokenEnum(UnBrokenInt, Enum): - __qualname__ = 'MyUnBrokenEnum' + __qualname__ = "MyUnBrokenEnum" G = 7 H = 8 I = 9 + self.assertIs(MyUnBrokenEnum._member_type_, UnBrokenInt) self.assertIs(MyUnBrokenEnum(7), MyUnBrokenEnum.G) - globals()['UnBrokenInt'] = UnBrokenInt - globals()['MyUnBrokenEnum'] = MyUnBrokenEnum + globals()["UnBrokenInt"] = UnBrokenInt + globals()["MyUnBrokenEnum"] = MyUnBrokenEnum test_pickle_dump_load(self.assertIs, MyUnBrokenEnum.I) test_pickle_dump_load(self.assertIs, MyUnBrokenEnum) @@ -1585,15 +1877,15 @@ def test_floatenum_fromhex(self): FloatStooges.fromhex(h) def test_programmatic_function_type(self): - MinorEnum = Enum('MinorEnum', 'june july august', type=int) + MinorEnum = Enum("MinorEnum", "june july august", type=int) lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) - for i, month in enumerate('june july august'.split(), 1): + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) + for i, month in enumerate("june july august".split(), 1): e = MinorEnum(i) self.assertEqual(e, i) self.assertEqual(e.name, month) @@ -1601,15 +1893,15 @@ def test_programmatic_function_type(self): self.assertIs(type(e), MinorEnum) def test_programmatic_function_string_with_start(self): - MinorEnum = Enum('MinorEnum', 'june july august', start=10) + MinorEnum = Enum("MinorEnum", "june july august", start=10) lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) - for i, month in enumerate('june july august'.split(), 10): + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) + for i, month in enumerate("june july august".split(), 10): e = MinorEnum(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) @@ -1618,15 +1910,15 @@ def test_programmatic_function_string_with_start(self): self.assertIs(type(e), MinorEnum) def test_programmatic_function_type_with_start(self): - MinorEnum = Enum('MinorEnum', 'june july august', type=int, start=30) + MinorEnum = Enum("MinorEnum", "june july august", type=int, start=30) lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) - for i, month in enumerate('june july august'.split(), 30): + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) + for i, month in enumerate("june july august".split(), 30): e = MinorEnum(i) self.assertEqual(e, i) self.assertEqual(e.name, month) @@ -1634,15 +1926,15 @@ def test_programmatic_function_type_with_start(self): self.assertIs(type(e), MinorEnum) def test_programmatic_function_string_list_with_start(self): - MinorEnum = Enum('MinorEnum', ['june', 'july', 'august'], start=20) + MinorEnum = Enum("MinorEnum", ["june", "july", "august"], start=20) lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) - for i, month in enumerate('june july august'.split(), 20): + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) + for i, month in enumerate("june july august".split(), 20): e = MinorEnum(i) self.assertEqual(int(e.value), i) self.assertNotEqual(e, i) @@ -1651,15 +1943,15 @@ def test_programmatic_function_string_list_with_start(self): self.assertIs(type(e), MinorEnum) def test_programmatic_function_type_from_subclass(self): - MinorEnum = IntEnum('MinorEnum', 'june july august') + MinorEnum = IntEnum("MinorEnum", "june july august") lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) - for i, month in enumerate('june july august'.split(), 1): + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) + for i, month in enumerate("june july august".split(), 1): e = MinorEnum(i) self.assertEqual(e, i) self.assertEqual(e.name, month) @@ -1667,15 +1959,15 @@ def test_programmatic_function_type_from_subclass(self): self.assertIs(type(e), MinorEnum) def test_programmatic_function_type_from_subclass_with_start(self): - MinorEnum = IntEnum('MinorEnum', 'june july august', start=40) + MinorEnum = IntEnum("MinorEnum", "june july august", start=40) lst = list(MinorEnum) self.assertEqual(len(lst), len(MinorEnum)) self.assertEqual(len(MinorEnum), 3, MinorEnum) self.assertEqual( - [MinorEnum.june, MinorEnum.july, MinorEnum.august], - lst, - ) - for i, month in enumerate('june july august'.split(), 40): + [MinorEnum.june, MinorEnum.july, MinorEnum.august], + lst, + ) + for i, month in enumerate("june july august".split(), 40): e = MinorEnum(i) self.assertEqual(e, i) self.assertEqual(e.name, month) @@ -1687,42 +1979,50 @@ class TwoPart(Enum): ONE = 1, 1.0 TWO = 2, 2.0 THREE = 3, 3.0 - self.assertRaisesRegex(ValueError, '1 is not a valid .*TwoPart', TwoPart, 1) + + self.assertRaisesRegex(ValueError, "1 is not a valid .*TwoPart", TwoPart, 1) self.assertIs(TwoPart((1, 1.0)), TwoPart.ONE) self.assertIs(TwoPart(1, 1.0), TwoPart.ONE) + class ThreePart(Enum): - ONE = 1, 1.0, 'one' - TWO = 2, 2.0, 'two' - THREE = 3, 3.0, 'three' - self.assertIs(ThreePart((3, 3.0, 'three')), ThreePart.THREE) - self.assertIs(ThreePart(3, 3.0, 'three'), ThreePart.THREE) + ONE = 1, 1.0, "one" + TWO = 2, 2.0, "two" + THREE = 3, 3.0, "three" + + self.assertIs(ThreePart((3, 3.0, "three")), ThreePart.THREE) + self.assertIs(ThreePart(3, 3.0, "three"), ThreePart.THREE) @reraise_if_not_enum(IntStooges) def test_intenum_from_bytes(self): - self.assertIs(IntStooges.from_bytes(b'\x00\x03', 'big'), IntStooges.MOE) + self.assertIs(IntStooges.from_bytes(b"\x00\x03", "big"), IntStooges.MOE) with self.assertRaises(ValueError): - IntStooges.from_bytes(b'\x00\x05', 'big') + IntStooges.from_bytes(b"\x00\x05", "big") def test_reserved_sunder_error(self): with self.assertRaisesRegex( - ValueError, - '_sunder_ names, such as ._bad_., are reserved', - ): + ValueError, + "_sunder_ names, such as ._bad_., are reserved", + ): + class Bad(Enum): _bad_ = 1 def test_too_many_data_types(self): - with self.assertRaisesRegex(TypeError, 'too many data types'): + with self.assertRaisesRegex(TypeError, "too many data types"): + class Huh(str, int, Enum): One = 1 class MyStr(str): def hello(self): - return 'hello, %s' % self + return "hello, %s" % self + class MyInt(int): def repr(self): return hex(self) - with self.assertRaisesRegex(TypeError, 'too many data types'): + + with self.assertRaisesRegex(TypeError, "too many data types"): + class Huh(MyStr, MyInt, Enum): One = 1 @@ -1754,25 +2054,25 @@ def test_pickle_enum_function_with_module(self): def test_pickle_nested_class(self): # would normally just have this directly in the class namespace class NestedEnum(Enum): - twigs = 'common' - shiny = 'rare' + twigs = "common" + shiny = "rare" self.__class__.NestedEnum = NestedEnum - self.NestedEnum.__qualname__ = '%s.NestedEnum' % self.__class__.__name__ + self.NestedEnum.__qualname__ = "%s.NestedEnum" % self.__class__.__name__ test_pickle_dump_load(self.assertIs, self.NestedEnum.twigs) def test_pickle_by_name(self): class ReplaceGlobalInt(IntEnum): ONE = 1 TWO = 2 + ReplaceGlobalInt.__reduce_ex__ = enum._reduce_ex_by_global_name for proto in range(HIGHEST_PROTOCOL): - self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), 'TWO') + self.assertEqual(ReplaceGlobalInt.TWO.__reduce_ex__(proto), "TWO") def test_pickle_explodes(self): - BadPickle = Enum( - 'BadPickle', 'dill sweet bread-n-butter', module=__name__) - globals()['BadPickle'] = BadPickle + BadPickle = Enum("BadPickle", "dill sweet bread-n-butter", module=__name__) + globals()["BadPickle"] = BadPickle # now break BadPickle to test exception raising enum._make_class_unpicklable(BadPickle) test_pickle_exception(self.assertRaises, TypeError, BadPickle.dill) @@ -1780,10 +2080,11 @@ def test_pickle_explodes(self): def test_string_enum(self): class SkillLevel(str, Enum): - master = 'what is the sound of one hand clapping?' - journeyman = 'why did the chicken cross the road?' - apprentice = 'knock, knock!' - self.assertEqual(SkillLevel.apprentice, 'knock, knock!') + master = "what is the sound of one hand clapping?" + journeyman = "why did the chicken cross the road?" + apprentice = "knock, knock!" + + self.assertEqual(SkillLevel.apprentice, "knock, knock!") def test_getattr_getitem(self): class Period(Enum): @@ -1791,13 +2092,14 @@ class Period(Enum): noon = 2 evening = 3 night = 4 + self.assertIs(Period(2), Period.noon) - self.assertIs(getattr(Period, 'night'), Period.night) - self.assertIs(Period['morning'], Period.morning) + self.assertIs(getattr(Period, "night"), Period.night) + self.assertIs(Period["morning"], Period.morning) def test_getattr_dunder(self): Season = self.Season - self.assertTrue(getattr(Season, '__eq__')) + self.assertTrue(getattr(Season, "__eq__")) def test_iteration_order(self): class Season(Enum): @@ -1805,16 +2107,17 @@ class Season(Enum): WINTER = 4 AUTUMN = 3 SPRING = 1 + self.assertEqual( - list(Season), - [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING], - ) + list(Season), + [Season.SUMMER, Season.WINTER, Season.AUTUMN, Season.SPRING], + ) @reraise_if_not_enum(Name) def test_subclassing(self): - self.assertEqual(Name.BDFL, 'Guido van Rossum') - self.assertTrue(Name.BDFL, Name('Guido van Rossum')) - self.assertIs(Name.BDFL, getattr(Name, 'BDFL')) + self.assertEqual(Name.BDFL, "Guido van Rossum") + self.assertTrue(Name.BDFL, Name("Guido van Rossum")) + self.assertIs(Name.BDFL, getattr(Name, "BDFL")) test_pickle_dump_load(self.assertIs, Name.BDFL) def test_extending(self): @@ -1822,43 +2125,57 @@ class Color(Enum): red = 1 green = 2 blue = 3 + # with self.assertRaises(TypeError): + class MoreColor(Color): cyan = 4 magenta = 5 yellow = 6 + # - with self.assertRaisesRegex(TypeError, " cannot extend "): + with self.assertRaisesRegex( + TypeError, " cannot extend " + ): + class EvenMoreColor(Color, IntEnum): chartruese = 7 + # - with self.assertRaisesRegex(ValueError, r"\(.Foo., \(.pink., .black.\)\) is not a valid .*Color"): - Color('Foo', ('pink', 'black')) + with self.assertRaisesRegex( + ValueError, r"\(.Foo., \(.pink., .black.\)\) is not a valid .*Color" + ): + Color("Foo", ("pink", "black")) def test_exclude_methods(self): class whatever(Enum): - this = 'that' - these = 'those' + this = "that" + these = "those" + def really(self): - return 'no, not %s' % self.value + return "no, not %s" % self.value + self.assertIsNot(type(whatever.really), whatever) - self.assertEqual(whatever.this.really(), 'no, not that') + self.assertEqual(whatever.this.really(), "no, not that") def test_wrong_inheritance_order(self): with self.assertRaises(TypeError): + class Wrong(Enum, str): - NotHere = 'error before this point' + NotHere = "error before this point" def test_intenum_transitivity(self): class number(IntEnum): one = 1 two = 2 three = 3 + class numero(IntEnum): uno = 1 dos = 2 tres = 3 + self.assertEqual(number.one, numero.uno) self.assertEqual(number.two, numero.dos) self.assertEqual(number.three, numero.tres) @@ -1867,63 +2184,78 @@ def test_wrong_enum_in_call(self): class Monochrome(Enum): black = 0 white = 1 + class Gender(Enum): male = 0 female = 1 + self.assertRaises(ValueError, Monochrome, Gender.male) def test_wrong_enum_in_mixed_call(self): class Monochrome(IntEnum): black = 0 white = 1 + class Gender(Enum): male = 0 female = 1 + self.assertRaises(ValueError, Monochrome, Gender.male) def test_mixed_enum_in_call_1(self): class Monochrome(IntEnum): black = 0 white = 1 + class Gender(IntEnum): male = 0 female = 1 + self.assertIs(Monochrome(Gender.female), Monochrome.white) def test_mixed_enum_in_call_2(self): class Monochrome(Enum): black = 0 white = 1 + class Gender(IntEnum): male = 0 female = 1 + self.assertIs(Monochrome(Gender.male), Monochrome.black) def test_flufl_enum(self): class Fluflnum(Enum): def __int__(self): return int(self.value) + class MailManOptions(Fluflnum): option1 = 1 option2 = 2 option3 = 3 + self.assertEqual(int(MailManOptions.option1), 1) def test_introspection(self): class Number(IntEnum): one = 100 two = 200 + self.assertIs(Number.one._member_type_, int) self.assertIs(Number._member_type_, int) + class String(str, Enum): - yarn = 'soft' - rope = 'rough' - wire = 'hard' + yarn = "soft" + rope = "rough" + wire = "hard" + self.assertIs(String.yarn._member_type_, str) self.assertIs(String._member_type_, str) + class Plain(Enum): - vanilla = 'white' + vanilla = "white" one = 1 + self.assertIs(Plain.vanilla._member_type_, object) self.assertIs(Plain._member_type_, object) @@ -1932,10 +2264,11 @@ class Color(Enum): red = 1 green = 2 blue = 3 + with self.assertRaises(ValueError): Color(4) with self.assertRaises(KeyError): - Color['chartreuse'] + Color["chartreuse"] # tests that need to be evalualted for moving @@ -1957,8 +2290,7 @@ def __new__(metacls, cls, bases, classdict): for k, v in classdict.items(): if k not in names: temp[k] = v - return super(auto_enum, metacls).__new__( - metacls, cls, bases, temp) + return super(auto_enum, metacls).__new__(metacls, cls, bases, temp) class AutoNumberedEnum(Enum, metaclass=auto_enum): pass @@ -1978,7 +2310,8 @@ class TestAutoInt(AutoIntEnum): def test_subclasses_with_getnewargs(self): class NamedInt(int): - __qualname__ = 'NamedInt' # needed for pickle protocol 4 + __qualname__ = "NamedInt" # needed for pickle protocol 4 + def __new__(cls, *args): _args = args name, *args = args @@ -1988,18 +2321,22 @@ def __new__(cls, *args): self._intname = name self._args = _args return self + def __getnewargs__(self): return self._args + @bltns.property def __name__(self): return self._intname + def __repr__(self): # repr() is updated to include the name and type info return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + type(self).__name__, + self.__name__, + int.__repr__(self), + ) + def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -2007,29 +2344,29 @@ def __str__(self): if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) + # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): - temp = int(self) + int( other) + temp = int(self) + int(other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( - '({0} + {1})'.format(self.__name__, other.__name__), + "({0} + {1})".format(self.__name__, other.__name__), temp, - ) + ) else: return temp class NEI(NamedInt, Enum): - __qualname__ = 'NEI' # needed for pickle protocol 4 - x = ('the-x', 1) - y = ('the-y', 2) - + __qualname__ = "NEI" # needed for pickle protocol 4 + x = ("the-x", 1) + y = ("the-y", 2) self.assertIs(NEI.__new__, Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") - globals()['NamedInt'] = NamedInt - globals()['NEI'] = NEI - NI5 = NamedInt('test', 5) + globals()["NamedInt"] = NamedInt + globals()["NEI"] = NEI + NI5 = NamedInt("test", 5) self.assertEqual(NI5, 5) test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) @@ -2038,7 +2375,8 @@ class NEI(NamedInt, Enum): def test_subclasses_with_getnewargs_ex(self): class NamedInt(int): - __qualname__ = 'NamedInt' # needed for pickle protocol 4 + __qualname__ = "NamedInt" # needed for pickle protocol 4 + def __new__(cls, *args): _args = args name, *args = args @@ -2048,18 +2386,22 @@ def __new__(cls, *args): self._intname = name self._args = _args return self + def __getnewargs_ex__(self): return self._args, {} + @bltns.property def __name__(self): return self._intname + def __repr__(self): # repr() is updated to include the name and type info return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + type(self).__name__, + self.__name__, + int.__repr__(self), + ) + def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -2067,29 +2409,29 @@ def __str__(self): if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) + # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): - temp = int(self) + int( other) + temp = int(self) + int(other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( - '({0} + {1})'.format(self.__name__, other.__name__), + "({0} + {1})".format(self.__name__, other.__name__), temp, - ) + ) else: return temp class NEI(NamedInt, Enum): - __qualname__ = 'NEI' # needed for pickle protocol 4 - x = ('the-x', 1) - y = ('the-y', 2) - + __qualname__ = "NEI" # needed for pickle protocol 4 + x = ("the-x", 1) + y = ("the-y", 2) self.assertIs(NEI.__new__, Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") - globals()['NamedInt'] = NamedInt - globals()['NEI'] = NEI - NI5 = NamedInt('test', 5) + globals()["NamedInt"] = NamedInt + globals()["NEI"] = NEI + NI5 = NamedInt("test", 5) self.assertEqual(NI5, 5) test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) @@ -2098,7 +2440,8 @@ class NEI(NamedInt, Enum): def test_subclasses_with_reduce(self): class NamedInt(int): - __qualname__ = 'NamedInt' # needed for pickle protocol 4 + __qualname__ = "NamedInt" # needed for pickle protocol 4 + def __new__(cls, *args): _args = args name, *args = args @@ -2108,18 +2451,22 @@ def __new__(cls, *args): self._intname = name self._args = _args return self + def __reduce__(self): return self.__class__, self._args + @bltns.property def __name__(self): return self._intname + def __repr__(self): # repr() is updated to include the name and type info return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + type(self).__name__, + self.__name__, + int.__repr__(self), + ) + def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -2127,29 +2474,29 @@ def __str__(self): if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) + # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): - temp = int(self) + int( other) + temp = int(self) + int(other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( - '({0} + {1})'.format(self.__name__, other.__name__), + "({0} + {1})".format(self.__name__, other.__name__), temp, - ) + ) else: return temp class NEI(NamedInt, Enum): - __qualname__ = 'NEI' # needed for pickle protocol 4 - x = ('the-x', 1) - y = ('the-y', 2) - + __qualname__ = "NEI" # needed for pickle protocol 4 + x = ("the-x", 1) + y = ("the-y", 2) self.assertIs(NEI.__new__, Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") - globals()['NamedInt'] = NamedInt - globals()['NEI'] = NEI - NI5 = NamedInt('test', 5) + globals()["NamedInt"] = NamedInt + globals()["NEI"] = NEI + NI5 = NamedInt("test", 5) self.assertEqual(NI5, 5) test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) @@ -2158,7 +2505,8 @@ class NEI(NamedInt, Enum): def test_subclasses_with_reduce_ex(self): class NamedInt(int): - __qualname__ = 'NamedInt' # needed for pickle protocol 4 + __qualname__ = "NamedInt" # needed for pickle protocol 4 + def __new__(cls, *args): _args = args name, *args = args @@ -2168,18 +2516,22 @@ def __new__(cls, *args): self._intname = name self._args = _args return self + def __reduce_ex__(self, proto): return self.__class__, self._args + @bltns.property def __name__(self): return self._intname + def __repr__(self): # repr() is updated to include the name and type info return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + type(self).__name__, + self.__name__, + int.__repr__(self), + ) + def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -2187,28 +2539,29 @@ def __str__(self): if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) + # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): - temp = int(self) + int( other) + temp = int(self) + int(other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( - '({0} + {1})'.format(self.__name__, other.__name__), + "({0} + {1})".format(self.__name__, other.__name__), temp, - ) + ) else: return temp class NEI(NamedInt, Enum): - __qualname__ = 'NEI' # needed for pickle protocol 4 - x = ('the-x', 1) - y = ('the-y', 2) + __qualname__ = "NEI" # needed for pickle protocol 4 + x = ("the-x", 1) + y = ("the-y", 2) self.assertIs(NEI.__new__, Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") - globals()['NamedInt'] = NamedInt - globals()['NEI'] = NEI - NI5 = NamedInt('test', 5) + globals()["NamedInt"] = NamedInt + globals()["NEI"] = NEI + NI5 = NamedInt("test", 5) self.assertEqual(NI5, 5) test_pickle_dump_load(self.assertEqual, NI5, 5) self.assertEqual(NEI.y.value, 2) @@ -2217,7 +2570,8 @@ class NEI(NamedInt, Enum): def test_subclasses_without_direct_pickle_support(self): class NamedInt(int): - __qualname__ = 'NamedInt' + __qualname__ = "NamedInt" + def __new__(cls, *args): _args = args name, *args = args @@ -2227,16 +2581,19 @@ def __new__(cls, *args): self._intname = name self._args = _args return self + @bltns.property def __name__(self): return self._intname + def __repr__(self): # repr() is updated to include the name and type info return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + type(self).__name__, + self.__name__, + int.__repr__(self), + ) + def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -2244,26 +2601,28 @@ def __str__(self): if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) + # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): - temp = int(self) + int( other) + temp = int(self) + int(other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( - '({0} + {1})'.format(self.__name__, other.__name__), - temp ) + "({0} + {1})".format(self.__name__, other.__name__), temp + ) else: return temp class NEI(NamedInt, Enum): - __qualname__ = 'NEI' - x = ('the-x', 1) - y = ('the-y', 2) + __qualname__ = "NEI" + x = ("the-x", 1) + y = ("the-y", 2) + self.assertIs(NEI.__new__, Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") - globals()['NamedInt'] = NamedInt - globals()['NEI'] = NEI - NI5 = NamedInt('test', 5) + globals()["NamedInt"] = NamedInt + globals()["NEI"] = NEI + NI5 = NamedInt("test", 5) self.assertEqual(NI5, 5) self.assertEqual(NEI.y.value, 2) with self.assertRaisesRegex(TypeError, "name and value must be specified"): @@ -2275,7 +2634,8 @@ class NEI(NamedInt, Enum): def test_subclasses_with_direct_pickle_support(self): class NamedInt(int): - __qualname__ = 'NamedInt' + __qualname__ = "NamedInt" + def __new__(cls, *args): _args = args name, *args = args @@ -2285,16 +2645,19 @@ def __new__(cls, *args): self._intname = name self._args = _args return self + @bltns.property def __name__(self): return self._intname + def __repr__(self): # repr() is updated to include the name and type info return "{}({!r}, {})".format( - type(self).__name__, - self.__name__, - int.__repr__(self), - ) + type(self).__name__, + self.__name__, + int.__repr__(self), + ) + def __str__(self): # str() is unchanged, even if it relies on the repr() fallback base = int @@ -2302,30 +2665,32 @@ def __str__(self): if base_str.__objclass__ is object: return base.__repr__(self) return base_str(self) + # for simplicity, we only define one operator that # propagates expressions def __add__(self, other): - temp = int(self) + int( other) + temp = int(self) + int(other) if isinstance(self, NamedInt) and isinstance(other, NamedInt): return NamedInt( - '({0} + {1})'.format(self.__name__, other.__name__), + "({0} + {1})".format(self.__name__, other.__name__), temp, - ) + ) else: return temp class NEI(NamedInt, Enum): - __qualname__ = 'NEI' - x = ('the-x', 1) - y = ('the-y', 2) + __qualname__ = "NEI" + x = ("the-x", 1) + y = ("the-y", 2) + def __reduce_ex__(self, proto): return getattr, (self.__class__, self._name_) self.assertIs(NEI.__new__, Enum.__new__) self.assertEqual(repr(NEI.x + NEI.y), "NamedInt('(the-x + the-y)', 3)") - globals()['NamedInt'] = NamedInt - globals()['NEI'] = NEI - NI5 = NamedInt('test', 5) + globals()["NamedInt"] = NamedInt + globals()["NEI"] = NEI + NI5 = NamedInt("test", 5) self.assertEqual(NI5, 5) self.assertEqual(NEI.y.value, 2) test_pickle_dump_load(self.assertIs, NEI.y) @@ -2333,14 +2698,15 @@ def __reduce_ex__(self, proto): def test_tuple_subclass(self): class SomeTuple(tuple, Enum): - __qualname__ = 'SomeTuple' # needed for pickle protocol 4 - first = (1, 'for the money') - second = (2, 'for the show') - third = (3, 'for the music') + __qualname__ = "SomeTuple" # needed for pickle protocol 4 + first = (1, "for the money") + second = (2, "for the show") + third = (3, "for the music") + self.assertIs(type(SomeTuple.first), SomeTuple) self.assertIsInstance(SomeTuple.second, tuple) - self.assertEqual(SomeTuple.third, (3, 'for the music')) - globals()['SomeTuple'] = SomeTuple + self.assertEqual(SomeTuple.third, (3, "for the music")) + globals()["SomeTuple"] = SomeTuple test_pickle_dump_load(self.assertIs, SomeTuple.first) def test_duplicate_values_give_unique_enum_items(self): @@ -2348,17 +2714,20 @@ class AutoNumber(Enum): first = () second = () third = () + def __new__(cls): value = len(cls.__members__) + 1 obj = object.__new__(cls) obj._value_ = value return obj + def __int__(self): return int(self._value_) + self.assertEqual( - list(AutoNumber), - [AutoNumber.first, AutoNumber.second, AutoNumber.third], - ) + list(AutoNumber), + [AutoNumber.first, AutoNumber.second, AutoNumber.third], + ) self.assertEqual(int(AutoNumber.second), 2) self.assertEqual(AutoNumber.third.value, 3) self.assertIs(AutoNumber(1), AutoNumber.first) @@ -2370,12 +2739,15 @@ def __new__(cls): obj = object.__new__(cls) obj._value_ = value return obj + def __int__(self): return int(self._value_) + class Color(AutoNumber): red = () green = () blue = () + self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) self.assertEqual(list(map(int, Color)), [1, 2, 3]) @@ -2386,16 +2758,19 @@ def __new__(cls): obj = int.__new__(cls, value) obj._value_ = value return obj + class Color(AutoNumber): red = () green = () blue = () + self.assertEqual(list(Color), [Color.red, Color.green, Color.blue]) self.assertEqual(list(map(int, Color)), [1, 2, 3]) def test_equality(self): class OrdinaryEnum(Enum): a = 1 + self.assertEqual(ALWAYS_EQ, OrdinaryEnum.a) self.assertEqual(OrdinaryEnum.a, ALWAYS_EQ) @@ -2405,24 +2780,29 @@ def __ge__(self, other): if self.__class__ is other.__class__: return self._value_ >= other._value_ return NotImplemented + def __gt__(self, other): if self.__class__ is other.__class__: return self._value_ > other._value_ return NotImplemented + def __le__(self, other): if self.__class__ is other.__class__: return self._value_ <= other._value_ return NotImplemented + def __lt__(self, other): if self.__class__ is other.__class__: return self._value_ < other._value_ return NotImplemented + class Grade(OrderedEnum): A = 5 B = 4 C = 3 D = 2 F = 1 + self.assertGreater(Grade.A, Grade.B) self.assertLessEqual(Grade.F, Grade.C) self.assertLess(Grade.D, Grade.A) @@ -2434,11 +2814,14 @@ def test_extending2(self): class Shade(Enum): def shade(self): print(self.name) + class Color(Shade): red = 1 green = 2 blue = 3 + with self.assertRaises(TypeError): + class MoreColor(Color): cyan = 4 magenta = 5 @@ -2448,40 +2831,51 @@ def test_extending3(self): class Shade(Enum): def shade(self): return self.name + class Color(Shade): def hex(self): - return '%s hexlified!' % self.value + return "%s hexlified!" % self.value + class MoreColor(Color): cyan = 4 magenta = 5 yellow = 6 - self.assertEqual(MoreColor.magenta.hex(), '5 hexlified!') + + self.assertEqual(MoreColor.magenta.hex(), "5 hexlified!") def test_subclass_duplicate_name(self): class Base(Enum): def test(self): pass + class Test(Base): test = 1 + self.assertIs(type(Test.test), Test) def test_subclass_duplicate_name_dynamic(self): from types import DynamicClassAttribute + class Base(Enum): @DynamicClassAttribute def test(self): - return 'dynamic' + return "dynamic" + class Test(Base): test = 1 - self.assertEqual(Test.test.test, 'dynamic') + + self.assertEqual(Test.test.test, "dynamic") self.assertEqual(Test.test.value, 1) + class Base2(Enum): @enum.property def flash(self): - return 'flashy dynamic' + return "flashy dynamic" + class Test(Base2): flash = 1 - self.assertEqual(Test.flash.flash, 'flashy dynamic') + + self.assertEqual(Test.flash.flash, "flashy dynamic") self.assertEqual(Test.flash.value, 1) def test_no_duplicates(self): @@ -2492,14 +2886,16 @@ def __init__(self, *args): a = self.name e = cls(self.value).name raise ValueError( - "aliases not allowed in UniqueEnum: %r --> %r" - % (a, e) - ) + "aliases not allowed in UniqueEnum: %r --> %r" % (a, e) + ) + class Color(UniqueEnum): red = 1 green = 2 blue = 3 + with self.assertRaises(ValueError): + class Color(UniqueEnum): red = 1 green = 2 @@ -2508,49 +2904,55 @@ class Color(UniqueEnum): def test_init(self): class Planet(Enum): - MERCURY = (3.303e+23, 2.4397e6) - VENUS = (4.869e+24, 6.0518e6) - EARTH = (5.976e+24, 6.37814e6) - MARS = (6.421e+23, 3.3972e6) - JUPITER = (1.9e+27, 7.1492e7) - SATURN = (5.688e+26, 6.0268e7) - URANUS = (8.686e+25, 2.5559e7) - NEPTUNE = (1.024e+26, 2.4746e7) + MERCURY = (3.303e23, 2.4397e6) + VENUS = (4.869e24, 6.0518e6) + EARTH = (5.976e24, 6.37814e6) + MARS = (6.421e23, 3.3972e6) + JUPITER = (1.9e27, 7.1492e7) + SATURN = (5.688e26, 6.0268e7) + URANUS = (8.686e25, 2.5559e7) + NEPTUNE = (1.024e26, 2.4746e7) + def __init__(self, mass, radius): - self.mass = mass # in kilograms - self.radius = radius # in meters + self.mass = mass # in kilograms + self.radius = radius # in meters + @enum.property def surface_gravity(self): # universal gravitational constant (m3 kg-1 s-2) - G = 6.67300E-11 + G = 6.67300e-11 return G * self.mass / (self.radius * self.radius) + self.assertEqual(round(Planet.EARTH.surface_gravity, 2), 9.80) - self.assertEqual(Planet.EARTH.value, (5.976e+24, 6.37814e6)) + self.assertEqual(Planet.EARTH.value, (5.976e24, 6.37814e6)) def test_ignore(self): class Period(timedelta, Enum): - ''' + """ different lengths of time - ''' + """ + def __new__(cls, value, period): obj = timedelta.__new__(cls, value) obj._value_ = value obj.period = period return obj - _ignore_ = 'Period i' + + _ignore_ = "Period i" Period = vars() for i in range(13): - Period['month_%d' % i] = i*30, 'month' + Period["month_%d" % i] = i * 30, "month" for i in range(53): - Period['week_%d' % i] = i*7, 'week' + Period["week_%d" % i] = i * 7, "week" for i in range(32): - Period['day_%d' % i] = i, 'day' + Period["day_%d" % i] = i, "day" OneDay = day_1 OneWeek = week_1 OneMonth = month_1 - self.assertFalse(hasattr(Period, '_ignore_')) - self.assertFalse(hasattr(Period, 'Period')) - self.assertFalse(hasattr(Period, 'i')) + + self.assertFalse(hasattr(Period, "_ignore_")) + self.assertFalse(hasattr(Period, "Period")) + self.assertFalse(hasattr(Period, "i")) self.assertTrue(isinstance(Period.day_1, timedelta)) self.assertTrue(Period.month_1 is Period.day_30) self.assertTrue(Period.week_4 is Period.day_28) @@ -2562,11 +2964,16 @@ def __new__(cls): obj = object.__new__(cls) obj._value_ = value return obj + class ColorInAList(AutoNumberInAList): red = () green = () blue = () - self.assertEqual(list(ColorInAList), [ColorInAList.red, ColorInAList.green, ColorInAList.blue]) + + self.assertEqual( + list(ColorInAList), + [ColorInAList.red, ColorInAList.green, ColorInAList.blue], + ) for enum, value in zip(ColorInAList, range(3)): value += 1 self.assertEqual(enum.value, [value]) @@ -2585,7 +2992,10 @@ class LabelledList(LabelledIntEnum): unprocessed = (1, "Unprocessed") payment_complete = (2, "Payment Complete") - self.assertEqual(list(LabelledList), [LabelledList.unprocessed, LabelledList.payment_complete]) + self.assertEqual( + list(LabelledList), + [LabelledList.unprocessed, LabelledList.payment_complete], + ) self.assertEqual(LabelledList.unprocessed, 1) self.assertEqual(LabelledList(1), LabelledList.unprocessed) @@ -2594,57 +3004,62 @@ class Color(Enum): RED = 1 GREEN = 2 BLUE = 3 + try: Color(7) except ValueError as exc: self.assertTrue(exc.__context__ is None) else: - raise Exception('Exception not raised.') + raise Exception("Exception not raised.") def test_missing_override(self): class Color(Enum): red = 1 green = 2 blue = 3 + @classmethod def _missing_(cls, item): - if item == 'three': + if item == "three": return cls.blue - elif item == 'bad return': + elif item == "bad return": # trigger internal error return 5 - elif item == 'error out': + elif item == "error out": raise ZeroDivisionError else: # trigger not found return None - self.assertIs(Color('three'), Color.blue) + + self.assertIs(Color("three"), Color.blue) try: Color(7) except ValueError as exc: self.assertTrue(exc.__context__ is None) else: - raise Exception('Exception not raised.') + raise Exception("Exception not raised.") try: - Color('bad return') + Color("bad return") except TypeError as exc: self.assertTrue(isinstance(exc.__context__, ValueError)) else: - raise Exception('Exception not raised.') + raise Exception("Exception not raised.") try: - Color('error out') + Color("error out") except ZeroDivisionError as exc: self.assertTrue(isinstance(exc.__context__, ValueError)) else: - raise Exception('Exception not raised.') + raise Exception("Exception not raised.") def test_missing_exceptions_reset(self): import gc import weakref + # class TestEnum(enum.Enum): - VAL1 = 'val1' - VAL2 = 'val2' + VAL1 = "val1" + VAL2 = "val2" + # class Class1: def __init__(self): @@ -2653,14 +3068,16 @@ def __init__(self): raise ValueError() except ValueError: pass + # class Class2: def __init__(self): # Gracefully handle an exception of Enum's making try: - TestEnum('invalid_value') + TestEnum("invalid_value") except ValueError: pass + # No strong refs here so these are free to die. class_1_ref = weakref.ref(Class1()) class_2_ref = weakref.ref(Class2()) @@ -2679,99 +3096,119 @@ def MAX(cls): max = len(cls) cls.MAX = max return max + class StrMixin: def __str__(self): return self._name_.lower() + class SomeEnum(Enum): def behavior(self): - return 'booyah' + return "booyah" + class AnotherEnum(Enum): def behavior(self): - return 'nuhuh!' + return "nuhuh!" + def social(self): return "what's up?" + class Color(MaxMixin, Enum): RED = auto() GREEN = auto() BLUE = auto() + self.assertEqual(Color.RED.value, 1) self.assertEqual(Color.GREEN.value, 2) self.assertEqual(Color.BLUE.value, 3) self.assertEqual(Color.MAX, 3) - self.assertEqual(str(Color.BLUE), 'Color.BLUE') + self.assertEqual(str(Color.BLUE), "Color.BLUE") + class Color(MaxMixin, StrMixin, Enum): RED = auto() GREEN = auto() BLUE = auto() - __str__ = StrMixin.__str__ # needed as of 3.11 + __str__ = StrMixin.__str__ # needed as of 3.11 + self.assertEqual(Color.RED.value, 1) self.assertEqual(Color.GREEN.value, 2) self.assertEqual(Color.BLUE.value, 3) self.assertEqual(Color.MAX, 3) - self.assertEqual(str(Color.BLUE), 'blue') + self.assertEqual(str(Color.BLUE), "blue") + class Color(StrMixin, MaxMixin, Enum): RED = auto() GREEN = auto() BLUE = auto() - __str__ = StrMixin.__str__ # needed as of 3.11 + __str__ = StrMixin.__str__ # needed as of 3.11 + self.assertEqual(Color.RED.value, 1) self.assertEqual(Color.GREEN.value, 2) self.assertEqual(Color.BLUE.value, 3) self.assertEqual(Color.MAX, 3) - self.assertEqual(str(Color.BLUE), 'blue') + self.assertEqual(str(Color.BLUE), "blue") + class CoolColor(StrMixin, SomeEnum, Enum): RED = auto() GREEN = auto() BLUE = auto() - __str__ = StrMixin.__str__ # needed as of 3.11 + __str__ = StrMixin.__str__ # needed as of 3.11 + self.assertEqual(CoolColor.RED.value, 1) self.assertEqual(CoolColor.GREEN.value, 2) self.assertEqual(CoolColor.BLUE.value, 3) - self.assertEqual(str(CoolColor.BLUE), 'blue') - self.assertEqual(CoolColor.RED.behavior(), 'booyah') + self.assertEqual(str(CoolColor.BLUE), "blue") + self.assertEqual(CoolColor.RED.behavior(), "booyah") + class CoolerColor(StrMixin, AnotherEnum, Enum): RED = auto() GREEN = auto() BLUE = auto() - __str__ = StrMixin.__str__ # needed as of 3.11 + __str__ = StrMixin.__str__ # needed as of 3.11 + self.assertEqual(CoolerColor.RED.value, 1) self.assertEqual(CoolerColor.GREEN.value, 2) self.assertEqual(CoolerColor.BLUE.value, 3) - self.assertEqual(str(CoolerColor.BLUE), 'blue') - self.assertEqual(CoolerColor.RED.behavior(), 'nuhuh!') + self.assertEqual(str(CoolerColor.BLUE), "blue") + self.assertEqual(CoolerColor.RED.behavior(), "nuhuh!") self.assertEqual(CoolerColor.RED.social(), "what's up?") + class CoolestColor(StrMixin, SomeEnum, AnotherEnum): RED = auto() GREEN = auto() BLUE = auto() - __str__ = StrMixin.__str__ # needed as of 3.11 + __str__ = StrMixin.__str__ # needed as of 3.11 + self.assertEqual(CoolestColor.RED.value, 1) self.assertEqual(CoolestColor.GREEN.value, 2) self.assertEqual(CoolestColor.BLUE.value, 3) - self.assertEqual(str(CoolestColor.BLUE), 'blue') - self.assertEqual(CoolestColor.RED.behavior(), 'booyah') + self.assertEqual(str(CoolestColor.BLUE), "blue") + self.assertEqual(CoolestColor.RED.behavior(), "booyah") self.assertEqual(CoolestColor.RED.social(), "what's up?") + class ConfusedColor(StrMixin, AnotherEnum, SomeEnum): RED = auto() GREEN = auto() BLUE = auto() - __str__ = StrMixin.__str__ # needed as of 3.11 + __str__ = StrMixin.__str__ # needed as of 3.11 + self.assertEqual(ConfusedColor.RED.value, 1) self.assertEqual(ConfusedColor.GREEN.value, 2) self.assertEqual(ConfusedColor.BLUE.value, 3) - self.assertEqual(str(ConfusedColor.BLUE), 'blue') - self.assertEqual(ConfusedColor.RED.behavior(), 'nuhuh!') + self.assertEqual(str(ConfusedColor.BLUE), "blue") + self.assertEqual(ConfusedColor.RED.behavior(), "nuhuh!") self.assertEqual(ConfusedColor.RED.social(), "what's up?") + class ReformedColor(StrMixin, IntEnum, SomeEnum, AnotherEnum): RED = auto() GREEN = auto() BLUE = auto() - __str__ = StrMixin.__str__ # needed as of 3.11 + __str__ = StrMixin.__str__ # needed as of 3.11 + self.assertEqual(ReformedColor.RED.value, 1) self.assertEqual(ReformedColor.GREEN.value, 2) self.assertEqual(ReformedColor.BLUE.value, 3) - self.assertEqual(str(ReformedColor.BLUE), 'blue') - self.assertEqual(ReformedColor.RED.behavior(), 'booyah') + self.assertEqual(str(ReformedColor.BLUE), "blue") + self.assertEqual(ReformedColor.RED.behavior(), "booyah") self.assertEqual(ConfusedColor.RED.social(), "what's up?") self.assertTrue(issubclass(ReformedColor, int)) @@ -2781,8 +3218,10 @@ class Decision1(StrEnum): REVERT = "REVERT" REVERT_ALL = "REVERT_ALL" RETRY = "RETRY" + class MyEnum(StrEnum): pass + @unique class Decision2(MyEnum): REVERT = "REVERT" @@ -2803,17 +3242,20 @@ class MyIntEnum(HexMixin, MyInt, enum.Enum): class Foo(MyIntEnum): TEST = 1 + self.assertTrue(isinstance(Foo.TEST, MyInt)) self.assertEqual(Foo._member_type_, MyInt) self.assertEqual(repr(Foo.TEST), "0x1") class Fee(MyIntEnum): TEST = 1 + def __new__(cls, value): value += 1 member = int.__new__(cls, value) member._value_ = value return member + self.assertEqual(Fee.TEST, 2) def test_multiple_mixin_with_common_data_type(self): @@ -2824,10 +3266,12 @@ def _missing_(cls, value): if member._value_.lower() == value.lower(): return member return super()._missing_(value) + # class LenientStrEnum(str, Enum): def __init__(self, *args): self._valid = True + @classmethod def _missing_(cls, value): unknown = cls._member_type_.__new__(cls, value) @@ -2836,26 +3280,29 @@ def _missing_(cls, value): unknown._value_ = value cls._member_map_[value] = unknown return unknown + @enum.property def valid(self): return self._valid + # class JobStatus(CaseInsensitiveStrEnum, LenientStrEnum): ACTIVE = "active" PENDING = "pending" TERMINATED = "terminated" + # JS = JobStatus self.assertEqual(list(JobStatus), [JS.ACTIVE, JS.PENDING, JS.TERMINATED]) - self.assertEqual(JS.ACTIVE, 'active') - self.assertEqual(JS.ACTIVE.value, 'active') - self.assertIs(JS('Active'), JS.ACTIVE) + self.assertEqual(JS.ACTIVE, "active") + self.assertEqual(JS.ACTIVE.value, "active") + self.assertIs(JS("Active"), JS.ACTIVE) self.assertTrue(JS.ACTIVE.valid) - missing = JS('missing') + missing = JS("missing") self.assertEqual(list(JobStatus), [JS.ACTIVE, JS.PENDING, JS.TERMINATED]) - self.assertEqual(JS.ACTIVE, 'active') - self.assertEqual(JS.ACTIVE.value, 'active') - self.assertIs(JS('Active'), JS.ACTIVE) + self.assertEqual(JS.ACTIVE, "active") + self.assertEqual(JS.ACTIVE.value, "active") + self.assertIs(JS("Active"), JS.ACTIVE) self.assertTrue(JS.ACTIVE.valid) self.assertTrue(isinstance(missing, JS)) self.assertFalse(missing.valid) @@ -2871,136 +3318,178 @@ def test_empty_globals(self): def test_strenum(self): class GoodStrEnum(StrEnum): - one = '1' - two = '2' - three = b'3', 'ascii' - four = b'4', 'latin1', 'strict' - self.assertEqual(GoodStrEnum.one, '1') - self.assertEqual(str(GoodStrEnum.one), '1') - self.assertEqual('{}'.format(GoodStrEnum.one), '1') + one = "1" + two = "2" + three = b"3", "ascii" + four = b"4", "latin1", "strict" + + self.assertEqual(GoodStrEnum.one, "1") + self.assertEqual(str(GoodStrEnum.one), "1") + self.assertEqual("{}".format(GoodStrEnum.one), "1") self.assertEqual(GoodStrEnum.one, str(GoodStrEnum.one)) - self.assertEqual(GoodStrEnum.one, '{}'.format(GoodStrEnum.one)) + self.assertEqual(GoodStrEnum.one, "{}".format(GoodStrEnum.one)) self.assertEqual(repr(GoodStrEnum.one), "") + # class DumbMixin: def __str__(self): return "don't do this" + class DumbStrEnum(DumbMixin, StrEnum): - five = '5' - six = '6' - seven = '7' - __str__ = DumbMixin.__str__ # needed as of 3.11 - self.assertEqual(DumbStrEnum.seven, '7') + five = "5" + six = "6" + seven = "7" + __str__ = DumbMixin.__str__ # needed as of 3.11 + + self.assertEqual(DumbStrEnum.seven, "7") self.assertEqual(str(DumbStrEnum.seven), "don't do this") + # class EnumMixin(Enum): def hello(self): - print('hello from %s' % (self, )) + print("hello from %s" % (self,)) + class HelloEnum(EnumMixin, StrEnum): - eight = '8' - self.assertEqual(HelloEnum.eight, '8') + eight = "8" + + self.assertEqual(HelloEnum.eight, "8") self.assertEqual(HelloEnum.eight, str(HelloEnum.eight)) + # class GoodbyeMixin: def goodbye(self): - print('%s wishes you a fond farewell') + print("%s wishes you a fond farewell") + class GoodbyeEnum(GoodbyeMixin, EnumMixin, StrEnum): - nine = '9' - self.assertEqual(GoodbyeEnum.nine, '9') + nine = "9" + + self.assertEqual(GoodbyeEnum.nine, "9") self.assertEqual(GoodbyeEnum.nine, str(GoodbyeEnum.nine)) # - with self.assertRaisesRegex(TypeError, '1 is not a string'): + with self.assertRaisesRegex(TypeError, "1 is not a string"): + class FirstFailedStrEnum(StrEnum): one = 1 - two = '2' + two = "2" + with self.assertRaisesRegex(TypeError, "2 is not a string"): + class SecondFailedStrEnum(StrEnum): - one = '1' - two = 2, - three = '3' - with self.assertRaisesRegex(TypeError, '2 is not a string'): + one = "1" + two = (2,) + three = "3" + + with self.assertRaisesRegex(TypeError, "2 is not a string"): + class ThirdFailedStrEnum(StrEnum): - one = '1' + one = "1" two = 2 - with self.assertRaisesRegex(TypeError, 'encoding must be a string, not %r' % (sys.getdefaultencoding, )): + + with self.assertRaisesRegex( + TypeError, "encoding must be a string, not %r" % (sys.getdefaultencoding,) + ): + class ThirdFailedStrEnum(StrEnum): - one = '1' - two = b'2', sys.getdefaultencoding - with self.assertRaisesRegex(TypeError, 'errors must be a string, not 9'): + one = "1" + two = b"2", sys.getdefaultencoding + + with self.assertRaisesRegex(TypeError, "errors must be a string, not 9"): + class ThirdFailedStrEnum(StrEnum): - one = '1' - two = b'2', 'ascii', 9 + one = "1" + two = b"2", "ascii", 9 def test_custom_strenum(self): class CustomStrEnum(str, Enum): pass + class OkayEnum(CustomStrEnum): - one = '1' - two = '2' - three = b'3', 'ascii' - four = b'4', 'latin1', 'strict' - self.assertEqual(OkayEnum.one, '1') - self.assertEqual(str(OkayEnum.one), 'OkayEnum.one') - self.assertEqual('{}'.format(OkayEnum.one), 'OkayEnum.one') + one = "1" + two = "2" + three = b"3", "ascii" + four = b"4", "latin1", "strict" + + self.assertEqual(OkayEnum.one, "1") + self.assertEqual(str(OkayEnum.one), "OkayEnum.one") + self.assertEqual("{}".format(OkayEnum.one), "OkayEnum.one") self.assertEqual(repr(OkayEnum.one), "") + # class DumbMixin: def __str__(self): return "don't do this" + class DumbStrEnum(DumbMixin, CustomStrEnum): - five = '5' - six = '6' - seven = '7' - __str__ = DumbMixin.__str__ # needed as of 3.11 - self.assertEqual(DumbStrEnum.seven, '7') + five = "5" + six = "6" + seven = "7" + __str__ = DumbMixin.__str__ # needed as of 3.11 + + self.assertEqual(DumbStrEnum.seven, "7") self.assertEqual(str(DumbStrEnum.seven), "don't do this") + # class EnumMixin(Enum): def hello(self): - print('hello from %s' % (self, )) + print("hello from %s" % (self,)) + class HelloEnum(EnumMixin, CustomStrEnum): - eight = '8' - self.assertEqual(HelloEnum.eight, '8') - self.assertEqual(str(HelloEnum.eight), 'HelloEnum.eight') + eight = "8" + + self.assertEqual(HelloEnum.eight, "8") + self.assertEqual(str(HelloEnum.eight), "HelloEnum.eight") + # class GoodbyeMixin: def goodbye(self): - print('%s wishes you a fond farewell') + print("%s wishes you a fond farewell") + class GoodbyeEnum(GoodbyeMixin, EnumMixin, CustomStrEnum): - nine = '9' - self.assertEqual(GoodbyeEnum.nine, '9') - self.assertEqual(str(GoodbyeEnum.nine), 'GoodbyeEnum.nine') + nine = "9" + + self.assertEqual(GoodbyeEnum.nine, "9") + self.assertEqual(str(GoodbyeEnum.nine), "GoodbyeEnum.nine") + # class FirstFailedStrEnum(CustomStrEnum): - one = 1 # this will become '1' - two = '2' + one = 1 # this will become '1' + two = "2" + class SecondFailedStrEnum(CustomStrEnum): - one = '1' - two = 2, # this will become '2' - three = '3' + one = "1" + two = (2,) # this will become '2' + three = "3" + class ThirdFailedStrEnum(CustomStrEnum): - one = '1' + one = "1" two = 2 # this will become '2' - with self.assertRaisesRegex(TypeError, - r"argument (2|'encoding') must be str, not "): + + with self.assertRaisesRegex( + TypeError, r"argument (2|'encoding') must be str, not " + ): + class ThirdFailedStrEnum(CustomStrEnum): - one = '1' - two = b'2', sys.getdefaultencoding - with self.assertRaisesRegex(TypeError, - r"argument (3|'errors') must be str, not "): + one = "1" + two = b"2", sys.getdefaultencoding + + with self.assertRaisesRegex( + TypeError, r"argument (3|'errors') must be str, not " + ): + class ThirdFailedStrEnum(CustomStrEnum): - one = '1' - two = b'2', 'ascii', 9 + one = "1" + two = b"2", "ascii", 9 def test_missing_value_error(self): with self.assertRaisesRegex(TypeError, "_value_ not set in __new__"): + class Combined(str, Enum): # def __new__(cls, value, sequence): enum = str.__new__(cls, value) - if '(' in value: - fis_name, segment = value.split('(', 1) - segment = segment.strip(' )') + if "(" in value: + fis_name, segment = value.split("(", 1) + segment = segment.strip(" )") else: fis_name = value segment = None @@ -3008,57 +3497,60 @@ def __new__(cls, value, sequence): enum.segment = segment enum.sequence = sequence return enum + # def __repr__(self): return "<%s.%s>" % (self.__class__.__name__, self._name_) - # - key_type = 'An$(1,2)', 0 - company_id = 'An$(3,2)', 1 - code = 'An$(5,1)', 2 - description = 'Bn$', 3 + # + key_type = "An$(1,2)", 0 + company_id = "An$(3,2)", 1 + code = "An$(5,1)", 2 + description = "Bn$", 3 def test_private_variable_is_normal_attribute(self): class Private(Enum): - __corporal = 'Radar' - __major_ = 'Hoolihan' - self.assertEqual(Private._Private__corporal, 'Radar') - self.assertEqual(Private._Private__major_, 'Hoolihan') + __corporal = "Radar" + __major_ = "Hoolihan" + + self.assertEqual(Private._Private__corporal, "Radar") + self.assertEqual(Private._Private__major_, "Hoolihan") def test_member_from_member_access(self): class Di(Enum): YES = 1 NO = 0 name = 3 + warn = Di.YES.NO self.assertIs(warn, Di.NO) - self.assertIs(Di.name, Di['name']) - self.assertEqual(Di.name.name, 'name') + self.assertIs(Di.name, Di["name"]) + self.assertEqual(Di.name.name, "name") def test_dynamic_members_with_static_methods(self): # - foo_defines = {'FOO_CAT': 'aloof', 'BAR_DOG': 'friendly', 'FOO_HORSE': 'big'} + foo_defines = {"FOO_CAT": "aloof", "BAR_DOG": "friendly", "FOO_HORSE": "big"} + class Foo(Enum): - vars().update({ - k: v - for k, v in foo_defines.items() - if k.startswith('FOO_') - }) + vars().update( + {k: v for k, v in foo_defines.items() if k.startswith("FOO_")} + ) + def upper(self): return self.value.upper() + self.assertEqual(list(Foo), [Foo.FOO_CAT, Foo.FOO_HORSE]) - self.assertEqual(Foo.FOO_CAT.value, 'aloof') - self.assertEqual(Foo.FOO_HORSE.upper(), 'BIG') + self.assertEqual(Foo.FOO_CAT.value, "aloof") + self.assertEqual(Foo.FOO_HORSE.upper(), "BIG") # with self.assertRaisesRegex(TypeError, "'FOO_CAT' already defined as 'aloof'"): + class FooBar(Enum): - vars().update({ - k: v - for k, v in foo_defines.items() - if k.startswith('FOO_') - }, - **{'FOO_CAT': 'small'}, - ) + vars().update( + {k: v for k, v in foo_defines.items() if k.startswith("FOO_")}, + **{"FOO_CAT": "small"}, + ) + def upper(self): return self.value.upper() @@ -3068,95 +3560,119 @@ def test_repr_with_dataclass(self): # check overridden dataclass __repr__ is used # from dataclasses import dataclass, field + @dataclass(repr=False) class Foo: - __qualname__ = 'Foo' + __qualname__ = "Foo" a: int + def __repr__(self): - return 'ha hah!' + return "ha hah!" + class Entries(Foo, Enum): ENTRY1 = 1 - self.assertEqual(repr(Entries.ENTRY1), '') + + self.assertEqual(repr(Entries.ENTRY1), "") self.assertTrue(Entries.ENTRY1.value == Foo(1), Entries.ENTRY1.value) self.assertTrue(isinstance(Entries.ENTRY1, Foo)) self.assertTrue(Entries._member_type_ is Foo, Entries._member_type_) + # # check auto-generated dataclass __repr__ is not used # @dataclass class CreatureDataMixin: - __qualname__ = 'CreatureDataMixin' + __qualname__ = "CreatureDataMixin" size: str legs: int tail: bool = field(repr=False, default=True) + class Creature(CreatureDataMixin, Enum): - __qualname__ = 'Creature' - BEETLE = ('small', 6) - DOG = ('medium', 4) + __qualname__ = "Creature" + BEETLE = ("small", 6) + DOG = ("medium", 4) + self.assertEqual(repr(Creature.DOG), "") + # # check inherited repr used # class Huh: def __repr__(self): - return 'inherited' + return "inherited" + @dataclass(repr=False) class CreatureDataMixin(Huh): - __qualname__ = 'CreatureDataMixin' + __qualname__ = "CreatureDataMixin" size: str legs: int tail: bool = field(repr=False, default=True) + class Creature(CreatureDataMixin, Enum): - __qualname__ = 'Creature' - BEETLE = ('small', 6) - DOG = ('medium', 4) + __qualname__ = "Creature" + BEETLE = ("small", 6) + DOG = ("medium", 4) + self.assertEqual(repr(Creature.DOG), "") + # # check default object.__repr__ used if nothing provided # @dataclass(repr=False) class CreatureDataMixin: - __qualname__ = 'CreatureDataMixin' + __qualname__ = "CreatureDataMixin" size: str legs: int tail: bool = field(repr=False, default=True) + class Creature(CreatureDataMixin, Enum): - __qualname__ = 'Creature' - BEETLE = ('small', 6) - DOG = ('medium', 4) - self.assertRegex(repr(Creature.DOG), "") + __qualname__ = "Creature" + BEETLE = ("small", 6) + DOG = ("medium", 4) + + self.assertRegex( + repr(Creature.DOG), "" + ) def test_repr_with_init_mixin(self): class Foo: def __init__(self, a): self.a = a + def __repr__(self): - return f'Foo(a={self.a!r})' + return f"Foo(a={self.a!r})" + class Entries(Foo, Enum): ENTRY1 = 1 + # - self.assertEqual(repr(Entries.ENTRY1), 'Foo(a=1)') + self.assertEqual(repr(Entries.ENTRY1), "Foo(a=1)") def test_repr_and_str_with_no_init_mixin(self): # non-data_type is a mixin that doesn't define __new__ class Foo: def __repr__(self): - return 'Foo' + return "Foo" + def __str__(self): - return 'ooF' + return "ooF" + class Entries(Foo, Enum): ENTRY1 = 1 + # - self.assertEqual(repr(Entries.ENTRY1), 'Foo') - self.assertEqual(str(Entries.ENTRY1), 'ooF') + self.assertEqual(repr(Entries.ENTRY1), "Foo") + self.assertEqual(str(Entries.ENTRY1), "ooF") def test_value_backup_assign(self): # check that enum will add missing values when custom __new__ does not class Some(Enum): def __new__(cls, val): return object.__new__(cls) + x = 1 y = 2 + self.assertEqual(Some.x.value, 1) self.assertEqual(Some.y.value, 2) @@ -3165,7 +3681,11 @@ class MyIntFlag(int, Flag): ONE = 1 TWO = 2 FOUR = 4 - self.assertTrue(isinstance(MyIntFlag.ONE | MyIntFlag.TWO, MyIntFlag), MyIntFlag.ONE | MyIntFlag.TWO) + + self.assertTrue( + isinstance(MyIntFlag.ONE | MyIntFlag.TWO, MyIntFlag), + MyIntFlag.ONE | MyIntFlag.TWO, + ) self.assertTrue(isinstance(MyIntFlag.ONE | 2, MyIntFlag)) def test_int_flags_copy(self): @@ -3189,17 +3709,26 @@ class MyIntFlag(IntFlag): def test_namedtuple_as_value(self): from collections import namedtuple - TTuple = namedtuple('TTuple', 'id a blist') + + TTuple = namedtuple("TTuple", "id a blist") + class NTEnum(Enum): NONE = TTuple(0, 0, []) A = TTuple(1, 2, [4]) B = TTuple(2, 4, [0, 1, 2]) - self.assertEqual(repr(NTEnum.NONE), "") + + self.assertEqual( + repr(NTEnum.NONE), "" + ) self.assertEqual(NTEnum.NONE.value, TTuple(id=0, a=0, blist=[])) self.assertEqual( - [x.value for x in NTEnum], - [TTuple(id=0, a=0, blist=[]), TTuple(id=1, a=2, blist=[4]), TTuple(id=2, a=4, blist=[0, 1, 2])], - ) + [x.value for x in NTEnum], + [ + TTuple(id=0, a=0, blist=[]), + TTuple(id=1, a=2, blist=[4]), + TTuple(id=2, a=4, blist=[0, 1, 2]), + ], + ) def test_flag_with_custom_new(self): class FlagFromChar(IntFlag): @@ -3208,13 +3737,16 @@ def __new__(cls, c): self = int.__new__(cls, value) self._value_ = value return self + # - a = ord('a') + a = ord("a") + # self.assertEqual(FlagFromChar._all_bits_, 316912650057057350374175801343) self.assertEqual(FlagFromChar._flag_mask_, 158456325028528675187087900672) self.assertEqual(FlagFromChar.a, 158456325028528675187087900672) - self.assertEqual(FlagFromChar.a|1, 158456325028528675187087900673) + self.assertEqual(FlagFromChar.a | 1, 158456325028528675187087900673) + # # class FlagFromChar(Flag): @@ -3223,14 +3755,19 @@ def __new__(cls, c): self = object.__new__(cls) self._value_ = value return self + # - a = ord('a') + a = ord("a") z = 1 + # self.assertEqual(FlagFromChar._all_bits_, 316912650057057350374175801343) self.assertEqual(FlagFromChar._flag_mask_, 158456325028528675187087900674) self.assertEqual(FlagFromChar.a.value, 158456325028528675187087900672) - self.assertEqual((FlagFromChar.a|FlagFromChar.z).value, 158456325028528675187087900674) + self.assertEqual( + (FlagFromChar.a | FlagFromChar.z).value, 158456325028528675187087900674 + ) + # # class FlagFromChar(int, Flag, boundary=KEEP): @@ -3239,30 +3776,40 @@ def __new__(cls, c): self = int.__new__(cls, value) self._value_ = value return self + # - a = ord('a') + a = ord("a") + # self.assertEqual(FlagFromChar._all_bits_, 316912650057057350374175801343) self.assertEqual(FlagFromChar._flag_mask_, 158456325028528675187087900672) self.assertEqual(FlagFromChar.a, 158456325028528675187087900672) - self.assertEqual(FlagFromChar.a|1, 158456325028528675187087900673) + self.assertEqual(FlagFromChar.a | 1, 158456325028528675187087900673) def test_init_exception(self): class Base: def __new__(cls, *args): return object.__new__(cls) + def __init__(self, x): raise ValueError("I don't like", x) + with self.assertRaises(TypeError): + class MyEnum(Base, enum.Enum): - A = 'a' + A = "a" + def __init__(self, y): self.y = y + with self.assertRaises(ValueError): + class MyEnum(Base, enum.Enum): - A = 'a' + A = "a" + def __init__(self, y): self.y = y + def __new__(cls, value): member = Base.__new__(cls) member._value_ = Base(value) @@ -3274,57 +3821,62 @@ class TestOrder(unittest.TestCase): def test_same_members(self): class Color(Enum): - _order_ = 'red green blue' + _order_ = "red green blue" red = 1 green = 2 blue = 3 def test_same_members_with_aliases(self): class Color(Enum): - _order_ = 'red green blue' + _order_ = "red green blue" red = 1 green = 2 blue = 3 verde = green def test_same_members_wrong_order(self): - with self.assertRaisesRegex(TypeError, 'member order does not match _order_'): + with self.assertRaisesRegex(TypeError, "member order does not match _order_"): + class Color(Enum): - _order_ = 'red green blue' + _order_ = "red green blue" red = 1 blue = 3 green = 2 def test_order_has_extra_members(self): - with self.assertRaisesRegex(TypeError, 'member order does not match _order_'): + with self.assertRaisesRegex(TypeError, "member order does not match _order_"): + class Color(Enum): - _order_ = 'red green blue purple' + _order_ = "red green blue purple" red = 1 green = 2 blue = 3 def test_order_has_extra_members_with_aliases(self): - with self.assertRaisesRegex(TypeError, 'member order does not match _order_'): + with self.assertRaisesRegex(TypeError, "member order does not match _order_"): + class Color(Enum): - _order_ = 'red green blue purple' + _order_ = "red green blue purple" red = 1 green = 2 blue = 3 verde = green def test_enum_has_extra_members(self): - with self.assertRaisesRegex(TypeError, 'member order does not match _order_'): + with self.assertRaisesRegex(TypeError, "member order does not match _order_"): + class Color(Enum): - _order_ = 'red green blue' + _order_ = "red green blue" red = 1 green = 2 blue = 3 purple = 4 def test_enum_has_extra_members_with_aliases(self): - with self.assertRaisesRegex(TypeError, 'member order does not match _order_'): + with self.assertRaisesRegex(TypeError, "member order does not match _order_"): + class Color(Enum): - _order_ = 'red green blue' + _order_ = "red green blue" red = 1 green = 2 blue = 3 @@ -3343,7 +3895,7 @@ class Open(Flag): WO = 1 RW = 2 AC = 3 - CE = 1<<19 + CE = 1 << 19 class Color(Flag): BLACK = 0 @@ -3351,9 +3903,9 @@ class Color(Flag): ROJO = 1 GREEN = 2 BLUE = 4 - PURPLE = RED|BLUE - WHITE = RED|GREEN|BLUE - BLANCO = RED|GREEN|BLUE + PURPLE = RED | BLUE + WHITE = RED | GREEN | BLUE + BLANCO = RED | GREEN | BLUE def test_or(self): Perm = self.Perm @@ -3408,32 +3960,40 @@ def test_bool(self): def test_boundary(self): self.assertIs(enum.Flag._boundary_, STRICT) + class Iron(Flag, boundary=CONFORM): ONE = 1 TWO = 2 EIGHT = 8 + self.assertIs(Iron._boundary_, CONFORM) + # class Water(Flag, boundary=STRICT): ONE = 1 TWO = 2 EIGHT = 8 + self.assertIs(Water._boundary_, STRICT) + # class Space(Flag, boundary=EJECT): ONE = 1 TWO = 2 EIGHT = 8 + self.assertIs(Space._boundary_, EJECT) + # class Bizarre(Flag, boundary=KEEP): b = 3 c = 4 d = 6 + # - self.assertRaisesRegex(ValueError, 'invalid value 7', Water, 7) + self.assertRaisesRegex(ValueError, "invalid value 7", Water, 7) # - self.assertIs(Iron(7), Iron.ONE|Iron.TWO) + self.assertIs(Iron(7), Iron.ONE | Iron.TWO) self.assertIs(Iron(~9), Iron.TWO) # self.assertEqual(Space(7), 7) @@ -3442,31 +4002,39 @@ class Bizarre(Flag, boundary=KEEP): self.assertEqual(list(Bizarre), [Bizarre.c]) self.assertIs(Bizarre(3), Bizarre.b) self.assertIs(Bizarre(6), Bizarre.d) + # class SkipFlag(enum.Flag): A = 1 B = 2 C = 4 | B + # - self.assertTrue(SkipFlag.C in (SkipFlag.A|SkipFlag.C)) - self.assertRaisesRegex(ValueError, 'SkipFlag.. invalid value 42', SkipFlag, 42) + self.assertTrue(SkipFlag.C in (SkipFlag.A | SkipFlag.C)) + self.assertRaisesRegex(ValueError, "SkipFlag.. invalid value 42", SkipFlag, 42) + # class SkipIntFlag(enum.IntFlag): A = 1 B = 2 C = 4 | B + # - self.assertTrue(SkipIntFlag.C in (SkipIntFlag.A|SkipIntFlag.C)) + self.assertTrue(SkipIntFlag.C in (SkipIntFlag.A | SkipIntFlag.C)) self.assertEqual(SkipIntFlag(42).value, 42) + # class MethodHint(Flag): HiddenText = 0x10 DigitsOnly = 0x01 LettersOnly = 0x02 - OnlyMask = 0x0f - # - self.assertEqual(str(MethodHint.HiddenText|MethodHint.OnlyMask), 'MethodHint.HiddenText|DigitsOnly|LettersOnly|OnlyMask') + OnlyMask = 0x0F + # + self.assertEqual( + str(MethodHint.HiddenText | MethodHint.OnlyMask), + "MethodHint.HiddenText|DigitsOnly|LettersOnly|OnlyMask", + ) def test_iter(self): Color = self.Color @@ -3475,13 +4043,13 @@ def test_iter(self): self.assertEqual(list(Open), [Open.WO, Open.RW, Open.CE]) def test_programatic_function_string(self): - Perm = Flag('Perm', 'R W X') + Perm = Flag("Perm", "R W X") lst = list(Perm) self.assertEqual(len(lst), len(Perm)) self.assertEqual(len(Perm), 3, Perm) self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) - for i, n in enumerate('R W X'.split()): - v = 1<: 3>') - self.assertEqual(str(simple), '3') + self.assertEqual(repr(simple), ": 3>") + self.assertEqual(str(simple), "3") def test_iter(self): Color = self.Color @@ -4047,13 +4660,13 @@ def test_iter(self): self.assertEqual(list(Open), [Open.WO, Open.RW, Open.CE]) def test_programatic_function_string(self): - Perm = IntFlag('Perm', 'R W X') + Perm = IntFlag("Perm", "R W X") lst = list(Perm) self.assertEqual(len(lst), len(Perm)) self.assertEqual(len(Perm), 3, Perm) self.assertEqual(lst, [Perm.R, Perm.W, Perm.X]) - for i, n in enumerate('R W X'.split()): - v = 1<= (3, 13), - 'mixed types with auto() no longer supported', - ) + python_version >= (3, 13), + "mixed types with auto() no longer supported", + ) def test_auto_garbage_ok(self): - with self.assertWarnsRegex(DeprecationWarning, 'will require all values to be sortable'): + with self.assertWarnsRegex( + DeprecationWarning, "will require all values to be sortable" + ): + class Color(Enum): - red = 'red' + red = "red" blue = auto() + self.assertEqual(Color.blue.value, 1) @unittest.skipIf( - python_version >= (3, 13), - 'mixed types with auto() no longer supported', - ) + python_version >= (3, 13), + "mixed types with auto() no longer supported", + ) def test_auto_garbage_corrected_ok(self): - with self.assertWarnsRegex(DeprecationWarning, 'will require all values to be sortable'): + with self.assertWarnsRegex( + DeprecationWarning, "will require all values to be sortable" + ): + class Color(Enum): - red = 'red' + red = "red" blue = 2 green = auto() self.assertEqual(list(Color), [Color.red, Color.blue, Color.green]) - self.assertEqual(Color.red.value, 'red') + self.assertEqual(Color.red.value, "red") self.assertEqual(Color.blue.value, 2) self.assertEqual(Color.green.value, 3) @unittest.skipIf( - python_version < (3, 13), - 'mixed types with auto() will raise in 3.13', - ) + python_version < (3, 13), + "mixed types with auto() will raise in 3.13", + ) def test_auto_garbage_fail(self): with self.assertRaisesRegex(TypeError, "unable to increment 'red'"): + class Color(Enum): - red = 'red' + red = "red" blue = auto() @unittest.skipIf( - python_version < (3, 13), - 'mixed types with auto() will raise in 3.13', - ) + python_version < (3, 13), + "mixed types with auto() will raise in 3.13", + ) def test_auto_garbage_corrected_fail(self): - with self.assertRaisesRegex(TypeError, 'unable to sort non-numeric values'): + with self.assertRaisesRegex(TypeError, "unable to sort non-numeric values"): + class Color(Enum): - red = 'red' + red = "red" blue = 2 green = auto() def test_auto_order(self): with self.assertRaises(TypeError): + class Color(Enum): red = auto() green = auto() blue = auto() + def _generate_next_value_(name, start, count, last): return name def test_auto_order_wierd(self): weird_auto = auto() - weird_auto.value = 'pathological case' + weird_auto.value = "pathological case" + class Color(Enum): red = weird_auto + def _generate_next_value_(name, start, count, last): return name + blue = auto() + self.assertEqual(list(Color), [Color.red, Color.blue]) - self.assertEqual(Color.red.value, 'pathological case') - self.assertEqual(Color.blue.value, 'blue') + self.assertEqual(Color.red.value, "pathological case") + self.assertEqual(Color.blue.value, "blue") @unittest.skipIf( - python_version < (3, 13), - 'auto() will return highest value + 1 in 3.13', - ) + python_version < (3, 13), + "auto() will return highest value + 1 in 3.13", + ) def test_auto_with_aliases(self): class Color(Enum): red = auto() @@ -4640,6 +5310,7 @@ class Color(Enum): oxford = blue crimson = red green = auto() + self.assertIs(Color.crimson, Color.red) self.assertIs(Color.oxford, Color.blue) self.assertIsNot(Color.green, Color.red) @@ -4650,6 +5321,7 @@ class Dupes(Enum): first = primero = auto() second = auto() third = auto() + self.assertEqual([Dupes.first, Dupes.second, Dupes.third], list(Dupes)) def test_multiple_auto_on_line(self): @@ -4657,9 +5329,11 @@ class Huh(Enum): ONE = auto() TWO = auto(), auto() THREE = auto(), auto(), auto() + self.assertEqual(Huh.ONE.value, 1) self.assertEqual(Huh.TWO.value, (2, 3)) self.assertEqual(Huh.THREE.value, (4, 5, 6)) + # class Hah(Enum): def __new__(cls, value, abbr=None): @@ -4667,31 +5341,37 @@ def __new__(cls, value, abbr=None): member._value_ = value member.abbr = abbr or value[:3].lower() return member + def _generate_next_value_(name, start, count, last): return name + # MONDAY = auto() TUESDAY = auto() - WEDNESDAY = auto(), 'WED' - THURSDAY = auto(), 'Thu' + WEDNESDAY = auto(), "WED" + THURSDAY = auto(), "Thu" FRIDAY = auto() - self.assertEqual(Hah.MONDAY.value, 'MONDAY') - self.assertEqual(Hah.MONDAY.abbr, 'mon') - self.assertEqual(Hah.TUESDAY.value, 'TUESDAY') - self.assertEqual(Hah.TUESDAY.abbr, 'tue') - self.assertEqual(Hah.WEDNESDAY.value, 'WEDNESDAY') - self.assertEqual(Hah.WEDNESDAY.abbr, 'WED') - self.assertEqual(Hah.THURSDAY.value, 'THURSDAY') - self.assertEqual(Hah.THURSDAY.abbr, 'Thu') - self.assertEqual(Hah.FRIDAY.value, 'FRIDAY') - self.assertEqual(Hah.FRIDAY.abbr, 'fri') + + self.assertEqual(Hah.MONDAY.value, "MONDAY") + self.assertEqual(Hah.MONDAY.abbr, "mon") + self.assertEqual(Hah.TUESDAY.value, "TUESDAY") + self.assertEqual(Hah.TUESDAY.abbr, "tue") + self.assertEqual(Hah.WEDNESDAY.value, "WEDNESDAY") + self.assertEqual(Hah.WEDNESDAY.abbr, "WED") + self.assertEqual(Hah.THURSDAY.value, "THURSDAY") + self.assertEqual(Hah.THURSDAY.abbr, "Thu") + self.assertEqual(Hah.FRIDAY.value, "FRIDAY") + self.assertEqual(Hah.FRIDAY.abbr, "fri") + # class Huh(Enum): def _generate_next_value_(name, start, count, last): - return count+1 + return count + 1 + ONE = auto() TWO = auto(), auto() THREE = auto(), auto(), auto() + self.assertEqual(Huh.ONE.value, 1) self.assertEqual(Huh.TWO.value, (2, 2)) self.assertEqual(Huh.THREE.value, (3, 3, 3)) @@ -4784,8 +5464,8 @@ class Color(enum.Enum) | | __members__""" -class TestStdLib(unittest.TestCase): +class TestStdLib(unittest.TestCase): maxDiff = None class Color(Enum): @@ -4806,35 +5486,40 @@ def test_pydoc(self): self.assertEqual(result, expected_text, result) def test_inspect_getmembers(self): - values = dict(( - ('__class__', EnumType), - ('__doc__', '...'), - ('__members__', self.Color.__members__), - ('__module__', __name__), - ('YELLOW', self.Color.YELLOW), - ('MAGENTA', self.Color.MAGENTA), - ('CYAN', self.Color.CYAN), - ('name', Enum.__dict__['name']), - ('value', Enum.__dict__['value']), - ('__len__', self.Color.__len__), - ('__contains__', self.Color.__contains__), - ('__name__', 'Color'), - ('__getitem__', self.Color.__getitem__), - ('__qualname__', 'TestStdLib.Color'), - ('__init_subclass__', getattr(self.Color, '__init_subclass__')), - ('__iter__', self.Color.__iter__), - )) + values = dict( + ( + ("__class__", EnumType), + ("__doc__", "..."), + ("__members__", self.Color.__members__), + ("__module__", __name__), + ("YELLOW", self.Color.YELLOW), + ("MAGENTA", self.Color.MAGENTA), + ("CYAN", self.Color.CYAN), + ("name", Enum.__dict__["name"]), + ("value", Enum.__dict__["value"]), + ("__len__", self.Color.__len__), + ("__contains__", self.Color.__contains__), + ("__name__", "Color"), + ("__getitem__", self.Color.__getitem__), + ("__qualname__", "TestStdLib.Color"), + ("__init_subclass__", getattr(self.Color, "__init_subclass__")), + ("__iter__", self.Color.__iter__), + ) + ) result = dict(inspect.getmembers(self.Color)) self.assertEqual(set(values.keys()), set(result.keys())) failed = False for k in values.keys(): - if k == '__doc__': + if k == "__doc__": # __doc__ is huge, not comparing continue if result[k] != values[k]: print() - print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' % - ('=' * 75, k, result[k], values[k], '=' * 75), sep='') + print( + "\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n" + % ("=" * 75, k, result[k], values[k], "=" * 75), + sep="", + ) failed = True if failed: self.fail("result does not equal expected, see print above") @@ -4842,40 +5527,96 @@ def test_inspect_getmembers(self): def test_inspect_classify_class_attrs(self): # indirectly test __objclass__ from inspect import Attribute + values = [ - Attribute(name='__class__', kind='data', - defining_class=object, object=EnumType), - Attribute(name='__contains__', kind='method', - defining_class=EnumType, object=self.Color.__contains__), - Attribute(name='__doc__', kind='data', - defining_class=self.Color, object='...'), - Attribute(name='__getitem__', kind='method', - defining_class=EnumType, object=self.Color.__getitem__), - Attribute(name='__iter__', kind='method', - defining_class=EnumType, object=self.Color.__iter__), - Attribute(name='__init_subclass__', kind='class method', - defining_class=object, object=getattr(self.Color, '__init_subclass__')), - Attribute(name='__len__', kind='method', - defining_class=EnumType, object=self.Color.__len__), - Attribute(name='__members__', kind='property', - defining_class=EnumType, object=EnumType.__members__), - Attribute(name='__module__', kind='data', - defining_class=self.Color, object=__name__), - Attribute(name='__name__', kind='data', - defining_class=self.Color, object='Color'), - Attribute(name='__qualname__', kind='data', - defining_class=self.Color, object='TestStdLib.Color'), - Attribute(name='YELLOW', kind='data', - defining_class=self.Color, object=self.Color.YELLOW), - Attribute(name='MAGENTA', kind='data', - defining_class=self.Color, object=self.Color.MAGENTA), - Attribute(name='CYAN', kind='data', - defining_class=self.Color, object=self.Color.CYAN), - Attribute(name='name', kind='data', - defining_class=Enum, object=Enum.__dict__['name']), - Attribute(name='value', kind='data', - defining_class=Enum, object=Enum.__dict__['value']), - ] + Attribute( + name="__class__", kind="data", defining_class=object, object=EnumType + ), + Attribute( + name="__contains__", + kind="method", + defining_class=EnumType, + object=self.Color.__contains__, + ), + Attribute( + name="__doc__", kind="data", defining_class=self.Color, object="..." + ), + Attribute( + name="__getitem__", + kind="method", + defining_class=EnumType, + object=self.Color.__getitem__, + ), + Attribute( + name="__iter__", + kind="method", + defining_class=EnumType, + object=self.Color.__iter__, + ), + Attribute( + name="__init_subclass__", + kind="class method", + defining_class=object, + object=getattr(self.Color, "__init_subclass__"), + ), + Attribute( + name="__len__", + kind="method", + defining_class=EnumType, + object=self.Color.__len__, + ), + Attribute( + name="__members__", + kind="property", + defining_class=EnumType, + object=EnumType.__members__, + ), + Attribute( + name="__module__", + kind="data", + defining_class=self.Color, + object=__name__, + ), + Attribute( + name="__name__", kind="data", defining_class=self.Color, object="Color" + ), + Attribute( + name="__qualname__", + kind="data", + defining_class=self.Color, + object="TestStdLib.Color", + ), + Attribute( + name="YELLOW", + kind="data", + defining_class=self.Color, + object=self.Color.YELLOW, + ), + Attribute( + name="MAGENTA", + kind="data", + defining_class=self.Color, + object=self.Color.MAGENTA, + ), + Attribute( + name="CYAN", + kind="data", + defining_class=self.Color, + object=self.Color.CYAN, + ), + Attribute( + name="name", + kind="data", + defining_class=Enum, + object=Enum.__dict__["name"], + ), + Attribute( + name="value", + kind="data", + defining_class=Enum, + object=Enum.__dict__["value"], + ), + ] for v in values: try: v.name @@ -4885,45 +5626,51 @@ def test_inspect_classify_class_attrs(self): result = list(inspect.classify_class_attrs(self.Color)) result.sort(key=lambda item: item.name) self.assertEqual( - len(values), len(result), - "%s != %s" % ([a.name for a in values], [a.name for a in result]) - ) + len(values), + len(result), + "%s != %s" % ([a.name for a in values], [a.name for a in result]), + ) failed = False for v, r in zip(values, result): - if r.name in ('__init_subclass__', '__doc__'): + if r.name in ("__init_subclass__", "__doc__"): # not sure how to make the __init_subclass_ Attributes match # so as long as there is one, call it good # __doc__ is too big to check exactly, so treat the same as __init_subclass__ - for name in ('name','kind','defining_class'): + for name in ("name", "kind", "defining_class"): if getattr(v, name) != getattr(r, name): - print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='') + print("\n%s\n%s\n%s\n%s\n" % ("=" * 75, r, v, "=" * 75), sep="") failed = True elif r != v: - print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='') + print("\n%s\n%s\n%s\n%s\n" % ("=" * 75, r, v, "=" * 75), sep="") failed = True if failed: self.fail("result does not equal expected, see print above") def test_inspect_signatures(self): from inspect import signature, Signature, Parameter + self.assertEqual( - signature(Enum), - Signature([ - Parameter('new_class_name', Parameter.POSITIONAL_ONLY), - Parameter('names', Parameter.POSITIONAL_OR_KEYWORD), - Parameter('module', Parameter.KEYWORD_ONLY, default=None), - Parameter('qualname', Parameter.KEYWORD_ONLY, default=None), - Parameter('type', Parameter.KEYWORD_ONLY, default=None), - Parameter('start', Parameter.KEYWORD_ONLY, default=1), - Parameter('boundary', Parameter.KEYWORD_ONLY, default=None), - ]), - ) + signature(Enum), + Signature( + [ + Parameter("new_class_name", Parameter.POSITIONAL_ONLY), + Parameter("names", Parameter.POSITIONAL_OR_KEYWORD), + Parameter("module", Parameter.KEYWORD_ONLY, default=None), + Parameter("qualname", Parameter.KEYWORD_ONLY, default=None), + Parameter("type", Parameter.KEYWORD_ONLY, default=None), + Parameter("start", Parameter.KEYWORD_ONLY, default=1), + Parameter("boundary", Parameter.KEYWORD_ONLY, default=None), + ] + ), + ) self.assertEqual( - signature(enum.FlagBoundary), - Signature([ - Parameter('values', Parameter.VAR_POSITIONAL), - ]), - ) + signature(enum.FlagBoundary), + Signature( + [ + Parameter("values", Parameter.VAR_POSITIONAL), + ] + ), + ) def test_test_simple_enum(self): @_simple_enum(Enum) @@ -4931,29 +5678,42 @@ class SimpleColor: CYAN = 1 MAGENTA = 2 YELLOW = 3 + @bltns.property def zeroth(self): - return 'zeroed %s' % self.name + return "zeroed %s" % self.name + class CheckedColor(Enum): CYAN = 1 MAGENTA = 2 YELLOW = 3 + @bltns.property def zeroth(self): - return 'zeroed %s' % self.name + return "zeroed %s" % self.name + self.assertTrue(_test_simple_enum(CheckedColor, SimpleColor) is None) SimpleColor.MAGENTA._value_ = 9 self.assertRaisesRegex( - TypeError, "enum mismatch", - _test_simple_enum, CheckedColor, SimpleColor, - ) + TypeError, + "enum mismatch", + _test_simple_enum, + CheckedColor, + SimpleColor, + ) + class CheckedMissing(IntFlag, boundary=KEEP): SIXTY_FOUR = 64 ONE_TWENTY_EIGHT = 128 TWENTY_FORTY_EIGHT = 2048 ALL = 2048 + 128 + 64 + 12 + CM = CheckedMissing - self.assertEqual(list(CheckedMissing), [CM.SIXTY_FOUR, CM.ONE_TWENTY_EIGHT, CM.TWENTY_FORTY_EIGHT]) + self.assertEqual( + list(CheckedMissing), + [CM.SIXTY_FOUR, CM.ONE_TWENTY_EIGHT, CM.TWENTY_FORTY_EIGHT], + ) + # @_simple_enum(IntFlag, boundary=KEEP) class Missing: @@ -4961,26 +5721,31 @@ class Missing: ONE_TWENTY_EIGHT = 128 TWENTY_FORTY_EIGHT = 2048 ALL = 2048 + 128 + 64 + 12 + M = Missing - self.assertEqual(list(CheckedMissing), [M.SIXTY_FOUR, M.ONE_TWENTY_EIGHT, M.TWENTY_FORTY_EIGHT]) + self.assertEqual( + list(CheckedMissing), + [M.SIXTY_FOUR, M.ONE_TWENTY_EIGHT, M.TWENTY_FORTY_EIGHT], + ) # _test_simple_enum(CheckedMissing, Missing) class MiscTestCase(unittest.TestCase): - def test__all__(self): - support.check__all__(self, enum, not_exported={'bin', 'show_flag_values'}) + support.check__all__(self, enum, not_exported={"bin", "show_flag_values"}) def test_doc_1(self): class Single(Enum): ONE = 1 + self.assertEqual(Single.__doc__, None) def test_doc_2(self): class Double(Enum): ONE = 1 TWO = 2 + self.assertEqual(Double.__doc__, None) def test_doc_3(self): @@ -4988,6 +5753,7 @@ class Triple(Enum): ONE = 1 TWO = 2 THREE = 3 + self.assertEqual(Triple.__doc__, None) def test_doc_4(self): @@ -4996,6 +5762,7 @@ class Quadruple(Enum): TWO = 2 THREE = 3 FOUR = 4 + self.assertEqual(Quadruple.__doc__, None) @@ -5016,52 +5783,50 @@ class Quadruple(Enum): CONVERT_STRING_TEST_NAME_F = 5 # global names for StrEnum._convert_ test -CONVERT_STR_TEST_2 = 'goodbye' -CONVERT_STR_TEST_1 = 'hello' +CONVERT_STR_TEST_2 = "goodbye" +CONVERT_STR_TEST_1 = "hello" # We also need values that cannot be compared: UNCOMPARABLE_A = 5 UNCOMPARABLE_C = (9, 1) # naming order is broken on purpose -UNCOMPARABLE_B = 'value' +UNCOMPARABLE_B = "value" COMPLEX_C = 1j COMPLEX_A = 2j COMPLEX_B = 3j + class TestConvert(unittest.TestCase): def tearDown(self): # Reset the module-level test variables to their original integer # values, otherwise the already created enum values get converted # instead. g = globals() - for suffix in ['A', 'B', 'C', 'D', 'E', 'F']: - g['CONVERT_TEST_NAME_%s' % suffix] = 5 - g['CONVERT_STRING_TEST_NAME_%s' % suffix] = 5 - for suffix, value in (('A', 5), ('B', (9, 1)), ('C', 'value')): - g['UNCOMPARABLE_%s' % suffix] = value - for suffix, value in (('A', 2j), ('B', 3j), ('C', 1j)): - g['COMPLEX_%s' % suffix] = value - for suffix, value in (('1', 'hello'), ('2', 'goodbye')): - g['CONVERT_STR_TEST_%s' % suffix] = value + for suffix in ["A", "B", "C", "D", "E", "F"]: + g["CONVERT_TEST_NAME_%s" % suffix] = 5 + g["CONVERT_STRING_TEST_NAME_%s" % suffix] = 5 + for suffix, value in (("A", 5), ("B", (9, 1)), ("C", "value")): + g["UNCOMPARABLE_%s" % suffix] = value + for suffix, value in (("A", 2j), ("B", 3j), ("C", 1j)): + g["COMPLEX_%s" % suffix] = value + for suffix, value in (("1", "hello"), ("2", "goodbye")): + g["CONVERT_STR_TEST_%s" % suffix] = value def test_convert_value_lookup_priority(self): test_type = enum.IntEnum._convert_( - 'UnittestConvert', - MODULE, - filter=lambda x: x.startswith('CONVERT_TEST_')) + "UnittestConvert", MODULE, filter=lambda x: x.startswith("CONVERT_TEST_") + ) # We don't want the reverse lookup value to vary when there are # multiple possible names for a given value. It should always # report the first lexigraphical name in that case. - self.assertEqual(test_type(5).name, 'CONVERT_TEST_NAME_A') + self.assertEqual(test_type(5).name, "CONVERT_TEST_NAME_A") def test_convert_int(self): test_type = enum.IntEnum._convert_( - 'UnittestConvert', - MODULE, - filter=lambda x: x.startswith('CONVERT_TEST_')) + "UnittestConvert", MODULE, filter=lambda x: x.startswith("CONVERT_TEST_") + ) # Ensure that test_type has all of the desired names and values. - self.assertEqual(test_type.CONVERT_TEST_NAME_F, - test_type.CONVERT_TEST_NAME_A) + self.assertEqual(test_type.CONVERT_TEST_NAME_F, test_type.CONVERT_TEST_NAME_A) self.assertEqual(test_type.CONVERT_TEST_NAME_B, 5) self.assertEqual(test_type.CONVERT_TEST_NAME_C, 5) self.assertEqual(test_type.CONVERT_TEST_NAME_D, 5) @@ -5070,101 +5835,126 @@ def test_convert_int(self): extra = [name for name in dir(test_type) if name not in enum_dir(test_type)] missing = [name for name in enum_dir(test_type) if name not in dir(test_type)] self.assertEqual( - extra + missing, - [], - msg='extra names: %r; missing names: %r' % (extra, missing), - ) - + extra + missing, + [], + msg="extra names: %r; missing names: %r" % (extra, missing), + ) def test_convert_uncomparable(self): uncomp = enum.Enum._convert_( - 'Uncomparable', - MODULE, - filter=lambda x: x.startswith('UNCOMPARABLE_')) + "Uncomparable", MODULE, filter=lambda x: x.startswith("UNCOMPARABLE_") + ) # Should be ordered by `name` only: self.assertEqual( list(uncomp), [uncomp.UNCOMPARABLE_A, uncomp.UNCOMPARABLE_B, uncomp.UNCOMPARABLE_C], - ) + ) def test_convert_complex(self): uncomp = enum.Enum._convert_( - 'Uncomparable', - MODULE, - filter=lambda x: x.startswith('COMPLEX_')) + "Uncomparable", MODULE, filter=lambda x: x.startswith("COMPLEX_") + ) # Should be ordered by `name` only: self.assertEqual( list(uncomp), [uncomp.COMPLEX_A, uncomp.COMPLEX_B, uncomp.COMPLEX_C], - ) + ) def test_convert_str(self): test_type = enum.StrEnum._convert_( - 'UnittestConvert', - MODULE, - filter=lambda x: x.startswith('CONVERT_STR_'), - as_global=True) + "UnittestConvert", + MODULE, + filter=lambda x: x.startswith("CONVERT_STR_"), + as_global=True, + ) # Ensure that test_type has all of the desired names and values. - self.assertEqual(test_type.CONVERT_STR_TEST_1, 'hello') - self.assertEqual(test_type.CONVERT_STR_TEST_2, 'goodbye') + self.assertEqual(test_type.CONVERT_STR_TEST_1, "hello") + self.assertEqual(test_type.CONVERT_STR_TEST_2, "goodbye") # Ensure that test_type only picked up names matching the filter. extra = [name for name in dir(test_type) if name not in enum_dir(test_type)] missing = [name for name in enum_dir(test_type) if name not in dir(test_type)] self.assertEqual( - extra + missing, - [], - msg='extra names: %r; missing names: %r' % (extra, missing), - ) - self.assertEqual(repr(test_type.CONVERT_STR_TEST_1), '%s.CONVERT_STR_TEST_1' % SHORT_MODULE) - self.assertEqual(str(test_type.CONVERT_STR_TEST_2), 'goodbye') - self.assertEqual(format(test_type.CONVERT_STR_TEST_1), 'hello') + extra + missing, + [], + msg="extra names: %r; missing names: %r" % (extra, missing), + ) + self.assertEqual( + repr(test_type.CONVERT_STR_TEST_1), "%s.CONVERT_STR_TEST_1" % SHORT_MODULE + ) + self.assertEqual(str(test_type.CONVERT_STR_TEST_2), "goodbye") + self.assertEqual(format(test_type.CONVERT_STR_TEST_1), "hello") def test_convert_raise(self): with self.assertRaises(AttributeError): enum.IntEnum._convert( - 'UnittestConvert', + "UnittestConvert", MODULE, - filter=lambda x: x.startswith('CONVERT_TEST_')) + filter=lambda x: x.startswith("CONVERT_TEST_"), + ) def test_convert_repr_and_str(self): test_type = enum.IntEnum._convert_( - 'UnittestConvert', - MODULE, - filter=lambda x: x.startswith('CONVERT_STRING_TEST_'), - as_global=True) - self.assertEqual(repr(test_type.CONVERT_STRING_TEST_NAME_A), '%s.CONVERT_STRING_TEST_NAME_A' % SHORT_MODULE) - self.assertEqual(str(test_type.CONVERT_STRING_TEST_NAME_A), '5') - self.assertEqual(format(test_type.CONVERT_STRING_TEST_NAME_A), '5') + "UnittestConvert", + MODULE, + filter=lambda x: x.startswith("CONVERT_STRING_TEST_"), + as_global=True, + ) + self.assertEqual( + repr(test_type.CONVERT_STRING_TEST_NAME_A), + "%s.CONVERT_STRING_TEST_NAME_A" % SHORT_MODULE, + ) + self.assertEqual(str(test_type.CONVERT_STRING_TEST_NAME_A), "5") + self.assertEqual(format(test_type.CONVERT_STRING_TEST_NAME_A), "5") # helpers + def enum_dir(cls): - interesting = set([ - '__class__', '__contains__', '__doc__', '__getitem__', - '__iter__', '__len__', '__members__', '__module__', - '__name__', '__qualname__', - ] - + cls._member_names_ - ) + interesting = set( + [ + "__class__", + "__contains__", + "__doc__", + "__getitem__", + "__iter__", + "__len__", + "__members__", + "__module__", + "__name__", + "__qualname__", + ] + + cls._member_names_ + ) if cls._new_member_ is not object.__new__: - interesting.add('__new__') + interesting.add("__new__") if cls.__init_subclass__ is not object.__init_subclass__: - interesting.add('__init_subclass__') + interesting.add("__init_subclass__") if cls._member_type_ is object: return sorted(interesting) else: # return whatever mixed-in data type has return sorted(set(dir(cls._member_type_)) | interesting) + def member_dir(member): if member.__class__._member_type_ is object: - allowed = set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value']) + allowed = set( + [ + "__class__", + "__doc__", + "__eq__", + "__hash__", + "__module__", + "name", + "value", + ] + ) else: allowed = set(dir(member)) for cls in member.__class__.mro(): for name, obj in cls.__dict__.items(): - if name[0] == '_': + if name[0] == "_": continue if isinstance(obj, enum.property): if obj.fget is not None or name not in member._member_map_: @@ -5176,5 +5966,5 @@ def member_dir(member): return sorted(allowed) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index e4de2c5ede15f1..4d4845476c7e66 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -24,12 +24,10 @@ import functools -py_functools = import_helper.import_fresh_module('functools', - blocked=['_functools']) -c_functools = import_helper.import_fresh_module('functools', - fresh=['_functools']) +py_functools = import_helper.import_fresh_module("functools", blocked=["_functools"]) +c_functools = import_helper.import_fresh_module("functools", fresh=["_functools"]) -decimal = import_helper.import_fresh_module('decimal', fresh=['_decimal']) +decimal = import_helper.import_fresh_module("decimal", fresh=["_decimal"]) _partial_types = [py_functools.partial] if c_functools: @@ -45,35 +43,37 @@ def replaced_module(name, replacement): finally: sys.modules[name] = original_module + def capture(*args, **kw): """capture all positional and keyword arguments""" return args, kw def signature(part): - """ return the signature of a partial object """ + """return the signature of a partial object""" return (part.func, part.args, part.keywords, part.__dict__) + class MyTuple(tuple): pass + class BadTuple(tuple): def __add__(self, other): return list(self) + list(other) + class MyDict(dict): pass class TestPartial: - def test_basic_examples(self): p = self.partial(capture, 1, 2, a=10, b=20) self.assertTrue(callable(p)) - self.assertEqual(p(3, 4, b=30, c=40), - ((1, 2, 3, 4), dict(a=10, b=30, c=40))) - p = self.partial(map, lambda x: x*10) - self.assertEqual(list(p([1,2,3,4])), [10, 20, 30, 40]) + self.assertEqual(p(3, 4, b=30, c=40), ((1, 2, 3, 4), dict(a=10, b=30, c=40))) + p = self.partial(map, lambda x: x * 10) + self.assertEqual(list(p([1, 2, 3, 4])), [10, 20, 30, 40]) def test_attributes(self): p = self.partial(capture, 1, 2, a=10, b=20) @@ -83,43 +83,44 @@ def test_attributes(self): self.assertEqual(p.keywords, dict(a=10, b=20)) def test_argument_checking(self): - self.assertRaises(TypeError, self.partial) # need at least a func arg + self.assertRaises(TypeError, self.partial) # need at least a func arg try: self.partial(2)() except TypeError: pass else: - self.fail('First arg not checked for callability') + self.fail("First arg not checked for callability") def test_protection_of_callers_dict_argument(self): # a caller's dictionary should not be altered by partial def func(a=10, b=20): return a - d = {'a':3} + + d = {"a": 3} p = self.partial(func, a=5) self.assertEqual(p(**d), 3) - self.assertEqual(d, {'a':3}) + self.assertEqual(d, {"a": 3}) p(b=7) - self.assertEqual(d, {'a':3}) + self.assertEqual(d, {"a": 3}) def test_kwargs_copy(self): # Issue #29532: Altering a kwarg dictionary passed to a constructor # should not affect a partial object after creation - d = {'a': 3} + d = {"a": 3} p = self.partial(capture, **d) - self.assertEqual(p(), ((), {'a': 3})) - d['a'] = 5 - self.assertEqual(p(), ((), {'a': 3})) + self.assertEqual(p(), ((), {"a": 3})) + d["a"] = 5 + self.assertEqual(p(), ((), {"a": 3})) def test_arg_combinations(self): # exercise special code paths for zero args in either partial # object or the caller p = self.partial(capture) self.assertEqual(p(), ((), {})) - self.assertEqual(p(1,2), ((1,2), {})) + self.assertEqual(p(1, 2), ((1, 2), {})) p = self.partial(capture, 1, 2) - self.assertEqual(p(), ((1,2), {})) - self.assertEqual(p(3,4), ((1,2,3,4), {})) + self.assertEqual(p(), ((1, 2), {})) + self.assertEqual(p(3, 4), ((1, 2, 3, 4), {})) def test_kw_combinations(self): # exercise special code paths for no keyword args in @@ -127,27 +128,27 @@ def test_kw_combinations(self): p = self.partial(capture) self.assertEqual(p.keywords, {}) self.assertEqual(p(), ((), {})) - self.assertEqual(p(a=1), ((), {'a':1})) + self.assertEqual(p(a=1), ((), {"a": 1})) p = self.partial(capture, a=1) - self.assertEqual(p.keywords, {'a':1}) - self.assertEqual(p(), ((), {'a':1})) - self.assertEqual(p(b=2), ((), {'a':1, 'b':2})) + self.assertEqual(p.keywords, {"a": 1}) + self.assertEqual(p(), ((), {"a": 1})) + self.assertEqual(p(b=2), ((), {"a": 1, "b": 2})) # keyword args in the call override those in the partial object - self.assertEqual(p(a=3, b=2), ((), {'a':3, 'b':2})) + self.assertEqual(p(a=3, b=2), ((), {"a": 3, "b": 2})) def test_positional(self): # make sure positional arguments are captured correctly - for args in [(), (0,), (0,1), (0,1,2), (0,1,2,3)]: + for args in [(), (0,), (0, 1), (0, 1, 2), (0, 1, 2, 3)]: p = self.partial(capture, *args) - expected = args + ('x',) - got, empty = p('x') + expected = args + ("x",) + got, empty = p("x") self.assertTrue(expected == got and empty == {}) def test_keyword(self): # make sure keyword arguments are captured correctly - for a in ['a', 0, None, 3.5]: + for a in ["a", 0, None, 3.5]: p = self.partial(capture, a=a) - expected = {'a':a,'x':None} + expected = {"a": a, "x": None} empty, got = p(x=None) self.assertTrue(expected == got and empty == ()) @@ -155,13 +156,14 @@ def test_no_side_effects(self): # make sure there are no side effects that affect subsequent calls p = self.partial(capture, 0, a=1) args1, kw1 = p(1, b=2) - self.assertTrue(args1 == (0,1) and kw1 == {'a':1,'b':2}) + self.assertTrue(args1 == (0, 1) and kw1 == {"a": 1, "b": 2}) args2, kw2 = p() - self.assertTrue(args2 == (0,) and kw2 == {'a':1}) + self.assertTrue(args2 == (0,) and kw2 == {"a": 1}) def test_error_propagation(self): def f(x, y): x / y + self.assertRaises(ZeroDivisionError, self.partial(f, 1, 0)) self.assertRaises(ZeroDivisionError, self.partial(f, 1), 0) self.assertRaises(ZeroDivisionError, self.partial(f), 1, 0) @@ -173,20 +175,20 @@ def test_weakref(self): self.assertEqual(f.func, p.func) f = None support.gc_collect() # For PyPy or other GCs. - self.assertRaises(ReferenceError, getattr, p, 'func') + self.assertRaises(ReferenceError, getattr, p, "func") def test_with_bound_and_unbound_methods(self): data = list(map(str, range(10))) - join = self.partial(str.join, '') - self.assertEqual(join(data), '0123456789') - join = self.partial(''.join) - self.assertEqual(join(data), '0123456789') + join = self.partial(str.join, "") + self.assertEqual(join(data), "0123456789") + join = self.partial("".join) + self.assertEqual(join(data), "0123456789") def test_nested_optimization(self): partial = self.partial - inner = partial(signature, 'asdf') + inner = partial(signature, "asdf") nested = partial(inner, bar=True) - flat = partial(signature, 'asdf', bar=True) + flat = partial(signature, "asdf", bar=True) self.assertEqual(signature(nested), signature(flat)) def test_nested_partial_with_attribute(self): @@ -196,75 +198,96 @@ def test_nested_partial_with_attribute(self): def foo(bar): return bar - p = partial(foo, 'first') - p2 = partial(p, 'second') - p2.new_attr = 'spam' - self.assertEqual(p2.new_attr, 'spam') + p = partial(foo, "first") + p2 = partial(p, "second") + p2.new_attr = "spam" + self.assertEqual(p2.new_attr, "spam") def test_repr(self): args = (object(), object()) - args_repr = ', '.join(repr(a) for a in args) - kwargs = {'a': object(), 'b': object()} - kwargs_reprs = ['a={a!r}, b={b!r}'.format_map(kwargs), - 'b={b!r}, a={a!r}'.format_map(kwargs)] + args_repr = ", ".join(repr(a) for a in args) + kwargs = {"a": object(), "b": object()} + kwargs_reprs = [ + "a={a!r}, b={b!r}".format_map(kwargs), + "b={b!r}, a={a!r}".format_map(kwargs), + ] if self.partial in _partial_types: - name = 'functools.partial' + name = "functools.partial" else: name = self.partial.__name__ f = self.partial(capture) - self.assertEqual(f'{name}({capture!r})', repr(f)) + self.assertEqual(f"{name}({capture!r})", repr(f)) f = self.partial(capture, *args) - self.assertEqual(f'{name}({capture!r}, {args_repr})', repr(f)) + self.assertEqual(f"{name}({capture!r}, {args_repr})", repr(f)) f = self.partial(capture, **kwargs) - self.assertIn(repr(f), - [f'{name}({capture!r}, {kwargs_repr})' - for kwargs_repr in kwargs_reprs]) + self.assertIn( + repr(f), + [f"{name}({capture!r}, {kwargs_repr})" for kwargs_repr in kwargs_reprs], + ) f = self.partial(capture, *args, **kwargs) - self.assertIn(repr(f), - [f'{name}({capture!r}, {args_repr}, {kwargs_repr})' - for kwargs_repr in kwargs_reprs]) + self.assertIn( + repr(f), + [ + f"{name}({capture!r}, {args_repr}, {kwargs_repr})" + for kwargs_repr in kwargs_reprs + ], + ) def test_recursive_repr(self): if self.partial in _partial_types: - name = 'functools.partial' + name = "functools.partial" else: name = self.partial.__name__ f = self.partial(capture) f.__setstate__((f, (), {}, {})) try: - self.assertEqual(repr(f), '%s(...)' % (name,)) + self.assertEqual(repr(f), "%s(...)" % (name,)) finally: f.__setstate__((capture, (), {}, {})) f = self.partial(capture) f.__setstate__((capture, (f,), {}, {})) try: - self.assertEqual(repr(f), '%s(%r, ...)' % (name, capture,)) + self.assertEqual( + repr(f), + "%s(%r, ...)" + % ( + name, + capture, + ), + ) finally: f.__setstate__((capture, (), {}, {})) f = self.partial(capture) - f.__setstate__((capture, (), {'a': f}, {})) + f.__setstate__((capture, (), {"a": f}, {})) try: - self.assertEqual(repr(f), '%s(%r, a=...)' % (name, capture,)) + self.assertEqual( + repr(f), + "%s(%r, a=...)" + % ( + name, + capture, + ), + ) finally: f.__setstate__((capture, (), {}, {})) def test_pickle(self): - with replaced_module('functools', self.module): - f = self.partial(signature, ['asdf'], bar=[True]) + with replaced_module("functools", self.module): + f = self.partial(signature, ["asdf"], bar=[True]) f.attr = [] for proto in range(pickle.HIGHEST_PROTOCOL + 1): f_copy = pickle.loads(pickle.dumps(f, proto)) self.assertEqual(signature(f_copy), signature(f)) def test_copy(self): - f = self.partial(signature, ['asdf'], bar=[True]) + f = self.partial(signature, ["asdf"], bar=[True]) f.attr = [] f_copy = copy.copy(f) self.assertEqual(signature(f_copy), signature(f)) @@ -273,7 +296,7 @@ def test_copy(self): self.assertIs(f_copy.keywords, f.keywords) def test_deepcopy(self): - f = self.partial(signature, ['asdf'], bar=[True]) + f = self.partial(signature, ["asdf"], bar=[True]) f.attr = [] f_copy = copy.deepcopy(f) self.assertEqual(signature(f_copy), signature(f)) @@ -281,30 +304,29 @@ def test_deepcopy(self): self.assertIsNot(f_copy.args, f.args) self.assertIsNot(f_copy.args[0], f.args[0]) self.assertIsNot(f_copy.keywords, f.keywords) - self.assertIsNot(f_copy.keywords['bar'], f.keywords['bar']) + self.assertIsNot(f_copy.keywords["bar"], f.keywords["bar"]) def test_setstate(self): f = self.partial(signature) f.__setstate__((capture, (1,), dict(a=10), dict(attr=[]))) - self.assertEqual(signature(f), - (capture, (1,), dict(a=10), dict(attr=[]))) - self.assertEqual(f(2, b=20), ((1, 2), {'a': 10, 'b': 20})) + self.assertEqual(signature(f), (capture, (1,), dict(a=10), dict(attr=[]))) + self.assertEqual(f(2, b=20), ((1, 2), {"a": 10, "b": 20})) f.__setstate__((capture, (1,), dict(a=10), None)) self.assertEqual(signature(f), (capture, (1,), dict(a=10), {})) - self.assertEqual(f(2, b=20), ((1, 2), {'a': 10, 'b': 20})) + self.assertEqual(f(2, b=20), ((1, 2), {"a": 10, "b": 20})) f.__setstate__((capture, (1,), None, None)) - #self.assertEqual(signature(f), (capture, (1,), {}, {})) - self.assertEqual(f(2, b=20), ((1, 2), {'b': 20})) + # self.assertEqual(signature(f), (capture, (1,), {}, {})) + self.assertEqual(f(2, b=20), ((1, 2), {"b": 20})) self.assertEqual(f(2), ((1, 2), {})) self.assertEqual(f(), ((1,), {})) f.__setstate__((capture, (), {}, None)) self.assertEqual(signature(f), (capture, (), {}, {})) - self.assertEqual(f(2, b=20), ((2,), {'b': 20})) + self.assertEqual(f(2, b=20), ((2,), {"b": 20})) self.assertEqual(f(2), ((2,), {})) self.assertEqual(f(), ((), {})) @@ -326,7 +348,7 @@ def test_setstate_subclasses(self): self.assertIs(type(s[1]), tuple) self.assertIs(type(s[2]), dict) r = f() - self.assertEqual(r, ((1,), {'a': 10})) + self.assertEqual(r, ((1,), {"a": 10})) self.assertIs(type(r[0]), tuple) self.assertIs(type(r[1]), dict) @@ -339,7 +361,7 @@ def test_setstate_subclasses(self): self.assertIs(type(r[0]), tuple) def test_recursive_pickle(self): - with replaced_module('functools', self.module): + with replaced_module("functools", self.module): f = self.partial(capture) f.__setstate__((f, (), {}, {})) try: @@ -362,12 +384,12 @@ def test_recursive_pickle(self): f.__setstate__((capture, (), {}, {})) f = self.partial(capture) - f.__setstate__((capture, (), {'a': f}, {})) + f.__setstate__((capture, (), {"a": f}, {})) try: for proto in range(pickle.HIGHEST_PROTOCOL + 1): f_copy = pickle.loads(pickle.dumps(f, proto)) try: - self.assertIs(f_copy.keywords['a'], f_copy) + self.assertIs(f_copy.keywords["a"], f_copy) finally: f_copy.__setstate__((capture, (), {}, {})) finally: @@ -378,6 +400,7 @@ def test_setstate_refcount(self): class BadSequence: def __len__(self): return 4 + def __getitem__(self, key): if key == 0: return max @@ -390,7 +413,8 @@ def __getitem__(self, key): f = self.partial(object) self.assertRaises(TypeError, f.__setstate__, BadSequence()) -@unittest.skipUnless(c_functools, 'requires the C _functools module') + +@unittest.skipUnless(c_functools, "requires the C _functools module") class TestPartialC(TestPartial, unittest.TestCase): if c_functools: module = c_functools @@ -399,9 +423,9 @@ class TestPartialC(TestPartial, unittest.TestCase): def test_attributes_unwritable(self): # attributes should not be writable p = self.partial(capture, 1, 2, a=10, b=20) - self.assertRaises(AttributeError, setattr, p, 'func', map) - self.assertRaises(AttributeError, setattr, p, 'args', (1, 2)) - self.assertRaises(AttributeError, setattr, p, 'keywords', dict(a=1, b=2)) + self.assertRaises(AttributeError, setattr, p, "func", map) + self.assertRaises(AttributeError, setattr, p, "args", (1, 2)) + self.assertRaises(AttributeError, setattr, p, "keywords", dict(a=1, b=2)) p = self.partial(hex) try: @@ -409,14 +433,14 @@ def test_attributes_unwritable(self): except TypeError: pass else: - self.fail('partial object allowed __dict__ to be deleted') + self.fail("partial object allowed __dict__ to be deleted") def test_manually_adding_non_string_keyword(self): p = self.partial(capture) # Adding a non-string/unicode keyword to partial kwargs - p.keywords[1234] = 'value' + p.keywords[1234] = "value" r = repr(p) - self.assertIn('1234', r) + self.assertIn("1234", r) self.assertIn("'value'", r) with self.assertRaises(TypeError): p() @@ -426,14 +450,14 @@ def test_keystr_replaces_value(self): class MutatesYourDict(object): def __str__(self): - p.keywords[self] = ['sth2'] - return 'astr' + p.keywords[self] = ["sth2"] + return "astr" # Replacing the value during key formatting should keep the original # value alive (at least long enough). - p.keywords[MutatesYourDict()] = ['sth'] + p.keywords[MutatesYourDict()] = ["sth"] r = repr(p) - self.assertIn('astr', r) + self.assertIn("astr", r) self.assertIn("['sth']", r) @@ -443,13 +467,16 @@ class TestPartialPy(TestPartial, unittest.TestCase): if c_functools: + class CPartialSubclass(c_functools.partial): pass + class PyPartialSubclass(py_functools.partial): pass -@unittest.skipUnless(c_functools, 'requires the C _functools module') + +@unittest.skipUnless(c_functools, "requires the C _functools module") class TestPartialCSubclass(TestPartialC): if c_functools: partial = CPartialSubclass @@ -457,11 +484,12 @@ class TestPartialCSubclass(TestPartialC): # partial subclasses are not optimized for nested calls test_nested_optimization = None + class TestPartialPySubclass(TestPartialPy): partial = PyPartialSubclass -class TestPartialMethod(unittest.TestCase): +class TestPartialMethod(unittest.TestCase): class A(object): nothing = functools.partialmethod(capture) positional = functools.partialmethod(capture, 1) @@ -481,43 +509,49 @@ class A(object): def test_arg_combinations(self): self.assertEqual(self.a.nothing(), ((self.a,), {})) self.assertEqual(self.a.nothing(5), ((self.a, 5), {})) - self.assertEqual(self.a.nothing(c=6), ((self.a,), {'c': 6})) - self.assertEqual(self.a.nothing(5, c=6), ((self.a, 5), {'c': 6})) + self.assertEqual(self.a.nothing(c=6), ((self.a,), {"c": 6})) + self.assertEqual(self.a.nothing(5, c=6), ((self.a, 5), {"c": 6})) self.assertEqual(self.a.positional(), ((self.a, 1), {})) self.assertEqual(self.a.positional(5), ((self.a, 1, 5), {})) - self.assertEqual(self.a.positional(c=6), ((self.a, 1), {'c': 6})) - self.assertEqual(self.a.positional(5, c=6), ((self.a, 1, 5), {'c': 6})) + self.assertEqual(self.a.positional(c=6), ((self.a, 1), {"c": 6})) + self.assertEqual(self.a.positional(5, c=6), ((self.a, 1, 5), {"c": 6})) - self.assertEqual(self.a.keywords(), ((self.a,), {'a': 2})) - self.assertEqual(self.a.keywords(5), ((self.a, 5), {'a': 2})) - self.assertEqual(self.a.keywords(c=6), ((self.a,), {'a': 2, 'c': 6})) - self.assertEqual(self.a.keywords(5, c=6), ((self.a, 5), {'a': 2, 'c': 6})) + self.assertEqual(self.a.keywords(), ((self.a,), {"a": 2})) + self.assertEqual(self.a.keywords(5), ((self.a, 5), {"a": 2})) + self.assertEqual(self.a.keywords(c=6), ((self.a,), {"a": 2, "c": 6})) + self.assertEqual(self.a.keywords(5, c=6), ((self.a, 5), {"a": 2, "c": 6})) - self.assertEqual(self.a.both(), ((self.a, 3), {'b': 4})) - self.assertEqual(self.a.both(5), ((self.a, 3, 5), {'b': 4})) - self.assertEqual(self.a.both(c=6), ((self.a, 3), {'b': 4, 'c': 6})) - self.assertEqual(self.a.both(5, c=6), ((self.a, 3, 5), {'b': 4, 'c': 6})) + self.assertEqual(self.a.both(), ((self.a, 3), {"b": 4})) + self.assertEqual(self.a.both(5), ((self.a, 3, 5), {"b": 4})) + self.assertEqual(self.a.both(c=6), ((self.a, 3), {"b": 4, "c": 6})) + self.assertEqual(self.a.both(5, c=6), ((self.a, 3, 5), {"b": 4, "c": 6})) - self.assertEqual(self.A.both(self.a, 5, c=6), ((self.a, 3, 5), {'b': 4, 'c': 6})) + self.assertEqual( + self.A.both(self.a, 5, c=6), ((self.a, 3, 5), {"b": 4, "c": 6}) + ) - self.assertEqual(self.a.spec_keywords(), ((self.a,), {'self': 1, 'func': 2})) + self.assertEqual(self.a.spec_keywords(), ((self.a,), {"self": 1, "func": 2})) def test_nested(self): self.assertEqual(self.a.nested(), ((self.a, 1, 5), {})) self.assertEqual(self.a.nested(6), ((self.a, 1, 5, 6), {})) - self.assertEqual(self.a.nested(d=7), ((self.a, 1, 5), {'d': 7})) - self.assertEqual(self.a.nested(6, d=7), ((self.a, 1, 5, 6), {'d': 7})) + self.assertEqual(self.a.nested(d=7), ((self.a, 1, 5), {"d": 7})) + self.assertEqual(self.a.nested(6, d=7), ((self.a, 1, 5, 6), {"d": 7})) - self.assertEqual(self.A.nested(self.a, 6, d=7), ((self.a, 1, 5, 6), {'d': 7})) + self.assertEqual(self.A.nested(self.a, 6, d=7), ((self.a, 1, 5, 6), {"d": 7})) def test_over_partial(self): - self.assertEqual(self.a.over_partial(), ((self.a, 7), {'c': 6})) - self.assertEqual(self.a.over_partial(5), ((self.a, 7, 5), {'c': 6})) - self.assertEqual(self.a.over_partial(d=8), ((self.a, 7), {'c': 6, 'd': 8})) - self.assertEqual(self.a.over_partial(5, d=8), ((self.a, 7, 5), {'c': 6, 'd': 8})) + self.assertEqual(self.a.over_partial(), ((self.a, 7), {"c": 6})) + self.assertEqual(self.a.over_partial(5), ((self.a, 7, 5), {"c": 6})) + self.assertEqual(self.a.over_partial(d=8), ((self.a, 7), {"c": 6, "d": 8})) + self.assertEqual( + self.a.over_partial(5, d=8), ((self.a, 7, 5), {"c": 6, "d": 8}) + ) - self.assertEqual(self.A.over_partial(self.a, 5, d=8), ((self.a, 7, 5), {'c': 6, 'd': 8})) + self.assertEqual( + self.A.over_partial(self.a, 5, d=8), ((self.a, 7, 5), {"c": 6, "d": 8}) + ) def test_bound_method_introspection(self): obj = self.a @@ -540,36 +574,42 @@ def test_descriptors(self): with self.subTest(obj=obj): self.assertEqual(obj.static(), ((8,), {})) self.assertEqual(obj.static(5), ((8, 5), {})) - self.assertEqual(obj.static(d=8), ((8,), {'d': 8})) - self.assertEqual(obj.static(5, d=8), ((8, 5), {'d': 8})) + self.assertEqual(obj.static(d=8), ((8,), {"d": 8})) + self.assertEqual(obj.static(5, d=8), ((8, 5), {"d": 8})) - self.assertEqual(obj.cls(), ((self.A,), {'d': 9})) - self.assertEqual(obj.cls(5), ((self.A, 5), {'d': 9})) - self.assertEqual(obj.cls(c=8), ((self.A,), {'c': 8, 'd': 9})) - self.assertEqual(obj.cls(5, c=8), ((self.A, 5), {'c': 8, 'd': 9})) + self.assertEqual(obj.cls(), ((self.A,), {"d": 9})) + self.assertEqual(obj.cls(5), ((self.A, 5), {"d": 9})) + self.assertEqual(obj.cls(c=8), ((self.A,), {"c": 8, "d": 9})) + self.assertEqual(obj.cls(5, c=8), ((self.A, 5), {"c": 8, "d": 9})) def test_overriding_keywords(self): - self.assertEqual(self.a.keywords(a=3), ((self.a,), {'a': 3})) - self.assertEqual(self.A.keywords(self.a, a=3), ((self.a,), {'a': 3})) + self.assertEqual(self.a.keywords(a=3), ((self.a,), {"a": 3})) + self.assertEqual(self.A.keywords(self.a, a=3), ((self.a,), {"a": 3})) def test_invalid_args(self): with self.assertRaises(TypeError): + class B(object): method = functools.partialmethod(None, 1) + with self.assertRaises(TypeError): + class B: method = functools.partialmethod() + with self.assertRaises(TypeError): + class B: method = functools.partialmethod(func=capture, a=1) def test_repr(self): - self.assertEqual(repr(vars(self.A)['both']), - 'functools.partialmethod({}, 3, b=4)'.format(capture)) + self.assertEqual( + repr(vars(self.A)["both"]), + "functools.partialmethod({}, 3, b=4)".format(capture), + ) def test_abstract(self): class Abstract(abc.ABCMeta): - @abc.abstractmethod def add(self, x, y): pass @@ -579,8 +619,14 @@ def add(self, x, y): self.assertTrue(Abstract.add.__isabstractmethod__) self.assertTrue(Abstract.add5.__isabstractmethod__) - for func in [self.A.static, self.A.cls, self.A.over_partial, self.A.nested, self.A.both]: - self.assertFalse(getattr(func, '__isabstractmethod__', False)) + for func in [ + self.A.static, + self.A.cls, + self.A.over_partial, + self.A.nested, + self.A.both, + ]: + self.assertFalse(getattr(func, "__isabstractmethod__", False)) def test_positional_only(self): def f(a, b, /): @@ -591,10 +637,13 @@ def f(a, b, /): class TestUpdateWrapper(unittest.TestCase): - - def check_wrapper(self, wrapper, wrapped, - assigned=functools.WRAPPER_ASSIGNMENTS, - updated=functools.WRAPPER_UPDATES): + def check_wrapper( + self, + wrapper, + wrapped, + assigned=functools.WRAPPER_ASSIGNMENTS, + updated=functools.WRAPPER_UPDATES, + ): # Check attributes were assigned for name in assigned: self.assertIs(getattr(wrapper, name), getattr(wrapped, name)) @@ -610,80 +659,91 @@ def check_wrapper(self, wrapper, wrapped, # Check __wrapped__ self.assertIs(wrapper.__wrapped__, wrapped) - def _default_update(self): - def f[T](a:'This is a new annotation'): + def f[T](a: "This is a new annotation"): """This is a test""" pass - f.attr = 'This is also a test' + + f.attr = "This is also a test" f.__wrapped__ = "This is a bald faced lie" - def wrapper(b:'This is the prior annotation'): + + def wrapper(b: "This is the prior annotation"): pass + functools.update_wrapper(wrapper, f) return wrapper, f def test_default_update(self): wrapper, f = self._default_update() self.check_wrapper(wrapper, f) - T, = f.__type_params__ + (T,) = f.__type_params__ self.assertIs(wrapper.__wrapped__, f) - self.assertEqual(wrapper.__name__, 'f') + self.assertEqual(wrapper.__name__, "f") self.assertEqual(wrapper.__qualname__, f.__qualname__) - self.assertEqual(wrapper.attr, 'This is also a test') - self.assertEqual(wrapper.__annotations__['a'], 'This is a new annotation') - self.assertNotIn('b', wrapper.__annotations__) + self.assertEqual(wrapper.attr, "This is also a test") + self.assertEqual(wrapper.__annotations__["a"], "This is a new annotation") + self.assertNotIn("b", wrapper.__annotations__) self.assertEqual(wrapper.__type_params__, (T,)) - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") + @unittest.skipIf( + sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above" + ) def test_default_update_doc(self): wrapper, f = self._default_update() - self.assertEqual(wrapper.__doc__, 'This is a test') + self.assertEqual(wrapper.__doc__, "This is a test") def test_no_update(self): def f(): """This is a test""" pass - f.attr = 'This is also a test' + + f.attr = "This is also a test" + def wrapper(): pass + functools.update_wrapper(wrapper, f, (), ()) self.check_wrapper(wrapper, f, (), ()) - self.assertEqual(wrapper.__name__, 'wrapper') + self.assertEqual(wrapper.__name__, "wrapper") self.assertNotEqual(wrapper.__qualname__, f.__qualname__) self.assertEqual(wrapper.__doc__, None) self.assertEqual(wrapper.__annotations__, {}) - self.assertFalse(hasattr(wrapper, 'attr')) + self.assertFalse(hasattr(wrapper, "attr")) def test_selective_update(self): def f(): pass - f.attr = 'This is a different test' + + f.attr = "This is a different test" f.dict_attr = dict(a=1, b=2, c=3) + def wrapper(): pass + wrapper.dict_attr = {} - assign = ('attr',) - update = ('dict_attr',) + assign = ("attr",) + update = ("dict_attr",) functools.update_wrapper(wrapper, f, assign, update) self.check_wrapper(wrapper, f, assign, update) - self.assertEqual(wrapper.__name__, 'wrapper') + self.assertEqual(wrapper.__name__, "wrapper") self.assertNotEqual(wrapper.__qualname__, f.__qualname__) self.assertEqual(wrapper.__doc__, None) - self.assertEqual(wrapper.attr, 'This is a different test') + self.assertEqual(wrapper.attr, "This is a different test") self.assertEqual(wrapper.dict_attr, f.dict_attr) def test_missing_attributes(self): def f(): pass + def wrapper(): pass + wrapper.dict_attr = {} - assign = ('attr',) - update = ('dict_attr',) + assign = ("attr",) + update = ("dict_attr",) # Missing attributes on wrapped object are ignored functools.update_wrapper(wrapper, f, assign, update) - self.assertNotIn('attr', wrapper.__dict__) + self.assertNotIn("attr", wrapper.__dict__) self.assertEqual(wrapper.dict_attr, {}) # Wrapper must have expected attributes for updating del wrapper.dict_attr @@ -694,77 +754,90 @@ def wrapper(): functools.update_wrapper(wrapper, f, assign, update) @support.requires_docstrings - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") + @unittest.skipIf( + sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above" + ) def test_builtin_update(self): # Test for bug #1576241 def wrapper(): pass + functools.update_wrapper(wrapper, max) - self.assertEqual(wrapper.__name__, 'max') - self.assertTrue(wrapper.__doc__.startswith('max(')) + self.assertEqual(wrapper.__name__, "max") + self.assertTrue(wrapper.__doc__.startswith("max(")) self.assertEqual(wrapper.__annotations__, {}) class TestWraps(TestUpdateWrapper): - def _default_update(self): def f(): """This is a test""" pass - f.attr = 'This is also a test' + + f.attr = "This is also a test" f.__wrapped__ = "This is still a bald faced lie" + @functools.wraps(f) def wrapper(): pass + return wrapper, f def test_default_update(self): wrapper, f = self._default_update() self.check_wrapper(wrapper, f) - self.assertEqual(wrapper.__name__, 'f') + self.assertEqual(wrapper.__name__, "f") self.assertEqual(wrapper.__qualname__, f.__qualname__) - self.assertEqual(wrapper.attr, 'This is also a test') + self.assertEqual(wrapper.attr, "This is also a test") - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") + @unittest.skipIf( + sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above" + ) def test_default_update_doc(self): wrapper, _ = self._default_update() - self.assertEqual(wrapper.__doc__, 'This is a test') + self.assertEqual(wrapper.__doc__, "This is a test") def test_no_update(self): def f(): """This is a test""" pass - f.attr = 'This is also a test' + + f.attr = "This is also a test" + @functools.wraps(f, (), ()) def wrapper(): pass + self.check_wrapper(wrapper, f, (), ()) - self.assertEqual(wrapper.__name__, 'wrapper') + self.assertEqual(wrapper.__name__, "wrapper") self.assertNotEqual(wrapper.__qualname__, f.__qualname__) self.assertEqual(wrapper.__doc__, None) - self.assertFalse(hasattr(wrapper, 'attr')) + self.assertFalse(hasattr(wrapper, "attr")) def test_selective_update(self): def f(): pass - f.attr = 'This is a different test' + + f.attr = "This is a different test" f.dict_attr = dict(a=1, b=2, c=3) + def add_dict_attr(f): f.dict_attr = {} return f - assign = ('attr',) - update = ('dict_attr',) + + assign = ("attr",) + update = ("dict_attr",) + @functools.wraps(f, assign, update) @add_dict_attr def wrapper(): pass + self.check_wrapper(wrapper, f, assign, update) - self.assertEqual(wrapper.__name__, 'wrapper') + self.assertEqual(wrapper.__name__, "wrapper") self.assertNotEqual(wrapper.__qualname__, f.__qualname__) self.assertEqual(wrapper.__doc__, None) - self.assertEqual(wrapper.attr, 'This is a different test') + self.assertEqual(wrapper.attr, "This is a different test") self.assertEqual(wrapper.dict_attr, f.dict_attr) @@ -779,23 +852,24 @@ def __len__(self): return len(self.sofar) def __getitem__(self, i): - if not 0 <= i < self.max: raise IndexError + if not 0 <= i < self.max: + raise IndexError n = len(self.sofar) while n <= i: - self.sofar.append(n*n) + self.sofar.append(n * n) n += 1 return self.sofar[i] + def add(x, y): return x + y - self.assertEqual(self.reduce(add, ['a', 'b', 'c'], ''), 'abc') + + self.assertEqual(self.reduce(add, ["a", "b", "c"], ""), "abc") self.assertEqual( - self.reduce(add, [['a', 'c'], [], ['d', 'w']], []), - ['a','c','d','w'] + self.reduce(add, [["a", "c"], [], ["d", "w"]], []), ["a", "c", "d", "w"] ) - self.assertEqual(self.reduce(lambda x, y: x*y, range(2,8), 1), 5040) + self.assertEqual(self.reduce(lambda x, y: x * y, range(2, 8), 1), 5040) self.assertEqual( - self.reduce(lambda x, y: x*y, range(2,21), 1), - 2432902008176640000 + self.reduce(lambda x, y: x * y, range(2, 21), 1), 2432902008176640000 ) self.assertEqual(self.reduce(add, Squares(10)), 285) self.assertEqual(self.reduce(add, Squares(10), 0), 285) @@ -803,10 +877,16 @@ def add(x, y): self.assertRaises(TypeError, self.reduce) self.assertRaises(TypeError, self.reduce, 42, 42) self.assertRaises(TypeError, self.reduce, 42, 42, 42) - self.assertEqual(self.reduce(42, "1"), "1") # func is never called with one item - self.assertEqual(self.reduce(42, "", "1"), "1") # func is never called with one item + self.assertEqual( + self.reduce(42, "1"), "1" + ) # func is never called with one item + self.assertEqual( + self.reduce(42, "", "1"), "1" + ) # func is never called with one item self.assertRaises(TypeError, self.reduce, 42, (42, 42)) - self.assertRaises(TypeError, self.reduce, add, []) # arg 2 must not be empty sequence with no initial value + self.assertRaises( + TypeError, self.reduce, add, [] + ) # arg 2 must not be empty sequence with no initial value self.assertRaises(TypeError, self.reduce, add, "") self.assertRaises(TypeError, self.reduce, add, ()) self.assertRaises(TypeError, self.reduce, add, object()) @@ -814,6 +894,7 @@ def add(x, y): class TestFailingIter: def __iter__(self): raise RuntimeError + self.assertRaises(RuntimeError, self.reduce, add, TestFailingIter()) self.assertEqual(self.reduce(add, [], None), None) @@ -822,6 +903,7 @@ def __iter__(self): class BadSeq: def __getitem__(self, index): raise ValueError + self.assertRaises(ValueError, self.reduce, 42, BadSeq()) # Test reduce()'s use of iterators. @@ -829,6 +911,7 @@ def test_iterator_usage(self): class SequenceClass: def __init__(self, n): self.n = n + def __getitem__(self, i): if 0 <= i < self.n: return i @@ -836,6 +919,7 @@ def __getitem__(self, i): raise IndexError from operator import add + self.assertEqual(self.reduce(add, SequenceClass(5)), 10) self.assertEqual(self.reduce(add, SequenceClass(5), 42), 52) self.assertRaises(TypeError, self.reduce, add, SequenceClass(0)) @@ -847,7 +931,7 @@ def __getitem__(self, i): self.assertEqual(self.reduce(add, d), "".join(d.keys())) -@unittest.skipUnless(c_functools, 'requires the C _functools module') +@unittest.skipUnless(c_functools, "requires the C _functools module") class TestReduceC(TestReduce, unittest.TestCase): if c_functools: reduce = c_functools.reduce @@ -858,10 +942,10 @@ class TestReducePy(TestReduce, unittest.TestCase): class TestCmpToKey: - def test_cmp_to_key(self): def cmp1(x, y): return (x > y) - (x < y) + key = self.cmp_to_key(cmp1) self.assertEqual(key(3), key(3)) self.assertGreater(key(3), key(1)) @@ -869,35 +953,38 @@ def cmp1(x, y): def cmp2(x, y): return int(x) - int(y) + key = self.cmp_to_key(cmp2) - self.assertEqual(key(4.0), key('4')) - self.assertLess(key(2), key('35')) - self.assertLessEqual(key(2), key('35')) - self.assertNotEqual(key(2), key('35')) + self.assertEqual(key(4.0), key("4")) + self.assertLess(key(2), key("35")) + self.assertLessEqual(key(2), key("35")) + self.assertNotEqual(key(2), key("35")) def test_cmp_to_key_arguments(self): def cmp1(x, y): return (x > y) - (x < y) + key = self.cmp_to_key(mycmp=cmp1) self.assertEqual(key(obj=3), key(obj=3)) self.assertGreater(key(obj=3), key(obj=1)) with self.assertRaises((TypeError, AttributeError)): - key(3) > 1 # rhs is not a K object + key(3) > 1 # rhs is not a K object with self.assertRaises((TypeError, AttributeError)): - 1 < key(3) # lhs is not a K object + 1 < key(3) # lhs is not a K object with self.assertRaises(TypeError): - key = self.cmp_to_key() # too few args + key = self.cmp_to_key() # too few args with self.assertRaises(TypeError): - key = self.cmp_to_key(cmp1, None) # too many args + key = self.cmp_to_key(cmp1, None) # too many args key = self.cmp_to_key(cmp1) with self.assertRaises(TypeError): - key() # too few args + key() # too few args with self.assertRaises(TypeError): - key(None, None) # too many args + key(None, None) # too many args def test_bad_cmp(self): def cmp1(x, y): raise ZeroDivisionError + key = self.cmp_to_key(cmp1) with self.assertRaises(ZeroDivisionError): key(3) > key(1) @@ -905,46 +992,49 @@ def cmp1(x, y): class BadCmp: def __lt__(self, other): raise ZeroDivisionError + def cmp1(x, y): return BadCmp() + with self.assertRaises(ZeroDivisionError): key(3) > key(1) def test_obj_field(self): def cmp1(x, y): return (x > y) - (x < y) + key = self.cmp_to_key(mycmp=cmp1) self.assertEqual(key(50).obj, 50) def test_sort_int(self): def mycmp(x, y): return y - x - self.assertEqual(sorted(range(5), key=self.cmp_to_key(mycmp)), - [4, 3, 2, 1, 0]) + + self.assertEqual(sorted(range(5), key=self.cmp_to_key(mycmp)), [4, 3, 2, 1, 0]) def test_sort_int_str(self): def mycmp(x, y): x, y = int(x), int(y) return (x > y) - (x < y) - values = [5, '3', 7, 2, '0', '1', 4, '10', 1] + + values = [5, "3", 7, 2, "0", "1", 4, "10", 1] values = sorted(values, key=self.cmp_to_key(mycmp)) - self.assertEqual([int(value) for value in values], - [0, 1, 1, 2, 3, 4, 5, 7, 10]) + self.assertEqual([int(value) for value in values], [0, 1, 1, 2, 3, 4, 5, 7, 10]) def test_hash(self): def mycmp(x, y): return y - x + key = self.cmp_to_key(mycmp) k = key(10) self.assertRaises(TypeError, hash, k) self.assertNotIsInstance(k, collections.abc.Hashable) def test_cmp_to_signature(self): - self.assertEqual(str(Signature.from_callable(self.cmp_to_key)), - '(mycmp)') + self.assertEqual(str(Signature.from_callable(self.cmp_to_key)), "(mycmp)") -@unittest.skipUnless(c_functools, 'requires the C _functools module') +@unittest.skipUnless(c_functools, "requires the C _functools module") class TestCmpToKeyC(TestCmpToKey, unittest.TestCase): if c_functools: cmp_to_key = c_functools.cmp_to_key @@ -952,9 +1042,7 @@ class TestCmpToKeyC(TestCmpToKey, unittest.TestCase): @support.cpython_only def test_disallow_instantiation(self): # Ensure that the type disallows instantiation (bpo-43916) - support.check_disallow_instantiation( - self, type(c_functools.cmp_to_key(None)) - ) + support.check_disallow_instantiation(self, type(c_functools.cmp_to_key(None))) class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase): @@ -962,16 +1050,18 @@ class TestCmpToKeyPy(TestCmpToKey, unittest.TestCase): class TestTotalOrdering(unittest.TestCase): - def test_total_ordering_lt(self): @functools.total_ordering class A: def __init__(self, value): self.value = value + def __lt__(self, other): return self.value < other.value + def __eq__(self, other): return self.value == other.value + self.assertTrue(A(1) < A(2)) self.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -985,10 +1075,13 @@ def test_total_ordering_le(self): class A: def __init__(self, value): self.value = value + def __le__(self, other): return self.value <= other.value + def __eq__(self, other): return self.value == other.value + self.assertTrue(A(1) < A(2)) self.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -1002,10 +1095,13 @@ def test_total_ordering_gt(self): class A: def __init__(self, value): self.value = value + def __gt__(self, other): return self.value > other.value + def __eq__(self, other): return self.value == other.value + self.assertTrue(A(1) < A(2)) self.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -1019,10 +1115,13 @@ def test_total_ordering_ge(self): class A: def __init__(self, value): self.value = value + def __ge__(self, other): return self.value >= other.value + def __eq__(self, other): return self.value == other.value + self.assertTrue(A(1) < A(2)) self.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -1036,6 +1135,7 @@ def test_total_ordering_no_overwrite(self): @functools.total_ordering class A(int): pass + self.assertTrue(A(1) < A(2)) self.assertTrue(A(2) > A(1)) self.assertTrue(A(1) <= A(2)) @@ -1045,6 +1145,7 @@ class A(int): def test_no_operations_defined(self): with self.assertRaises(ValueError): + @functools.total_ordering class A: pass @@ -1055,10 +1156,12 @@ def test_notimplemented(self): class ImplementsLessThan: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ImplementsLessThan): return self.value == other.value return False + def __lt__(self, other): if isinstance(other, ImplementsLessThan): return self.value < other.value @@ -1068,10 +1171,12 @@ def __lt__(self, other): class ImplementsLessThanEqualTo: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ImplementsLessThanEqualTo): return self.value == other.value return False + def __le__(self, other): if isinstance(other, ImplementsLessThanEqualTo): return self.value <= other.value @@ -1081,10 +1186,12 @@ def __le__(self, other): class ImplementsGreaterThan: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ImplementsGreaterThan): return self.value == other.value return False + def __gt__(self, other): if isinstance(other, ImplementsGreaterThan): return self.value > other.value @@ -1094,10 +1201,12 @@ def __gt__(self, other): class ImplementsGreaterThanEqualTo: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ImplementsGreaterThanEqualTo): return self.value == other.value return False + def __ge__(self, other): if isinstance(other, ImplementsGreaterThanEqualTo): return self.value >= other.value @@ -1123,10 +1232,12 @@ def test_type_error_when_not_implemented(self): class ImplementsLessThan: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ImplementsLessThan): return self.value == other.value return False + def __lt__(self, other): if isinstance(other, ImplementsLessThan): return self.value < other.value @@ -1136,10 +1247,12 @@ def __lt__(self, other): class ImplementsGreaterThan: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ImplementsGreaterThan): return self.value == other.value return False + def __gt__(self, other): if isinstance(other, ImplementsGreaterThan): return self.value > other.value @@ -1149,10 +1262,12 @@ def __gt__(self, other): class ImplementsLessThanEqualTo: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ImplementsLessThanEqualTo): return self.value == other.value return False + def __le__(self, other): if isinstance(other, ImplementsLessThanEqualTo): return self.value <= other.value @@ -1162,10 +1277,12 @@ def __le__(self, other): class ImplementsGreaterThanEqualTo: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ImplementsGreaterThanEqualTo): return self.value == other.value return False + def __ge__(self, other): if isinstance(other, ImplementsGreaterThanEqualTo): return self.value >= other.value @@ -1175,10 +1292,12 @@ def __ge__(self, other): class ComparatorNotImplemented: def __init__(self, value): self.value = value + def __eq__(self, other): if isinstance(other, ComparatorNotImplemented): return self.value == other.value return False + def __lt__(self, other): return NotImplemented @@ -1225,15 +1344,13 @@ def __lt__(self, other): def test_pickle(self): for proto in range(pickle.HIGHEST_PROTOCOL + 1): - for name in '__lt__', '__gt__', '__le__', '__ge__': + for name in "__lt__", "__gt__", "__le__", "__ge__": with self.subTest(method=name, proto=proto): method = getattr(Orderable_LT, name) method_copy = pickle.loads(pickle.dumps(method, proto)) self.assertIs(method_copy, method) - def test_total_ordering_for_metaclasses_issue_44605(self): - @functools.total_ordering class SortableMeta(type): def __new__(cls, name, bases, ns): @@ -1263,8 +1380,10 @@ class A(metaclass=SortableMeta): class Orderable_LT: def __init__(self, value): self.value = value + def __lt__(self, other): return self.value < other.value + def __eq__(self, other): return self.value == other.value @@ -1278,21 +1397,28 @@ def test_cache(self): def fib(n): if n < 2: return n - return fib(n-1) + fib(n-2) - self.assertEqual([fib(n) for n in range(16)], - [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) - self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + return fib(n - 1) + fib(n - 2) + + self.assertEqual( + [fib(n) for n in range(16)], + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610], + ) + self.assertEqual( + fib.cache_info(), + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16), + ) fib.cache_clear() - self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.assertEqual( + fib.cache_info(), + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0), + ) class TestLRU: - def test_lru(self): def orig(x, y): return 3 * x + y + f = self.module.lru_cache(maxsize=20)(orig) hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(maxsize, 20) @@ -1311,7 +1437,7 @@ def orig(x, y): self.assertEqual(hits + misses, 1000) self.assertEqual(currsize, 20) - f.cache_clear() # test clearing + f.cache_clear() # test clearing hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(hits, 0) self.assertEqual(misses, 0) @@ -1336,6 +1462,7 @@ def f(): nonlocal f_cnt f_cnt += 1 return 20 + self.assertEqual(f.cache_info().maxsize, 0) f_cnt = 0 for i in range(5): @@ -1352,6 +1479,7 @@ def f(): nonlocal f_cnt f_cnt += 1 return 20 + self.assertEqual(f.cache_info().maxsize, 1) f_cnt = 0 for i in range(5): @@ -1367,12 +1495,13 @@ def f(): def f(x): nonlocal f_cnt f_cnt += 1 - return x*10 + return x * 10 + self.assertEqual(f.cache_info().maxsize, 2) f_cnt = 0 for x in 7, 9, 7, 9, 7, 9, 8, 8, 8, 9, 9, 9, 8, 8, 8, 7: # * * * * - self.assertEqual(f(x), x*10) + self.assertEqual(f(x), x * 10) self.assertEqual(f_cnt, 4) hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(hits, 12) @@ -1382,10 +1511,9 @@ def f(x): def test_lru_no_args(self): @self.module.lru_cache def square(x): - return x ** 2 + return x**2 - self.assertEqual(list(map(square, [10, 20, 10])), - [100, 400, 100]) + self.assertEqual(list(map(square, [10, 20, 10])), [100, 400, 100]) self.assertEqual(square.cache_info().hits, 1) self.assertEqual(square.cache_info().misses, 2) self.assertEqual(square.cache_info().maxsize, 128) @@ -1398,12 +1526,12 @@ def test_lru_bug_35780(self): # This cause the cache to have orphan links not referenced # by the cache dictionary. - once = True # Modified by f(x) below + once = True # Modified by f(x) below @self.module.lru_cache(maxsize=10) def f(x): nonlocal once - rv = f'.{x}.' + rv = f".{x}." if x == 20 and once: once = False rv = f(x) @@ -1411,11 +1539,11 @@ def f(x): # Fill the cache for x in range(15): - self.assertEqual(f(x), f'.{x}.') + self.assertEqual(f(x), f".{x}.") self.assertEqual(f.cache_info().currsize, 10) # Make a recursive call and make sure the cache remains full - self.assertEqual(f(20), '.20.') + self.assertEqual(f(20), ".20.") self.assertEqual(f.cache_info().currsize, 10) def test_lru_bug_36650(self): @@ -1475,7 +1603,7 @@ def test_lru_reentrancy_with_len(self): try: builtins.len = self.module.lru_cache(4)(len) for i in [0, 0, 1, 2, 3, 3, 4, 5, 6, 1, 7, 2, 1]: - self.assertEqual(len('abcdefghijklmn'[:i]), i) + self.assertEqual(len("abcdefghijklmn"[:i]), i) finally: builtins.len = old_len @@ -1512,33 +1640,45 @@ def test_lru_with_maxsize_none(self): def fib(n): if n < 2: return n - return fib(n-1) + fib(n-2) - self.assertEqual([fib(n) for n in range(16)], - [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) - self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + return fib(n - 1) + fib(n - 2) + + self.assertEqual( + [fib(n) for n in range(16)], + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610], + ) + self.assertEqual( + fib.cache_info(), + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16), + ) fib.cache_clear() - self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.assertEqual( + fib.cache_info(), + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0), + ) def test_lru_with_maxsize_negative(self): @self.module.lru_cache(maxsize=-10) def eq(n): return n + for i in (0, 1): self.assertEqual([eq(n) for n in range(150)], list(range(150))) - self.assertEqual(eq.cache_info(), - self.module._CacheInfo(hits=0, misses=300, maxsize=0, currsize=0)) + self.assertEqual( + eq.cache_info(), + self.module._CacheInfo(hits=0, misses=300, maxsize=0, currsize=0), + ) def test_lru_with_exceptions(self): # Verify that user_function exceptions get passed through without # creating a hard-to-read chained exception. # http://bugs.python.org/issue13177 for maxsize in (None, 128): + @self.module.lru_cache(maxsize) def func(i): - return 'abc'[i] - self.assertEqual(func(0), 'a') + return "abc"[i] + + self.assertEqual(func(0), "a") with self.assertRaises(IndexError) as cm: func(15) self.assertIsNone(cm.exception.__context__) @@ -1548,9 +1688,11 @@ def func(i): def test_lru_with_types(self): for maxsize in (None, 128): + @self.module.lru_cache(maxsize=maxsize, typed=True) def square(x): return x * x + self.assertEqual(square(3), 9) self.assertEqual(type(square(3)), type(9)) self.assertEqual(square(3.0), 9.0) @@ -1565,74 +1707,90 @@ def square(x): def test_lru_cache_typed_is_not_recursive(self): cached = self.module.lru_cache(typed=True)(repr) - self.assertEqual(cached(1), '1') - self.assertEqual(cached(True), 'True') - self.assertEqual(cached(1.0), '1.0') - self.assertEqual(cached(0), '0') - self.assertEqual(cached(False), 'False') - self.assertEqual(cached(0.0), '0.0') + self.assertEqual(cached(1), "1") + self.assertEqual(cached(True), "True") + self.assertEqual(cached(1.0), "1.0") + self.assertEqual(cached(0), "0") + self.assertEqual(cached(False), "False") + self.assertEqual(cached(0.0), "0.0") - self.assertEqual(cached((1,)), '(1,)') - self.assertEqual(cached((True,)), '(1,)') - self.assertEqual(cached((1.0,)), '(1,)') - self.assertEqual(cached((0,)), '(0,)') - self.assertEqual(cached((False,)), '(0,)') - self.assertEqual(cached((0.0,)), '(0,)') + self.assertEqual(cached((1,)), "(1,)") + self.assertEqual(cached((True,)), "(1,)") + self.assertEqual(cached((1.0,)), "(1,)") + self.assertEqual(cached((0,)), "(0,)") + self.assertEqual(cached((False,)), "(0,)") + self.assertEqual(cached((0.0,)), "(0,)") class T(tuple): pass - self.assertEqual(cached(T((1,))), '(1,)') - self.assertEqual(cached(T((True,))), '(1,)') - self.assertEqual(cached(T((1.0,))), '(1,)') - self.assertEqual(cached(T((0,))), '(0,)') - self.assertEqual(cached(T((False,))), '(0,)') - self.assertEqual(cached(T((0.0,))), '(0,)') + self.assertEqual(cached(T((1,))), "(1,)") + self.assertEqual(cached(T((True,))), "(1,)") + self.assertEqual(cached(T((1.0,))), "(1,)") + self.assertEqual(cached(T((0,))), "(0,)") + self.assertEqual(cached(T((False,))), "(0,)") + self.assertEqual(cached(T((0.0,))), "(0,)") def test_lru_with_keyword_args(self): @self.module.lru_cache() def fib(n): if n < 2: return n - return fib(n=n-1) + fib(n=n-2) + return fib(n=n - 1) + fib(n=n - 2) + self.assertEqual( [fib(n=number) for number in range(16)], - [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610], + ) + self.assertEqual( + fib.cache_info(), + self.module._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16), ) - self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=128, currsize=16)) fib.cache_clear() - self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0)) + self.assertEqual( + fib.cache_info(), + self.module._CacheInfo(hits=0, misses=0, maxsize=128, currsize=0), + ) def test_lru_with_keyword_args_maxsize_none(self): @self.module.lru_cache(maxsize=None) def fib(n): if n < 2: return n - return fib(n=n-1) + fib(n=n-2) - self.assertEqual([fib(n=number) for number in range(16)], - [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]) - self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16)) + return fib(n=n - 1) + fib(n=n - 2) + + self.assertEqual( + [fib(n=number) for number in range(16)], + [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610], + ) + self.assertEqual( + fib.cache_info(), + self.module._CacheInfo(hits=28, misses=16, maxsize=None, currsize=16), + ) fib.cache_clear() - self.assertEqual(fib.cache_info(), - self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0)) + self.assertEqual( + fib.cache_info(), + self.module._CacheInfo(hits=0, misses=0, maxsize=None, currsize=0), + ) def test_kwargs_order(self): # PEP 468: Preserving Keyword Argument Order @self.module.lru_cache(maxsize=10) def f(**kwargs): return list(kwargs.items()) - self.assertEqual(f(a=1, b=2), [('a', 1), ('b', 2)]) - self.assertEqual(f(b=2, a=1), [('b', 2), ('a', 1)]) - self.assertEqual(f.cache_info(), - self.module._CacheInfo(hits=0, misses=2, maxsize=10, currsize=2)) + + self.assertEqual(f(a=1, b=2), [("a", 1), ("b", 2)]) + self.assertEqual(f(b=2, a=1), [("b", 2), ("a", 1)]) + self.assertEqual( + f.cache_info(), + self.module._CacheInfo(hits=0, misses=2, maxsize=10, currsize=2), + ) def test_lru_cache_decoration(self): - def f(zomg: 'zomg_annotation'): + def f(zomg: "zomg_annotation"): """f doc string""" return 42 + g = self.module.lru_cache()(f) for attr in self.module.WRAPPER_ASSIGNMENTS: self.assertEqual(getattr(g, attr), getattr(f, attr)) @@ -1640,13 +1798,16 @@ def f(zomg: 'zomg_annotation'): @threading_helper.requires_working_threading() def test_lru_cache_threaded(self): n, m = 5, 11 + def orig(x, y): return 3 * x + y - f = self.module.lru_cache(maxsize=n*m)(orig) + + f = self.module.lru_cache(maxsize=n * m)(orig) hits, misses, maxsize, currsize = f.cache_info() self.assertEqual(currsize, 0) start = threading.Event() + def full(k): start.wait(10) for _ in range(m): @@ -1654,15 +1815,14 @@ def full(k): def clear(): start.wait(10) - for _ in range(2*m): + for _ in range(2 * m): f.cache_clear() orig_si = sys.getswitchinterval() support.setswitchinterval(1e-6) try: # create n threads in order to fill cache - threads = [threading.Thread(target=full, args=[k]) - for k in range(n)] + threads = [threading.Thread(target=full, args=[k]) for k in range(n)] with threading_helper.start_threads(threads): start.set() @@ -1670,16 +1830,15 @@ def clear(): if self.module is py_functools: # XXX: Why can be not equal? self.assertLessEqual(misses, n) - self.assertLessEqual(hits, m*n - misses) + self.assertLessEqual(hits, m * n - misses) else: self.assertEqual(misses, n) - self.assertEqual(hits, m*n - misses) + self.assertEqual(hits, m * n - misses) self.assertEqual(currsize, n) # create n threads in order to fill cache and 1 to clear it threads = [threading.Thread(target=clear)] - threads += [threading.Thread(target=full, args=[k]) - for k in range(n)] + threads += [threading.Thread(target=full, args=[k]) for k in range(n)] start.clear() with threading_helper.start_threads(threads): start.set() @@ -1690,19 +1849,23 @@ def clear(): def test_lru_cache_threaded2(self): # Simultaneous call with the same arguments n, m = 5, 7 - start = threading.Barrier(n+1) - pause = threading.Barrier(n+1) - stop = threading.Barrier(n+1) - @self.module.lru_cache(maxsize=m*n) + start = threading.Barrier(n + 1) + pause = threading.Barrier(n + 1) + stop = threading.Barrier(n + 1) + + @self.module.lru_cache(maxsize=m * n) def f(x): pause.wait(10) return 3 * x - self.assertEqual(f.cache_info(), (0, 0, m*n, 0)) + + self.assertEqual(f.cache_info(), (0, 0, m * n, 0)) + def test(): for i in range(m): start.wait(10) self.assertEqual(f(i), 3 * i) stop.wait(10) + threads = [threading.Thread(target=test) for k in range(n)] with threading_helper.start_threads(threads): for i in range(m): @@ -1712,19 +1875,23 @@ def test(): start.reset() stop.wait(10) pause.reset() - self.assertEqual(f.cache_info(), (0, (i+1)*n, m*n, i+1)) + self.assertEqual(f.cache_info(), (0, (i + 1) * n, m * n, i + 1)) @threading_helper.requires_working_threading() def test_lru_cache_threaded3(self): @self.module.lru_cache(maxsize=2) def f(x): - time.sleep(.01) + time.sleep(0.01) return 3 * x + def test(i, x): with self.subTest(thread=i): self.assertEqual(f(x), 3 * x, i) - threads = [threading.Thread(target=test, args=(i, v)) - for i, v in enumerate([1, 2, 2, 3, 2])] + + threads = [ + threading.Thread(target=test, args=(i, v)) + for i, v in enumerate([1, 2, 2, 3, 2]) + ] with threading_helper.start_threads(threads): pass @@ -1733,49 +1900,56 @@ def test_need_for_rlock(self): @self.module.lru_cache(maxsize=10) def test_func(x): - 'Used to demonstrate a reentrant lru_cache call within a single thread' + "Used to demonstrate a reentrant lru_cache call within a single thread" return x class DoubleEq: - 'Demonstrate a reentrant lru_cache call within a single thread' + "Demonstrate a reentrant lru_cache call within a single thread" + def __init__(self, x): self.x = x + def __hash__(self): return self.x + def __eq__(self, other): if self.x == 2: test_func(DoubleEq(1)) return self.x == other.x - test_func(DoubleEq(1)) # Load the cache - test_func(DoubleEq(2)) # Load the cache - self.assertEqual(test_func(DoubleEq(2)), # Trigger a re-entrant __eq__ call - DoubleEq(2)) # Verify the correct return value + test_func(DoubleEq(1)) # Load the cache + test_func(DoubleEq(2)) # Load the cache + self.assertEqual( + test_func(DoubleEq(2)), # Trigger a re-entrant __eq__ call + DoubleEq(2), + ) # Verify the correct return value def test_lru_method(self): class X(int): f_cnt = 0 + @self.module.lru_cache(2) def f(self, x): self.f_cnt += 1 - return x*10+self + return x * 10 + self + a = X(5) b = X(5) c = X(7) self.assertEqual(X.f.cache_info(), (0, 0, 2, 0)) for x in 1, 2, 2, 3, 1, 1, 1, 2, 3, 3: - self.assertEqual(a.f(x), x*10 + 5) + self.assertEqual(a.f(x), x * 10 + 5) self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 0, 0)) self.assertEqual(X.f.cache_info(), (4, 6, 2, 2)) for x in 1, 2, 1, 1, 1, 1, 3, 2, 2, 2: - self.assertEqual(b.f(x), x*10 + 5) + self.assertEqual(b.f(x), x * 10 + 5) self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 4, 0)) self.assertEqual(X.f.cache_info(), (10, 10, 2, 2)) for x in 2, 1, 1, 1, 1, 2, 1, 3, 2, 1: - self.assertEqual(c.f(x), x*10 + 7) + self.assertEqual(c.f(x), x * 10 + 7) self.assertEqual((a.f_cnt, b.f_cnt, c.f_cnt), (6, 4, 5)) self.assertEqual(X.f.cache_info(), (15, 15, 2, 2)) @@ -1793,11 +1967,17 @@ def test_pickle(self): def test_copy(self): cls = self.__class__ + def orig(x, y): return 3 * x + y + part = self.module.partial(orig, 2) - funcs = (cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth, - self.module.lru_cache(2)(part)) + funcs = ( + cls.cached_func[0], + cls.cached_meth, + cls.cached_staticmeth, + self.module.lru_cache(2)(part), + ) for f in funcs: with self.subTest(func=f): f_copy = copy.copy(f) @@ -1805,11 +1985,17 @@ def orig(x, y): def test_deepcopy(self): cls = self.__class__ + def orig(x, y): return 3 * x + y + part = self.module.partial(orig, 2) - funcs = (cls.cached_func[0], cls.cached_meth, cls.cached_staticmeth, - self.module.lru_cache(2)(part)) + funcs = ( + cls.cached_func[0], + cls.cached_meth, + cls.cached_staticmeth, + self.module.lru_cache(2)(part), + ) for f in funcs: with self.subTest(func=f): f_copy = copy.deepcopy(f) @@ -1819,12 +2005,14 @@ def test_lru_cache_parameters(self): @self.module.lru_cache(maxsize=2) def f(): return 1 - self.assertEqual(f.cache_parameters(), {'maxsize': 2, "typed": False}) + + self.assertEqual(f.cache_parameters(), {"maxsize": 2, "typed": False}) @self.module.lru_cache(maxsize=1000, typed=True) def f(): return 1 - self.assertEqual(f.cache_parameters(), {'maxsize': 1000, "typed": True}) + + self.assertEqual(f.cache_parameters(), {"maxsize": 1000, "typed": True}) def test_lru_cache_weakrefable(self): @self.module.lru_cache @@ -1841,9 +2029,11 @@ def test_method(self, x): def test_staticmethod(x): return (self, x) - refs = [weakref.ref(test_function), - weakref.ref(A.test_method), - weakref.ref(A.test_staticmethod)] + refs = [ + weakref.ref(test_function), + weakref.ref(A.test_method), + weakref.ref(A.test_staticmethod), + ] for ref in refs: self.assertIsNotNone(ref()) @@ -1856,18 +2046,22 @@ def test_staticmethod(x): self.assertIsNone(ref()) def test_common_signatures(self): - def orig(): ... + def orig(): + ... + lru = self.module.lru_cache(1)(orig) - self.assertEqual(str(Signature.from_callable(lru.cache_info)), '()') - self.assertEqual(str(Signature.from_callable(lru.cache_clear)), '()') + self.assertEqual(str(Signature.from_callable(lru.cache_info)), "()") + self.assertEqual(str(Signature.from_callable(lru.cache_clear)), "()") @py_functools.lru_cache() def py_cached_func(x, y): return 3 * x + y + if c_functools: + @c_functools.lru_cache() def c_cached_func(x, y): return 3 * x + y @@ -1875,7 +2069,7 @@ def c_cached_func(x, y): class TestLRUPy(TestLRU, unittest.TestCase): module = py_functools - cached_func = py_cached_func, + cached_func = (py_cached_func,) @module.lru_cache() def cached_meth(self, x, y): @@ -1887,11 +2081,11 @@ def cached_staticmeth(x, y): return 3 * x + y -@unittest.skipUnless(c_functools, 'requires the C _functools module') +@unittest.skipUnless(c_functools, "requires the C _functools module") class TestLRUC(TestLRU, unittest.TestCase): if c_functools: module = c_functools - cached_func = c_cached_func, + cached_func = (c_cached_func,) @module.lru_cache() def cached_meth(self, x, y): @@ -1908,29 +2102,38 @@ def test_simple_overloads(self): @functools.singledispatch def g(obj): return "base" + def g_int(i): return "integer" + g.register(int, g_int) self.assertEqual(g("str"), "base") self.assertEqual(g(1), "integer") - self.assertEqual(g([1,2,3]), "base") + self.assertEqual(g([1, 2, 3]), "base") def test_mro(self): @functools.singledispatch def g(obj): return "base" + class A: pass + class C(A): pass + class B(A): pass + class D(C, B): pass + def g_A(a): return "A" + def g_B(b): return "B" + g.register(A, g_A) g.register(B, g_B) self.assertEqual(g(A()), "A") @@ -1942,9 +2145,11 @@ def test_register_decorator(self): @functools.singledispatch def g(obj): return "base" + @g.register(int) def g_int(i): return "int %s" % (i,) + self.assertEqual(g(""), "base") self.assertEqual(g(12), "int 12") self.assertIs(g.dispatch(int), g_int) @@ -1957,26 +2162,31 @@ def test_wrapping_attributes(self): def g(obj): "Simple test" return "Test" + self.assertEqual(g.__name__, "g") if sys.flags.optimize < 2: self.assertEqual(g.__doc__, "Simple test") - @unittest.skipUnless(decimal, 'requires _decimal') + @unittest.skipUnless(decimal, "requires _decimal") @support.cpython_only def test_c_classes(self): @functools.singledispatch def g(obj): return "base" + @g.register(decimal.DecimalException) def _(obj): return obj.args + subn = decimal.Subnormal("Exponent < Emin") rnd = decimal.Rounded("Number got rounded") self.assertEqual(g(subn), ("Exponent < Emin",)) self.assertEqual(g(rnd), ("Number got rounded",)) + @g.register(decimal.Subnormal) def _(obj): return "Too small to care." + self.assertEqual(g(subn), "Too small to care.") self.assertEqual(g(rnd), ("Number got rounded",)) @@ -1987,15 +2197,35 @@ def test_compose_mro(self): bases = [c.Sequence, c.MutableMapping, c.Mapping, c.Set] for haystack in permutations(bases): m = mro(dict, haystack) - self.assertEqual(m, [dict, c.MutableMapping, c.Mapping, - c.Collection, c.Sized, c.Iterable, - c.Container, object]) + self.assertEqual( + m, + [ + dict, + c.MutableMapping, + c.Mapping, + c.Collection, + c.Sized, + c.Iterable, + c.Container, + object, + ], + ) bases = [c.Container, c.Mapping, c.MutableMapping, collections.OrderedDict] for haystack in permutations(bases): m = mro(collections.ChainMap, haystack) - self.assertEqual(m, [collections.ChainMap, c.MutableMapping, c.Mapping, - c.Collection, c.Sized, c.Iterable, - c.Container, object]) + self.assertEqual( + m, + [ + collections.ChainMap, + c.MutableMapping, + c.Mapping, + c.Collection, + c.Sized, + c.Iterable, + c.Container, + object, + ], + ) # If there's a generic function with implementations registered for # both Sized and Container, passing a defaultdict to it results in an @@ -2004,22 +2234,38 @@ def test_compose_mro(self): bases = [c.Container, c.Sized, str] for haystack in permutations(bases): m = mro(collections.defaultdict, [c.Sized, c.Container, str]) - self.assertEqual(m, [collections.defaultdict, dict, c.Sized, - c.Container, object]) + self.assertEqual( + m, [collections.defaultdict, dict, c.Sized, c.Container, object] + ) # MutableSequence below is registered directly on D. In other words, it # precedes MutableMapping which means single dispatch will always # choose MutableSequence here. class D(collections.defaultdict): pass + c.MutableSequence.register(D) bases = [c.MutableSequence, c.MutableMapping] for haystack in permutations(bases): m = mro(D, haystack) - self.assertEqual(m, [D, c.MutableSequence, c.Sequence, c.Reversible, - collections.defaultdict, dict, c.MutableMapping, c.Mapping, - c.Collection, c.Sized, c.Iterable, c.Container, - object]) + self.assertEqual( + m, + [ + D, + c.MutableSequence, + c.Sequence, + c.Reversible, + collections.defaultdict, + dict, + c.MutableMapping, + c.Mapping, + c.Collection, + c.Sized, + c.Iterable, + c.Container, + object, + ], + ) # Container and Callable are registered on different base classes and # a generic function supporting both should always pick the Callable @@ -2027,12 +2273,25 @@ class D(collections.defaultdict): class C(collections.defaultdict): def __call__(self): pass + bases = [c.Sized, c.Callable, c.Container, c.Mapping] for haystack in permutations(bases): m = mro(C, haystack) - self.assertEqual(m, [C, c.Callable, collections.defaultdict, dict, c.Mapping, - c.Collection, c.Sized, c.Iterable, - c.Container, object]) + self.assertEqual( + m, + [ + C, + c.Callable, + collections.defaultdict, + dict, + c.Mapping, + c.Collection, + c.Sized, + c.Iterable, + c.Container, + object, + ], + ) def test_register_abc(self): c = collections.abc @@ -2041,9 +2300,11 @@ def test_register_abc(self): s = {object(), None} f = frozenset(s) t = (1, 2, 3) + @functools.singledispatch def g(obj): return "base" + self.assertEqual(g(d), "base") self.assertEqual(g(l), "base") self.assertEqual(g(s), "base") @@ -2131,19 +2392,25 @@ def g(obj): def test_c3_abc(self): c = collections.abc mro = functools._c3_mro + class A(object): pass + class B(A): def __len__(self): - return 0 # implies Sized + return 0 # implies Sized + @c.Container.register class C(object): pass + class D(object): - pass # unrelated + pass # unrelated + class X(D, C, B): def __call__(self): - pass # implies Callable + pass # implies Callable + expected = [X, c.Callable, D, C, c.Container, B, c.Sized, A, object] for abcs in permutations([c.Sized, c.Callable, c.Container]): self.assertEqual(mro(X, abcs=abcs), expected) @@ -2156,27 +2423,35 @@ def test_false_meta(self): class MetaA(type): def __len__(self): return 0 + class A(metaclass=MetaA): pass + class AA(A): pass + @functools.singledispatch def fun(a): - return 'base A' + return "base A" + @fun.register(A) def _(a): - return 'fun A' + return "fun A" + aa = AA() - self.assertEqual(fun(aa), 'fun A') + self.assertEqual(fun(aa), "fun A") def test_mro_conflicts(self): c = collections.abc + @functools.singledispatch def g(arg): return "base" + class O(c.Sized): def __len__(self): return 0 + o = O() self.assertEqual(g(o), "base") g.register(c.Iterable, lambda arg: "iterable") @@ -2185,14 +2460,16 @@ def __len__(self): g.register(c.Set, lambda arg: "set") self.assertEqual(g(o), "sized") c.Iterable.register(O) - self.assertEqual(g(o), "sized") # because it's explicitly in __mro__ + self.assertEqual(g(o), "sized") # because it's explicitly in __mro__ c.Container.register(O) - self.assertEqual(g(o), "sized") # see above: Sized is in __mro__ + self.assertEqual(g(o), "sized") # see above: Sized is in __mro__ c.Set.register(O) - self.assertEqual(g(o), "set") # because c.Set is a subclass of - # c.Sized and c.Container + self.assertEqual(g(o), "set") # because c.Set is a subclass of + + # c.Sized and c.Container class P: pass + p = P() self.assertEqual(g(p), "base") c.Iterable.register(P) @@ -2202,30 +2479,42 @@ class P: g(p) self.assertIn( str(re_one.exception), - (("Ambiguous dispatch: " - "or "), - ("Ambiguous dispatch: " - "or ")), + ( + ( + "Ambiguous dispatch: " + "or " + ), + ( + "Ambiguous dispatch: " + "or " + ), + ), ) + class Q(c.Sized): def __len__(self): return 0 + q = Q() self.assertEqual(g(q), "sized") c.Iterable.register(Q) - self.assertEqual(g(q), "sized") # because it's explicitly in __mro__ + self.assertEqual(g(q), "sized") # because it's explicitly in __mro__ c.Set.register(Q) - self.assertEqual(g(q), "set") # because c.Set is a subclass of - # c.Sized and c.Iterable + self.assertEqual(g(q), "set") # because c.Set is a subclass of + + # c.Sized and c.Iterable @functools.singledispatch def h(arg): return "base" + @h.register(c.Sized) def _(arg): return "sized" + @h.register(c.Container) def _(arg): return "container" + # Even though Sized and Container are explicit bases of MutableMapping, # this ABC is implicitly registered on defaultdict which makes all of # MutableMapping's bases implicit as well from defaultdict's @@ -2234,68 +2523,96 @@ def _(arg): h(collections.defaultdict(lambda: 0)) self.assertIn( str(re_two.exception), - (("Ambiguous dispatch: " - "or "), - ("Ambiguous dispatch: " - "or ")), + ( + ( + "Ambiguous dispatch: " + "or " + ), + ( + "Ambiguous dispatch: " + "or " + ), + ), ) + class R(collections.defaultdict): pass + c.MutableSequence.register(R) + @functools.singledispatch def i(arg): return "base" + @i.register(c.MutableMapping) def _(arg): return "mapping" + @i.register(c.MutableSequence) def _(arg): return "sequence" + r = R() self.assertEqual(i(r), "sequence") + class S: pass + class T(S, c.Sized): def __len__(self): return 0 + t = T() self.assertEqual(h(t), "sized") c.Container.register(T) - self.assertEqual(h(t), "sized") # because it's explicitly in the MRO + self.assertEqual(h(t), "sized") # because it's explicitly in the MRO + class U: def __len__(self): return 0 + u = U() - self.assertEqual(h(u), "sized") # implicit Sized subclass inferred - # from the existence of __len__() + self.assertEqual(h(u), "sized") # implicit Sized subclass inferred + # from the existence of __len__() c.Container.register(U) # There is no preference for registered versus inferred ABCs. with self.assertRaises(RuntimeError) as re_three: h(u) self.assertIn( str(re_three.exception), - (("Ambiguous dispatch: " - "or "), - ("Ambiguous dispatch: " - "or ")), + ( + ( + "Ambiguous dispatch: " + "or " + ), + ( + "Ambiguous dispatch: " + "or " + ), + ), ) + class V(c.Sized, S): def __len__(self): return 0 + @functools.singledispatch def j(arg): return "base" + @j.register(S) def _(arg): return "s" + @j.register(c.Container) def _(arg): return "container" + v = V() self.assertEqual(j(v), "s") c.Container.register(V) - self.assertEqual(j(v), "container") # because it ends up right after - # Sized in the MRO + self.assertEqual(j(v), "container") # because it ends up right after + # Sized in the MRO def test_cache_invalidation(self): from collections import UserDict @@ -2306,22 +2623,27 @@ def __init__(self, *args, **kwargs): super(TracingDict, self).__init__(*args, **kwargs) self.set_ops = [] self.get_ops = [] + def __getitem__(self, key): result = self.data[key] self.get_ops.append(key) return result + def __setitem__(self, key, value): self.set_ops.append(key) self.data[key] = value + def clear(self): self.data.clear() td = TracingDict() with support.swap_attr(weakref, "WeakKeyDictionary", lambda: td): c = collections.abc + @functools.singledispatch def g(arg): return "base" + d = {} l = [] self.assertEqual(len(td), 0) @@ -2348,18 +2670,18 @@ def g(arg): self.assertEqual(len(td), 1) self.assertEqual(td.get_ops, [list, dict]) self.assertEqual(td.set_ops, [dict, list, dict]) - self.assertEqual(td.data[dict], - functools._find_impl(dict, g.registry)) + self.assertEqual(td.data[dict], functools._find_impl(dict, g.registry)) self.assertEqual(g(l), "list") self.assertEqual(len(td), 2) self.assertEqual(td.get_ops, [list, dict]) self.assertEqual(td.set_ops, [dict, list, dict, list]) - self.assertEqual(td.data[list], - functools._find_impl(list, g.registry)) + self.assertEqual(td.data[list], functools._find_impl(list, g.registry)) + class X: pass - c.MutableMapping.register(X) # Will not invalidate the cache, - # not using ABCs yet. + + c.MutableMapping.register(X) # Will not invalidate the cache, + # not using ABCs yet. self.assertEqual(g(d), "base") self.assertEqual(g(l), "list") self.assertEqual(td.get_ops, [list, dict, dict, list]) @@ -2380,11 +2702,12 @@ class X: self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list]) g.dispatch(list) g.dispatch(dict) - self.assertEqual(td.get_ops, [list, dict, dict, list, list, dict, - list, dict]) + self.assertEqual( + td.get_ops, [list, dict, dict, list, list, dict, list, dict] + ) self.assertEqual(td.set_ops, [dict, list, dict, list, dict, list]) - c.MutableSet.register(X) # Will invalidate the cache. - self.assertEqual(len(td), 2) # Stale cache. + c.MutableSet.register(X) # Will invalidate the cache. + self.assertEqual(len(td), 2) # Stale cache. self.assertEqual(g(l), "list") self.assertEqual(len(td), 1) g.register(c.MutableMapping, lambda arg: "mutablemapping") @@ -2403,12 +2726,15 @@ def test_annotations(self): @functools.singledispatch def i(arg): return "base" + @i.register def _(arg: collections.abc.Mapping): return "mapping" + @i.register def _(arg: "collections.abc.Sequence"): return "sequence" + self.assertEqual(i(None), "base") self.assertEqual(i({"a": 1}), "mapping") self.assertEqual(i([1, 2, 3]), "sequence") @@ -2424,6 +2750,7 @@ def __init__(self, arg): def __eq__(self, other): return self.arg == other + self.assertEqual(i("str"), "str") def test_method_register(self): @@ -2431,26 +2758,29 @@ class A: @functools.singledispatchmethod def t(self, arg): self.arg = "base" + @t.register(int) def _(self, arg): self.arg = "int" + @t.register(str) def _(self, arg): self.arg = "str" + a = A() a.t(0) self.assertEqual(a.arg, "int") aa = A() - self.assertFalse(hasattr(aa, 'arg')) - a.t('') + self.assertFalse(hasattr(aa, "arg")) + a.t("") self.assertEqual(a.arg, "str") aa = A() - self.assertFalse(hasattr(aa, 'arg')) + self.assertFalse(hasattr(aa, "arg")) a.t(0.0) self.assertEqual(a.arg, "base") aa = A() - self.assertFalse(hasattr(aa, 'arg')) + self.assertFalse(hasattr(aa, "arg")) def test_staticmethod_register(self): class A: @@ -2458,23 +2788,27 @@ class A: @staticmethod def t(arg): return arg + @t.register(int) @staticmethod def _(arg): return isinstance(arg, int) + @t.register(str) @staticmethod def _(arg): return isinstance(arg, str) + a = A() self.assertTrue(A.t(0)) - self.assertTrue(A.t('')) + self.assertTrue(A.t("")) self.assertEqual(A.t(0.0), 0.0) def test_slotted_class(self): class Slot: - __slots__ = ('a', 'b') + __slots__ = ("a", "b") + @functools.singledispatchmethod def go(self, item, arg): pass @@ -2488,7 +2822,8 @@ def _(self, item: int, arg): def test_classmethod_slotted_class(self): class Slot: - __slots__ = ('a', 'b') + __slots__ = ("a", "b") + @functools.singledispatchmethod @classmethod def go(cls, item, arg): @@ -2505,26 +2840,30 @@ def _(cls, item: int, arg): def test_staticmethod_slotted_class(self): class A: - __slots__ = ['a'] + __slots__ = ["a"] + @functools.singledispatchmethod @staticmethod def t(arg): return arg + @t.register(int) @staticmethod def _(arg): return isinstance(arg, int) + @t.register(str) @staticmethod def _(arg): return isinstance(arg, str) + a = A() self.assertTrue(A.t(0)) - self.assertTrue(A.t('')) + self.assertTrue(A.t("")) self.assertEqual(A.t(0.0), 0.0) self.assertTrue(a.t(0)) - self.assertTrue(a.t('')) + self.assertTrue(a.t("")) self.assertEqual(a.t(0.0), 0.0) def test_assignment_behavior(self): @@ -2535,7 +2874,7 @@ def t(arg): return arg a = A() - a.t.foo = 'bar' + a.t.foo = "bar" a2 = A() with self.assertRaises(AttributeError): a2.t.foo @@ -2549,17 +2888,19 @@ def __init__(self, arg): @classmethod def t(cls, arg): return cls("base") + @t.register(int) @classmethod def _(cls, arg): return cls("int") + @t.register(str) @classmethod def _(cls, arg): return cls("str") self.assertEqual(A.t(0).arg, "int") - self.assertEqual(A.t('').arg, "str") + self.assertEqual(A.t("").arg, "str") self.assertEqual(A.t(0.0).arg, "base") def test_callable_register(self): @@ -2576,25 +2917,25 @@ def t(cls, arg): @classmethod def _(cls, arg): return cls("int") + @A.t.register(str) @classmethod def _(cls, arg): return cls("str") self.assertEqual(A.t(0).arg, "int") - self.assertEqual(A.t('').arg, "str") + self.assertEqual(A.t("").arg, "str") self.assertEqual(A.t(0.0).arg, "base") def test_abstractmethod_register(self): class Abstract(metaclass=abc.ABCMeta): - @functools.singledispatchmethod @abc.abstractmethod def add(self, x, y): pass self.assertTrue(Abstract.add.__isabstractmethod__) - self.assertTrue(Abstract.__dict__['add'].__isabstractmethod__) + self.assertTrue(Abstract.__dict__["add"].__isabstractmethod__) with self.assertRaises(TypeError): Abstract() @@ -2604,16 +2945,19 @@ class A: @functools.singledispatchmethod def t(self, arg): return "base" + @t.register def _(self, arg: int): return "int" + @t.register def _(self, arg: str): return "str" + a = A() self.assertEqual(a.t(0), "int") - self.assertEqual(a.t(''), "str") + self.assertEqual(a.t(""), "str") self.assertEqual(a.t(0.0), "base") def test_staticmethod_type_ann_register(self): @@ -2622,18 +2966,21 @@ class A: @staticmethod def t(arg): return arg + @t.register @staticmethod def _(arg: int): return isinstance(arg, int) + @t.register @staticmethod def _(arg: str): return isinstance(arg, str) + a = A() self.assertTrue(A.t(0)) - self.assertTrue(A.t('')) + self.assertTrue(A.t("")) self.assertEqual(A.t(0.0), 0.0) def test_classmethod_type_ann_register(self): @@ -2645,17 +2992,19 @@ def __init__(self, arg): @classmethod def t(cls, arg): return cls("base") + @t.register @classmethod def _(cls, arg: int): return cls("int") + @t.register @classmethod def _(cls, arg: str): return cls("str") self.assertEqual(A.t(0).arg, "int") - self.assertEqual(A.t('').arg, "str") + self.assertEqual(A.t("").arg, "str") self.assertEqual(A.t(0.0).arg, "base") def test_method_wrapping_attributes(self): @@ -2664,11 +3013,13 @@ class A: def func(self, arg: int) -> str: """My function docstring""" return str(arg) + @functools.singledispatchmethod @classmethod def cls_func(cls, arg: int) -> str: """My function docstring""" return str(arg) + @functools.singledispatchmethod @staticmethod def static_func(arg: int) -> str: @@ -2681,26 +3032,28 @@ def static_func(arg: int) -> str: A.cls_func, A().cls_func, A.static_func, - A().static_func + A().static_func, ): with self.subTest(meth=meth): - self.assertEqual(meth.__doc__, 'My function docstring') - self.assertEqual(meth.__annotations__['arg'], int) + self.assertEqual(meth.__doc__, "My function docstring") + self.assertEqual(meth.__annotations__["arg"], int) - self.assertEqual(A.func.__name__, 'func') - self.assertEqual(A().func.__name__, 'func') - self.assertEqual(A.cls_func.__name__, 'cls_func') - self.assertEqual(A().cls_func.__name__, 'cls_func') - self.assertEqual(A.static_func.__name__, 'static_func') - self.assertEqual(A().static_func.__name__, 'static_func') + self.assertEqual(A.func.__name__, "func") + self.assertEqual(A().func.__name__, "func") + self.assertEqual(A.cls_func.__name__, "cls_func") + self.assertEqual(A().cls_func.__name__, "cls_func") + self.assertEqual(A.static_func.__name__, "static_func") + self.assertEqual(A().static_func.__name__, "static_func") def test_double_wrapped_methods(self): def classmethod_friendly_decorator(func): wrapped = func.__func__ + @classmethod @functools.wraps(wrapped) def wrapper(*args, **kwargs): return wrapped(*args, **kwargs) + return wrapper class WithoutSingleDispatch: @@ -2710,7 +3063,7 @@ def cls_context_manager(cls, arg: int) -> str: try: yield str(arg) finally: - return 'Done' + return "Done" @classmethod_friendly_decorator @classmethod @@ -2726,7 +3079,7 @@ def cls_context_manager(cls, arg: int) -> str: try: yield str(arg) finally: - return 'Done' + return "Done" @functools.singledispatchmethod @classmethod_friendly_decorator @@ -2744,53 +3097,49 @@ def decorated_classmethod(cls, arg: int) -> str: single_dispatch_foo = foo self.assertEqual(without_single_dispatch_foo, single_dispatch_foo) - self.assertEqual(single_dispatch_foo, '5') + self.assertEqual(single_dispatch_foo, "5") self.assertEqual( WithoutSingleDispatch.decorated_classmethod(5), - WithSingleDispatch.decorated_classmethod(5) + WithSingleDispatch.decorated_classmethod(5), ) - self.assertEqual(WithSingleDispatch.decorated_classmethod(5), '5') + self.assertEqual(WithSingleDispatch.decorated_classmethod(5), "5") # Behavioural checks now follow - for method_name in ('cls_context_manager', 'decorated_classmethod'): + for method_name in ("cls_context_manager", "decorated_classmethod"): with self.subTest(method=method_name): self.assertEqual( getattr(WithSingleDispatch, method_name).__name__, - getattr(WithoutSingleDispatch, method_name).__name__ + getattr(WithoutSingleDispatch, method_name).__name__, ) self.assertEqual( getattr(WithSingleDispatch(), method_name).__name__, - getattr(WithoutSingleDispatch(), method_name).__name__ + getattr(WithoutSingleDispatch(), method_name).__name__, ) for meth in ( WithSingleDispatch.cls_context_manager, WithSingleDispatch().cls_context_manager, WithSingleDispatch.decorated_classmethod, - WithSingleDispatch().decorated_classmethod + WithSingleDispatch().decorated_classmethod, ): with self.subTest(meth=meth): - self.assertEqual(meth.__doc__, 'My function docstring') - self.assertEqual(meth.__annotations__['arg'], int) + self.assertEqual(meth.__doc__, "My function docstring") + self.assertEqual(meth.__annotations__["arg"], int) self.assertEqual( - WithSingleDispatch.cls_context_manager.__name__, - 'cls_context_manager' + WithSingleDispatch.cls_context_manager.__name__, "cls_context_manager" ) self.assertEqual( - WithSingleDispatch().cls_context_manager.__name__, - 'cls_context_manager' + WithSingleDispatch().cls_context_manager.__name__, "cls_context_manager" ) self.assertEqual( - WithSingleDispatch.decorated_classmethod.__name__, - 'decorated_classmethod' + WithSingleDispatch.decorated_classmethod.__name__, "decorated_classmethod" ) self.assertEqual( - WithSingleDispatch().decorated_classmethod.__name__, - 'decorated_classmethod' + WithSingleDispatch().decorated_classmethod.__name__, "decorated_classmethod" ) def test_invalid_registrations(self): @@ -2799,25 +3148,35 @@ def test_invalid_registrations(self): ". Use either `@register(some_class)` or plain `@register` on an " "annotated function." ) + @functools.singledispatch def i(arg): return "base" + with self.assertRaises(TypeError) as exc: + @i.register(42) def _(arg): return "I annotated with a non-type" + self.assertTrue(str(exc.exception).startswith(msg_prefix + "42")) self.assertTrue(str(exc.exception).endswith(msg_suffix)) with self.assertRaises(TypeError) as exc: + @i.register def _(arg): return "I forgot to annotate" - self.assertTrue(str(exc.exception).startswith(msg_prefix + - "._" - )) + + self.assertTrue( + str(exc.exception).startswith( + msg_prefix + + "._" + ) + ) self.assertTrue(str(exc.exception).endswith(msg_suffix)) with self.assertRaises(TypeError) as exc: + @i.register def _(arg: typing.Iterable[str]): # At runtime, dispatching on generics is impossible. @@ -2825,29 +3184,31 @@ def _(arg: typing.Iterable[str]): # types from `typing`. Instead, annotate with regular types # or ABCs. return "I annotated with a generic collection" - self.assertTrue(str(exc.exception).startswith( - "Invalid annotation for 'arg'." - )) - self.assertTrue(str(exc.exception).endswith( - 'typing.Iterable[str] is not a class.' - )) + + self.assertTrue(str(exc.exception).startswith("Invalid annotation for 'arg'.")) + self.assertTrue( + str(exc.exception).endswith("typing.Iterable[str] is not a class.") + ) with self.assertRaises(TypeError) as exc: + @i.register def _(arg: typing.Union[int, typing.Iterable[str]]): return "Invalid Union" - self.assertTrue(str(exc.exception).startswith( - "Invalid annotation for 'arg'." - )) - self.assertTrue(str(exc.exception).endswith( - 'typing.Union[int, typing.Iterable[str]] not all arguments are classes.' - )) + + self.assertTrue(str(exc.exception).startswith("Invalid annotation for 'arg'.")) + self.assertTrue( + str(exc.exception).endswith( + "typing.Union[int, typing.Iterable[str]] not all arguments are classes." + ) + ) def test_invalid_positional_argument(self): @functools.singledispatch def f(*args): pass - msg = 'f requires at least 1 positional argument' + + msg = "f requires at least 1 positional argument" with self.assertRaisesRegex(TypeError, msg): f() @@ -2923,9 +3284,14 @@ def f(arg): with self.assertRaisesRegex(TypeError, "Invalid first argument to "): f.register(typing.List[int], lambda arg: "typing.GenericAlias") with self.assertRaisesRegex(TypeError, "Invalid first argument to "): - f.register(list[int] | str, lambda arg: "types.UnionTypes(types.GenericAlias)") + f.register( + list[int] | str, lambda arg: "types.UnionTypes(types.GenericAlias)" + ) with self.assertRaisesRegex(TypeError, "Invalid first argument to "): - f.register(typing.List[float] | bytes, lambda arg: "typing.Union[typing.GenericAlias]") + f.register( + typing.List[float] | bytes, + lambda arg: "typing.Union[typing.GenericAlias]", + ) self.assertEqual(f([1]), "default") self.assertEqual(f([1.0]), "default") @@ -2952,18 +3318,25 @@ def f(arg): return "default" with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register def _(arg: list[int]): return "types.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register def _(arg: typing.List[float]): return "typing.GenericAlias" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register def _(arg: list[int] | str): return "types.UnionType(types.GenericAlias)" + with self.assertRaisesRegex(TypeError, "Invalid annotation for 'arg'"): + @f.register def _(arg: typing.List[float] | bytes): return "typing.Union[typing.GenericAlias]" @@ -3000,21 +3373,21 @@ def get_cost(self): class CachedCostItemWithSlots: - __slots__ = ('_cost') + __slots__ = "_cost" def __init__(self): self._cost = 1 @py_functools.cached_property def cost(self): - raise RuntimeError('never called, slots not supported') + raise RuntimeError("never called, slots not supported") class TestCachedProperty(unittest.TestCase): def test_cached(self): item = CachedCostItem() self.assertEqual(item.cost, 2) - self.assertEqual(item.cost, 2) # not 3 + self.assertEqual(item.cost, 2) # not 3 def test_cached_attribute_name_differs_from_func_name(self): item = OptionallyCachedCostItem() @@ -3026,8 +3399,8 @@ def test_cached_attribute_name_differs_from_func_name(self): def test_object_with_slots(self): item = CachedCostItemWithSlots() with self.assertRaisesRegex( - TypeError, - "No '__dict__' attribute on 'CachedCostItemWithSlots' instance to cache 'cost' property.", + TypeError, + "No '__dict__' attribute on 'CachedCostItemWithSlots' instance to cache 'cost' property.", ): item.cost @@ -3049,6 +3422,7 @@ class MyClass(metaclass=MyMeta): def test_reuse_different_names(self): """Disallow this case because decorated function a would not be cached.""" with self.assertRaises(TypeError) as ctx: + class ReusedCachedProperty: @py_functools.cached_property def a(self): @@ -3058,7 +3432,11 @@ def a(self): self.assertEqual( str(ctx.exception), - str(TypeError("Cannot assign the same cached_property to two different names ('a' and 'b').")) + str( + TypeError( + "Cannot assign the same cached_property to two different names ('a' and 'b')." + ) + ), ) def test_reuse_same_name(self): @@ -3086,14 +3464,15 @@ class B: def test_set_name_not_called(self): cp = py_functools.cached_property(lambda s: None) + class Foo: pass Foo.cp = cp with self.assertRaisesRegex( - TypeError, - "Cannot use cached_property instance without calling __set_name__ on it.", + TypeError, + "Cannot use cached_property instance without calling __set_name__ on it.", ): Foo().cp @@ -3108,6 +3487,7 @@ def test_module(self): def test_subclass_with___set__(self): """Caching still works for a subclass defining __set__.""" + class readonly_cached_property(py_functools.cached_property): def __set__(self, obj, value): raise AttributeError("read only property") @@ -3126,5 +3506,5 @@ def prop(self): self.assertEqual(t.prop, 1) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_getopt.py b/Lib/test/test_getopt.py index 056d08322b893a..c8f96a6666a34a 100644 --- a/Lib/test/test_getopt.py +++ b/Lib/test/test_getopt.py @@ -181,10 +181,10 @@ def test_libref_examples(): >>> import getopt - >>> args = '-a -b -cfoo -d bar a1 a2'.split() + >>> args = "-a -b -cfoo -d bar a1 a2".split() >>> args ['-a', '-b', '-cfoo', '-d', 'bar', 'a1', 'a2'] - >>> optlist, args = getopt.getopt(args, 'abc:d:') + >>> optlist, args = getopt.getopt(args, "abc:d:") >>> optlist [('-a', ''), ('-b', ''), ('-c', 'foo'), ('-d', 'bar')] >>> args @@ -193,12 +193,11 @@ def test_libref_examples(): Using long option names is equally easy: - >>> s = '--condition=foo --testing --output-file abc.def -x a1 a2' + >>> s = "--condition=foo --testing --output-file abc.def -x a1 a2" >>> args = s.split() >>> args ['--condition=foo', '--testing', '--output-file', 'abc.def', '-x', 'a1', 'a2'] - >>> optlist, args = getopt.getopt(args, 'x', [ - ... 'condition=', 'output-file=', 'testing']) + >>> optlist, args = getopt.getopt(args, "x", ["condition=", "output-file=", "testing"]) >>> optlist [('--condition', 'foo'), ('--testing', ''), ('--output-file', 'abc.def'), ('-x', '')] >>> args diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 8501006b799262..ef645ea66dcf87 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -7,6 +7,7 @@ import unittest import sys import warnings + # testing import * from sys import * @@ -22,169 +23,177 @@ # Note: since several test cases filter out floats by looking for "e" and ".", # don't add hexadecimal literals that contain "e" or "E". VALID_UNDERSCORE_LITERALS = [ - '0_0_0', - '4_2', - '1_0000_0000', - '0b1001_0100', - '0xffff_ffff', - '0o5_7_7', - '1_00_00.5', - '1_00_00.5e5', - '1_00_00e5_1', - '1e1_0', - '.1_4', - '.1_4e1', - '0b_0', - '0x_f', - '0o_5', - '1_00_00j', - '1_00_00.5j', - '1_00_00e5_1j', - '.1_4j', - '(1_2.5+3_3j)', - '(.5_6j)', + "0_0_0", + "4_2", + "1_0000_0000", + "0b1001_0100", + "0xffff_ffff", + "0o5_7_7", + "1_00_00.5", + "1_00_00.5e5", + "1_00_00e5_1", + "1e1_0", + ".1_4", + ".1_4e1", + "0b_0", + "0x_f", + "0o_5", + "1_00_00j", + "1_00_00.5j", + "1_00_00e5_1j", + ".1_4j", + "(1_2.5+3_3j)", + "(.5_6j)", ] INVALID_UNDERSCORE_LITERALS = [ # Trailing underscores: - '0_', - '42_', - '1.4j_', - '0x_', - '0b1_', - '0xf_', - '0o5_', - '0 if 1_Else 1', + "0_", + "42_", + "1.4j_", + "0x_", + "0b1_", + "0xf_", + "0o5_", + "0 if 1_Else 1", # Underscores in the base selector: - '0_b0', - '0_xf', - '0_o5', + "0_b0", + "0_xf", + "0_o5", # Old-style octal, still disallowed: - '0_7', - '09_99', + "0_7", + "09_99", # Multiple consecutive underscores: - '4_______2', - '0.1__4', - '0.1__4j', - '0b1001__0100', - '0xffff__ffff', - '0x___', - '0o5__77', - '1e1__0', - '1e1__0j', + "4_______2", + "0.1__4", + "0.1__4j", + "0b1001__0100", + "0xffff__ffff", + "0x___", + "0o5__77", + "1e1__0", + "1e1__0j", # Underscore right before a dot: - '1_.4', - '1_.4j', + "1_.4", + "1_.4j", # Underscore right after a dot: - '1._4', - '1._4j', - '._5', - '._5j', + "1._4", + "1._4j", + "._5", + "._5j", # Underscore right after a sign: - '1.0e+_1', - '1.0e+_1j', + "1.0e+_1", + "1.0e+_1j", # Underscore right before j: - '1.4_j', - '1.4e5_j', + "1.4_j", + "1.4e5_j", # Underscore right before e: - '1_e1', - '1.4_e1', - '1.4_e1j', + "1_e1", + "1.4_e1", + "1.4_e1j", # Underscore right after e: - '1e_1', - '1.4e_1', - '1.4e_1j', + "1e_1", + "1.4e_1", + "1.4e_1j", # Complex cases with parens: - '(1+1.5_j_)', - '(1+1.5_j)', + "(1+1.5_j_)", + "(1+1.5_j)", ] class TokenTests(unittest.TestCase): - from test.support import check_syntax_error from test.support.warnings_helper import check_syntax_warning def test_backslash(self): # Backslash means line continuation: - x = 1 \ - + 1 - self.assertEqual(x, 2, 'backslash for line continuation') + x = 1 + 1 + self.assertEqual(x, 2, "backslash for line continuation") # Backslash does not means continuation in comments :\ x = 0 - self.assertEqual(x, 0, 'backslash ending comment') + self.assertEqual(x, 0, "backslash ending comment") def test_plain_integers(self): self.assertEqual(type(000), type(0)) - self.assertEqual(0xff, 255) + self.assertEqual(0xFF, 255) self.assertEqual(0o377, 255) self.assertEqual(2147483647, 0o17777777777) self.assertEqual(0b1001, 9) # "0x" is not a valid literal self.assertRaises(SyntaxError, eval, "0x") from sys import maxsize + if maxsize == 2147483647: - self.assertEqual(-2147483647-1, -0o20000000000) + self.assertEqual(-2147483647 - 1, -0o20000000000) # XXX -2147483648 self.assertTrue(0o37777777777 > 0) - self.assertTrue(0xffffffff > 0) + self.assertTrue(0xFFFFFFFF > 0) self.assertTrue(0b1111111111111111111111111111111 > 0) - for s in ('2147483648', '0o40000000000', '0x100000000', - '0b10000000000000000000000000000000'): + for s in ( + "2147483648", + "0o40000000000", + "0x100000000", + "0b10000000000000000000000000000000", + ): try: x = eval(s) except OverflowError: self.fail("OverflowError on huge integer literal %r" % s) elif maxsize == 9223372036854775807: - self.assertEqual(-9223372036854775807-1, -0o1000000000000000000000) + self.assertEqual(-9223372036854775807 - 1, -0o1000000000000000000000) self.assertTrue(0o1777777777777777777777 > 0) - self.assertTrue(0xffffffffffffffff > 0) - self.assertTrue(0b11111111111111111111111111111111111111111111111111111111111111 > 0) - for s in '9223372036854775808', '0o2000000000000000000000', \ - '0x10000000000000000', \ - '0b100000000000000000000000000000000000000000000000000000000000000': + self.assertTrue(0xFFFFFFFFFFFFFFFF > 0) + self.assertTrue( + 0b11111111111111111111111111111111111111111111111111111111111111 > 0 + ) + for s in ( + "9223372036854775808", + "0o2000000000000000000000", + "0x10000000000000000", + "0b100000000000000000000000000000000000000000000000000000000000000", + ): try: x = eval(s) except OverflowError: self.fail("OverflowError on huge integer literal %r" % s) else: - self.fail('Weird maxsize value %r' % maxsize) + self.fail("Weird maxsize value %r" % maxsize) def test_long_integers(self): x = 0 - x = 0xffffffffffffffff - x = 0Xffffffffffffffff + x = 0xFFFFFFFFFFFFFFFF + x = 0xFFFFFFFFFFFFFFFF + x = 0o77777777777777777 x = 0o77777777777777777 - x = 0O77777777777777777 x = 123456789012345678901234567890 x = 0b100000000000000000000000000000000000000000000000000000000000000000000 - x = 0B111111111111111111111111111111111111111111111111111111111111111111111 + x = 0b111111111111111111111111111111111111111111111111111111111111111111111 def test_floats(self): x = 3.14 - x = 314. + x = 314.0 x = 0.314 # XXX x = 000.314 - x = .314 + x = 0.314 + x = 3e14 x = 3e14 - x = 3E14 x = 3e-14 - x = 3e+14 - x = 3.e14 - x = .3e14 + x = 3e14 + x = 3.0e14 + x = 0.3e14 x = 3.1e4 def test_float_exponent_tokenization(self): # See issue 21642. with warnings.catch_warnings(): - warnings.simplefilter('ignore', SyntaxWarning) + warnings.simplefilter("ignore", SyntaxWarning) self.assertEqual(eval("1 if 1else 0"), 1) self.assertEqual(eval("1 if 0else 0"), 0) self.assertRaises(SyntaxError, eval, "0 if 1Else 0") def test_underscore_literals(self): for lit in VALID_UNDERSCORE_LITERALS: - self.assertEqual(eval(lit), eval(lit.replace('_', ''))) + self.assertEqual(eval(lit), eval(lit.replace("_", ""))) for lit in INVALID_UNDERSCORE_LITERALS: self.assertRaises(SyntaxError, eval, lit) # Sanity check: no literal begins with an underscore @@ -205,9 +214,11 @@ def test_bad_numerical_literals(self): check("0x1_", "invalid hexadecimal literal") check("0x", "invalid hexadecimal literal") check("1_", "invalid decimal literal") - check("012", - "leading zeros in decimal integer literals are not permitted; " - "use an 0o prefix for octal integers") + check( + "012", + "leading zeros in decimal integer literals are not permitted; " + "use an 0o prefix for octal integers", + ) check("1.2_", "invalid decimal literal") check("1e2_", "invalid decimal literal") check("1e+", "invalid decimal literal") @@ -217,13 +228,13 @@ def check(test, error=False): with self.subTest(expr=test): if error: with warnings.catch_warnings(record=True) as w: - with self.assertRaisesRegex(SyntaxError, - r'invalid \w+ literal'): + with self.assertRaisesRegex( + SyntaxError, r"invalid \w+ literal" + ): compile(test, "", "eval") - self.assertEqual(w, []) + self.assertEqual(w, []) else: - self.check_syntax_warning(test, - errtext=r'invalid \w+ literal') + self.check_syntax_warning(test, errtext=r"invalid \w+ literal") for num in "0xf", "0o7", "0b1", "9", "0", "1.", "1e3", "1j": compile(num, "", "eval") @@ -237,15 +248,16 @@ def check(test, error=False): check(f"{num}spam", error=True) # gh-88943: Invalid non-ASCII character following a numerical literal. - with self.assertRaisesRegex(SyntaxError, r"invalid character '⁄' \(U\+2044\)"): + with self.assertRaisesRegex( + SyntaxError, r"invalid character '⁄' \(U\+2044\)" + ): compile(f"{num}⁄7", "", "eval") - with self.assertWarnsRegex(SyntaxWarning, r'invalid \w+ literal'): + with self.assertWarnsRegex(SyntaxWarning, r"invalid \w+ literal"): compile(f"{num}is x", "", "eval") with warnings.catch_warnings(): - warnings.simplefilter('error', SyntaxWarning) - with self.assertRaisesRegex(SyntaxError, - r'invalid \w+ literal'): + warnings.simplefilter("error", SyntaxWarning) + with self.assertRaisesRegex(SyntaxError, r"invalid \w+ literal"): compile(f"{num}is x", "", "eval") check("[0x1ffor x in ()]") @@ -253,13 +265,19 @@ def check(test, error=False): check("[0xfor x in ()]") def test_string_literals(self): - x = ''; y = ""; self.assertTrue(len(x) == 0 and x == y) - x = '\''; y = "'"; self.assertTrue(len(x) == 1 and x == y and ord(x) == 39) - x = '"'; y = "\""; self.assertTrue(len(x) == 1 and x == y and ord(x) == 34) - x = "doesn't \"shrink\" does it" + x = "" + y = "" + self.assertTrue(len(x) == 0 and x == y) + x = "'" + y = "'" + self.assertTrue(len(x) == 1 and x == y and ord(x) == 39) + x = '"' + y = '"' + self.assertTrue(len(x) == 1 and x == y and ord(x) == 34) + x = 'doesn\'t "shrink" does it' y = 'doesn\'t "shrink" does it' self.assertTrue(len(x) == 24 and x == y) - x = "does \"shrink\" doesn't it" + x = 'does "shrink" doesn\'t it' y = 'does "shrink" doesn\'t it' self.assertTrue(len(x) == 24 and x == y) x = """ @@ -268,14 +286,14 @@ def test_string_literals(self): jumps over the 'lazy' dog. """ - y = '\nThe "quick"\nbrown fox\njumps over\nthe \'lazy\' dog.\n' + y = "\nThe \"quick\"\nbrown fox\njumps over\nthe 'lazy' dog.\n" self.assertEqual(x, y) - y = ''' + y = """ The "quick" brown fox jumps over the 'lazy' dog. -''' +""" self.assertEqual(x, y) y = "\n\ The \"quick\"\n\ @@ -284,12 +302,12 @@ def test_string_literals(self): the 'lazy' dog.\n\ " self.assertEqual(x, y) - y = '\n\ + y = "\n\ The \"quick\"\n\ brown fox\n\ jumps over\n\ -the \'lazy\' dog.\n\ -' +the 'lazy' dog.\n\ +" self.assertEqual(x, y) def test_ellipsis(self): @@ -304,21 +322,24 @@ def test_eof_error(self): compile(s, "", "exec") self.assertIn("was never closed", str(cm.exception)) -var_annot_global: int # a global annotated is necessary for test_var_annot + +var_annot_global: int # a global annotated is necessary for test_var_annot # custom namespace for testing __annotations__ + class CNS: def __init__(self): self._dct = {} + def __setitem__(self, item, value): self._dct[item.lower()] = value + def __getitem__(self, item): return self._dct[item] class GrammarTests(unittest.TestCase): - from test.support import check_syntax_error from test.support.warnings_helper import check_syntax_warning from test.support.warnings_helper import check_no_warnings @@ -334,28 +355,28 @@ class GrammarTests(unittest.TestCase): def test_eval_input(self): # testlist ENDMARKER - x = eval('1, 0 or 1') + x = eval("1, 0 or 1") def test_var_annot_basics(self): # all these should be allowed var1: int = 5 var2: [int, str] my_lst = [42] + def one(): return 1 + int.new_attr: int [list][0]: type - my_lst[one()-1]: int = 5 + my_lst[one() - 1]: int = 5 self.assertEqual(my_lst, [5]) def test_var_annot_syntax_errors(self): # parser pass check_syntax_error(self, "def f: int") check_syntax_error(self, "x: int: str") - check_syntax_error(self, "def f():\n" - " nonlocal x: int\n") - check_syntax_error(self, "def f():\n" - " global x: int\n") + check_syntax_error(self, "def f():\n" " nonlocal x: int\n") + check_syntax_error(self, "def f():\n" " global x: int\n") check_syntax_error(self, "x: int = y = 1") check_syntax_error(self, "z = w: int = 1") check_syntax_error(self, "x: int = y: int = 1") @@ -363,28 +384,19 @@ def test_var_annot_syntax_errors(self): check_syntax_error(self, "[x, 0]: int\n") check_syntax_error(self, "f(): int\n") check_syntax_error(self, "(x,): int") - check_syntax_error(self, "def f():\n" - " (x, y): int = (1, 2)\n") + check_syntax_error(self, "def f():\n" " (x, y): int = (1, 2)\n") # symtable pass - check_syntax_error(self, "def f():\n" - " x: int\n" - " global x\n") - check_syntax_error(self, "def f():\n" - " global x\n" - " x: int\n") - check_syntax_error(self, "def f():\n" - " x: int\n" - " nonlocal x\n") - check_syntax_error(self, "def f():\n" - " nonlocal x\n" - " x: int\n") + check_syntax_error(self, "def f():\n" " x: int\n" " global x\n") + check_syntax_error(self, "def f():\n" " global x\n" " x: int\n") + check_syntax_error(self, "def f():\n" " x: int\n" " nonlocal x\n") + check_syntax_error(self, "def f():\n" " nonlocal x\n" " x: int\n") def test_var_annot_basic_semantics(self): # execution order with self.assertRaises(ZeroDivisionError): - no_name[does_not_exist]: no_name_again = 1/0 + no_name[does_not_exist]: no_name_again = 1 / 0 with self.assertRaises(NameError): - no_name[does_not_exist]: 1/0 = 0 + no_name[does_not_exist]: 1 / 0 = 0 global var_annot_global # function semantics @@ -392,18 +404,25 @@ def f(): st: str = "Hello" a.b: int = (1, 2) return st + self.assertEqual(f.__annotations__, {}) + def f_OK(): - x: 1/0 + x: 1 / 0 + f_OK() + def fbad(): x: int print(x) + with self.assertRaises(UnboundLocalError): fbad() + def f2bad(): (no_such_global): int print(no_such_global) + try: f2bad() except Exception as e: @@ -414,13 +433,18 @@ class C: __foo: int s: str = "attr" z = 2 + def __init__(self, x): self.x: int = x - self.assertEqual(C.__annotations__, {'_C__foo': int, 's': str}) + + self.assertEqual(C.__annotations__, {"_C__foo": int, "s": str}) with self.assertRaises(NameError): + class CBad: no_such_name_defined.attr: int = 0 + with self.assertRaises(NameError): + class Cbad2(C): x: int x.y: list = [] @@ -429,45 +453,55 @@ def test_annotations_inheritance(self): # Check that annotations are not inherited by derived classes class A: attr: int + class B(A): pass + class C(A): attr: str + class D: attr2: int + class E(A, D): pass + class F(C, A): pass + self.assertEqual(A.__annotations__, {"attr": int}) self.assertEqual(B.__annotations__, {}) - self.assertEqual(C.__annotations__, {"attr" : str}) - self.assertEqual(D.__annotations__, {"attr2" : int}) + self.assertEqual(C.__annotations__, {"attr": str}) + self.assertEqual(D.__annotations__, {"attr2": int}) self.assertEqual(E.__annotations__, {}) self.assertEqual(F.__annotations__, {}) - def test_var_annot_metaclass_semantics(self): class CMeta(type): @classmethod def __prepare__(metacls, name, bases, **kwds): - return {'__annotations__': CNS()} + return {"__annotations__": CNS()} + class CC(metaclass=CMeta): - XX: 'ANNOT' - self.assertEqual(CC.__annotations__['xx'], 'ANNOT') + XX: "ANNOT" + + self.assertEqual(CC.__annotations__["xx"], "ANNOT") def test_var_annot_module_semantics(self): self.assertEqual(test.__annotations__, {}) - self.assertEqual(ann_module.__annotations__, - {1: 2, 'x': int, 'y': str, 'f': typing.Tuple[int, int], 'u': int | float}) - self.assertEqual(ann_module.M.__annotations__, - {'123': 123, 'o': type}) + self.assertEqual( + ann_module.__annotations__, + {1: 2, "x": int, "y": str, "f": typing.Tuple[int, int], "u": int | float}, + ) + self.assertEqual(ann_module.M.__annotations__, {"123": 123, "o": type}) self.assertEqual(ann_module2.__annotations__, {}) def test_var_annot_in_module(self): # check that functions fail the same way when executed # outside of module where they were defined - ann_module3 = import_helper.import_fresh_module("test.typinganndata.ann_module3") + ann_module3 = import_helper.import_fresh_module( + "test.typinganndata.ann_module3" + ) with self.assertRaises(NameError): ann_module3.f_bad_ann() with self.assertRaises(NameError): @@ -476,64 +510,70 @@ def test_var_annot_in_module(self): ann_module3.D_bad_ann(5) def test_var_annot_simple_exec(self): - gns = {}; lns= {} - exec("'docstring'\n" - "__annotations__[1] = 2\n" - "x: int = 5\n", gns, lns) - self.assertEqual(lns["__annotations__"], {1: 2, 'x': int}) + gns = {} + lns = {} + exec("'docstring'\n" "__annotations__[1] = 2\n" "x: int = 5\n", gns, lns) + self.assertEqual(lns["__annotations__"], {1: 2, "x": int}) with self.assertRaises(KeyError): - gns['__annotations__'] + gns["__annotations__"] def test_var_annot_custom_maps(self): # tests with custom locals() and __annotations__ - ns = {'__annotations__': CNS()} + ns = {"__annotations__": CNS()} exec('X: int; Z: str = "Z"; (w): complex = 1j', ns) - self.assertEqual(ns['__annotations__']['x'], int) - self.assertEqual(ns['__annotations__']['z'], str) + self.assertEqual(ns["__annotations__"]["x"], int) + self.assertEqual(ns["__annotations__"]["z"], str) with self.assertRaises(KeyError): - ns['__annotations__']['w'] + ns["__annotations__"]["w"] nonloc_ns = {} + class CNS2: def __init__(self): self._dct = {} + def __setitem__(self, item, value): nonlocal nonloc_ns self._dct[item] = value nonloc_ns[item] = value + def __getitem__(self, item): return self._dct[item] - exec('x: int = 1', {}, CNS2()) - self.assertEqual(nonloc_ns['__annotations__']['x'], int) + + exec("x: int = 1", {}, CNS2()) + self.assertEqual(nonloc_ns["__annotations__"]["x"], int) def test_var_annot_refleak(self): # complex case: custom locals plus custom __annotations__ # this was causing refleak cns = CNS() - nonloc_ns = {'__annotations__': cns} + nonloc_ns = {"__annotations__": cns} + class CNS2: def __init__(self): - self._dct = {'__annotations__': cns} + self._dct = {"__annotations__": cns} + def __setitem__(self, item, value): nonlocal nonloc_ns self._dct[item] = value nonloc_ns[item] = value + def __getitem__(self, item): return self._dct[item] - exec('X: str', {}, CNS2()) - self.assertEqual(nonloc_ns['__annotations__']['x'], str) + + exec("X: str", {}, CNS2()) + self.assertEqual(nonloc_ns["__annotations__"]["x"], str) def test_var_annot_rhs(self): ns = {} - exec('x: tuple = 1, 2', ns) - self.assertEqual(ns['x'], (1, 2)) - stmt = ('def f():\n' - ' x: int = yield') + exec("x: tuple = 1, 2", ns) + self.assertEqual(ns["x"], (1, 2)) + stmt = "def f():\n" " x: int = yield" exec(stmt, ns) - self.assertEqual(list(ns['f']()), [None]) + self.assertEqual(list(ns["f"]()), [None]) - ns = {"a": 1, 'b': (2, 3, 4), "c":5, "Tuple": typing.Tuple} - exec('x: Tuple[int, ...] = a,*b,c', ns) - self.assertEqual(ns['x'], (1, 2, 3, 4, 5)) + ns = {"a": 1, "b": (2, 3, 4), "c": 5, "Tuple": typing.Tuple} + exec("x: Tuple[int, ...] = a,*b,c", ns) + self.assertEqual(ns["x"], (1, 2, 3, 4, 5)) def test_funcdef(self): ### [decorators] 'def' NAME parameters ['->' test] ':' suite @@ -548,135 +588,210 @@ def test_funcdef(self): ### ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef] | '**' vfpdef) ### | vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) ### vfpdef: NAME - def f1(): pass + def f1(): + pass + f1() f1(*()) f1(*(), **{}) - def f2(one_argument): pass - def f3(two, arguments): pass - self.assertEqual(f2.__code__.co_varnames, ('one_argument',)) - self.assertEqual(f3.__code__.co_varnames, ('two', 'arguments')) - def a1(one_arg,): pass - def a2(two, args,): pass - def v0(*rest): pass - def v1(a, *rest): pass - def v2(a, b, *rest): pass + + def f2(one_argument): + pass + + def f3(two, arguments): + pass + + self.assertEqual(f2.__code__.co_varnames, ("one_argument",)) + self.assertEqual(f3.__code__.co_varnames, ("two", "arguments")) + + def a1( + one_arg, + ): + pass + + def a2( + two, + args, + ): + pass + + def v0(*rest): + pass + + def v1(a, *rest): + pass + + def v2(a, b, *rest): + pass f1() f2(1) - f2(1,) + f2( + 1, + ) f3(1, 2) - f3(1, 2,) + f3( + 1, + 2, + ) v0() v0(1) - v0(1,) - v0(1,2) - v0(1,2,3,4,5,6,7,8,9,0) + v0( + 1, + ) + v0(1, 2) + v0(1, 2, 3, 4, 5, 6, 7, 8, 9, 0) v1(1) - v1(1,) - v1(1,2) - v1(1,2,3) - v1(1,2,3,4,5,6,7,8,9,0) - v2(1,2) - v2(1,2,3) - v2(1,2,3,4) - v2(1,2,3,4,5,6,7,8,9,0) - - def d01(a=1): pass + v1( + 1, + ) + v1(1, 2) + v1(1, 2, 3) + v1(1, 2, 3, 4, 5, 6, 7, 8, 9, 0) + v2(1, 2) + v2(1, 2, 3) + v2(1, 2, 3, 4) + v2(1, 2, 3, 4, 5, 6, 7, 8, 9, 0) + + def d01(a=1): + pass + d01() d01(1) d01(*(1,)) d01(*[] or [2]) d01(*() or (), *{} and (), **() or {}) - d01(**{'a':2}) - d01(**{'a':2} or {}) - def d11(a, b=1): pass + d01(**{"a": 2}) + d01(**{"a": 2} or {}) + + def d11(a, b=1): + pass + d11(1) d11(1, 2) - d11(1, **{'b':2}) - def d21(a, b, c=1): pass + d11(1, **{"b": 2}) + + def d21(a, b, c=1): + pass + d21(1, 2) d21(1, 2, 3) d21(*(1, 2, 3)) d21(1, *(2, 3)) d21(1, 2, *(3,)) - d21(1, 2, **{'c':3}) - def d02(a=1, b=2): pass + d21(1, 2, **{"c": 3}) + + def d02(a=1, b=2): + pass + d02() d02(1) d02(1, 2) d02(*(1, 2)) d02(1, *(2,)) - d02(1, **{'b':2}) - d02(**{'a': 1, 'b': 2}) - def d12(a, b=1, c=2): pass + d02(1, **{"b": 2}) + d02(**{"a": 1, "b": 2}) + + def d12(a, b=1, c=2): + pass + d12(1) d12(1, 2) d12(1, 2, 3) - def d22(a, b, c=1, d=2): pass + + def d22(a, b, c=1, d=2): + pass + d22(1, 2) d22(1, 2, 3) d22(1, 2, 3, 4) - def d01v(a=1, *rest): pass + + def d01v(a=1, *rest): + pass + d01v() d01v(1) d01v(1, 2) d01v(*(1, 2, 3, 4)) d01v(*(1,)) - d01v(**{'a':2}) - def d11v(a, b=1, *rest): pass + d01v(**{"a": 2}) + + def d11v(a, b=1, *rest): + pass + d11v(1) d11v(1, 2) d11v(1, 2, 3) - def d21v(a, b, c=1, *rest): pass + + def d21v(a, b, c=1, *rest): + pass + d21v(1, 2) d21v(1, 2, 3) d21v(1, 2, 3, 4) d21v(*(1, 2, 3, 4)) - d21v(1, 2, **{'c': 3}) - def d02v(a=1, b=2, *rest): pass + d21v(1, 2, **{"c": 3}) + + def d02v(a=1, b=2, *rest): + pass + d02v() d02v(1) d02v(1, 2) d02v(1, 2, 3) d02v(1, *(2, 3, 4)) - d02v(**{'a': 1, 'b': 2}) - def d12v(a, b=1, c=2, *rest): pass + d02v(**{"a": 1, "b": 2}) + + def d12v(a, b=1, c=2, *rest): + pass + d12v(1) d12v(1, 2) d12v(1, 2, 3) d12v(1, 2, 3, 4) d12v(*(1, 2, 3, 4)) d12v(1, 2, *(3, 4, 5)) - d12v(1, *(2,), **{'c': 3}) - def d22v(a, b, c=1, d=2, *rest): pass + d12v(1, *(2,), **{"c": 3}) + + def d22v(a, b, c=1, d=2, *rest): + pass + d22v(1, 2) d22v(1, 2, 3) d22v(1, 2, 3, 4) d22v(1, 2, 3, 4, 5) d22v(*(1, 2, 3, 4)) d22v(1, 2, *(3, 4, 5)) - d22v(1, *(2, 3), **{'d': 4}) + d22v(1, *(2, 3), **{"d": 4}) # keyword argument type tests with warnings.catch_warnings(): - warnings.simplefilter('ignore', BytesWarning) + warnings.simplefilter("ignore", BytesWarning) try: - str('x', **{b'foo':1 }) + str("x", **{b"foo": 1}) except TypeError: pass else: - self.fail('Bytes should not work as keyword argument names') + self.fail("Bytes should not work as keyword argument names") + # keyword only argument tests - def pos0key1(*, key): return key + def pos0key1(*, key): + return key + pos0key1(key=100) - def pos2key2(p1, p2, *, k1, k2=100): return p1,p2,k1,k2 + + def pos2key2(p1, p2, *, k1, k2=100): + return p1, p2, k1, k2 + pos2key2(1, 2, k1=100) pos2key2(1, 2, k1=100, k2=200) pos2key2(1, 2, k2=100, k1=200) - def pos2key2dict(p1, p2, *, k1=100, k2, **kwarg): return p1,p2,k1,k2,kwarg - pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200) - pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100) + + def pos2key2dict(p1, p2, *, k1=100, k2, **kwarg): + return p1, p2, k1, k2, kwarg + + pos2key2dict(1, 2, k2=100, tokwarg1=100, tokwarg2=200) + pos2key2dict(1, 2, tokwarg1=100, tokwarg2=200, k2=100) self.assertRaises(SyntaxError, eval, "def f(*): pass") self.assertRaises(SyntaxError, eval, "def f(*,): pass") @@ -685,121 +800,295 @@ def pos2key2dict(p1, p2, *, k1=100, k2, **kwarg): return p1,p2,k1,k2,kwarg # keyword arguments after *arglist def f(*args, **kwargs): return args, kwargs - self.assertEqual(f(1, x=2, *[3, 4], y=5), ((1, 3, 4), - {'x':2, 'y':5})) - self.assertEqual(f(1, *(2,3), 4), ((1, 2, 3, 4), {})) + + self.assertEqual(f(1, x=2, *[3, 4], y=5), ((1, 3, 4), {"x": 2, "y": 5})) + self.assertEqual(f(1, *(2, 3), 4), ((1, 2, 3, 4), {})) self.assertRaises(SyntaxError, eval, "f(1, x=2, *(3,4), x=5)") - self.assertEqual(f(**{'eggs':'scrambled', 'spam':'fried'}), - ((), {'eggs':'scrambled', 'spam':'fried'})) - self.assertEqual(f(spam='fried', **{'eggs':'scrambled'}), - ((), {'eggs':'scrambled', 'spam':'fried'})) + self.assertEqual( + f(**{"eggs": "scrambled", "spam": "fried"}), + ((), {"eggs": "scrambled", "spam": "fried"}), + ) + self.assertEqual( + f(spam="fried", **{"eggs": "scrambled"}), + ((), {"eggs": "scrambled", "spam": "fried"}), + ) # Check ast errors in *args and *kwargs check_syntax_error(self, "f(*g(1=2))") check_syntax_error(self, "f(**g(1=2))") # argument annotation tests - def f(x) -> list: pass - self.assertEqual(f.__annotations__, {'return': list}) - def f(x: int): pass - self.assertEqual(f.__annotations__, {'x': int}) - def f(x: int, /): pass - self.assertEqual(f.__annotations__, {'x': int}) - def f(x: int = 34, /): pass - self.assertEqual(f.__annotations__, {'x': int}) - def f(*x: str): pass - self.assertEqual(f.__annotations__, {'x': str}) - def f(**x: float): pass - self.assertEqual(f.__annotations__, {'x': float}) - def f(x, y: 1+2): pass - self.assertEqual(f.__annotations__, {'y': 3}) - def f(x, y: 1+2, /): pass - self.assertEqual(f.__annotations__, {'y': 3}) - def f(a, b: 1, c: 2, d): pass - self.assertEqual(f.__annotations__, {'b': 1, 'c': 2}) - def f(a, b: 1, /, c: 2, d): pass - self.assertEqual(f.__annotations__, {'b': 1, 'c': 2}) - def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6): pass - self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6}) - def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6, h: 7, i=8, j: 9 = 10, - **k: 11) -> 12: pass - self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'g': 6, 'h': 7, 'j': 9, - 'k': 11, 'return': 12}) - def f(a, b: 1, c: 2, d, e: 3 = 4, f: int = 5, /, *g: 6, h: 7, i=8, j: 9 = 10, - **k: 11) -> 12: pass - self.assertEqual(f.__annotations__, - {'b': 1, 'c': 2, 'e': 3, 'f': int, 'g': 6, 'h': 7, 'j': 9, - 'k': 11, 'return': 12}) + def f(x) -> list: + pass + + self.assertEqual(f.__annotations__, {"return": list}) + + def f(x: int): + pass + + self.assertEqual(f.__annotations__, {"x": int}) + + def f(x: int, /): + pass + + self.assertEqual(f.__annotations__, {"x": int}) + + def f(x: int = 34, /): + pass + + self.assertEqual(f.__annotations__, {"x": int}) + + def f(*x: str): + pass + + self.assertEqual(f.__annotations__, {"x": str}) + + def f(**x: float): + pass + + self.assertEqual(f.__annotations__, {"x": float}) + + def f(x, y: 1 + 2): + pass + + self.assertEqual(f.__annotations__, {"y": 3}) + + def f(x, y: 1 + 2, /): + pass + + self.assertEqual(f.__annotations__, {"y": 3}) + + def f(a, b: 1, c: 2, d): + pass + + self.assertEqual(f.__annotations__, {"b": 1, "c": 2}) + + def f(a, b: 1, /, c: 2, d): + pass + + self.assertEqual(f.__annotations__, {"b": 1, "c": 2}) + + def f(a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6): + pass + + self.assertEqual(f.__annotations__, {"b": 1, "c": 2, "e": 3, "g": 6}) + + def f( + a, b: 1, c: 2, d, e: 3 = 4, f=5, *g: 6, h: 7, i=8, j: 9 = 10, **k: 11 + ) -> 12: + pass + + self.assertEqual( + f.__annotations__, + {"b": 1, "c": 2, "e": 3, "g": 6, "h": 7, "j": 9, "k": 11, "return": 12}, + ) + + def f( + a, + b: 1, + c: 2, + d, + e: 3 = 4, + f: int = 5, + /, + *g: 6, + h: 7, + i=8, + j: 9 = 10, + **k: 11, + ) -> 12: + pass + + self.assertEqual( + f.__annotations__, + { + "b": 1, + "c": 2, + "e": 3, + "f": int, + "g": 6, + "h": 7, + "j": 9, + "k": 11, + "return": 12, + }, + ) + # Check for issue #20625 -- annotations mangling class Spam: def f(self, *, __kw: 1): pass - class Ham(Spam): pass - self.assertEqual(Spam.f.__annotations__, {'_Spam__kw': 1}) - self.assertEqual(Ham.f.__annotations__, {'_Spam__kw': 1}) + + class Ham(Spam): + pass + + self.assertEqual(Spam.f.__annotations__, {"_Spam__kw": 1}) + self.assertEqual(Ham.f.__annotations__, {"_Spam__kw": 1}) + # Check for SF Bug #1697248 - mixing decorators and a return annotation - def null(x): return x + def null(x): + return x + @null - def f(x) -> list: pass - self.assertEqual(f.__annotations__, {'return': list}) + def f(x) -> list: + pass + + self.assertEqual(f.__annotations__, {"return": list}) # Test expressions as decorators (PEP 614): @False or null - def f(x): pass + def f(x): + pass + @d := null - def f(x): pass + def f(x): + pass + @lambda f: null(f) - def f(x): pass + def f(x): + pass + @[..., null, ...][1] - def f(x): pass + def f(x): + pass + @null(null)(null) - def f(x): pass + def f(x): + pass + @[null][0].__call__.__call__ - def f(x): pass + def f(x): + pass # test closures with a variety of opargs closure = 1 - def f(): return closure - def f(x=1): return closure - def f(*, k=1): return closure - def f() -> int: return closure + + def f(): + return closure + + def f(x=1): + return closure + + def f(*, k=1): + return closure + + def f() -> int: + return closure # Check trailing commas are permitted in funcdef argument list - def f(a,): pass - def f(*args,): pass - def f(**kwds,): pass - def f(a, *args,): pass - def f(a, **kwds,): pass - def f(*args, b,): pass - def f(*, b,): pass - def f(*args, **kwds,): pass - def f(a, *args, b,): pass - def f(a, *, b,): pass - def f(a, *args, **kwds,): pass - def f(*args, b, **kwds,): pass - def f(*, b, **kwds,): pass - def f(a, *args, b, **kwds,): pass - def f(a, *, b, **kwds,): pass + def f( + a, + ): + pass + + def f( + *args, + ): + pass + + def f( + **kwds, + ): + pass + + def f( + a, + *args, + ): + pass + + def f( + a, + **kwds, + ): + pass + + def f( + *args, + b, + ): + pass + + def f( + *, + b, + ): + pass + + def f( + *args, + **kwds, + ): + pass + + def f( + a, + *args, + b, + ): + pass + + def f( + a, + *, + b, + ): + pass + + def f( + a, + *args, + **kwds, + ): + pass + + def f( + *args, + b, + **kwds, + ): + pass + + def f( + *, + b, + **kwds, + ): + pass + + def f( + a, + *args, + b, + **kwds, + ): + pass + + def f( + a, + *, + b, + **kwds, + ): + pass def test_lambdef(self): ### lambdef: 'lambda' [varargslist] ':' test - l1 = lambda : 0 + l1 = lambda: 0 self.assertEqual(l1(), 0) - l2 = lambda : a[d] # XXX just testing the expression - l3 = lambda : [2 < x for x in [-1, 3, 0]] + l2 = lambda: a[d] # XXX just testing the expression + l3 = lambda: [2 < x for x in [-1, 3, 0]] self.assertEqual(l3(), [0, 1, 0]) - l4 = lambda x = lambda y = lambda z=1 : z : y() : x() + l4 = lambda x=lambda y=lambda z=1: z: y(): x() self.assertEqual(l4(), 1) l5 = lambda x, y, z=2: x + y + z self.assertEqual(l5(1, 2), 5) self.assertEqual(l5(1, 2, 3), 6) check_syntax_error(self, "lambda x: x = 2") check_syntax_error(self, "lambda (None,): None") - l6 = lambda x, y, *, k=20: x+y+k - self.assertEqual(l6(1,2), 1+2+20) - self.assertEqual(l6(1,2,k=10), 1+2+10) + l6 = lambda x, y, *, k=20: x + y + k + self.assertEqual(l6(1, 2), 1 + 2 + 20) + self.assertEqual(l6(1, 2, k=10), 1 + 2 + 10) # check that trailing commas are permitted l10 = lambda a,: 0 @@ -818,16 +1107,21 @@ def test_lambdef(self): l23 = lambda a, *args, b, **kwds,: 0 l24 = lambda a, *, b, **kwds,: 0 - ### stmt: simple_stmt | compound_stmt # Tested below def test_simple_stmt(self): ### simple_stmt: small_stmt (';' small_stmt)* [';'] - x = 1; pass; del x + x = 1 + pass + del x + def foo(): # verify statements that end with semi-colons - x = 1; pass; del x; + x = 1 + pass + del x + foo() ### small_stmt: expr_stmt | pass_stmt | del_stmt | flow_stmt | import_stmt | global_stmt | access_stmt @@ -873,7 +1167,7 @@ def test_former_statements_refer_to_builtins(self): def test_del_stmt(self): # 'del' exprlist - abc = [1,2,3] + abc = [1, 2, 3] x, y, z = abc xyz = x, y, z @@ -882,8 +1176,8 @@ def test_del_stmt(self): x, y, z = "xyz" del x - del y, - del (z) + del y + del z del () a, b, c, d, e, f, g = "abcdefg" @@ -906,12 +1200,15 @@ def test_pass_stmt(self): def test_break_stmt(self): # 'break' - while 1: break + while 1: + break def test_continue_stmt(self): # 'continue' i = 1 - while i: i = 0; continue + while i: + i = 0 + continue msg = "" while not msg: @@ -944,7 +1241,7 @@ def test_break_continue_loop(self): # *must* written as a function, and the tracking vars *must* be function # arguments with default values. Otherwise, the test will loop and loop. - def test_inner(extra_burning_oil = 1, count=0): + def test_inner(extra_burning_oil=1, count=0): big_hippo = 2 while big_hippo: count += 1 @@ -958,12 +1255,17 @@ def test_inner(extra_burning_oil = 1, count=0): raise if count > 2 or big_hippo != 1: self.fail("continue then break in try/except in loop broken!") + test_inner() def test_return(self): # 'return' [testlist_star_expr] - def g1(): return - def g2(): return 1 + def g1(): + return + + def g2(): + return 1 + def g3(): z = [2, 3] return 1, *z @@ -997,7 +1299,7 @@ def test_break_in_finally(self): while count < 2: count += 1 try: - 1/0 + 1 / 0 finally: break self.assertEqual(count, 1) @@ -1021,7 +1323,7 @@ def test_break_in_finally(self): for count in [0, 1]: self.assertEqual(count, 0) try: - 1/0 + 1 / 0 finally: break self.assertEqual(count, 0) @@ -1050,7 +1352,7 @@ def test_continue_in_finally(self): while count < 2: count += 1 try: - 1/0 + 1 / 0 finally: continue break @@ -1073,7 +1375,7 @@ def test_continue_in_finally(self): for count in [0, 1]: try: - 1/0 + 1 / 0 finally: continue break @@ -1085,6 +1387,7 @@ def g1(): pass finally: return 1 + self.assertEqual(g1(), 1) def g2(): @@ -1092,13 +1395,15 @@ def g2(): return 2 finally: return 3 + self.assertEqual(g2(), 3) def g3(): try: - 1/0 + 1 / 0 finally: return 4 + self.assertEqual(g3(), 4) def test_break_in_finally_after_return(self): @@ -1113,9 +1418,10 @@ def g1(x): finally: if x: break - return 'end', count, count2 + return "end", count, count2 + self.assertEqual(g1(False), 10) - self.assertEqual(g1(True), ('end', 1, 10)) + self.assertEqual(g1(True), ("end", 1, 10)) def g2(x): for count in [0, 1]: @@ -1125,9 +1431,10 @@ def g2(x): finally: if x: break - return 'end', count, count2 + return "end", count, count2 + self.assertEqual(g2(False), 10) - self.assertEqual(g2(True), ('end', 1, 10)) + self.assertEqual(g2(True), ("end", 1, 10)) def test_continue_in_finally_after_return(self): # See issue #37830 @@ -1140,9 +1447,10 @@ def g1(x): finally: if x: continue - return 'end', count + return "end", count + self.assertEqual(g1(False), 1) - self.assertEqual(g1(True), ('end', 100)) + self.assertEqual(g1(True), ("end", 100)) def g2(x): for count in [0, 1]: @@ -1151,35 +1459,65 @@ def g2(x): finally: if x: continue - return 'end', count + return "end", count + self.assertEqual(g2(False), 0) - self.assertEqual(g2(True), ('end', 1)) + self.assertEqual(g2(True), ("end", 1)) def test_yield(self): # Allowed as standalone statement - def g(): yield 1 - def g(): yield from () + def g(): + yield 1 + + def g(): + yield from () + # Allowed as RHS of assignment - def g(): x = yield 1 - def g(): x = yield from () + def g(): + x = yield 1 + + def g(): + x = yield from () + # Ordinary yield accepts implicit tuples - def g(): yield 1, 1 - def g(): x = yield 1, 1 + def g(): + yield 1, 1 + + def g(): + x = yield 1, 1 + # 'yield from' does not check_syntax_error(self, "def g(): yield from (), 1") check_syntax_error(self, "def g(): x = yield from (), 1") + # Requires parentheses as subexpression - def g(): 1, (yield 1) - def g(): 1, (yield from ()) + def g(): + 1, (yield 1) + + def g(): + 1, (yield from ()) + check_syntax_error(self, "def g(): 1, yield 1") check_syntax_error(self, "def g(): 1, yield from ()") + # Requires parentheses as call argument - def g(): f((yield 1)) - def g(): f((yield 1), 1) - def g(): f((yield from ())) - def g(): f((yield from ()), 1) + def g(): + f((yield 1)) + + def g(): + f((yield 1), 1) + + def g(): + f((yield from ())) + + def g(): + f((yield from ()), 1) + # Do not require parenthesis for tuple unpacking - def g(): rest = 4, 5, 6; yield 1, 2, 3, *rest + def g(): + rest = 4, 5, 6 + yield 1, 2, 3, *rest + self.assertEqual(list(g()), [(1, 2, 3, 4, 5, 6)]) check_syntax_error(self, "def g(): f(yield 1)") check_syntax_error(self, "def g(): f(yield 1, 1)") @@ -1196,50 +1534,64 @@ def g(): rest = 4, 5, 6; yield 1, 2, 3, *rest def test_yield_in_comprehensions(self): # Check yield in comprehensions - def g(): [x for x in [(yield 1)]] - def g(): [x for x in [(yield from ())]] + def g(): + [x for x in [(yield 1)]] + + def g(): + [x for x in [(yield from ())]] check = self.check_syntax_error - check("def g(): [(yield x) for x in ()]", - "'yield' inside list comprehension") - check("def g(): [x for x in () if not (yield x)]", - "'yield' inside list comprehension") - check("def g(): [y for x in () for y in [(yield x)]]", - "'yield' inside list comprehension") - check("def g(): {(yield x) for x in ()}", - "'yield' inside set comprehension") - check("def g(): {(yield x): x for x in ()}", - "'yield' inside dict comprehension") - check("def g(): {x: (yield x) for x in ()}", - "'yield' inside dict comprehension") - check("def g(): ((yield x) for x in ())", - "'yield' inside generator expression") - check("def g(): [(yield from x) for x in ()]", - "'yield' inside list comprehension") - check("class C: [(yield x) for x in ()]", - "'yield' inside list comprehension") - check("[(yield x) for x in ()]", - "'yield' inside list comprehension") + check("def g(): [(yield x) for x in ()]", "'yield' inside list comprehension") + check( + "def g(): [x for x in () if not (yield x)]", + "'yield' inside list comprehension", + ) + check( + "def g(): [y for x in () for y in [(yield x)]]", + "'yield' inside list comprehension", + ) + check("def g(): {(yield x) for x in ()}", "'yield' inside set comprehension") + check( + "def g(): {(yield x): x for x in ()}", "'yield' inside dict comprehension" + ) + check( + "def g(): {x: (yield x) for x in ()}", "'yield' inside dict comprehension" + ) + check("def g(): ((yield x) for x in ())", "'yield' inside generator expression") + check( + "def g(): [(yield from x) for x in ()]", "'yield' inside list comprehension" + ) + check("class C: [(yield x) for x in ()]", "'yield' inside list comprehension") + check("[(yield x) for x in ()]", "'yield' inside list comprehension") def test_raise(self): # 'raise' test [',' test] - try: raise RuntimeError('just testing') - except RuntimeError: pass - try: raise KeyboardInterrupt - except KeyboardInterrupt: pass + try: + raise RuntimeError("just testing") + except RuntimeError: + pass + try: + raise KeyboardInterrupt + except KeyboardInterrupt: + pass def test_import(self): # 'import' dotted_as_names import sys import time, sys + # 'from' dotted_name 'import' ('*' | '(' import_as_names ')' | import_as_names) from time import time - from time import (time) + from time import time + # not testable inside a function, but already done at top of the module # from sys import * from sys import path, argv - from sys import (path, argv) - from sys import (path, argv,) + from sys import path, argv + from sys import ( + path, + argv, + ) def test_global(self): # 'global' NAME (',' NAME)* @@ -1251,6 +1603,7 @@ def test_nonlocal(self): # 'nonlocal' NAME (',' NAME)* x = 0 y = 0 + def f(): nonlocal x nonlocal x, y @@ -1259,8 +1612,8 @@ def test_assert(self): # assertTruestmt: 'assert' test [',' test] assert 1 assert 1, 1 - assert lambda x:x - assert 1, lambda x:x+1 + assert lambda x: x + assert 1, lambda x: x + 1 try: assert True @@ -1268,10 +1621,9 @@ def test_assert(self): self.fail("'assert True' should not have raised an AssertionError") try: - assert True, 'this should always pass' + assert True, "this should always pass" except AssertionError as e: - self.fail("'assert True, msg' should not have " - "raised an AssertionError") + self.fail("'assert True, msg' should not have " "raised an AssertionError") # these tests fail if python is run with -O, so check __debug__ @unittest.skipUnless(__debug__, "Won't work if __debug__ is False") @@ -1293,56 +1645,65 @@ def test_assert_failures(self): def test_assert_syntax_warnings(self): # Ensure that we warn users if they provide a non-zero length tuple as # the assertion test. - self.check_syntax_warning('assert(x, "msg")', - 'assertion is always true') - self.check_syntax_warning('assert(False, "msg")', - 'assertion is always true') - self.check_syntax_warning('assert(False,)', - 'assertion is always true') + self.check_syntax_warning('assert(x, "msg")', "assertion is always true") + self.check_syntax_warning('assert(False, "msg")', "assertion is always true") + self.check_syntax_warning("assert(False,)", "assertion is always true") with self.check_no_warnings(category=SyntaxWarning): - compile('assert x, "msg"', '', 'exec') - compile('assert False, "msg"', '', 'exec') + compile('assert x, "msg"', "", "exec") + compile('assert False, "msg"', "", "exec") def test_assert_warning_promotes_to_syntax_error(self): # If SyntaxWarning is configured to be an error, it actually raises a # SyntaxError. # https://bugs.python.org/issue35029 with warnings.catch_warnings(): - warnings.simplefilter('error', SyntaxWarning) + warnings.simplefilter("error", SyntaxWarning) try: - compile('assert x, "msg" ', '', 'exec') + compile('assert x, "msg" ', "", "exec") except SyntaxError: - self.fail('SyntaxError incorrectly raised for \'assert x, "msg"\'') + self.fail("SyntaxError incorrectly raised for 'assert x, \"msg\"'") with self.assertRaises(SyntaxError): - compile('assert(x, "msg")', '', 'exec') + compile('assert(x, "msg")', "", "exec") with self.assertRaises(SyntaxError): - compile('assert(False, "msg")', '', 'exec') + compile('assert(False, "msg")', "", "exec") with self.assertRaises(SyntaxError): - compile('assert(False,)', '', 'exec') - + compile("assert(False,)", "", "exec") ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef # Tested below def test_if(self): # 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] - if 1: pass - if 1: pass - else: pass - if 0: pass - elif 0: pass - if 0: pass - elif 0: pass - elif 0: pass - elif 0: pass - else: pass + if 1: + pass + if 1: + pass + else: + pass + if 0: + pass + elif 0: + pass + if 0: + pass + elif 0: + pass + elif 0: + pass + elif 0: + pass + else: + pass def test_while(self): # 'while' test ':' suite ['else' ':' suite] - while 0: pass - while 0: pass - else: pass + while 0: + pass + while 0: + pass + else: + pass # Issue1920: "while 0" is optimized away, # ensure that the "else" clause is still present. @@ -1355,28 +1716,38 @@ def test_while(self): def test_for(self): # 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] - for i in 1, 2, 3: pass - for i, j, k in (): pass - else: pass + for i in 1, 2, 3: + pass + for i, j, k in (): + pass + else: + pass + class Squares: def __init__(self, max): self.max = max self.sofar = [] - def __len__(self): return len(self.sofar) + + def __len__(self): + return len(self.sofar) + def __getitem__(self, i): - if not 0 <= i < self.max: raise IndexError + if not 0 <= i < self.max: + raise IndexError n = len(self.sofar) while n <= i: - self.sofar.append(n*n) - n = n+1 + self.sofar.append(n * n) + n = n + 1 return self.sofar[i] + n = 0 - for x in Squares(10): n = n+x + for x in Squares(10): + n = n + x if n != 285: - self.fail('for over growing sequence') + self.fail("for over growing sequence") result = [] - for x, in [(1,), (2,), (3,)]: + for (x,) in [(1,), (2,), (3,)]: result.append(x) self.assertEqual(result, [1, 2, 3]) @@ -1391,22 +1762,33 @@ def test_try(self): ### | 'try' ':' suite 'finally' ':' suite ### except_clause: 'except' [expr ['as' NAME]] try: - 1/0 + 1 / 0 except ZeroDivisionError: pass else: pass - try: 1/0 - except EOFError: pass - except TypeError as msg: pass - except: pass - else: pass - try: 1/0 - except (EOFError, TypeError, ZeroDivisionError): pass - try: 1/0 - except (EOFError, TypeError, ZeroDivisionError) as msg: pass - try: pass - finally: pass + try: + 1 / 0 + except EOFError: + pass + except TypeError as msg: + pass + except: + pass + else: + pass + try: + 1 / 0 + except (EOFError, TypeError, ZeroDivisionError): + pass + try: + 1 / 0 + except (EOFError, TypeError, ZeroDivisionError) as msg: + pass + try: + pass + finally: + pass with self.assertRaises(SyntaxError): compile("try:\n pass\nexcept Exception as a.b:\n pass", "?", "exec") compile("try:\n pass\nexcept Exception as a[b]:\n pass", "?", "exec") @@ -1415,21 +1797,31 @@ def test_try_star(self): ### try_stmt: 'try': suite (except_star_clause : suite) + ['else' ':' suite] ### except_star_clause: 'except*' expr ['as' NAME] try: - 1/0 + 1 / 0 except* ZeroDivisionError: pass else: pass - try: 1/0 - except* EOFError: pass - except* ZeroDivisionError as msg: pass - else: pass - try: 1/0 - except* (EOFError, TypeError, ZeroDivisionError): pass - try: 1/0 - except* (EOFError, TypeError, ZeroDivisionError) as msg: pass - try: pass - finally: pass + try: + 1 / 0 + except* EOFError: + pass + except* ZeroDivisionError as msg: + pass + else: + pass + try: + 1 / 0 + except* (EOFError, TypeError, ZeroDivisionError): + pass + try: + 1 / 0 + except* (EOFError, TypeError, ZeroDivisionError) as msg: + pass + try: + pass + finally: + pass with self.assertRaises(SyntaxError): compile("try:\n pass\nexcept* Exception as a.b:\n pass", "?", "exec") compile("try:\n pass\nexcept* Exception as a[b]:\n pass", "?", "exec") @@ -1437,7 +1829,8 @@ def test_try_star(self): def test_suite(self): # simple_stmt | NEWLINE INDENT NEWLINE* (stmt NEWLINE*)+ DEDENT - if 1: pass + if 1: + pass if 1: pass if 1: @@ -1454,140 +1847,158 @@ def test_test(self): ### and_test ('or' and_test)* ### and_test: not_test ('and' not_test)* ### not_test: 'not' not_test | comparison - if not 1: pass - if 1 and 1: pass - if 1 or 1: pass - if not not not 1: pass - if not 1 and 1 and 1: pass - if 1 and 1 or 1 and 1 and 1 or not 1 and 1: pass + if not 1: + pass + if 1 and 1: + pass + if 1 or 1: + pass + if not not not 1: + pass + if not 1 and 1 and 1: + pass + if 1 and 1 or 1 and 1 and 1 or not 1 and 1: + pass def test_comparison(self): ### comparison: expr (comp_op expr)* ### comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'in'|'not' 'in'|'is'|'is' 'not' - if 1: pass - x = (1 == 1) - if 1 == 1: pass - if 1 != 1: pass - if 1 < 1: pass - if 1 > 1: pass - if 1 <= 1: pass - if 1 >= 1: pass - if x is x: pass - if x is not x: pass - if 1 in (): pass - if 1 not in (): pass - if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in x is x is not x: pass + if 1: + pass + x = 1 == 1 + if 1 == 1: + pass + if 1 != 1: + pass + if 1 < 1: + pass + if 1 > 1: + pass + if 1 <= 1: + pass + if 1 >= 1: + pass + if x is x: + pass + if x is not x: + pass + if 1 in (): + pass + if 1 not in (): + pass + if 1 < 1 > 1 == 1 >= 1 <= 1 != 1 in 1 not in x is x is not x: + pass def test_comparison_is_literal(self): def check(test, msg): self.check_syntax_warning(test, msg) - check('x is 1', '"is" with \'int\' literal') - check('x is "thing"', '"is" with \'str\' literal') - check('1 is x', '"is" with \'int\' literal') - check('x is y is 1', '"is" with \'int\' literal') - check('x is not 1', '"is not" with \'int\' literal') - check('x is not (1, 2)', '"is not" with \'tuple\' literal') - check('(1, 2) is not x', '"is not" with \'tuple\' literal') + check("x is 1", "\"is\" with 'int' literal") + check('x is "thing"', "\"is\" with 'str' literal") + check("1 is x", "\"is\" with 'int' literal") + check("x is y is 1", "\"is\" with 'int' literal") + check("x is not 1", "\"is not\" with 'int' literal") + check("x is not (1, 2)", "\"is not\" with 'tuple' literal") + check("(1, 2) is not x", "\"is not\" with 'tuple' literal") - check('None is 1', '"is" with \'int\' literal') - check('1 is None', '"is" with \'int\' literal') + check("None is 1", "\"is\" with 'int' literal") + check("1 is None", "\"is\" with 'int' literal") - check('x == 3 is y', '"is" with \'int\' literal') - check('x == "thing" is y', '"is" with \'str\' literal') + check("x == 3 is y", "\"is\" with 'int' literal") + check('x == "thing" is y', "\"is\" with 'str' literal") with warnings.catch_warnings(): - warnings.simplefilter('error', SyntaxWarning) - compile('x is None', '', 'exec') - compile('x is False', '', 'exec') - compile('x is True', '', 'exec') - compile('x is ...', '', 'exec') - compile('None is x', '', 'exec') - compile('False is x', '', 'exec') - compile('True is x', '', 'exec') - compile('... is x', '', 'exec') + warnings.simplefilter("error", SyntaxWarning) + compile("x is None", "", "exec") + compile("x is False", "", "exec") + compile("x is True", "", "exec") + compile("x is ...", "", "exec") + compile("None is x", "", "exec") + compile("False is x", "", "exec") + compile("True is x", "", "exec") + compile("... is x", "", "exec") def test_warn_missed_comma(self): def check(test): self.check_syntax_warning(test, msg) - msg=r'is not callable; perhaps you missed a comma\?' - check('[(1, 2) (3, 4)]') - check('[(x, y) (3, 4)]') - check('[[1, 2] (3, 4)]') - check('[{1, 2} (3, 4)]') - check('[{1: 2} (3, 4)]') - check('[[i for i in range(5)] (3, 4)]') - check('[{i for i in range(5)} (3, 4)]') - check('[(i for i in range(5)) (3, 4)]') - check('[{i: i for i in range(5)} (3, 4)]') + msg = r"is not callable; perhaps you missed a comma\?" + check("[(1, 2) (3, 4)]") + check("[(x, y) (3, 4)]") + check("[[1, 2] (3, 4)]") + check("[{1, 2} (3, 4)]") + check("[{1: 2} (3, 4)]") + check("[[i for i in range(5)] (3, 4)]") + check("[{i for i in range(5)} (3, 4)]") + check("[(i for i in range(5)) (3, 4)]") + check("[{i: i for i in range(5)} (3, 4)]") check('[f"{x}" (3, 4)]') check('[f"x={x}" (3, 4)]') check('["abc" (3, 4)]') check('[b"abc" (3, 4)]') - check('[123 (3, 4)]') - check('[12.3 (3, 4)]') - check('[12.3j (3, 4)]') - check('[None (3, 4)]') - check('[True (3, 4)]') - check('[... (3, 4)]') - - msg=r'is not subscriptable; perhaps you missed a comma\?' - check('[{1, 2} [i, j]]') - check('[{i for i in range(5)} [i, j]]') - check('[(i for i in range(5)) [i, j]]') - check('[(lambda x, y: x) [i, j]]') - check('[123 [i, j]]') - check('[12.3 [i, j]]') - check('[12.3j [i, j]]') - check('[None [i, j]]') - check('[True [i, j]]') - check('[... [i, j]]') - - msg=r'indices must be integers or slices, not tuple; perhaps you missed a comma\?' - check('[(1, 2) [i, j]]') - check('[(x, y) [i, j]]') - check('[[1, 2] [i, j]]') - check('[[i for i in range(5)] [i, j]]') + check("[123 (3, 4)]") + check("[12.3 (3, 4)]") + check("[12.3j (3, 4)]") + check("[None (3, 4)]") + check("[True (3, 4)]") + check("[... (3, 4)]") + + msg = r"is not subscriptable; perhaps you missed a comma\?" + check("[{1, 2} [i, j]]") + check("[{i for i in range(5)} [i, j]]") + check("[(i for i in range(5)) [i, j]]") + check("[(lambda x, y: x) [i, j]]") + check("[123 [i, j]]") + check("[12.3 [i, j]]") + check("[12.3j [i, j]]") + check("[None [i, j]]") + check("[True [i, j]]") + check("[... [i, j]]") + + msg = r"indices must be integers or slices, not tuple; perhaps you missed a comma\?" + check("[(1, 2) [i, j]]") + check("[(x, y) [i, j]]") + check("[[1, 2] [i, j]]") + check("[[i for i in range(5)] [i, j]]") check('[f"{x}" [i, j]]') check('[f"x={x}" [i, j]]') check('["abc" [i, j]]') check('[b"abc" [i, j]]') - msg=r'indices must be integers or slices, not tuple;' - check('[[1, 2] [3, 4]]') - msg=r'indices must be integers or slices, not list;' - check('[[1, 2] [[3, 4]]]') - check('[[1, 2] [[i for i in range(5)]]]') - msg=r'indices must be integers or slices, not set;' - check('[[1, 2] [{3, 4}]]') - check('[[1, 2] [{i for i in range(5)}]]') - msg=r'indices must be integers or slices, not dict;' - check('[[1, 2] [{3: 4}]]') - check('[[1, 2] [{i: i for i in range(5)}]]') - msg=r'indices must be integers or slices, not generator;' - check('[[1, 2] [(i for i in range(5))]]') - msg=r'indices must be integers or slices, not function;' - check('[[1, 2] [(lambda x, y: x)]]') - msg=r'indices must be integers or slices, not str;' + msg = r"indices must be integers or slices, not tuple;" + check("[[1, 2] [3, 4]]") + msg = r"indices must be integers or slices, not list;" + check("[[1, 2] [[3, 4]]]") + check("[[1, 2] [[i for i in range(5)]]]") + msg = r"indices must be integers or slices, not set;" + check("[[1, 2] [{3, 4}]]") + check("[[1, 2] [{i for i in range(5)}]]") + msg = r"indices must be integers or slices, not dict;" + check("[[1, 2] [{3: 4}]]") + check("[[1, 2] [{i: i for i in range(5)}]]") + msg = r"indices must be integers or slices, not generator;" + check("[[1, 2] [(i for i in range(5))]]") + msg = r"indices must be integers or slices, not function;" + check("[[1, 2] [(lambda x, y: x)]]") + msg = r"indices must be integers or slices, not str;" check('[[1, 2] [f"{x}"]]') check('[[1, 2] [f"x={x}"]]') check('[[1, 2] ["abc"]]') - msg=r'indices must be integers or slices, not' + msg = r"indices must be integers or slices, not" check('[[1, 2] [b"abc"]]') - check('[[1, 2] [12.3]]') - check('[[1, 2] [12.3j]]') - check('[[1, 2] [None]]') - check('[[1, 2] [...]]') + check("[[1, 2] [12.3]]") + check("[[1, 2] [12.3j]]") + check("[[1, 2] [None]]") + check("[[1, 2] [...]]") with warnings.catch_warnings(): - warnings.simplefilter('error', SyntaxWarning) - compile('[(lambda x, y: x) (3, 4)]', '', 'exec') - compile('[[1, 2] [i]]', '', 'exec') - compile('[[1, 2] [0]]', '', 'exec') - compile('[[1, 2] [True]]', '', 'exec') - compile('[[1, 2] [1:2]]', '', 'exec') - compile('[{(1, 2): 3} [i, j]]', '', 'exec') + warnings.simplefilter("error", SyntaxWarning) + compile("[(lambda x, y: x) (3, 4)]", "", "exec") + compile("[[1, 2] [i]]", "", "exec") + compile("[[1, 2] [0]]", "", "exec") + compile("[[1, 2] [True]]", "", "exec") + compile("[[1, 2] [1:2]]", "", "exec") + compile("[{(1, 2): 3} [i, j]]", "", "exec") def test_binary_mask_ops(self): x = 1 & 1 @@ -1616,17 +2027,18 @@ def test_unary_ops(self): x = -1 x = ~1 x = ~1 ^ 1 & 1 | 1 & 1 ^ -1 - x = -1*1/1 + 1*1 - ---1*1 + x = -1 * 1 / 1 + 1 * 1 - ---1 * 1 def test_selectors(self): ### trailer: '(' [testlist] ')' | '[' subscript ']' | '.' NAME ### subscript: expr | [expr] ':' [expr] import sys, time + c = sys.path[0] x = time.time() - x = sys.modules['time'].time() - a = '01234' + x = sys.modules["time"].time() + a = "01234" c = a[0] c = a[-1] s = a[0:5] @@ -1642,18 +2054,18 @@ def test_selectors(self): d = {} d[1] = 1 d[1,] = 2 - d[1,2] = 3 - d[1,2,3] = 4 + d[1, 2] = 3 + d[1, 2, 3] = 4 L = list(d) L.sort(key=lambda x: (type(x).__name__, x)) - self.assertEqual(str(L), '[1, (1,), (1, 2), (1, 2, 3)]') + self.assertEqual(str(L), "[1, (1,), (1, 2), (1, 2, 3)]") def test_atoms(self): ### atom: '(' [testlist] ')' | '[' [testlist] ']' | '{' [dictsetmaker] '}' | NAME | NUMBER | STRING ### dictsetmaker: (test ':' test (',' test ':' test)* [',']) | (test (',' test)* [',']) - x = (1) - x = (1 or 2 or 3) + x = 1 + x = 1 or 2 or 3 x = (1 or 2 or 3, 2, 3) x = [] @@ -1663,20 +2075,32 @@ def test_atoms(self): x = [] x = {} - x = {'one': 1} - x = {'one': 1,} - x = {'one' or 'two': 1 or 2} - x = {'one': 1, 'two': 2} - x = {'one': 1, 'two': 2,} - x = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5, 'six': 6} - - x = {'one'} - x = {'one', 1,} - x = {'one', 'two', 'three'} - x = {2, 3, 4,} + x = {"one": 1} + x = { + "one": 1, + } + x = {"one" or "two": 1 or 2} + x = {"one": 1, "two": 2} + x = { + "one": 1, + "two": 2, + } + x = {"one": 1, "two": 2, "three": 3, "four": 4, "five": 5, "six": 6} + + x = {"one"} + x = { + "one", + 1, + } + x = {"one", "two", "three"} + x = { + 2, + 3, + 4, + } x = x - x = 'x' + x = "x" x = 123 ### exprlist: expr (',' expr)* [','] @@ -1685,43 +2109,72 @@ def test_atoms(self): def test_classdef(self): # 'class' NAME ['(' [testlist] ')'] ':' suite - class B: pass - class B2(): pass - class C1(B): pass - class C2(B): pass - class D(C1, C2, B): pass + class B: + pass + + class B2: + pass + + class C1(B): + pass + + class C2(B): + pass + + class D(C1, C2, B): + pass + class C: - def meth1(self): pass - def meth2(self, arg): pass - def meth3(self, a1, a2): pass + def meth1(self): + pass + + def meth2(self, arg): + pass + + def meth3(self, a1, a2): + pass # decorator: '@' namedexpr_test NEWLINE # decorators: decorator+ # decorated: decorators (classdef | funcdef) - def class_decorator(x): return x + def class_decorator(x): + return x + @class_decorator - class G: pass + class G: + pass # Test expressions as decorators (PEP 614): @False or class_decorator - class H: pass + class H: + pass + @d := class_decorator - class I: pass + class I: + pass + @lambda c: class_decorator(c) - class J: pass + class J: + pass + @[..., class_decorator, ...][1] - class K: pass + class K: + pass + @class_decorator(class_decorator)(class_decorator) - class L: pass + class L: + pass + @[class_decorator][0].__call__.__call__ - class M: pass + class M: + pass def test_dictcomps(self): # dictorsetmaker: ( (test ':' test (comp_for | # (',' test ':' test)* [','])) | # (test (comp_for | (',' test)* [','])) ) nums = [1, 2, 3] - self.assertEqual({i:i+1 for i in nums}, {1: 2, 2: 3, 3: 4}) + self.assertEqual({i: i + 1 for i in nums}, {1: 2, 2: 3, 3: 4}) def test_listcomps(self): # list comprehension tests @@ -1729,21 +2182,48 @@ def test_listcomps(self): strs = ["Apple", "Banana", "Coconut"] spcs = [" Apple", " Banana ", "Coco nut "] - self.assertEqual([s.strip() for s in spcs], ['Apple', 'Banana', 'Coco nut']) + self.assertEqual([s.strip() for s in spcs], ["Apple", "Banana", "Coco nut"]) self.assertEqual([3 * x for x in nums], [3, 6, 9, 12, 15]) self.assertEqual([x for x in nums if x > 2], [3, 4, 5]) - self.assertEqual([(i, s) for i in nums for s in strs], - [(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), - (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), - (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), - (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), - (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')]) - self.assertEqual([(i, s) for i in nums for s in [f for f in strs if "n" in f]], - [(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), - (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), - (5, 'Banana'), (5, 'Coconut')]) - self.assertEqual([(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)], - [[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]]) + self.assertEqual( + [(i, s) for i in nums for s in strs], + [ + (1, "Apple"), + (1, "Banana"), + (1, "Coconut"), + (2, "Apple"), + (2, "Banana"), + (2, "Coconut"), + (3, "Apple"), + (3, "Banana"), + (3, "Coconut"), + (4, "Apple"), + (4, "Banana"), + (4, "Coconut"), + (5, "Apple"), + (5, "Banana"), + (5, "Coconut"), + ], + ) + self.assertEqual( + [(i, s) for i in nums for s in [f for f in strs if "n" in f]], + [ + (1, "Banana"), + (1, "Coconut"), + (2, "Banana"), + (2, "Coconut"), + (3, "Banana"), + (3, "Coconut"), + (4, "Banana"), + (4, "Coconut"), + (5, "Banana"), + (5, "Coconut"), + ], + ) + self.assertEqual( + [(lambda a: [a**i for i in range(a + 1)])(j) for j in range(5)], + [[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]], + ) def test_in_func(l): return [0 < x < 3 for x in l if x > 2] @@ -1751,40 +2231,38 @@ def test_in_func(l): self.assertEqual(test_in_func(nums), [False, False, False]) def test_nested_front(): - self.assertEqual([[y for y in [x, x + 1]] for x in [1,3,5]], - [[1, 2], [3, 4], [5, 6]]) + self.assertEqual( + [[y for y in [x, x + 1]] for x in [1, 3, 5]], [[1, 2], [3, 4], [5, 6]] + ) test_nested_front() check_syntax_error(self, "[i, s for i in nums for s in strs]") check_syntax_error(self, "[x if y]") - suppliers = [ - (1, "Boeing"), - (2, "Ford"), - (3, "Macdonalds") - ] + suppliers = [(1, "Boeing"), (2, "Ford"), (3, "Macdonalds")] - parts = [ - (10, "Airliner"), - (20, "Engine"), - (30, "Cheeseburger") - ] + parts = [(10, "Airliner"), (20, "Engine"), (30, "Cheeseburger")] - suppart = [ - (1, 10), (1, 20), (2, 20), (3, 30) - ] + suppart = [(1, 10), (1, 20), (2, 20), (3, 30)] x = [ - (sname, pname) + (sname, pname) for (sno, sname) in suppliers - for (pno, pname) in parts - for (sp_sno, sp_pno) in suppart - if sno == sp_sno and pno == sp_pno + for (pno, pname) in parts + for (sp_sno, sp_pno) in suppart + if sno == sp_sno and pno == sp_pno ] - self.assertEqual(x, [('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), - ('Macdonalds', 'Cheeseburger')]) + self.assertEqual( + x, + [ + ("Boeing", "Airliner"), + ("Boeing", "Engine"), + ("Ford", "Engine"), + ("Macdonalds", "Cheeseburger"), + ], + ) def test_genexps(self): # generator expression tests @@ -1792,7 +2270,7 @@ def test_genexps(self): self.assertEqual(next(g), [x for x in range(10)]) try: next(g) - self.fail('should produce StopIteration exception') + self.fail("should produce StopIteration exception") except StopIteration: pass @@ -1800,50 +2278,81 @@ def test_genexps(self): try: g = (a for d in a) next(g) - self.fail('should produce TypeError') + self.fail("should produce TypeError") except TypeError: pass - self.assertEqual(list((x, y) for x in 'abcd' for y in 'abcd'), [(x, y) for x in 'abcd' for y in 'abcd']) - self.assertEqual(list((x, y) for x in 'ab' for y in 'xy'), [(x, y) for x in 'ab' for y in 'xy']) + self.assertEqual( + list((x, y) for x in "abcd" for y in "abcd"), + [(x, y) for x in "abcd" for y in "abcd"], + ) + self.assertEqual( + list((x, y) for x in "ab" for y in "xy"), + [(x, y) for x in "ab" for y in "xy"], + ) a = [x for x in range(10)] b = (x for x in (y for y in a)) self.assertEqual(sum(b), sum([x for x in range(10)])) self.assertEqual(sum(x**2 for x in range(10)), sum([x**2 for x in range(10)])) - self.assertEqual(sum(x*x for x in range(10) if x%2), sum([x*x for x in range(10) if x%2])) - self.assertEqual(sum(x for x in (y for y in range(10))), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10)))), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in [y for y in (z for z in range(10))]), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True)) if True), sum([x for x in range(10)])) - self.assertEqual(sum(x for x in (y for y in (z for z in range(10) if True) if False) if True), 0) + self.assertEqual( + sum(x * x for x in range(10) if x % 2), + sum([x * x for x in range(10) if x % 2]), + ) + self.assertEqual( + sum(x for x in (y for y in range(10))), sum([x for x in range(10)]) + ) + self.assertEqual( + sum(x for x in (y for y in (z for z in range(10)))), + sum([x for x in range(10)]), + ) + self.assertEqual( + sum(x for x in [y for y in (z for z in range(10))]), + sum([x for x in range(10)]), + ) + self.assertEqual( + sum(x for x in (y for y in (z for z in range(10) if True)) if True), + sum([x for x in range(10)]), + ) + self.assertEqual( + sum( + x for x in (y for y in (z for z in range(10) if True) if False) if True + ), + 0, + ) check_syntax_error(self, "foo(x for x in range(10), 100)") check_syntax_error(self, "foo(100, x for x in range(10))") def test_comprehension_specials(self): # test for outmost iterable precomputation - x = 10; g = (i for i in range(x)); x = 5 + x = 10 + g = (i for i in range(x)) + x = 5 self.assertEqual(len(list(g)), 10) # This should hold, since we're only precomputing outmost iterable. - x = 10; t = False; g = ((i,j) for i in range(x) if t for j in range(x)) - x = 5; t = True; - self.assertEqual([(i,j) for i in range(10) for j in range(5)], list(g)) + x = 10 + t = False + g = ((i, j) for i in range(x) if t for j in range(x)) + x = 5 + t = True + self.assertEqual([(i, j) for i in range(10) for j in range(5)], list(g)) # Grammar allows multiple adjacent 'if's in listcomps and genexps, # even though it's silly. Make sure it works (ifelse broke this.) - self.assertEqual([ x for x in range(10) if x % 2 if x % 3 ], [1, 5, 7]) + self.assertEqual([x for x in range(10) if x % 2 if x % 3], [1, 5, 7]) self.assertEqual(list(x for x in range(10) if x % 2 if x % 3), [1, 5, 7]) # verify unpacking single element tuples in listcomp/genexp. - self.assertEqual([x for x, in [(4,), (5,), (6,)]], [4, 5, 6]) - self.assertEqual(list(x for x, in [(7,), (8,), (9,)]), [7, 8, 9]) + self.assertEqual([x for (x,) in [(4,), (5,), (6,)]], [4, 5, 6]) + self.assertEqual(list(x for (x,) in [(7,), (8,), (9,)]), [7, 8, 9]) def test_with_statement(self): class manager(object): def __enter__(self): return (1, 2) + def __exit__(self, *args): pass @@ -1860,14 +2369,10 @@ def __exit__(self, *args): with manager() as x, manager(): pass - with ( - manager() - ): + with manager(): pass - with ( - manager() as x - ): + with manager() as x: pass with ( @@ -1876,22 +2381,13 @@ def __exit__(self, *args): ): pass - with ( - manager(), - manager() - ): + with manager(), manager(): pass - with ( - manager() as x, - manager() as y - ): + with manager() as x, manager() as y: pass - with ( - manager() as x, - manager() - ): + with manager() as x, manager(): pass with ( @@ -1916,16 +2412,28 @@ def _checkeval(msg, ret): return ret # the next line is not allowed anymore - #self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True]) - self.assertEqual([ x() for x in (lambda: True, lambda: False) if x() ], [True]) - self.assertEqual([ x(False) for x in (lambda x: False if x else True, lambda x: True if x else False) if x(False) ], [True]) + # self.assertEqual([ x() for x in lambda: True, lambda: False if x() ], [True]) + self.assertEqual([x() for x in (lambda: True, lambda: False) if x()], [True]) + self.assertEqual( + [ + x(False) + for x in ( + lambda x: False if x else True, + lambda x: True if x else False, + ) + if x(False) + ], + [True], + ) self.assertEqual((5 if 1 else _checkeval("check 1", 0)), 5) self.assertEqual((_checkeval("check 2", 0) if 0 else 5), 5) self.assertEqual((5 and 6 if 0 else 1), 1) self.assertEqual(((5 and 6) if 0 else 1), 1) self.assertEqual((5 and (6 if 1 else 1)), 6) self.assertEqual((0 or _checkeval("check 3", 2) if 0 else 3), 3) - self.assertEqual((1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)), 1) + self.assertEqual( + (1 or _checkeval("check 4", 2) if 1 else _checkeval("check 5", 3)), 1 + ) self.assertEqual((0 or 5 if 1 else _checkeval("check 6", 3)), 5) self.assertEqual((not 5 if 1 else 1), False) self.assertEqual((not 5 if 0 else 1), 1) @@ -1951,9 +2459,11 @@ def test_matrix_mul(self): class M: def __matmul__(self, o): return 4 + def __imatmul__(self, o): self.other = o return self + m = M() self.assertEqual(m @ m, 4) m @= 42 @@ -1963,29 +2473,33 @@ def test_async_await(self): async def test(): def sum(): pass + if 1: await someobj() - self.assertEqual(test.__name__, 'test') + self.assertEqual(test.__name__, "test") self.assertTrue(bool(test.__code__.co_flags & inspect.CO_COROUTINE)) def decorator(func): - setattr(func, '_marked', True) + setattr(func, "_marked", True) return func @decorator async def test2(): return 22 + self.assertTrue(test2._marked) - self.assertEqual(test2.__name__, 'test2') + self.assertEqual(test2.__name__, "test2") self.assertTrue(bool(test2.__code__.co_flags & inspect.CO_COROUTINE)) def test_async_for(self): - class Done(Exception): pass + class Done(Exception): + pass class AIter: def __aiter__(self): return self + async def __anext__(self): raise StopAsyncIteration @@ -2004,11 +2518,13 @@ async def foo(): foo().send(None) def test_async_with(self): - class Done(Exception): pass + class Done(Exception): + pass class manager: async def __aenter__(self): return (1, 2) + async def __aexit__(self, *exc): return False @@ -2031,5 +2547,5 @@ async def foo(): foo().send(None) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index aa465c70dfbcd0..9029aa6ec2b98f 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -5,7 +5,10 @@ import importlib.util from importlib._bootstrap_external import _get_sourcefile from importlib.machinery import ( - BuiltinImporter, ExtensionFileLoader, FrozenImporter, SourceFileLoader, + BuiltinImporter, + ExtensionFileLoader, + FrozenImporter, + SourceFileLoader, ) import marshal import os @@ -25,17 +28,31 @@ from test.support import os_helper from test.support import ( - STDLIB_DIR, swap_attr, swap_item, cpython_only, is_emscripten, - is_wasi, run_in_subinterp, run_in_subinterp_with_config, Py_TRACE_REFS) + STDLIB_DIR, + swap_attr, + swap_item, + cpython_only, + is_emscripten, + is_wasi, + run_in_subinterp, + run_in_subinterp_with_config, + Py_TRACE_REFS, +) from test.support.import_helper import ( - forget, make_legacy_pyc, unlink, unload, ready_to_import, - DirsOnSysPath, CleanImport) -from test.support.os_helper import ( - TESTFN, rmtree, temp_umask, TESTFN_UNENCODABLE) + forget, + make_legacy_pyc, + unlink, + unload, + ready_to_import, + DirsOnSysPath, + CleanImport, +) +from test.support.os_helper import TESTFN, rmtree, temp_umask, TESTFN_UNENCODABLE from test.support import script_helper from test.support import threading_helper from test.test_importlib.util import uncache from types import ModuleType + try: import _testsinglephase except ImportError: @@ -55,8 +72,8 @@ skip_if_dont_write_bytecode = unittest.skipIf( - sys.dont_write_bytecode, - "test meaningful only when writing bytecode") + sys.dont_write_bytecode, "test meaningful only when writing bytecode" +) def _require_loader(module, loader, skip): @@ -64,10 +81,10 @@ def _require_loader(module, loader, skip): module = __import__(module) MODULE_KINDS = { - BuiltinImporter: 'built-in', - ExtensionFileLoader: 'extension', - FrozenImporter: 'frozen', - SourceFileLoader: 'pure Python', + BuiltinImporter: "built-in", + ExtensionFileLoader: "extension", + FrozenImporter: "frozen", + SourceFileLoader: "pure Python", } expected = loader @@ -80,33 +97,35 @@ def _require_loader(module, loader, skip): actual = MODULE_KINDS[actual] if actual != expected: - err = f'expected module to be {expected}, got {module.__spec__}' + err = f"expected module to be {expected}, got {module.__spec__}" if skip: raise unittest.SkipTest(err) raise Exception(err) return module + def require_builtin(module, *, skip=False): module = _require_loader(module, BuiltinImporter, skip) - assert module.__spec__.origin == 'built-in', module.__spec__ + assert module.__spec__.origin == "built-in", module.__spec__ + def require_extension(module, *, skip=False): _require_loader(module, ExtensionFileLoader, skip) + def require_frozen(module, *, skip=True): module = _require_loader(module, FrozenImporter, skip) - assert module.__spec__.origin == 'frozen', module.__spec__ + assert module.__spec__.origin == "frozen", module.__spec__ + def require_pure_python(module, *, skip=False): _require_loader(module, SourceFileLoader, skip) + def remove_files(name): - for f in (name + ".py", - name + ".pyc", - name + ".pyw", - name + "$py.class"): + for f in (name + ".py", name + ".pyc", name + ".pyw", name + "$py.class"): unlink(f) - rmtree('__pycache__') + rmtree("__pycache__") def no_rerun(reason): @@ -116,45 +135,52 @@ def no_rerun(reason): impossible to find reference leaks. Provide a clear reason for skipping the test using the 'reason' parameter. """ + def deco(func): _has_run = False + def wrapper(self): nonlocal _has_run if _has_run: self.skipTest(reason) func(self) _has_run = True + return wrapper + return deco if _testsinglephase is not None: + def restore__testsinglephase(*, _orig=_testsinglephase): # We started with the module imported and want to restore # it to its nominal state. - sys.modules.pop('_testsinglephase', None) + sys.modules.pop("_testsinglephase", None) _orig._clear_globals() - _testinternalcapi.clear_extension('_testsinglephase', _orig.__file__) + _testinternalcapi.clear_extension("_testsinglephase", _orig.__file__) import _testsinglephase def requires_singlephase_init(meth): """Decorator to skip if single-phase init modules are not supported.""" if not isinstance(meth, type): + def meth(self, _meth=meth): try: return _meth(self) finally: restore__testsinglephase() + meth = cpython_only(meth) - return unittest.skipIf(_testsinglephase is None, - 'test requires _testsinglephase module')(meth) + return unittest.skipIf( + _testsinglephase is None, "test requires _testsinglephase module" + )(meth) def requires_subinterpreters(meth): """Decorator to skip a test if subinterpreters are not supported.""" - return unittest.skipIf(_interpreters is None, - 'subinterpreters required')(meth) + return unittest.skipIf(_interpreters is None, "subinterpreters required")(meth) class ModuleSnapshot(types.SimpleNamespace): @@ -176,7 +202,8 @@ class ModuleSnapshot(types.SimpleNamespace): In cases where the value is not available (e.g. due to serialization), the value will be None. """ - _fields = tuple('id module ns ns_id cached cached_id'.split()) + + _fields = tuple("id module ns ns_id cached cached_id".split()) @classmethod def from_module(cls, mod): @@ -191,7 +218,8 @@ def from_module(cls, mod): cached_id=id(cached), ) - SCRIPT = textwrap.dedent(''' + SCRIPT = textwrap.dedent( + """ {imports} name = {name!r} @@ -203,11 +231,15 @@ def from_module(cls, mod): {body} {postscript} - ''') - IMPORTS = textwrap.dedent(''' + """ + ) + IMPORTS = textwrap.dedent( + """ import sys - ''').strip() - SCRIPT_BODY = textwrap.dedent(''' + """ + ).strip() + SCRIPT_BODY = textwrap.dedent( + """ # Capture the snapshot data. cached = sys.modules.get(name) snapshot = dict( @@ -224,28 +256,34 @@ def from_module(cls, mod): cached=None, cached_id=id(cached) if cached else None, ) - ''').strip() - CLEANUP_SCRIPT = textwrap.dedent(''' + """ + ).strip() + CLEANUP_SCRIPT = textwrap.dedent( + """ # Clean up the module. sys.modules.pop(name, None) - ''').strip() + """ + ).strip() @classmethod - def build_script(cls, name, *, - prescript=None, - import_first=False, - postscript=None, - postcleanup=False, - ): + def build_script( + cls, + name, + *, + prescript=None, + import_first=False, + postscript=None, + postcleanup=False, + ): if postcleanup is True: postcleanup = cls.CLEANUP_SCRIPT elif isinstance(postcleanup, str): postcleanup = textwrap.dedent(postcleanup).strip() postcleanup = cls.CLEANUP_SCRIPT + os.linesep + postcleanup else: - postcleanup = '' - prescript = textwrap.dedent(prescript).strip() if prescript else '' - postscript = textwrap.dedent(postscript).strip() if postscript else '' + postcleanup = "" + prescript = textwrap.dedent(prescript).strip() if prescript else "" + postscript = textwrap.dedent(postscript).strip() if postscript else "" if postcleanup: if postscript: @@ -254,11 +292,13 @@ def build_script(cls, name, *, postscript = postcleanup if import_first: - prescript += textwrap.dedent(f''' + prescript += textwrap.dedent( + f""" # Now import the module. assert name not in sys.modules - import {name}''') + import {name}""" + ) return cls.SCRIPT.format( imports=cls.IMPORTS.strip(), @@ -271,9 +311,9 @@ def build_script(cls, name, *, @classmethod def parse(cls, text): raw = json.loads(text) - mod = raw['module'] - mod['__spec__'] = types.SimpleNamespace(**mod['__spec__']) - raw['module'] = types.SimpleNamespace(**mod) + mod = raw["module"] + mod["__spec__"] = types.SimpleNamespace(**mod["__spec__"]) + raw["module"] = types.SimpleNamespace(**mod) return cls(**raw) @classmethod @@ -293,25 +333,27 @@ def _from_subinterp(cls, name, interpid, pipe, script_kwargs): r, w = pipe # Build the script. - postscript = textwrap.dedent(f''' + postscript = textwrap.dedent( + f""" # Send the result over the pipe. import json import os os.write({w}, json.dumps(snapshot).encode()) - ''') - _postscript = script_kwargs.get('postscript') + """ + ) + _postscript = script_kwargs.get("postscript") if _postscript: _postscript = textwrap.dedent(_postscript).lstrip() postscript += _postscript - script_kwargs['postscript'] = postscript.strip() + script_kwargs["postscript"] = postscript.strip() script = cls.build_script(name, **script_kwargs) # Run the script. if interpid is None: ret = run_in_subinterp(script) if ret != 0: - raise AssertionError(f'{ret} != 0') + raise AssertionError(f"{ret} != 0") else: _interpreters.run_string(interpid, script) @@ -321,7 +363,6 @@ def _from_subinterp(cls, name, interpid, pipe, script_kwargs): class ImportTests(unittest.TestCase): - def setUp(self): remove_files(TESTFN) importlib.invalidate_caches() @@ -342,49 +383,55 @@ def test_from_import_missing_attr_raises_ImportError(self): from importlib import something_that_should_not_exist_anywhere def test_from_import_missing_attr_has_name_and_path(self): - with CleanImport('os'): + with CleanImport("os"): import os + with self.assertRaises(ImportError) as cm: from os import i_dont_exist - self.assertEqual(cm.exception.name, 'os') + self.assertEqual(cm.exception.name, "os") self.assertEqual(cm.exception.path, os.__file__) - self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from 'os' \(.*os.py\)") + self.assertRegex( + str(cm.exception), + r"cannot import name 'i_dont_exist' from 'os' \(.*os.py\)", + ) @cpython_only def test_from_import_missing_attr_has_name_and_so_path(self): import _testcapi + with self.assertRaises(ImportError) as cm: from _testcapi import i_dont_exist - self.assertEqual(cm.exception.name, '_testcapi') + self.assertEqual(cm.exception.name, "_testcapi") if hasattr(_testcapi, "__file__"): self.assertEqual(cm.exception.path, _testcapi.__file__) self.assertRegex( str(cm.exception), - r"cannot import name 'i_dont_exist' from '_testcapi' \(.*\.(so|pyd)\)" + r"cannot import name 'i_dont_exist' from '_testcapi' \(.*\.(so|pyd)\)", ) else: self.assertEqual( str(cm.exception), - "cannot import name 'i_dont_exist' from '_testcapi' (unknown location)" + "cannot import name 'i_dont_exist' from '_testcapi' (unknown location)", ) def test_from_import_missing_attr_has_name(self): with self.assertRaises(ImportError) as cm: # _warning has no path as it's a built-in module. from _warning import i_dont_exist - self.assertEqual(cm.exception.name, '_warning') + self.assertEqual(cm.exception.name, "_warning") self.assertIsNone(cm.exception.path) def test_from_import_missing_attr_path_is_canonical(self): with self.assertRaises(ImportError) as cm: from os.path import i_dont_exist - self.assertIn(cm.exception.name, {'posixpath', 'ntpath'}) + self.assertIn(cm.exception.name, {"posixpath", "ntpath"}) self.assertIsNotNone(cm.exception) def test_from_import_star_invalid_type(self): import re + with ready_to_import() as (name, path): - with open(path, 'w', encoding='utf-8') as f: + with open(path, "w", encoding="utf-8") as f: f.write("__all__ = [b'invalid_type']") globals = {} with self.assertRaisesRegex( @@ -393,7 +440,7 @@ def test_from_import_star_invalid_type(self): exec(f"from {name} import *", globals) self.assertNotIn(b"invalid_type", globals) with ready_to_import() as (name, path): - with open(path, 'w', encoding='utf-8') as f: + with open(path, "w", encoding="utf-8") as f: f.write("globals()[b'invalid_type'] = object()") globals = {} with self.assertRaisesRegex( @@ -419,9 +466,8 @@ def test_with_extension(ext): source = TESTFN + ext pyc = TESTFN + ".pyc" - with open(source, "w", encoding='utf-8') as f: - print("# This tests Python's ability to import a", - ext, "file.", file=f) + with open(source, "w", encoding="utf-8") as f: + print("# This tests Python's ability to import a", ext, "file.", file=f) a = random.randrange(1000) b = random.randrange(1000) print("a =", a, file=f) @@ -436,10 +482,12 @@ def test_with_extension(ext): except ImportError as err: self.fail("import from %s failed: %s" % (ext, err)) - self.assertEqual(mod.a, a, - "module loaded (%s) but contents invalid" % mod) - self.assertEqual(mod.b, b, - "module loaded (%s) but contents invalid" % mod) + self.assertEqual( + mod.a, a, "module loaded (%s) but contents invalid" % mod + ) + self.assertEqual( + mod.b, b, "module loaded (%s) but contents invalid" % mod + ) finally: forget(TESTFN) unlink(source) @@ -454,16 +502,16 @@ def test_with_extension(ext): finally: del sys.path[0] - def test_module_with_large_stack(self, module='longlist'): + def test_module_with_large_stack(self, module="longlist"): # Regression test for http://bugs.python.org/issue561858. - filename = module + '.py' + filename = module + ".py" # Create a file with a list of 65000 elements. - with open(filename, 'w', encoding='utf-8') as f: - f.write('d = [\n') + with open(filename, "w", encoding="utf-8") as f: + f.write("d = [\n") for i in range(65000): f.write('"",\n') - f.write(']') + f.write("]") try: # Compile & remove .py file; we only need .pyc. @@ -473,19 +521,19 @@ def test_module_with_large_stack(self, module='longlist'): unlink(filename) # Need to be able to load from current dir. - sys.path.append('') + sys.path.append("") importlib.invalidate_caches() namespace = {} try: make_legacy_pyc(filename) # This used to crash. - exec('import ' + module, None, namespace) + exec("import " + module, None, namespace) finally: # Cleanup. del sys.path[-1] - unlink(filename + 'c') - unlink(filename + 'o') + unlink(filename + "c") + unlink(filename + "o") # Remove references to the module (unload the module) namespace.clear() @@ -496,7 +544,7 @@ def test_module_with_large_stack(self, module='longlist'): def test_failing_import_sticks(self): source = TESTFN + ".py" - with open(source, "w", encoding='utf-8') as f: + with open(source, "w", encoding="utf-8") as f: print("a = 1/0", file=f) # New in 2.4, we shouldn't be able to import that no matter how often @@ -508,8 +556,9 @@ def test_failing_import_sticks(self): try: for i in [1, 2, 3]: self.assertRaises(ZeroDivisionError, __import__, TESTFN) - self.assertNotIn(TESTFN, sys.modules, - "damaged module in sys.modules on %i try" % i) + self.assertNotIn( + TESTFN, sys.modules, "damaged module in sys.modules on %i try" % i + ) finally: del sys.path[0] remove_files(TESTFN) @@ -518,11 +567,13 @@ def test_import_name_binding(self): # import x.y.z binds x in the current namespace import test as x import test.support + self.assertIs(x, test, x.__name__) self.assertTrue(hasattr(test.support, "__file__")) # import x.y.z as w binds z as w import test.support as y + self.assertIs(y, test.support, y.__name__) def test_issue31286(self): @@ -536,6 +587,7 @@ def test_issue31286(self): i = 0 while i < 10: import test.support.script_helper as x + i += 1 # import in a 'for' loop resulted in segmentation fault @@ -545,7 +597,7 @@ def test_issue31286(self): def test_failing_reload(self): # A failing reload should leave the module object in sys.modules. source = TESTFN + os.extsep + "py" - with open(source, "w", encoding='utf-8') as f: + with open(source, "w", encoding="utf-8") as f: f.write("a = 1\nb=2\n") sys.path.insert(0, os.curdir) @@ -562,7 +614,7 @@ def test_failing_reload(self): remove_files(TESTFN) # Now damage the module. - with open(source, "w", encoding='utf-8') as f: + with open(source, "w", encoding="utf-8") as f: f.write("a = 10\nb=20//0\n") self.assertRaises(ZeroDivisionError, importlib.reload, mod) @@ -584,20 +636,20 @@ def test_failing_reload(self): def test_file_to_source(self): # check if __file__ points to the source file where available source = TESTFN + ".py" - with open(source, "w", encoding='utf-8') as f: + with open(source, "w", encoding="utf-8") as f: f.write("test = None\n") sys.path.insert(0, os.curdir) try: mod = __import__(TESTFN) - self.assertTrue(mod.__file__.endswith('.py')) + self.assertTrue(mod.__file__.endswith(".py")) os.remove(source) del sys.modules[TESTFN] make_legacy_pyc(source) importlib.invalidate_caches() mod = __import__(TESTFN) base, ext = os.path.splitext(mod.__file__) - self.assertEqual(ext, '.pyc') + self.assertEqual(ext, ".pyc") finally: del sys.path[0] remove_files(TESTFN) @@ -610,19 +662,25 @@ def test_import_by_filename(self): try: path.encode(encoding) except UnicodeEncodeError: - self.skipTest('path is not encodable to {}'.format(encoding)) + self.skipTest("path is not encodable to {}".format(encoding)) with self.assertRaises(ImportError) as c: __import__(path) def test_import_in_del_does_not_crash(self): # Issue 4236 - testfn = script_helper.make_script('', TESTFN, textwrap.dedent("""\ + testfn = script_helper.make_script( + "", + TESTFN, + textwrap.dedent( + """\ import sys class C: def __del__(self): import importlib sys.argv.insert(0, C()) - """)) + """ + ), + ) script_helper.assert_python_ok(testfn) @skip_if_dont_write_bytecode @@ -633,17 +691,21 @@ def test_timestamp_overflow(self): try: source = TESTFN + ".py" compiled = importlib.util.cache_from_source(source) - with open(source, 'w', encoding='utf-8') as f: + with open(source, "w", encoding="utf-8") as f: pass try: - os.utime(source, (2 ** 33 - 5, 2 ** 33 - 5)) + os.utime(source, (2**33 - 5, 2**33 - 5)) except OverflowError: self.skipTest("cannot set modification time to large integer") except OSError as e: - if e.errno not in (getattr(errno, 'EOVERFLOW', None), - getattr(errno, 'EINVAL', None)): + if e.errno not in ( + getattr(errno, "EOVERFLOW", None), + getattr(errno, "EINVAL", None), + ): raise - self.skipTest("cannot set modification time to large integer ({})".format(e)) + self.skipTest( + "cannot set modification time to large integer ({})".format(e) + ) __import__(TESTFN) # The pyc file was created. os.stat(compiled) @@ -653,7 +715,7 @@ def test_timestamp_overflow(self): def test_bogus_fromlist(self): try: - __import__('http', fromlist=['blah']) + __import__("http", fromlist=["blah"]) except ImportError: self.fail("fromlist must allow bogus names") @@ -679,21 +741,23 @@ class AlwaysAttributeError: def __getattr__(self, _): raise AttributeError - module_name = 'test_from_import_AttributeError' + module_name = "test_from_import_AttributeError" self.addCleanup(unload, module_name) sys.modules[module_name] = AlwaysAttributeError() with self.assertRaises(ImportError) as cm: from test_from_import_AttributeError import does_not_exist - self.assertEqual(str(cm.exception), - "cannot import name 'does_not_exist' from '' (unknown location)") + self.assertEqual( + str(cm.exception), + "cannot import name 'does_not_exist' from '' (unknown location)", + ) @cpython_only def test_issue31492(self): # There shouldn't be an assertion failure in case of failing to import # from a module with a bad __name__ attribute, or in case of failing # to access an attribute of such a module. - with swap_attr(os, '__name__', None): + with swap_attr(os, "__name__", None): with self.assertRaises(ImportError): from os import does_not_exist @@ -705,12 +769,13 @@ def test_concurrency(self): # bpo 38091: this is a hack to slow down the code that calls # has_deadlock(); the logic was itself sometimes deadlocking. def delay_has_deadlock(frame, event, arg): - if event == 'call' and frame.f_code.co_name == 'has_deadlock': + if event == "call" and frame.f_code.co_name == "has_deadlock": time.sleep(0.1) - sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'data')) + sys.path.insert(0, os.path.join(os.path.dirname(__file__), "data")) try: exc = None + def run(): sys.settrace(delay_has_deadlock) event.wait() @@ -728,8 +793,8 @@ def run(): with threading_helper.start_threads(threads, event.set): time.sleep(0) finally: - sys.modules.pop('package', None) - sys.modules.pop('package.submodule', None) + sys.modules.pop("package", None) + sys.modules.pop("package.submodule", None) if exc is not None: raise exc finally: @@ -738,11 +803,13 @@ def run(): @unittest.skipUnless(sys.platform == "win32", "Windows-specific") def test_dll_dependency_import(self): from _winapi import GetModuleFileName + dllname = GetModuleFileName(sys.dllhandle) pydname = importlib.util.find_spec("_sqlite3").origin depname = os.path.join( os.path.dirname(pydname), - "sqlite3{}.dll".format("_d" if "_d" in pydname else "")) + "sqlite3{}.dll".format("_d" if "_d" in pydname else ""), + ) with os_helper.temp_dir() as tmp: tmp2 = os.path.join(tmp, "DLLs") @@ -761,60 +828,62 @@ def test_dll_dependency_import(self): env["PYTHONPATH"] = tmp2 + ";" + STDLIB_DIR # Test 1: import with added DLL directory - subprocess.check_call([ - pyexe, "-Sc", ";".join([ - "import os", - "p = os.add_dll_directory({!r})".format( - os.path.dirname(depname)), - "import _sqlite3", - "p.close" - ])], + subprocess.check_call( + [ + pyexe, + "-Sc", + ";".join( + [ + "import os", + "p = os.add_dll_directory({!r})".format( + os.path.dirname(depname) + ), + "import _sqlite3", + "p.close", + ] + ), + ], stderr=subprocess.STDOUT, env=env, - cwd=os.path.dirname(pyexe)) + cwd=os.path.dirname(pyexe), + ) # Test 2: import with DLL adjacent to PYD shutil.copy(depname, tmp2) - subprocess.check_call([pyexe, "-Sc", "import _sqlite3"], - stderr=subprocess.STDOUT, - env=env, - cwd=os.path.dirname(pyexe)) + subprocess.check_call( + [pyexe, "-Sc", "import _sqlite3"], + stderr=subprocess.STDOUT, + env=env, + cwd=os.path.dirname(pyexe), + ) def test_issue105979(self): # this used to crash with self.assertRaises(ImportError) as cm: - _imp.get_frozen_object("x", b"6\'\xd5Cu\x12") - self.assertIn("Frozen object named 'x' is invalid", - str(cm.exception)) + _imp.get_frozen_object("x", b"6'\xd5Cu\x12") + self.assertIn("Frozen object named 'x' is invalid", str(cm.exception)) @skip_if_dont_write_bytecode class FilePermissionTests(unittest.TestCase): # tests for file mode on cached .pyc files - @unittest.skipUnless(os.name == 'posix', - "test meaningful only on posix systems") - @unittest.skipIf( - is_emscripten or is_wasi, - "Emscripten's/WASI's umask is a stub." - ) + @unittest.skipUnless(os.name == "posix", "test meaningful only on posix systems") + @unittest.skipIf(is_emscripten or is_wasi, "Emscripten's/WASI's umask is a stub.") def test_creation_mode(self): mask = 0o022 with temp_umask(mask), ready_to_import() as (name, path): cached_path = importlib.util.cache_from_source(path) module = __import__(name) if not os.path.exists(cached_path): - self.fail("__import__ did not result in creation of " - "a .pyc file") + self.fail("__import__ did not result in creation of " "a .pyc file") stat_info = os.stat(cached_path) # Check that the umask is respected, and the executable bits # aren't set. - self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), - oct(0o666 & ~mask)) + self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(0o666 & ~mask)) - @unittest.skipUnless(os.name == 'posix', - "test meaningful only on posix systems") + @unittest.skipUnless(os.name == "posix", "test meaningful only on posix systems") @os_helper.skip_unless_working_chmod def test_cached_mode_issue_2051(self): # permissions of .pyc should match those of .py, regardless of mask @@ -824,14 +893,12 @@ def test_cached_mode_issue_2051(self): os.chmod(path, mode) __import__(name) if not os.path.exists(cached_path): - self.fail("__import__ did not result in creation of " - "a .pyc file") + self.fail("__import__ did not result in creation of " "a .pyc file") stat_info = os.stat(cached_path) self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(mode)) - @unittest.skipUnless(os.name == 'posix', - "test meaningful only on posix systems") + @unittest.skipUnless(os.name == "posix", "test meaningful only on posix systems") @os_helper.skip_unless_working_chmod def test_cached_readonly(self): mode = 0o400 @@ -840,11 +907,10 @@ def test_cached_readonly(self): os.chmod(path, mode) __import__(name) if not os.path.exists(cached_path): - self.fail("__import__ did not result in creation of " - "a .pyc file") + self.fail("__import__ did not result in creation of " "a .pyc file") stat_info = os.stat(cached_path) - expected = mode | 0o200 # Account for fix for issue #6074 + expected = mode | 0o200 # Account for fix for issue #6074 self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(expected)) def test_pyc_always_writable(self): @@ -852,22 +918,22 @@ def test_pyc_always_writable(self): # with later updates, see issue #6074 for details with ready_to_import() as (name, path): # Write a Python file, make it read-only and import it - with open(path, 'w', encoding='utf-8') as f: + with open(path, "w", encoding="utf-8") as f: f.write("x = 'original'\n") # Tweak the mtime of the source to ensure pyc gets updated later s = os.stat(path) - os.utime(path, (s.st_atime, s.st_mtime-100000000)) + os.utime(path, (s.st_atime, s.st_mtime - 100000000)) os.chmod(path, 0o400) m = __import__(name) - self.assertEqual(m.x, 'original') + self.assertEqual(m.x, "original") # Change the file and then reimport it os.chmod(path, 0o600) - with open(path, 'w', encoding='utf-8') as f: + with open(path, "w", encoding="utf-8") as f: f.write("x = 'rewritten'\n") unload(name) importlib.invalidate_caches() m = __import__(name) - self.assertEqual(m.x, 'rewritten') + self.assertEqual(m.x, "rewritten") # Now delete the source file and check the pyc was rewritten unlink(path) unload(name) @@ -875,7 +941,7 @@ def test_pyc_always_writable(self): bytecode_only = path + "c" os.rename(importlib.util.cache_from_source(path), bytecode_only) m = __import__(name) - self.assertEqual(m.x, 'rewritten') + self.assertEqual(m.x, "rewritten") class PycRewritingTests(unittest.TestCase): @@ -901,7 +967,7 @@ def setUp(self): self.sys_path = sys.path[:] self.orig_module = sys.modules.pop(self.module_name, None) os.mkdir(self.dir_name) - with open(self.file_name, "w", encoding='utf-8') as f: + with open(self.file_name, "w", encoding="utf-8") as f: f.write(self.module_source) sys.path.insert(0, self.dir_name) importlib.invalidate_caches() @@ -968,8 +1034,12 @@ def test_foreign_code(self): class PathsTests(unittest.TestCase): - SAMPLES = ('test', 'test\u00e4\u00f6\u00fc\u00df', 'test\u00e9\u00e8', - 'test\u00b0\u00b3\u00b2') + SAMPLES = ( + "test", + "test\u00e4\u00f6\u00fc\u00df", + "test\u00e9\u00e8", + "test\u00b0\u00b3\u00b2", + ) path = TESTFN def setUp(self): @@ -982,26 +1052,28 @@ def tearDown(self): # Regression test for http://bugs.python.org/issue1293. def test_trailing_slash(self): - with open(os.path.join(self.path, 'test_trailing_slash.py'), - 'w', encoding='utf-8') as f: + with open( + os.path.join(self.path, "test_trailing_slash.py"), "w", encoding="utf-8" + ) as f: f.write("testdata = 'test_trailing_slash'") - sys.path.append(self.path+'/') + sys.path.append(self.path + "/") mod = __import__("test_trailing_slash") - self.assertEqual(mod.testdata, 'test_trailing_slash') + self.assertEqual(mod.testdata, "test_trailing_slash") unload("test_trailing_slash") # Regression test for http://bugs.python.org/issue3677. - @unittest.skipUnless(sys.platform == 'win32', 'Windows-specific') + @unittest.skipUnless(sys.platform == "win32", "Windows-specific") def test_UNC_path(self): - with open(os.path.join(self.path, 'test_unc_path.py'), 'w') as f: + with open(os.path.join(self.path, "test_unc_path.py"), "w") as f: f.write("testdata = 'test_unc_path'") importlib.invalidate_caches() # Create the UNC path, like \\myhost\c$\foo\bar. path = os.path.abspath(self.path) import socket + hn = socket.gethostname() drive = path[0] - unc = "\\\\%s\\%s$"%(hn, drive) + unc = "\\\\%s\\%s$" % (hn, drive) unc += path[2:] try: os.listdir(unc) @@ -1014,22 +1086,22 @@ def test_UNC_path(self): try: mod = __import__("test_unc_path") except ImportError as e: - self.fail("could not import 'test_unc_path' from %r: %r" - % (unc, e)) - self.assertEqual(mod.testdata, 'test_unc_path') + self.fail("could not import 'test_unc_path' from %r: %r" % (unc, e)) + self.assertEqual(mod.testdata, "test_unc_path") self.assertTrue(mod.__file__.startswith(unc), mod.__file__) unload("test_unc_path") class RelativeImportTests(unittest.TestCase): - def tearDown(self): unload("test.relimport") + setUp = tearDown def test_relimport_star(self): # This will import * from .test_import. from .. import relimport + self.assertTrue(hasattr(relimport, "RelativeImportTests")) def test_issue3221(self): @@ -1042,19 +1114,19 @@ def check_relative(): exec("from . import relimport", ns) # Check relative import OK with __package__ and __name__ correct - ns = dict(__package__='test', __name__='test.notarealmodule') + ns = dict(__package__="test", __name__="test.notarealmodule") check_relative() # Check relative import OK with only __name__ wrong - ns = dict(__package__='test', __name__='notarealpkg.notarealmodule') + ns = dict(__package__="test", __name__="notarealpkg.notarealmodule") check_relative() # Check relative import fails with only __package__ wrong - ns = dict(__package__='foo', __name__='test.notarealmodule') + ns = dict(__package__="foo", __name__="test.notarealmodule") self.assertRaises(ModuleNotFoundError, check_relative) # Check relative import fails with __package__ and __name__ wrong - ns = dict(__package__='foo', __name__='notarealpkg.notarealmodule') + ns = dict(__package__="foo", __name__="notarealpkg.notarealmodule") self.assertRaises(ModuleNotFoundError, check_relative) # Check relative import fails with package set to a non-string @@ -1063,8 +1135,9 @@ def check_relative(): def test_parentless_import_shadowed_by_global(self): # Test as if this were done from the REPL where this error most commonly occurs (bpo-37409). - script_helper.assert_python_failure('-W', 'ignore', '-c', - "foo = 1; from . import foo") + script_helper.assert_python_failure( + "-W", "ignore", "-c", "foo = 1; from . import foo" + ) def test_absolute_import_without_future(self): # If explicit relative import syntax is used, then do not try @@ -1072,21 +1145,25 @@ def test_absolute_import_without_future(self): # Issue #7902. with self.assertRaises(ImportError): from .os import sep - self.fail("explicit relative import triggered an " - "implicit absolute import") + + self.fail( + "explicit relative import triggered an " "implicit absolute import" + ) def test_import_from_non_package(self): - path = os.path.join(os.path.dirname(__file__), 'data', 'package2') - with uncache('submodule1', 'submodule2'), DirsOnSysPath(path): + path = os.path.join(os.path.dirname(__file__), "data", "package2") + with uncache("submodule1", "submodule2"), DirsOnSysPath(path): with self.assertRaises(ImportError): import submodule1 - self.assertNotIn('submodule1', sys.modules) - self.assertNotIn('submodule2', sys.modules) + self.assertNotIn("submodule1", sys.modules) + self.assertNotIn("submodule2", sys.modules) def test_import_from_unloaded_package(self): - with uncache('package2', 'package2.submodule1', 'package2.submodule2'), \ - DirsOnSysPath(os.path.join(os.path.dirname(__file__), 'data')): + with uncache( + "package2", "package2.submodule1", "package2.submodule2" + ), DirsOnSysPath(os.path.join(os.path.dirname(__file__), "data")): import package2.submodule1 + package2.submodule1.submodule2 @@ -1097,7 +1174,9 @@ def test_override_builtin(self): def foo(): import os + return os + self.assertEqual(foo(), os) # Quick sanity check. with swap_attr(builtins, "__import__", lambda *x: 5): @@ -1115,34 +1194,34 @@ class PycacheTests(unittest.TestCase): def _clean(self): forget(TESTFN) - rmtree('__pycache__') + rmtree("__pycache__") unlink(self.source) def setUp(self): - self.source = TESTFN + '.py' + self.source = TESTFN + ".py" self._clean() - with open(self.source, 'w', encoding='utf-8') as fp: - print('# This is a test file written by test_import.py', file=fp) + with open(self.source, "w", encoding="utf-8") as fp: + print("# This is a test file written by test_import.py", file=fp) sys.path.insert(0, os.curdir) importlib.invalidate_caches() def tearDown(self): - assert sys.path[0] == os.curdir, 'Unexpected sys.path[0]' + assert sys.path[0] == os.curdir, "Unexpected sys.path[0]" del sys.path[0] self._clean() @skip_if_dont_write_bytecode def test_import_pyc_path(self): - self.assertFalse(os.path.exists('__pycache__')) + self.assertFalse(os.path.exists("__pycache__")) __import__(TESTFN) - self.assertTrue(os.path.exists('__pycache__')) + self.assertTrue(os.path.exists("__pycache__")) pyc_path = importlib.util.cache_from_source(self.source) - self.assertTrue(os.path.exists(pyc_path), - 'bytecode file {!r} for {!r} does not ' - 'exist'.format(pyc_path, TESTFN)) + self.assertTrue( + os.path.exists(pyc_path), + "bytecode file {!r} for {!r} does not " "exist".format(pyc_path, TESTFN), + ) - @unittest.skipUnless(os.name == 'posix', - "test meaningful only on posix systems") + @unittest.skipUnless(os.name == "posix", "test meaningful only on posix systems") @skip_if_dont_write_bytecode @os_helper.skip_unless_working_chmod @os_helper.skip_if_dac_override @@ -1152,11 +1231,12 @@ def test_unwritable_directory(self): # unwritable, the import still succeeds but no .pyc file is written. with temp_umask(0o222): __import__(TESTFN) - self.assertTrue(os.path.exists('__pycache__')) + self.assertTrue(os.path.exists("__pycache__")) pyc_path = importlib.util.cache_from_source(self.source) - self.assertFalse(os.path.exists(pyc_path), - 'bytecode file {!r} for {!r} ' - 'exists'.format(pyc_path, TESTFN)) + self.assertFalse( + os.path.exists(pyc_path), + "bytecode file {!r} for {!r} " "exists".format(pyc_path, TESTFN), + ) @skip_if_dont_write_bytecode def test_missing_source(self): @@ -1184,15 +1264,16 @@ def test_missing_source_legacy(self): importlib.invalidate_caches() m = __import__(TESTFN) try: - self.assertEqual(m.__file__, - os.path.join(os.getcwd(), os.path.relpath(pyc_file))) + self.assertEqual( + m.__file__, os.path.join(os.getcwd(), os.path.relpath(pyc_file)) + ) finally: os.remove(pyc_file) def test___cached__(self): # Modules now also have an __cached__ that points to the pyc file. m = __import__(TESTFN) - pyc_file = importlib.util.cache_from_source(TESTFN + '.py') + pyc_file = importlib.util.cache_from_source(TESTFN + ".py") self.assertEqual(m.__cached__, os.path.join(os.getcwd(), pyc_file)) @skip_if_dont_write_bytecode @@ -1208,73 +1289,80 @@ def test___cached___legacy_pyc(self): unload(TESTFN) importlib.invalidate_caches() m = __import__(TESTFN) - self.assertEqual(m.__cached__, - os.path.join(os.getcwd(), os.path.relpath(pyc_file))) + self.assertEqual( + m.__cached__, os.path.join(os.getcwd(), os.path.relpath(pyc_file)) + ) @skip_if_dont_write_bytecode def test_package___cached__(self): # Like test___cached__ but for packages. def cleanup(): - rmtree('pep3147') - unload('pep3147.foo') - unload('pep3147') - os.mkdir('pep3147') + rmtree("pep3147") + unload("pep3147.foo") + unload("pep3147") + + os.mkdir("pep3147") self.addCleanup(cleanup) # Touch the __init__.py - with open(os.path.join('pep3147', '__init__.py'), 'wb'): + with open(os.path.join("pep3147", "__init__.py"), "wb"): pass - with open(os.path.join('pep3147', 'foo.py'), 'wb'): + with open(os.path.join("pep3147", "foo.py"), "wb"): pass importlib.invalidate_caches() - m = __import__('pep3147.foo') + m = __import__("pep3147.foo") init_pyc = importlib.util.cache_from_source( - os.path.join('pep3147', '__init__.py')) + os.path.join("pep3147", "__init__.py") + ) self.assertEqual(m.__cached__, os.path.join(os.getcwd(), init_pyc)) - foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py')) - self.assertEqual(sys.modules['pep3147.foo'].__cached__, - os.path.join(os.getcwd(), foo_pyc)) + foo_pyc = importlib.util.cache_from_source(os.path.join("pep3147", "foo.py")) + self.assertEqual( + sys.modules["pep3147.foo"].__cached__, os.path.join(os.getcwd(), foo_pyc) + ) def test_package___cached___from_pyc(self): # Like test___cached__ but ensuring __cached__ when imported from a # PEP 3147 pyc file. def cleanup(): - rmtree('pep3147') - unload('pep3147.foo') - unload('pep3147') - os.mkdir('pep3147') + rmtree("pep3147") + unload("pep3147.foo") + unload("pep3147") + + os.mkdir("pep3147") self.addCleanup(cleanup) # Touch the __init__.py - with open(os.path.join('pep3147', '__init__.py'), 'wb'): + with open(os.path.join("pep3147", "__init__.py"), "wb"): pass - with open(os.path.join('pep3147', 'foo.py'), 'wb'): + with open(os.path.join("pep3147", "foo.py"), "wb"): pass importlib.invalidate_caches() - m = __import__('pep3147.foo') - unload('pep3147.foo') - unload('pep3147') + m = __import__("pep3147.foo") + unload("pep3147.foo") + unload("pep3147") importlib.invalidate_caches() - m = __import__('pep3147.foo') + m = __import__("pep3147.foo") init_pyc = importlib.util.cache_from_source( - os.path.join('pep3147', '__init__.py')) + os.path.join("pep3147", "__init__.py") + ) self.assertEqual(m.__cached__, os.path.join(os.getcwd(), init_pyc)) - foo_pyc = importlib.util.cache_from_source(os.path.join('pep3147', 'foo.py')) - self.assertEqual(sys.modules['pep3147.foo'].__cached__, - os.path.join(os.getcwd(), foo_pyc)) + foo_pyc = importlib.util.cache_from_source(os.path.join("pep3147", "foo.py")) + self.assertEqual( + sys.modules["pep3147.foo"].__cached__, os.path.join(os.getcwd(), foo_pyc) + ) def test_recompute_pyc_same_second(self): # Even when the source file doesn't change timestamp, a change in # source size is enough to trigger recomputation of the pyc file. __import__(TESTFN) unload(TESTFN) - with open(self.source, 'a', encoding='utf-8') as fp: + with open(self.source, "a", encoding="utf-8") as fp: print("x = 5", file=fp) m = __import__(TESTFN) self.assertEqual(m.x, 5) class TestSymbolicallyLinkedPackage(unittest.TestCase): - package_name = 'sample' - tagged = package_name + '-tagged' + package_name = "sample" + tagged = package_name + "-tagged" def setUp(self): os_helper.rmtree(self.tagged) @@ -1285,7 +1373,7 @@ def setUp(self): # you want to symbolically link it from its untagged name. os.mkdir(self.tagged) self.addCleanup(os_helper.rmtree, self.tagged) - init_file = os.path.join(self.tagged, '__init__.py') + init_file = os.path.join(self.tagged, "__init__.py") os_helper.create_empty_file(init_file) assert os.path.exists(init_file) @@ -1297,22 +1385,22 @@ def setUp(self): self.assertEqual(os.path.isdir(self.package_name), True) - assert os.path.isfile(os.path.join(self.package_name, '__init__.py')) + assert os.path.isfile(os.path.join(self.package_name, "__init__.py")) def tearDown(self): sys.path[:] = self.orig_sys_path # regression test for issue6727 @unittest.skipUnless( - not hasattr(sys, 'getwindowsversion') - or sys.getwindowsversion() >= (6, 0), - "Windows Vista or later required") + not hasattr(sys, "getwindowsversion") or sys.getwindowsversion() >= (6, 0), + "Windows Vista or later required", + ) @os_helper.skip_unless_symlink def test_symlinked_dir_importable(self): # make sure sample can only be imported from the current directory. - sys.path[:] = ['.'] + sys.path[:] = ["."] assert os.path.exists(self.package_name) - assert os.path.exists(os.path.join(self.package_name, '__init__.py')) + assert os.path.exists(os.path.join(self.package_name, "__init__.py")) # Try to import the package importlib.import_module(self.package_name) @@ -1323,31 +1411,34 @@ class ImportlibBootstrapTests(unittest.TestCase): # These tests check that importlib is bootstrapped. def test_frozen_importlib(self): - mod = sys.modules['_frozen_importlib'] + mod = sys.modules["_frozen_importlib"] self.assertTrue(mod) def test_frozen_importlib_is_bootstrap(self): from importlib import _bootstrap - mod = sys.modules['_frozen_importlib'] + + mod = sys.modules["_frozen_importlib"] self.assertIs(mod, _bootstrap) - self.assertEqual(mod.__name__, 'importlib._bootstrap') - self.assertEqual(mod.__package__, 'importlib') - self.assertTrue(mod.__file__.endswith('_bootstrap.py'), mod.__file__) + self.assertEqual(mod.__name__, "importlib._bootstrap") + self.assertEqual(mod.__package__, "importlib") + self.assertTrue(mod.__file__.endswith("_bootstrap.py"), mod.__file__) def test_frozen_importlib_external_is_bootstrap_external(self): from importlib import _bootstrap_external - mod = sys.modules['_frozen_importlib_external'] + + mod = sys.modules["_frozen_importlib_external"] self.assertIs(mod, _bootstrap_external) - self.assertEqual(mod.__name__, 'importlib._bootstrap_external') - self.assertEqual(mod.__package__, 'importlib') - self.assertTrue(mod.__file__.endswith('_bootstrap_external.py'), mod.__file__) + self.assertEqual(mod.__name__, "importlib._bootstrap_external") + self.assertEqual(mod.__package__, "importlib") + self.assertTrue(mod.__file__.endswith("_bootstrap_external.py"), mod.__file__) def test_there_can_be_only_one(self): # Issue #15386 revealed a tricky loophole in the bootstrapping # This test is technically redundant, since the bug caused importing # this test module to crash completely, but it helps prove the point from importlib import machinery - mod = sys.modules['_frozen_importlib'] + + mod = sys.modules["_frozen_importlib"] self.assertIs(machinery.ModuleSpec, mod.ModuleSpec) @@ -1364,29 +1455,28 @@ class GetSourcefileTests(unittest.TestCase): def test_get_sourcefile(self): # Given a valid bytecode path, return the path to the corresponding # source file if it exists. - with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: + with mock.patch("importlib._bootstrap_external._path_isfile") as _path_isfile: _path_isfile.return_value = True - path = TESTFN + '.pyc' - expect = TESTFN + '.py' + path = TESTFN + ".pyc" + expect = TESTFN + ".py" self.assertEqual(_get_sourcefile(path), expect) def test_get_sourcefile_no_source(self): # Given a valid bytecode path without a corresponding source path, # return the original bytecode path. - with mock.patch('importlib._bootstrap_external._path_isfile') as _path_isfile: + with mock.patch("importlib._bootstrap_external._path_isfile") as _path_isfile: _path_isfile.return_value = False - path = TESTFN + '.pyc' + path = TESTFN + ".pyc" self.assertEqual(_get_sourcefile(path), path) def test_get_sourcefile_bad_ext(self): # Given a path with an invalid bytecode extension, return the # bytecode path passed as the argument. - path = TESTFN + '.bad_ext' + path = TESTFN + ".bad_ext" self.assertEqual(_get_sourcefile(path), path) class ImportTracebackTests(unittest.TestCase): - def setUp(self): os.mkdir(TESTFN) self.old_path = sys.path[:] @@ -1398,7 +1488,7 @@ def tearDown(self): def create_module(self, mod, contents, ext=".py"): fname = os.path.join(TESTFN, mod + ext) - with open(fname, "w", encoding='utf-8') as f: + with open(fname, "w", encoding="utf-8") as f: f.write(contents) self.addCleanup(unload, mod) importlib.invalidate_caches() @@ -1434,7 +1524,7 @@ def test_nonexistent_module_nested(self): tb = e.__traceback__ else: self.fail("ImportError should have been raised") - self.assert_traceback(tb, [__file__, 'foo.py']) + self.assert_traceback(tb, [__file__, "foo.py"]) def test_exec_failure(self): self.create_module("foo", "1/0") @@ -1444,7 +1534,7 @@ def test_exec_failure(self): tb = e.__traceback__ else: self.fail("ZeroDivisionError should have been raised") - self.assert_traceback(tb, [__file__, 'foo.py']) + self.assert_traceback(tb, [__file__, "foo.py"]) def test_exec_failure_nested(self): self.create_module("foo", "import bar") @@ -1455,7 +1545,7 @@ def test_exec_failure_nested(self): tb = e.__traceback__ else: self.fail("ZeroDivisionError should have been raised") - self.assert_traceback(tb, [__file__, 'foo.py', 'bar.py']) + self.assert_traceback(tb, [__file__, "foo.py", "bar.py"]) # A few more examples from issue #15425 def test_syntax_error(self): @@ -1474,11 +1564,11 @@ def _setup_broken_package(self, parent, child): pkg_path = os.path.join(TESTFN, pkg_name) os.mkdir(pkg_path) # Touch the __init__.py - init_path = os.path.join(pkg_path, '__init__.py') - with open(init_path, 'w', encoding='utf-8') as f: + init_path = os.path.join(pkg_path, "__init__.py") + with open(init_path, "w", encoding="utf-8") as f: f.write(parent) - bar_path = os.path.join(pkg_path, 'bar.py') - with open(bar_path, 'w', encoding='utf-8') as f: + bar_path = os.path.join(pkg_path, "bar.py") + with open(bar_path, "w", encoding="utf-8") as f: f.write(child) importlib.invalidate_caches() return init_path, bar_path @@ -1528,14 +1618,16 @@ def test_import_bug(self): # We simulate a bug in importlib and check that it's not stripped # away from the traceback. self.create_module("foo", "") - importlib = sys.modules['_frozen_importlib_external'] - if 'load_module' in vars(importlib.SourceLoader): + importlib = sys.modules["_frozen_importlib_external"] + if "load_module" in vars(importlib.SourceLoader): old_exec_module = importlib.SourceLoader.exec_module else: old_exec_module = None try: + def exec_module(*args): - 1/0 + 1 / 0 + importlib.SourceLoader.exec_module = exec_module try: import foo @@ -1543,22 +1635,23 @@ def exec_module(*args): tb = e.__traceback__ else: self.fail("ZeroDivisionError should have been raised") - self.assert_traceback(tb, [__file__, ' 0 + (f"{self.NAME}_with_reinit", False), # m_size == 0 + (f"{self.NAME}_with_state", True), # m_size > 0 ]: self.add_module_cleanup(name) with self.subTest(name=name, has_state=has_state): @@ -2437,24 +2572,24 @@ def test_with_reinit_reloaded(self): self.check_common(reloaded) # Make sure the original __dict__ did not get replaced. - self.assertEqual(id(loaded.module.__dict__), - loaded.snapshot.ns_id) - self.assertEqual(loaded.snapshot.ns.__dict__, - loaded.module.__dict__) + self.assertEqual(id(loaded.module.__dict__), loaded.snapshot.ns_id) + self.assertEqual(loaded.snapshot.ns.__dict__, loaded.module.__dict__) self.assertEqual(reloaded.module.__spec__.name, reloaded.name) - self.assertEqual(reloaded.module.__name__, - reloaded.snapshot.ns.__name__) + self.assertEqual( + reloaded.module.__name__, reloaded.snapshot.ns.__name__ + ) self.assertIsNot(reloaded.module, loaded.module) - self.assertNotEqual(reloaded.module.__dict__, - loaded.module.__dict__) + self.assertNotEqual(reloaded.module.__dict__, loaded.module.__dict__) self.assertIs(reloaded.snapshot.lookedup, reloaded.module) if loaded.snapshot.state_initialized is None: self.assertIs(reloaded.snapshot.state_initialized, None) else: - self.assertGreater(reloaded.snapshot.state_initialized, - loaded.snapshot.state_initialized) + self.assertGreater( + reloaded.snapshot.state_initialized, + loaded.snapshot.state_initialized, + ) self.assertIs(reloaded.snapshot.cached, reloaded.module) @@ -2480,7 +2615,7 @@ def test_basic_multiple_interpreters_main_no_reset(self): main_loaded = self.load(self.NAME) _testsinglephase = main_loaded.module # Attrs set after loading are not in m_copy. - _testsinglephase.spam = 'spam, spam, spam, spam, eggs, and spam' + _testsinglephase.spam = "spam, spam, spam, spam, eggs, and spam" self.check_common(main_loaded) self.check_fresh(main_loaded) @@ -2532,7 +2667,9 @@ def test_basic_multiple_interpreters_main_no_reset(self): # * m_copy was copied from interp2 (was from interp1) # * module's global state was updated, not reset - @no_rerun(reason="rerun not possible; module state is never cleared (see gh-102251)") + @no_rerun( + reason="rerun not possible; module state is never cleared (see gh-102251)" + ) @requires_subinterpreters def test_basic_multiple_interpreters_deleted_no_reset(self): # without resetting; already loaded in a deleted interpreter @@ -2541,7 +2678,7 @@ def test_basic_multiple_interpreters_deleted_no_reset(self): # It's a Py_TRACE_REFS build. # This test breaks interpreter isolation a little, # which causes problems on Py_TRACE_REF builds. - raise unittest.SkipTest('crashes on Py_TRACE_REFS builds') + raise unittest.SkipTest("crashes on Py_TRACE_REFS builds") # At this point: # * alive in 0 interpreters @@ -2569,10 +2706,12 @@ def test_basic_multiple_interpreters_deleted_no_reset(self): # * module's global state was initialized but cleared # Start with an interpreter that gets destroyed right away. - base = self.import_in_subinterp(postscript=''' + base = self.import_in_subinterp( + postscript=""" # Attrs set after loading are not in m_copy. mod.spam = 'spam, spam, mash, spam, eggs, and spam' - ''') + """ + ) self.check_common(base) self.check_fresh(base) @@ -2625,10 +2764,10 @@ def test_basic_multiple_interpreters_reset_each(self): # Use an interpreter that gets destroyed right away. loaded = self.import_in_subinterp( - postscript=''' + postscript=""" # Attrs set after loading are not in m_copy. mod.spam = 'spam, spam, mash, spam, eggs, and spam' - ''', + """, postcleanup=True, ) self.check_common(loaded) @@ -2672,9 +2811,10 @@ def test_pyimport_addmodule(self): # gh-105922: Test PyImport_AddModuleRef(), PyImport_AddModule() # and PyImport_AddModuleObject() import _testcapi + for name in ( - 'sys', # frozen module - 'test', # package + "sys", # frozen module + "test", # package __name__, # package.module ): _testcapi.check_pyimport_addmodule(name) @@ -2682,7 +2822,8 @@ def test_pyimport_addmodule(self): def test_pyimport_addmodule_create(self): # gh-105922: Test PyImport_AddModuleRef(), create a new module import _testcapi - name = 'dontexist' + + name = "dontexist" self.assertNotIn(name, sys.modules) self.addCleanup(unload, name) @@ -2690,6 +2831,6 @@ def test_pyimport_addmodule_create(self): self.assertIs(mod, sys.modules[name]) -if __name__ == '__main__': +if __name__ == "__main__": # Test needs to be a package, so we can do relative imports. unittest.main() diff --git a/Lib/test/test_importlib/_context.py b/Lib/test/test_importlib/_context.py index 8a53eb55d1503b..f9577ad3f5976a 100644 --- a/Lib/test/test_importlib/_context.py +++ b/Lib/test/test_importlib/_context.py @@ -8,6 +8,6 @@ class suppress(contextlib.suppress, contextlib.ContextDecorator): >>> @suppress(KeyError) ... def key_error(): - ... {}[''] + ... {}[""] >>> key_error() """ diff --git a/Lib/test/test_importlib/_path.py b/Lib/test/test_importlib/_path.py index be5782e35279db..8e843acd21b7b7 100644 --- a/Lib/test/test_importlib/_path.py +++ b/Lib/test/test_importlib/_path.py @@ -44,18 +44,18 @@ def build( the content. Content may be a nested directory. >>> spec = { - ... 'README.txt': "A README file", + ... "README.txt": "A README file", ... "foo": { ... "__init__.py": "", ... "bar": { ... "__init__.py": "", ... }, ... "baz.py": "# Some code", - ... } + ... }, ... } - >>> target = getfixture('tmp_path') + >>> target = getfixture("tmp_path") >>> build(spec, target) - >>> target.joinpath('foo/baz.py').read_text(encoding='utf-8') + >>> target.joinpath("foo/baz.py").read_text(encoding="utf-8") '# Some code' """ for name, contents in spec.items(): @@ -88,7 +88,7 @@ class Recording: A TreeMaker object that records everything that would be written. >>> r = Recording() - >>> build({'foo': {'foo1.txt': 'yes'}, 'bar.txt': 'abc'}, r) + >>> build({"foo": {"foo1.txt": "yes"}, "bar.txt": "abc"}, r) >>> r.record ['foo/foo1.txt', 'bar.txt'] """ diff --git a/Lib/test/test_importlib/resources/_path.py b/Lib/test/test_importlib/resources/_path.py index 78cd100edaa397..ef4d7e9dab5df9 100644 --- a/Lib/test/test_importlib/resources/_path.py +++ b/Lib/test/test_importlib/resources/_path.py @@ -18,18 +18,18 @@ def build(spec: FilesSpec, prefix=pathlib.Path()): the content. Content may be a nested directory. >>> spec = { - ... 'README.txt': "A README file", + ... "README.txt": "A README file", ... "foo": { ... "__init__.py": "", ... "bar": { ... "__init__.py": "", ... }, ... "baz.py": "# Some code", - ... } + ... }, ... } - >>> target = getfixture('tmp_path') + >>> target = getfixture("tmp_path") >>> build(spec, target) - >>> target.joinpath('foo/baz.py').read_text(encoding='utf-8') + >>> target.joinpath("foo/baz.py").read_text(encoding="utf-8") '# Some code' """ for name, contents in spec.items(): diff --git a/Lib/test/test_importlib/resources/update-zips.py b/Lib/test/test_importlib/resources/update-zips.py index b2ca0750a5a9bd..176accd6e57f19 100755 --- a/Lib/test/test_importlib/resources/update-zips.py +++ b/Lib/test/test_importlib/resources/update-zips.py @@ -17,9 +17,10 @@ def main(): """ >>> from unittest import mock - >>> monkeypatch = getfixture('monkeypatch') - >>> monkeypatch.setattr(zipfile, 'ZipFile', mock.MagicMock()) - >>> print(); main() # print workaround for bpo-32509 + >>> monkeypatch = getfixture("monkeypatch") + >>> monkeypatch.setattr(zipfile, "ZipFile", mock.MagicMock()) + >>> print() + ... main() # print workaround for bpo-32509 ...data01... -> ziptestdata/... ... diff --git a/Lib/test/test_importlib/test_namespace_pkgs.py b/Lib/test/test_importlib/test_namespace_pkgs.py index 1bdfdbdf410c29..0a7598008fbb0a 100644 --- a/Lib/test/test_importlib/test_namespace_pkgs.py +++ b/Lib/test/test_importlib/test_namespace_pkgs.py @@ -42,8 +42,7 @@ def namespace_tree_context(**kwargs): Save import state and sys.modules cache and restore it on exit. Typical usage: - >>> with namespace_tree_context(path=['/tmp/xxyy/portion1', - ... '/tmp/xxyy/portion2']): + >>> with namespace_tree_context(path=["/tmp/xxyy/portion1", "/tmp/xxyy/portion2"]): ... pass """ # use default meta_path and path_hooks unless specified otherwise diff --git a/Lib/test/test_json/test_enum.py b/Lib/test/test_json/test_enum.py index 10f414898b8935..4722feb42415a0 100644 --- a/Lib/test/test_json/test_enum.py +++ b/Lib/test/test_json/test_enum.py @@ -3,9 +3,10 @@ from test.test_json import PyTest, CTest SMALL = 1 -BIG = 1<<32 -HUGE = 1<<64 -REALLY_HUGE = 1<<96 +BIG = 1 << 32 +HUGE = 1 << 64 +REALLY_HUGE = 1 << 96 + class BigNum(IntEnum): small = SMALL @@ -13,26 +14,30 @@ class BigNum(IntEnum): huge = HUGE really_huge = REALLY_HUGE + E = 2.718281 PI = 3.141593 TAU = 2 * PI + class FloatNum(float, Enum): e = E pi = PI tau = TAU -INF = float('inf') -NEG_INF = float('-inf') -NAN = float('nan') + +INF = float("inf") +NEG_INF = float("-inf") +NAN = float("nan") + class WierdNum(float, Enum): inf = INF neg_inf = NEG_INF nan = NAN -class TestEnum: +class TestEnum: def test_floats(self): for enum in FloatNum: self.assertEqual(self.dumps(enum), repr(enum.value)) @@ -40,7 +45,7 @@ def test_floats(self): self.assertEqual(self.loads(self.dumps(enum)), enum) def test_weird_floats(self): - for enum, expected in zip(WierdNum, ('Infinity', '-Infinity', 'NaN')): + for enum, expected in zip(WierdNum, ("Infinity", "-Infinity", "NaN")): self.assertEqual(self.dumps(enum), expected) if not isnan(enum): self.assertEqual(float(self.dumps(enum)), enum) @@ -56,18 +61,12 @@ def test_ints(self): self.assertEqual(self.loads(self.dumps(enum)), enum) def test_list(self): - self.assertEqual(self.dumps(list(BigNum)), - str([SMALL, BIG, HUGE, REALLY_HUGE])) - self.assertEqual(self.loads(self.dumps(list(BigNum))), - list(BigNum)) - self.assertEqual(self.dumps(list(FloatNum)), - str([E, PI, TAU])) - self.assertEqual(self.loads(self.dumps(list(FloatNum))), - list(FloatNum)) - self.assertEqual(self.dumps(list(WierdNum)), - '[Infinity, -Infinity, NaN]') - self.assertEqual(self.loads(self.dumps(list(WierdNum)))[:2], - list(WierdNum)[:2]) + self.assertEqual(self.dumps(list(BigNum)), str([SMALL, BIG, HUGE, REALLY_HUGE])) + self.assertEqual(self.loads(self.dumps(list(BigNum))), list(BigNum)) + self.assertEqual(self.dumps(list(FloatNum)), str([E, PI, TAU])) + self.assertEqual(self.loads(self.dumps(list(FloatNum))), list(FloatNum)) + self.assertEqual(self.dumps(list(WierdNum)), "[Infinity, -Infinity, NaN]") + self.assertEqual(self.loads(self.dumps(list(WierdNum)))[:2], list(WierdNum)[:2]) self.assertTrue(isnan(self.loads(self.dumps(list(WierdNum)))[2])) def test_dict_keys(self): @@ -75,46 +74,58 @@ def test_dict_keys(self): e, p, t = FloatNum i, j, n = WierdNum d = { - s:'tiny', b:'large', h:'larger', r:'largest', - e:"Euler's number", p:'pi', t:'tau', - i:'Infinity', j:'-Infinity', n:'NaN', - } + s: "tiny", + b: "large", + h: "larger", + r: "largest", + e: "Euler's number", + p: "pi", + t: "tau", + i: "Infinity", + j: "-Infinity", + n: "NaN", + } nd = self.loads(self.dumps(d)) - self.assertEqual(nd[str(SMALL)], 'tiny') - self.assertEqual(nd[str(BIG)], 'large') - self.assertEqual(nd[str(HUGE)], 'larger') - self.assertEqual(nd[str(REALLY_HUGE)], 'largest') + self.assertEqual(nd[str(SMALL)], "tiny") + self.assertEqual(nd[str(BIG)], "large") + self.assertEqual(nd[str(HUGE)], "larger") + self.assertEqual(nd[str(REALLY_HUGE)], "largest") self.assertEqual(nd[repr(E)], "Euler's number") - self.assertEqual(nd[repr(PI)], 'pi') - self.assertEqual(nd[repr(TAU)], 'tau') - self.assertEqual(nd['Infinity'], 'Infinity') - self.assertEqual(nd['-Infinity'], '-Infinity') - self.assertEqual(nd['NaN'], 'NaN') + self.assertEqual(nd[repr(PI)], "pi") + self.assertEqual(nd[repr(TAU)], "tau") + self.assertEqual(nd["Infinity"], "Infinity") + self.assertEqual(nd["-Infinity"], "-Infinity") + self.assertEqual(nd["NaN"], "NaN") def test_dict_values(self): d = dict( - tiny=BigNum.small, - large=BigNum.big, - larger=BigNum.huge, - largest=BigNum.really_huge, - e=FloatNum.e, - pi=FloatNum.pi, - tau=FloatNum.tau, - i=WierdNum.inf, - j=WierdNum.neg_inf, - n=WierdNum.nan, - ) + tiny=BigNum.small, + large=BigNum.big, + larger=BigNum.huge, + largest=BigNum.really_huge, + e=FloatNum.e, + pi=FloatNum.pi, + tau=FloatNum.tau, + i=WierdNum.inf, + j=WierdNum.neg_inf, + n=WierdNum.nan, + ) nd = self.loads(self.dumps(d)) - self.assertEqual(nd['tiny'], SMALL) - self.assertEqual(nd['large'], BIG) - self.assertEqual(nd['larger'], HUGE) - self.assertEqual(nd['largest'], REALLY_HUGE) - self.assertEqual(nd['e'], E) - self.assertEqual(nd['pi'], PI) - self.assertEqual(nd['tau'], TAU) - self.assertEqual(nd['i'], INF) - self.assertEqual(nd['j'], NEG_INF) - self.assertTrue(isnan(nd['n'])) - -class TestPyEnum(TestEnum, PyTest): pass -class TestCEnum(TestEnum, CTest): pass + self.assertEqual(nd["tiny"], SMALL) + self.assertEqual(nd["large"], BIG) + self.assertEqual(nd["larger"], HUGE) + self.assertEqual(nd["largest"], REALLY_HUGE) + self.assertEqual(nd["e"], E) + self.assertEqual(nd["pi"], PI) + self.assertEqual(nd["tau"], TAU) + self.assertEqual(nd["i"], INF) + self.assertEqual(nd["j"], NEG_INF) + self.assertTrue(isnan(nd["n"])) + + +class TestPyEnum(TestEnum, PyTest): + pass + + +class TestCEnum(TestEnum, CTest): + pass diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 225d10c8774d2c..ca67a192392dcd 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -44,15 +44,19 @@ def test_pdb_displayhook(): """This tests the custom displayhook for pdb. >>> def test_function(foo, bar): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... pass - >>> with PdbTestInput([ - ... 'foo', - ... 'bar', - ... 'for i in range(5): print(i)', - ... 'continue', - ... ]): + >>> with PdbTestInput( + ... [ + ... "foo", + ... "bar", + ... "for i in range(5): print(i)", + ... "continue", + ... ] + ... ): ... test_function(1, None) > (3)test_function() -> pass @@ -72,15 +76,15 @@ def test_pdb_displayhook(): def test_pdb_basic_commands(): """Test the basic commands of pdb. - >>> def test_function_2(foo, bar='default'): + >>> def test_function_2(foo, bar="default"): ... print(foo) ... for i in range(5): ... print(i) ... print(bar) ... for i in range(10): ... never_executed - ... print('after for') - ... print('...') + ... print("after for") + ... print("...") ... return foo.upper() >>> def test_function3(arg=None, *, kwonly=None): @@ -90,37 +94,41 @@ def test_pdb_basic_commands(): ... pass >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() - ... ret = test_function_2('baz') + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... ret = test_function_2("baz") ... test_function3(kwonly=True) ... test_function4(1, 2, 3) ... print(ret) - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'step', # entering the function call - ... 'args', # display function args - ... 'list', # list function source - ... 'bt', # display backtrace - ... 'up', # step up to test_function() - ... 'down', # step down to test_function_2() again - ... 'next', # stepping to print(foo) - ... 'next', # stepping to the for loop - ... 'step', # stepping into the for loop - ... 'until', # continuing until out of the for loop - ... 'next', # executing the print(bar) - ... 'jump 8', # jump over second for loop - ... 'return', # return out of function - ... 'retval', # display return value - ... 'next', # step to test_function3() - ... 'step', # stepping into test_function3() - ... 'args', # display function args - ... 'return', # return out of function - ... 'next', # step to test_function4() - ... 'step', # stepping to test_function4() - ... 'args', # display function args - ... 'continue', - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "step", # entering the function call + ... "args", # display function args + ... "list", # list function source + ... "bt", # display backtrace + ... "up", # step up to test_function() + ... "down", # step down to test_function_2() again + ... "next", # stepping to print(foo) + ... "next", # stepping to the for loop + ... "step", # stepping into the for loop + ... "until", # continuing until out of the for loop + ... "next", # executing the print(bar) + ... "jump 8", # jump over second for loop + ... "return", # return out of function + ... "retval", # display return value + ... "next", # step to test_function3() + ... "step", # stepping into test_function3() + ... "args", # display function args + ... "return", # return out of function + ... "next", # step to test_function4() + ... "step", # stepping to test_function4() + ... "args", # display function args + ... "continue", + ... ] + ... ): + ... test_function() > (3)test_function() -> ret = test_function_2('baz') (Pdb) step @@ -229,7 +237,9 @@ def test_pdb_breakpoint_commands(): """Test basic commands related to breakpoints. >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... print(1) ... print(2) ... print(3) @@ -244,39 +254,41 @@ def test_pdb_breakpoint_commands(): the breakpoint list outputs a tab for the "stop only" and "ignore next" lines, which we don't want to put in here. - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'break 3', - ... 'break 4, +', - ... 'disable 1', - ... 'ignore 1 10', - ... 'condition 1 1 < 2', - ... 'condition 1 1 <', - ... 'break 4', - ... 'break 4', - ... 'break', - ... 'clear 3', - ... 'break', - ... 'condition 1', - ... 'enable 1', - ... 'clear 1', - ... 'commands 2', - ... 'p "42"', - ... 'print("42", 7*6)', # Issue 18764 (not about breakpoints) - ... 'end', - ... 'continue', # will stop at breakpoint 2 (line 4) - ... 'clear', # clear all! - ... 'y', - ... 'tbreak 5', - ... 'continue', # will stop at temporary breakpoint - ... 'break', # make sure breakpoint is gone - ... 'commands 10', # out of range - ... 'commands a', # display help - ... 'commands 4', # already deleted - ... 'break 6, undefined', # condition causing `NameError` during evaluation - ... 'continue', # will stop, ignoring runtime error - ... 'continue', - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "break 3", + ... "break 4, +", + ... "disable 1", + ... "ignore 1 10", + ... "condition 1 1 < 2", + ... "condition 1 1 <", + ... "break 4", + ... "break 4", + ... "break", + ... "clear 3", + ... "break", + ... "condition 1", + ... "enable 1", + ... "clear 1", + ... "commands 2", + ... 'p "42"', + ... 'print("42", 7*6)', # Issue 18764 (not about breakpoints) + ... "end", + ... "continue", # will stop at breakpoint 2 (line 4) + ... "clear", # clear all! + ... "y", + ... "tbreak 5", + ... "continue", # will stop at temporary breakpoint + ... "break", # make sure breakpoint is gone + ... "commands 10", # out of range + ... "commands a", # display help + ... "commands 4", # already deleted + ... "break 6, undefined", # condition causing `NameError` during evaluation + ... "continue", # will stop, ignoring runtime error + ... "continue", + ... ] + ... ): + ... test_function() > (3)test_function() -> print(1) (Pdb) break 3 @@ -362,14 +374,16 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions(): """Breakpoints are remembered between interactive sessions >>> reset_Breakpoint() - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'import test.test_pdb', - ... 'break test.test_pdb.do_something', - ... 'break test.test_pdb.do_nothing', - ... 'break', - ... 'continue', - ... ]): - ... pdb.run('print()') + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "import test.test_pdb", + ... "break test.test_pdb.do_something", + ... "break test.test_pdb.do_nothing", + ... "break", + ... "continue", + ... ] + ... ): + ... pdb.run("print()") > (1)()... (Pdb) import test.test_pdb (Pdb) break test.test_pdb.do_something @@ -382,14 +396,16 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions(): 2 breakpoint keep yes at ...test_pdb.py:... (Pdb) continue - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'break', - ... 'break pdb.find_function', - ... 'break', - ... 'clear 1', - ... 'continue', - ... ]): - ... pdb.run('print()') + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "break", + ... "break pdb.find_function", + ... "break", + ... "clear 1", + ... "continue", + ... ] + ... ): + ... pdb.run("print()") > (1)()... (Pdb) break Num Type Disp Enb Where @@ -406,13 +422,15 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions(): Deleted breakpoint 1 at ...test_pdb.py:... (Pdb) continue - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'break', - ... 'clear 2', - ... 'clear 3', - ... 'continue', - ... ]): - ... pdb.run('print()') + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "break", + ... "clear 2", + ... "clear 3", + ... "continue", + ... ] + ... ): + ... pdb.run("print()") > (1)()... (Pdb) break Num Type Disp Enb Where @@ -431,18 +449,22 @@ def test_pdb_pp_repr_exc(): >>> class BadRepr: ... def __repr__(self): - ... raise Exception('repr_exc') + ... raise Exception("repr_exc") >>> obj = BadRepr() >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() - - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'p obj', - ... 'pp obj', - ... 'continue', - ... ]): - ... test_function() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "p obj", + ... "pp obj", + ... "continue", + ... ] + ... ): + ... test_function() --Return-- > (2)test_function()->None -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() @@ -467,40 +489,45 @@ def test_list_commands(): >>> def test_function_2(foo): ... import test.test_pdb + ... ... test.test_pdb.do_nothing() - ... 'some...' - ... 'more...' - ... 'code...' - ... 'to...' - ... 'make...' - ... 'a...' - ... 'long...' - ... 'listing...' - ... 'useful...' - ... '...' - ... '...' + ... "some..." + ... "more..." + ... "code..." + ... "to..." + ... "make..." + ... "a..." + ... "long..." + ... "listing..." + ... "useful..." + ... "..." + ... "..." ... return foo >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() - ... ret = test_function_2('baz') - - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'list', # list first function - ... 'step', # step into second function - ... 'list', # list second function - ... 'list', # continue listing to EOF - ... 'list 1,3', # list specific lines - ... 'list x', # invalid argument - ... 'next', # step to import - ... 'next', # step over import - ... 'step', # step into do_nothing - ... 'longlist', # list all lines - ... 'source do_something', # list all lines of function - ... 'source fooxxx', # something that doesn't exit - ... 'continue', - ... ]): - ... test_function() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... ret = test_function_2("baz") + + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "list", # list first function + ... "step", # step into second function + ... "list", # list second function + ... "list", # continue listing to EOF + ... "list 1,3", # list specific lines + ... "list x", # invalid argument + ... "next", # step to import + ... "next", # step over import + ... "step", # step into do_nothing + ... "longlist", # list all lines + ... "source do_something", # list all lines of function + ... "source fooxxx", # something that doesn't exit + ... "continue", + ... ] + ... ): + ... test_function() > (3)test_function() -> ret = test_function_2('baz') (Pdb) list @@ -561,27 +588,31 @@ def test_list_commands(): def test_pdb_whatis_command(): """Test the whatis command - >>> myvar = (1,2) + >>> myvar = (1, 2) >>> def myfunc(): ... pass >>> class MyClass: - ... def mymethod(self): - ... pass + ... def mymethod(self): + ... pass >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() - - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'whatis myvar', - ... 'whatis myfunc', - ... 'whatis MyClass', - ... 'whatis MyClass()', - ... 'whatis MyClass.mymethod', - ... 'whatis MyClass().mymethod', - ... 'continue', - ... ]): - ... test_function() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "whatis myvar", + ... "whatis myfunc", + ... "whatis MyClass", + ... "whatis MyClass()", + ... "whatis MyClass.mymethod", + ... "whatis MyClass().mymethod", + ... "continue", + ... ] + ... ): + ... test_function() --Return-- > (2)test_function()->None -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() @@ -606,28 +637,32 @@ def test_pdb_display_command(): >>> def test_function(): ... a = 0 - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... a = 1 ... a = 2 ... a = 3 ... a = 4 - >>> with PdbTestInput([ # doctest: +ELLIPSIS - ... 'display +', - ... 'display', - ... 'display a', - ... 'n', - ... 'display', - ... 'undisplay a', - ... 'n', - ... 'display a', - ... 'undisplay', - ... 'display a < 1', - ... 'n', - ... 'display undefined', - ... 'continue', - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS + ... "display +", + ... "display", + ... "display a", + ... "n", + ... "display", + ... "undisplay a", + ... "n", + ... "display a", + ... "undisplay", + ... "display a < 1", + ... "n", + ... "display undefined", + ... "continue", + ... ] + ... ): + ... test_function() > (4)test_function() -> a = 1 (Pdb) display + @@ -667,34 +702,39 @@ def test_pdb_alias_command(): >>> class A: ... def __init__(self): ... self.attr1 = 10 - ... self.attr2 = 'str' + ... self.attr2 = "str" + ... ... def method(self): ... pass >>> def test_function(): ... o = A() - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... o.method() - >>> with PdbTestInput([ # doctest: +ELLIPSIS - ... 'alias pi', - ... 'alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}")', - ... 'alias ps pi self', - ... 'alias ps', - ... 'pi o', - ... 's', - ... 'ps', - ... 'alias myp p %2', - ... 'alias myp', - ... 'alias myp p %1', - ... 'myp', - ... 'myp 1', - ... 'myp 1 2', - ... 'alias repeat_second_arg p "%* %2"', - ... 'repeat_second_arg 1 2 3', - ... 'continue', - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS + ... "alias pi", + ... 'alias pi for k in %1.__dict__.keys(): print(f"%1.{k} = {%1.__dict__[k]}")', + ... "alias ps pi self", + ... "alias ps", + ... "pi o", + ... "s", + ... "ps", + ... "alias myp p %2", + ... "alias myp", + ... "alias myp p %1", + ... "myp", + ... "myp 1", + ... "myp 1 2", + ... 'alias repeat_second_arg p "%* %2"', + ... "repeat_second_arg 1 2 3", + ... "continue", + ... ] + ... ): + ... test_function() > (4)test_function() -> o.method() (Pdb) alias pi @@ -735,22 +775,26 @@ def test_pdb_where_command(): """Test where command >>> def g(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() >>> def f(): - ... g(); + ... g() >>> def test_function(): ... f() - >>> with PdbTestInput([ # doctest: +ELLIPSIS - ... 'w', - ... 'where', - ... 'u', - ... 'w', - ... 'continue', - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS + ... "w", + ... "where", + ... "u", + ... "w", + ... "continue", + ... ] + ... ): + ... test_function() --Return-- > (2)g()->None -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() @@ -795,9 +839,11 @@ def test_convenience_variables(): """Test convenience variables >>> def util_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... try: - ... raise Exception('test') + ... raise Exception("test") ... except: ... pass ... return 1 @@ -805,25 +851,27 @@ def test_convenience_variables(): >>> def test_function(): ... util_function() - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... '$_frame.f_lineno', # Check frame convenience variable - ... '$a = 10', # Set a convenience variable - ... '$a', # Print its value - ... 'p $a + 2', # Do some calculation - ... 'u', # Switch frame - ... '$_frame.f_lineno', # Make sure the frame changed - ... '$a', # Make sure the value persists - ... 'd', # Go back to the original frame - ... 'next', - ... '$a', # The value should be gone - ... 'next', - ... '$_exception', # Check exception convenience variable - ... 'next', - ... '$_exception', # Exception should be gone - ... 'return', - ... '$_retval', # Check return convenience variable - ... 'continue', - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "$_frame.f_lineno", # Check frame convenience variable + ... "$a = 10", # Set a convenience variable + ... "$a", # Print its value + ... "p $a + 2", # Do some calculation + ... "u", # Switch frame + ... "$_frame.f_lineno", # Make sure the frame changed + ... "$a", # Make sure the value persists + ... "d", # Go back to the original frame + ... "next", + ... "$a", # The value should be gone + ... "next", + ... "$_exception", # Check exception convenience variable + ... "next", + ... "$_exception", # Exception should be gone + ... "return", + ... "$_retval", # Check return convenience variable + ... "continue", + ... ] + ... ): ... test_function() > (3)util_function() -> try: @@ -875,43 +923,46 @@ def test_post_mortem_chained(): >>> def test_function_2(): ... try: - ... 1/0 + ... 1 / 0 ... finally: - ... print('Exception!') + ... print("Exception!") >>> def test_function_reraise(): ... try: ... test_function_2() ... except ZeroDivisionError as e: - ... raise ZeroDivisionError('reraised') from e + ... raise ZeroDivisionError("reraised") from e >>> def test_function(): - ... import pdb; + ... import pdb + ... ... instance = pdb.Pdb(nosigint=True, readrc=False) ... try: ... test_function_reraise() ... except Exception as e: ... pdb._post_mortem(e, instance) - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'exceptions', - ... 'exceptions 0', - ... '$_exception', - ... 'up', - ... 'down', - ... 'exceptions 1', - ... '$_exception', - ... 'up', - ... 'down', - ... 'exceptions -1', - ... 'exceptions 3', - ... 'up', - ... 'exit', - ... ]): - ... try: - ... test_function() - ... except ZeroDivisionError: - ... print('Correctly reraised.') + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "exceptions", + ... "exceptions 0", + ... "$_exception", + ... "up", + ... "down", + ... "exceptions 1", + ... "$_exception", + ... "up", + ... "down", + ... "exceptions -1", + ... "exceptions 3", + ... "up", + ... "exit", + ... ] + ... ): + ... try: + ... test_function() + ... except ZeroDivisionError: + ... print("Correctly reraised.") Exception! > (5)test_function_reraise() -> raise ZeroDivisionError('reraised') from e @@ -959,34 +1010,36 @@ def test_post_mortem_cause_no_context(): ... raise type_(*content) from from_ ... except Exception as out: ... return out - ... >>> def main(): ... try: - ... raise ValueError('Context Not Shown') + ... raise ValueError("Context Not Shown") ... except Exception as e1: - ... raise ValueError("With Cause") from make_exc_with_stack(TypeError,'The Cause') + ... raise ValueError("With Cause") from make_exc_with_stack(TypeError, "The Cause") >>> def test_function(): - ... import pdb; + ... import pdb + ... ... instance = pdb.Pdb(nosigint=True, readrc=False) ... try: ... main() ... except Exception as e: ... pdb._post_mortem(e, instance) - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'exceptions', - ... 'exceptions 0', - ... 'exceptions 1', - ... 'up', - ... 'down', - ... 'exit', - ... ]): - ... try: - ... test_function() - ... except ValueError: - ... print('Ok.') + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "exceptions", + ... "exceptions 0", + ... "exceptions 1", + ... "up", + ... "down", + ... "exit", + ... ] + ... ): + ... try: + ... test_function() + ... except ValueError: + ... print("Ok.") > (5)main() -> raise ValueError("With Cause") from make_exc_with_stack(TypeError,'The Cause') (Pdb) exceptions @@ -1013,39 +1066,42 @@ def test_post_mortem_context_of_the_cause(): >>> def main(): ... try: - ... raise TypeError('Context of the cause') + ... raise TypeError("Context of the cause") ... except Exception as e1: ... try: - ... raise ValueError('Root Cause') + ... raise ValueError("Root Cause") ... except Exception as e2: ... ex = e2 ... raise ValueError("With Cause, and cause has context") from ex >>> def test_function(): - ... import pdb; + ... import pdb + ... ... instance = pdb.Pdb(nosigint=True, readrc=False) ... try: ... main() ... except Exception as e: ... pdb._post_mortem(e, instance) - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'exceptions', - ... 'exceptions 2', - ... 'up', - ... 'down', - ... 'exceptions 3', - ... 'up', - ... 'down', - ... 'exceptions 4', - ... 'up', - ... 'down', - ... 'exit', - ... ]): - ... try: - ... test_function() - ... except ValueError: - ... print('Correctly reraised.') + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "exceptions", + ... "exceptions 2", + ... "up", + ... "down", + ... "exceptions 3", + ... "up", + ... "down", + ... "exceptions 4", + ... "up", + ... "down", + ... "exit", + ... ] + ... ): + ... try: + ... test_function() + ... except ValueError: + ... print("Correctly reraised.") > (9)main() -> raise ValueError("With Cause, and cause has context") from ex (Pdb) exceptions @@ -1090,26 +1146,29 @@ def test_post_mortem_from_none(): >>> def main(): ... try: - ... raise TypeError('Context of the cause') + ... raise TypeError("Context of the cause") ... except Exception as e1: ... raise ValueError("With Cause, and cause has context") from None >>> def test_function(): - ... import pdb; + ... import pdb + ... ... instance = pdb.Pdb(nosigint=True, readrc=False) ... try: ... main() ... except Exception as e: ... pdb._post_mortem(e, instance) - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'exceptions', - ... 'exit', - ... ]): - ... try: - ... test_function() - ... except ValueError: - ... print('Correctly reraised.') + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "exceptions", + ... "exit", + ... ] + ... ): + ... try: + ... test_function() + ... except ValueError: + ... print("Correctly reraised.") > (5)main() -> raise ValueError("With Cause, and cause has context") from None (Pdb) exceptions @@ -1128,7 +1187,8 @@ def test_post_mortem_from_no_stack(): >>> def test_function(): - ... import pdb; + ... import pdb + ... ... instance = pdb.Pdb(nosigint=True, readrc=False) ... try: ... main() @@ -1136,14 +1196,12 @@ def test_post_mortem_from_no_stack(): ... pdb._post_mortem(e, instance) >>> with PdbTestInput( # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... ["exceptions", - ... "exceptions 0", - ... "exit"], + ... ["exceptions", "exceptions 0", "exit"], ... ): - ... try: - ... test_function() - ... except ValueError: - ... print('Correctly reraised.') + ... try: + ... test_function() + ... except ValueError: + ... print("Correctly reraised.") > (2)main() -> raise Exception() from Exception() (Pdb) exceptions @@ -1160,19 +1218,21 @@ def test_post_mortem_single_no_stack(): >>> def test_function(): - ... import pdb; + ... import pdb + ... ... instance = pdb.Pdb(nosigint=True, readrc=False) ... import sys + ... ... sys.last_exc = Exception() ... pdb._post_mortem(sys.last_exc, instance) >>> with PdbTestInput( # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE ... [] ... ): - ... try: - ... test_function() - ... except ValueError as e: - ... print(e) + ... try: + ... test_function() + ... except ValueError as e: + ... print(e) A valid traceback must be passed if no exception is being handled """ @@ -1187,14 +1247,12 @@ def test_post_mortem_complex(): ... raise type_(*content) from from_ ... except Exception as out: ... return out - ... >>> def cycle(): ... try: ... raise ValueError("Cycle Leaf") ... except Exception as e: ... raise e from e - ... >>> def tri_cycle(): ... a = make_ex_with_stack(ValueError, "Cycle1") @@ -1205,14 +1263,12 @@ def test_post_mortem_complex(): ... b.__cause__ = c ... ... raise c from a - ... >>> def cause(): ... try: ... raise ValueError("Cause Leaf") ... except Exception as e: ... raise e - ... >>> def context(n=10): ... try: @@ -1222,7 +1278,6 @@ def test_post_mortem_complex(): ... raise ValueError(f"With Context {n}") from e ... else: ... context(n - 1) - ... >>> def main(): ... try: @@ -1236,7 +1291,8 @@ def test_post_mortem_complex(): >>> def test_function(): - ... import pdb; + ... import pdb + ... ... instance = pdb.Pdb(nosigint=True, readrc=False) ... try: ... main() @@ -1244,17 +1300,19 @@ def test_post_mortem_complex(): ... pdb._post_mortem(e, instance) >>> with PdbTestInput( # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... ["exceptions", - ... "exceptions 0", - ... "exceptions 1", - ... "exceptions 2", - ... "exceptions 3", - ... "exit"], + ... [ + ... "exceptions", + ... "exceptions 0", + ... "exceptions 1", + ... "exceptions 2", + ... "exceptions 3", + ... "exit", + ... ], ... ): - ... try: - ... test_function() - ... except ValueError: - ... print('Correctly reraised.') + ... try: + ... test_function() + ... except ValueError: + ... print("Correctly reraised.") > (9)main() -> raise ValueError("With Context and With Cause") from ex (Pdb) exceptions @@ -1283,27 +1341,31 @@ def test_post_mortem(): >>> def test_function_2(): ... try: - ... 1/0 + ... 1 / 0 ... finally: - ... print('Exception!') + ... print("Exception!") >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... test_function_2() - ... print('Not reached.') - - >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE - ... 'next', # step over exception-raising call - ... 'bt', # get a backtrace - ... 'list', # list code of test_function() - ... 'down', # step into test_function_2() - ... 'list', # list code of test_function_2() - ... 'continue', - ... ]): - ... try: - ... test_function() - ... except ZeroDivisionError: - ... print('Correctly reraised.') + ... print("Not reached.") + + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE + ... "next", # step over exception-raising call + ... "bt", # get a backtrace + ... "list", # list code of test_function() + ... "down", # step into test_function_2() + ... "list", # list code of test_function_2() + ... "continue", + ... ] + ... ): + ... try: + ... test_function() + ... except ZeroDivisionError: + ... print("Correctly reraised.") > (3)test_function() -> test_function_2() (Pdb) next @@ -1345,13 +1407,17 @@ def test_pdb_skip_modules(): >>> def skip_module(): ... import string - ... import pdb; pdb.Pdb(skip=['stri*'], nosigint=True, readrc=False).set_trace() - ... string.capwords('FOO') - - >>> with PdbTestInput([ - ... 'step', - ... 'continue', - ... ]): + ... import pdb + ... + ... pdb.Pdb(skip=["stri*"], nosigint=True, readrc=False).set_trace() + ... string.capwords("FOO") + + >>> with PdbTestInput( + ... [ + ... "step", + ... "continue", + ... ] + ... ): ... skip_module() > (4)skip_module() -> string.capwords('FOO') @@ -1367,15 +1433,12 @@ def test_pdb_invalid_arg(): """This tests pdb commands that have invalid arguments >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... pass - >>> with PdbTestInput([ - ... 'a = 3', - ... 'll 4', - ... 'step 1', - ... 'continue' - ... ]): + >>> with PdbTestInput(["a = 3", "ll 4", "step 1", "continue"]): ... test_function() > (3)test_function() -> pass @@ -1403,17 +1466,22 @@ def test_pdb_skip_modules_with_callback(): >>> def skip_module(): ... def callback(): ... return None - ... import pdb; pdb.Pdb(skip=['module_to_skip*'], nosigint=True, readrc=False).set_trace() + ... + ... import pdb + ... + ... pdb.Pdb(skip=["module_to_skip*"], nosigint=True, readrc=False).set_trace() ... mod.foo_pony(callback) - >>> with PdbTestInput([ - ... 'step', - ... 'step', - ... 'step', - ... 'step', - ... 'step', - ... 'continue', - ... ]): + >>> with PdbTestInput( + ... [ + ... "step", + ... "step", + ... "step", + ... "step", + ... "step", + ... "continue", + ... ] + ... ): ... skip_module() ... pass # provides something to "step" to > (5)skip_module() @@ -1444,7 +1512,9 @@ def test_pdb_continue_in_bottomframe(): """Test that "continue" and "next" work properly in bottom frame (issue #5294). >>> def test_function(): - ... import pdb, sys; inst = pdb.Pdb(nosigint=True, readrc=False) + ... import pdb, sys + ... + ... inst = pdb.Pdb(nosigint=True, readrc=False) ... inst.set_trace() ... inst.botframe = sys._getframe() # hackery to get the right botframe ... print(1) @@ -1452,15 +1522,17 @@ def test_pdb_continue_in_bottomframe(): ... print(3) ... print(4) - >>> with PdbTestInput([ # doctest: +ELLIPSIS - ... 'next', - ... 'break 7', - ... 'continue', - ... 'next', - ... 'continue', - ... 'continue', - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS + ... "next", + ... "break 7", + ... "continue", + ... "next", + ... "continue", + ... "continue", + ... ] + ... ): + ... test_function() > (4)test_function() -> inst.botframe = sys._getframe() # hackery to get the right botframe (Pdb) next @@ -1490,14 +1562,18 @@ def pdb_invoke(method, arg): def test_pdb_run_with_incorrect_argument(): """Testing run and runeval with incorrect first argument. - >>> pti = PdbTestInput(['continue',]) + >>> pti = PdbTestInput( + ... [ + ... "continue", + ... ] + ... ) >>> with pti: - ... pdb_invoke('run', lambda x: x) + ... pdb_invoke("run", lambda x: x) Traceback (most recent call last): TypeError: exec() arg 1 must be a string, bytes or code object >>> with pti: - ... pdb_invoke('runeval', lambda x: x) + ... pdb_invoke("runeval", lambda x: x) Traceback (most recent call last): TypeError: eval() arg 1 must be a string, bytes or code object """ @@ -1506,8 +1582,8 @@ def test_pdb_run_with_incorrect_argument(): def test_pdb_run_with_code_object(): """Testing run and runeval with code object as a first argument. - >>> with PdbTestInput(['step','x', 'continue']): # doctest: +ELLIPSIS - ... pdb_invoke('run', compile('x=1', '', 'exec')) + >>> with PdbTestInput(["step", "x", "continue"]): # doctest: +ELLIPSIS + ... pdb_invoke("run", compile("x=1", "", "exec")) > (1)()... (Pdb) step --Return-- @@ -1516,9 +1592,9 @@ def test_pdb_run_with_code_object(): 1 (Pdb) continue - >>> with PdbTestInput(['x', 'continue']): - ... x=0 - ... pdb_invoke('runeval', compile('x+1', '', 'eval')) + >>> with PdbTestInput(["x", "continue"]): + ... x = 0 + ... pdb_invoke("runeval", compile("x+1", "", "eval")) > (1)()->None (Pdb) x 1 @@ -1534,24 +1610,30 @@ def test_next_until_return_at_return_event(): ... x = 2 >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... test_function_2() ... test_function_2() ... test_function_2() ... end = 1 >>> reset_Breakpoint() - >>> with PdbTestInput(['break test_function_2', - ... 'continue', - ... 'return', - ... 'next', - ... 'continue', - ... 'return', - ... 'until', - ... 'continue', - ... 'return', - ... 'return', - ... 'continue']): + >>> with PdbTestInput( + ... [ + ... "break test_function_2", + ... "continue", + ... "return", + ... "next", + ... "continue", + ... "return", + ... "until", + ... "continue", + ... "return", + ... "return", + ... "continue", + ... ] + ... ): ... test_function() > (3)test_function() -> test_function_2() @@ -1600,7 +1682,9 @@ def test_pdb_next_command_for_generator(): ... yield 2 >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... it = test_gen() ... try: ... if next(it) != 0: @@ -1611,14 +1695,7 @@ def test_pdb_next_command_for_generator(): ... raise AssertionError ... print("finished") - >>> with PdbTestInput(['step', - ... 'step', - ... 'step', - ... 'next', - ... 'next', - ... 'step', - ... 'step', - ... 'continue']): + >>> with PdbTestInput(["step", "step", "step", "next", "next", "step", "step", "continue"]): ... test_function() > (3)test_function() -> it = test_gen() @@ -1662,7 +1739,9 @@ def test_pdb_next_command_for_coroutine(): ... await asyncio.sleep(0) >>> async def test_main(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... await test_coro() >>> def test_function(): @@ -1672,13 +1751,7 @@ def test_pdb_next_command_for_coroutine(): ... asyncio.set_event_loop_policy(None) ... print("finished") - >>> with PdbTestInput(['step', - ... 'step', - ... 'next', - ... 'next', - ... 'next', - ... 'step', - ... 'continue']): + >>> with PdbTestInput(["step", "step", "next", "next", "next", "step", "continue"]): ... test_function() > (3)test_main() -> await test_coro() @@ -1723,7 +1796,9 @@ def test_pdb_next_command_for_asyncgen(): ... print(x) >>> async def test_main(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... await test_coro() >>> def test_function(): @@ -1733,13 +1808,7 @@ def test_pdb_next_command_for_asyncgen(): ... asyncio.set_event_loop_policy(None) ... print("finished") - >>> with PdbTestInput(['step', - ... 'step', - ... 'next', - ... 'next', - ... 'step', - ... 'next', - ... 'continue']): + >>> with PdbTestInput(["step", "step", "next", "next", "step", "next", "continue"]): ... test_function() > (3)test_main() -> await test_coro() @@ -1780,7 +1849,9 @@ def test_pdb_return_command_for_generator(): ... yield 2 >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... it = test_gen() ... try: ... if next(it) != 0: @@ -1791,13 +1862,7 @@ def test_pdb_return_command_for_generator(): ... raise AssertionError ... print("finished") - >>> with PdbTestInput(['step', - ... 'step', - ... 'step', - ... 'return', - ... 'step', - ... 'step', - ... 'continue']): + >>> with PdbTestInput(["step", "step", "step", "return", "step", "step", "continue"]): ... test_function() > (3)test_function() -> it = test_gen() @@ -1837,7 +1902,9 @@ def test_pdb_return_command_for_coroutine(): ... await asyncio.sleep(0) >>> async def test_main(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... await test_coro() >>> def test_function(): @@ -1847,10 +1914,7 @@ def test_pdb_return_command_for_coroutine(): ... asyncio.set_event_loop_policy(None) ... print("finished") - >>> with PdbTestInput(['step', - ... 'step', - ... 'next', - ... 'continue']): + >>> with PdbTestInput(["step", "step", "next", "continue"]): ... test_function() > (3)test_main() -> await test_coro() @@ -1879,16 +1943,14 @@ def test_pdb_until_command_for_generator(): ... yield 2 >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... for i in test_gen(): ... print(i) ... print("finished") - >>> with PdbTestInput(['step', - ... 'until 4', - ... 'step', - ... 'step', - ... 'continue']): + >>> with PdbTestInput(["step", "until 4", "step", "step", "continue"]): ... test_function() > (3)test_function() -> for i in test_gen(): @@ -1930,7 +1992,9 @@ def test_pdb_until_command_for_coroutine(): ... print(3) >>> async def test_main(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... await test_coro() >>> def test_function(): @@ -1940,9 +2004,7 @@ def test_pdb_until_command_for_coroutine(): ... asyncio.set_event_loop_policy(None) ... print("finished") - >>> with PdbTestInput(['step', - ... 'until 8', - ... 'continue']): + >>> with PdbTestInput(["step", "until 8", "continue"]): ... test_function() > (3)test_main() -> await test_coro() @@ -1970,18 +2032,15 @@ def test_pdb_next_command_in_generator_for_loop(): ... return 1 >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... for i in test_gen(): - ... print('value', i) + ... print("value", i) ... x = 123 >>> reset_Breakpoint() - >>> with PdbTestInput(['break test_gen', - ... 'continue', - ... 'next', - ... 'next', - ... 'next', - ... 'continue']): + >>> with PdbTestInput(["break test_gen", "continue", "next", "next", "next", "continue"]): ... test_function() > (3)test_function() -> for i in test_gen(): @@ -2017,17 +2076,14 @@ def test_pdb_next_command_subiterator(): ... return x >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... for i in test_gen(): - ... print('value', i) + ... print("value", i) ... x = 123 - >>> with PdbTestInput(['step', - ... 'step', - ... 'next', - ... 'next', - ... 'next', - ... 'continue']): + >>> with PdbTestInput(["step", "step", "next", "next", "next", "continue"]): ... test_function() > (3)test_function() -> for i in test_gen(): @@ -2057,16 +2113,20 @@ def test_pdb_multiline_statement(): """Test for multiline statement >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... pass - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'def f(x):', - ... ' return x * 2', - ... '', - ... 'f(2)', - ... 'c' - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "def f(x):", + ... " return x * 2", + ... "", + ... "f(2)", + ... "c", + ... ] + ... ): ... test_function() > (3)test_function() -> pass @@ -2085,20 +2145,24 @@ def test_pdb_show_attribute_and_item(): >>> def test_function(): ... n = lambda x: x ... c = {"a": 1} - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... pass - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'c["a"]', - ... 'c.get("a")', - ... 'n(1)', - ... 'j=1', - ... 'j+1', - ... 'r"a"', - ... 'next(iter([1]))', - ... 'list((0, 1))', - ... 'c' - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... 'c["a"]', + ... 'c.get("a")', + ... "n(1)", + ... "j=1", + ... "j+1", + ... 'r"a"', + ... "next(iter([1]))", + ... "list((0, 1))", + ... "c", + ... ] + ... ): ... test_function() > (5)test_function() -> pass @@ -2129,12 +2193,11 @@ def test_pdb_issue_20766(): ... while i <= 2: ... sess = pdb.Pdb() ... sess.set_trace(sys._getframe()) - ... print('pdb %d: %s' % (i, sess._previous_sigint_handler)) + ... print("pdb %d: %s" % (i, sess._previous_sigint_handler)) ... i += 1 >>> reset_Breakpoint() - >>> with PdbTestInput(['continue', - ... 'continue']): + >>> with PdbTestInput(["continue", "continue"]): ... test_function() > (6)test_function() -> print('pdb %d: %s' % (i, sess._previous_sigint_handler)) @@ -2151,17 +2214,21 @@ def test_pdb_issue_43318(): """echo breakpoints cleared with filename:lineno >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... print(1) ... print(2) ... print(3) ... print(4) >>> reset_Breakpoint() - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'break 3', - ... 'clear :3', - ... 'continue' - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "break 3", + ... "clear :3", + ... "continue", + ... ] + ... ): ... test_function() > (3)test_function() -> print(1) @@ -2181,27 +2248,29 @@ def test_pdb_issue_gh_91742(): """See GH-91742 >>> def test_function(): - ... __author__ = "pi" - ... __version__ = "3.14" + ... __author__ = "pi" + ... __version__ = "3.14" ... - ... def about(): - ... '''About''' - ... print(f"Author: {__author__!r}", - ... f"Version: {__version__!r}", - ... sep=" ") + ... def about(): + ... '''About''' + ... print(f"Author: {__author__!r}", f"Version: {__version__!r}", sep=" ") ... - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() - ... about() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... about() >>> reset_Breakpoint() - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'step', - ... 'next', - ... 'next', - ... 'jump 5', - ... 'continue' - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "step", + ... "next", + ... "next", + ... "jump 5", + ... "continue", + ... ] + ... ): ... test_function() > (12)test_function() -> about() @@ -2229,29 +2298,33 @@ def test_pdb_issue_gh_94215(): Check that frame_setlineno() does not leak references. >>> def test_function(): - ... def func(): - ... def inner(v): pass - ... inner( - ... 42 - ... ) + ... def func(): + ... def inner(v): + ... pass + ... + ... inner(42) ... - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() - ... func() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... func() >>> reset_Breakpoint() - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'step', - ... 'next', - ... 'next', - ... 'jump 3', - ... 'next', - ... 'next', - ... 'jump 3', - ... 'next', - ... 'next', - ... 'jump 3', - ... 'continue' - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "step", + ... "next", + ... "next", + ... "jump 3", + ... "next", + ... "next", + ... "jump 3", + ... "next", + ... "next", + ... "jump 3", + ... "continue", + ... ] + ... ): ... test_function() > (9)test_function() -> func() @@ -2296,15 +2369,19 @@ def test_pdb_issue_gh_101673(): Make sure ll won't revert local variable assignment >>> def test_function(): - ... a = 1 - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() - - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... '!a = 2', - ... 'll', - ... 'p a', - ... 'continue' - ... ]): + ... a = 1 + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() + + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "!a = 2", + ... "ll", + ... "p a", + ... "continue", + ... ] + ... ): ... test_function() --Return-- > (3)test_function()->None @@ -2325,12 +2402,16 @@ def test_pdb_issue_gh_103225(): Make sure longlist uses 1-based line numbers in frames that correspond to a module - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'longlist', - ... 'continue' - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "longlist", + ... "continue", + ... ] + ... ): ... a = 1 - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... b = 2 > (7)() -> b = 2 @@ -2355,12 +2436,16 @@ def test_pdb_issue_gh_101517(): ... try: ... raise KeyError ... except* Exception as e: - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'continue' - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "continue" + ... ] + ... ): + ... test_function() --Return-- > (None)test_function()->None -> Warning: lineno is None @@ -2373,13 +2458,18 @@ def test_pdb_issue_gh_108976(): Make sure setting f_trace_opcodes = True won't crash pdb >>> def test_function(): ... import sys + ... ... sys._getframe().f_trace_opcodes = True - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... a = 1 - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'continue' - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "continue" + ... ] + ... ): + ... test_function() bdb.Bdb.dispatch: unknown debugging event: 'opcode' > (5)test_function() -> a = 1 @@ -2392,15 +2482,19 @@ def test_pdb_issue_gh_80731(): pdb should correctly print exception info if in an except block. - >>> with PdbTestInput([ # doctest: +ELLIPSIS - ... 'import sys', - ... 'sys.exc_info()', - ... 'continue' - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS + ... "import sys", + ... "sys.exc_info()", + ... "continue", + ... ] + ... ): ... try: - ... raise ValueError('Correct') + ... raise ValueError("Correct") ... except ValueError: - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... pass > (10)() -> pass @@ -2416,13 +2510,17 @@ def test_pdb_ambiguous_statements(): Make sure that ambiguous statements prefixed by '!' are properly disambiguated - >>> with PdbTestInput([ - ... '! n = 42', # disambiguated statement: reassign the name n - ... 'n', # advance the debugger into the print() - ... 'continue' - ... ]): + >>> with PdbTestInput( + ... [ + ... "! n = 42", # disambiguated statement: reassign the name n + ... "n", # advance the debugger into the print() + ... "continue", + ... ] + ... ): ... n = -1 - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... print(f"The value of n is {n}") > (8)() -> print(f"The value of n is {n}") @@ -2444,16 +2542,21 @@ def test_pdb_f_trace_lines(): >>> def test_function(): ... import sys + ... ... frame = sys._getframe() ... frame.f_trace_lines = False - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... if frame.f_trace_lines != False: ... print("f_trace_lines is not reset after continue!") - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE - ... 'continue' - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +NORMALIZE_WHITESPACE + ... "continue" + ... ] + ... ): + ... test_function() > (6)test_function() -> if frame.f_trace_lines != False: (Pdb) continue @@ -2463,10 +2566,10 @@ def test_pdb_f_trace_lines(): def test_pdb_function_break(): """Testing the line number of break on function - >>> def foo(): pass + >>> def foo(): + ... pass >>> def bar(): - ... ... pass >>> def boo(): @@ -2478,16 +2581,20 @@ def test_pdb_function_break(): ... yield 42 >>> def test_function(): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... pass - >>> with PdbTestInput([ # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - ... 'break foo', - ... 'break bar', - ... 'break boo', - ... 'break gen', - ... 'continue' - ... ]): + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE + ... "break foo", + ... "break bar", + ... "break boo", + ... "break gen", + ... "continue", + ... ] + ... ): ... test_function() > (3)test_function() -> pass @@ -2509,26 +2616,34 @@ def test_pdb_issue_gh_65052(): args, retval and display should not crash if the object is not displayable >>> class A: ... def __new__(cls): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... return object.__new__(cls) + ... ... def __init__(self): - ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... import pdb + ... + ... pdb.Pdb(nosigint=True, readrc=False).set_trace() ... self.a = 1 + ... ... def __repr__(self): ... return self.a >>> def test_function(): ... A() - >>> with PdbTestInput([ # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - ... 's', - ... 'retval', - ... 'continue', - ... 'args', - ... 'display self', - ... 'display', - ... 'continue', - ... ]): - ... test_function() + >>> with PdbTestInput( + ... [ # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE + ... "s", + ... "retval", + ... "continue", + ... "args", + ... "display self", + ... "display", + ... "continue", + ... ] + ... ): + ... test_function() > (4)__new__() -> return object.__new__(cls) (Pdb) s diff --git a/Lib/test/test_pkg.py b/Lib/test/test_pkg.py index eed0fd1c6b73fa..4e17d5102d4caa 100644 --- a/Lib/test/test_pkg.py +++ b/Lib/test/test_pkg.py @@ -9,6 +9,7 @@ # Helpers to create and destroy hierarchies. + def cleanout(root): names = os.listdir(root) for name in names: @@ -19,6 +20,7 @@ def cleanout(root): os.remove(fullname) os.rmdir(root) + def fixdir(lst): if "__builtins__" in lst: lst.remove("__builtins__") @@ -44,7 +46,6 @@ def fixdir(lst): class TestPkg(unittest.TestCase): - def setUp(self): self.root = None self.pkgname = None @@ -56,13 +57,12 @@ def tearDown(self): for modulename in self.modules_to_cleanup: if modulename in sys.modules: del sys.modules[modulename] - if self.root: # Only clean if the test was actually run + if self.root: # Only clean if the test was actually run cleanout(self.root) # delete all modules concerning the tested hierarchy if self.pkgname: - modules = [name for name in sys.modules - if self.pkgname in name.split('.')] + modules = [name for name in sys.modules if self.pkgname in name.split(".")] for name in modules: del sys.modules[name] @@ -76,7 +76,7 @@ def mkhier(self, descr): os.mkdir(root) for name, contents in descr: comps = name.split() - self.modules_to_cleanup.add('.'.join(comps)) + self.modules_to_cleanup.add(".".join(comps)) fullname = root for c in comps: fullname = os.path.join(fullname, c) @@ -85,8 +85,8 @@ def mkhier(self, descr): else: with open(fullname, "w") as f: f.write(contents) - if not contents.endswith('\n'): - f.write('\n') + if not contents.endswith("\n"): + f.write("\n") self.root = root # package name is the name of the first item self.pkgname = descr[0][0] @@ -98,17 +98,18 @@ def test_1(self): def test_2(self): hier = [ - ("t2", None), - ("t2 __init__.py", "'doc for t2'"), - ("t2 sub", None), - ("t2 sub __init__.py", ""), - ("t2 sub subsub", None), - ("t2 sub subsub __init__.py", "spam = 1"), + ("t2", None), + ("t2 __init__.py", "'doc for t2'"), + ("t2 sub", None), + ("t2 sub __init__.py", ""), + ("t2 sub subsub", None), + ("t2 sub subsub __init__.py", "spam = 1"), ] self.mkhier(hier) import t2.sub import t2.sub.subsub + self.assertEqual(t2.__name__, "t2") self.assertEqual(t2.sub.__name__, "t2.sub") self.assertEqual(t2.sub.subsub.__name__, "t2.sub.subsub") @@ -125,14 +126,16 @@ def test_2(self): from t2 import sub from t2.sub import subsub from t2.sub.subsub import spam + self.assertEqual(sub.__name__, "t2.sub") self.assertEqual(subsub.__name__, "t2.sub.subsub") self.assertEqual(sub.subsub.__name__, "t2.sub.subsub") - for name in ['spam', 'sub', 'subsub', 't2']: + for name in ["spam", "sub", "subsub", "t2"]: self.assertTrue(locals()["name"], "Failed to import %s" % name) import t2.sub import t2.sub.subsub + self.assertEqual(t2.__name__, "t2") self.assertEqual(t2.sub.__name__, "t2.sub") self.assertEqual(t2.sub.subsub.__name__, "t2.sub.subsub") @@ -145,33 +148,33 @@ def test_2(self): def test_3(self): hier = [ - ("t3", None), - ("t3 __init__.py", ""), - ("t3 sub", None), - ("t3 sub __init__.py", ""), - ("t3 sub subsub", None), - ("t3 sub subsub __init__.py", "spam = 1"), - ] + ("t3", None), + ("t3 __init__.py", ""), + ("t3 sub", None), + ("t3 sub __init__.py", ""), + ("t3 sub subsub", None), + ("t3 sub subsub __init__.py", "spam = 1"), + ] self.mkhier(hier) import t3.sub.subsub + self.assertEqual(t3.__name__, "t3") self.assertEqual(t3.sub.__name__, "t3.sub") self.assertEqual(t3.sub.subsub.__name__, "t3.sub.subsub") def test_4(self): hier = [ - ("t4.py", "raise RuntimeError('Shouldnt load t4.py')"), - ("t4", None), - ("t4 __init__.py", ""), - ("t4 sub.py", "raise RuntimeError('Shouldnt load sub.py')"), - ("t4 sub", None), - ("t4 sub __init__.py", ""), - ("t4 sub subsub.py", - "raise RuntimeError('Shouldnt load subsub.py')"), - ("t4 sub subsub", None), - ("t4 sub subsub __init__.py", "spam = 1"), - ] + ("t4.py", "raise RuntimeError('Shouldnt load t4.py')"), + ("t4", None), + ("t4 __init__.py", ""), + ("t4 sub.py", "raise RuntimeError('Shouldnt load sub.py')"), + ("t4 sub", None), + ("t4 sub __init__.py", ""), + ("t4 sub subsub.py", "raise RuntimeError('Shouldnt load subsub.py')"), + ("t4 sub subsub", None), + ("t4 sub subsub __init__.py", "spam = 1"), + ] self.mkhier(hier) s = """ @@ -182,15 +185,15 @@ def test_4(self): def test_5(self): hier = [ - ("t5", None), - ("t5 __init__.py", "import t5.foo"), - ("t5 string.py", "spam = 1"), - ("t5 foo.py", - "from . import string; assert string.spam == 1"), - ] + ("t5", None), + ("t5 __init__.py", "import t5.foo"), + ("t5 string.py", "spam = 1"), + ("t5 foo.py", "from . import string; assert string.spam == 1"), + ] self.mkhier(hier) import t5 + s = """ from t5 import * self.assertEqual(dir(), ['foo', 'self', 'string', 't5']) @@ -198,33 +201,76 @@ def test_5(self): self.run_code(s) import t5 - self.assertEqual(fixdir(dir(t5)), - ['__cached__', '__doc__', '__file__', '__loader__', - '__name__', '__package__', '__path__', '__spec__', - 'foo', 'string', 't5']) - self.assertEqual(fixdir(dir(t5.foo)), - ['__cached__', '__doc__', '__file__', '__loader__', - '__name__', '__package__', '__spec__', 'string']) - self.assertEqual(fixdir(dir(t5.string)), - ['__cached__', '__doc__', '__file__', '__loader__', - '__name__', '__package__', '__spec__', 'spam']) + + self.assertEqual( + fixdir(dir(t5)), + [ + "__cached__", + "__doc__", + "__file__", + "__loader__", + "__name__", + "__package__", + "__path__", + "__spec__", + "foo", + "string", + "t5", + ], + ) + self.assertEqual( + fixdir(dir(t5.foo)), + [ + "__cached__", + "__doc__", + "__file__", + "__loader__", + "__name__", + "__package__", + "__spec__", + "string", + ], + ) + self.assertEqual( + fixdir(dir(t5.string)), + [ + "__cached__", + "__doc__", + "__file__", + "__loader__", + "__name__", + "__package__", + "__spec__", + "spam", + ], + ) def test_6(self): hier = [ - ("t6", None), - ("t6 __init__.py", - "__all__ = ['spam', 'ham', 'eggs']"), - ("t6 spam.py", ""), - ("t6 ham.py", ""), - ("t6 eggs.py", ""), - ] + ("t6", None), + ("t6 __init__.py", "__all__ = ['spam', 'ham', 'eggs']"), + ("t6 spam.py", ""), + ("t6 ham.py", ""), + ("t6 eggs.py", ""), + ] self.mkhier(hier) import t6 - self.assertEqual(fixdir(dir(t6)), - ['__all__', '__cached__', '__doc__', '__file__', - '__loader__', '__name__', '__package__', '__path__', - '__spec__']) + + self.assertEqual( + fixdir(dir(t6)), + [ + "__all__", + "__cached__", + "__doc__", + "__file__", + "__loader__", + "__name__", + "__package__", + "__path__", + "__spec__", + ], + ) s = """ import t6 from t6 import * @@ -238,59 +284,92 @@ def test_6(self): def test_7(self): hier = [ - ("t7.py", ""), - ("t7", None), - ("t7 __init__.py", ""), - ("t7 sub.py", - "raise RuntimeError('Shouldnt load sub.py')"), - ("t7 sub", None), - ("t7 sub __init__.py", ""), - ("t7 sub .py", - "raise RuntimeError('Shouldnt load subsub.py')"), - ("t7 sub subsub", None), - ("t7 sub subsub __init__.py", - "spam = 1"), - ] + ("t7.py", ""), + ("t7", None), + ("t7 __init__.py", ""), + ("t7 sub.py", "raise RuntimeError('Shouldnt load sub.py')"), + ("t7 sub", None), + ("t7 sub __init__.py", ""), + ("t7 sub .py", "raise RuntimeError('Shouldnt load subsub.py')"), + ("t7 sub subsub", None), + ("t7 sub subsub __init__.py", "spam = 1"), + ] self.mkhier(hier) - t7, sub, subsub = None, None, None import t7 as tas - self.assertEqual(fixdir(dir(tas)), - ['__cached__', '__doc__', '__file__', '__loader__', - '__name__', '__package__', '__path__', '__spec__']) + + self.assertEqual( + fixdir(dir(tas)), + [ + "__cached__", + "__doc__", + "__file__", + "__loader__", + "__name__", + "__package__", + "__path__", + "__spec__", + ], + ) self.assertFalse(t7) from t7 import sub as subpar - self.assertEqual(fixdir(dir(subpar)), - ['__cached__', '__doc__', '__file__', '__loader__', - '__name__', '__package__', '__path__', '__spec__']) + + self.assertEqual( + fixdir(dir(subpar)), + [ + "__cached__", + "__doc__", + "__file__", + "__loader__", + "__name__", + "__package__", + "__path__", + "__spec__", + ], + ) self.assertFalse(t7) self.assertFalse(sub) from t7.sub import subsub as subsubsub - self.assertEqual(fixdir(dir(subsubsub)), - ['__cached__', '__doc__', '__file__', '__loader__', - '__name__', '__package__', '__path__', '__spec__', - 'spam']) + + self.assertEqual( + fixdir(dir(subsubsub)), + [ + "__cached__", + "__doc__", + "__file__", + "__loader__", + "__name__", + "__package__", + "__path__", + "__spec__", + "spam", + ], + ) self.assertFalse(t7) self.assertFalse(sub) self.assertFalse(subsub) from t7.sub.subsub import spam as ham + self.assertEqual(ham, 1) self.assertFalse(t7) self.assertFalse(sub) self.assertFalse(subsub) - @unittest.skipIf(sys.flags.optimize >= 2, - "Docstrings are omitted with -O2 and above") + @unittest.skipIf( + sys.flags.optimize >= 2, "Docstrings are omitted with -O2 and above" + ) def test_8(self): hier = [ - ("t8", None), - ("t8 __init__"+os.extsep+"py", "'doc for t8'"), - ] + ("t8", None), + ("t8 __init__" + os.extsep + "py", "'doc for t8'"), + ] self.mkhier(hier) import t8 + self.assertEqual(t8.__doc__, "doc for t8") + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index f113e17fef4abf..ed3038b080795f 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -43,21 +43,21 @@ def sign(x): def _nan_equal(a, b): """Return True if a and b are both the same kind of NAN. - >>> _nan_equal(Decimal('NAN'), Decimal('NAN')) + >>> _nan_equal(Decimal("NAN"), Decimal("NAN")) True - >>> _nan_equal(Decimal('sNAN'), Decimal('sNAN')) + >>> _nan_equal(Decimal("sNAN"), Decimal("sNAN")) True - >>> _nan_equal(Decimal('NAN'), Decimal('sNAN')) + >>> _nan_equal(Decimal("NAN"), Decimal("sNAN")) False - >>> _nan_equal(Decimal(42), Decimal('NAN')) + >>> _nan_equal(Decimal(42), Decimal("NAN")) False - >>> _nan_equal(float('NAN'), float('NAN')) + >>> _nan_equal(float("NAN"), float("NAN")) True - >>> _nan_equal(float('NAN'), 0.5) + >>> _nan_equal(float("NAN"), 0.5) False - >>> _nan_equal(float('NAN'), Decimal('NAN')) + >>> _nan_equal(float("NAN"), Decimal("NAN")) False NAN payloads are not compared. @@ -229,14 +229,14 @@ def assertApproxEqual(self, first, second, tol=None, rel=None, msg=None): >>> class MyTest(NumericTestCase): ... def test_number(self): - ... x = 1.0/6 - ... y = sum([x]*6) + ... x = 1.0 / 6 + ... y = sum([x] * 6) ... self.assertApproxEqual(y, 1.0, tol=1e-15) + ... ... def test_sequence(self): ... a = [1.001, 1.001e-10, 1.001e10] ... b = [1.0, 1e-10, 1e10] ... self.assertApproxEqual(a, b, rel=1e-3) - ... >>> import unittest >>> from io import StringIO # Suppress test runner output. >>> suite = unittest.TestLoader().loadTestsFromTestCase(MyTest) diff --git a/Lib/test/test_yield_from.py b/Lib/test/test_yield_from.py index 1a60357a1bcd62..72449938d6356e 100644 --- a/Lib/test/test_yield_from.py +++ b/Lib/test/test_yield_from.py @@ -13,6 +13,7 @@ from test.support import captured_stderr, disable_gc, gc_collect from test import support + class TestPEP380Operation(unittest.TestCase): """ Test semantics. @@ -23,41 +24,50 @@ def test_delegation_of_initial_next_to_subgenerator(self): Test delegation of initial next() call to subgenerator """ trace = [] + def g1(): trace.append("Starting g1") yield from g2() trace.append("Finishing g1") + def g2(): trace.append("Starting g2") yield 42 trace.append("Finishing g2") + for x in g1(): trace.append("Yielded %s" % (x,)) - self.assertEqual(trace,[ - "Starting g1", - "Starting g2", - "Yielded 42", - "Finishing g2", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Starting g2", + "Yielded 42", + "Finishing g2", + "Finishing g1", + ], + ) def test_raising_exception_in_initial_next_call(self): """ Test raising exception in initial next() call """ trace = [] + def g1(): try: trace.append("Starting g1") yield from g2() finally: trace.append("Finishing g1") + def g2(): try: trace.append("Starting g2") raise ValueError("spanish inquisition occurred") finally: trace.append("Finishing g2") + try: for x in g1(): trace.append("Yielded %s" % (x,)) @@ -65,47 +75,57 @@ def g2(): self.assertEqual(e.args[0], "spanish inquisition occurred") else: self.fail("subgenerator failed to raise ValueError") - self.assertEqual(trace,[ - "Starting g1", - "Starting g2", - "Finishing g2", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Starting g2", + "Finishing g2", + "Finishing g1", + ], + ) def test_delegation_of_next_call_to_subgenerator(self): """ Test delegation of next() call to subgenerator """ trace = [] + def g1(): trace.append("Starting g1") yield "g1 ham" yield from g2() yield "g1 eggs" trace.append("Finishing g1") + def g2(): trace.append("Starting g2") yield "g2 spam" yield "g2 more spam" trace.append("Finishing g2") + for x in g1(): trace.append("Yielded %s" % (x,)) - self.assertEqual(trace,[ - "Starting g1", - "Yielded g1 ham", - "Starting g2", - "Yielded g2 spam", - "Yielded g2 more spam", - "Finishing g2", - "Yielded g1 eggs", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Yielded g1 ham", + "Starting g2", + "Yielded g2 spam", + "Yielded g2 more spam", + "Finishing g2", + "Yielded g1 eggs", + "Finishing g1", + ], + ) def test_raising_exception_in_delegated_next_call(self): """ Test raising exception in delegated next() call """ trace = [] + def g1(): try: trace.append("Starting g1") @@ -114,6 +134,7 @@ def g1(): yield "g1 eggs" finally: trace.append("Finishing g1") + def g2(): try: trace.append("Starting g2") @@ -122,6 +143,7 @@ def g2(): yield "g2 more spam" finally: trace.append("Finishing g2") + try: for x in g1(): trace.append("Yielded %s" % (x,)) @@ -129,20 +151,24 @@ def g2(): self.assertEqual(e.args[0], "hovercraft is full of eels") else: self.fail("subgenerator failed to raise ValueError") - self.assertEqual(trace,[ - "Starting g1", - "Yielded g1 ham", - "Starting g2", - "Yielded g2 spam", - "Finishing g2", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Yielded g1 ham", + "Starting g2", + "Yielded g2 spam", + "Finishing g2", + "Finishing g1", + ], + ) def test_delegation_of_send(self): """ Test delegation of send() """ trace = [] + def g1(): trace.append("Starting g1") x = yield "g1 ham" @@ -151,6 +177,7 @@ def g1(): x = yield "g1 eggs" trace.append("g1 received %s" % (x,)) trace.append("Finishing g1") + def g2(): trace.append("Starting g2") x = yield "g2 spam" @@ -158,6 +185,7 @@ def g2(): x = yield "g2 more spam" trace.append("g2 received %s" % (x,)) trace.append("Finishing g2") + g = g1() y = next(g) x = 1 @@ -168,25 +196,29 @@ def g2(): x += 1 except StopIteration: pass - self.assertEqual(trace,[ - "Starting g1", - "g1 received 1", - "Starting g2", - "Yielded g2 spam", - "g2 received 2", - "Yielded g2 more spam", - "g2 received 3", - "Finishing g2", - "Yielded g1 eggs", - "g1 received 4", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "g1 received 1", + "Starting g2", + "Yielded g2 spam", + "g2 received 2", + "Yielded g2 more spam", + "g2 received 3", + "Finishing g2", + "Yielded g1 eggs", + "g1 received 4", + "Finishing g1", + ], + ) def test_handling_exception_while_delegating_send(self): """ Test handling exception while delegating 'send' """ trace = [] + def g1(): trace.append("Starting g1") x = yield "g1 ham" @@ -195,6 +227,7 @@ def g1(): x = yield "g1 eggs" trace.append("g1 received %s" % (x,)) trace.append("Finishing g1") + def g2(): trace.append("Starting g2") x = yield "g2 spam" @@ -203,6 +236,7 @@ def g2(): x = yield "g2 more spam" trace.append("g2 received %s" % (x,)) trace.append("Finishing g2") + def run(): g = g1() y = next(g) @@ -214,20 +248,25 @@ def run(): x += 1 except StopIteration: trace.append("StopIteration") - self.assertRaises(ValueError,run) - self.assertEqual(trace,[ - "Starting g1", - "g1 received 1", - "Starting g2", - "Yielded g2 spam", - "g2 received 2", - ]) + + self.assertRaises(ValueError, run) + self.assertEqual( + trace, + [ + "Starting g1", + "g1 received 1", + "Starting g2", + "Yielded g2 spam", + "g2 received 2", + ], + ) def test_delegating_close(self): """ Test delegating 'close' """ trace = [] + def g1(): try: trace.append("Starting g1") @@ -236,6 +275,7 @@ def g1(): yield "g1 eggs" finally: trace.append("Finishing g1") + def g2(): try: trace.append("Starting g2") @@ -243,25 +283,30 @@ def g2(): yield "g2 more spam" finally: trace.append("Finishing g2") + g = g1() for i in range(2): x = next(g) trace.append("Yielded %s" % (x,)) g.close() - self.assertEqual(trace,[ - "Starting g1", - "Yielded g1 ham", - "Starting g2", - "Yielded g2 spam", - "Finishing g2", - "Finishing g1" - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Yielded g1 ham", + "Starting g2", + "Yielded g2 spam", + "Finishing g2", + "Finishing g1", + ], + ) def test_handing_exception_while_delegating_close(self): """ Test handling exception while delegating 'close' """ trace = [] + def g1(): try: trace.append("Starting g1") @@ -270,6 +315,7 @@ def g1(): yield "g1 eggs" finally: trace.append("Finishing g1") + def g2(): try: trace.append("Starting g2") @@ -278,6 +324,7 @@ def g2(): finally: trace.append("Finishing g2") raise ValueError("nybbles have exploded with delight") + try: g = g1() for i in range(2): @@ -289,20 +336,24 @@ def g2(): self.assertIsInstance(e.__context__, GeneratorExit) else: self.fail("subgenerator failed to raise ValueError") - self.assertEqual(trace,[ - "Starting g1", - "Yielded g1 ham", - "Starting g2", - "Yielded g2 spam", - "Finishing g2", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Yielded g1 ham", + "Starting g2", + "Yielded g2 spam", + "Finishing g2", + "Finishing g1", + ], + ) def test_delegating_throw(self): """ Test delegating 'throw' """ trace = [] + def g1(): try: trace.append("Starting g1") @@ -311,6 +362,7 @@ def g1(): yield "g1 eggs" finally: trace.append("Finishing g1") + def g2(): try: trace.append("Starting g2") @@ -318,6 +370,7 @@ def g2(): yield "g2 more spam" finally: trace.append("Finishing g2") + try: g = g1() for i in range(2): @@ -329,55 +382,64 @@ def g2(): self.assertEqual(e.args[0], "tomato ejected") else: self.fail("subgenerator failed to raise ValueError") - self.assertEqual(trace,[ - "Starting g1", - "Yielded g1 ham", - "Starting g2", - "Yielded g2 spam", - "Finishing g2", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Yielded g1 ham", + "Starting g2", + "Yielded g2 spam", + "Finishing g2", + "Finishing g1", + ], + ) def test_value_attribute_of_StopIteration_exception(self): """ Test 'value' attribute of StopIteration exception """ trace = [] + def pex(e): trace.append("%s: %s" % (e.__class__.__name__, e)) trace.append("value = %s" % (e.value,)) + e = StopIteration() pex(e) e = StopIteration("spam") pex(e) e.value = "eggs" pex(e) - self.assertEqual(trace,[ - "StopIteration: ", - "value = None", - "StopIteration: spam", - "value = spam", - "StopIteration: spam", - "value = eggs", - ]) - + self.assertEqual( + trace, + [ + "StopIteration: ", + "value = None", + "StopIteration: spam", + "value = spam", + "StopIteration: spam", + "value = eggs", + ], + ) def test_exception_value_crash(self): # There used to be a refcount error when the return value # stored in the StopIteration has a refcount of 1. def g1(): yield from g2() + def g2(): yield "g2" return [42] - self.assertEqual(list(g1()), ["g2"]) + self.assertEqual(list(g1()), ["g2"]) def test_generator_return_value(self): """ Test generator return value """ trace = [] + def g1(): trace.append("Starting g1") yield "g1 ham" @@ -388,80 +450,95 @@ def g1(): trace.append("g2 returned %r" % (ret,)) yield "g1 eggs" trace.append("Finishing g1") - def g2(v = None): + + def g2(v=None): trace.append("Starting g2") yield "g2 spam" yield "g2 more spam" trace.append("Finishing g2") if v: return v + for x in g1(): trace.append("Yielded %s" % (x,)) - self.assertEqual(trace,[ - "Starting g1", - "Yielded g1 ham", - "Starting g2", - "Yielded g2 spam", - "Yielded g2 more spam", - "Finishing g2", - "g2 returned None", - "Starting g2", - "Yielded g2 spam", - "Yielded g2 more spam", - "Finishing g2", - "g2 returned 1", - "Starting g2", - "Yielded g2 spam", - "Yielded g2 more spam", - "Finishing g2", - "g2 returned (2,)", - "Starting g2", - "Yielded g2 spam", - "Yielded g2 more spam", - "Finishing g2", - "g2 returned StopIteration(3)", - "Yielded g1 eggs", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Yielded g1 ham", + "Starting g2", + "Yielded g2 spam", + "Yielded g2 more spam", + "Finishing g2", + "g2 returned None", + "Starting g2", + "Yielded g2 spam", + "Yielded g2 more spam", + "Finishing g2", + "g2 returned 1", + "Starting g2", + "Yielded g2 spam", + "Yielded g2 more spam", + "Finishing g2", + "g2 returned (2,)", + "Starting g2", + "Yielded g2 spam", + "Yielded g2 more spam", + "Finishing g2", + "g2 returned StopIteration(3)", + "Yielded g1 eggs", + "Finishing g1", + ], + ) def test_delegation_of_next_to_non_generator(self): """ Test delegation of next() to non-generator """ trace = [] + def g(): yield from range(3) + for x in g(): trace.append("Yielded %s" % (x,)) - self.assertEqual(trace,[ - "Yielded 0", - "Yielded 1", - "Yielded 2", - ]) - + self.assertEqual( + trace, + [ + "Yielded 0", + "Yielded 1", + "Yielded 2", + ], + ) def test_conversion_of_sendNone_to_next(self): """ Test conversion of send(None) to next() """ trace = [] + def g(): yield from range(3) + gi = g() for x in range(3): y = gi.send(None) trace.append("Yielded: %s" % (y,)) - self.assertEqual(trace,[ - "Yielded: 0", - "Yielded: 1", - "Yielded: 2", - ]) + self.assertEqual( + trace, + [ + "Yielded: 0", + "Yielded: 1", + "Yielded: 2", + ], + ) def test_delegation_of_close_to_non_generator(self): """ Test delegation of close() to non-generator """ trace = [] + def g(): try: trace.append("starting g") @@ -469,27 +546,33 @@ def g(): trace.append("g should not be here") finally: trace.append("finishing g") + gi = g() next(gi) with captured_stderr() as output: gi.close() - self.assertEqual(output.getvalue(), '') - self.assertEqual(trace,[ - "starting g", - "finishing g", - ]) + self.assertEqual(output.getvalue(), "") + self.assertEqual( + trace, + [ + "starting g", + "finishing g", + ], + ) def test_delegating_throw_to_non_generator(self): """ Test delegating 'throw' to non-generator """ trace = [] + def g(): try: trace.append("Starting g") yield from range(10) finally: trace.append("Finishing g") + try: gi = g() for i in range(5): @@ -498,24 +581,28 @@ def g(): e = ValueError("tomato ejected") gi.throw(e) except ValueError as e: - self.assertEqual(e.args[0],"tomato ejected") + self.assertEqual(e.args[0], "tomato ejected") else: self.fail("subgenerator failed to raise ValueError") - self.assertEqual(trace,[ - "Starting g", - "Yielded 0", - "Yielded 1", - "Yielded 2", - "Yielded 3", - "Yielded 4", - "Finishing g", - ]) + self.assertEqual( + trace, + [ + "Starting g", + "Yielded 0", + "Yielded 1", + "Yielded 2", + "Yielded 3", + "Yielded 4", + "Finishing g", + ], + ) def test_attempting_to_send_to_non_generator(self): """ Test attempting to send to non-generator """ trace = [] + def g(): try: trace.append("starting g") @@ -523,6 +610,7 @@ def g(): trace.append("g should not be here") finally: trace.append("finishing g") + try: gi = g() next(gi) @@ -533,22 +621,28 @@ def g(): self.assertIn("send", e.args[0]) else: self.fail("was able to send into non-generator") - self.assertEqual(trace,[ - "starting g", - "finishing g", - ]) + self.assertEqual( + trace, + [ + "starting g", + "finishing g", + ], + ) def test_broken_getattr_handling(self): """ Test subiterator with a broken getattr implementation """ + class Broken: def __iter__(self): return self + def __next__(self): return 1 + def __getattr__(self, attr): - 1/0 + 1 / 0 def g(): yield from Broken() @@ -575,25 +669,28 @@ def test_exception_in_initial_next_call(self): Test exception in initial next() call """ trace = [] + def g1(): trace.append("g1 about to yield from g2") yield from g2() trace.append("g1 should not be here") + def g2(): - yield 1/0 + yield 1 / 0 + def run(): gi = g1() next(gi) - self.assertRaises(ZeroDivisionError,run) - self.assertEqual(trace,[ - "g1 about to yield from g2" - ]) + + self.assertRaises(ZeroDivisionError, run) + self.assertEqual(trace, ["g1 about to yield from g2"]) def test_attempted_yield_from_loop(self): """ Test attempted yield-from loop """ trace = [] + def g1(): trace.append("g1: starting") yield "y1" @@ -607,28 +704,33 @@ def g2(): trace.append("g2: about to yield from g1") yield from gi trace.append("g2 should not be here") + try: gi = g1() for y in gi: trace.append("Yielded: %s" % (y,)) except ValueError as e: - self.assertEqual(e.args[0],"generator already executing") + self.assertEqual(e.args[0], "generator already executing") else: self.fail("subgenerator didn't raise ValueError") - self.assertEqual(trace,[ - "g1: starting", - "Yielded: y1", - "g1: about to yield from g2", - "g2: starting", - "Yielded: y2", - "g2: about to yield from g1", - ]) + self.assertEqual( + trace, + [ + "g1: starting", + "Yielded: y1", + "g1: about to yield from g2", + "g2: starting", + "Yielded: y2", + "g2: about to yield from g1", + ], + ) def test_returning_value_from_delegated_throw(self): """ Test returning value from delegated 'throw' """ trace = [] + def g1(): try: trace.append("Starting g1") @@ -637,6 +739,7 @@ def g1(): yield "g1 eggs" finally: trace.append("Finishing g1") + def g2(): try: trace.append("Starting g2") @@ -646,8 +749,10 @@ def g2(): trace.append("Caught LunchError in g2") yield "g2 lunch saved" yield "g2 yet more spam" + class LunchError(Exception): pass + g = g1() for i in range(2): x = next(g) @@ -656,22 +761,26 @@ class LunchError(Exception): g.throw(e) for x in g: trace.append("Yielded %s" % (x,)) - self.assertEqual(trace,[ - "Starting g1", - "Yielded g1 ham", - "Starting g2", - "Yielded g2 spam", - "Caught LunchError in g2", - "Yielded g2 yet more spam", - "Yielded g1 eggs", - "Finishing g1", - ]) + self.assertEqual( + trace, + [ + "Starting g1", + "Yielded g1 ham", + "Starting g2", + "Yielded g2 spam", + "Caught LunchError in g2", + "Yielded g2 yet more spam", + "Yielded g1 eggs", + "Finishing g1", + ], + ) def test_next_and_return_with_value(self): """ Test next and return with value """ trace = [] + def f(r): gi = g(r) next(gi) @@ -681,39 +790,45 @@ def f(r): trace.append("f SHOULD NOT BE HERE") except StopIteration as e: trace.append("f caught %r" % (e,)) + def g(r): trace.append("g starting") yield trace.append("g returning %r" % (r,)) return r + f(None) f(1) f((2,)) f(StopIteration(3)) - self.assertEqual(trace,[ - "g starting", - "f resuming g", - "g returning None", - "f caught StopIteration()", - "g starting", - "f resuming g", - "g returning 1", - "f caught StopIteration(1)", - "g starting", - "f resuming g", - "g returning (2,)", - "f caught StopIteration((2,))", - "g starting", - "f resuming g", - "g returning StopIteration(3)", - "f caught StopIteration(StopIteration(3))", - ]) + self.assertEqual( + trace, + [ + "g starting", + "f resuming g", + "g returning None", + "f caught StopIteration()", + "g starting", + "f resuming g", + "g returning 1", + "f caught StopIteration(1)", + "g starting", + "f resuming g", + "g returning (2,)", + "f caught StopIteration((2,))", + "g starting", + "f resuming g", + "g returning StopIteration(3)", + "f caught StopIteration(StopIteration(3))", + ], + ) def test_send_and_return_with_value(self): """ Test send and return with value """ trace = [] + def f(r): gi = g(r) next(gi) @@ -723,44 +838,50 @@ def f(r): trace.append("f SHOULD NOT BE HERE") except StopIteration as e: trace.append("f caught %r" % (e,)) + def g(r): trace.append("g starting") x = yield trace.append("g received %r" % (x,)) trace.append("g returning %r" % (r,)) return r + f(None) f(1) f((2,)) f(StopIteration(3)) - self.assertEqual(trace, [ - "g starting", - "f sending spam to g", - "g received 'spam'", - "g returning None", - "f caught StopIteration()", - "g starting", - "f sending spam to g", - "g received 'spam'", - "g returning 1", - 'f caught StopIteration(1)', - 'g starting', - 'f sending spam to g', - "g received 'spam'", - 'g returning (2,)', - 'f caught StopIteration((2,))', - 'g starting', - 'f sending spam to g', - "g received 'spam'", - 'g returning StopIteration(3)', - 'f caught StopIteration(StopIteration(3))' - ]) + self.assertEqual( + trace, + [ + "g starting", + "f sending spam to g", + "g received 'spam'", + "g returning None", + "f caught StopIteration()", + "g starting", + "f sending spam to g", + "g received 'spam'", + "g returning 1", + "f caught StopIteration(1)", + "g starting", + "f sending spam to g", + "g received 'spam'", + "g returning (2,)", + "f caught StopIteration((2,))", + "g starting", + "f sending spam to g", + "g received 'spam'", + "g returning StopIteration(3)", + "f caught StopIteration(StopIteration(3))", + ], + ) def test_catching_exception_from_subgen_and_returning(self): """ Test catching an exception thrown into a subgenerator and returning a value """ + def inner(): try: yield 1 @@ -778,12 +899,15 @@ def outer(): g = outer() trace.append(next(g)) trace.append(repr(g.throw(ValueError))) - self.assertEqual(trace, [ - 1, - "inner caught ValueError", - "inner returned %r to outer" % (value,), - repr(value), - ]) + self.assertEqual( + trace, + [ + 1, + "inner caught ValueError", + "inner returned %r to outer" % (value,), + repr(value), + ], + ) def test_throwing_GeneratorExit_into_subgen_that_returns(self): """ @@ -791,6 +915,7 @@ def test_throwing_GeneratorExit_into_subgen_that_returns(self): catches it and returns normally. """ trace = [] + def f(): try: trace.append("Enter f") @@ -798,10 +923,12 @@ def f(): trace.append("Exit f") except GeneratorExit: return + def g(): trace.append("Enter g") yield from f() trace.append("Exit g") + try: gi = g() next(gi) @@ -810,10 +937,13 @@ def g(): pass else: self.fail("subgenerator failed to raise GeneratorExit") - self.assertEqual(trace,[ - "Enter g", - "Enter f", - ]) + self.assertEqual( + trace, + [ + "Enter g", + "Enter f", + ], + ) def test_throwing_GeneratorExit_into_subgenerator_that_yields(self): """ @@ -821,6 +951,7 @@ def test_throwing_GeneratorExit_into_subgenerator_that_yields(self): catches it and yields. """ trace = [] + def f(): try: trace.append("Enter f") @@ -828,10 +959,12 @@ def f(): trace.append("Exit f") except GeneratorExit: yield + def g(): trace.append("Enter g") yield from f() trace.append("Exit g") + try: gi = g() next(gi) @@ -840,10 +973,13 @@ def g(): self.assertEqual(e.args[0], "generator ignored GeneratorExit") else: self.fail("subgenerator failed to raise GeneratorExit") - self.assertEqual(trace,[ - "Enter g", - "Enter f", - ]) + self.assertEqual( + trace, + [ + "Enter g", + "Enter f", + ], + ) def test_throwing_GeneratorExit_into_subgen_that_raises(self): """ @@ -851,6 +987,7 @@ def test_throwing_GeneratorExit_into_subgen_that_raises(self): catches it and raises a different exception. """ trace = [] + def f(): try: trace.append("Enter f") @@ -858,10 +995,12 @@ def f(): trace.append("Exit f") except GeneratorExit: raise ValueError("Vorpal bunny encountered") + def g(): trace.append("Enter g") yield from f() trace.append("Exit g") + try: gi = g() next(gi) @@ -871,14 +1010,18 @@ def g(): self.assertIsInstance(e.__context__, GeneratorExit) else: self.fail("subgenerator failed to raise ValueError") - self.assertEqual(trace,[ - "Enter g", - "Enter f", - ]) + self.assertEqual( + trace, + [ + "Enter g", + "Enter f", + ], + ) def test_yield_from_empty(self): def g(): yield from () + self.assertRaises(StopIteration, next, g()) def test_delegating_generators_claim_to_be_running(self): @@ -887,6 +1030,7 @@ def one(): yield 0 yield from two() yield 3 + def two(): yield 1 try: @@ -894,6 +1038,7 @@ def two(): except ValueError: pass yield 2 + g1 = one() self.assertEqual(list(g1), [0, 1, 2, 3]) # Check with send @@ -905,9 +1050,11 @@ def two(): except StopIteration: pass self.assertEqual(res, [0, 1, 2, 3]) + # Check with throw class MyErr(Exception): pass + def one(): try: yield 0 @@ -918,6 +1065,7 @@ def one(): yield 3 except MyErr: pass + def two(): try: yield 1 @@ -931,6 +1079,7 @@ def two(): yield 2 except MyErr: pass + g1 = one() res = [next(g1)] try: @@ -941,17 +1090,22 @@ def two(): except: self.assertEqual(res, [0, 1, 2, 3]) raise + # Check with close class MyIt(object): def __iter__(self): return self + def __next__(self): return 42 + def close(self_): self.assertTrue(g1.gi_running) self.assertRaises(ValueError, next, g1) + def one(): yield from MyIt() + g1 = one() next(g1) g1.close() @@ -972,21 +1126,24 @@ def eggs(g): yield from g for stack in spam(gen()): - self.assertTrue('spam' in stack) + self.assertTrue("spam" in stack) for stack in spam(eggs(gen())): - self.assertTrue('spam' in stack and 'eggs' in stack) + self.assertTrue("spam" in stack and "eggs" in stack) def test_custom_iterator_return(self): # See issue #15568 class MyIter: def __iter__(self): return self + def __next__(self): raise StopIteration(42) + def gen(): nonlocal ret ret = yield from MyIter() + ret = None list(gen()) self.assertEqual(ret, 42) @@ -1012,9 +1169,11 @@ def test_close_with_cleared_frame(self): def innermost(): yield + def inner(): outer_gen = yield yield from innermost() + def outer(): inner_gen = yield yield from inner_gen @@ -1035,22 +1194,26 @@ def test_send_tuple_with_custom_generator(self): class MyGen: def __iter__(self): return self + def __next__(self): return 42 + def send(self, what): nonlocal v v = what return None + def outer(): v = yield from MyGen() + g = outer() next(g) v = None g.send((1, 2, 3, 4)) self.assertEqual(v, (1, 2, 3, 4)) -class TestInterestingEdgeCases(unittest.TestCase): +class TestInterestingEdgeCases(unittest.TestCase): def assert_stop_iteration(self, iterator): with self.assertRaises(StopIteration) as caught: next(iterator) @@ -1061,10 +1224,11 @@ def assert_generator_raised_stop_iteration(self): return self.assertRaisesRegex(RuntimeError, r"^generator raised StopIteration$") def assert_generator_ignored_generator_exit(self): - return self.assertRaisesRegex(RuntimeError, r"^generator ignored GeneratorExit$") + return self.assertRaisesRegex( + RuntimeError, r"^generator ignored GeneratorExit$" + ) def test_close_and_throw_work(self): - yielded_first = object() yielded_second = object() returned = object() @@ -1125,7 +1289,6 @@ def outer(): self.assert_stop_iteration(g) def test_close_and_throw_raise_generator_exit(self): - yielded_first = object() yielded_second = object() returned = object() @@ -1201,7 +1364,6 @@ def outer(): self.assert_stop_iteration(g) def test_close_and_throw_raise_stop_iteration(self): - yielded_first = object() yielded_second = object() returned = object() @@ -1225,7 +1387,9 @@ def outer(): with self.assert_generator_raised_stop_iteration() as caught: g.close() self.assertIs(caught.exception.__context__, raised) - self.assertIsInstance(caught.exception.__context__.__context__, GeneratorExit) + self.assertIsInstance( + caught.exception.__context__.__context__, GeneratorExit + ) self.assertIsNone(caught.exception.__context__.__context__.__context__) self.assert_stop_iteration(g) @@ -1240,7 +1404,9 @@ def outer(): self.assertIs(caught.exception.__context__, raised) # This isn't the same GeneratorExit as thrown! It's the one created # by calling inner.close(): - self.assertIsInstance(caught.exception.__context__.__context__, GeneratorExit) + self.assertIsInstance( + caught.exception.__context__.__context__, GeneratorExit + ) self.assertIsNone(caught.exception.__context__.__context__.__context__) self.assert_stop_iteration(g) @@ -1284,7 +1450,6 @@ def outer(): self.assert_stop_iteration(g) def test_close_and_throw_raise_base_exception(self): - yielded_first = object() yielded_second = object() returned = object() @@ -1362,7 +1527,6 @@ def outer(): self.assert_stop_iteration(g) def test_close_and_throw_raise_exception(self): - yielded_first = object() yielded_second = object() returned = object() @@ -1440,7 +1604,6 @@ def outer(): self.assert_stop_iteration(g) def test_close_and_throw_yield(self): - yielded_first = object() yielded_second = object() returned = object() @@ -1511,7 +1674,6 @@ def outer(): self.assert_stop_iteration(g) def test_close_and_throw_return(self): - yielded_first = object() yielded_second = object() returned = object() @@ -1577,5 +1739,5 @@ def outer(): self.assert_stop_iteration(g) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/Lib/test/time_hashlib.py b/Lib/test/time_hashlib.py index 55ebac62912fe1..7ad0f5c6232b70 100644 --- a/Lib/test/time_hashlib.py +++ b/Lib/test/time_hashlib.py @@ -9,9 +9,10 @@ def creatorFunc(): raise RuntimeError("eek, creatorFunc not overridden") + def test_scaled_msg(scale, name): - iterations = 106201//scale * 20 - longStr = b'Z'*scale + iterations = 106201 // scale * 20 + longStr = b"Z" * scale localCF = creatorFunc start = time.perf_counter() @@ -19,7 +20,16 @@ def test_scaled_msg(scale, name): x = localCF(longStr).digest() end = time.perf_counter() - print(('%2.2f' % (end-start)), "seconds", iterations, "x", len(longStr), "bytes", name) + print( + ("%2.2f" % (end - start)), + "seconds", + iterations, + "x", + len(longStr), + "bytes", + name, + ) + def test_create(): start = time.perf_counter() @@ -27,7 +37,8 @@ def test_create(): d = creatorFunc() end = time.perf_counter() - print(('%2.2f' % (end-start)), "seconds", '[20000 creations]') + print(("%2.2f" % (end - start)), "seconds", "[20000 creations]") + def test_zero(): start = time.perf_counter() @@ -35,8 +46,7 @@ def test_zero(): x = creatorFunc().digest() end = time.perf_counter() - print(('%2.2f' % (end-start)), "seconds", '[20000 "" digests]') - + print(("%2.2f" % (end - start)), "seconds", '[20000 "" digests]') hName = sys.argv[1] @@ -44,21 +54,23 @@ def test_zero(): # # setup our creatorFunc to test the requested hash # -if hName in ('_md5', '_sha'): - exec('import '+hName) - exec('creatorFunc = '+hName+'.new') +if hName in ("_md5", "_sha"): + exec("import " + hName) + exec("creatorFunc = " + hName + ".new") print("testing speed of old", hName, "legacy interface") -elif hName == '_hashlib' and len(sys.argv) > 3: +elif hName == "_hashlib" and len(sys.argv) > 3: import _hashlib - exec('creatorFunc = _hashlib.%s' % sys.argv[2]) + + exec("creatorFunc = _hashlib.%s" % sys.argv[2]) print("testing speed of _hashlib.%s" % sys.argv[2], getattr(_hashlib, sys.argv[2])) -elif hName == '_hashlib' and len(sys.argv) == 3: +elif hName == "_hashlib" and len(sys.argv) == 3: import _hashlib - exec('creatorFunc = lambda x=_hashlib.new : x(%r)' % sys.argv[2]) + + exec("creatorFunc = lambda x=_hashlib.new : x(%r)" % sys.argv[2]) print("testing speed of _hashlib.new(%r)" % sys.argv[2]) -elif hasattr(hashlib, hName) and hasattr(getattr(hashlib, hName), '__call__'): +elif hasattr(hashlib, hName) and hasattr(getattr(hashlib, hName), "__call__"): creatorFunc = getattr(hashlib, hName) - print("testing speed of hashlib."+hName, getattr(hashlib, hName)) + print("testing speed of hashlib." + hName, getattr(hashlib, hName)) else: exec("creatorFunc = lambda x=hashlib.new : x(%r)" % hName) print("testing speed of hashlib.new(%r)" % hName) @@ -77,12 +89,12 @@ def test_zero(): raise test_zero() -test_scaled_msg(scale=106201, name='[huge data]') -test_scaled_msg(scale=10620, name='[large data]') -test_scaled_msg(scale=1062, name='[medium data]') -test_scaled_msg(scale=424, name='[4*small data]') -test_scaled_msg(scale=336, name='[3*small data]') -test_scaled_msg(scale=212, name='[2*small data]') -test_scaled_msg(scale=106, name='[small data]') -test_scaled_msg(scale=creatorFunc().digest_size, name='[digest_size data]') -test_scaled_msg(scale=10, name='[tiny data]') +test_scaled_msg(scale=106201, name="[huge data]") +test_scaled_msg(scale=10620, name="[large data]") +test_scaled_msg(scale=1062, name="[medium data]") +test_scaled_msg(scale=424, name="[4*small data]") +test_scaled_msg(scale=336, name="[3*small data]") +test_scaled_msg(scale=212, name="[2*small data]") +test_scaled_msg(scale=106, name="[small data]") +test_scaled_msg(scale=creatorFunc().digest_size, name="[digest_size data]") +test_scaled_msg(scale=10, name="[tiny data]") diff --git a/Lib/test/tokenizedata/bad_coding2.py b/Lib/test/tokenizedata/bad_coding2.py index bb2bb7e1e75e43..5bfff964fdf736 100644 --- a/Lib/test/tokenizedata/bad_coding2.py +++ b/Lib/test/tokenizedata/bad_coding2.py @@ -1,2 +1,2 @@ -#coding: utf8 -print('我') +# coding: utf8 +print("我") diff --git a/Lib/test/tokenizedata/coding20731.py b/Lib/test/tokenizedata/coding20731.py index b0e227ad110e94..01ca672108c54b 100644 --- a/Lib/test/tokenizedata/coding20731.py +++ b/Lib/test/tokenizedata/coding20731.py @@ -1,4 +1,3 @@ -#coding:latin1 - +# coding:latin1 diff --git a/Lib/turtle.py b/Lib/turtle.py index 5e8b1a260b0d62..ef84eeb5a6001d 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -1100,7 +1100,7 @@ def addcomponent(self, poly, fill, outline=None): -- s.addcomponent(((0,0), (10,10), (-10,10)), "red", "blue") Example: - >>> poly = ((0,0),(10,-5),(0,10),(-10,-5)) + >>> poly = ((0, 0), (10, -5), (0, 10), (-10, -5)) >>> s = Shape("compound") >>> s.addcomponent(poly, "red", "blue") >>> # .. add more components and then use register_shape() @@ -1295,7 +1295,7 @@ def mode(self, mode=None): 'logo' upward (north) clockwise Examples: - >>> mode('logo') # resets turtle heading to north + >>> mode("logo") # resets turtle heading to north >>> mode() 'logo' """ @@ -1332,7 +1332,7 @@ def setworldcoordinates(self, llx, lly, urx, ury): distorted. (see Screen.mode()) Example (for a TurtleScreen instance named screen): - >>> screen.setworldcoordinates(-10,-0.5,50,1.5) + >>> screen.setworldcoordinates(-10, -0.5, 50, 1.5) >>> for _ in range(36): ... left(10) ... forward(0.5) @@ -1374,7 +1374,7 @@ def register_shape(self, name, shape=None): --or: register_shape("tri", ((0,0), (10,10), (-10,10))) Example (for a TurtleScreen instance named screen): - >>> screen.register_shape("triangle", ((5,-3),(0,5),(-5,-3))) + >>> screen.register_shape("triangle", ((5, -3), (0, 5), (-5, -3))) """ if shape is None: @@ -1440,7 +1440,7 @@ def colormode(self, cmode=None): >>> screen.colormode() 1.0 >>> screen.colormode(255) - >>> pencolor(240,160,80) + >>> pencolor(240, 160, 80) """ if cmode is None: return self._colormode @@ -1480,7 +1480,7 @@ def bgcolor(self, *args): >>> screen.bgcolor("orange") >>> screen.bgcolor() 'orange' - >>> screen.bgcolor(0.5,0,0.5) + >>> screen.bgcolor(0.5, 0, 0.5) >>> screen.bgcolor() '#800080' """ @@ -1628,7 +1628,6 @@ def onkey(self, fun, key): >>> def f(): ... fd(50) ... lt(60) - ... >>> screen.onkey(f, "Up") >>> screen.listen() @@ -1660,7 +1659,6 @@ def onkeypress(self, fun, key=None): >>> def f(): ... fd(50) ... lt(60) - ... >>> screen.onkeypress(f, "Up") >>> screen.listen() @@ -1699,11 +1697,10 @@ def ontimer(self, fun, t=0): >>> running = True >>> def f(): ... if running: - ... fd(50) - ... lt(60) - ... screen.ontimer(f, 250) - ... - >>> f() # makes the turtle marching around + ... fd(50) + ... lt(60) + ... screen.ontimer(f, 250) + >>> f() # makes the turtle marching around >>> running = False """ self._ontimer(fun, t) @@ -1746,7 +1743,7 @@ def screensize(self, canvwidth=None, canvheight=None, bg=None): of a drawing, which were outside the canvas before!) Example (for a Turtle instance named turtle): - >>> turtle.screensize(2000,1500) + >>> turtle.screensize(2000, 1500) >>> # e.g. to search for an erroneously escaped turtle ;-) """ return self._resize(canvwidth, canvheight, bg) @@ -2018,10 +2015,10 @@ def goto(self, x, y=None): >>> tp = turtle.pos() >>> tp (0.00, 0.00) - >>> turtle.setpos(60,30) + >>> turtle.setpos(60, 30) >>> turtle.pos() (60.00,30.00) - >>> turtle.setpos((20,80)) + >>> turtle.setpos((20, 80)) >>> turtle.pos() (20.00,80.00) >>> turtle.setpos(tp) @@ -2098,7 +2095,7 @@ def distance(self, x, y=None): Example (for a Turtle instance named turtle): >>> turtle.pos() (0.00, 0.00) - >>> turtle.distance(30,40) + >>> turtle.distance(30, 40) 50.0 >>> pen = Turtle() >>> pen.forward(77) @@ -2134,7 +2131,7 @@ def towards(self, x, y=None): Example (for a Turtle instance named turtle): >>> turtle.pos() (10.00, 10.00) - >>> turtle.towards(0,0) + >>> turtle.towards(0, 0) 225.0 """ if y is not None: @@ -2345,7 +2342,7 @@ def pensize(self, width=None): Example (for a Turtle instance named turtle): >>> turtle.pensize() 1 - >>> turtle.pensize(10) # from here on lines of width 10 are drawn + >>> turtle.pensize(10) # from here on lines of width 10 are drawn """ if width is None: return self._pensize @@ -2456,7 +2453,7 @@ def color(self, *args): For more info see: pencolor, fillcolor Example (for a Turtle instance named turtle): - >>> turtle.color('red', 'green') + >>> turtle.color("red", "green") >>> turtle.color() ('red', 'green') >>> colormode(255) @@ -2501,7 +2498,7 @@ def pencolor(self, *args): with the newly set pencolor. Example (for a Turtle instance named turtle): - >>> turtle.pencolor('brown') + >>> turtle.pencolor("brown") >>> tup = (0.2, 0.8, 0.55) >>> turtle.pencolor(tup) >>> turtle.pencolor() @@ -2538,10 +2535,10 @@ def fillcolor(self, *args): with the newly set fillcolor. Example (for a Turtle instance named turtle): - >>> turtle.fillcolor('violet') + >>> turtle.fillcolor("violet") >>> col = turtle.pencolor() >>> turtle.fillcolor(col) - >>> turtle.fillcolor(0, .5, 0) + >>> turtle.fillcolor(0, 0.5, 0) """ if args: color = self._colorstr(args) @@ -2635,8 +2632,8 @@ def pen(self, pen=None, **pendict): {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1, 'pencolor': 'red', 'pendown': True, 'fillcolor': 'black', 'stretchfactor': (1,1), 'speed': 3, 'shearfactor': 0.0} - >>> penstate=turtle.pen() - >>> turtle.color("yellow","") + >>> penstate = turtle.pen() + >>> turtle.color("yellow", "") >>> turtle.penup() >>> turtle.pen() {'pensize': 10, 'shown': True, 'resizemode': 'auto', 'outline': 1, @@ -3158,7 +3155,7 @@ def shearfactor(self, shear=None): Examples (for a Turtle instance named turtle): >>> turtle.shape("circle") - >>> turtle.shapesize(5,2) + >>> turtle.shapesize(5, 2) >>> turtle.shearfactor(0.5) >>> turtle.shearfactor() >>> 0.5 @@ -3214,7 +3211,7 @@ def tilt(self, angle): Examples (for a Turtle instance named turtle): >>> turtle.shape("circle") - >>> turtle.shapesize(5,2) + >>> turtle.shapesize(5, 2) >>> turtle.tilt(30) >>> turtle.fd(50) >>> turtle.tilt(30) @@ -3237,7 +3234,7 @@ def shapetransform(self, t11=None, t12=None, t21=None, t22=None): Examples (for a Turtle instance named turtle): >>> turtle.shape("square") - >>> turtle.shapesize(4,2) + >>> turtle.shapesize(4, 2) >>> turtle.shearfactor(-0.5) >>> turtle.shapetransform() (4.0, -1.0, -0.0, 2.0) @@ -3466,8 +3463,8 @@ def clearstamps(self, n=None): Example (for a Turtle instance named turtle): >>> for i in range(8): - ... turtle.stamp(); turtle.fd(30) - ... + ... turtle.stamp() + ... turtle.fd(30) >>> turtle.clearstamps(2) >>> turtle.clearstamps(-2) >>> turtle.clearstamps() @@ -3715,7 +3712,9 @@ def dot(self, size=None, *color): Example (for a Turtle instance named turtle): >>> turtle.dot() - >>> turtle.fd(50); turtle.dot(20, "blue"); turtle.fd(50) + >>> turtle.fd(50) + ... turtle.dot(20, "blue") + ... turtle.fd(50) """ if not color: if isinstance(size, (str, tuple)): @@ -3771,8 +3770,8 @@ def write(self, arg, move=False, align="left", font=("Arial", 8, "normal")): of the text. By default, move is False. Example (for a Turtle instance named turtle): - >>> turtle.write('Home = ', True, align="center") - >>> turtle.write((0,0), True) + >>> turtle.write("Home = ", True, align="center") + >>> turtle.write((0, 0), True) """ if self.undobuffer: self.undobuffer.push(["seq"]) @@ -3881,7 +3880,6 @@ def onclick(self, fun, btn=1, add=None): >>> def turn(x, y): ... left(360) - ... >>> onclick(turn) # Now clicking into the turtle will turn it. >>> onclick(None) # event-binding will be removed """ @@ -3898,11 +3896,11 @@ def onrelease(self, fun, btn=1, add=None): Example (for a MyTurtle instance named joe): >>> class MyTurtle(Turtle): - ... def glow(self,x,y): - ... self.fillcolor("red") - ... def unglow(self,x,y): - ... self.fillcolor("") + ... def glow(self, x, y): + ... self.fillcolor("red") ... + ... def unglow(self, x, y): + ... self.fillcolor("") >>> joe = MyTurtle() >>> joe.onclick(joe.glow) >>> joe.onrelease(joe.unglow) @@ -3974,11 +3972,10 @@ def undo(self): Example (for a Turtle instance named turtle): >>> for i in range(4): - ... turtle.fd(50); turtle.lt(80) - ... + ... turtle.fd(50) + ... turtle.lt(80) >>> for i in range(8): ... turtle.undo() - ... """ if self.undobuffer is None: return @@ -4053,11 +4050,11 @@ def setup( Default, starty=None is to center window vertically. Examples (for a Screen instance named screen): - >>> screen.setup (width=200, height=200, startx=0, starty=0) + >>> screen.setup(width=200, height=200, startx=0, starty=0) sets window to 200x200 pixels, in upper left of screen - >>> screen.setup(width=.75, height=0.5, startx=None, starty=None) + >>> screen.setup(width=0.75, height=0.5, startx=None, starty=None) sets window to 75% of screen by 50% of screen and centers """ diff --git a/Lib/typing.py b/Lib/typing.py index cf11f4ea561997..ce7aa60e3d4bef 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -213,7 +213,7 @@ def _should_unflatten_callable_args(typ, args): For example:: >>> import collections.abc - >>> P = ParamSpec('P') + >>> P = ParamSpec("P") >>> collections.abc.Callable[[int, int], str].__args__ == (int, int, str) True >>> collections.abc.Callable[P, str].__args__ == (P, str) @@ -258,8 +258,8 @@ def _collect_parameters(args): For example:: - >>> P = ParamSpec('P') - >>> T = TypeVar('T') + >>> P = ParamSpec("P") + >>> T = TypeVar("T") >>> _collect_parameters((T, Callable[P, T])) (~T, ~P) """ @@ -2357,7 +2357,7 @@ def get_origin(tp): Examples:: - >>> P = ParamSpec('P') + >>> P = ParamSpec("P") >>> assert get_origin(Literal[42]) is Literal >>> assert get_origin(int) is None >>> assert get_origin(ClassVar[int]) is ClassVar @@ -2387,7 +2387,7 @@ def get_args(tp): Examples:: - >>> T = TypeVar('T') + >>> T = TypeVar("T") >>> assert get_args(Dict[str, int]) == (str, int) >>> assert get_args(int) == () >>> assert get_args(Union[int, Union[T, int], str][int]) == (int, str) @@ -2415,7 +2415,6 @@ def is_typeddict(tp): >>> class Film(TypedDict): ... title: str ... year: int - ... >>> is_typeddict(Film) True >>> is_typeddict(dict) @@ -3057,10 +3056,9 @@ def TypedDict(typename, fields=_sentinel, /, *, total=True): ... x: int ... y: int ... label: str - ... - >>> a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK - >>> b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check - >>> Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') + >>> a: Point2D = {"x": 1, "y": 2, "label": "good"} # OK + >>> b: Point2D = {"z": 3, "label": "bad"} # Fails type check + >>> Point2D(x=1, y=2, label="first") == dict(x=1, y=2, label="first") True The type info can be accessed via the Point2D.__annotations__ dict, and @@ -3543,7 +3541,9 @@ def is_protocol(tp: type, /) -> bool: >>> from typing import Protocol, is_protocol >>> class P(Protocol): - ... def a(self) -> str: ... + ... def a(self) -> str: + ... ... + ... ... b: int >>> is_protocol(P) True @@ -3562,9 +3562,11 @@ def get_protocol_members(tp: type, /) -> frozenset[str]: >>> from typing import Protocol, get_protocol_members >>> class P(Protocol): - ... def a(self) -> str: ... + ... def a(self) -> str: + ... ... + ... ... b: int - >>> get_protocol_members(P) == frozenset({'a', 'b'}) + >>> get_protocol_members(P) == frozenset({"a", "b"}) True Raise a TypeError for arguments that are not Protocols. diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 8fa703e88a6f58..138bfe33d31b96 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -715,8 +715,8 @@ def configure_mock(self, /, **kwargs): mocks using standard dot notation and unpacking a dictionary in the method call: - >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError} - >>> mock.configure_mock(**attrs)""" + >>> attrs = {"method.return_value": 3, "other.side_effect": KeyError} + """ for arg, val in sorted( kwargs.items(), # we sort on the number of dots so that diff --git a/Lib/zipfile/_path/__init__.py b/Lib/zipfile/_path/__init__.py index e0e730806fc03d..52d1c3588efabc 100644 --- a/Lib/zipfile/_path/__init__.py +++ b/Lib/zipfile/_path/__init__.py @@ -17,15 +17,15 @@ def _parents(path): Given a path with elements separated by posixpath.sep, generate all parents of that path. - >>> list(_parents('b/d')) + >>> list(_parents("b/d")) ['b'] - >>> list(_parents('/b/d/')) + >>> list(_parents("/b/d/")) ['/b'] - >>> list(_parents('b/d/f/')) + >>> list(_parents("b/d/f/")) ['b/d', 'b'] - >>> list(_parents('b')) + >>> list(_parents("b")) [] - >>> list(_parents('')) + >>> list(_parents("")) [] """ return itertools.islice(_ancestry(path), 1, None) @@ -36,15 +36,15 @@ def _ancestry(path): Given a path with elements separated by posixpath.sep, generate all elements of that path - >>> list(_ancestry('b/d')) + >>> list(_ancestry("b/d")) ['b/d', 'b'] - >>> list(_ancestry('/b/d/')) + >>> list(_ancestry("/b/d/")) ['/b/d', '/b'] - >>> list(_ancestry('b/d/f/')) + >>> list(_ancestry("b/d/f/")) ['b/d/f', 'b/d', 'b'] - >>> list(_ancestry('b')) + >>> list(_ancestry("b")) ['b'] - >>> list(_ancestry('')) + >>> list(_ancestry("")) [] """ path = path.rstrip(posixpath.sep) @@ -88,9 +88,9 @@ class CompleteDirs(InitializedState, zipfile.ZipFile): A ZipFile subclass that ensures that implied directories are always included in the namelist. - >>> list(CompleteDirs._implied_dirs(['foo/bar.txt', 'foo/bar/baz.txt'])) + >>> list(CompleteDirs._implied_dirs(["foo/bar.txt", "foo/bar/baz.txt"])) ['foo/', 'foo/bar/'] - >>> list(CompleteDirs._implied_dirs(['foo/bar.txt', 'foo/bar/baz.txt', 'foo/bar/'])) + >>> list(CompleteDirs._implied_dirs(["foo/bar.txt", "foo/bar/baz.txt", "foo/bar/"])) ['foo/'] """ @@ -186,11 +186,11 @@ class Path: └── e.txt >>> data = io.BytesIO() - >>> zf = ZipFile(data, 'w') - >>> zf.writestr('a.txt', 'content of a') - >>> zf.writestr('b/c.txt', 'content of c') - >>> zf.writestr('b/d/e.txt', 'content of e') - >>> zf.filename = 'mem/abcde.zip' + >>> zf = ZipFile(data, "w") + >>> zf.writestr("a.txt", "content of a") + >>> zf.writestr("b/c.txt", "content of c") + >>> zf.writestr("b/d/e.txt", "content of e") + >>> zf.filename = "mem/abcde.zip" Path accepts the zipfile object itself or a filename @@ -213,7 +213,7 @@ class Path: join with divide operator: - >>> c = b / 'c.txt' + >>> c = b / "c.txt" >>> c Path('mem/abcde.zip', 'b/c.txt') >>> c.name @@ -221,14 +221,14 @@ class Path: Read text: - >>> c.read_text(encoding='utf-8') + >>> c.read_text(encoding="utf-8") 'content of c' existence: >>> c.exists() True - >>> (b / 'missing.txt').exists() + >>> (b / "missing.txt").exists() False Coercion to string: @@ -267,7 +267,7 @@ def __init__(self, root, at=""): def __eq__(self, other): """ - >>> Path(zipfile.ZipFile(io.BytesIO(), 'w')) == 'foo' + >>> Path(zipfile.ZipFile(io.BytesIO(), "w")) == "foo" False """ if self.__class__ is not other.__class__: diff --git a/Lib/zipfile/_path/glob.py b/Lib/zipfile/_path/glob.py index 380f05a6d0bab8..d9d9b0dba60355 100644 --- a/Lib/zipfile/_path/glob.py +++ b/Lib/zipfile/_path/glob.py @@ -5,11 +5,11 @@ def translate(pattern): r""" Given a glob pattern, produce a regex that matches it. - >>> translate('*.txt') + >>> translate("*.txt") '[^/]*\\.txt' - >>> translate('a?txt') + >>> translate("a?txt") 'a.txt' - >>> translate('**/*') + >>> translate("**/*") '.*/[^/]*' """ return "".join(map(replace, separate(pattern))) @@ -19,9 +19,9 @@ def separate(pattern): """ Separate out character sets to avoid translating their contents. - >>> [m.group(0) for m in separate('*.txt')] + >>> [m.group(0) for m in separate("*.txt")] ['*.txt'] - >>> [m.group(0) for m in separate('a[?]txt')] + >>> [m.group(0) for m in separate("a[?]txt")] ['a', '[?]', 'txt'] """ return re.finditer(r"([^\[]+)|(?P[\[].*?[\]])|([\[][^\]]*$)", pattern)