summaryrefslogtreecommitdiff
path: root/gerbonara
diff options
context:
space:
mode:
Diffstat (limited to 'gerbonara')
-rw-r--r--gerbonara/apertures.py32
-rw-r--r--gerbonara/graphic_objects.py10
-rw-r--r--gerbonara/graphic_primitives.py16
-rw-r--r--gerbonara/ipc356.py5
4 files changed, 43 insertions, 20 deletions
diff --git a/gerbonara/apertures.py b/gerbonara/apertures.py
index 33b78df..0a4bf37 100644
--- a/gerbonara/apertures.py
+++ b/gerbonara/apertures.py
@@ -17,7 +17,7 @@
#
import math
-from dataclasses import dataclass, replace, field, fields, InitVar, KW_ONLY
+from dataclasses import dataclass, replace, field, fields, InitVar
from .aperture_macros.parse import GenericMacros
from .utils import MM, Inch
@@ -60,16 +60,26 @@ class Length:
@dataclass
class Aperture:
""" Base class for all apertures. """
- _ : KW_ONLY
- #: :py:class:`gerbonara.utils.LengthUnit` used for all length fields of this aperture.
- unit : str = None
- #: GerberX2 attributes of this aperture. Note that this will only contain aperture attributes, not file attributes.
- #: File attributes are stored in the :py:attr:`~.GerberFile.attrs` of the :py:class:`.GerberFile`.
- attrs : dict = field(default_factory=dict)
- #: Aperture index this aperture had when it was read from the Gerber file. This field is purely informational since
- #: apertures are de-duplicated and re-numbered when writing a Gerber file. For `D10`, this field would be `10`. When
- #: you programmatically create a new aperture, you do not have to set this.
- original_number : int = None
+
+ # hackety hack: Work around python < 3.10 not having dataclasses.KW_ONLY.
+ #
+ # For details, refer to graphic_objects.py
+ def __init_subclass__(cls):
+ #: :py:class:`gerbonara.utils.LengthUnit` used for all length fields of this aperture.
+ cls.unit = None
+ #: GerberX2 attributes of this aperture. Note that this will only contain aperture attributes, not file attributes.
+ #: File attributes are stored in the :py:attr:`~.GerberFile.attrs` of the :py:class:`.GerberFile`.
+ cls.attrs = field(default_factory=dict)
+ #: Aperture index this aperture had when it was read from the Gerber file. This field is purely informational since
+ #: apertures are de-duplicated and re-numbered when writing a Gerber file. For `D10`, this field would be `10`. When
+ #: you programmatically create a new aperture, you do not have to set this.
+ cls.original_number = None
+
+ d = {'unit': str, 'attrs': dict, 'original_number': int}
+ if hasattr(cls, '__annotations__'):
+ cls.__annotations__.update(d)
+ else:
+ cls.__annotations__ = d
@property
def hole_shape(self):
diff --git a/gerbonara/graphic_objects.py b/gerbonara/graphic_objects.py
index 3136b39..35c08f3 100644
--- a/gerbonara/graphic_objects.py
+++ b/gerbonara/graphic_objects.py
@@ -18,7 +18,7 @@
import math
import copy
-from dataclasses import dataclass, KW_ONLY, astuple, replace, field, fields
+from dataclasses import dataclass, astuple, replace, field, fields
from .utils import MM, InterpMode, to_unit, rotate_point
from . import graphic_primitives as gp
@@ -45,6 +45,8 @@ class GraphicObject:
# hackety hack: Work around python < 3.10 not having dataclasses.KW_ONLY. Once we drop python 3.8 and 3.9, we can
# get rid of this, just set these as normal fields, and decorate GraphicObject with @dataclass.
+ #
+ # See also: apertures.py, graphic_primitives.py
def __init_subclass__(cls):
#: bool representing the *color* of this feature: whether this is a *dark* or *clear* feature. Clear and dark are
#: meant in the sense that they are used in the Gerber spec and refer to whether the transparency film that this
@@ -61,7 +63,11 @@ class GraphicObject:
#: which are stored in the :py:class:`.GerberFile` object instead.
cls.attrs = field(default_factory=dict)
- cls.__annotations__.update({'polarity_dark' : bool, 'unit' : str, 'attrs': dict})
+ d = {'polarity_dark' : bool, 'unit' : str, 'attrs': dict}
+ if hasattr(cls, '__annotations__'):
+ cls.__annotations__.update(d)
+ else:
+ cls.__annotations__ = d
def converted(self, unit):
diff --git a/gerbonara/graphic_primitives.py b/gerbonara/graphic_primitives.py
index dd421a7..072a98a 100644
--- a/gerbonara/graphic_primitives.py
+++ b/gerbonara/graphic_primitives.py
@@ -19,7 +19,7 @@
import math
import itertools
-from dataclasses import dataclass, KW_ONLY, replace
+from dataclasses import dataclass, replace
from .utils import *
@@ -28,8 +28,18 @@ prec = lambda x: f'{float(x):.6}'
@dataclass
class GraphicPrimitive:
- _ : KW_ONLY
- polarity_dark : bool = True
+
+ # hackety hack: Work around python < 3.10 not having dataclasses.KW_ONLY.
+ #
+ # For details, refer to graphic_objects.py
+ def __init_subclass__(cls):
+ cls.polarity_dark = True
+
+ d = {'polarity_dark': bool}
+ if hasattr(cls, '__annotations__'):
+ cls.__annotations__.update(d)
+ else:
+ cls.__annotations__ = d
def bounding_box(self):
""" Return the axis-aligned bounding box of this feature.
diff --git a/gerbonara/ipc356.py b/gerbonara/ipc356.py
index 06a87f0..435a805 100644
--- a/gerbonara/ipc356.py
+++ b/gerbonara/ipc356.py
@@ -23,7 +23,7 @@ import math
import re
from enum import Enum
import warnings
-from dataclasses import dataclass, KW_ONLY
+from dataclasses import dataclass
from pathlib import Path
from .cam import CamFile, FileSettings
@@ -414,7 +414,6 @@ class TestRecord:
rotation : float = 0
solder_mask : SoldermaskInfo = None
lefover : str = None
- _ : KW_ONLY
unit : LengthUnit = None
def __str__(self):
@@ -563,7 +562,6 @@ def format_coord_chain(line, settings, coords, cont, unit):
class Outline:
outline_type : OutlineType
outline : [(float,)]
- _ : KW_ONLY
unit : LengthUnit = None
@classmethod
@@ -596,7 +594,6 @@ class Conductor:
layer : int
aperture : (float,)
coords : [(float,)]
- _ : KW_ONLY
unit : LengthUnit = None
@classmethod