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`.
See :pep:`484` for details and comparison with other typing semantics.
+.. decorator:: final
+
+ A decorator to indicate to type checkers that the decorated method
+ cannot be overridden, and the 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. See :pep:`591` for
+ more details.
+
+ .. versionadded:: 3.8
+
.. decorator:: no_type_check
Decorator to indicate that annotations are not type hints.
.. versionadded:: 3.5.3
+.. data:: Final
+
+ A special typing construct to indicate to type checkers that a 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. See :pep:`591` for
+ more details.
+
+ .. versionadded:: 3.8
+
.. data:: AnyStr
``AnyStr`` is a type variable defined as
from typing import Union, Optional
from typing import Tuple, List, MutableMapping
from typing import Callable
-from typing import Generic, ClassVar
+from typing import Generic, ClassVar, Final, final
from typing import cast
from typing import get_type_hints
from typing import no_type_check, no_type_check_decorator
issubclass(int, ClassVar)
+class FinalTests(BaseTestCase):
+
+ def test_basics(self):
+ Final[int] # OK
+ with self.assertRaises(TypeError):
+ Final[1]
+ with self.assertRaises(TypeError):
+ Final[int, str]
+ with self.assertRaises(TypeError):
+ Final[int][str]
+ with self.assertRaises(TypeError):
+ Optional[Final[int]]
+
+ def test_repr(self):
+ self.assertEqual(repr(Final), 'typing.Final')
+ cv = Final[int]
+ self.assertEqual(repr(cv), 'typing.Final[int]')
+ cv = Final[Employee]
+ self.assertEqual(repr(cv), 'typing.Final[%s.Employee]' % __name__)
+
+ def test_cannot_subclass(self):
+ with self.assertRaises(TypeError):
+ class C(type(Final)):
+ pass
+ with self.assertRaises(TypeError):
+ class C(type(Final[int])):
+ pass
+
+ def test_cannot_init(self):
+ with self.assertRaises(TypeError):
+ Final()
+ with self.assertRaises(TypeError):
+ type(Final)()
+ with self.assertRaises(TypeError):
+ type(Final[Optional[int]])()
+
+ def test_no_isinstance(self):
+ with self.assertRaises(TypeError):
+ isinstance(1, Final[int])
+ with self.assertRaises(TypeError):
+ issubclass(int, Final)
+
+ def test_final_unmodified(self):
+ def func(x): ...
+ self.assertIs(func, final(func))
+
+
class CastTests(BaseTestCase):
def test_basics(self):
'Any',
'Callable',
'ClassVar',
+ 'Final',
'Generic',
'Optional',
'Tuple',
# One-off things.
'AnyStr',
'cast',
+ 'final',
'get_type_hints',
'NewType',
'no_type_check',
"""
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)
@_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 == ():
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.
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.
--- /dev/null
+PEP 591: Add ``Final`` qualifier and ``@final`` decorator to the ``typing`` module.
\ No newline at end of file