Compare commits

..

No commits in common. "968392a4a32956a6b85112673908516249f1a021" and "7efc5a39d4b8e549040a47786b0858a477d7acaa" have entirely different histories.

24 changed files with 3102 additions and 3043 deletions

View File

@ -27,4 +27,3 @@ ignore =
per-file-ignores = per-file-ignores =
# F401 import without use # F401 import without use
*/__init__.py: F401, */__init__.py: F401,
__init__.py: F401,

View File

@ -3,8 +3,6 @@
**fatamorgana** is a Python package for reading and writing OASIS format layout files. **fatamorgana** is a Python package for reading and writing OASIS format layout files.
**Homepage:** https://mpxd.net/code/jan/fatamorgana **Homepage:** https://mpxd.net/code/jan/fatamorgana
* [PyPI](https://pypi.org/project/fatamorgana)
* [Github mirror](https://github.com/anewusername/fatamorgana)
**Capabilities:** **Capabilities:**
* This package is a work-in-progress and is largely untested -- it works for * This package is a work-in-progress and is largely untested -- it works for
@ -22,7 +20,7 @@
## Installation ## Installation
**Dependencies:** **Dependencies:**
* python >=3.11 * python 3.5 or newer
* (optional) numpy * (optional) numpy

View File

@ -15,7 +15,7 @@
numpy to speed up reading/writing. numpy to speed up reading/writing.
Dependencies: Dependencies:
- Python 3.11 or later - Python 3.8 or later
- numpy (optional, faster but no additional functionality) - numpy (optional, faster but no additional functionality)
To get started, try: To get started, try:
@ -24,28 +24,17 @@
help(fatamorgana.OasisLayout) help(fatamorgana.OasisLayout)
``` ```
""" """
from .main import ( import pathlib
OasisLayout as OasisLayout,
Cell as Cell, from .main import OasisLayout, Cell, XName
XName as XName,
)
from .basic import ( from .basic import (
NString as NString, NString, AString, Validation, OffsetTable, OffsetEntry,
AString as AString, EOFError, SignedError, InvalidDataError, InvalidRecordError,
Validation as Validation, UnfilledModalError,
OffsetTable as OffsetTable, ReuseRepetition, GridRepetition, ArbitraryRepetition
OffsetEntry as OffsetEntry,
EOFError as EOFError,
SignedError as SignedError,
InvalidDataError as InvalidDataError,
InvalidRecordError as InvalidRecordError,
UnfilledModalError as UnfilledModalError,
ReuseRepetition as ReuseRepetition,
GridRepetition as GridRepetition,
ArbitraryRepetition as ArbitraryRepetition,
) )
__author__ = 'Jan Petykiewicz' __author__ = 'Jan Petykiewicz'
__version__ = '0.13' __version__ = '0.12'
version = __version__ version = __version__

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ This module contains data structures and functions for reading from and
writing to whole OASIS layout files, and provides a few additional writing to whole OASIS layout files, and provides a few additional
abstractions for the data contained inside them. abstractions for the data contained inside them.
""" """
from typing import IO from typing import List, Dict, Union, Optional, Type
import io import io
import logging import logging
@ -27,20 +27,20 @@ class FileModals:
""" """
File-scoped modal variables File-scoped modal variables
""" """
cellname_implicit: bool | None = None cellname_implicit: Optional[bool] = None
propname_implicit: bool | None = None propname_implicit: Optional[bool] = None
xname_implicit: bool | None = None xname_implicit: Optional[bool] = None
textstring_implicit: bool | None = None textstring_implicit: Optional[bool] = None
propstring_implicit: bool | None = None propstring_implicit: Optional[bool] = None
property_target: list[records.Property] property_target: List[records.Property]
within_cell: bool = False within_cell: bool = False
within_cblock: bool = False within_cblock: bool = False
end_has_offset_table: bool = False end_has_offset_table: bool = False
started: bool = False started: bool = False
def __init__(self, property_target: list[records.Property]) -> None: def __init__(self, property_target: List[records.Property]):
self.property_target = property_target self.property_target = property_target
@ -53,49 +53,43 @@ class OasisLayout:
record objects. record objects.
Cells are stored using `Cell` objects (different from `records.Cell` Cells are stored using `Cell` objects (different from `records.Cell`
record objects). record objects).
Attributes:
(File properties)
version (AString): Version string ('1.0')
unit (real_t): grid steps per micron
validation (Validation): checksum data
(Names)
cellnames (Dict[int, CellName]): Cell names
propnames (Dict[int, NString]): Property names
xnames (Dict[int, XName]): Custom names
(Strings)
textstrings (Dict[int, AString]): Text strings
propstrings (Dict[int, AString]): Property strings
(Data)
layers (List[records.LayerName]): Layer definitions
properties (List[records.Property]): Property values
cells (List[Cell]): Layout cells
""" """
# File properties
version: AString version: AString
"""File format version string ('1.0')"""
unit: real_t unit: real_t
"""grid steps per micron"""
validation: Validation validation: Validation
"""checksum data"""
# Data properties: List[records.Property]
properties: list[records.Property] cells: List['Cell']
"""Property values"""
cells: list['Cell'] cellnames: Dict[int, 'CellName']
"""Layout cells""" propnames: Dict[int, NString]
xnames: Dict[int, 'XName']
layers: list[records.LayerName] textstrings: Dict[int, AString]
"""Layer definitions""" propstrings: Dict[int, AString]
layers: List[records.LayerName]
# Names def __init__(self, unit: real_t, validation: Validation = None):
cellnames: dict[int, 'CellName']
"""Cell names"""
propnames: dict[int, NString]
"""Property names"""
xnames: dict[int, 'XName']
"""Custom names"""
# String storage
textstrings: dict[int, AString]
"""Text strings"""
propstrings: dict[int, AString]
"""Property strings"""
def __init__(
self,
unit: real_t,
validation: Validation | None = None,
) -> None:
""" """
Args: Args:
unit: Real number (i.e. int, float, or `Fraction`), grid steps per micron. unit: Real number (i.e. int, float, or `Fraction`), grid steps per micron.
@ -118,7 +112,7 @@ class OasisLayout:
self.layers = [] self.layers = []
@staticmethod @staticmethod
def read(stream: IO[bytes]) -> 'OasisLayout': def read(stream: io.BufferedIOBase) -> 'OasisLayout':
""" """
Read an entire .oas file into an `OasisLayout` object. Read an entire .oas file into an `OasisLayout` object.
@ -138,12 +132,11 @@ class OasisLayout:
pass pass
return layout return layout
def read_record( def read_record(self,
self, stream: io.BufferedIOBase,
stream: IO[bytes], modals: Modals,
modals: Modals, file_state: FileModals
file_state: FileModals ) -> bool:
) -> bool:
""" """
Read a single record of unspecified type from a stream, adding its Read a single record of unspecified type from a stream, adding its
contents into this `OasisLayout` object. contents into this `OasisLayout` object.
@ -163,12 +156,13 @@ class OasisLayout:
""" """
try: try:
record_id = read_uint(stream) record_id = read_uint(stream)
except EOFError: except EOFError as e:
if file_state.within_cblock: if file_state.within_cblock:
return True return True
raise else:
raise e
logger.info(f'read_record of type {record_id} at position 0x{stream.tell():x}') logger.info('read_record of type {} at position 0x{:x}'.format(record_id, stream.tell()))
record: Record record: Record
@ -188,11 +182,12 @@ class OasisLayout:
# Make sure order is valid (eg, no out-of-cell geometry) # Make sure order is valid (eg, no out-of-cell geometry)
if not file_state.started and record_id != 1: if not file_state.started and record_id != 1:
raise InvalidRecordError(f'Non-Start record {record_id} before Start') raise InvalidRecordError('Non-Start record {} before Start'.format(record_id))
if record_id == 1: if record_id == 1:
if file_state.started: if file_state.started:
raise InvalidRecordError('Duplicate Start record') raise InvalidRecordError('Duplicate Start record')
file_state.started = True else:
file_state.started = True
if record_id == 2 and file_state.within_cblock: if record_id == 2 and file_state.within_cblock:
raise InvalidRecordError('End within CBlock') raise InvalidRecordError('End within CBlock')
@ -202,11 +197,11 @@ class OasisLayout:
file_state.within_cell = False file_state.within_cell = False
elif record_id in range(15, 28) or record_id in (32, 33): elif record_id in range(15, 28) or record_id in (32, 33):
if not file_state.within_cell: if not file_state.within_cell:
raise InvalidRecordError('Geometry outside Cell') raise Exception('Geometry outside Cell')
elif record_id in (13, 14): elif record_id in (13, 14):
file_state.within_cell = True file_state.within_cell = True
else: else:
raise InvalidRecordError(f'Unknown record id: {record_id}') raise InvalidRecordError('Unknown record id: {}'.format(record_id))
if record_id == 0: if record_id == 0:
''' Pad ''' ''' Pad '''
@ -340,10 +335,10 @@ class OasisLayout:
self.cells[-1].geometry.append(record) self.cells[-1].geometry.append(record)
file_state.property_target = record.properties file_state.property_target = record.properties
else: else:
raise InvalidRecordError(f'Unknown record id: {record_id}') raise InvalidRecordError('Unknown record id: {}'.format(record_id))
return False return False
def write(self, stream: IO[bytes]) -> int: def write(self, stream: io.BufferedIOBase) -> int:
""" """
Write this object in OASIS fromat to a stream. Write this object in OASIS fromat to a stream.
@ -404,28 +399,32 @@ class OasisLayout:
class Cell: class Cell:
""" """
Representation of an OASIS cell. Representation of an OASIS cell.
Attributes:
name (Union[NString, int]): name or "CellName reference" number
properties (List[records.Property]): Properties of this cell
placements (List[records.Placement]): Placement record objects
geometry: (List[records.geometry_t]): Geometry record objectes
""" """
name: NString | int name: Union[NString, int]
"""name or "CellName reference" number""" properties: List[records.Property]
placements: List[records.Placement]
geometry: List[records.geometry_t]
properties: list[records.Property] def __init__(self,
placements: list[records.Placement] name: Union[NString, str, int],
geometry: list[records.geometry_t] *,
properties: Optional[List[records.Property]] = None,
def __init__( placements: Optional[List[records.Placement]] = None,
self, geometry: Optional[List[records.geometry_t]] = None,
name: NString | str | int, ):
*, self.name = name if isinstance(name, (NString, int)) else NString(name)
properties: list[records.Property] | None = None,
placements: list[records.Placement] | None = None,
geometry: list[records.geometry_t] | None = None,
) -> None:
self.name = name if isinstance(name, NString | int) else NString(name)
self.properties = [] if properties is None else properties self.properties = [] if properties is None else properties
self.placements = [] if placements is None else placements self.placements = [] if placements is None else placements
self.geometry = [] if geometry is None else geometry self.geometry = [] if geometry is None else geometry
def dedup_write(self, stream: IO[bytes], modals: Modals) -> int: def dedup_write(self, stream: io.BufferedIOBase, modals: Modals) -> int:
""" """
Write this cell to a stream, using the provided modal variables to Write this cell to a stream, using the provided modal variables to
deduplicate any repeated data. deduplicate any repeated data.
@ -459,13 +458,11 @@ class CellName:
with the reference data stripped out. with the reference data stripped out.
""" """
nstring: NString nstring: NString
properties: list[records.Property] properties: List[records.Property]
def __init__( def __init__(self,
self, nstring: Union[NString, str],
nstring: NString | str, properties: Optional[List[records.Property]] = None):
properties: list[records.Property] | None = None,
) -> None:
""" """
Args: Args:
nstring: The contained string. nstring: The contained string.
@ -502,7 +499,7 @@ class XName:
attribute: int attribute: int
bstring: bytes bstring: bytes
def __init__(self, attribute: int, bstring: bytes) -> None: def __init__(self, attribute: int, bstring: bytes):
""" """
Args: Args:
attribute: Attribute number. attribute: Attribute number.
@ -526,7 +523,7 @@ class XName:
# Mapping from record id to record class. # Mapping from record id to record class.
_GEOMETRY: dict[int, type[records.geometry_t]] = { _GEOMETRY: Dict[int, Type[records.geometry_t]] = {
19: records.Text, 19: records.Text,
20: records.Rectangle, 20: records.Rectangle,
21: records.Polygon, 21: records.Polygon,

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
""" '''
Build files equivalent to the test cases used by KLayout. Build files equivalent to the test cases used by KLayout.
""" '''
# type: ignore
from typing import IO from typing import Callable
from collections.abc import Callable from io import BufferedIOBase
from pathlib import Path
from . import ( from . import (
@ -12,13 +12,12 @@ from . import (
test_files_circles, test_files_ctrapezoids, test_files_trapezoids, test_files_circles, test_files_ctrapezoids, test_files_trapezoids,
test_files_placements, test_files_paths, test_files_modals, test_files_placements, test_files_paths, test_files_modals,
test_files_polygons, test_files_rectangles, test_files_empty, test_files_polygons, test_files_rectangles, test_files_empty,
test_files_texts, test_files_cells, test_files_texts, test_files_cells)
)
def build_file(num: str, func: Callable[[IO[bytes]], IO[bytes]]) -> None: def build_file(num: str, func: Callable[[BufferedIOBase], BufferedIOBase]) -> None:
with Path('t' + num + '.oas').open('wb') as ff: with open('t' + num + '.oas', 'wb') as f:
func(ff) func(f)
def write_all_files() -> None: def write_all_files() -> None:

View File

@ -1,11 +1,17 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO
from io import BytesIO
from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
import numpy
from numpy.testing import assert_equal from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte, PathExtensionScheme
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -26,9 +32,9 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.cells[0].properties assert not layout.cells[0].properties
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
@ -92,105 +98,86 @@ def test_file_1() -> None:
assert geometry[1].height == 610 assert geometry[1].height == 610
assert geometry[1].width == 680 assert geometry[1].width == 680
assert_equal(geometry[2].point_list, [ assert_equal(geometry[2].point_list,
[-30, -360], [[-30, -360], [480, -50], [180, 430], [-630, -20]])
[480, -50],
[180, 430],
[-630, -20],
])
assert_equal(geometry[3].point_list, [ assert_equal(geometry[3].point_list,
[-30, -400], [[-30, -400],
[450, 40], [450, 40],
[70, -220], [70, -220],
[10, 210], [10, 210],
[740, -20], [740, -20],
[0, 660], [0, 660],
[570, 10], [570, 10],
[50, 500], [50, 500],
[630, 20], [630, 20],
[10, 100], [10, 100],
[-810, 10], [-810, 10],
[20, -470], [20, -470],
[-660, 0], [-660, 0],
[20, -470], [20, -470],
[-620, 10], [-620, 10],
[0, 610], [0, 610],
[610, -10], [610, -10],
[0, -100], [0, -100],
[210, 10], [210, 10],
[40, 820], [40, 820],
[-1340, 60], [-1340, 60],
[30, -1370], [30, -1370]])
])
assert_equal(geometry[4].point_list, [ assert_equal(geometry[4].point_list,
[40, -760], [[40, -760], [490, -50], [110, 800], [-640, 10]])
[490, -50],
[110, 800],
[-640, 10],
])
assert_equal(geometry[5].point_list, [ assert_equal(geometry[5].point_list,
[140, -380], [[140, -380],
[340, -10], [340, -10],
[30, -100], [30, -100],
[-320, 20], [-320, 20],
[130, -460], [130, -460],
[-480, -20], [-480, -20],
[-210, 910], [-210, 910],
[370, 40], [370, 40]])
])
assert_equal(geometry[6].point_list, [ assert_equal(geometry[6].point_list,
[720, -20], [[720, -20],
[20, 20], [20, 20],
[690, 0], [690, 0],
[-10, 650], [-10, 650],
[-20, 30], [-20, 30],
[-90, -10], [-90, -10],
[10, 70], [10, 70],
[470, -30], [470, -30],
[20, -120], [20, -120],
[-320, 0], [-320, 0],
[40, -790], [40, -790],
[-90, -20], [-90, -20],
[-60, 140], [-60, 140],
[-1390, 50], [-1390, 50],
[10, 30], [10, 30]])
])
assert_equal(geometry[7].point_list, [ assert_equal(geometry[7].point_list,
[150, -830], [[150, -830],
[-1320, 40], [-1320, 40],
[-70, 370], [-70, 370],
[310, -30], [310, -30],
[10, 220], [10, 220],
[250, -40], [250, -40],
[40, -220], [40, -220],
[340, 10], [340, 10],
[-20, 290], [-20, 290],
[-1070, 20], [-1070, 20],
[0, 230], [0, 230],
[1380, -60], [1380, -60]])
])
assert_equal(geometry[8].point_list, [ assert_equal(geometry[8].point_list,
[330, 0], [[330, 0], [-10, 480], [620, -20], [-10, 330], [-930, 60], [0, -850]])
[-10, 480],
[620, -20],
[-10, 330],
[-930, 60],
[0, -850],
])
assert_equal(geometry[9].point_list, [ assert_equal(geometry[9].point_list,
[-140, -410], [[-140, -410],
[10, -140], [10, -140],
[270, 0], [270, 0],
[130, 1030], [130, 1030],
[-500, 50], [-500, 50],
[10, -330], [10, -330],
[210, -10], [210, -10],
[10, -190], [10, -190]])
])

View File

@ -1,11 +1,14 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO
from io import BytesIO
import pytest from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_bstring from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring
from ..basic import InvalidRecordError, InvalidDataError from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -23,10 +26,10 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.layers assert not layout.layers
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
Single cell with explicit name 'XYZ' Single cell with explicit name 'XYZ'
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
@ -48,10 +51,10 @@ def test_file_1() -> None:
assert not layout.cellnames assert not layout.cellnames
def write_file_2(buf: IO[bytes]) -> IO[bytes]: def write_file_2(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
Two cellnames ('XYZ', 'ABC') and two cells with name references. Two cellnames ('XYZ', 'ABC') and two cells with name references.
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 3) # CELLNAME record (implicit id 0) write_uint(buf, 3) # CELLNAME record (implicit id 0)
@ -85,10 +88,10 @@ def test_file_2() -> None:
assert layout.cells[1].name == 1 assert layout.cells[1].name == 1
def write_file_3(buf: IO[bytes]) -> IO[bytes]: def write_file_3(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
Invalid file, contains a mix of explicit and implicit cellnames Invalid file, contains a mix of explicit and implicit cellnames
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 4) # CELLNAME record (explicit id) write_uint(buf, 4) # CELLNAME record (explicit id)
@ -113,13 +116,13 @@ def test_file_3() -> None:
buf.seek(0) buf.seek(0)
with pytest.raises(InvalidRecordError): with pytest.raises(InvalidRecordError):
_layout = OasisLayout.read(buf) layout = OasisLayout.read(buf)
def write_file_4(buf: IO[bytes]) -> IO[bytes]: def write_file_4(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
Two cells referencing two names with explicit ids (unsorted) Two cells referencing two names with explicit ids (unsorted)
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 4) # CELLNAME record (explicit id) write_uint(buf, 4) # CELLNAME record (explicit id)
@ -155,10 +158,10 @@ def test_file_4() -> None:
assert layout.cells[1].name == 1 assert layout.cells[1].name == 1
def write_file_5(buf: IO[bytes]) -> IO[bytes]: def write_file_5(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
Reference to non-existent cell name. Reference to non-existent cell name.
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 4) # CELLNAME record (explicit id) write_uint(buf, 4) # CELLNAME record (explicit id)
@ -196,10 +199,10 @@ def test_file_5() -> None:
#TODO add optional error checking for this case #TODO add optional error checking for this case
def write_file_6(buf: IO[bytes]) -> IO[bytes]: def write_file_6(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
Cellname with invalid n-string. Cellname with invalid n-string.
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 4) # CELLNAME record (explicit id) write_uint(buf, 4) # CELLNAME record (explicit id)
@ -226,7 +229,7 @@ def test_file_6() -> None:
buf.seek(0) buf.seek(0)
with pytest.raises(InvalidDataError): with pytest.raises(InvalidDataError):
_layout = OasisLayout.read(buf) layout = OasisLayout.read(buf)
#base_tests(layout) #base_tests(layout)
#assert len(layout.cellnames) == 2 #assert len(layout.cellnames) == 2
@ -237,10 +240,10 @@ def test_file_6() -> None:
#assert layout.cells[1].name == 1 #assert layout.cells[1].name == 1
def write_file_7(buf: IO[bytes]) -> IO[bytes]: def write_file_7(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
Unused cellname. Unused cellname.
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 4) # CELLNAME record (explicit id) write_uint(buf, 4) # CELLNAME record (explicit id)

View File

@ -1,9 +1,17 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO
from io import BytesIO from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
import numpy
from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte, PathExtensionScheme
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -24,57 +32,57 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.cells[0].properties assert not layout.cells[0].properties
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'A') # Cell name write_bstring(buf, b'A') # Cell name
write_uint(buf, 27) # CIRCLE record write_uint(buf, 27) # CIRCLE record
write_byte(buf, 0b0011_1011) # 00rX_YRDL write_byte(buf, 0b0011_1011) # 00rX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 150) # radius write_uint(buf, 150) # radius
write_sint(buf, -100) # geometry-x (absolute) write_sint(buf, -100) # geometry-x (absolute)
write_sint(buf, 200) # geometry-y (absolute) write_sint(buf, 200) # geometry-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
write_uint(buf, 27) # CIRCLE record write_uint(buf, 27) # CIRCLE record
write_byte(buf, 0b0000_1000) # 00rX_YRDL write_byte(buf, 0b0000_1000) # 00rX_YRDL
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 27) # CIRCLE record write_uint(buf, 27) # CIRCLE record
write_byte(buf, 0b0010_1000) # 00rX_YRDL write_byte(buf, 0b0010_1000) # 00rX_YRDL
write_uint(buf, 0) # radius write_uint(buf, 0) # radius
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 27) # CIRCLE record write_uint(buf, 27) # CIRCLE record
write_byte(buf, 0b0010_1000) # 00rX_YRDL write_byte(buf, 0b0010_1000) # 00rX_YRDL
write_uint(buf, 1) # radius write_uint(buf, 1) # radius
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 27) # CIRCLE record write_uint(buf, 27) # CIRCLE record
write_byte(buf, 0b0010_1000) # 00rX_YRDL write_byte(buf, 0b0010_1000) # 00rX_YRDL
write_uint(buf, 6) # radius write_uint(buf, 6) # radius
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 27) # CIRCLE record write_uint(buf, 27) # CIRCLE record
write_byte(buf, 0b0010_1000) # 00rX_YRDL write_byte(buf, 0b0010_1000) # 00rX_YRDL
write_uint(buf, 20) # radius write_uint(buf, 20) # radius
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 27) # CIRCLE record write_uint(buf, 27) # CIRCLE record
write_byte(buf, 0b0010_1100) # 00rX_YRDL write_byte(buf, 0b0010_1100) # 00rX_YRDL
write_uint(buf, 100) # radius write_uint(buf, 100) # radius
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 400) # (repetition) x-spacing write_uint(buf, 400) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
buf.write(FOOTER) buf.write(FOOTER)
return buf return buf

View File

@ -1,9 +1,17 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO
from io import BytesIO from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
import numpy
from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte, PathExtensionScheme
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -20,34 +28,34 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.layers assert not layout.layers
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'A') # Cell name write_bstring(buf, b'A') # Cell name
write_uint(buf, 26) # CTRAPEZOID record write_uint(buf, 26) # CTRAPEZOID record
write_byte(buf, 0b1111_1011) # TWHX_YRDL write_byte(buf, 0b1111_1011) # TWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 24) # ctrapezoid type write_uint(buf, 24) # ctrapezoid type
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, -100) # geometry-x (absolute) write_sint(buf, -100) # geometry-x (absolute)
write_sint(buf, 200) # geometry-y (absolute) write_sint(buf, 200) # geometry-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
write_uint(buf, 26) # CTRAPEZOID record write_uint(buf, 26) # CTRAPEZOID record
write_byte(buf, 0b0000_1000) # TWHX_YRDL write_byte(buf, 0b0000_1000) # TWHX_YRDL
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0000_0011) # SWHX_YRDL write_byte(buf, 0b0000_0011) # SWHX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
h = [250, 100] h = [250, 100]
v = [100, 250] v = [100, 250]
@ -58,34 +66,33 @@ def write_file_1(buf: IO[bytes]) -> IO[bytes]:
+ [0b10] * 4 + [0b10] * 4
+ [0b01] * 2 + [0b01] * 2
+ [0b10] * 2 + [0b10] * 2
+ [0b11, 0b10] + [0b11, 0b10])
)
for t, (x, x_en) in enumerate(zip(wh, wh_en, strict=True)): for t, (x, x_en) in enumerate(zip(wh, wh_en)):
write_uint(buf, 26) # CTRAPEZOID record write_uint(buf, 26) # CTRAPEZOID record
write_byte(buf, 0b1000_1011 | (x_en << 5)) # TWHX_YRDL write_byte(buf, 0b1000_1011 | (x_en << 5)) # TWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, t) # ctrapezoid type write_uint(buf, t) # ctrapezoid type
if x_en & 0b10: if x_en & 0b10:
write_uint(buf, x[0]) # width write_uint(buf, x[0]) # width
if x_en & 0b01: if x_en & 0b01:
write_uint(buf, x[1]) # height write_uint(buf, x[1]) # height
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0000_0011) # SWHX_YRDL write_byte(buf, 0b0000_0011) # SWHX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 26) # CTRAPEZOID record write_uint(buf, 26) # CTRAPEZOID record
write_byte(buf, 0b0000_1100) # TWHX_YRDL write_byte(buf, 0b0000_1100) # TWHX_YRDL
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 400) # (repetition) x-spacing write_uint(buf, 400) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
buf.write(FOOTER) buf.write(FOOTER)
return buf return buf
@ -135,12 +142,13 @@ def test_file_1() -> None:
assert gg.width == [250, None][is_ctrapz], msg assert gg.width == [250, None][is_ctrapz], msg
elif ct_type in range(22, 24) or ct_type == 25: elif ct_type in range(22, 24) or ct_type == 25:
assert gg.height == [100, None][is_ctrapz], msg assert gg.height == [100, None][is_ctrapz], msg
elif ct_type < 8 or 16 <= ct_type < 25 or ct_type >= 26:
assert gg.width == 250, msg
assert gg.height == 100, msg
else: else:
assert gg.width == 100, msg if ct_type < 8 or 16 <= ct_type < 25 or 26 <= ct_type :
assert gg.height == 250, msg assert gg.width == 250, msg
assert gg.height == 100, msg
else:
assert gg.width == 100, msg
assert gg.height == 250, msg
elif ii < 3 and ii % 2: elif ii < 3 and ii % 2:
assert gg.ctrapezoid_type == 24, msg assert gg.ctrapezoid_type == 24, msg
elif ii == 55: elif ii == 55:
@ -152,48 +160,48 @@ def test_file_1() -> None:
assert geometry[55].repetition.b_vector == [0, 300] assert geometry[55].repetition.b_vector == [0, 300]
def write_file_2(buf: IO[bytes]) -> IO[bytes]: def write_file_2(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'A') # Cell name write_bstring(buf, b'A') # Cell name
# Shouldn't access (undefined) height modal, despite not having a height. # Shouldn't access (undefined) height modal, despite not having a height.
write_uint(buf, 26) # CTRAPEZOID record write_uint(buf, 26) # CTRAPEZOID record
write_byte(buf, 0b1101_1011) # TWHX_YRDL write_byte(buf, 0b1101_1011) # TWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 16) # ctrapezoid type write_uint(buf, 16) # ctrapezoid type
write_uint(buf, 200) # width write_uint(buf, 200) # width
write_sint(buf, -100) # geometry-x (absolute) write_sint(buf, -100) # geometry-x (absolute)
write_sint(buf, 200) # geometry-y (absolute) write_sint(buf, 200) # geometry-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
write_uint(buf, 26) # CTRAPEZOID record write_uint(buf, 26) # CTRAPEZOID record
write_byte(buf, 0b0000_1000) # TWHX_YRDL write_byte(buf, 0b0000_1000) # TWHX_YRDL
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'B') # Cell name write_bstring(buf, b'B') # Cell name
# Shouldn't access (undefined) width modal, despite not having a width. # Shouldn't access (undefined) width modal, despite not having a width.
write_uint(buf, 26) # CTRAPEZOID record write_uint(buf, 26) # CTRAPEZOID record
write_byte(buf, 0b1011_1011) # TWHX_YRDL write_byte(buf, 0b1011_1011) # TWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 20) # ctrapezoid type write_uint(buf, 20) # ctrapezoid type
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, -100) # geometry-x (absolute) write_sint(buf, -100) # geometry-x (absolute)
write_sint(buf, 200) # geometry-y (absolute) write_sint(buf, 200) # geometry-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
write_uint(buf, 26) # CTRAPEZOID record write_uint(buf, 26) # CTRAPEZOID record
write_byte(buf, 0b0000_1000) # TWHX_YRDL write_byte(buf, 0b0000_1000) # TWHX_YRDL
write_sint(buf, 400) # geometry-y (relative) write_sint(buf, 400) # geometry-y (relative)
buf.write(FOOTER) buf.write(FOOTER)
return buf return buf

View File

@ -1,9 +1,14 @@
from typing import IO # type: ignore
from io import BytesIO
from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct import struct
import pytest # type: ignore
from .utils import MAGIC_BYTES, FOOTER from .utils import MAGIC_BYTES, FOOTER
from ..basic import write_uint, write_bstring from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring
from ..main import OasisLayout from ..main import OasisLayout
@ -21,12 +26,12 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.layers assert not layout.layers
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File contains one PAD record. File contains one PAD record.
1000 units/micron 1000 units/micron
Offset table inside START. Offset table inside START.
""" '''
buf.write(MAGIC_BYTES) buf.write(MAGIC_BYTES)
write_uint(buf, 1) # START record write_uint(buf, 1) # START record
@ -54,12 +59,13 @@ def test_file_1() -> None:
assert layout.unit == 1000 assert layout.unit == 1000
def write_file_2(buf: IO[bytes]) -> IO[bytes]:
""" def write_file_2(buf: BufferedIOBase) -> BufferedIOBase:
'''
File contains no records. File contains no records.
1/2 unit/micron 1/2 unit/micron
Offset table inside START. Offset table inside START.
""" '''
buf.write(MAGIC_BYTES) buf.write(MAGIC_BYTES)
write_uint(buf, 1) # START record write_uint(buf, 1) # START record
@ -85,12 +91,12 @@ def test_file_2() -> None:
assert layout.unit == 0.5 assert layout.unit == 0.5
def write_file_3(buf: IO[bytes]) -> IO[bytes]: def write_file_3(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File contains no records. File contains no records.
10/4 unit/micron 10/4 unit/micron
Offset table inside START. Offset table inside START.
""" '''
buf.write(MAGIC_BYTES) buf.write(MAGIC_BYTES)
write_uint(buf, 1) # START record write_uint(buf, 1) # START record
@ -117,12 +123,12 @@ def test_file_3() -> None:
assert layout.unit == 10 / 4 assert layout.unit == 10 / 4
def write_file_4(buf: IO[bytes]) -> IO[bytes]: def write_file_4(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File contains no records. File contains no records.
12.5 unit/micron (float32) 12.5 unit/micron (float32)
Offset table inside START. Offset table inside START.
""" '''
buf.write(MAGIC_BYTES) buf.write(MAGIC_BYTES)
write_uint(buf, 1) # START record write_uint(buf, 1) # START record
@ -148,12 +154,12 @@ def test_file_4() -> None:
assert layout.unit == 12.5 assert layout.unit == 12.5
def write_file_5(buf: IO[bytes]) -> IO[bytes]: def write_file_5(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File contains no records. File contains no records.
12.5 unit/micron (float64) 12.5 unit/micron (float64)
Offset table inside START. Offset table inside START.
""" '''
buf.write(MAGIC_BYTES) buf.write(MAGIC_BYTES)
write_uint(buf, 1) # START record write_uint(buf, 1) # START record

View File

@ -1,19 +1,24 @@
from typing import IO # type: ignore
from collections.abc import Sequence
from io import BytesIO from typing import List, Tuple, Iterable, Sequence
from itertools import chain
from io import BytesIO, BufferedIOBase
import pytest # type: ignore
import numpy
from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte, PathExtensionScheme
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
LAYERS = [ LAYERS = [(1, 2), (1, 5), (1, 6), (1, 8),
(1, 2), (1, 5), (1, 6), (1, 8), (5, 2), (5, 5), (5, 6), (5, 8),
(5, 2), (5, 5), (5, 6), (5, 8), (6, 2), (6, 5), (6, 6), (6, 8),
(6, 2), (6, 5), (6, 6), (6, 8), (7, 2), (7, 5), (7, 6), (7, 8),
(7, 2), (7, 5), (7, 6), (7, 8), ]
]
def base_tests(layout: OasisLayout) -> None: def base_tests(layout: OasisLayout) -> None:
assert layout.version.string == '1.0' assert layout.version.string == '1.0'
@ -27,77 +32,77 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.cellnames assert not layout.cellnames
assert len(layout.cells) == 1 assert len(layout.cells) == 1
assert layout.cells[0].name.string == 'A' # type: ignore assert layout.cells[0].name.string == 'A'
assert not layout.cells[0].properties assert not layout.cells[0].properties
def write_names_geom(buf: IO[bytes], short: bool = False) -> IO[bytes]: def write_names_geom(buf: BufferedIOBase, short: bool = False) -> BufferedIOBase:
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'AA') # name write_bstring(buf, b'AA') # name
write_uint(buf, 0) # all layers write_uint(buf, 0) # all layers
write_uint(buf, 0) # all datatypes write_uint(buf, 0) # all datatypes
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'L5A') # name write_bstring(buf, b'L5A') # name
write_uint(buf, 1) # layer <=5 write_uint(buf, 1) # layer <=5
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 0) # all datatypes write_uint(buf, 0) # all datatypes
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'H5A') # name write_bstring(buf, b'H5A') # name
write_uint(buf, 2) # layer >=5 write_uint(buf, 2) # layer >=5
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 0) # all datatypes write_uint(buf, 0) # all datatypes
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'E5A') # name write_bstring(buf, b'E5A') # name
write_uint(buf, 3) # layer ==5 write_uint(buf, 3) # layer ==5
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 0) # all datatypes write_uint(buf, 0) # all datatypes
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'I56A') # name write_bstring(buf, b'I56A') # name
write_uint(buf, 4) # layer 5 to 6 write_uint(buf, 4) # layer 5 to 6
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 6) # (...) write_uint(buf, 6) # (...)
write_uint(buf, 0) # all datatypes write_uint(buf, 0) # all datatypes
if short: if short:
return buf return buf
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'E5L4') # name write_bstring(buf, b'E5L4') # name
write_uint(buf, 3) # layer ==5 write_uint(buf, 3) # layer ==5
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 1) # datatype <=4 write_uint(buf, 1) # datatype <=4
write_uint(buf, 4) # (...) write_uint(buf, 4) # (...)
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'E5H4') # name write_bstring(buf, b'E5H4') # name
write_uint(buf, 3) # layer ==5 write_uint(buf, 3) # layer ==5
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 2) # datatype >=4 write_uint(buf, 2) # datatype >=4
write_uint(buf, 4) # (...) write_uint(buf, 4) # (...)
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'E5E4') # name write_bstring(buf, b'E5E4') # name
write_uint(buf, 3) # layer ==5 write_uint(buf, 3) # layer ==5
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 3) # datatype ==4 write_uint(buf, 3) # datatype ==4
write_uint(buf, 4) # (...) write_uint(buf, 4) # (...)
write_uint(buf, 11) # LAYERNAME record (geometry) write_uint(buf, 11) # LAYERNAME record (geometry)
write_bstring(buf, b'E5I47') # name write_bstring(buf, b'E5I47') # name
write_uint(buf, 3) # layer ==5 write_uint(buf, 3) # layer ==5
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 4) # datatype 4 to 7 write_uint(buf, 4) # datatype 4 to 7
write_uint(buf, 4) # (...) write_uint(buf, 4) # (...)
write_uint(buf, 7) # (...) write_uint(buf, 7) # (...)
return buf return buf
def write_names_text(buf: IO[bytes], prefix: bytes = b'') -> IO[bytes]: def write_names_text(buf: BufferedIOBase, prefix: bytes = b'') -> BufferedIOBase:
write_uint(buf, 12) # LAYERNAME record (geometry) write_uint(buf, 12) # LAYERNAME record (geometry)
write_bstring(buf, prefix + b'AA') # name write_bstring(buf, prefix + b'AA') # name
write_uint(buf, 0) # all layers write_uint(buf, 0) # all layers
@ -122,14 +127,14 @@ def write_names_text(buf: IO[bytes], prefix: bytes = b'') -> IO[bytes]:
write_uint(buf, 0) # all datatypes write_uint(buf, 0) # all datatypes
write_uint(buf, 12) # LAYERNAME record (geometry) write_uint(buf, 12) # LAYERNAME record (geometry)
write_bstring(buf, prefix + b'I56A') # name write_bstring(buf, prefix + b'I56A') # name
write_uint(buf, 4) # layer 5 to 6 write_uint(buf, 4) # layer 5 to 6
write_uint(buf, 5) # (...) write_uint(buf, 5) # (...)
write_uint(buf, 6) # (...) write_uint(buf, 6) # (...)
write_uint(buf, 0) # all datatypes write_uint(buf, 0) # all datatypes
return buf return buf
def write_geom(buf: IO[bytes]) -> IO[bytes]: def write_geom(buf: BufferedIOBase) -> BufferedIOBase:
for ll, dt in LAYERS: for ll, dt in LAYERS:
write_uint(buf, 27) # CIRCLE record write_uint(buf, 27) # CIRCLE record
write_byte(buf, 0b0011_1011) # 00rX_YRDL write_byte(buf, 0b0011_1011) # 00rX_YRDL
@ -141,7 +146,7 @@ def write_geom(buf: IO[bytes]) -> IO[bytes]:
return buf return buf
def write_text(buf: IO[bytes]) -> IO[bytes]: def write_text(buf: BufferedIOBase) -> BufferedIOBase:
for ll, dt in LAYERS: for ll, dt in LAYERS:
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0101_1011) # 0CNX_YRTL write_byte(buf, 0b0101_1011) # 0CNX_YRTL
@ -155,8 +160,7 @@ def write_text(buf: IO[bytes]) -> IO[bytes]:
def name_test(layers: Sequence, is_textlayer: bool) -> None: def name_test(layers: Sequence, is_textlayer: bool) -> None:
for ii, nn in enumerate(layers): for ii, nn in enumerate(layers):
msg = f'Fail on layername {ii}' assert is_textlayer == nn.is_textlayer, f'Fail on layername {ii}'
assert is_textlayer == nn.is_textlayer, msg
assert nn.nstring.string == ['AA', 'L5A', 'H5A', 'E5A', 'I56A', assert nn.nstring.string == ['AA', 'L5A', 'H5A', 'E5A', 'I56A',
'E5L4', 'E5H4', 'E5E4', 'E5I47'][ii], msg 'E5L4', 'E5H4', 'E5E4', 'E5I47'][ii], msg
@ -168,8 +172,7 @@ def name_test(layers: Sequence, is_textlayer: bool) -> None:
def name_test_text(layers: Sequence) -> None: def name_test_text(layers: Sequence) -> None:
for ii, nn in enumerate(layers): for ii, nn in enumerate(layers):
msg = f'Fail on layername {ii}' assert nn.is_textlayer, f'Fail on layername {ii}'
assert nn.is_textlayer, msg
assert nn.nstring.string == ['TAA', 'TL5A', 'TH5A', 'TE5A', 'TI56A'][ii], msg assert nn.nstring.string == ['TAA', 'TL5A', 'TH5A', 'TE5A', 'TI56A'][ii], msg
assert nn.layer_interval[0] == [None, None, 5, 5, 5][ii], msg assert nn.layer_interval[0] == [None, None, 5, 5, 5][ii], msg
@ -206,9 +209,9 @@ def elem_test_text(geometry: Sequence) -> None:
assert not gg.properties, msg assert not gg.properties, msg
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_names_geom(buf) write_names_geom(buf)
@ -236,9 +239,9 @@ def test_file_1() -> None:
name_test(layout.layers, is_textlayer=False) name_test(layout.layers, is_textlayer=False)
def write_file_2(buf: IO[bytes]) -> IO[bytes]: def write_file_2(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_names_text(buf) write_names_text(buf)
@ -266,9 +269,9 @@ def test_file_2() -> None:
name_test(layout.layers, is_textlayer=True) name_test(layout.layers, is_textlayer=True)
def write_file_3(buf: IO[bytes]) -> IO[bytes]: def write_file_3(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_names_text(buf, prefix=b'T') write_names_text(buf, prefix=b'T')
write_names_geom(buf, short=True) write_names_geom(buf, short=True)
@ -282,9 +285,9 @@ def write_file_3(buf: IO[bytes]) -> IO[bytes]:
return buf return buf
def write_file_4(buf: IO[bytes]) -> IO[bytes]: def write_file_4(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)

View File

@ -1,9 +1,17 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO
from io import BytesIO from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
import numpy
from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte, PathExtensionScheme
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -20,156 +28,156 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.layers assert not layout.layers
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'A') # Cell name write_bstring(buf, b'A') # Cell name
# RECTANGLE 0 # RECTANGLE 0
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0110_0011) # SWHX_YRDL write_byte(buf, 0b0110_0011) # SWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 10) # width write_uint(buf, 10) # width
write_uint(buf, 20) # height write_uint(buf, 20) # height
# TEXT 1 # TEXT 1
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0100_0011) # 0CNX_YRTL write_byte(buf, 0b0100_0011) # 0CNX_YRTL
write_bstring(buf, b'A') # text string write_bstring(buf, b'A') # text string
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 1) # datatype write_uint(buf, 1) # datatype
# RECTANGLE 2 # RECTANGLE 2
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0001_1000) # SWHX_YRDL write_byte(buf, 0b0001_1000) # SWHX_YRDL
write_sint(buf, 100) # geometry-x (absolute) write_sint(buf, 100) # geometry-x (absolute)
write_sint(buf, -100) # geometry-y (absolute) write_sint(buf, -100) # geometry-y (absolute)
# TEXT 3 # TEXT 3
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0001_1000) # 0CNX_YRTL write_byte(buf, 0b0001_1000) # 0CNX_YRTL
write_sint(buf, 100) # text-x (absolute) write_sint(buf, 100) # text-x (absolute)
write_sint(buf, -100) # text-y (absolute) write_sint(buf, -100) # text-y (absolute)
# RECTANGLE 4 # RECTANGLE 4
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0001_1000) # SWHX_YRDL write_byte(buf, 0b0001_1000) # SWHX_YRDL
write_sint(buf, 200) # geometry-x (absolute) write_sint(buf, 200) # geometry-x (absolute)
write_sint(buf, -200) # geometry-y (absolute) write_sint(buf, -200) # geometry-y (absolute)
# TEXT 5 # TEXT 5
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0001_1000) # 0CNX_YRTL write_byte(buf, 0b0001_1000) # 0CNX_YRTL
write_sint(buf, 200) # text-x (absolute) write_sint(buf, 200) # text-x (absolute)
write_sint(buf, -200) # text-y (absolute) write_sint(buf, -200) # text-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# RECTANGLE 6 # RECTANGLE 6
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0001_1000) # SWHX_YRDL write_byte(buf, 0b0001_1000) # SWHX_YRDL
write_sint(buf, 100) # geometry-x (relative) write_sint(buf, 100) # geometry-x (relative)
write_sint(buf, -100) # geometry-y (relative) write_sint(buf, -100) # geometry-y (relative)
# TEXT 7 # TEXT 7
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0001_1000) # 0CNX_YRTL write_byte(buf, 0b0001_1000) # 0CNX_YRTL
write_sint(buf, 100) # text-x (relative) write_sint(buf, 100) # text-x (relative)
write_sint(buf, -100) # text-y (relative) write_sint(buf, -100) # text-y (relative)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'B') # Cell name write_bstring(buf, b'B') # Cell name
# RECTANGLE 0 # RECTANGLE 0
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0110_0011) # SWHX_YRDL write_byte(buf, 0b0110_0011) # SWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 20) # width write_uint(buf, 20) # width
write_uint(buf, 10) # height write_uint(buf, 10) # height
# TEXT 1 # TEXT 1
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0100_0011) # 0CNX_YRTL write_byte(buf, 0b0100_0011) # 0CNX_YRTL
write_bstring(buf, b'B') # text string write_bstring(buf, b'B') # text string
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 1) # datatype write_uint(buf, 1) # datatype
# RECTANGLE 2 # RECTANGLE 2
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0001_1000) # SWHX_YRDL write_byte(buf, 0b0001_1000) # SWHX_YRDL
write_sint(buf, 100) # geometry-x (absolute) write_sint(buf, 100) # geometry-x (absolute)
write_sint(buf, 100) # geometry-y (absolute) write_sint(buf, 100) # geometry-y (absolute)
# TEXT 3 # TEXT 3
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0001_1000) # 0CNX_YRTL write_byte(buf, 0b0001_1000) # 0CNX_YRTL
write_sint(buf, 100) # text-x (absolute) write_sint(buf, 100) # text-x (absolute)
write_sint(buf, 100) # text-y (absolute) write_sint(buf, 100) # text-y (absolute)
# RECTANGLE 4 # RECTANGLE 4
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0001_1000) # SWHX_YRDL write_byte(buf, 0b0001_1000) # SWHX_YRDL
write_sint(buf, 200) # geometry-x (absolute) write_sint(buf, 200) # geometry-x (absolute)
write_sint(buf, 200) # geometry-y (absolute) write_sint(buf, 200) # geometry-y (absolute)
# TEXT 5 # TEXT 5
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0001_1000) # 0CNX_YRTL write_byte(buf, 0b0001_1000) # 0CNX_YRTL
write_sint(buf, 200) # text-x (absolute) write_sint(buf, 200) # text-x (absolute)
write_sint(buf, 200) # text-y (absolute) write_sint(buf, 200) # text-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# RECTANGLE 6 # RECTANGLE 6
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0001_1000) # SWHX_YRDL write_byte(buf, 0b0001_1000) # SWHX_YRDL
write_sint(buf, 100) # geometry-x (relative) write_sint(buf, 100) # geometry-x (relative)
write_sint(buf, 100) # geometry-y (relative) write_sint(buf, 100) # geometry-y (relative)
# TEXT 7 # TEXT 7
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0001_1000) # 0CNX_YRTL write_byte(buf, 0b0001_1000) # 0CNX_YRTL
write_sint(buf, 100) # text-x (relative) write_sint(buf, 100) # text-x (relative)
write_sint(buf, 100) # text-y (relative) write_sint(buf, 100) # text-y (relative)
# PLACEMENT 0 # PLACEMENT 0
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b1000_0000) # CNXY_RAAF write_byte(buf, 0b1000_0000) # CNXY_RAAF
write_bstring(buf, b'A') # Cell reference write_bstring(buf, b'A') # Cell reference
# PLACEMENT 1 # PLACEMENT 1
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_0000) # CNXY_RAAF write_byte(buf, 0b0011_0000) # CNXY_RAAF
write_sint(buf, 50) # placement-x (relative) write_sint(buf, 50) # placement-x (relative)
write_sint(buf, 50) # placement-y (relative) write_sint(buf, 50) # placement-y (relative)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'TOP') # Cell name write_bstring(buf, b'TOP') # Cell name
# PLACEMENT 0 # PLACEMENT 0
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b1000_0000) # CNXY_RAAF write_byte(buf, 0b1000_0000) # CNXY_RAAF
write_bstring(buf, b'B') # Cell reference write_bstring(buf, b'B') # Cell reference
# RECTANGLE 0 # RECTANGLE 0
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0110_0011) # SWHX_YRDL write_byte(buf, 0b0110_0011) # SWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 50) # width write_uint(buf, 50) # width
write_uint(buf, 5) # height write_uint(buf, 5) # height
# TEXT 1 # TEXT 1
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
write_byte(buf, 0b0100_0011) # 0CNX_YRTL write_byte(buf, 0b0100_0011) # 0CNX_YRTL
write_bstring(buf, b'TOP') # text string write_bstring(buf, b'TOP') # text string
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 1) # datatype write_uint(buf, 1) # datatype
buf.write(FOOTER) buf.write(FOOTER)
return buf return buf

View File

@ -1,11 +1,17 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO
from io import BytesIO
from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
import numpy
from numpy.testing import assert_equal from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte, PathExtensionScheme from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte, PathExtensionScheme
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -26,113 +32,113 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.cells[0].properties assert not layout.cells[0].properties
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'ABC') # Cell name write_bstring(buf, b'ABC') # Cell name
# PATH 0 # PATH 0
write_uint(buf, 22) # PATH record write_uint(buf, 22) # PATH record
write_byte(buf, 0b1111_1011) # EWPX_YRDL write_byte(buf, 0b1111_1011) # EWPX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 10) # half-width write_uint(buf, 10) # half-width
write_byte(buf, 0b0000_1111) # extension-scheme 0000_SSEE write_byte(buf, 0b0000_1111) # extension-scheme 0000_SSEE
write_sint(buf, 5) # (extension-scheme) start write_sint(buf, 5) # (extension-scheme) start
write_sint(buf, -5) # (extension-scheme) end write_sint(buf, -5) # (extension-scheme) end
write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt
write_uint(buf, 3) # (pointlist) dimension write_uint(buf, 3) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 0) # geometry-x (absolute) write_sint(buf, 0) # geometry-x (absolute)
write_sint(buf, 100) # geometry-y (absolute) write_sint(buf, 100) # geometry-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PATH 1 # PATH 1
write_uint(buf, 22) # PATH record write_uint(buf, 22) # PATH record
write_byte(buf, 0b1110_1011) # EWPX_YRDL write_byte(buf, 0b1110_1011) # EWPX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 10) # half-width write_uint(buf, 10) # half-width
write_byte(buf, 0b0000_0000) # extension-scheme 0000_SSEE write_byte(buf, 0b0000_0000) # extension-scheme 0000_SSEE
write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt
write_uint(buf, 3) # (pointlist) dimension write_uint(buf, 3) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 200) # geometry-y (relative) write_sint(buf, 200) # geometry-y (relative)
# PATH 2 # PATH 2
write_uint(buf, 22) # PATH record write_uint(buf, 22) # PATH record
write_byte(buf, 0b1110_1001) # EWPX_YRDL write_byte(buf, 0b1110_1001) # EWPX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 10) # half-width write_uint(buf, 10) # half-width
write_byte(buf, 0b0000_0100) # extension-scheme 0000_SSEE write_byte(buf, 0b0000_0100) # extension-scheme 0000_SSEE
write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt
write_uint(buf, 3) # (pointlist) dimension write_uint(buf, 3) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 200) # geometry-y (relative) write_sint(buf, 200) # geometry-y (relative)
# PATH 3 # PATH 3
write_uint(buf, 22) # PATH record write_uint(buf, 22) # PATH record
write_byte(buf, 0b1110_1010) # EWPX_YRDL write_byte(buf, 0b1110_1010) # EWPX_YRDL
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 12) # half-width write_uint(buf, 12) # half-width
write_byte(buf, 0b0000_0101) # extension-scheme 0000_SSEE write_byte(buf, 0b0000_0101) # extension-scheme 0000_SSEE
write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt
write_uint(buf, 3) # (pointlist) dimension write_uint(buf, 3) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 200) # geometry-y (relative) write_sint(buf, 200) # geometry-y (relative)
# PATH 4 # PATH 4
write_uint(buf, 22) # PATH record write_uint(buf, 22) # PATH record
write_byte(buf, 0b1010_1011) # EWPX_YRDL write_byte(buf, 0b1010_1011) # EWPX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_byte(buf, 0b0000_1010) # extension-scheme 0000_SSEE write_byte(buf, 0b0000_1010) # extension-scheme 0000_SSEE
write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt
write_uint(buf, 3) # (pointlist) dimension write_uint(buf, 3) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 200) # geometry-y (relative) write_sint(buf, 200) # geometry-y (relative)
# PATH 5 # PATH 5
write_uint(buf, 22) # PATH record write_uint(buf, 22) # PATH record
write_byte(buf, 0b0000_1011) # EWPX_YRDL write_byte(buf, 0b0000_1011) # EWPX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_sint(buf, 200) # geometry-y (relative) write_sint(buf, 200) # geometry-y (relative)
# PATH 6 # PATH 6
write_uint(buf, 22) # PATH record write_uint(buf, 22) # PATH record
write_byte(buf, 0b0000_1111) # EWPX_YRDL write_byte(buf, 0b0000_1111) # EWPX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_sint(buf, 200) # geometry-y (relative) write_sint(buf, 200) # geometry-y (relative)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 200) # (repetition) x-spacing write_uint(buf, 200) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PATH 7 # PATH 7
write_uint(buf, 22) # PATH record write_uint(buf, 22) # PATH record
write_byte(buf, 0b0001_0101) # EWPX_YRDL write_byte(buf, 0b0001_0101) # EWPX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_sint(buf, 1000) # geometry-x (relative) write_sint(buf, 1000) # geometry-x (relative)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
buf.write(FOOTER) buf.write(FOOTER)
return buf return buf
@ -182,7 +188,7 @@ def test_file_1() -> None:
else: else:
assert gg.half_width == 12, msg assert gg.half_width == 12, msg
assert len(gg.point_list) == 3, msg # type: ignore assert len(gg.point_list) == 3, msg
assert_equal(gg.point_list, [[150, 0], [0, 50], [-50, 0]], err_msg=msg) assert_equal(gg.point_list, [[150, 0], [0, 50], [-50, 0]], err_msg=msg)
if ii >= 4: if ii >= 4:

View File

@ -1,12 +1,17 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO, cast
from io import BytesIO
from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
import numpy
from numpy.testing import assert_equal from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte, write_float32, write_float64 from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte, PathExtensionScheme
from ..records import Rectangle from ..basic import InvalidRecordError, InvalidDataError, write_float32, write_float64
from ..main import OasisLayout from ..main import OasisLayout
@ -22,136 +27,136 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.layers assert not layout.layers
def write_rectangle(buf: IO[bytes], pos: tuple[int, int] = (300, -400)) -> None: def write_rectangle(buf: BufferedIOBase, pos: Tuple[int, int] = (300, -400)) -> None:
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0111_1011) # SWHX_YRDL write_byte(buf, 0b0111_1011) # SWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, pos[0]) # geometry-x (absolute) write_sint(buf, pos[0]) # geometry-x (absolute)
write_sint(buf, pos[1]) # geometry-y (absolute) write_sint(buf, pos[1]) # geometry-y (absolute)
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'A') # Cell name write_bstring(buf, b'A') # Cell name
write_rectangle(buf) write_rectangle(buf)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'TOP') # Cell name write_bstring(buf, b'TOP') # Cell name
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PLACEMENT 0 # PLACEMENT 0
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b1011_0000) # CNXY_RAAF write_byte(buf, 0b1011_0000) # CNXY_RAAF
write_bstring(buf, b'A') # cell reference write_bstring(buf, b'A') # cell reference
write_sint(buf, -300) # placement-x (relative) write_sint(buf, -300) # placement-x (relative)
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
# PLACEMENT 1 # PLACEMENT 1
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_0000) # CNXY_RAAF write_byte(buf, 0b0011_0000) # CNXY_RAAF
write_sint(buf, 0) # placement-x (relative) write_sint(buf, 0) # placement-x (relative)
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
# PLACEMENT 2 # PLACEMENT 2
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_0000) # CNXY_RAAF write_byte(buf, 0b0001_0000) # CNXY_RAAF
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
# PLACEMENT 3 # PLACEMENT 3
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0010_0000) # CNXY_RAAF write_byte(buf, 0b0010_0000) # CNXY_RAAF
write_sint(buf, 300) # placement-x (relative) write_sint(buf, 300) # placement-x (relative)
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# PLACEMENT 4 # PLACEMENT 4
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_0001) # CNXY_RAAF write_byte(buf, 0b0011_0001) # CNXY_RAAF
write_sint(buf, 700) # placement-x (absolute) write_sint(buf, 700) # placement-x (absolute)
write_sint(buf, 400) # placement-y (absolute) write_sint(buf, 400) # placement-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PLACEMENT 5 # PLACEMENT 5
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_0010) # CNXY_RAAF write_byte(buf, 0b0001_0010) # CNXY_RAAF
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
# PLACEMENT 6 # PLACEMENT 6
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_0011) # CNXY_RAAF write_byte(buf, 0b0001_0011) # CNXY_RAAF
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# PLACEMENT 7 # PLACEMENT 7
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_1111) # CNXY_RAAF write_byte(buf, 0b0011_1111) # CNXY_RAAF
write_sint(buf, 2000) # placement-x (absolute) write_sint(buf, 2000) # placement-x (absolute)
write_sint(buf, 0) # placement-y (absolute) write_sint(buf, 0) # placement-y (absolute)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 300) # (repetition) x-spacing write_uint(buf, 300) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PLACEMENT 8 # PLACEMENT 8
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_1111) # CNXY_RAAF write_byte(buf, 0b0011_1111) # CNXY_RAAF
write_sint(buf, 2000) # placement-x (relative) write_sint(buf, 2000) # placement-x (relative)
write_sint(buf, 0) # placement-y (relative) write_sint(buf, 0) # placement-y (relative)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
# PLACEMENT 9 # PLACEMENT 9
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_1111) # CNXY_RAAF write_byte(buf, 0b0011_1111) # CNXY_RAAF
write_sint(buf, 2000) # placement-x (relative) write_sint(buf, 2000) # placement-x (relative)
write_sint(buf, 0) # placement-y (relative) write_sint(buf, 0) # placement-y (relative)
write_uint(buf, 2) # repetition (3 cols.) write_uint(buf, 2) # repetition (3 cols.)
write_uint(buf, 1) # (repetition) count write_uint(buf, 1) # (repetition) count
write_uint(buf, 320) # (repetition) spacing write_uint(buf, 320) # (repetition) spacing
# PLACEMENT 10 # PLACEMENT 10
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_1111) # CNXY_RAAF write_byte(buf, 0b0011_1111) # CNXY_RAAF
write_sint(buf, 2000) # placement-x (relative) write_sint(buf, 2000) # placement-x (relative)
write_sint(buf, 0) # placement-y (relative) write_sint(buf, 0) # placement-y (relative)
write_uint(buf, 3) # repetition (4 rows) write_uint(buf, 3) # repetition (4 rows)
write_uint(buf, 2) # (repetition) count write_uint(buf, 2) # (repetition) count
write_uint(buf, 310) # (repetition) spacing write_uint(buf, 310) # (repetition) spacing
# PLACEMENT 11 # PLACEMENT 11
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_1111) # CNXY_RAAF write_byte(buf, 0b0011_1111) # CNXY_RAAF
write_sint(buf, 2000) # placement-x (relative) write_sint(buf, 2000) # placement-x (relative)
write_sint(buf, 0) # placement-y (relative) write_sint(buf, 0) # placement-y (relative)
write_uint(buf, 4) # repetition (4 arbitrary cols.) write_uint(buf, 4) # repetition (4 arbitrary cols.)
write_uint(buf, 2) # (repetition) dimension write_uint(buf, 2) # (repetition) dimension
write_uint(buf, 320) # (repetition) spacing write_uint(buf, 320) # (repetition) spacing
write_uint(buf, 330) # (repetition) spacing write_uint(buf, 330) # (repetition) spacing
write_uint(buf, 340) # (repetition) spacing write_uint(buf, 340) # (repetition) spacing
# PLACEMENT 12 # PLACEMENT 12
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_1111) # CNXY_RAAF write_byte(buf, 0b0011_1111) # CNXY_RAAF
write_sint(buf, 2000) # placement-x (relative) write_sint(buf, 2000) # placement-x (relative)
write_sint(buf, 0) # placement-y (relative) write_sint(buf, 0) # placement-y (relative)
write_uint(buf, 8) # repetition (3x4 matrix, arbitrary vectors) write_uint(buf, 8) # repetition (3x4 matrix, arbitrary vectors)
write_uint(buf, 1) # (repetition) n-dimension write_uint(buf, 1) # (repetition) n-dimension
write_uint(buf, 2) # (repetition) m-dimension write_uint(buf, 2) # (repetition) m-dimension
write_uint(buf, 310 << 2 | 0b01) # (repetition) n-displacement g-delta: (310, 320) write_uint(buf, 310 << 2 | 0b01) # (repetition) n-displacement g-delta: (310, 320)
write_sint(buf, 320) # (repetition g-delta) write_sint(buf, 320) # (repetition g-delta)
write_uint(buf, 330 << 4 | 0b1010) # (repetition) m-displacement g-delta: 330-northwest (-330, 330) write_uint(buf, 330 << 4 | 0b1010) # (repetition) m-displacement g-delta: 330-northwest (-330, 330)
buf.write(FOOTER) buf.write(FOOTER)
@ -174,7 +179,7 @@ def test_file_1() -> None:
assert not layout.cells[1].properties assert not layout.cells[1].properties
assert not layout.cells[1].geometry assert not layout.cells[1].geometry
geometry = cast(list[Rectangle], layout.cells[0].geometry) geometry = layout.cells[0].geometry
assert len(geometry) == 1 assert len(geometry) == 1
assert geometry[0].layer == 1 assert geometry[0].layer == 1
assert geometry[0].datatype == 2 assert geometry[0].datatype == 2
@ -202,19 +207,19 @@ def test_file_1() -> None:
if ii < 3: if ii < 3:
assert pp.y == 400 * (ii + 1), msg assert pp.y == 400 * (ii + 1), msg
elif ii >= 7: elif 7 <= ii:
assert pp.y == 0, msg assert pp.y == 0, msg
if ii < 4 or ii == 5: if ii < 4 or ii == 5:
assert not bool(pp.flip), msg assert pp.flip == False, msg
else: else:
assert bool(pp.flip), msg assert pp.flip == True, msg
if ii < 5: if ii < 5:
assert pp.angle == 0, msg assert pp.angle == 0, msg
elif ii in (5, 6): elif ii in (5, 6):
assert pp.angle == 90, msg assert pp.angle == 90, msg
elif ii >= 7: elif 7 <= ii:
assert pp.angle == 270, msg assert pp.angle == 270, msg
if ii < 7: if ii < 7:
@ -249,9 +254,9 @@ def test_file_1() -> None:
assert placements[12].repetition.b_vector == [-330, 330] assert placements[12].repetition.b_vector == [-330, 330]
def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]: def write_file_common(buf: BufferedIOBase, variant: int) -> BufferedIOBase:
""" '''
""" '''
assert variant in (2, 3, 5, 7), 'Error in test definition!' assert variant in (2, 3, 5, 7), 'Error in test definition!'
buf.write(HEADER) buf.write(HEADER)
@ -281,49 +286,49 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
# PLACEMENT 0 # PLACEMENT 0
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
if variant == 2: if variant == 2:
write_byte(buf, 0b1011_0000) # CNXY_RAAF write_byte(buf, 0b1011_0000) # CNXY_RAAF
write_bstring(buf, b'A') # cell reference write_bstring(buf, b'A') # cell reference
else: else:
write_byte(buf, 0b1111_0000) # CNXY_RAAF write_byte(buf, 0b1111_0000) # CNXY_RAAF
write_uint(buf, 0) # cell reference write_uint(buf, 0) # cell reference
write_sint(buf, -300) # placement-x (relative) write_sint(buf, -300) # placement-x (relative)
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
# PLACEMENT 1 # PLACEMENT 1
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_0000) # CNXY_RAAF write_byte(buf, 0b0011_0000) # CNXY_RAAF
write_sint(buf, 0) # placement-x (relative) write_sint(buf, 0) # placement-x (relative)
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
# PLACEMENT 2 # PLACEMENT 2
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_0000) # CNXY_RAAF write_byte(buf, 0b0001_0000) # CNXY_RAAF
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
# PLACEMENT 3 # PLACEMENT 3
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0010_0000) # CNXY_RAAF write_byte(buf, 0b0010_0000) # CNXY_RAAF
write_sint(buf, 300) # placement-x (relative) write_sint(buf, 300) # placement-x (relative)
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# PLACEMENT 4 # PLACEMENT 4
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_0001) # CNXY_RAAF write_byte(buf, 0b0011_0001) # CNXY_RAAF
write_sint(buf, 700) # placement-x (absolute) write_sint(buf, 700) # placement-x (absolute)
write_sint(buf, 400) # placement-y (absolute) write_sint(buf, 400) # placement-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PLACEMENT 5 # PLACEMENT 5
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_0010) # CNXY_RAAF write_byte(buf, 0b0001_0010) # CNXY_RAAF
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
# PLACEMENT 6 # PLACEMENT 6
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_0011) # CNXY_RAAF write_byte(buf, 0b0001_0011) # CNXY_RAAF
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
if variant == 2: if variant == 2:
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
@ -497,9 +502,9 @@ def common_tests(layout: OasisLayout, variant: int) -> None:
assert pp.y == 400 * (ii + 1), msg assert pp.y == 400 * (ii + 1), msg
if ii in (4, 6): if ii in (4, 6):
assert bool(pp.flip), msg assert pp.flip == True, msg
else: else:
assert not bool(pp.flip), msg assert pp.flip == False, msg
if ii in (5, 6): if ii in (5, 6):
assert pp.angle == 90, msg assert pp.angle == 90, msg
@ -515,78 +520,78 @@ def common_tests(layout: OasisLayout, variant: int) -> None:
assert placements[6].y == 2400 assert placements[6].y == 2400
def write_file_4(buf: IO[bytes]) -> IO[bytes]: def write_file_4(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 3) # CELLNAME record (implicit id 0) write_uint(buf, 3) # CELLNAME record (implicit id 0)
write_bstring(buf, b'A') write_bstring(buf, b'A')
write_uint(buf, 3) # CELLNAME record (implicit id 1) write_uint(buf, 3) # CELLNAME record (implicit id 1)
write_bstring(buf, b'TOP') write_bstring(buf, b'TOP')
write_uint(buf, 13) # CELL record (name ref.) write_uint(buf, 13) # CELL record (name ref.)
write_uint(buf, 1) # Cell name 1 (TOP) write_uint(buf, 1) # Cell name 1 (TOP)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PLACEMENT 0 # PLACEMENT 0
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b1111_1000) # CNXY_RAAF write_byte(buf, 0b1111_1000) # CNXY_RAAF
write_uint(buf, 0) # cell reference write_uint(buf, 0) # cell reference
write_sint(buf, -300) # placement-x (relative) write_sint(buf, -300) # placement-x (relative)
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 20) # (repetition) x-spacing write_uint(buf, 20) # (repetition) x-spacing
write_uint(buf, 30) # (repetition) y-spacing write_uint(buf, 30) # (repetition) y-spacing
# PLACEMENT 1 # PLACEMENT 1
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_1000) # CNXY_RAAF write_byte(buf, 0b0011_1000) # CNXY_RAAF
write_sint(buf, 0) # placement-x (relative) write_sint(buf, 0) # placement-x (relative)
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
# PLACEMENT 2 # PLACEMENT 2
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_1000) # CNXY_RAAF write_byte(buf, 0b0001_1000) # CNXY_RAAF
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
# PLACEMENT 3 # PLACEMENT 3
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0010_1000) # CNXY_RAAF write_byte(buf, 0b0010_1000) # CNXY_RAAF
write_sint(buf, 300) # placement-x (relative) write_sint(buf, 300) # placement-x (relative)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# PLACEMENT 4 # PLACEMENT 4
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0011_1001) # CNXY_RAAF write_byte(buf, 0b0011_1001) # CNXY_RAAF
write_sint(buf, 700) # placement-x (absolute) write_sint(buf, 700) # placement-x (absolute)
write_sint(buf, 400) # placement-y (absolute) write_sint(buf, 400) # placement-y (absolute)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PLACEMENT 5 # PLACEMENT 5
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_1010) # CNXY_RAAF write_byte(buf, 0b0001_1010) # CNXY_RAAF
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
# PLACEMENT 6 # PLACEMENT 6
write_uint(buf, 17) # PLACEMENT (simple) write_uint(buf, 17) # PLACEMENT (simple)
write_byte(buf, 0b0001_1011) # CNXY_RAAF write_byte(buf, 0b0001_1011) # CNXY_RAAF
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
write_uint(buf, 13) # CELL record (name ref.) write_uint(buf, 13) # CELL record (name ref.)
write_uint(buf, 0) # Cell name 0 (A) write_uint(buf, 0) # Cell name 0 (A)
write_rectangle(buf) write_rectangle(buf)
@ -594,89 +599,89 @@ def write_file_4(buf: IO[bytes]) -> IO[bytes]:
return buf return buf
def write_file_6(buf: IO[bytes]) -> IO[bytes]: def write_file_6(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'TOPTOP') # Cell name write_bstring(buf, b'TOPTOP') # Cell name
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
write_uint(buf, 18) # PLACEMENT (mag 0.5, manhattan) write_uint(buf, 18) # PLACEMENT (mag 0.5, manhattan)
write_byte(buf, 0b1011_0110) # CNXY_RMAF write_byte(buf, 0b1011_0110) # CNXY_RMAF
write_bstring(buf, b'TOP') # Cell reference write_bstring(buf, b'TOP') # Cell reference
write_uint(buf, 6) # magnitude, float32 write_uint(buf, 6) # magnitude, float32
write_float32(buf, 0.5) # (magnitude) write_float32(buf, 0.5) # (magnitude)
write_uint(buf, 7) # angle, float64 write_uint(buf, 7) # angle, float64
write_float64(buf, 90.0) # (angle) write_float64(buf, 90.0) # (angle)
write_sint(buf, 100) # placement-x (relative) write_sint(buf, 100) # placement-x (relative)
write_sint(buf, 0) # placement-y (relative) write_sint(buf, 0) # placement-y (relative)
write_uint(buf, 18) # PLACEMENT (no mag, manhattan) write_uint(buf, 18) # PLACEMENT (no mag, manhattan)
write_byte(buf, 0b0011_0000) # CNXY_RMAF write_byte(buf, 0b0011_0000) # CNXY_RMAF
write_sint(buf, 100) # placement-x (relative) write_sint(buf, 100) # placement-x (relative)
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'TOP') # Cell name write_bstring(buf, b'TOP') # Cell name
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PLACEMENT 0 # PLACEMENT 0
write_uint(buf, 18) # PLACEMENT (mag 0.5, manhattan) write_uint(buf, 18) # PLACEMENT (mag 0.5, manhattan)
write_byte(buf, 0b1011_0110) # CNXY_RMAF write_byte(buf, 0b1011_0110) # CNXY_RMAF
write_bstring(buf, b'A') # Cell reference write_bstring(buf, b'A') # Cell reference
write_uint(buf, 6) # magnitude, float32 write_uint(buf, 6) # magnitude, float32
write_float32(buf, 0.5) # (magnitude) write_float32(buf, 0.5) # (magnitude)
write_uint(buf, 7) # angle, float64 write_uint(buf, 7) # angle, float64
write_float64(buf, 0.0) # (angle) write_float64(buf, 0.0) # (angle)
write_sint(buf, -150) # placement-x (relative) write_sint(buf, -150) # placement-x (relative)
write_sint(buf, 200) # placement-y (relative) write_sint(buf, 200) # placement-y (relative)
# PLACEMENT 1 # PLACEMENT 1
write_uint(buf, 18) # PLACEMENT (no mag, manhattan) write_uint(buf, 18) # PLACEMENT (no mag, manhattan)
write_byte(buf, 0b0011_0000) # CNXY_RMAF write_byte(buf, 0b0011_0000) # CNXY_RMAF
write_sint(buf, -150) # placement-x (relative) write_sint(buf, -150) # placement-x (relative)
write_sint(buf, 600) # placement-y (relative) write_sint(buf, 600) # placement-y (relative)
# PLACEMENT 2 # PLACEMENT 2
write_uint(buf, 18) # PLACEMENT (no mag, manhattan) write_uint(buf, 18) # PLACEMENT (no mag, manhattan)
write_byte(buf, 0b0001_0000) # CNXY_RMAF write_byte(buf, 0b0001_0000) # CNXY_RMAF
write_sint(buf, 400) # placement-y (relative) write_sint(buf, 400) # placement-y (relative)
# PLACEMENT 3 # PLACEMENT 3
write_uint(buf, 18) # PLACEMENT (no mag, manhattan) write_uint(buf, 18) # PLACEMENT (no mag, manhattan)
write_byte(buf, 0b0010_0000) # CNXY_RMAF write_byte(buf, 0b0010_0000) # CNXY_RMAF
write_sint(buf, 300) # placement-x (relative) write_sint(buf, 300) # placement-x (relative)
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# PLACEMENT 4 # PLACEMENT 4
write_uint(buf, 18) # PLACEMENT (no mag, manhattan) write_uint(buf, 18) # PLACEMENT (no mag, manhattan)
write_byte(buf, 0b0011_0001) # CNXY_RMAF write_byte(buf, 0b0011_0001) # CNXY_RMAF
write_sint(buf, 700) # placement-x (absolute) write_sint(buf, 700) # placement-x (absolute)
write_sint(buf, 400) # placement-y (absolute) write_sint(buf, 400) # placement-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# PLACEMENT 5 # PLACEMENT 5
write_uint(buf, 18) # PLACEMENT (no mag, manhattan) write_uint(buf, 18) # PLACEMENT (no mag, manhattan)
write_byte(buf, 0b0001_0010) # CNXY_RMAF write_byte(buf, 0b0001_0010) # CNXY_RMAF
write_uint(buf, 0) # angle (uint, positive) write_uint(buf, 0) # angle (uint, positive)
write_uint(buf, 90) # (angle) write_uint(buf, 90) # (angle)
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
# PLACEMENT 6 # PLACEMENT 6
write_uint(buf, 18) # PLACEMENT (no mag, manhattan) write_uint(buf, 18) # PLACEMENT (no mag, manhattan)
write_byte(buf, 0b0001_0011) # CNXY_RMAF write_byte(buf, 0b0001_0011) # CNXY_RMAF
write_uint(buf, 1) # angle (uint, negative) write_uint(buf, 1) # angle (uint, negative)
write_uint(buf, 90) # (angle) write_uint(buf, 90) # (angle)
write_sint(buf, 1000) # placement-y (relative) write_sint(buf, 1000) # placement-y (relative)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'A') # Cell name write_bstring(buf, b'A') # Cell name
write_rectangle(buf) write_rectangle(buf)
@ -747,76 +752,76 @@ def test_file_6() -> None:
assert pp.y == [0, 1000][ii], msg assert pp.y == [0, 1000][ii], msg
def write_file_8(buf: IO[bytes]) -> IO[bytes]: def write_file_8(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'TOPTOP') # Cell name write_bstring(buf, b'TOPTOP') # Cell name
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
write_uint(buf, 18) # PLACEMENT (mag 0.5, arbitrary angle) write_uint(buf, 18) # PLACEMENT (mag 0.5, arbitrary angle)
write_byte(buf, 0b1011_0110) # CNXY_RMAF write_byte(buf, 0b1011_0110) # CNXY_RMAF
write_bstring(buf, b'TOP') # Cell reference write_bstring(buf, b'TOP') # Cell reference
write_uint(buf, 6) # magnitude, float32 write_uint(buf, 6) # magnitude, float32
write_float32(buf, 0.5) # (magnitude) write_float32(buf, 0.5) # (magnitude)
write_uint(buf, 7) # angle, float64 write_uint(buf, 7) # angle, float64
write_float64(buf, 22.5) # (angle) write_float64(buf, 22.5) # (angle)
write_sint(buf, 100) # placement-x (absolute) write_sint(buf, 100) # placement-x (absolute)
write_sint(buf, 0) # placement-y (absolute) write_sint(buf, 0) # placement-y (absolute)
write_uint(buf, 18) # PLACEMENT (mag 1.0, manhattan) write_uint(buf, 18) # PLACEMENT (mag 1.0, manhattan)
write_byte(buf, 0b1011_0110) # CNXY_RMAF write_byte(buf, 0b1011_0110) # CNXY_RMAF
write_bstring(buf, b'TOP') # Cell reference write_bstring(buf, b'TOP') # Cell reference
write_uint(buf, 6) # magnitude, float32 write_uint(buf, 6) # magnitude, float32
write_float32(buf, 1.0) # (magnitude) write_float32(buf, 1.0) # (magnitude)
write_uint(buf, 7) # angle, float64 write_uint(buf, 7) # angle, float64
write_float64(buf, 0.0) # (angle) write_float64(buf, 0.0) # (angle)
write_sint(buf, 1100) # placement-x (absolute) write_sint(buf, 1100) # placement-x (absolute)
write_sint(buf, 0) # placement-y (absolute) write_sint(buf, 0) # placement-y (absolute)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'TOP') # Cell name write_bstring(buf, b'TOP') # Cell name
write_uint(buf, 18) # PLACEMENT (mag 2.0, manhattan) write_uint(buf, 18) # PLACEMENT (mag 2.0, manhattan)
write_byte(buf, 0b1011_0110) # CNXY_RMAF write_byte(buf, 0b1011_0110) # CNXY_RMAF
write_bstring(buf, b'A') # Cell reference write_bstring(buf, b'A') # Cell reference
write_uint(buf, 6) # magnitude, float32 write_uint(buf, 6) # magnitude, float32
write_float32(buf, 2.0) # (magnitude) write_float32(buf, 2.0) # (magnitude)
write_uint(buf, 7) # angle, float64 write_uint(buf, 7) # angle, float64
write_float64(buf, 0.0) # (angle) write_float64(buf, 0.0) # (angle)
write_sint(buf, -100) # placement-x (absolute) write_sint(buf, -100) # placement-x (absolute)
write_sint(buf, 100) # placement-y (absolute) write_sint(buf, 100) # placement-y (absolute)
write_uint(buf, 18) # PLACEMENT (mag 1.0, arbitrary angle) write_uint(buf, 18) # PLACEMENT (mag 1.0, arbitrary angle)
write_byte(buf, 0b1011_0110) # CNXY_RMAF write_byte(buf, 0b1011_0110) # CNXY_RMAF
write_bstring(buf, b'A') # Cell reference write_bstring(buf, b'A') # Cell reference
write_uint(buf, 6) # magnitude, float32 write_uint(buf, 6) # magnitude, float32
write_float32(buf, 1.0) # (magnitude) write_float32(buf, 1.0) # (magnitude)
write_uint(buf, 7) # angle, float64 write_uint(buf, 7) # angle, float64
write_float64(buf, 45.0) # (angle) write_float64(buf, 45.0) # (angle)
write_sint(buf, -150) # placement-x (absolute) write_sint(buf, -150) # placement-x (absolute)
write_sint(buf, 1100) # placement-y (absolute) write_sint(buf, 1100) # placement-y (absolute)
write_uint(buf, 18) # PLACEMENT (mag 0.5, arbitrary angle) write_uint(buf, 18) # PLACEMENT (mag 0.5, arbitrary angle)
write_byte(buf, 0b1011_1111) # CNXY_RMAF write_byte(buf, 0b1011_1111) # CNXY_RMAF
write_bstring(buf, b'A') # Cell reference write_bstring(buf, b'A') # Cell reference
write_uint(buf, 6) # magnitude, float32 write_uint(buf, 6) # magnitude, float32
write_float32(buf, 0.5) # (magnitude) write_float32(buf, 0.5) # (magnitude)
write_uint(buf, 7) # angle, float64 write_uint(buf, 7) # angle, float64
write_float64(buf, 135.0) # (angle) write_float64(buf, 135.0) # (angle)
write_sint(buf, -200) # placement-x (absolute) write_sint(buf, -200) # placement-x (absolute)
write_sint(buf, 2100) # placement-y (absolute) write_sint(buf, 2100) # placement-y (absolute)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 200) # (repetition) x-spacing write_uint(buf, 200) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'A') # Cell name write_bstring(buf, b'A') # Cell name
write_rectangle(buf, pos=(30, -40)) write_rectangle(buf, pos=(30, -40))
@ -843,7 +848,7 @@ def test_file_8() -> None:
assert not layout.cells[2].properties assert not layout.cells[2].properties
assert not layout.cells[2].placements assert not layout.cells[2].placements
geometry = cast(list[Rectangle], layout.cells[2].geometry) geometry = layout.cells[2].geometry
assert len(geometry) == 1 assert len(geometry) == 1
assert geometry[0].layer == 1 assert geometry[0].layer == 1
assert geometry[0].datatype == 2 assert geometry[0].datatype == 2

View File

@ -1,12 +1,17 @@
# mypy: disable-error-code="union-attr, arg-type" # type: ignore
from typing import IO
from io import BytesIO
from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
import numpy import numpy
from numpy.testing import assert_equal from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -80,11 +85,8 @@ def common_tests(layout: OasisLayout) -> None:
for ii in range(4): for ii in range(4):
msg = f'Fail on poly {ii}' msg = f'Fail on poly {ii}'
assert len(geometry[0].point_list) == 6, msg assert len(geometry[0].point_list) == 6, msg
assert_equal( assert_equal(geometry[0].point_list, [[150, 0], [0, 50], [-50, 0], [0, 50],
geometry[0].point_list, [-100, 0], [0, -100]], err_msg=msg)
[[150, 0], [0, 50], [-50, 0], [0, 50], [-100, 0], [0, -100]],
err_msg=msg,
)
assert len(geometry[4].point_list) == 6 assert len(geometry[4].point_list) == 6
assert_equal(geometry[4].point_list, [[0, 150], [50, 0], [0, -50], [50, 0], [0, -100], [-100, 0]]) assert_equal(geometry[4].point_list, [[0, 150], [50, 0], [0, -50], [50, 0], [0, -100], [-100, 0]])
@ -95,10 +97,8 @@ def common_tests(layout: OasisLayout) -> None:
assert len(geometry[7].point_list) == 9 assert len(geometry[7].point_list) == 9
assert_equal(geometry[7].point_list, [[25, 0], [50, 50], [0, 50], [-50, 50], [-50, 0], [-50, -50], [10, -75], [25, -25], [40, 0]]) assert_equal(geometry[7].point_list, [[25, 0], [50, 50], [0, 50], [-50, 50], [-50, 0], [-50, -50], [10, -75], [25, -25], [40, 0]])
assert len(geometry[8].point_list) == 9 assert len(geometry[8].point_list) == 9
assert_equal( assert_equal(geometry[8].point_list,
geometry[8].point_list, numpy.cumsum([[25, 0], [50, 50], [0, 50], [-50, 50], [-50, 0], [-50, -50], [10, -75], [25, -25], [45, -575]], axis=0))
numpy.cumsum([[25, 0], [50, 50], [0, 50], [-50, 50], [-50, 0], [-50, -50], [10, -75], [25, -25], [45, -575]], axis=0),
)
for ii in range(9, 12): for ii in range(9, 12):
msg = f'Fail on poly {ii}' msg = f'Fail on poly {ii}'
@ -106,57 +106,57 @@ def common_tests(layout: OasisLayout) -> None:
assert_equal(geometry[ii].point_list, [[0, 150], [50, 0], [0, -50], [50, 0], [0, -100], [-100, 0]], err_msg=msg) assert_equal(geometry[ii].point_list, [[0, 150], [50, 0], [0, -50], [50, 0], [0, -100], [-100, 0]], err_msg=msg)
def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]: def write_file_common(buf: BufferedIOBase, variant: int) -> BufferedIOBase:
""" '''
""" '''
assert variant in (1, 3), 'Error in test!!' assert variant in (1, 3), 'Error in test!!'
buf.write(HEADER) buf.write(HEADER)
if variant == 3: if variant == 3:
write_uint(buf, 7) # PROPNAME record (implict id 0) write_uint(buf, 7) # PROPNAME record (implict id 0)
write_bstring(buf, b'PROP0') # property name write_bstring(buf, b'PROP0') # property name
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'ABC') # Cell name write_bstring(buf, b'ABC') # Cell name
# POLYGON 0 # POLYGON 0
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_1011) # 00PX_YRDL write_byte(buf, 0b0011_1011) # 00PX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt
write_uint(buf, 4) # (pointlist) dimension write_uint(buf, 4) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, 0) # geometry-x (absolute) write_sint(buf, 0) # geometry-x (absolute)
write_sint(buf, 100) # geometry-y (absolute) write_sint(buf, 100) # geometry-y (absolute)
if variant == 3: if variant == 3:
# PROPERTY 0 # PROPERTY 0
write_uint(buf, 28) # PROPERTY record (explicit) write_uint(buf, 28) # PROPERTY record (explicit)
write_byte(buf, 0b0001_0110) # UUUU_VCNS write_byte(buf, 0b0001_0110) # UUUU_VCNS
write_uint(buf, 0) # propname id write_uint(buf, 0) # propname id
write_uint(buf, 2) # property value (real: positive reciprocal) write_uint(buf, 2) # property value (real: positive reciprocal)
write_uint(buf, 5) # (real) 1/5 write_uint(buf, 5) # (real) 1/5
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# Polygon 1 # Polygon 1
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_1011) # 00PX_YRDL write_byte(buf, 0b0011_1011) # 00PX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt
write_uint(buf, 4) # (pointlist) dimension write_uint(buf, 4) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -200) # geometry-x (relative) write_sint(buf, -200) # geometry-x (relative)
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
if variant == 3: if variant == 3:
# PROPERTY 1 # PROPERTY 1
@ -165,55 +165,55 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# Polygon 2 # Polygon 2
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0011) # 00PX_YRDL write_byte(buf, 0b0011_0011) # 00PX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt write_uint(buf, 0) # pointlist: 1-delta, horiz-fisrt
write_uint(buf, 4) # (pointlist) dimension write_uint(buf, 4) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, 0) # geometry-x (absolute) write_sint(buf, 0) # geometry-x (absolute)
if variant == 3: if variant == 3:
# PROPERTY 2 # PROPERTY 2
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# Polygon 3 # Polygon 3
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0000_1000) # 00PX_YRDL write_byte(buf, 0b0000_1000) # 00PX_YRDL
write_sint(buf, 1000) # geometry-y (absolute) write_sint(buf, 1000) # geometry-y (absolute)
if variant == 3: if variant == 3:
# PROPERTY 3 # PROPERTY 3
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# Polygon 4 # Polygon 4
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0011) # 00PX_YRDL write_byte(buf, 0b0011_0011) # 00PX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 1) # pointlist: 1-delta, vert-fisrt write_uint(buf, 1) # pointlist: 1-delta, vert-fisrt
write_uint(buf, 4) # (pointlist) dimension write_uint(buf, 4) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, 200) # geometry-x (absolute) write_sint(buf, 200) # geometry-x (absolute)
if variant == 3: if variant == 3:
# PROPERTY 4 # PROPERTY 4
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# Polygon 5 # Polygon 5
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0011) # 00PX_YRDL write_byte(buf, 0b0011_0011) # 00PX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 2) # pointlist: 2-delta write_uint(buf, 2) # pointlist: 2-delta
write_uint(buf, 7) # (pointlist) dimension write_uint(buf, 7) # (pointlist) dimension
write_uint(buf, 150 << 2 | 0b00) # (pointlist) write_uint(buf, 150 << 2 | 0b00) # (pointlist)
write_uint(buf, 50 << 2 | 0b01) # (pointlist) write_uint(buf, 50 << 2 | 0b01) # (pointlist)
write_uint(buf, 50 << 2 | 0b10) # (pointlist) write_uint(buf, 50 << 2 | 0b10) # (pointlist)
@ -228,12 +228,12 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# Polygon 6 # Polygon 6
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0011) # 00PX_YRDL write_byte(buf, 0b0011_0011) # 00PX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 3) # pointlist: 3-delta write_uint(buf, 3) # pointlist: 3-delta
write_uint(buf, 8) # (pointlist) dimension write_uint(buf, 8) # (pointlist) dimension
write_uint(buf, 25 << 3 | 0b000) # (pointlist) write_uint(buf, 25 << 3 | 0b000) # (pointlist)
write_uint(buf, 50 << 3 | 0b100) # (pointlist) write_uint(buf, 50 << 3 | 0b100) # (pointlist)
write_uint(buf, 50 << 3 | 0b001) # (pointlist) write_uint(buf, 50 << 3 | 0b001) # (pointlist)
@ -249,12 +249,12 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# Polygon 7 # Polygon 7
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0011) # 00PX_YRDL write_byte(buf, 0b0011_0011) # 00PX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 4) # pointlist: g-delta write_uint(buf, 4) # pointlist: g-delta
write_uint(buf, 8) # (pointlist) dimension write_uint(buf, 8) # (pointlist) dimension
write_uint(buf, 25 << 4 | 0b0000) # (pointlist) write_uint(buf, 25 << 4 | 0b0000) # (pointlist)
write_uint(buf, 50 << 4 | 0b1000) # (pointlist) write_uint(buf, 50 << 4 | 0b1000) # (pointlist)
write_uint(buf, 50 << 4 | 0b0010) # (pointlist) write_uint(buf, 50 << 4 | 0b0010) # (pointlist)
@ -263,7 +263,7 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 50 << 4 | 0b0100) # (pointlist) write_uint(buf, 50 << 4 | 0b0100) # (pointlist)
write_uint(buf, 50 << 4 | 0b1100) # (pointlist) write_uint(buf, 50 << 4 | 0b1100) # (pointlist)
write_uint(buf, 10 << 2 | 0b01) # (pointlist) write_uint(buf, 10 << 2 | 0b01) # (pointlist)
write_sint(buf, -75) write_sint(buf, -75 )
write_uint(buf, 25 << 4 | 0b1110) # (pointlist) write_uint(buf, 25 << 4 | 0b1110) # (pointlist)
write_sint(buf, 900) # geometry-x (absolute) write_sint(buf, 900) # geometry-x (absolute)
@ -272,12 +272,12 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# Polygon 8 # Polygon 8
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0011) # 00PX_YRDL write_byte(buf, 0b0011_0011) # 00PX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 5) # pointlist: double g-delta write_uint(buf, 5) # pointlist: double g-delta
write_uint(buf, 8) # (pointlist) dimension write_uint(buf, 8) # (pointlist) dimension
write_uint(buf, 25 << 4 | 0b0000) # (pointlist) write_uint(buf, 25 << 4 | 0b0000) # (pointlist)
write_uint(buf, 50 << 4 | 0b1000) # (pointlist) write_uint(buf, 50 << 4 | 0b1000) # (pointlist)
write_uint(buf, 50 << 4 | 0b0010) # (pointlist) write_uint(buf, 50 << 4 | 0b0010) # (pointlist)
@ -286,7 +286,7 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 50 << 4 | 0b0100) # (pointlist) write_uint(buf, 50 << 4 | 0b0100) # (pointlist)
write_uint(buf, 50 << 4 | 0b1100) # (pointlist) write_uint(buf, 50 << 4 | 0b1100) # (pointlist)
write_uint(buf, 10 << 2 | 0b01) # (pointlist) write_uint(buf, 10 << 2 | 0b01) # (pointlist)
write_sint(buf, -75) write_sint(buf, -75 )
write_uint(buf, 25 << 4 | 0b1110) # (pointlist) write_uint(buf, 25 << 4 | 0b1110) # (pointlist)
write_sint(buf, 1100) # geometry-x (absolute) write_sint(buf, 1100) # geometry-x (absolute)
@ -295,62 +295,62 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# Polygon 9 # Polygon 9
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_1111) # 00PX_YRDL write_byte(buf, 0b0011_1111) # 00PX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 1) # pointlist: 1-delta (vert. first) write_uint(buf, 1) # pointlist: 1-delta (vert. first)
write_uint(buf, 4) # (pointlist) dimension write_uint(buf, 4) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, 0) # geometry-x (absolute) write_sint(buf, 0) # geometry-x (absolute)
write_sint(buf, 2000) # geometry-y (absolute) write_sint(buf, 2000) # geometry-y (absolute)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 200) # (repetition) x-spacing write_uint(buf, 200) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
if variant == 3: if variant == 3:
# PROPERTY 9 # PROPERTY 9
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# Polygon 10 # Polygon 10
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0110) # 00PX_YRDL write_byte(buf, 0b0011_0110) # 00PX_YRDL
write_uint(buf, 1) # datatype write_uint(buf, 1) # datatype
write_uint(buf, 1) # pointlist: 1-delta (vert. first) write_uint(buf, 1) # pointlist: 1-delta (vert. first)
write_uint(buf, 4) # (pointlist) dimension write_uint(buf, 4) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, 1000) # geometry-x (relative) write_sint(buf, 1000) # geometry-x (relative)
write_uint(buf, 0) # repetition (reuse) write_uint(buf, 0) # repetition (reuse)
if variant == 3: if variant == 3:
# PROPERTY 10 # PROPERTY 10
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# Polygon 11 # Polygon 11
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0110) # 00PX_YRDL write_byte(buf, 0b0011_0110) # 00PX_YRDL
write_uint(buf, 1) # datatype write_uint(buf, 1) # datatype
write_uint(buf, 1) # pointlist: 1-delta (vert. first) write_uint(buf, 1) # pointlist: 1-delta (vert. first)
write_uint(buf, 4) # (pointlist) dimension write_uint(buf, 4) # (pointlist) dimension
write_sint(buf, 150) # (pointlist) write_sint(buf, 150) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, -50) # (pointlist) write_sint(buf, -50) # (pointlist)
write_sint(buf, 50) # (pointlist) write_sint(buf, 50) # (pointlist)
write_sint(buf, 1000) # geometry-x (relative) write_sint(buf, 1000) # geometry-x (relative)
write_uint(buf, 6) # repetition (3 rows) write_uint(buf, 6) # repetition (3 rows)
write_uint(buf, 1) # (repetition) dimension write_uint(buf, 1) # (repetition) dimension
write_uint(buf, 200) # (repetition) y-delta write_uint(buf, 200) # (repetition) y-delta
write_uint(buf, 300) # (repetition) y-delta write_uint(buf, 300) # (repetition) y-delta
if variant == 3: if variant == 3:
# PROPERTY 11 # PROPERTY 11
@ -375,9 +375,9 @@ def test_file_1() -> None:
assert not gg.properties, f'Fail on polygon {ii}' assert not gg.properties, f'Fail on polygon {ii}'
def write_file_2(buf: IO[bytes]) -> IO[bytes]: def write_file_2(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
@ -386,21 +386,21 @@ def write_file_2(buf: IO[bytes]) -> IO[bytes]:
write_uint(buf, 15) # XYRELATIVE record write_uint(buf, 15) # XYRELATIVE record
# POLYGON 0 # POLYGON 0
write_uint(buf, 21) # POLYGON record write_uint(buf, 21) # POLYGON record
write_byte(buf, 0b0011_0011) # 00PX_YRDL write_byte(buf, 0b0011_0011) # 00PX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 4) # pointlist: g-delta write_uint(buf, 4) # pointlist: g-delta
write_uint(buf, 8002) # (pointlist) dimension write_uint(buf, 8002) # (pointlist) dimension
write_uint(buf, 1000 << 2 | 0b11) # (pointlist) write_uint(buf, 1000 << 2 | 0b11) # (pointlist)
write_sint(buf, 0) # (pointlist) write_sint(buf, 0) # (pointlist)
for _ in range(4000): for _ in range(4000):
write_uint(buf, 10 << 2 | 0b01) # (pointlist) write_uint(buf, 10 << 2 | 0b01) # (pointlist)
write_sint(buf, 20) # (pointlist) write_sint(buf, 20) # (pointlist)
write_uint(buf, 10 << 2 | 0b11) # (pointlist) write_uint(buf, 10 << 2 | 0b11) # (pointlist)
write_sint(buf, 20) # (pointlist) write_sint(buf, 20) # (pointlist)
write_uint(buf, 1000 << 2 | 0b01) # (pointlist) write_uint(buf, 1000 << 2 | 0b01) # (pointlist)
write_sint(buf, 0) # (pointlist) write_sint(buf, 0) # (pointlist)
write_sint(buf, 0) # geometry-x (absolute) write_sint(buf, 0) # geometry-x (absolute)
buf.write(FOOTER) buf.write(FOOTER)
@ -425,8 +425,7 @@ def test_file_2() -> None:
assert_equal(poly.point_list, assert_equal(poly.point_list,
([[-1000, 0]] ([[-1000, 0]]
+ [[(-1) ** nn * 10, 20] for nn in range(8000)] + [[(-1) ** nn * 10, 20] for nn in range(8000)]
+ [[1000, 0], [0, -20 * 8000]]), + [[1000, 0], [0, -20 * 8000]]))
)
def test_file_3() -> None: def test_file_3() -> None:
@ -445,7 +444,7 @@ def test_file_3() -> None:
for ii, gg in enumerate(geometry): for ii, gg in enumerate(geometry):
msg = f'Fail on polygon {ii}' msg = f'Fail on polygon {ii}'
assert len(gg.properties) == 1, msg assert len(gg.properties) == 1, msg
assert gg.properties[0].name == 0, msg # type: ignore assert gg.properties[0].name == 0, msg
assert len(gg.properties[0].values) == 1, msg assert len(gg.properties[0].values) == 1, msg
assert gg.properties[0].values[0] * 5 == 1, msg # type: ignore assert gg.properties[0].values[0] * 5 == 1, msg

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,15 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO
from io import BytesIO from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -74,157 +80,157 @@ def base_tests(layout: OasisLayout) -> None:
assert geometry[10].repetition.x_displacements == [200, 300] assert geometry[10].repetition.x_displacements == [200, 300]
def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]: def write_file_common(buf: BufferedIOBase, variant: int) -> BufferedIOBase:
""" '''
""" '''
assert variant in (1, 2), 'Error in test!!' assert variant in (1, 2), 'Error in test!!'
buf.write(HEADER) buf.write(HEADER)
if variant == 2: if variant == 2:
write_uint(buf, 7) # PROPNAME record (implict id 0) write_uint(buf, 7) # PROPNAME record (implict id 0)
write_bstring(buf, b'PROP0') # property name write_bstring(buf, b'PROP0') # property name
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'ABC') # Cell name write_bstring(buf, b'ABC') # Cell name
# RECTANGLE 0 # RECTANGLE 0
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0111_1011) # SWHX_YRDL write_byte(buf, 0b0111_1011) # SWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, 300) # geometry-x (absolute) write_sint(buf, 300) # geometry-x (absolute)
write_sint(buf, -400) # geometry-y (absolute) write_sint(buf, -400) # geometry-y (absolute)
if variant == 2: if variant == 2:
# PROPERTY 0 # PROPERTY 0
write_uint(buf, 28) # PROPERTY record (explicit) write_uint(buf, 28) # PROPERTY record (explicit)
write_byte(buf, 0b0001_0110) # UUUU_VCNS write_byte(buf, 0b0001_0110) # UUUU_VCNS
write_uint(buf, 0) # propname id write_uint(buf, 0) # propname id
write_uint(buf, 2) # property value (real: positive reciprocal) write_uint(buf, 2) # property value (real: positive reciprocal)
write_uint(buf, 5) # (real) 1/5 write_uint(buf, 5) # (real) 1/5
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# RECTANGLE 1 # RECTANGLE 1
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0111_1011) # SWHX_YRDL write_byte(buf, 0b0111_1011) # SWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, 100) # geometry-x (relative) write_sint(buf, 100) # geometry-x (relative)
write_sint(buf, -100) # geometry-y (relative) write_sint(buf, -100) # geometry-y (relative)
if variant == 2: if variant == 2:
# PROPERTY 1 # PROPERTY 1
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# RECTANGLE 2 # RECTANGLE 2
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0111_1011) # SWHX_YRDL write_byte(buf, 0b0111_1011) # SWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, 600) # geometry-x (absolute) write_sint(buf, 600) # geometry-x (absolute)
write_sint(buf, -300) # geometry-y (absolute) write_sint(buf, -300) # geometry-y (absolute)
if variant == 2: if variant == 2:
# PROPERTY 2 # PROPERTY 2
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# RECTANGLE 3 # RECTANGLE 3
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0111_0011) # SWHX_YRDL write_byte(buf, 0b0111_0011) # SWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, 800) # geometry-x (absolute) write_sint(buf, 800) # geometry-x (absolute)
if variant == 2: if variant == 2:
# PROPERTY 3 # PROPERTY 3
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# RECTANGLE 4 # RECTANGLE 4
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0110_1011) # SWHX_YRDL write_byte(buf, 0b0110_1011) # SWHX_YRDL
write_uint(buf, 2) # layer write_uint(buf, 2) # layer
write_uint(buf, 3) # datatype write_uint(buf, 3) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, -600) # geometry-y (absolute) write_sint(buf, -600) # geometry-y (absolute)
if variant == 2: if variant == 2:
# PROPERTY 4 # PROPERTY 4
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# RECTANGLE 5 # RECTANGLE 5
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0110_1000) # SWHX_YRDL write_byte(buf, 0b0110_1000) # SWHX_YRDL
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 200) # height write_uint(buf, 200) # height
write_sint(buf, -900) # geometry-y (absolute) write_sint(buf, -900) # geometry-y (absolute)
if variant == 2: if variant == 2:
# PROPERTY 5 # PROPERTY 5
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# RECTANGLE 6 # RECTANGLE 6
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0000_1000) # SWHX_YRDL write_byte(buf, 0b0000_1000) # SWHX_YRDL
write_sint(buf, -1200) # geometry-y (absolute) write_sint(buf, -1200) # geometry-y (absolute)
if variant == 2: if variant == 2:
# PROPERTY 6 # PROPERTY 6
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# RECTANGLE 7 # RECTANGLE 7
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b1100_1000) # SWHX_YRDL write_byte(buf, 0b1100_1000) # SWHX_YRDL
write_uint(buf, 150) # width write_uint(buf, 150) # width
write_sint(buf, -1500) # geometry-y (absolute) write_sint(buf, -1500) # geometry-y (absolute)
if variant == 2: if variant == 2:
# PROPERTY 7 # PROPERTY 7
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# RECTANGLE 8 # RECTANGLE 8
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0000_1000) # SWHX_YRDL write_byte(buf, 0b0000_1000) # SWHX_YRDL
write_sint(buf, -1800) # geometry-y (absolute) write_sint(buf, -1800) # geometry-y (absolute)
if variant == 2: if variant == 2:
# PROPERTY 8 # PROPERTY 8
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# RECTANGLE 9 # RECTANGLE 9
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0000_1100) # SWHX_YRDL write_byte(buf, 0b0000_1100) # SWHX_YRDL
write_sint(buf, 500) # geometry-y (absolute) write_sint(buf, 500) # geometry-y (absolute)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 200) # (repetition) x-spacing write_uint(buf, 200) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
if variant == 2: if variant == 2:
# PROPERTY 9 # PROPERTY 9
write_uint(buf, 29) # PROPERTY record (repeat) write_uint(buf, 29) # PROPERTY record (repeat)
# RECTANGLE 10 # RECTANGLE 10
write_uint(buf, 20) # RECTANGLE record write_uint(buf, 20) # RECTANGLE record
write_byte(buf, 0b0000_1100) # SWHX_YRDL write_byte(buf, 0b0000_1100) # SWHX_YRDL
write_sint(buf, 2000) # geometry-y (absolute) write_sint(buf, 2000) # geometry-y (absolute)
write_uint(buf, 4) # repetition (3 arbitrary cols.) write_uint(buf, 4) # repetition (3 arbitrary cols.)
write_uint(buf, 1) # (repetition) dimension write_uint(buf, 1) # (repetition) dimension
write_uint(buf, 200) # (repetition) x-delta write_uint(buf, 200) # (repetition) x-delta
write_uint(buf, 300) # (repetition) x-delta write_uint(buf, 300) # (repetition) x-delta
if variant == 2: if variant == 2:
# PROPERTY 10 # PROPERTY 10
@ -267,7 +273,7 @@ def test_file_2() -> None:
prop = gg.properties[0] prop = gg.properties[0]
assert prop.name == 0, msg assert prop.name == 0, msg
assert len(prop.values) == 1, msg # type: ignore assert len(prop.values) == 1, msg
assert prop.values[0].numerator == 1, msg # type: ignore assert prop.values[0].numerator == 1, msg
assert prop.values[0].denominator == 5, msg # type: ignore assert prop.values[0].denominator == 5, msg

View File

@ -1,11 +1,14 @@
# mypy: disable-error-code="union-attr, index" # type: ignore
from typing import IO
from io import BytesIO
import pytest from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte
from ..basic import InvalidRecordError, InvalidDataError from ..basic import InvalidRecordError, InvalidDataError
from ..basic import GridRepetition, ArbitraryRepetition from ..basic import GridRepetition, ArbitraryRepetition
from ..main import OasisLayout from ..main import OasisLayout
@ -30,8 +33,8 @@ def common_tests(layout: OasisLayout) -> None:
geometry = layout.cells[0].geometry geometry = layout.cells[0].geometry
assert geometry[0].layer == 1 geometry[0].layer == 1
assert geometry[0].datatype == 2 geometry[0].datatype == 2
for ii, gg in enumerate(geometry[1:]): for ii, gg in enumerate(geometry[1:]):
assert gg.layer == 2, f'textstring #{ii + 1}' assert gg.layer == 2, f'textstring #{ii + 1}'
assert gg.datatype == 1, f'textstring #{ii + 1}' assert gg.datatype == 1, f'textstring #{ii + 1}'
@ -83,12 +86,12 @@ def common_tests(layout: OasisLayout) -> None:
assert geometry[13].repetition.b_vector == [-10, 10] assert geometry[13].repetition.b_vector == [-10, 10]
assert geometry[14].repetition.a_count == 3 assert geometry[14].repetition.a_count == 3
assert geometry[14].repetition.b_count is None assert geometry[14].repetition.b_count == None
assert geometry[14].repetition.a_vector == [11, 12] assert geometry[14].repetition.a_vector == [11, 12]
assert geometry[14].repetition.b_vector is None assert geometry[14].repetition.b_vector is None
assert geometry[15].repetition.a_count == 4 assert geometry[15].repetition.a_count == 4
assert geometry[15].repetition.b_count is None assert geometry[15].repetition.b_count == None
assert geometry[15].repetition.a_vector == [-10, 10] assert geometry[15].repetition.a_vector == [-10, 10]
assert geometry[15].repetition.b_vector is None assert geometry[15].repetition.b_vector is None
@ -99,10 +102,10 @@ def common_tests(layout: OasisLayout) -> None:
assert geometry[19].repetition.y_displacements == [12, -9] assert geometry[19].repetition.y_displacements == [12, -9]
def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]: def write_file_common(buf: BufferedIOBase, variant: int) -> BufferedIOBase:
""" '''
Single cell with explicit name 'XYZ' Single cell with explicit name 'XYZ'
""" '''
assert variant in (1, 2, 5, 12), 'Error in test!!' assert variant in (1, 2, 5, 12), 'Error in test!!'
buf.write(HEADER) buf.write(HEADER)
@ -253,9 +256,9 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 8) # repetition (3x4 matrix w/arb. vectors) write_uint(buf, 8) # repetition (3x4 matrix w/arb. vectors)
write_uint(buf, 1) # (repetition) n-dimension write_uint(buf, 1) # (repetition) n-dimension
write_uint(buf, 2) # (repetition) m-dimension write_uint(buf, 2) # (repetition) m-dimension
write_uint(buf, (10 << 4) | 0b0000) # (repetition) n-displacement g-delta: 10/east = (10, 0) write_uint(buf, (10 << 4) | 0b0000) # (repetition) n-displacement g-delta: 10/east = (10, 0)
write_uint(buf, (11 << 2) | 0b11) # (repetition) m-displacement g-delta: (-11, -12) write_uint(buf, (11 << 2) | 0b11) # (repetition) m-displacement g-delta: (-11, -12)
write_sint(buf, -12) # (repetition g-delta) write_sint(buf, -12) # (repetition g-delta)
# TEXT 13 # TEXT 13
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
@ -264,9 +267,9 @@ def write_file_common(buf: IO[bytes], variant: int) -> IO[bytes]:
write_uint(buf, 8) # repetition (3x4 matrix w/arb. vectors) write_uint(buf, 8) # repetition (3x4 matrix w/arb. vectors)
write_uint(buf, 1) # (repetition) n-dimension write_uint(buf, 1) # (repetition) n-dimension
write_uint(buf, 2) # (repetition) m-dimension write_uint(buf, 2) # (repetition) m-dimension
write_uint(buf, (11 << 2) | 0b01) # (repetition) n-displacement g-delta: (11, 12) write_uint(buf, (11 << 2) | 0b01) # (repetition) n-displacement g-delta: (11, 12)
write_sint(buf, 12) write_sint(buf, 12)
write_uint(buf, (10 << 4) | 0b1010) # (repetition) n-displacement g-delta: 10/northwest = (-10, 10) write_uint(buf, (10 << 4) | 0b1010) # (repetition) n-displacement g-delta: 10/northwest = (-10, 10)
# TEXT 14 # TEXT 14
write_uint(buf, 19) # TEXT record write_uint(buf, 19) # TEXT record
@ -460,11 +463,11 @@ def test_file_12() -> None:
assert layout.textstrings[2].string == 'B' assert layout.textstrings[2].string == 'B'
def write_file_3(buf: IO[bytes]) -> IO[bytes]: def write_file_3(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File with one textstring with explicit id, and one with an implicit id. File with one textstring with explicit id, and one with an implicit id.
Should fail. Should fail.
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 6) # TEXTSTRING record (explicit id) write_uint(buf, 6) # TEXTSTRING record (explicit id)
@ -494,15 +497,15 @@ def test_file_3() -> None:
buf.seek(0) buf.seek(0)
with pytest.raises(InvalidRecordError): with pytest.raises(InvalidRecordError):
_layout = OasisLayout.read(buf) layout = OasisLayout.read(buf)
def write_file_4(buf: IO[bytes]) -> IO[bytes]: def write_file_4(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File with a TEXT record that references a non-existent TEXTSTRING File with a TEXT record that references a non-existent TEXTSTRING
TODO add an optional check for valid references TODO add an optional check for valid references
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 5) # TEXTSTRING record (implicit id 0) write_uint(buf, 5) # TEXTSTRING record (implicit id 0)
@ -537,10 +540,10 @@ def test_file_4() -> None:
base_tests(layout) base_tests(layout)
def write_file_6(buf: IO[bytes]) -> IO[bytes]: def write_file_6(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File with TEXT record that uses an un-filled modal for the repetition File with TEXT record that uses an un-filled modal for the repetition
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 5) # TEXTSTRING record (implicit id 0) write_uint(buf, 5) # TEXTSTRING record (implicit id 0)
@ -567,13 +570,13 @@ def test_file_6() -> None:
buf.seek(0) buf.seek(0)
with pytest.raises(InvalidDataError): with pytest.raises(InvalidDataError):
_layout = OasisLayout.read(buf) layout = OasisLayout.read(buf)
def write_file_7(buf: IO[bytes]) -> IO[bytes]: def write_file_7(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File with TEXT record that uses an un-filled modal for the layer File with TEXT record that uses an un-filled modal for the layer
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 5) # TEXTSTRING record (implicit id 0) write_uint(buf, 5) # TEXTSTRING record (implicit id 0)
@ -598,13 +601,13 @@ def test_file_7() -> None:
buf.seek(0) buf.seek(0)
with pytest.raises(InvalidDataError): with pytest.raises(InvalidDataError):
_layout = OasisLayout.read(buf) layout = OasisLayout.read(buf)
def write_file_8(buf: IO[bytes]) -> IO[bytes]: def write_file_8(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File with TEXT record that uses an un-filled modal for the datatype File with TEXT record that uses an un-filled modal for the datatype
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 5) # TEXTSTRING record (implicit id 0) write_uint(buf, 5) # TEXTSTRING record (implicit id 0)
@ -629,13 +632,13 @@ def test_file_8() -> None:
buf.seek(0) buf.seek(0)
with pytest.raises(InvalidDataError): with pytest.raises(InvalidDataError):
_layout = OasisLayout.read(buf) layout = OasisLayout.read(buf)
def write_file_9(buf: IO[bytes]) -> IO[bytes]: def write_file_9(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File with TEXT record that uses a default modal for the x coordinate File with TEXT record that uses a default modal for the x coordinate
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 5) # TEXTSTRING record (implicit id 0) write_uint(buf, 5) # TEXTSTRING record (implicit id 0)
@ -668,10 +671,10 @@ def test_file_9() -> None:
assert text.y == -200 assert text.y == -200
def write_file_10(buf: IO[bytes]) -> IO[bytes]: def write_file_10(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File with TEXT record that uses a default modal for the y coordinate File with TEXT record that uses a default modal for the y coordinate
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 5) # TEXTSTRING record (implicit id 0) write_uint(buf, 5) # TEXTSTRING record (implicit id 0)
@ -704,10 +707,10 @@ def test_file_10() -> None:
assert text.x == 100 assert text.x == 100
def write_file_11(buf: IO[bytes]) -> IO[bytes]: def write_file_11(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
File with TEXT record that uses an un-filled modal for the text string File with TEXT record that uses an un-filled modal for the text string
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 5) # TEXTSTRING record (implicit id 0) write_uint(buf, 5) # TEXTSTRING record (implicit id 0)
@ -732,4 +735,4 @@ def test_file_11() -> None:
buf.seek(0) buf.seek(0)
with pytest.raises(InvalidDataError): with pytest.raises(InvalidDataError):
_layout = OasisLayout.read(buf) layout = OasisLayout.read(buf)

View File

@ -1,9 +1,17 @@
# mypy: disable-error-code="union-attr" # type: ignore
from typing import IO
from io import BytesIO from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
import pytest # type: ignore
import numpy
from numpy.testing import assert_equal
from .utils import HEADER, FOOTER from .utils import HEADER, FOOTER
from ..basic import write_uint, write_sint, write_bstring, write_byte from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte, PathExtensionScheme
from ..basic import InvalidRecordError, InvalidDataError
from ..main import OasisLayout from ..main import OasisLayout
@ -24,150 +32,150 @@ def base_tests(layout: OasisLayout) -> None:
assert not layout.cells[0].properties assert not layout.cells[0].properties
def write_file_1(buf: IO[bytes]) -> IO[bytes]: def write_file_1(buf: BufferedIOBase) -> BufferedIOBase:
""" '''
""" '''
buf.write(HEADER) buf.write(HEADER)
write_uint(buf, 14) # CELL record (explicit) write_uint(buf, 14) # CELL record (explicit)
write_bstring(buf, b'ABC') # Cell name write_bstring(buf, b'ABC') # Cell name
# Trapezoid 0 # Trapezoid 0
write_uint(buf, 23) # TRAPEZOID record write_uint(buf, 23) # TRAPEZOID record
write_byte(buf, 0b0111_1011) # OWHX_YRDL write_byte(buf, 0b0111_1011) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 50) # height write_uint(buf, 50) # height
write_sint(buf, -20) # delta-a write_sint(buf, -20) # delta-a
write_sint(buf, 40) # delta-b write_sint(buf, 40) # delta-b
write_sint(buf, 0) # geometry-x (absolute) write_sint(buf, 0) # geometry-x (absolute)
write_sint(buf, 100) # geometry-y (absolute) write_sint(buf, 100) # geometry-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# Trapezoid 1 # Trapezoid 1
write_uint(buf, 23) # TRAPEZOID record write_uint(buf, 23) # TRAPEZOID record
write_byte(buf, 0b1010_1011) # OWHX_YRDL write_byte(buf, 0b1010_1011) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 50) # height write_uint(buf, 50) # height
write_sint(buf, 20) # delta-a write_sint(buf, 20) # delta-a
write_sint(buf, 40) # delta-b write_sint(buf, 40) # delta-b
write_sint(buf, 300) # geometry-y (absolute) write_sint(buf, 300) # geometry-y (absolute)
# Trapezoid 2 # Trapezoid 2
write_uint(buf, 23) # TRAPEZOID record write_uint(buf, 23) # TRAPEZOID record
write_byte(buf, 0b1100_1001) # OWHX_YRDL write_byte(buf, 0b1100_1001) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 150) # width write_uint(buf, 150) # width
write_sint(buf, 20) # delta-a write_sint(buf, 20) # delta-a
write_sint(buf, -20) # delta-b write_sint(buf, -20) # delta-b
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
# Trapezoid 3 # Trapezoid 3
write_uint(buf, 23) # TRAPEZOID record write_uint(buf, 23) # TRAPEZOID record
write_byte(buf, 0b0100_1101) # OWHX_YRDL write_byte(buf, 0b0100_1101) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 150) # width write_uint(buf, 150) # width
write_sint(buf, 20) # delta-a write_sint(buf, 20) # delta-a
write_sint(buf, -20) # delta-b write_sint(buf, -20) # delta-b
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 200) # (repetition) x-spacing write_uint(buf, 200) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# Trapezoid 4 # Trapezoid 4
write_uint(buf, 24) # TRAPEZOID record write_uint(buf, 24) # TRAPEZOID record
write_byte(buf, 0b0111_1011) # OWHX_YRDL write_byte(buf, 0b0111_1011) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 50) # height write_uint(buf, 50) # height
write_sint(buf, -20) # delta-a write_sint(buf, -20) # delta-a
write_sint(buf, 1000) # geometry-x (absolute) write_sint(buf, 1000) # geometry-x (absolute)
write_sint(buf, 100) # geometry-y (absolute) write_sint(buf, 100) # geometry-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# Trapezoid 5 # Trapezoid 5
write_uint(buf, 24) # TRAPEZOID record write_uint(buf, 24) # TRAPEZOID record
write_byte(buf, 0b1010_1011) # OWHX_YRDL write_byte(buf, 0b1010_1011) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 50) # height write_uint(buf, 50) # height
write_sint(buf, 20) # delta-a write_sint(buf, 20) # delta-a
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
# Trapezoid 6 # Trapezoid 6
write_uint(buf, 24) # TRAPEZOID record write_uint(buf, 24) # TRAPEZOID record
write_byte(buf, 0b1100_1001) # OWHX_YRDL write_byte(buf, 0b1100_1001) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 150) # width write_uint(buf, 150) # width
write_sint(buf, 20) # delta-a write_sint(buf, 20) # delta-a
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
# Trapezoid 7 # Trapezoid 7
write_uint(buf, 24) # TRAPEZOID record write_uint(buf, 24) # TRAPEZOID record
write_byte(buf, 0b0100_1101) # OWHX_YRDL write_byte(buf, 0b0100_1101) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 150) # width write_uint(buf, 150) # width
write_sint(buf, 20) # delta-a write_sint(buf, 20) # delta-a
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 200) # (repetition) x-spacing write_uint(buf, 200) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
write_uint(buf, 15) # XYABSOLUTE record write_uint(buf, 15) # XYABSOLUTE record
# Trapezoid 8 # Trapezoid 8
write_uint(buf, 25) # TRAPEZOID record write_uint(buf, 25) # TRAPEZOID record
write_byte(buf, 0b0111_1011) # OWHX_YRDL write_byte(buf, 0b0111_1011) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 100) # width write_uint(buf, 100) # width
write_uint(buf, 50) # height write_uint(buf, 50) # height
write_sint(buf, 40) # delta-b write_sint(buf, 40) # delta-b
write_sint(buf, 2000) # geometry-x (absolute) write_sint(buf, 2000) # geometry-x (absolute)
write_sint(buf, 100) # geometry-y (absolute) write_sint(buf, 100) # geometry-y (absolute)
write_uint(buf, 16) # XYRELATIVE record write_uint(buf, 16) # XYRELATIVE record
# Trapezoid 9 # Trapezoid 9
write_uint(buf, 25) # TRAPEZOID record write_uint(buf, 25) # TRAPEZOID record
write_byte(buf, 0b1010_1011) # OWHX_YRDL write_byte(buf, 0b1010_1011) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 2) # datatype write_uint(buf, 2) # datatype
write_uint(buf, 50) # height write_uint(buf, 50) # height
write_sint(buf, 40) # delta-b write_sint(buf, 40) # delta-b
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
# Trapezoid 10 # Trapezoid 10
write_uint(buf, 25) # TRAPEZOID record write_uint(buf, 25) # TRAPEZOID record
write_byte(buf, 0b1100_1001) # OWHX_YRDL write_byte(buf, 0b1100_1001) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 150) # width write_uint(buf, 150) # width
write_sint(buf, -20) # delta-b write_sint(buf, -20) # delta-b
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
# Trapezoid 11 # Trapezoid 11
write_uint(buf, 25) # TRAPEZOID record write_uint(buf, 25) # TRAPEZOID record
write_byte(buf, 0b0100_1101) # OWHX_YRDL write_byte(buf, 0b0100_1101) # OWHX_YRDL
write_uint(buf, 1) # layer write_uint(buf, 1) # layer
write_uint(buf, 150) # width write_uint(buf, 150) # width
write_sint(buf, -20) # delta-b write_sint(buf, -20) # delta-b
write_sint(buf, 300) # geometry-y (relative) write_sint(buf, 300) # geometry-y (relative)
write_uint(buf, 1) # repetition (3x4 matrix) write_uint(buf, 1) # repetition (3x4 matrix)
write_uint(buf, 1) # (repetition) x-dimension write_uint(buf, 1) # (repetition) x-dimension
write_uint(buf, 2) # (repetition) y-dimension write_uint(buf, 2) # (repetition) y-dimension
write_uint(buf, 200) # (repetition) x-spacing write_uint(buf, 200) # (repetition) x-spacing
write_uint(buf, 300) # (repetition) y-spacing write_uint(buf, 300) # (repetition) y-spacing
buf.write(FOOTER) buf.write(FOOTER)
return buf return buf
@ -209,7 +217,7 @@ def test_file_1() -> None:
if ii in (0, 4): if ii in (0, 4):
assert gg.delta_a == -20, msg assert gg.delta_a == -20, msg
elif ii >= 8: elif 8 <= ii:
assert gg.delta_a == 0, msg assert gg.delta_a == 0, msg
else: else:
assert gg.delta_a == 20, msg assert gg.delta_a == 20, msg

