Skip to content

Commit

Permalink
typing.Protocol + abc.ABC x 2.
Browse files Browse the repository at this point in the history
This commit is the next in a commit chain supporting PEP 544-compliant
inheritance trees subclassing non-trivial combinations of the
`typing.Protocol` + `abc.ABC` superclasses, en-route to resolving beartype#117
kindly submitted by too-entertaining pun master @twoertwein (Torsten
Wörtwein). Specifically, this commit sanitizes the generalization of our
test suite to test the `typing.Literal` and `typing.Annotated` type hint
factories against the official `typing` module, the third-party
`typing_extensions` module, and the `beartype.typing` compatibility
layer implemented by the prior commit. Although doing so admittedly has
no relation whatsoever to this issue, every bug resolution begins with a
mild detour into the annals of inanity... *yet again.* (*A bier of beer!*)
  • Loading branch information
leycec committed Apr 2, 2022
1 parent da3874b commit 8c256e3
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 358 deletions.
132 changes: 60 additions & 72 deletions beartype_test/a00_unit/data/hint/pep/proposal/_data_pep586.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
'''

# ....................{ IMPORTS }....................
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
is_hints_pep_metadata,
make_hints_pep_metadata,
from beartype_test.a00_unit.data.hint.util.data_typingattrutil import (
is_typing_attrs,
iter_typing_attrs,
)
from enum import Enum

Expand All @@ -37,7 +37,7 @@ def add_data(data_module: 'ModuleType') -> None:

# If *NO* typing module declares a "Literal" factory, the active Python
# interpreter fails to support PEP 586. In this case, reduce to a noop.
if not is_hints_pep_metadata('Literal'):
if not is_typing_attrs('Literal'):
# print('Ignoring "Literal"...')
return
# print('Testing "Literal"...')
Expand All @@ -52,19 +52,20 @@ def add_data(data_module: 'ModuleType') -> None:
)
from beartype._util.py.utilpyversion import IS_PYTHON_AT_LEAST_3_7
from beartype_test.a00_unit.data.hint.util.data_hintmetacls import (
HintPepMetadata,
HintPithSatisfiedMetadata,
HintPithUnsatisfiedMetadata,
)

# ..................{ TUPLES }..................
# Add PEP 586-specific test type hints to this tuple global.
data_module.HINTS_PEP_META.extend(
# ................{ LITERALS }................
# Literal "None" singleton. Look, this is ridiculous. What can you do?
make_hints_pep_metadata(
typing_attr_basenames=('Literal',),
hint_maker=lambda Literal: Literal[None],
hint_metadata=dict(
# ..................{ FACTORIES }..................
# For each "Literal" type hint factory importable from a typing module...
for Literal in iter_typing_attrs('Literal'):
# Add PEP 586-specific test type hints to this tuple global.
data_module.HINTS_PEP_META.extend((
# ..............{ LITERALS }..............
# Literal "None" singleton. Look, this is ridiculous. What you do?
HintPepMetadata(
hint=Literal[None],
pep_sign=HintSignLiteral,
# "typing_extensions.Literal" type hints define a non-standard
# "__values__" rather than standard "__args__" dunder tuple
Expand All @@ -87,13 +88,10 @@ def add_data(data_module: 'ModuleType') -> None:
),
),
),
) +

# Literal arbitrary boolean. (Not that there are many of those...)
make_hints_pep_metadata(
typing_attr_basenames=('Literal',),
hint_maker=lambda Literal: Literal[True],
hint_metadata=dict(
# Literal arbitrary boolean. (Not that there are many of those...)
HintPepMetadata(
hint=Literal[True],
pep_sign=HintSignLiteral,
is_args=IS_PYTHON_AT_LEAST_3_7,
piths_meta=(
Expand Down Expand Up @@ -121,13 +119,10 @@ def add_data(data_module: 'ModuleType') -> None:
),
),
),
) +

# Literal arbitrary integer.
make_hints_pep_metadata(
typing_attr_basenames=('Literal',),
hint_maker=lambda Literal: Literal[0x2a],
hint_metadata=dict(
# Literal arbitrary integer.
HintPepMetadata(
hint=Literal[0x2a],
pep_sign=HintSignLiteral,
is_args=IS_PYTHON_AT_LEAST_3_7,
piths_meta=(
Expand Down Expand Up @@ -155,14 +150,11 @@ def add_data(data_module: 'ModuleType') -> None:
),
),
),
) +

# Literal arbitrary byte string.
make_hints_pep_metadata(
typing_attr_basenames=('Literal',),
hint_maker=lambda Literal: Literal[
b"Worthy, 'vain truthiness of (very invective-elected)"],
hint_metadata=dict(
# Literal arbitrary byte string.
HintPepMetadata(
hint=Literal[
b"Worthy, 'vain truthiness of (very invective-elected)"],
pep_sign=HintSignLiteral,
is_args=IS_PYTHON_AT_LEAST_3_7,
piths_meta=(
Expand Down Expand Up @@ -197,13 +189,10 @@ def add_data(data_module: 'ModuleType') -> None:
),
),
),
) +

# Literal arbitrary Unicode string.
make_hints_pep_metadata(
typing_attr_basenames=('Literal',),
hint_maker=lambda Literal: Literal['Thanklessly classed, nominal'],
hint_metadata=dict(
# Literal arbitrary Unicode string.
HintPepMetadata(
hint=Literal['Thanklessly classed, nominal'],
pep_sign=HintSignLiteral,
is_args=IS_PYTHON_AT_LEAST_3_7,
piths_meta=(
Expand Down Expand Up @@ -234,21 +223,21 @@ def add_data(data_module: 'ModuleType') -> None:
),
),
),
) +

# Literal arbitrary enumeration member.
make_hints_pep_metadata(
typing_attr_basenames=('Literal',),
hint_maker=lambda Literal: Literal[
_MasterlessDecreeVenomlessWhich.NOMENCLATURE_WEATHER_VANES_OF],
hint_metadata=dict(
# Literal arbitrary enumeration member.
HintPepMetadata(
hint=Literal[
_MasterlessDecreeVenomlessWhich.
NOMENCLATURE_WEATHER_VANES_OF
],
pep_sign=HintSignLiteral,
is_args=IS_PYTHON_AT_LEAST_3_7,
piths_meta=(
# Enumeration member accessed by the same syntax.
HintPithSatisfiedMetadata(
_MasterlessDecreeVenomlessWhich.
NOMENCLATURE_WEATHER_VANES_OF),
NOMENCLATURE_WEATHER_VANES_OF
),
# Enumeration member accessed by different syntax but
# semantically equal to the same enumeration member.
HintPithSatisfiedMetadata(
Expand All @@ -257,7 +246,8 @@ def add_data(data_module: 'ModuleType') -> None:
HintPithUnsatisfiedMetadata(
pith=(
_MasterlessDecreeVenomlessWhich.
NOMINALLY_UNSWAIN_AUTODIDACTIC_IDIOCRACY_LESS_A),
NOMINALLY_UNSWAIN_AUTODIDACTIC_IDIOCRACY_LESS_A
),
# Match that the exception message raised for this
# object embeds the representation of the expected
# literal.
Expand All @@ -276,15 +266,12 @@ def add_data(data_module: 'ModuleType') -> None:
),
),
),
) +

# ................{ LITERALS ~ nested }................
# List of literal arbitrary Unicode strings.
make_hints_pep_metadata(
typing_attr_basenames=('Literal',),
hint_maker=lambda Literal: List[Literal[
'ç‐omically gnomical whitebellied burden’s empathy of']],
hint_metadata=dict(
# ..............{ LITERALS ~ nested }..............
# List of literal arbitrary Unicode strings.
HintPepMetadata(
hint=List[Literal[
'ç‐omically gnomical whitebellied burden’s empathy of']],
pep_sign=HintSignList,
isinstanceable_type=list,
piths_meta=(
Expand Down Expand Up @@ -323,21 +310,21 @@ def add_data(data_module: 'ModuleType') -> None:
),
),
),
) +

# ................{ LITERALS ~ union }................
# Literal union of two or more arbitrary literal objects.
make_hints_pep_metadata(
typing_attr_basenames=('Literal',),
hint_maker=lambda Literal: Literal[
None,
True,
0x2a,
b"Worthy, 'vain truthiness of (very invective-elected)",
'Thanklessly classed, nominal',
_MasterlessDecreeVenomlessWhich.NOMENCLATURE_WEATHER_VANES_OF,
],
hint_metadata=dict(
# ..............{ LITERALS ~ union }..............
# Literal union of two or more arbitrary literal objects.
HintPepMetadata(
hint=Literal[
None,
True,
0x2a,
b"Worthy, 'vain truthiness of (very invective-elected)",
'Thanklessly classed, nominal',
(
_MasterlessDecreeVenomlessWhich.
NOMENCLATURE_WEATHER_VANES_OF
),
],
pep_sign=HintSignLiteral,
is_args=IS_PYTHON_AT_LEAST_3_7,
piths_meta=(
Expand All @@ -350,7 +337,9 @@ def add_data(data_module: 'ModuleType') -> None:
),
HintPithSatisfiedMetadata('Thanklessly classed, nominal'),
HintPithSatisfiedMetadata(
_MasterlessDecreeVenomlessWhich.NOMENCLATURE_WEATHER_VANES_OF),
_MasterlessDecreeVenomlessWhich.
NOMENCLATURE_WEATHER_VANES_OF
),
# Arbitrary object of the same type as one or more literal
# objects subscripting this literal union but unequal to
# any objects subscripting this literal union.
Expand Down Expand Up @@ -386,5 +375,4 @@ def add_data(data_module: 'ModuleType') -> None:
),
),
),
)
)
))
89 changes: 39 additions & 50 deletions beartype_test/a00_unit/data/hint/pep/proposal/_data_pep593.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@
'''

