Skip to content

Commit 6b59f1b

Browse files
authoredJan 26, 2025··
add mypy workflow (#41)
* add `mypy` workflow * fix mypy errors
1 parent 4b254f5 commit 6b59f1b

File tree

4 files changed

+71
-33
lines changed

4 files changed

+71
-33
lines changed
 

‎.github/workflows/mypy.yaml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: mypy
2+
3+
on:
4+
- push
5+
- pull_request
6+
7+
jobs:
8+
mypy:
9+
strategy:
10+
fail-fast: false
11+
matrix:
12+
python-version:
13+
- "3.10"
14+
- "3.12"
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v3
18+
- name: Set up Python ${{ matrix.python-version }}
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: ${{ matrix.python-version }}
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install mypy
26+
pip install .
27+
- name: Typecheck with mypy
28+
run: |
29+
mypy --ignore-missing-imports ocpsvg

‎ocpsvg/hlr.py

+10-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
Mapping,
1313
Optional,
1414
Sequence,
15+
TypeAlias,
1516
Union,
1617
)
1718
from xml.etree import ElementTree as ET
@@ -38,16 +39,16 @@
3839
}
3940

4041

41-
Padding = Union[
42+
Padding: TypeAlias = Union[
4243
float,
4344
tuple[float],
4445
tuple[float, float],
4546
tuple[float, float, float],
4647
tuple[float, float, float, float],
4748
]
48-
CssStyle = Mapping[str, Mapping[str, Any]]
49-
RGB = tuple[float, float, float]
50-
EdgeColor = Union[RGB, tuple[RGB, RGB]]
49+
CssStyle: TypeAlias = Mapping[str, Mapping[str, Any]]
50+
RGB: TypeAlias = tuple[float, float, float]
51+
EdgeColor: TypeAlias = Union[RGB, tuple[RGB, RGB]]
5152

5253

5354
PRIMARY_EDGES = "sharp", "outline"
@@ -253,12 +254,12 @@ def basic_style(
253254
) -> CssStyle:
254255
if secondary_linewidth is None:
255256
secondary_linewidth = linewidth * 0.75
256-
color, hidden_color = _edge_color_pair(color)
257+
visible_color, hidden_color = _edge_color_pair(color)
257258

258-
style = {
259+
style: dict[str, dict[str, Union[str, float]]] = {
259260
"path": {
260261
"fill": "none",
261-
"stroke": hexcolor(color),
262+
"stroke": hexcolor(visible_color),
262263
"stroke-width": linewidth,
263264
"stroke-linecap": "round",
264265
"stroke-linejoin": "round",
@@ -278,8 +279,8 @@ def basic_style(
278279

279280
if shape_colors:
280281
for i, color in shape_colors.items():
281-
color, hidden_color = _edge_color_pair(color)
282-
style[f".s{i}"] = {"stroke": hexcolor(color)}
282+
visible_color, hidden_color = _edge_color_pair(color)
283+
style[f".s{i}"] = {"stroke": hexcolor(visible_color)}
283284
style[f".s{i}.hidden"] = {"stroke": hexcolor(hidden_color)}
284285

285286
return style

‎ocpsvg/ocp.py

+2
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ def circle_curve(
326326
) -> Union[Geom_Circle, Geom_TrimmedCurve]:
327327
circle_gp = gp_Circ(gp_Ax2(gp_Pnt(), normal), radius)
328328

329+
circle: Union[Geom_Circle, Geom_TrimmedCurve] # for mypy
329330
if start_angle == end_angle:
330331
circle = GC_MakeCircle(circle_gp).Value()
331332
else:
@@ -360,6 +361,7 @@ def ellipse_curve(
360361
ellipse_gp = gp_Elips(gp_Ax2(gp_Pnt(), normal), major_radius, minor_radius)
361362
ellipse_gp.Rotate(gp_Ax1(), radians(angle_adjustment))
362363

364+
ellipse: Union[Geom_Ellipse, Geom_TrimmedCurve] # for mypy
363365
if start_angle == end_angle:
364366
ellipse = GC_MakeEllipse(ellipse_gp).Value()
365367
else:

‎ocpsvg/svg.py

+30-24
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
Optional,
1414
Sequence,
1515
TextIO,
16+
TypeAlias,
1617
TypeVar,
1718
Union,
1819
overload,
@@ -109,11 +110,11 @@ def format_svg(path: Iterable[SvgPathCommand], float_format: str = "f") -> str:
109110
)
110111

111112

112-
SvgPathLike = Union[str, Iterable[SvgPathCommand], svgelements.Path]
113-
ShapeElement = svgelements.Shape
114-
ParentElement = Union[svgelements.Group, svgelements.Use]
113+
SvgPathLike: TypeAlias = Union[str, Iterable[SvgPathCommand], svgelements.Path]
114+
ShapeElement: TypeAlias = svgelements.Shape
115+
ParentElement: TypeAlias = Union[svgelements.Group, svgelements.Use]
115116

116-
FaceOrWire = Union[TopoDS_Wire, TopoDS_Face]
117+
FaceOrWire: TypeAlias = Union[TopoDS_Wire, TopoDS_Face]
117118

118119

119120
class DocumentInfo(NamedTuple):
@@ -220,31 +221,31 @@ def process_wire(
220221
yield from wires
221222

222223
if metadata:
223-
wires_from_doc = wires_from_svg_document(
224+
wires_from_doc_with_metadata = wires_from_svg_document(
224225
svg_file,
225226
ignore_visibility=ignore_visibility,
226227
metadata_factory=metadata,
227228
)
228-
transform = doc_transform(wires_from_doc.doc_info)
229+
transform = doc_transform(wires_from_doc_with_metadata.doc_info)
229230
items = (
230-
(transform(face_or_wire), m)
231-
for wires, is_filled, m in wires_from_doc
231+
(transform(face_or_wire), metadata)
232+
for wires, is_filled, metadata in wires_from_doc_with_metadata
232233
for face_or_wire in process_wire(wires, is_filled)
233234
)
234-
return ItemsFromDocument(items, wires_from_doc.doc_info)
235+
return ItemsFromDocument(items, wires_from_doc_with_metadata.doc_info)
235236
else:
236-
wires_from_doc = wires_from_svg_document(
237+
wires_from_doc_without_metadata = wires_from_svg_document(
237238
svg_file,
238239
ignore_visibility=ignore_visibility,
239240
metadata_factory=None,
240241
)
241-
transform = doc_transform(wires_from_doc.doc_info)
242+
transform = doc_transform(wires_from_doc_without_metadata.doc_info)
242243
items = (
243244
transform(face_or_wire)
244-
for wires, is_filled, _metadata in wires_from_doc
245+
for wires, is_filled, _metadata in wires_from_doc_without_metadata
245246
for face_or_wire in process_wire(wires, is_filled)
246247
)
247-
return ItemsFromDocument(items, wires_from_doc.doc_info)
248+
return ItemsFromDocument(items, wires_from_doc_without_metadata.doc_info)
248249

249250

250251
class ColorAndLabel:
@@ -274,6 +275,8 @@ def _color(
274275
return tuple(float(v) / 255 for v in rgba) # type: ignore
275276
except TypeError:
276277
return 0, 0, 0, 1
278+
else:
279+
return None
277280

278281
@staticmethod
279282
def _label(element: Union[ShapeElement, ParentElement], label_by: str):
@@ -312,6 +315,8 @@ def check_unskewed_transform() -> Union[tuple[float, float, float], None]:
312315
is_skewed = abs(o.angle_to(y) - o.angle_to(x)) != pi / 2 # type: ignore
313316
if not is_skewed:
314317
return o.distance_to(x), o.distance_to(y), o.angle_to(x) # type: ignore
318+
else:
319+
return None
315320

316321
element.reify()
317322

@@ -325,11 +330,12 @@ def check_unskewed_transform() -> Union[tuple[float, float, float], None]:
325330
scale_x, scale_y, angle = scale_and_angle
326331
r1 = float(element.rx) * scale_x # type: ignore
327332
r2 = float(element.ry) * scale_y # type: ignore
328-
if r1 == r2:
329-
curve = circle_curve(r1, center=center)
330-
else:
331-
curve = ellipse_curve(r1, r2, center=center, rotation=degrees(angle))
332-
yield wire_from_continuous_edges((edge_from_curve(curve),))
333+
circle_or_ellpise = (
334+
circle_curve(r1, center=center)
335+
if r1 == r2
336+
else ellipse_curve(r1, r2, center=center, rotation=degrees(angle))
337+
)
338+
yield wire_from_continuous_edges((edge_from_curve(circle_or_ellpise),))
333339

334340
elif path := svg_element_to_path(element):
335341
yield from wires_from_svg_path(path)
@@ -503,7 +509,7 @@ def wire_to_svg_path(
503509
# but wires can be non-manifold or otherwise degenerate and may not have visit them all.
504510
# We'll add remaining edges individually
505511

506-
#TODO use a set if/when OCP implements `__eq__`
512+
# TODO use a set if/when OCP implements `__eq__`
507513
all_edges = {hash(e): e for e in map(TopoDS.Edge_s, topoDS_iterator(wire))}
508514

509515
if len(ordered_edges) < len(all_edges):
@@ -777,25 +783,25 @@ def is_filled(element: ShapeElement):
777783
return fill.value is not None # type: ignore
778784

779785
if callable(metadata_factory):
780-
wires = (
786+
wires_with_metadata = (
781787
(
782788
list(wires_from_svg_element(source_element)),
783789
is_filled(source_element),
784790
metadata_factory(source_element, source_parents),
785791
)
786792
for source_element, source_parents in elements
787793
)
788-
return ItemsFromDocument(wires, elements.doc_info)
794+
return ItemsFromDocument(wires_with_metadata, elements.doc_info)
789795
else:
790-
wires = (
796+
wires_without_metadata = (
791797
(
792798
list(wires_from_svg_element(source_element)),
793799
is_filled(source_element),
794800
None,
795801
)
796802
for source_element, _source_parents in elements
797803
)
798-
return ItemsFromDocument(wires, elements.doc_info)
804+
return ItemsFromDocument(wires_without_metadata, elements.doc_info)
799805

800806

801807
def find_shapes_svg_in_document(
@@ -806,7 +812,7 @@ def find_shapes_svg_in_document(
806812
def walk_svg_element(
807813
element: svgelements.SVGElement, parents: tuple[ParentElement, ...] = ()
808814
) -> Iterator[tuple[ShapeElement, tuple[ParentElement, ...]]]:
809-
if isinstance(element, ShapeElement):
815+
if isinstance(element, svgelements.Shape):
810816
yield element, parents
811817
elif isinstance(element, (svgelements.Group, svgelements.Use)):
812818
new_parents = *parents, element

0 commit comments

Comments
 (0)
Please sign in to comment.