bpo-37045: PEP 591: Add final qualifiers to typing module (GH-13571)

The implementation is straightforward, it just mimics `ClassVar` (since the latter is also a name/access qualifier, not really a type). Also it is essentially copied from `typing_extensions`.
This commit is contained in:
Ivan Levkivskyi 2019-05-26 09:37:07 +01:00 committed by GitHub
parent 47dd2f9fd8
commit f367242d10
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 142 additions and 4 deletions

View file

@ -35,6 +35,7 @@ __all__ = [
'Any',
'Callable',
'ClassVar',
'Final',
'Generic',
'Optional',
'Tuple',
@ -92,6 +93,7 @@ __all__ = [
# One-off things.
'AnyStr',
'cast',
'final',
'get_type_hints',
'NewType',
'no_type_check',
@ -121,7 +123,7 @@ def _type_check(arg, msg, is_argument=True):
"""
invalid_generic_forms = (Generic, _Protocol)
if is_argument:
invalid_generic_forms = invalid_generic_forms + (ClassVar, )
invalid_generic_forms = invalid_generic_forms + (ClassVar, Final)
if arg is None:
return type(None)
@ -336,8 +338,8 @@ class _SpecialForm(_Final, _Immutable, _root=True):
@_tp_cache
def __getitem__(self, parameters):
if self._name == 'ClassVar':
item = _type_check(parameters, 'ClassVar accepts only single type.')
if self._name in ('ClassVar', 'Final'):
item = _type_check(parameters, f'{self._name} accepts only single type.')
return _GenericAlias(self, (item,))
if self._name == 'Union':
if parameters == ():
@ -398,6 +400,24 @@ ClassVar = _SpecialForm('ClassVar', doc=
be used with isinstance() or issubclass().
""")
Final = _SpecialForm('Final', doc=
"""Special typing construct to indicate final names to type checkers.
A final name cannot be re-assigned or overridden in a subclass.
For example:
MAX_SIZE: Final = 9000
MAX_SIZE += 1 # Error reported by type checker
class Connection:
TIMEOUT: Final[int] = 10
class FastConnector(Connection):
TIMEOUT = 1 # Error reported by type checker
There is no runtime checking of these properties.
""")
Union = _SpecialForm('Union', doc=
"""Union type; Union[X, Y] means either X or Y.
@ -1085,6 +1105,32 @@ def overload(func):
return _overload_dummy
def final(f):
"""A decorator to indicate final methods and final classes.
Use this decorator to indicate to type checkers that the decorated
method cannot be overridden, and decorated class cannot be subclassed.
For example:
class Base:
@final
def done(self) -> None:
...
class Sub(Base):
def done(self) -> None: # Error reported by type checker
...
@final
class Leaf:
...
class Other(Leaf): # Error reported by type checker
...
There is no runtime checking of these properties.
"""
return f
class _ProtocolMeta(type):
"""Internal metaclass for _Protocol.