# ....................{ IMPORTS }....................
from beartype_test.a00_unit.data.hint.util.data_hintmetautil import (
is_hints_pep_metadata,
from beartype_test.a00_unit.data.hint.util.data_typingattrutil import (
is_typing_attrs,
iter_typing_attrs,
make_hints_pep_metadata,
)

# ....................{ ADDERS }....................
Expand All @@ -28,7 +27,7 @@ def add_data(data_module: 'ModuleType') -> None:

# If *NO* typing module declares an "Annotated" factory, the active Python
# interpreter fails to support PEP 593. In this case, reduce to a noop.
if not is_hints_pep_metadata('Annotated'):
if not is_typing_attrs('Annotated'):
# print('Ignoring "Annotated"...')
return
# print('Testing "Annotated"...')
Expand Down Expand Up @@ -66,47 +65,6 @@ def add_data(data_module: 'ModuleType') -> None:
HintPithUnsatisfiedMetadata,
)

# ..................{ TUPLES }..................
# Add PEP 593-specific test type hints to this tuple global.
data_module.HINTS_PEP_META.extend(
# ................{ ANNOTATED }................
# Hashable annotated of an isinstanceable type annotated by an arbitrary
# hashable object.
make_hints_pep_metadata(
typing_attr_basenames=('Annotated',),
hint_maker=lambda Annotated: Annotated[str, int],
hint_metadata=dict(
pep_sign=HintSignAnnotated,
piths_meta=(
# String constant.
HintPithSatisfiedMetadata(
'Towards a timely, wines‐enticing gate'),
# List of string constants.
HintPithUnsatisfiedMetadata([
'Of languished anger’s sap‐spated rushings',]),
),
),
) +

# Annotated of a "typing" type.
make_hints_pep_metadata(
typing_attr_basenames=('Annotated',),
hint_maker=lambda Annotated: Annotated[List[str], int],
hint_metadata=dict(
pep_sign=HintSignAnnotated,
piths_meta=(
# List of string constants.
HintPithSatisfiedMetadata([
'MINERVA‐unnerving, verve‐sapping enervations',
'Of a magik-stoned Shinto rivery',
]),
# String constant.
HintPithUnsatisfiedMetadata('Of a Spicily sated',),
),
),
)
)

