Cherry-picked Python type hint enhancements from master

This commit is contained in:
Matthias Koefferlein
2022-10-19 22:13:03 +02:00
parent c9c9d6198b
commit c012bb846e
20 changed files with 3940 additions and 1011 deletions
+74 -1
View File
@@ -1,6 +1,79 @@
import functools
from typing import Type
import klayout.dbcore
from klayout.dbcore import *
from klayout.db.pcell_declaration_helper import PCellDeclarationHelper
__all__ = klayout.dbcore.__all__ + ['PCellDeclarationHelper']
__all__ = klayout.dbcore.__all__ + ["PCellDeclarationHelper"] # type: ignore
# Implementing deepcopy of common objects
# Point-like classes
PointLike = (Point, DPoint, DVector, Vector)
def pyaPoint__deepcopy__(self, memo):
return self.dup()
def convert_type_error_to_not_implemented(cls, method):
"""If cls.method exists raises a TypeError, patch it so
it returns a NotImplemented error instead.
"""
if not hasattr(cls, method):
return
old_func = getattr(cls, method)
@functools.wraps(old_func)
def new_func(*args, **kwargs):
try:
return old_func(*args, **kwargs)
except TypeError:
return NotImplemented
try:
setattr(cls, method, new_func)
except TypeError:
# Some classes are immutable and cannot be changed.
# At the time of writing, this happens to (_StaticAttribute, _AmbiguousMethodDispatcher, _Iterator, _Signal).__or__
return
for PClass in PointLike:
PClass.__deepcopy__ = pyaPoint__deepcopy__ # type: ignore
for cls in klayout.dbcore.__dict__.values():
if not isinstance(cls, type): # skip if not a class
continue
for method in (
"__add__",
"__sub__",
"__mul__",
"__matmul__",
"__truediv__",
"__floordiv__",
"__mod__",
"__divmod__",
"__pow__",
"__lshift__",
"__rshift__",
"__and__",
"__xor__",
"__or__",
):
# list of methods extracted from https://docs.python.org/3.7/reference/datamodel.html#emulating-numeric-types
convert_type_error_to_not_implemented(cls, method)
# If class has from_s, to_s, and assign, use them to
# enable serialization.
for name, cls in klayout.dbcore.__dict__.items():
if not isinstance(cls, type):
continue
if hasattr(cls, 'from_s') and hasattr(cls, 'to_s') and hasattr(cls, 'assign'):
cls.__getstate__ = cls.to_s # type: ignore
def _setstate(self, str):
cls = self.__class__
self.assign(cls.from_s(str))
cls.__setstate__ = _setstate # type: ignore
@@ -63,7 +63,17 @@ class _PCellDeclarationHelper(PCellDeclaration):
self.layer = None
self.cell = None
def param(self, name, value_type, description, hidden=False, readonly=False, unit=None, default=None, choices=None):
def param(
self,
name,
value_type,
description,
hidden=False,
readonly=False,
unit=None,
default=None,
choices=None,
):
"""
Defines a parameter
name -> the short name of the parameter
@@ -84,11 +94,16 @@ class _PCellDeclarationHelper(PCellDeclaration):
# create accessor methods for the parameters
param_index = len(self._param_decls)
setattr(type(self), name, _PCellDeclarationHelperParameterDescriptor(param_index))
setattr(
type(self), name, _PCellDeclarationHelperParameterDescriptor(param_index)
)
if value_type == type(self).TypeLayer:
setattr(type(self), name + "_layer",
_PCellDeclarationHelperLayerDescriptor(len(self._layer_param_index)))
setattr(
type(self),
name + "_layer",
_PCellDeclarationHelperLayerDescriptor(len(self._layer_param_index)),
)
self._layer_param_index.append(param_index)
# store the parameter declarations
@@ -104,10 +119,16 @@ class _PCellDeclarationHelper(PCellDeclaration):
pdecl.unit = unit
if not (choices is None):
if not isinstance(choices, list) and not isinstance(choices, tuple):
raise Exception("choices value must be an list/tuple of two-element arrays (description, value)")
raise Exception(
"choices value must be an list/tuple of two-element arrays (description, value)"
)
for c in choices:
if (not isinstance(choices, list) and not isinstance(choices, tuple)) or len(c) != 2:
raise Exception("choices value must be an list/tuple of two-element arrays (description, value)")
if (
not isinstance(choices, list) and not isinstance(choices, tuple)
) or len(c) != 2:
raise Exception(
"choices value must be an list/tuple of two-element arrays (description, value)"
)
pdecl.add_choice(c[0], c[1])
# return the declaration object for further operations
File diff suppressed because it is too large Load Diff
+30 -16
View File
@@ -1,4 +1,4 @@
from typing import Any, ClassVar, Dict, Iterable, Optional
from typing import Any, ClassVar, Dict, Sequence, List, Iterator, Optional
from typing import overload
import klayout.db as db
class RdbReference:
@@ -19,6 +19,10 @@ class RdbReference:
@return The transformation
@brief Sets the transformation for this reference
"""
def __copy__(self) -> RdbReference:
r"""
@brief Creates a copy of self
"""
def __init__(self, trans: db.DCplxTrans, parent_cell_id: int) -> None:
r"""
@brief Creates a reference with a given transformation and parent cell ID
@@ -136,13 +140,13 @@ class RdbCell:
This method has been introduced in version 0.23.
"""
def each_item(self) -> Iterable[RdbItem]:
def each_item(self) -> Iterator[RdbItem]:
r"""
@brief Iterates over all items inside the database which are associated with this cell
This method has been introduced in version 0.23.
"""
def each_reference(self) -> Iterable[RdbReference]:
def each_reference(self) -> Iterator[RdbReference]:
r"""
@brief Iterates over all references
"""
@@ -236,13 +240,13 @@ class RdbCategory:
This method has been introduced in version 0.23.
"""
def each_item(self) -> Iterable[RdbItem]:
def each_item(self) -> Iterator[RdbItem]:
r"""
@brief Iterates over all items inside the database which are associated with this category
This method has been introduced in version 0.23.
"""
def each_sub_category(self) -> Iterable[RdbCategory]:
def each_sub_category(self) -> Iterator[RdbCategory]:
r"""
@brief Iterates over all sub-categories
"""
@@ -368,6 +372,10 @@ class RdbItemValue:
This variant has been introduced in version 0.24
"""
def __copy__(self) -> RdbItemValue:
r"""
@brief Creates a copy of self
"""
@overload
def __init__(self, b: db.DBox) -> None:
r"""
@@ -414,6 +422,12 @@ class RdbItemValue:
This method has been introduced in version 0.22.
"""
def __repr__(self) -> str:
r"""
@brief Converts a value to a string
The string can be used by the string constructor to create another object from it.
@return The string
"""
def __str__(self) -> str:
r"""
@brief Converts a value to a string
@@ -696,7 +710,7 @@ class RdbItem:
This method has been introduced in version 0.23.
"""
def each_value(self) -> Iterable[RdbItemValue]:
def each_value(self) -> Iterator[RdbItemValue]:
r"""
@brief Iterates over all values
"""
@@ -892,7 +906,7 @@ class ReportDatabase:
@param iter The iterator (a \RecursiveShapeIterator object) from which to take the items
"""
@overload
def create_items(self, cell_id: int, category_id: int, trans: db.CplxTrans, array: Iterable[db.EdgePair]) -> None:
def create_items(self, cell_id: int, category_id: int, trans: db.CplxTrans, array: Sequence[db.EdgePair]) -> None:
r"""
@brief Creates new edge pair items for the given cell/category combination
For each edge pair a single item will be created. The value of the item will be this edge pair.
@@ -906,7 +920,7 @@ class ReportDatabase:
@param edge_pairs The list of edge_pairs for which the items are created
"""
@overload
def create_items(self, cell_id: int, category_id: int, trans: db.CplxTrans, array: Iterable[db.Edge]) -> None:
def create_items(self, cell_id: int, category_id: int, trans: db.CplxTrans, array: Sequence[db.Edge]) -> None:
r"""
@brief Creates new edge items for the given cell/category combination
For each edge a single item will be created. The value of the item will be this edge.
@@ -920,7 +934,7 @@ class ReportDatabase:
@param edges The list of edges for which the items are created
"""
@overload
def create_items(self, cell_id: int, category_id: int, trans: db.CplxTrans, array: Iterable[db.Polygon]) -> None:
def create_items(self, cell_id: int, category_id: int, trans: db.CplxTrans, array: Sequence[db.Polygon]) -> None:
r"""
@brief Creates new polygon items for the given cell/category combination
For each polygon a single item will be created. The value of the item will be this polygon.
@@ -995,29 +1009,29 @@ class ReportDatabase:
@param shapes The shape container from which to take the items
@param trans The transformation to apply
"""
def each_category(self) -> Iterable[RdbCategory]:
def each_category(self) -> Iterator[RdbCategory]:
r"""
@brief Iterates over all top-level categories
"""
def each_cell(self) -> Iterable[RdbCell]:
def each_cell(self) -> Iterator[RdbCell]:
r"""
@brief Iterates over all cells
"""
def each_item(self) -> Iterable[RdbItem]:
def each_item(self) -> Iterator[RdbItem]:
r"""
@brief Iterates over all items inside the database
"""
def each_item_per_category(self, category_id: int) -> Iterable[RdbItem]:
def each_item_per_category(self, category_id: int) -> Iterator[RdbItem]:
r"""
@brief Iterates over all items inside the database which are associated with the given category
@param category_id The ID of the category for which all associated items should be retrieved
"""
def each_item_per_cell(self, cell_id: int) -> Iterable[RdbItem]:
def each_item_per_cell(self, cell_id: int) -> Iterator[RdbItem]:
r"""
@brief Iterates over all items inside the database which are associated with the given cell
@param cell_id The ID of the cell for which all associated items should be retrieved
"""
def each_item_per_cell_and_category(self, cell_id: int, category_id: int) -> Iterable[RdbItem]:
def each_item_per_cell_and_category(self, cell_id: int, category_id: int) -> Iterator[RdbItem]:
r"""
@brief Iterates over all items inside the database which are associated with the given cell and category
@param cell_id The ID of the cell for which all associated items should be retrieved
@@ -1129,7 +1143,7 @@ class ReportDatabase:
This method has been added in version 0.24.
"""
def variants(self, name: str) -> Iterable[int]:
def variants(self, name: str) -> List[int]:
r"""
@brief Gets the variants for a given cell name
@param name The basic name of the cell
+70 -22
View File
@@ -1,8 +1,12 @@
from typing import Any, ClassVar, Dict, Iterable, Optional
from typing import Any, ClassVar, Dict, Sequence, List, Iterator, Optional
from typing import overload
class EmptyClass:
r"""
"""
def __copy__(self) -> EmptyClass:
r"""
@brief Creates a copy of self
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
@@ -64,6 +68,10 @@ class Value:
@brief Gets the actual value.
@brief Set the actual value.
"""
def __copy__(self) -> Value:
r"""
@brief Creates a copy of self
"""
@overload
def __init__(self) -> None:
r"""
@@ -75,6 +83,10 @@ class Value:
@brief Constructs a non-nil object with the given value.
This constructor has been introduced in version 0.22.
"""
def __repr__(self) -> str:
r"""
@brief Convert this object to a string
"""
def __str__(self) -> str:
r"""
@brief Convert this object to a string
@@ -148,14 +160,16 @@ class Interpreter:
This class was introduced in version 0.27.5.
"""
python_interpreter: ClassVar[Interpreter]
r"""
@brief Gets the instance of the Python interpreter
"""
ruby_interpreter: ClassVar[Interpreter]
r"""
@brief Gets the instance of the Ruby interpreter
"""
@classmethod
def python_interpreter(cls) -> Interpreter:
r"""
@brief Gets the instance of the Python interpreter
"""
@classmethod
def ruby_interpreter(cls) -> Interpreter:
r"""
@brief Gets the instance of the Ruby interpreter
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
@@ -279,6 +293,10 @@ class ArgType:
TypeVoidPtr: ClassVar[int]
r"""
"""
def __copy__(self) -> ArgType:
r"""
@brief Creates a copy of self
"""
def __eq__(self, arg0: object) -> bool:
r"""
@brief Equality of two types
@@ -291,6 +309,10 @@ class ArgType:
r"""
@brief Inequality of two types
"""
def __repr__(self) -> str:
r"""
@brief Convert to a string
"""
def __str__(self) -> str:
r"""
@brief Convert to a string
@@ -413,6 +435,10 @@ class MethodOverload:
r"""
@hide
"""
def __copy__(self) -> MethodOverload:
r"""
@brief Creates a copy of self
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
@@ -539,11 +565,11 @@ class Method:
r"""
@brief The documentation string for this method
"""
def each_argument(self) -> Iterable[ArgType]:
def each_argument(self) -> Iterator[ArgType]:
r"""
@brief Iterate over all arguments of this method
"""
def each_overload(self) -> Iterable[MethodOverload]:
def each_overload(self) -> Iterator[MethodOverload]:
r"""
@brief This iterator delivers the synonyms (overloads).
@@ -608,10 +634,11 @@ class Class:
r"""
@hide
"""
each_class: ClassVar[Iterable[Class]]
r"""
@brief Iterate over all classes
"""
@classmethod
def each_class(cls) -> Iterator[Class]:
r"""
@brief Iterate over all classes
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
@@ -673,11 +700,11 @@ class Class:
r"""
@brief The documentation string for this class
"""
def each_child_class(self) -> Iterable[Class]:
def each_child_class(self) -> Iterator[Class]:
r"""
@brief Iterate over all child classes defined within this class
"""
def each_method(self) -> Iterable[Method]:
def each_method(self) -> Iterator[Method]:
r"""
@brief Iterate over all methods of this class
"""
@@ -801,16 +828,25 @@ class Timer:
This class has been introduced in version 0.23.
"""
memory_size: ClassVar[int]
r"""
@brief Gets the current memory usage of the process in Bytes
@classmethod
def memory_size(cls) -> int:
r"""
@brief Gets the current memory usage of the process in Bytes
This method has been introduced in version 0.27.
"""
This method has been introduced in version 0.27.
"""
def __copy__(self) -> Timer:
r"""
@brief Creates a copy of self
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
"""
def __repr__(self) -> str:
r"""
@brief Produces a string with the currently elapsed times
"""
def __str__(self) -> str:
r"""
@brief Produces a string with the currently elapsed times
@@ -1229,6 +1265,10 @@ class ExpressionContext:
This class has been introduced in version 0.26 when \Expression was separated into the execution and context part.
"""
def __copy__(self) -> ExpressionContext:
r"""
@brief Creates a copy of self
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class
@@ -1384,6 +1424,10 @@ class GlobPattern:
@brief Sets a value indicating whether trailing characters are allowed.
If this predicate is false, the glob pattern needs to match the full subject string. If true, the match function will ignore trailing characters and return true if the front part of the subject string matches.
"""
def __copy__(self) -> GlobPattern:
r"""
@brief Creates a copy of self
"""
def __init__(self, pattern: str) -> None:
r"""
@brief Creates a new glob pattern match object
@@ -1444,6 +1488,10 @@ class ExecutableBase:
@hide
@alias Executable
"""
def __copy__(self) -> ExecutableBase:
r"""
@brief Creates a copy of self
"""
def __init__(self) -> None:
r"""
@brief Creates a new object of this class