diff --git a/masque/file/dxf.py b/masque/file/dxf.py index 4c30124..7f1ad41 100644 --- a/masque/file/dxf.py +++ b/masque/file/dxf.py @@ -127,7 +127,7 @@ def readfile( filename: Union[str, pathlib.Path], *args, **kwargs, - ) -> Tuple[Pattern, Dict[str, Any]]: + ) -> Tuple[Dict[str, Pattern], Dict[str, Any]]: """ Wrapper for `dxf.read()` that takes a filename or path instead of a stream. diff --git a/masque/file/gdsii.py b/masque/file/gdsii.py index c54cc88..5eb9896 100644 --- a/masque/file/gdsii.py +++ b/masque/file/gdsii.py @@ -19,7 +19,7 @@ Notes: * Creation/modification/access times are set to 1900-01-01 for reproducibility. """ from typing import List, Any, Dict, Tuple, Callable, Union, Iterable, Optional -from typing import Sequence, BinaryIO, Mapping +from typing import Sequence, BinaryIO, Mapping, cast import re import io import mmap @@ -298,7 +298,7 @@ def _gref_to_mref(ref: klamath.library.Reference) -> Ref: repetition = Grid(a_vector=a_vector, b_vector=b_vector, a_count=a_count, b_count=b_count) - ref = Ref( + mref = Ref( target=ref.struct_name.decode('ASCII'), offset=offset, rotation=numpy.deg2rad(ref.angle_deg), @@ -307,7 +307,7 @@ def _gref_to_mref(ref: klamath.library.Reference) -> Ref: annotations=_properties_to_annotations(ref.properties), repetition=repetition, ) - return ref + return mref def _gpath_to_mpath(gpath: klamath.library.Path, raw_mode: bool) -> Path: @@ -341,7 +341,7 @@ def _boundary_to_polygon(boundary: klamath.library.Boundary, raw_mode: bool) -> def _mrefs_to_grefs(refs: List[Ref]) -> List[klamath.library.Reference]: - refs = [] + grefs = [] for ref in refs: if ref.target is None: continue @@ -370,9 +370,9 @@ def _mrefs_to_grefs(refs: List[Ref]) -> List[klamath.library.Reference]: mag=ref.scale, properties=properties, ) - refs.append(aref) + grefs.append(aref) elif rep is None: - ref = klamath.library.Reference( + sref = klamath.library.Reference( struct_name=encoded_name, xy=rint_cast([ref.offset]), colrow=None, @@ -381,7 +381,7 @@ def _mrefs_to_grefs(refs: List[Ref]) -> List[klamath.library.Reference]: mag=ref.scale, properties=properties, ) - refs.append(ref) + grefs.append(sref) else: new_srefs = [ klamath.library.Reference( @@ -394,8 +394,8 @@ def _mrefs_to_grefs(refs: List[Ref]) -> List[klamath.library.Reference]: properties=properties, ) for dd in rep.displacements] - refs += new_srefs - return refs + grefs += new_srefs + return grefs def _properties_to_annotations(properties: Dict[int, bytes]) -> annotations_t: @@ -635,17 +635,17 @@ def load_libraryfile( if is_gzipped(path): if mmap: logger.info('Asked to mmap a gzipped file, reading into memory instead...') - base_stream = gzip.open(path, mode='rb') - stream = io.BytesIO(base_stream.read()) + gz_stream = gzip.open(path, mode='rb') + stream = io.BytesIO(gz_stream.read()) # type: ignore else: - base_stream = gzip.open(path, mode='rb') - stream = io.BufferedReader(base_stream) + gz_stream = gzip.open(path, mode='rb') + stream = io.BufferedReader(gz_stream) # type: ignore else: - base_stream = open(path, mode='rb') if mmap: - stream = mmap.mmap(base_stream.fileno(), 0, access=mmap.ACCESS_READ) + base_stream = open(path, mode='rb', buffering=0) + stream = mmap.mmap(base_stream.fileno(), 0, access=mmap.ACCESS_READ) # type: ignore else: - stream = io.BufferedReader(base_stream) + stream = open(path, mode='rb') return load_library(stream, full_load=full_load) diff --git a/masque/file/oasis.py b/masque/file/oasis.py index 4785f55..543700c 100644 --- a/masque/file/oasis.py +++ b/masque/file/oasis.py @@ -484,8 +484,10 @@ def _placement_to_ref(placement: fatrec.Placement, lib: fatamorgana.OasisLayout) assert(not isinstance(placement.repetition, fatamorgana.ReuseRepetition)) xy = numpy.array((placement.x, placement.y)) mag = placement.magnification if placement.magnification is not None else 1 + pname = placement.get_name() - name = pname if isinstance(pname, int) else pname.string + name: Union[int, str] = pname if isinstance(pname, int) else pname.string # TODO deal with referenced names + annotations = properties_to_annotations(placement.properties, lib.propnames, lib.propstrings) if placement.angle is None: rotation = 0 @@ -506,7 +508,7 @@ def _placement_to_ref(placement: fatrec.Placement, lib: fatamorgana.OasisLayout) def _refs_to_placements( refs: List[Ref], ) -> List[fatrec.Placement]: - refs = [] + placements = [] for ref in refs: if ref.target is None: continue @@ -517,7 +519,7 @@ def _refs_to_placements( offset = rint_cast(ref.offset + rep_offset) angle = numpy.rad2deg(ref.rotation + extra_angle) % 360 - ref = fatrec.Placement( + placement = fatrec.Placement( name=ref.target, flip=mirror_across_x, angle=angle, @@ -528,8 +530,8 @@ def _refs_to_placements( repetition=frep, ) - refs.append(ref) - return refs + placements.append(placement) + return placements def _shapes_to_elements( diff --git a/masque/shapes/path.py b/masque/shapes/path.py index f177d07..ec76bbd 100644 --- a/masque/shapes/path.py +++ b/masque/shapes/path.py @@ -1,4 +1,4 @@ -from typing import List, Tuple, Dict, Optional, Sequence, Any +from typing import List, Tuple, Dict, Optional, Sequence, Any, cast import copy from enum import Enum @@ -365,7 +365,7 @@ class Path(Shape, metaclass=AutoSlots): x_min = rotated_vertices[:, 0].argmin() if not is_scalar(x_min): y_min = rotated_vertices[x_min, 1].argmin() - x_min = x_min[y_min] + x_min = cast(Sequence, x_min)[y_min] reordered_vertices = numpy.roll(rotated_vertices, -x_min, axis=0) width0 = self.width / norm_value diff --git a/masque/shapes/polygon.py b/masque/shapes/polygon.py index 0a05e78..252cf22 100644 --- a/masque/shapes/polygon.py +++ b/masque/shapes/polygon.py @@ -1,4 +1,4 @@ -from typing import List, Dict, Optional, Sequence, Any +from typing import List, Dict, Optional, Sequence, Any, cast import copy import numpy @@ -374,7 +374,7 @@ class Polygon(Shape, metaclass=AutoSlots): x_min = rotated_vertices[:, 0].argmin() if not is_scalar(x_min): y_min = rotated_vertices[x_min, 1].argmin() - x_min = x_min[y_min] + x_min = cast(Sequence, x_min)[y_min] reordered_vertices = numpy.roll(rotated_vertices, -x_min, axis=0) # TODO: normalize mirroring? diff --git a/masque/traits/annotatable.py b/masque/traits/annotatable.py index 3fca734..b10b042 100644 --- a/masque/traits/annotatable.py +++ b/masque/traits/annotatable.py @@ -6,6 +6,9 @@ from ..utils import annotations_t from ..error import MasqueError +_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass + + T = TypeVar('T', bound='Annotatable') I = TypeVar('I', bound='AnnotatableImpl') @@ -33,7 +36,7 @@ class AnnotatableImpl(Annotatable, metaclass=ABCMeta): """ Simple implementation of `Annotatable`. """ - __slots__ = () + __slots__ = _empty_slots _annotations: annotations_t """ Dictionary storing annotation name/value pairs """ @@ -46,7 +49,7 @@ class AnnotatableImpl(Annotatable, metaclass=ABCMeta): return self._annotations @annotations.setter - def annotations(self, annotations: annotations_t): + def annotations(self, annotations: annotations_t) -> None: if not isinstance(annotations, dict): raise MasqueError(f'annotations expected dict, got {type(annotations)}') self._annotations = annotations diff --git a/masque/traits/layerable.py b/masque/traits/layerable.py index c3c6aba..eae2de4 100644 --- a/masque/traits/layerable.py +++ b/masque/traits/layerable.py @@ -4,6 +4,9 @@ from abc import ABCMeta, abstractmethod from ..utils import layer_t +_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass + + T = TypeVar('T', bound='Layerable') I = TypeVar('I', bound='LayerableImpl') @@ -50,7 +53,7 @@ class LayerableImpl(Layerable, metaclass=ABCMeta): """ Simple implementation of Layerable """ - __slots__ = () + __slots__ = _empty_slots _layer: layer_t """ Layer number, pair, or name """ diff --git a/masque/traits/positionable.py b/masque/traits/positionable.py index b7548cb..58c225c 100644 --- a/masque/traits/positionable.py +++ b/masque/traits/positionable.py @@ -9,6 +9,9 @@ from numpy.typing import NDArray, ArrayLike from ..error import MasqueError +_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass + + T = TypeVar('T', bound='Positionable') I = TypeVar('I', bound='PositionableImpl') @@ -85,7 +88,7 @@ class PositionableImpl(Positionable, metaclass=ABCMeta): """ Simple implementation of Positionable """ - __slots__ = () + __slots__ = _empty_slots _offset: NDArray[numpy.float64] """ `[x_offset, y_offset]` """ @@ -108,7 +111,7 @@ class PositionableImpl(Positionable, metaclass=ABCMeta): if val.size != 2: raise MasqueError('Offset must be convertible to size-2 ndarray') - self._offset = val.flatten() + self._offset = val.flatten() # type: ignore ''' ---- Methods diff --git a/masque/traits/repeatable.py b/masque/traits/repeatable.py index 9f032b7..4ec9147 100644 --- a/masque/traits/repeatable.py +++ b/masque/traits/repeatable.py @@ -4,6 +4,9 @@ from abc import ABCMeta, abstractmethod from ..error import MasqueError +_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass + + if TYPE_CHECKING: from ..repetition import Repetition @@ -55,7 +58,7 @@ class RepeatableImpl(Repeatable, metaclass=ABCMeta): """ Simple implementation of `Repeatable` """ - __slots__ = () + __slots__ = _empty_slots _repetition: Optional['Repetition'] """ Repetition object, or None (single instance only) """ diff --git a/masque/traits/rotatable.py b/masque/traits/rotatable.py index add9686..c8b1479 100644 --- a/masque/traits/rotatable.py +++ b/masque/traits/rotatable.py @@ -10,6 +10,9 @@ from ..error import MasqueError from ..utils import is_scalar, rotation_matrix_2d +_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass + + T = TypeVar('T', bound='Rotatable') I = TypeVar('I', bound='RotatableImpl') P = TypeVar('P', bound='Pivotable') @@ -43,7 +46,7 @@ class RotatableImpl(Rotatable, metaclass=ABCMeta): """ Simple implementation of `Rotatable` """ - __slots__ = () + __slots__ = _empty_slots _rotation: float """ rotation for the object, radians counterclockwise """ diff --git a/masque/traits/scalable.py b/masque/traits/scalable.py index ec87c69..2216945 100644 --- a/masque/traits/scalable.py +++ b/masque/traits/scalable.py @@ -5,6 +5,9 @@ from ..error import MasqueError from ..utils import is_scalar +_empty_slots = () # Workaround to get mypy to ignore intentionally empty slots for superclass + + T = TypeVar('T', bound='Scalable') I = TypeVar('I', bound='ScalableImpl') @@ -36,7 +39,7 @@ class ScalableImpl(Scalable, metaclass=ABCMeta): """ Simple implementation of Scalable """ - __slots__ = () + __slots__ = _empty_slots _scale: float """ scale factor for the entity """