# ..................{ VALIDATORS ~ is }..................
# Beartype-specific validators defined as lambda functions.
IsLengthy = Is[lambda text: len(text) > 30]
Expand Down Expand Up @@ -151,8 +109,8 @@ def __init__(self) -> None:
SORDIDLY_FLABBY_WRMCASTINGS.this_mobbed_triste_of = [
'An atomical caroller', 'carousing Thanatos', '(nucl‐eating',]

# ..................{ TYPING }..................
# For each "Annotated" factory declared by a typing module...
# ..................{ FACTORIES }..................
# For each "Annotated" type hint factory importable from a typing module...
for Annotated in iter_typing_attrs('Annotated'):
# ................{ ANNOTATED }................
# Annotated of an isinstanceable type annotated by one beartype-specific
Expand All @@ -179,12 +137,43 @@ def __init__(self) -> None:
Union[str, List[int], NewType('MetaType', Annotated[object, 53])],
))

# ................{ VALIDATORS ~ tuples }................
# ................{ TUPLES }................
# Add PEP 593-specific test type hints to this tuple global.
data_module.HINTS_PEP_META.extend((
# ..............{ ANNOTATED }..............
# Hashable annotated of an isinstanceable type annotated by an
# arbitrary hashable object.
HintPepMetadata(
hint=Annotated[str, int],
pep_sign=HintSignAnnotated,
piths_meta=(
# String constant.
HintPithSatisfiedMetadata(
'Towards a timely, wines‐enticing gate'),
# List of string constants.
HintPithUnsatisfiedMetadata([
'Of languished anger’s sap‐spated rushings',]),
),
),

# Annotated of a "typing" type.
HintPepMetadata(
hint=Annotated[List[str], int],
pep_sign=HintSignAnnotated,
piths_meta=(
# List of string constants.
HintPithSatisfiedMetadata([
'MINERVA‐unnerving, verve‐sapping enervations',
'Of a magik-stoned Shinto rivery',
]),
# String constant.
HintPithUnsatisfiedMetadata('Of a Spicily sated',),
),
),

# ..............{ ANNOTATED ~ beartype : is }..............
# Annotated of an isinstanceable type annotated by one beartype-specific
# validator defined as a lambda function.
# Annotated of an isinstanceable type annotated by one
# beartype-specific validator defined as a lambda function.
HintPepMetadata(
hint=AnnotatedStrIsLength,
pep_sign=HintSignAnnotated,
Expand Down
Loading

0 comments on commit 8c256e3

Please sign in to comment.