1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

feat: provide cv2.typing aliases at runtime

This commit is contained in:
Vadim Levin
2023-06-14 17:55:38 +03:00
parent 19f4f2eb92
commit 8e8638431d
3 changed files with 115 additions and 79 deletions
@@ -19,6 +19,17 @@ class TypeNode(abc.ABC):
e.g. `cv::Rect`.
- There is no information about types visibility (see `ASTNodeTypeNode`).
"""
compatible_to_runtime_usage = False
"""Class-wide property that switches exported type names for several nodes.
Example:
>>> node = OptionalTypeNode(ASTNodeTypeNode("Size"))
>>> node.typename # TypeNode.compatible_to_runtime_usage == False
"Size | None"
>>> TypeNode.compatible_to_runtime_usage = True
>>> node.typename
"typing.Optional[Size]"
"""
def __init__(self, ctype_name: str) -> None:
self.ctype_name = ctype_name
@@ -247,11 +258,11 @@ class AliasTypeNode(TypeNode):
"""
def __init__(self, ctype_name: str, value: TypeNode,
export_name: Optional[str] = None,
comment: Optional[str] = None) -> None:
doc: Optional[str] = None) -> None:
super().__init__(ctype_name)
self.value = value
self._export_name = export_name
self.comment = comment
self.doc = doc
@property
def typename(self) -> str:
@@ -287,82 +298,82 @@ class AliasTypeNode(TypeNode):
@classmethod
def int_(cls, ctype_name: str, export_name: Optional[str] = None,
comment: Optional[str] = None):
return cls(ctype_name, PrimitiveTypeNode.int_(), export_name, comment)
doc: Optional[str] = None):
return cls(ctype_name, PrimitiveTypeNode.int_(), export_name, doc)
@classmethod
def float_(cls, ctype_name: str, export_name: Optional[str] = None,
comment: Optional[str] = None):
return cls(ctype_name, PrimitiveTypeNode.float_(), export_name, comment)
doc: Optional[str] = None):
return cls(ctype_name, PrimitiveTypeNode.float_(), export_name, doc)
@classmethod
def array_(cls, ctype_name: str, shape: Optional[Tuple[int, ...]],
dtype: Optional[str] = None, export_name: Optional[str] = None,
comment: Optional[str] = None):
if comment is None:
comment = "Shape: " + str(shape)
doc: Optional[str] = None):
if doc is None:
doc = "Shape: " + str(shape)
else:
comment += ". Shape: " + str(shape)
doc += ". Shape: " + str(shape)
return cls(ctype_name, NDArrayTypeNode(ctype_name, shape, dtype),
export_name, comment)
export_name, doc)
@classmethod
def union_(cls, ctype_name: str, items: Tuple[TypeNode, ...],
export_name: Optional[str] = None,
comment: Optional[str] = None):
doc: Optional[str] = None):
return cls(ctype_name, UnionTypeNode(ctype_name, items),
export_name, comment)
export_name, doc)
@classmethod
def optional_(cls, ctype_name: str, item: TypeNode,
export_name: Optional[str] = None,
comment: Optional[str] = None):
return cls(ctype_name, OptionalTypeNode(item), export_name, comment)
doc: Optional[str] = None):
return cls(ctype_name, OptionalTypeNode(item), export_name, doc)
@classmethod
def sequence_(cls, ctype_name: str, item: TypeNode,
export_name: Optional[str] = None,
comment: Optional[str] = None):
doc: Optional[str] = None):
return cls(ctype_name, SequenceTypeNode(ctype_name, item),
export_name, comment)
export_name, doc)
@classmethod
def tuple_(cls, ctype_name: str, items: Tuple[TypeNode, ...],
export_name: Optional[str] = None,
comment: Optional[str] = None):
doc: Optional[str] = None):
return cls(ctype_name, TupleTypeNode(ctype_name, items),
export_name, comment)
export_name, doc)
@classmethod
def class_(cls, ctype_name: str, class_name: str,
export_name: Optional[str] = None,
comment: Optional[str] = None):
doc: Optional[str] = None):
return cls(ctype_name, ASTNodeTypeNode(class_name),
export_name, comment)
export_name, doc)
@classmethod
def callable_(cls, ctype_name: str,
arg_types: Union[TypeNode, Sequence[TypeNode]],
ret_type: TypeNode = NoneTypeNode("void"),
export_name: Optional[str] = None,
comment: Optional[str] = None):
doc: Optional[str] = None):
return cls(ctype_name,
CallableTypeNode(ctype_name, arg_types, ret_type),
export_name, comment)
export_name, doc)
@classmethod
def ref_(cls, ctype_name: str, alias_ctype_name: str,
alias_export_name: Optional[str] = None,
export_name: Optional[str] = None, comment: Optional[str] = None):
export_name: Optional[str] = None, doc: Optional[str] = None):
return cls(ctype_name,
AliasRefTypeNode(alias_ctype_name, alias_export_name),
export_name, comment)
export_name, doc)
@classmethod
def dict_(cls, ctype_name: str, key_type: TypeNode, value_type: TypeNode,
export_name: Optional[str] = None, comment: Optional[str] = None):
export_name: Optional[str] = None, doc: Optional[str] = None):
return cls(ctype_name, DictTypeNode(ctype_name, key_type, value_type),
export_name, comment)
export_name, doc)
class NDArrayTypeNode(TypeNode):
@@ -543,6 +554,16 @@ class ContainerTypeNode(AggregatedTypeNode):
item.relative_typename(module) for item in self
))
@property
def required_definition_imports(self) -> Generator[str, None, None]:
yield "import typing"
return super().required_definition_imports
@property
def required_usage_imports(self) -> Generator[str, None, None]:
if TypeNode.compatible_to_runtime_usage:
yield "import typing"
return super().required_usage_imports
@abc.abstractproperty
def type_format(self) -> str:
pass
@@ -560,30 +581,22 @@ class SequenceTypeNode(ContainerTypeNode):
super().__init__(ctype_name, (item, ))
@property
def type_format(self):
def type_format(self) -> str:
return "typing.Sequence[{}]"
@property
def types_separator(self):
def types_separator(self) -> str:
return ", "
@property
def required_definition_imports(self) -> Generator[str, None, None]:
yield "import typing"
yield from super().required_definition_imports
@property
def required_usage_imports(self) -> Generator[str, None, None]:
yield "import typing"
yield from super().required_usage_imports
class TupleTypeNode(ContainerTypeNode):
"""Type node representing possibly heterogenous collection of types with
"""Type node representing possibly heterogeneous collection of types with
possibly unspecified length.
"""
@property
def type_format(self):
def type_format(self) -> str:
if TypeNode.compatible_to_runtime_usage:
return "typing.Tuple[{}]"
return "tuple[{}]"
@property
@@ -595,20 +608,34 @@ class UnionTypeNode(ContainerTypeNode):
"""Type node representing type that can be one of the predefined set of types.
"""
@property
def type_format(self):
def type_format(self) -> str:
if TypeNode.compatible_to_runtime_usage:
return "typing.Union[{}]"
return "{}"
@property
def types_separator(self):
def types_separator(self) -> str:
if TypeNode.compatible_to_runtime_usage:
return ", "
return " | "
class OptionalTypeNode(UnionTypeNode):
class OptionalTypeNode(ContainerTypeNode):
"""Type node representing optional type which is effectively is a union
of value type node and None.
"""
def __init__(self, value: TypeNode) -> None:
super().__init__(value.ctype_name, (value, NoneTypeNode(value.ctype_name)))
super().__init__(value.ctype_name, (value,))
@property
def type_format(self) -> str:
if TypeNode.compatible_to_runtime_usage:
return "typing.Optional[{}]"
return "{} | None"
@property
def types_separator(self) -> str:
return ", "
class DictTypeNode(ContainerTypeNode):
@@ -627,11 +654,13 @@ class DictTypeNode(ContainerTypeNode):
return self.items[1]
@property
def type_format(self):
def type_format(self) -> str:
if TypeNode.compatible_to_runtime_usage:
return "typing.Dict[{}]"
return "dict[{}]"
@property
def types_separator(self):
def types_separator(self) -> str:
return ", "