* begin to add annotations to some extensions
* break_apart: use path operations
* do not follow pyembroidery imports
pull/3578/head
Kaalleen 2025-03-12 08:16:28 +01:00 zatwierdzone przez GitHub
rodzic e3ac18d643
commit 760c17b815
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
6 zmienionych plików z 48 dodań i 46 usunięć

Wyświetl plik

@ -9,6 +9,6 @@ from .base import InkstitchExtension
class About(InkstitchExtension):
def effect(self):
def effect(self) -> None:
app = AboutInkstitchApp()
app.MainLoop()

Wyświetl plik

@ -16,7 +16,7 @@ class ApplyPalette(InkstitchExtension):
Applies colors of a color palette to elements
'''
def effect(self):
def effect(self) -> None:
# Remove selection, we want all the elements in the document
self.svg.selection.clear()
@ -32,7 +32,7 @@ class ApplyPalette(InkstitchExtension):
if palette_choice.palette:
self.apply_palette(palette_choice.palette)
def apply_palette(self, palette_name):
def apply_palette(self, palette_name: str) -> None:
palette = ThreadCatalog().get_palette_by_name(palette_name)
# Iterate through the color blocks to apply colors

Wyświetl plik

@ -6,6 +6,7 @@
import os
import re
import sys
from typing import List, Optional
import inkex
@ -31,7 +32,7 @@ class ApplyThreadlist(InkstitchExtension):
self.arg_parser.add_argument("-m", "--method", type=int, default=1, dest="method")
self.arg_parser.add_argument("-t", "--palette", type=str, default=None, dest="palette")
def effect(self):
def effect(self) -> None:
# Remove selection, we want all the elements in the document
self.svg.selection.clear()
@ -72,7 +73,7 @@ class ApplyThreadlist(InkstitchExtension):
if colors[i][1] is not None:
element.node.set(INKSTITCH_ATTRIBS['cutwork_needle'], colors[i][1])
def verify_path(self, path):
def verify_path(self, path: str) -> None:
if not os.path.exists(path):
inkex.errormsg(_("File not found."))
sys.exit(1)
@ -80,7 +81,7 @@ class ApplyThreadlist(InkstitchExtension):
inkex.errormsg(_("The filepath specified is not a file but a dictionary.\nPlease choose a threadlist file to import."))
sys.exit(1)
def verify_colors(self, colors, method):
def verify_colors(self, colors: List[List[Optional[str]]], method: int) -> None:
if all(c is None for c in colors):
inkex.errormsg(_("Couldn't find any matching colors in the file."))
if method == 1:
@ -89,7 +90,7 @@ class ApplyThreadlist(InkstitchExtension):
inkex.errormsg(_("Please chose an other color palette for your design."))
sys.exit(1)
def parse_inkstitch_threadlist(self, path):
def parse_inkstitch_threadlist(self, path: str) -> List[List[Optional[str]]]:
colors = []
with open(path) as threadlist:
for line in threadlist:
@ -102,7 +103,7 @@ class ApplyThreadlist(InkstitchExtension):
colors.append([None, None])
return colors
def parse_color_format(self, path):
def parse_color_format(self, path: str) -> List[List[Optional[str]]]:
colors = []
threads = pyembroidery.read(path).threadlist
for color in threads:
@ -113,7 +114,7 @@ class ApplyThreadlist(InkstitchExtension):
colors.append([color.hex_color(), None])
return colors
def parse_threadlist_by_catalog_number(self, path):
def parse_threadlist_by_catalog_number(self, path: str) -> List[List[Optional[str]]]:
palette_name = self.options.palette
palette = ThreadCatalog().get_palette_by_name(palette_name)

Wyświetl plik

@ -3,7 +3,9 @@
# Copyright (c) 2010 Authors
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
import inkex
from typing import Any, List, Optional, Union
from inkex import Boolean, Vector2d, errormsg
from ..elements import Stroke
from ..i18n import _
@ -17,12 +19,12 @@ class AutoRun(CommandsExtension):
def __init__(self, *args, **kwargs):
CommandsExtension.__init__(self, *args, **kwargs)
self.arg_parser.add_argument("-b", "--break_up", dest="break_up", type=inkex.Boolean, default=True)
self.arg_parser.add_argument("-p", "--preserve_order", dest="preserve_order", type=inkex.Boolean, default=False)
self.arg_parser.add_argument("-b", "--break_up", dest="break_up", type=Boolean, default=True)
self.arg_parser.add_argument("-p", "--preserve_order", dest="preserve_order", type=Boolean, default=False)
self.arg_parser.add_argument("-o", "--options", dest="options", type=str, default="")
self.arg_parser.add_argument("-i", "--info", dest="help", type=str, default="")
def effect(self):
def effect(self) -> None:
elements = self.check_selection()
if not elements:
return
@ -34,32 +36,29 @@ class AutoRun(CommandsExtension):
autorun(elements, self.options.preserve_order, break_up, starting_point, ending_point, self.options.trim)
def get_starting_point(self):
def get_starting_point(self) -> Optional[Vector2d]:
return self.get_command_point("autoroute_start")
def get_ending_point(self):
def get_ending_point(self) -> Optional[Vector2d]:
return self.get_command_point("autoroute_end")
def get_command_point(self, command_type):
def get_command_point(self, command_type: str) -> Optional[Vector2d]:
command = None
for stroke in self.elements:
command = stroke.get_command(command_type)
# return the first occurence directly
if command:
return command.target_point
return None
def check_selection(self):
if not self.get_elements():
return
def check_selection(self) -> List[Union[Stroke, Any]]:
if not self.svg.selection:
# L10N auto-route running stitch columns extension
inkex.errormsg(_("Please select one or more stroke elements."))
return False
errormsg(_("Please select one or more stroke elements."))
self.get_elements()
elements = [element for element in self.elements if isinstance(element, Stroke)]
if len(elements) == 0:
inkex.errormsg(_("Please select at least one stroke element."))
return False
errormsg(_("Please select at least one stroke element."))
return elements

Wyświetl plik

@ -4,8 +4,9 @@
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
from copy import copy
from typing import List, Tuple, Union
import inkex
from inkex import Path, errormsg
from shapely.geometry import LinearRing, MultiPolygon, Polygon
from shapely.ops import polygonize, unary_union
@ -26,9 +27,9 @@ class BreakApart(InkstitchExtension):
self.arg_parser.add_argument("-m", "--method", type=int, default=1, dest="method")
self.minimum_size = 5
def effect(self): # noqa: C901
def effect(self) -> None: # noqa: C901
if not self.svg.selection:
inkex.errormsg(_("Please select one or more fill areas to break apart."))
errormsg(_("Please select one or more fill areas to break apart."))
return
elements = []
@ -58,29 +59,29 @@ class BreakApart(InkstitchExtension):
if polygons:
self.polygons_to_nodes(polygons, element)
def break_apart_paths(self, paths):
def break_apart_paths(self, paths: List[List[Union[List[float], Tuple[float, float]]]]) -> List[Polygon]:
polygons = []
for path in paths:
if len(path) < 3:
continue
linearring = LinearRing(path)
if not linearring.is_simple:
linearring = unary_union(linearring)
for polygon in polygonize(linearring):
union = unary_union(linearring)
for polygon in polygonize(union):
polygons.append(polygon)
else:
polygon = Polygon(path).buffer(0)
polygons.append(polygon)
return polygons
def combine_overlapping_polygons(self, polygons):
def combine_overlapping_polygons(self, polygons: List[Polygon]) -> List[Polygon]:
for polygon in polygons:
for other in polygons:
if polygon == other:
continue
if polygon.overlaps(other):
diff = polygon.symmetric_difference(other)
if diff.geom_type == 'MultiPolygon':
if isinstance(diff, MultiPolygon):
polygons.remove(other)
polygons.remove(polygon)
for p in diff.geoms:
@ -91,17 +92,17 @@ class BreakApart(InkstitchExtension):
return polygons
return polygons
def geom_is_valid(self, geom):
def geom_is_valid(self, geom: MultiPolygon) -> bool:
valid = geom.is_valid
return valid
def ensure_minimum_size(self, polygons, size):
def ensure_minimum_size(self, polygons: List[Polygon], size: int) -> List[Polygon]:
for polygon in polygons:
if polygon.area < size:
polygons.remove(polygon)
return polygons
def recombine_polygons(self, polygons):
def recombine_polygons(self, polygons: List[Polygon]) -> List[List[Polygon]]:
polygons.sort(key=lambda polygon: polygon.area, reverse=True)
multipolygons = []
holes = []
@ -126,10 +127,12 @@ class BreakApart(InkstitchExtension):
multipolygons.append(polygon_list)
return multipolygons
def polygons_to_nodes(self, polygon_list, element):
def polygons_to_nodes(self, polygon_list: List[List[Polygon]], element: EmbroideryElement) -> None:
# reverse the list of polygons, we don't want to cover smaller shapes
polygon_list = polygon_list[::-1]
index = element.node.getparent().index(element.node)
parent = element.node.getparent()
assert parent is not None, "The element should be part of a group."
index = parent.index(element.node)
for polygons in polygon_list:
if polygons[0].area < 5:
continue
@ -148,14 +151,12 @@ class BreakApart(InkstitchExtension):
el.set('id', node_id)
# Set path
d = ""
d = Path()
for polygon in polygons:
d += "M"
for x, y in polygon.exterior.coords:
d += "%s,%s " % (x, y)
d += " "
d += "Z"
el.set('d', d)
path = Path(polygon.exterior.coords)
path.close()
d += path
el.set('d', str(d))
el.set('transform', get_correction_transform(element.node))
element.node.getparent().insert(index, el)
element.node.getparent().remove(element.node)
parent.insert(index, el)
parent.remove(element.node)

Wyświetl plik

@ -38,3 +38,4 @@ ignore_missing_imports = True
# ... And this one is ours but is missing type information for now anyway...
[mypy-pyembroidery.*]
ignore_missing_imports = True
follow_imports = skip