Compare commits
	
		
			28 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 90e30821eb | |||
| b3a4862e46 | |||
| 763f09051a | |||
| eaef972c88 | |||
| 5fb229c09f | |||
| a3773df853 | |||
| 0f68796831 | |||
| deb3460df3 | |||
| afa2f0259d | |||
| b450fd10fe | |||
| dfbb907274 | |||
| feeaef6aa4 | |||
| 9d01997275 | |||
| e47bff3204 | |||
| 701400d442 | |||
| 26ca1cd012 | |||
| 7e318b2001 | |||
| 4dc3a6892a | |||
| 9a35859210 | |||
| cbd484db6a | |||
| 41d994e8fc | |||
| 2b8b50d084 | |||
| 65533b8d99 | |||
| 9ee5778933 | |||
| 8d5f60ca72 | |||
| 6648b607ff | |||
| 411ad512e5 | |||
| 28eb68f57a | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,5 +1,5 @@ | |||||||
| *.pyc | *.pyc | ||||||
| __pycache__ | __pycache__/ | ||||||
| 
 | 
 | ||||||
| *.idea | *.idea | ||||||
| 
 | 
 | ||||||
| @ -7,6 +7,7 @@ build/ | |||||||
| dist/ | dist/ | ||||||
| *.egg-info/ | *.egg-info/ | ||||||
| .mypy_cache/ | .mypy_cache/ | ||||||
|  | .pytest_cache/ | ||||||
| 
 | 
 | ||||||
