|
83 | 83 | 'TypeAlias',
|
84 | 84 | 'TypeAliasType',
|
85 | 85 | 'TypeGuard',
|
| 86 | + 'TypeIs', |
86 | 87 | 'TYPE_CHECKING',
|
87 | 88 | 'Never',
|
88 | 89 | 'NoReturn',
|
@@ -1822,6 +1823,98 @@ def is_str(val: Union[str, float]):
|
1822 | 1823 | PEP 647 (User-Defined Type Guards).
|
1823 | 1824 | """)
|
1824 | 1825 |
|
| 1826 | +# 3.13+ |
| 1827 | +if hasattr(typing, 'TypeIs'): |
| 1828 | + TypeIs = typing.TypeIs |
| 1829 | +# 3.9 |
| 1830 | +elif sys.version_info[:2] >= (3, 9): |
| 1831 | + @_ExtensionsSpecialForm |
| 1832 | + def TypeIs(self, parameters): |
| 1833 | + """Special typing form used to annotate the return type of a user-defined |
| 1834 | + type narrower function. ``TypeIs`` only accepts a single type argument. |
| 1835 | + At runtime, functions marked this way should return a boolean. |
| 1836 | +
|
| 1837 | + ``TypeIs`` aims to benefit *type narrowing* -- a technique used by static |
| 1838 | + type checkers to determine a more precise type of an expression within a |
| 1839 | + program's code flow. Usually type narrowing is done by analyzing |
| 1840 | + conditional code flow and applying the narrowing to a block of code. The |
| 1841 | + conditional expression here is sometimes referred to as a "type guard". |
| 1842 | +
|
| 1843 | + Sometimes it would be convenient to use a user-defined boolean function |
| 1844 | + as a type guard. Such a function should use ``TypeIs[...]`` as its |
| 1845 | + return type to alert static type checkers to this intention. |
| 1846 | +
|
| 1847 | + Using ``-> TypeIs`` tells the static type checker that for a given |
| 1848 | + function: |
| 1849 | +
|
| 1850 | + 1. The return value is a boolean. |
| 1851 | + 2. If the return value is ``True``, the type of its argument |
| 1852 | + is the intersection of the type inside ``TypeGuard`` and the argument's |
| 1853 | + previously known type. |
| 1854 | +
|
| 1855 | + For example:: |
| 1856 | +
|
| 1857 | + def is_awaitable(val: object) -> TypeIs[Awaitable[Any]]: |
| 1858 | + return hasattr(val, '__await__') |
| 1859 | +
|
| 1860 | + def f(val: Union[int, Awaitable[int]]) -> int: |
| 1861 | + if is_awaitable(val): |
| 1862 | + assert_type(val, Awaitable[int]) |
| 1863 | + else: |
| 1864 | + assert_type(val, int) |
| 1865 | +
|
| 1866 | + ``TypeIs`` also works with type variables. For more information, see |
| 1867 | + PEP 742 (Narrowing types with TypeIs). |
| 1868 | + """ |
| 1869 | + item = typing._type_check(parameters, f'{self} accepts only a single type.') |
| 1870 | + return typing._GenericAlias(self, (item,)) |
| 1871 | +# 3.8 |
| 1872 | +else: |
| 1873 | + class _TypeIsForm(_ExtensionsSpecialForm, _root=True): |
| 1874 | + def __getitem__(self, parameters): |
| 1875 | + item = typing._type_check(parameters, |
| 1876 | + f'{self._name} accepts only a single type') |
| 1877 | + return typing._GenericAlias(self, (item,)) |
| 1878 | + |
| 1879 | + TypeIs = _TypeIsForm( |
| 1880 | + 'TypeIs', |
| 1881 | + doc="""Special typing form used to annotate the return type of a user-defined |
| 1882 | + type narrower function. ``TypeIs`` only accepts a single type argument. |
| 1883 | + At runtime, functions marked this way should return a boolean. |
| 1884 | +
|
| 1885 | + ``TypeIs`` aims to benefit *type narrowing* -- a technique used by static |
| 1886 | + type checkers to determine a more precise type of an expression within a |
| 1887 | + program's code flow. Usually type narrowing is done by analyzing |
| 1888 | + conditional code flow and applying the narrowing to a block of code. The |
| 1889 | + conditional expression here is sometimes referred to as a "type guard". |
| 1890 | +
|
| 1891 | + Sometimes it would be convenient to use a user-defined boolean function |
| 1892 | + as a type guard. Such a function should use ``TypeIs[...]`` as its |
| 1893 | + return type to alert static type checkers to this intention. |
| 1894 | +
|
| 1895 | + Using ``-> TypeIs`` tells the static type checker that for a given |
| 1896 | + function: |
| 1897 | +
|
| 1898 | + 1. The return value is a boolean. |
| 1899 | + 2. If the return value is ``True``, the type of its argument |
| 1900 | + is the intersection of the type inside ``TypeGuard`` and the argument's |
| 1901 | + previously known type. |
| 1902 | +
|
| 1903 | + For example:: |
| 1904 | +
|
| 1905 | + def is_awaitable(val: object) -> TypeIs[Awaitable[Any]]: |
| 1906 | + return hasattr(val, '__await__') |
| 1907 | +
|
| 1908 | + def f(val: Union[int, Awaitable[int]]) -> int: |
| 1909 | + if is_awaitable(val): |
| 1910 | + assert_type(val, Awaitable[int]) |
| 1911 | + else: |
| 1912 | + assert_type(val, int) |
| 1913 | +
|
| 1914 | + ``TypeIs`` also works with type variables. For more information, see |
| 1915 | + PEP 742 (Narrowing types with TypeIs). |
| 1916 | + """) |
| 1917 | + |
1825 | 1918 |
|
1826 | 1919 | # Vendored from cpython typing._SpecialFrom
|
1827 | 1920 | class _SpecialForm(typing._Final, _root=True):
|
|
0 commit comments