View File

@ -1,6 +1,9 @@
from typing import List, Tuple, Iterable
from itertools import chain from itertools import chain
from io import BytesIO from io import BytesIO
import pytest # type: ignore
from ..basic import read_uint, read_sint, write_uint, write_sint from ..basic import read_uint, read_sint, write_uint, write_sint

View File

@ -1,6 +1,12 @@
from io import BytesIO from typing import List, Tuple, Iterable
from itertools import chain
from io import BytesIO, BufferedIOBase
import struct
from ..basic import write_uint, write_bstring, write_byte import pytest # type: ignore
from ..basic import write_uint, write_sint, read_uint, read_sint, write_bstring, write_byte
from ..main import OasisLayout
MAGIC_BYTES = b'%SEMI-OASIS\r\n' MAGIC_BYTES = b'%SEMI-OASIS\r\n'

View File

@ -44,7 +44,7 @@ classifiers = [
"Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)",
] ]
requires-python = ">=3.11" requires-python = ">=3.8"
dynamic = ["version"] dynamic = ["version"]
dependencies = [ dependencies = [
] ]
@ -53,38 +53,4 @@ dependencies = [
path = "fatamorgana/__init__.py" path = "fatamorgana/__init__.py"
[project.optional-dependencies] [project.optional-dependencies]
numpy = ["numpy>=1.26"] numpy = ["numpy~=1.21"]
[tool.ruff]
exclude = [
".git",
"dist",
]
line-length = 145
indent-width = 4
lint.dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
lint.select = [
"NPY", "E", "F", "W", "B", "ANN", "UP", "SLOT", "SIM", "LOG",
"C4", "ISC", "PIE", "PT", "RET", "TCH", "PTH", "INT",
"ARG", "PL", "R", "TRY",
"G010", "G101", "G201", "G202",
"Q002", "Q003", "Q004",
]
lint.ignore = [
#"ANN001", # No annotation
"ANN002", # *args
"ANN003", # **kwargs
"ANN401", # Any
"ANN101", # self: Self
"SIM108", # single-line if / else assignment
"RET504", # x=y+z; return x
"PIE790", # unnecessary pass
"ISC003", # non-implicit string concatenation
"C408", # dict(x=y) instead of {'x': y}
"PLR09", # Too many xxx
"PLR2004", # magic number
"PLC0414", # import x as x
"TRY003", # Long exception message
]