flake8-aided fixes

This commit is contained in:
Jan Petykiewicz 2023-01-23 22:27:26 -08:00 committed by jan
commit 6b01b43559
29 changed files with 241 additions and 349 deletions

View file

@ -1,7 +1,7 @@
"""
DXF file format readers and writers
"""
from typing import List, Any, Dict, Tuple, Callable, Union, Sequence, Iterable, Mapping
from typing import List, Any, Dict, Tuple, Callable, Union, Iterable, Mapping
import re
import io
import base64
@ -17,7 +17,6 @@ from .. import Pattern, Ref, PatternError, Label, Shape
from ..shapes import Polygon, Path
from ..repetition import Grid
from ..utils import rotation_matrix_2d, layer_t
from .gdsii import check_valid_names
logger = logging.getLogger(__name__)
@ -52,8 +51,11 @@ def write(
DXF does not support shape repetition (only block repeptition). Please call
library.wrap_repeated_shapes() before writing to file.
If you want pattern polygonized with non-default arguments, just call `pattern.polygonize()`
prior to calling this function.
Other functions you may want to call:
- `masque.file.oasis.check_valid_names(library.keys())` to check for invalid names
- `library.dangling_references()` to check for references to missing patterns
- `pattern.polygonize()` for any patterns with shapes other
than `masque.shapes.Polygon` or `masque.shapes.Path`
Only `Grid` repetition objects with manhattan basis vectors are preserved as arrays. Since DXF
rotations apply to basis vectors while `masque`'s rotations do not, the basis vectors of an
@ -70,8 +72,6 @@ def write(
"""
#TODO consider supporting DXF arcs?
check_valid_names(library.keys())
pattern = library[top_name]
# Create library
@ -83,7 +83,7 @@ def write(
# Now create a block for each referenced pattern, and add in any shapes
for name, pat in library.items():
assert(pat is not None)
assert pat is not None
block = lib.blocks.new(name=name)
_shapes_to_elements(block, pat.shapes)
@ -173,8 +173,9 @@ def read(
msp = lib.modelspace()
npat = _read_block(msp, clean_vertices)
patterns_dict = dict([npat]
+ [_read_block(bb, clean_vertices) for bb in lib.blocks if bb.name != '*Model_Space'])
patterns_dict = dict(
[npat] + [_read_block(bb, clean_vertices) for bb in lib.blocks if bb.name != '*Model_Space']
)
library_info = {
'layers': [ll.dxfattribs() for ll in lib.layers]
@ -323,8 +324,10 @@ def _shapes_to_elements(
# Could set do paths with width setting, but need to consider endcaps.
for shape in shapes:
if shape.repetition is not None:
raise PatternError('Shape repetitions are not supported by DXF.'
' Please call library.wrap_repeated_shapes() before writing to file.')
raise PatternError(
'Shape repetitions are not supported by DXF.'
' Please call library.wrap_repeated_shapes() before writing to file.'
)
attribs = {'layer': _mlayer2dxf(shape.layer)}
for polygon in shape.to_polygons():

View file

@ -18,14 +18,10 @@ Notes:
* GDS does not support library- or structure-level annotations
* 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, cast
import re
from typing import List, Any, Dict, Tuple, Callable, Union, Iterable
from typing import BinaryIO, Mapping
import io
import mmap
import copy
import base64
import struct
import logging
import pathlib
import gzip
@ -83,10 +79,13 @@ def write(
otherwise `0`
GDS does not support shape repetition (only cell repeptition). Please call
library.wrap_repeated_shapes() before writing to file.
`library.wrap_repeated_shapes()` before writing to file.
If you want pattern polygonized with non-default arguments, just call `pattern.polygonize()`
prior to calling this function.
Other functions you may want to call:
- `masque.file.gdsii.check_valid_names(library.keys())` to check for invalid names
- `library.dangling_references()` to check for references to missing patterns
- `pattern.polygonize()` for any patterns with shapes other
than `masque.shapes.Polygon` or `masque.shapes.Path`
Args:
library: A {name: Pattern} mapping of patterns to write.
@ -98,10 +97,6 @@ def write(
library_name: Library name written into the GDSII file.
Default 'masque-klamath'.
"""
check_valid_names(library.keys())
# TODO check all hierarchy present
if not isinstance(library, MutableLibrary):
if isinstance(library, dict):
library = WrapLibrary(library)
@ -433,7 +428,7 @@ def _shapes_to_elements(
for shape in shapes:
if shape.repetition is not None:
raise PatternError('Shape repetitions are not supported by GDS.'
' Please call library.wrap_repeated_shapes() before writing to file.')
' Please call library.wrap_repeated_shapes() before writing to file.')
layer, data_type = _mlayer2gds(shape.layer)
properties = _annotations_to_properties(shape.annotations, 128)
@ -504,56 +499,6 @@ def _labels_to_texts(labels: List[Label]) -> List[klamath.elements.Text]:
return texts
def disambiguate_pattern_names(
names: Iterable[str],
max_name_length: int = 32,
suffix_length: int = 6,
) -> List[str]:
"""
Args:
names: List of pattern names to disambiguate
max_name_length: Names longer than this will be truncated
suffix_length: Names which get truncated are truncated by this many extra characters. This is to
leave room for a suffix if one is necessary.
"""
new_names = []
for name in names:
# Shorten names which already exceed max-length
if len(name) > max_name_length:
shortened_name = name[:max_name_length - suffix_length]
logger.warning(f'Pattern name "{name}" is too long ({len(name)}/{max_name_length} chars),\n'
+ f' shortening to "{shortened_name}" before generating suffix')
else:
shortened_name = name
# Remove invalid characters
sanitized_name = re.compile(r'[^A-Za-z0-9_\?\$]').sub('_', shortened_name)
# Add a suffix that makes the name unique
i = 0
suffixed_name = sanitized_name
while suffixed_name in new_names or suffixed_name == '':
suffix = base64.b64encode(struct.pack('>Q', i), b'$?').decode('ASCII')
suffixed_name = sanitized_name + '$' + suffix[:-1].lstrip('A')
i += 1
if sanitized_name == '':
logger.warning(f'Empty pattern name saved as "{suffixed_name}"')
# Encode into a byte-string and perform some final checks
encoded_name = suffixed_name.encode('ASCII')
if len(encoded_name) == 0:
# Should never happen since zero-length names are replaced
raise PatternError(f'Zero-length name after sanitize+encode,\n originally "{name}"')
if len(encoded_name) > max_name_length:
raise PatternError(f'Pattern name "{encoded_name!r}" length > {max_name_length} after encode,\n'
+ f' originally "{name}"')
new_names.append(suffixed_name)
return new_names
def load_library(
stream: BinaryIO,
*,

View file

@ -12,11 +12,7 @@ Note that OASIS references follow the same convention as `masque`,
vectors or offsets.
"""
from typing import List, Any, Dict, Tuple, Callable, Union, Sequence, Iterable, Mapping, Optional, cast
import re
import io
import copy
import base64
import struct
import logging
import pathlib
import gzip
@ -77,8 +73,11 @@ def build(
If a layer map is provided, layer strings will be converted
automatically, and layer names will be written to the file.
If you want pattern polygonized with non-default arguments, just call `pattern.polygonize()`
prior to calling this function.
Other functions you may want to call:
- `masque.file.oasis.check_valid_names(library.keys())` to check for invalid names
- `library.dangling_references()` to check for references to missing patterns
- `pattern.polygonize()` for any patterns with shapes other
than `masque.shapes.Polygon`, `masque.shapes.Path`, or `masque.shapes.Circle`
Args:
library: A {name: Pattern} mapping of patterns to write.
@ -97,10 +96,6 @@ def build(
Returns:
`fatamorgana.OasisLayout`
"""
check_valid_names(library.keys())
# TODO check all hierarchy present
if not isinstance(library, MutableLibrary):
if isinstance(library, dict):
library = WrapLibrary(library)
@ -130,7 +125,7 @@ def build(
for tt in (True, False)]
def layer2oas(mlayer: layer_t) -> Tuple[int, int]:
assert(layer_map is not None)
assert layer_map is not None
layer_num = layer_map[mlayer] if isinstance(mlayer, str) else mlayer
return _mlayer2oas(layer_num)
else:
@ -270,7 +265,7 @@ def read(
# note XELEMENT has no repetition
continue
assert(not isinstance(element.repetition, fatamorgana.ReuseRepetition))
assert not isinstance(element.repetition, fatamorgana.ReuseRepetition)
repetition = repetition_fata2masq(element.repetition)
# Switch based on element type:
@ -481,7 +476,7 @@ def _placement_to_ref(placement: fatrec.Placement, lib: fatamorgana.OasisLayout)
"""
Helper function to create a Ref from a placment. Sets ref.target to the placement name.
"""
assert(not isinstance(placement.repetition, fatamorgana.ReuseRepetition))
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
@ -659,7 +654,7 @@ def repetition_masq2fata(
frep = fatamorgana.ArbitraryRepetition(diff_ints[:, 0], diff_ints[:, 1]) # type: ignore
offset = rep.displacements[0, :]
else:
assert(rep is None)
assert rep is None
frep = None
offset = (0, 0)
return frep, offset
@ -682,14 +677,14 @@ def properties_to_annotations(
) -> annotations_t:
annotations = {}
for proprec in properties:
assert(proprec.name is not None)
assert proprec.name is not None
if isinstance(proprec.name, int):
key = propnames[proprec.name].string
else:
key = proprec.name.string
values: List[Union[str, float, int]] = []
assert(proprec.values is not None)
assert proprec.values is not None
for value in proprec.values:
if isinstance(value, (float, int)):
values.append(value)

View file

@ -1,7 +1,7 @@
"""
SVG file format readers and writers
"""
from typing import Dict, Optional, Mapping
from typing import Mapping
import warnings
import numpy

View file

@ -1,14 +1,11 @@
"""
Helper functions for file reading and writing
"""
from typing import Set, Tuple, List, Iterable, Mapping
import re
import copy
import pathlib
import logging
from .. import Pattern, PatternError
from ..library import Library, WrapROLibrary
from ..shapes import Polygon, Path