mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-05 00:53:00 +02:00
Cherry-picked Python type hint enhancements from master
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user