"""
Steno Type Elements
Representations of the fundamental :py:mod:`stenotype` building blocks.
Each element holds the relevant information for both a :py:mod:`stenotype` and
:py:mod:`typing` conversion.
Note that all elements are represented as values, not types:
A :py:class:`Steno` encodes :py:mod:`stenotype` syntax/code,
not any concrete types.
For example, ``Identifier('typing', 'List')`` is not the type :py:class:`typing.List`
but represents the name ``typing.List``.
"""
from typing import NamedTuple, Tuple as TupleT, Union as UnionT, Optional as OptionalT
[docs]class Dots:
"""A literal ``...`` placeholder"""
__slots__ = ()
def __eq__(self, other):
return True if type(other) is Dots else NotImplemented
def __repr__(self):
return f"{self.__class__.__name__}()"
[docs]class Identifier(TupleT[str, ...]):
"""A qualified name, such as ``typing.Tuple``"""
def __new__(cls, *elements: str):
return super().__new__(cls, elements)
def __repr__(self):
return f'{self.__class__.__name__}({", ".join(map(repr, self))})'
[docs]class Generic(NamedTuple):
"""A generic type, such as ``typing.List[int]``"""
base: Identifier
parameters: TupleT[UnionT["Steno", Dots], ...]
[docs]class Any:
"""Any type as ``_``, same as :py:class:`typing.Any`"""
__slots__ = ()
def __eq__(self, other):
return True if type(other) is Any else NotImplemented
def __repr__(self):
return f"Any()"
[docs]class Optional(NamedTuple):
"""Optional type as ``?base``, equivalent to ``typing.Optional[base]``"""
base: "Steno"
[docs]class Union(TupleT["Steno"]):
"""Union of types as ``A or B``, equivalent to ``typing.Union[A, B]``"""
def __new__(cls, *elements: "Steno"):
return super().__new__(cls, elements)
def __repr__(self):
return f'{self.__class__.__name__}({", ".join(map(repr, self))})'
[docs]class Tuple(NamedTuple):
"""Typed tuple as ``(A, B, ...)``, equivalent to ``typing.Tuple[A, B, ...]``"""
elements: TupleT[UnionT["Steno", Dots], ...]
[docs]class List(NamedTuple):
"""Typed list as ``[values]``, equivalent to ``typing.List[values]``"""
values: "Steno"
[docs]class Dict(NamedTuple):
"""Typed dict as ``{keys: values}``, equivalent to ``typing.Dict[keys, values]``"""
keys: "Steno"
values: "Steno"
[docs]class Set(NamedTuple):
"""Typed dict as ``{values}``, equivalent to ``typing.Set[values]``"""
values: "Steno"
[docs]class Literal(NamedTuple):
"""Literal value, not a type"""
value: UnionT[None, bool, int, str, bytes, "ellipsis"]
[docs]class Iterable(NamedTuple):
"""Typed iterable as ``iter base``, equivalent to ``typing.Iterable[base]``"""
base: "Steno"
[docs]class Context(NamedTuple):
"""Typed context manager as ``with base``"""
base: "Steno"
[docs]class Awaitable(NamedTuple):
"""Typed awaitable as ``await base``, equivalent to ``typing.Awaitable[base]``"""
base: "Steno"
[docs]class AsyncIterable(NamedTuple):
"""Typed async iterable as ``async iter base``"""
base: "Steno"
[docs]class AsyncContext(NamedTuple):
"""Typed async context manager as ``async with base``"""
base: "Steno"
[docs]class Parameter(NamedTuple):
"""Typed parameter of a call signature as ``name: base``"""
name: OptionalT[str]
base: "Steno"
# Do we need a default value?
[docs]class Signature(NamedTuple):
"""Typed signature as ``(p: P, /, m: M, *a: A, k: K, **kw: KW) -> R``"""
#: positional only parameters, e.g. ``(a: A, b:B, /)``
positional: TupleT[Parameter, ...]
#: positional or keyword parameters, e.g. ``(a: A, b: B)``
mixed: TupleT[Parameter, ...]
#: variadic positional parameters, e.g. ``(*args: ARGS)``
args: OptionalT[Parameter]
#: keyword only parameters, e.g. ``(*, a: A, b: B)``
keywords: TupleT[Parameter, ...]
#: variadic keyword parameters, e.g. ``(**kwargs: KWARGS)``
kwargs: OptionalT[Parameter]
#: return type, e.g. ``() -> R``
returns: "Steno"
[docs]class Callable(NamedTuple):
"""Typed positional signature as ``(A, B, /, C, D) -> R``"""
positional: "UnionT[TupleT[Steno, ...], Dots]"
returns: "Steno"
#: Any steno element
Steno = UnionT[
Dots,
Identifier,
Generic,
Any,
Optional,
Tuple,
List,
Dict,
Set,
Literal,
Iterable,
Context,
Awaitable,
AsyncIterable,
AsyncContext,
Signature,
Callable,
]