| *.swp | *.swp | ||||||
| *.swo | *.swo | ||||||
|  | |||||||
| @ -6,13 +6,13 @@ | |||||||
| ### Links | ### Links | ||||||
| - [Source repository](https://mpxd.net/code/jan/g85) | - [Source repository](https://mpxd.net/code/jan/g85) | ||||||
| - [PyPI](https://pypi.org/project/g85) | - [PyPI](https://pypi.org/project/g85) | ||||||
|  | - [Github mirror](https://github.com/anewusername/g85) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ## Installation | ## Installation | ||||||
| 
 | 
 | ||||||
| Requirements: | Requirements: | ||||||
| * python >= 3.7 (written and tested with 3.9) | * python >= 3.10 (written and tested with 3.11) | ||||||
| * numpy |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Install with pip: | Install with pip: | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								g85/LICENSE.md
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								g85/LICENSE.md
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../LICENSE.md | ||||||
							
								
								
									
										1
									
								
								g85/README.md
									
									
									
									
									
										Symbolic link
									
								
							
							
						
						
									
										1
									
								
								g85/README.md
									
									
									
									
									
										Symbolic link
									
								
							| @ -0,0 +1 @@ | |||||||
|  | ../README.md | ||||||
| @ -1,4 +0,0 @@ | |||||||
| """ VERSION defintion. THIS FILE IS MANUALLY PARSED BY setup.py and REQUIRES A SPECIFIC FORMAT """ |  | ||||||
| __version__ = ''' |  | ||||||
| 0.1 |  | ||||||
| '''.strip() |  | ||||||
| @ -1,3 +1,9 @@ | |||||||
| from .main import Map, Device | from .main import ( | ||||||
| from .read import read |     Map as Map, | ||||||
| from .write import write |     Device as Device, | ||||||
|  |     ) | ||||||
|  | from .read import read as read | ||||||
|  | from .write import write as write | ||||||
|  | 
 | ||||||
|  | __author__ = 'Jan Petykiewicz' | ||||||
|  | __version__ = '0.7' | ||||||
|  | |||||||
							
								
								
									
										39
									
								
								g85/main.py
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								g85/main.py
									
									
									
									
									
								
							| @ -1,4 +1,3 @@ | |||||||
| from typing import Dict, List, Tuple, Union, Optional |  | ||||||
| import datetime | import datetime | ||||||
| from collections import Counter | from collections import Counter | ||||||
| from dataclasses import dataclass, field | from dataclasses import dataclass, field | ||||||
| @ -8,25 +7,25 @@ from itertools import chain | |||||||
| @dataclass | @dataclass | ||||||
| class Device: | class Device: | ||||||
|     BinType: str |     BinType: str | ||||||
|     NullBin: Union[str, int] |     NullBin: str | int | ||||||
|     ProductId: Optional[str] = None |     ProductId: str | None = None | ||||||
|     LotId: Optional[str] = None |     LotId: str | None = None | ||||||
|     WaferSize: Optional[float] = None |     WaferSize: float | None = None | ||||||
|     CreateDate: Optional[datetime.datetime] = None |     CreateDate: datetime.datetime | None = None | ||||||
|     DeviceSizeX: Optional[float] = None |     DeviceSizeX: float | None = None | ||||||
|     DeviceSizeY: Optional[float] = None |     DeviceSizeY: float | None = None | ||||||
|     SupplierName: Optional[str] = None |     SupplierName: str | None = None | ||||||
|     OriginLocation: Optional[int] = None |     OriginLocation: int | None = None | ||||||
|     MapType: str = 'Array' |     MapType: str = 'Array' | ||||||
|     Orientation: float = 0 |     Orientation: float = 0 | ||||||
|     reference_xy: Optional[Tuple[int, int]] = None |     reference_xy: tuple[int, int] | None = None | ||||||
| 
 | 
 | ||||||
|     bin_pass: Dict[Union[int, str], bool] = field(default_factory=dict)  # Is this bin passing? |     bin_pass: dict[int | str, bool] = field(default_factory=dict)  # Is this bin passing? | ||||||
|     map: Union[List[List[int]], List[List[str]]] = field(default_factory=list)   # The actual map |     map: list[list[int]] | list[list[str]] = field(default_factory=list)   # The actual map | ||||||
|     # Map attribs: MapName, MapVersion |     data_misc: dict[str, str] = field(default_factory=dict)    # <Data attribs> | ||||||
|     # SupplierData attribs: ProductCode, RecipeName |     supplier_data: dict[str, str] = field(default_factory=dict)    # <SupplierData attribs> | ||||||
| 
 | 
 | ||||||
|     misc: Dict[str, str] = field(default_factory=dict)  # Any unexpected fields go here |     misc: dict[str, str] = field(default_factory=dict)  # Any unexpected fields go here | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|     def Rows(self) -> int: |     def Rows(self) -> int: | ||||||
| @ -46,9 +45,9 @@ class Device: | |||||||
| class Map: | class Map: | ||||||
|     xmlns: str = 'http://www.semi.org' |     xmlns: str = 'http://www.semi.org' | ||||||
|     FormatRevision: str = "SEMI G85 0703" |     FormatRevision: str = "SEMI G85 0703" | ||||||
|     SubstrateType: Optional[str] = None |     SubstrateType: str | None = None | ||||||
|     SubstrateId: Optional[str] = None |     SubstrateId: str | None = None | ||||||
| 
 | 
 | ||||||
|     devices: List[Device] = field(default_factory=list) |     devices: list[Device] = field(default_factory=list) | ||||||
|     misc: Dict[str, str] = field(default_factory=dict)  # Any unexpected fields go here |     misc: dict[str, str] = field(default_factory=dict)  # Any unexpected fields go here | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										45
									
								
								g85/read.py
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								g85/read.py
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| from typing import List, Union, TextIO, Any | from typing import TextIO, Any | ||||||
| import logging | import logging | ||||||
| import datetime | import datetime | ||||||
| from dataclasses import fields | from dataclasses import fields | ||||||
| @ -10,7 +10,7 @@ from .main import Map, Device | |||||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def read(stream: TextIO) -> List[Map]: | def read(stream: TextIO) -> list[Map]: | ||||||
|     tree = ElementTree.parse(stream) |     tree = ElementTree.parse(stream) | ||||||
|     el_root = tree.getroot() |     el_root = tree.getroot() | ||||||
| 
 | 
 | ||||||
| @ -21,7 +21,7 @@ def read(stream: TextIO) -> List[Map]: | |||||||
|     return maps |     return maps | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def read_wmaps(el_root: ElementTree.Element) -> List[Map]: | def read_wmaps(el_root: ElementTree.Element) -> list[Map]: | ||||||
|     map_fields = [ff.name for ff in fields(Map)] |     map_fields = [ff.name for ff in fields(Map)] | ||||||
|     maps = [] |     maps = [] | ||||||
|     for el_map in el_root: |     for el_map in el_root: | ||||||
| @ -41,7 +41,7 @@ def read_wmaps(el_root: ElementTree.Element) -> List[Map]: | |||||||
|     return maps |     return maps | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def read_devices(el_map: ElementTree.Element) -> List[Device]: | def read_devices(el_map: ElementTree.Element) -> list[Device]: | ||||||
|     dev_fields = [ff.name for ff in fields(Device)] |     dev_fields = [ff.name for ff in fields(Device)] | ||||||
|     devices = [] |     devices = [] | ||||||
|     for el_device in el_map: |     for el_device in el_map: | ||||||
| @ -50,7 +50,7 @@ def read_devices(el_map: ElementTree.Element) -> List[Device]: | |||||||
|             continue |             continue | ||||||
| 
 | 
 | ||||||
|         bin_type = el_device.attrib['BinType'] |         bin_type = el_device.attrib['BinType'] | ||||||
|         null_bin: Union[int, str] |         null_bin: int | str | ||||||
|         if bin_type == 'Decimal': |         if bin_type == 'Decimal': | ||||||
|             null_bin = int(el_device.attrib['NullBin']) |             null_bin = int(el_device.attrib['NullBin']) | ||||||
|         else: |         else: | ||||||
| @ -58,22 +58,24 @@ def read_devices(el_map: ElementTree.Element) -> List[Device]: | |||||||
| 
 | 
 | ||||||
|         device = Device(BinType=bin_type, NullBin=null_bin) |         device = Device(BinType=bin_type, NullBin=null_bin) | ||||||
| 
 | 
 | ||||||
|         val: Any |  | ||||||
|         for key, val in el_device.attrib.items(): |         for key, val in el_device.attrib.items(): | ||||||
|             if key in ('BinType', 'NullBin'): |             if key in ('BinType', 'NullBin'): | ||||||
|                 continue |                 continue | ||||||
| 
 | 
 | ||||||
|  |             parsed_val: Any | ||||||
|             if key in ('WaferSize', 'DeviceSizeX', 'DeviceSizeY', 'Orientation'): |             if key in ('WaferSize', 'DeviceSizeX', 'DeviceSizeY', 'Orientation'): | ||||||
|                 val = float(val) |                 parsed_val = float(val) | ||||||
|             elif key in ('OriginLocation',): |             elif key in ('OriginLocation',): | ||||||
|                 val = int(val) |                 parsed_val = int(val) | ||||||
|             elif key == 'CreateDate': |             elif key == 'CreateDate': | ||||||
|                 val = datetime.datetime.strptime(val + '000', '%Y%m%d%H%M%S%f') |                 parsed_val = datetime.datetime.strptime(val + '000', '%Y%m%d%H%M%S%f') | ||||||
|  |             else: | ||||||
|  |                 parsed_val = val | ||||||
| 
 | 
 | ||||||
|             if key in dev_fields and key[0].isupper(): |             if key in dev_fields and key[0].isupper(): | ||||||
|                 setattr(device, key, val) |                 setattr(device, key, parsed_val) | ||||||
|             else: |             else: | ||||||
|                 device.misc[key] = val |                 device.misc[key] = parsed_val | ||||||
| 
 | 
 | ||||||
|         for el_entry in el_device: |         for el_entry in el_device: | ||||||
|             tag = _tag(el_entry) |             tag = _tag(el_entry) | ||||||
| @ -96,7 +98,12 @@ def read_devices(el_map: ElementTree.Element) -> List[Device]: | |||||||
|                                  f'with attributes {el_entry.attrib}') |                                  f'with attributes {el_entry.attrib}') | ||||||
|                     continue |                     continue | ||||||
| 
 | 
 | ||||||
|                 bin_code = attrib['BinCode'] |                 bin_code: int | str | ||||||
|  |                 if bin_type == 'Decimal': | ||||||
|  |                     bin_code = int(attrib['BinCode']) | ||||||
|  |                 else: | ||||||
|  |                     bin_code = attrib['BinCode'] | ||||||
|  | 
 | ||||||
|                 if bin_code in device.bin_pass: |                 if bin_code in device.bin_pass: | ||||||
|                     logger.error(f'Bin code {bin_code} was repeated; ignoring later entry!') |                     logger.error(f'Bin code {bin_code} was repeated; ignoring later entry!') | ||||||
|                     continue |                     continue | ||||||
| @ -104,17 +111,23 @@ def read_devices(el_map: ElementTree.Element) -> List[Device]: | |||||||
|                 device.bin_pass[bin_code] = attrib['BinQuality'].lower() == 'pass' |                 device.bin_pass[bin_code] = attrib['BinQuality'].lower() == 'pass' | ||||||
|             elif tag == 'Data': |             elif tag == 'Data': | ||||||
|                 data_strs = [read_row(rr) for rr in el_entry] |                 data_strs = [read_row(rr) for rr in el_entry] | ||||||
|                 data: Union[List[List[str]], List[List[int]]] |                 data: list[list[str]] | list[list[int]] | ||||||
|                 if device.BinType == 'Decimal': |                 if device.BinType == 'Decimal': | ||||||
|                     data = [[int(vv) for vv in rr] for rr in data_strs] |                     data = [[int(vv) for vv in rr] for rr in data_strs] | ||||||
|                 else: |                 else: | ||||||
|                     data = data_strs |                     data = data_strs | ||||||
|                 device.map = data |                 device.map = data | ||||||
|  |                 for key, value in attrib.items(): | ||||||
|  |                     device.data_misc[key] = value | ||||||
|  |             elif tag == 'SupplierData': | ||||||
|  |                 for key, value in attrib.items(): | ||||||
|  |                     device.supplier_data[key] = value | ||||||
|  | 
 | ||||||
|         devices.append(device) |         devices.append(device) | ||||||
|     return devices |     return devices | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def read_row(el_row: ElementTree.Element) -> List[str]: | def read_row(el_row: ElementTree.Element) -> list[str]: | ||||||
|     assert _tag(el_row) == 'Row' |     assert _tag(el_row) == 'Row' | ||||||
| 
 | 
 | ||||||
|     row_stripped = (el_row.text or '').strip() |     row_stripped = (el_row.text or '').strip() | ||||||
| @ -126,7 +139,7 @@ def read_row(el_row: ElementTree.Element) -> List[str]: | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _tag(element: ElementTree.Element) -> str: | def _tag(element: ElementTree.Element) -> str: | ||||||
|     ''' |     """ | ||||||
|     Get the element's tag, excluding any namespaces. |     Get the element's tag, excluding any namespaces. | ||||||
|     ''' |     """ | ||||||
|     return element.tag.split('}')[-1] |     return element.tag.split('}')[-1] | ||||||
|  | |||||||
							
								
								
									
										67
									
								
								g85/write.py
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								g85/write.py
									
									
									
									
									
								
							| @ -1,4 +1,5 @@ | |||||||
| from typing import Sequence, Tuple, List, TextIO, Union | from typing import TextIO, cast | ||||||
|  | from collections.abc import Sequence | ||||||
| import logging | import logging | ||||||
| import math | import math | ||||||
| from dataclasses import fields | from dataclasses import fields | ||||||
| @ -10,12 +11,15 @@ from .main import Map, Device | |||||||
| logger = logging.getLogger(__name__) | logger = logging.getLogger(__name__) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class G85Error(Exception): | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| # Hack to directly pass through <![CDATA[...]]> | # Hack to directly pass through <![CDATA[...]]> | ||||||
| def _escape_cdata(text): | def _escape_cdata(text: str) -> str: | ||||||
|     if text.startswith('<![CDATA[') and text.endswith(']]>'): |     if text.startswith('<![CDATA[') and text.endswith(']]>'): | ||||||
|         return text |         return text | ||||||
|     else: |     return _original_escape_cdata(text) | ||||||
|         return _original_escape_cdata(text) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| _original_escape_cdata = ElementTree._escape_cdata      # type: ignore | _original_escape_cdata = ElementTree._escape_cdata      # type: ignore | ||||||
| @ -41,8 +45,11 @@ def write_wmap(wmap: Map, el_root: ElementTree.Element) -> None: | |||||||
| 
 | 
 | ||||||
|     map_fields = [ff.name for ff in fields(wmap)] |     map_fields = [ff.name for ff in fields(wmap)] | ||||||
|     for field in map_fields: |     for field in map_fields: | ||||||
|         if field[0].isupper(): |         if field[0].isupper() or field == 'xmlns': | ||||||
|             el_map.set(field, getattr(wmap, field)) |             val = getattr(wmap, field) | ||||||
|  |             if val is None: | ||||||
|  |                 continue | ||||||
|  |             el_map.set(field, val) | ||||||
|     for key, value in wmap.misc.items(): |     for key, value in wmap.misc.items(): | ||||||
|         if key[0].isupper() and key in map_fields: |         if key[0].isupper() and key in map_fields: | ||||||
|             continue |             continue | ||||||
| @ -61,7 +68,7 @@ def write_devices(devices: Sequence[Device], el_map: ElementTree.Element) -> Non | |||||||
| 
 | 
 | ||||||
|         # Row data prep |         # Row data prep | ||||||
|         if device.map is None: |         if device.map is None: | ||||||
|             raise Exception(f'No _data for device pformat({device})') |             raise G85Error(f'No _data for device pformat({device})') | ||||||
| 
 | 
 | ||||||
|         is_decimal = device.BinType == 'Decimal' |         is_decimal = device.BinType == 'Decimal' | ||||||
|         row_texts, bin_length = prepare_data(device.map, decimal=is_decimal) |         row_texts, bin_length = prepare_data(device.map, decimal=is_decimal) | ||||||
| @ -81,8 +88,9 @@ def write_devices(devices: Sequence[Device], el_map: ElementTree.Element) -> Non | |||||||
|             el_bin.set('BinQuality', 'Pass' if passed else 'Fail') |             el_bin.set('BinQuality', 'Pass' if passed else 'Fail') | ||||||
|             el_bin.set('BinCount', str(bin_counts[bin_code])) |             el_bin.set('BinCount', str(bin_counts[bin_code])) | ||||||
| 
 | 
 | ||||||
|  |         el_data = ElementTree.SubElement(el_device, 'Data') | ||||||
|         for row_text in row_texts: |         for row_text in row_texts: | ||||||
|             el_row = ElementTree.SubElement(el_device, 'Row') |             el_row = ElementTree.SubElement(el_data, 'Row') | ||||||
|             el_row.text = f'<![CDATA[{row_text}]]>' |             el_row.text = f'<![CDATA[{row_text}]]>' | ||||||
| 
 | 
 | ||||||
|         # Device attribs |         # Device attribs | ||||||
| @ -90,6 +98,8 @@ def write_devices(devices: Sequence[Device], el_map: ElementTree.Element) -> Non | |||||||
|         for field in dev_fields: |         for field in dev_fields: | ||||||
|             if field[0].isupper(): |             if field[0].isupper(): | ||||||
|                 val = getattr(device, field) |                 val = getattr(device, field) | ||||||
|  |                 if val is None: | ||||||
|  |                     continue | ||||||
| 
 | 
 | ||||||
|                 if field in ('WaferSize', 'DeviceSizeX', 'DeviceSizeY', 'Orientation'): |                 if field in ('WaferSize', 'DeviceSizeX', 'DeviceSizeY', 'Orientation'): | ||||||
|                     val = f'{val:g}' |                     val = f'{val:g}' | ||||||
| @ -97,6 +107,8 @@ def write_devices(devices: Sequence[Device], el_map: ElementTree.Element) -> Non | |||||||
|                     val = f'{val:d}' |                     val = f'{val:d}' | ||||||
|                 elif field == 'CreateDate': |                 elif field == 'CreateDate': | ||||||
|                     val = val.strftime('%Y%m%d%H%M%S%f')[:-3] |                     val = val.strftime('%Y%m%d%H%M%S%f')[:-3] | ||||||
|  |                 elif field == 'NullBin' and device.BinType == 'Decimal': | ||||||
|  |                     val = f'{val:d}' | ||||||
| 
 | 
 | ||||||
|                 el_device.set(field, val) |                 el_device.set(field, val) | ||||||
| 
 | 
 | ||||||
| @ -105,27 +117,34 @@ def write_devices(devices: Sequence[Device], el_map: ElementTree.Element) -> Non | |||||||
|                 continue |                 continue | ||||||
|             el_device.set(key, value) |             el_device.set(key, value) | ||||||
| 
 | 
 | ||||||
|  |         for key, value in device.data_misc.items(): | ||||||
|  |             el_data.set(key, value) | ||||||
| 
 | 
 | ||||||
| def prepare_data(data: List[List[Union[str, int]]], decimal: bool) -> Tuple[List[str], int]: |         if device.supplier_data: | ||||||
|  |             el_suppdata = ElementTree.SubElement(el_device, 'SupplierData') | ||||||
|  |             for key, value in device.data_misc.items(): | ||||||
|  |                 el_suppdata.set(key, value) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def prepare_data(data: list[list[str]] | list[list[int]], decimal: bool) -> tuple[list[str], int]: | ||||||
|     is_char = isinstance(data[0][0], str) |     is_char = isinstance(data[0][0], str) | ||||||
| 
 | 
 | ||||||
|  |     row_texts = [] | ||||||
|     if is_char: |     if is_char: | ||||||
|  |         data = cast(list[list[str]], data) | ||||||
|         char_len = len(data[0][0]) |         char_len = len(data[0][0]) | ||||||
|     else: |         for srow in data: | ||||||
|  |             if char_len == 1: | ||||||
|  |                 row_text = ''.join(srow) | ||||||
|  |             else: | ||||||
|  |                 row_text = ' '.join(srow) + ' ' | ||||||
|  |             row_texts.append(row_text) | ||||||
|  |         return row_texts, char_len | ||||||
|  |     else:       # noqa: RET505 | ||||||
|  |         data = cast(list[list[int]], data) | ||||||
|         max_value = max(max(rr) for rr in data) |         max_value = max(max(rr) for rr in data) | ||||||
|         max_digits = math.ceil(math.log10(max_value)) |         max_digits = math.ceil(math.log10(max_value)) | ||||||
| 
 |         for irow in data: | ||||||
|     row_texts = [] |             row_text = ' '.join(str(vv).zfill(max_digits) for vv in irow) + ' ' | ||||||
|     for row in data: |             row_texts.append(row_text) | ||||||
|         if is_char and char_len == 1: |  | ||||||
|             row_text = ''.join(row) |  | ||||||
|         elif is_char: |  | ||||||
|             row_text = ' '.join(row) + ' ' |  | ||||||
|         else: |  | ||||||
|             row_text = ' '.join(str(vv).zfill(max_digits) for vv in row) + ' ' |  | ||||||
|         row_texts.append(row_text) |  | ||||||
| 
 |  | ||||||
|     if is_char: |  | ||||||
|         return row_texts, char_len |  | ||||||
|     else: |  | ||||||
|         return row_texts, max_digits |         return row_texts, max_digits | ||||||
|  | |||||||
							
								
								
									
										78
									
								
								pyproject.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								pyproject.toml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | |||||||
|  | [build-system] | ||||||
|  | requires = ["hatchling"] | ||||||
|  | build-backend = "hatchling.build" | ||||||
|  | 
 | ||||||
|  | [project] | ||||||
|  | name = "g85" | ||||||
|  | description = "G85 wafer map reader / writer" | ||||||
|  | readme = "README.md" | ||||||
|  | license = { file = "LICENSE.md" } | ||||||
|  | authors = [ | ||||||
|  |     { name="Jan Petykiewicz", email="jan@mpxd.net" }, | ||||||
|  |     ] | ||||||
|  | homepage = "https://mpxd.net/code/jan/g85" | ||||||
|  | repository = "https://mpxd.net/code/jan/g85" | ||||||
|  | keywords = [ | ||||||
|  |     "design", | ||||||
|  |     "CAD", | ||||||
|  |     "EDA", | ||||||
|  |     "electronics", | ||||||
|  |     "photonics", | ||||||
|  |     "IC", | ||||||
|  |     "mask", | ||||||
|  |     "wafer", | ||||||
|  |     "map", | ||||||
|  |     "G85", | ||||||
|  |     "wmap", | ||||||
|  |     ] | ||||||
|  | classifiers = [ | ||||||
|  |     "Programming Language :: Python :: 3", | ||||||
|  |     "Development Status :: 4 - Beta", | ||||||
|  |     "Intended Audience :: Developers", | ||||||
|  |     "Intended Audience :: Information Technology", | ||||||
|  |     "Intended Audience :: Manufacturing", | ||||||
|  |     "Intended Audience :: Science/Research", | ||||||
|  |     "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", | ||||||
|  |     "Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)", | ||||||
|  |     ] | ||||||
|  | requires-python = ">=3.10" | ||||||
|  | dynamic = ["version"] | ||||||
|  | dependencies = [ | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  | [tool.hatch.version] | ||||||
|  | path = "g85/__init__.py" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | [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 | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
							
								
								
									
										51
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								setup.py
									
									
									
									
									
								
							| @ -1,51 +0,0 @@ | |||||||
| #!/usr/bin/env python3 |  | ||||||
| 
 |  | ||||||
| from setuptools import setup, find_packages |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| with open('README.md', 'r') as f: |  | ||||||
|     long_description = f.read() |  | ||||||
| 
 |  | ||||||
| with open('g85/VERSION.py', 'rt') as f: |  | ||||||
|     version = f.readlines()[2].strip() |  | ||||||
| 
 |  | ||||||
| setup( |  | ||||||
|     name='g85', |  | ||||||
|     version=version, |  | ||||||
|     description='G85 wafer map reader / writer', |  | ||||||
|     long_description=long_description, |  | ||||||
|     long_description_content_type='text/markdown', |  | ||||||
|     author='Jan Petykiewicz', |  | ||||||
|     author_email='jan@mpxd.net', |  | ||||||
|     url='https://mpxd.net/code/jan/g85', |  | ||||||
|     packages=find_packages(), |  | ||||||
|     package_data={ |  | ||||||
|         'g85': ['py.typed'], |  | ||||||
|     }, |  | ||||||
|     install_requires=[ |  | ||||||
|         'numpy', |  | ||||||
|     ], |  | ||||||
|     classifiers=[ |  | ||||||
|         'Programming Language :: Python :: 3', |  | ||||||
|         'Development Status :: 4 - Beta', |  | ||||||
|         'Intended Audience :: Developers', |  | ||||||
|         'Intended Audience :: Information Technology', |  | ||||||
|         'Intended Audience :: Manufacturing', |  | ||||||
|         'Intended Audience :: Science/Research', |  | ||||||
|         'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', |  | ||||||
|         'Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)', |  | ||||||
|     ], |  | ||||||
|     keywords=[ |  | ||||||
|         'design', |  | ||||||
|         'CAD', |  | ||||||
|         'EDA', |  | ||||||
|         'electronics', |  | ||||||
|         'photonics', |  | ||||||
|         'IC', |  | ||||||
|         'mask', |  | ||||||
|         'wafer', |  | ||||||
|         'map', |  | ||||||
|         'G85', |  | ||||||
|         'wmap', |  | ||||||
|     ], |  | ||||||
|     ) |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user