From cdf902eda8c2ff551b4b958a95460c942bcb2397 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Wed, 16 Oct 2019 10:07:43 +0100 Subject: node.pyx: Add type information since this module is public Since this module is public and cythonized, it is quite hard for users to get good autocompletion and linting. Adding a type annotation file allows us to allow downstream users to check their code correctly. --- setup.cfg | 2 +- src/buildstream/element.py | 4 +-- src/buildstream/node.pyi | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/buildstream/node.pyi diff --git a/setup.cfg b/setup.cfg index 2264a317c..628d7c4a6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,7 +40,7 @@ ignore_missing_imports=True # Ignore missing stubs for Cythonized modules. # In future, these should be re-enabled by writing stubs for them. -[mypy-buildstream.node,buildstream._loader.*,buildstream._types,buildstream._utils,buildstream._variables] +[mypy-buildstream._loader.*,buildstream._types,buildstream._utils,buildstream._variables] ignore_missing_imports=True # Ignore issues with generated files and vendored code diff --git a/src/buildstream/element.py b/src/buildstream/element.py index 18e2aec7d..7931c49e1 100644 --- a/src/buildstream/element.py +++ b/src/buildstream/element.py @@ -893,7 +893,7 @@ class Element(Plugin): self._stage_sources_in_sandbox(sandbox, directory) - def get_public_data(self, domain: str) -> 'MappingNode[Any, Any]': + def get_public_data(self, domain: str) -> 'MappingNode[Node]': """Fetch public data on this element Args: @@ -918,7 +918,7 @@ class Element(Plugin): return data - def set_public_data(self, domain: str, data: 'MappingNode[Any, Any]') -> None: + def set_public_data(self, domain: str, data: 'MappingNode[Node]') -> None: """Set public data on this element Args: diff --git a/src/buildstream/node.pyi b/src/buildstream/node.pyi new file mode 100644 index 000000000..23db80976 --- /dev/null +++ b/src/buildstream/node.pyi @@ -0,0 +1,71 @@ +from enum import Enum +from typing import Optional, TypeVar, Generic, Union, Dict, Type, Mapping, List, ItemsView, KeysView, ValuesView, Iterator, Any + +from buildstream._project import Project + + +TAllowedScalars = Union[None, bool, int, str] +TAllowedNodeValues = Union[TAllowedScalars, List, Dict[str, Any]] +TSelf = TypeVar("TSelf") + +TNode = TypeVar("TNode", bound='Node') +T = TypeVar("T", bound=TAllowedNodeValues) +TEnum = TypeVar("TEnum", bound=Enum) + + +class Node(Generic[T]): + def clone(self: TSelf) -> TSelf: ... + def from_dict(self, value: Dict[str, TAllowedScalars]) -> MappingNode: ... + def get_provenance(self) -> ProvenanceInformation: ... + def strip_node_info(self) -> T: ... + + +class MappingNode(Node[Dict[str, TNode]]): + def __init__(self, file_index: int, line: int, column: int, value: Dict[str, Node]) -> None: ... + def __contains__(self, item: Node) -> bool: ... + def __delitem__(self, key: str) -> None: ... + def __setitem__(self, key: str, value: Union[Node, TAllowedNodeValues]) -> None: ... + def get_bool(self, key: str, default: Optional[bool]) -> bool: ... + def get_enum(self, key: str, constraint: Type[TEnum], default: Optional[TEnum]) -> TEnum: ... + def get_int(self, key: str, default: Optional[int]) -> int: ... + def get_mapping(self, key: str, default: Optional[Dict[str, TAllowedNodeValues]]) -> MappingNode: ... + def get_node(self, key: str, allowed_types: Optional[List[Type[Node]]], allow_none: bool) -> Node: ... + def get_scalar(self, key: str, default: Optional[TAllowedScalars]) -> None: ... + def get_sequence(self, key: str, default: Optional[List[TAllowedNodeValues]]) -> SequenceNode: ... + def get_str(self, key: str, default=Optional[str]) -> str: ... + def get_str_list(self, key: str, default=Optional[List[str]]) -> List[str]: ... + def items(self) -> ItemsView[str, Node]: ... + def keys(self) -> KeysView[str]: ... + def safe_del(self, key: str) -> None: ... + def validate_keys(self, valid_keys: List[str]) -> None: ... + def values(self) -> ValuesView[Node]: ... + + +class ScalarNode(Node[str]): + def __init__(self, file_index: int, line: int, column: int, value: TAllowedScalars) -> None: ... + def as_bool(self) -> bool: ... + def as_enum(self, constraint: Type[TEnum]) -> TEnum: ... + def as_int(self) -> int: ... + def as_str(self) -> str: ... + def is_none(self) -> bool: ... + + +class SequenceNode(Node[List[TNode]]): + def __init__(self, file_index: int, line: int, column: int, value: List[TNode]) -> None: ... + def __iter__(self) -> Iterator[TNode]: ... + def __len__(self) -> int: ... + def __reversed__(self) -> Iterator[int]: ... + def __setitem__(self, key: str, value: Union[TNode, TAllowedNodeValues]) -> None: ... + def append(self, value: Union[TNode, TAllowedNodeValues]) -> None: ... + def as_str_list(self) -> List[str]: ... + def mapping_at(self, index: int) -> MappingNode: ... + def node_at(self, index: int, allowed_types: Optional[List[Type[TNode]]]) -> Node: ... + def scalar_at(self, index: int) -> ScalarNode: ... + def sequence_at(self, index: int) -> SequenceNode: ... + + +class ProvenanceInformation: ... + + +def _assert_symbol_name(symbol_name: str, purpose: str, *, ref_node=Optional[Node], allow_dashes: bool) -> None: ... +def _new_synthetic_file(filename: str, project: Project): ... -- cgit v1.2.1