From 731ac2868e30dbccf5771abf79564d8bab1156c2 Mon Sep 17 00:00:00 2001 From: Kaalleen <36401965+kaalleen@users.noreply.github.com> Date: Sun, 27 Jul 2025 07:28:20 +0200 Subject: [PATCH] rename pyembroidery to pystitch (#3889) ... and remove it as a submodule (use pip to install) --- .gitmodules | 3 --- Makefile | 6 ++--- bin/pyembroidery-convert | 6 ----- bin/pyembroidery-gettext | 10 -------- bin/pystitch-convert | 6 +++++ bin/pystitch-gettext | 10 ++++++++ bin/style-check | 2 +- lib/extensions/apply_threadlist.py | 4 ++-- lib/extensions/batch_lettering.py | 4 ++-- lib/extensions/zip.py | 4 ++-- lib/inx/extensions.py | 12 +++++----- lib/inx/inputs.py | 8 +++---- lib/inx/outputs.py | 8 +++---- lib/output.py | 32 ++++++++++++------------- lib/stitch_plan/generate_stitch_plan.py | 12 +++++----- lib/stitch_plan/read_file.py | 8 +++---- lib/threads/color.py | 4 ++-- mypy.ini | 5 +++- pyembroidery | 1 - requirements.txt | 5 +--- 20 files changed, 73 insertions(+), 77 deletions(-) delete mode 100644 .gitmodules delete mode 100755 bin/pyembroidery-convert delete mode 100755 bin/pyembroidery-gettext create mode 100755 bin/pystitch-convert create mode 100755 bin/pystitch-gettext delete mode 160000 pyembroidery diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5edeeae78..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "pyembroidery"] - path = pyembroidery - url = https://github.com/inkstitch/pyembroidery diff --git a/Makefile b/Makefile index b5d4dfbed..4cf939c8a 100644 --- a/Makefile +++ b/Makefile @@ -23,14 +23,14 @@ messages.po: inx xgettext inx/*.inx --its=its/inx.its -o messages-inx.po # There seems to be no proper way to set the charset to utf-8 sed -i 's/charset=CHARSET/charset=UTF-8/g' messages-inx.po - bin/pyembroidery-gettext > pyembroidery-format-descriptions.py + bin/pystitch-gettext > pystitch-format-descriptions.py bin/inkstitch-fonts-gettext > inkstitch-fonts-metadata.py bin/inkstitch-tiles-gettext > inkstitch-tiles-metadata.py # After the inx files are finished building, we don't need the src/ folder anymore. # We don't want babel to grab possible translation strings from that folder, so let's remove it rm -rf src/ pybabel extract -o messages-babel.po -F babel.conf --add-location=full --add-comments=l10n,L10n,L10N --sort-by-file --strip-comments -k N_ -k '$$gettext' . - rm pyembroidery-format-descriptions.py inkstitch-fonts-metadata.py inkstitch-tiles-metadata.py + rm pystitch-format-descriptions.py inkstitch-fonts-metadata.py inkstitch-tiles-metadata.py msgcat -o messages.po messages-babel.po messages-inx.po %.po: %.mo @@ -38,7 +38,7 @@ messages.po: inx .PHONY: clean clean: - rm -f messages.po pyembroidery-format-descriptions.py + rm -f messages.po pystitch-format-descriptions.py .PHONY: locales locales: diff --git a/bin/pyembroidery-convert b/bin/pyembroidery-convert deleted file mode 100755 index ac58e3e57..000000000 --- a/bin/pyembroidery-convert +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python - -import sys -import pyembroidery - -pyembroidery.convert(sys.argv[1], sys.argv[2]) diff --git a/bin/pyembroidery-gettext b/bin/pyembroidery-gettext deleted file mode 100755 index f4e844b95..000000000 --- a/bin/pyembroidery-gettext +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python - -import pyembroidery - - -# generate fake python code containing the descriptions of pyembroidery formats -# as gettext calls so that pybabel will extract them into messages.po -for format in pyembroidery.supported_formats(): - print("# L10N description for pyembroidery file format: %s" % format['extension']) - print("_(%s)" % repr(format['description'])) diff --git a/bin/pystitch-convert b/bin/pystitch-convert new file mode 100755 index 000000000..92e814a26 --- /dev/null +++ b/bin/pystitch-convert @@ -0,0 +1,6 @@ +#!/usr/bin/env python + +import sys +import pystitch + +pystitch.convert(sys.argv[1], sys.argv[2]) diff --git a/bin/pystitch-gettext b/bin/pystitch-gettext new file mode 100755 index 000000000..068715274 --- /dev/null +++ b/bin/pystitch-gettext @@ -0,0 +1,10 @@ +#!/usr/bin/env python + +import pystitch + + +# generate fake python code containing the descriptions of pystitch formats +# as gettext calls so that pybabel will extract them into messages.po +for format in pystitch.supported_formats(): + print("# L10N description for pystitch file format: %s" % format['extension']) + print("_(%s)" % repr(format['description'])) diff --git a/bin/style-check b/bin/style-check index bdac3a76c..fa4cc7455 100755 --- a/bin/style-check +++ b/bin/style-check @@ -5,4 +5,4 @@ # Instead of files, "--diff" may be passed to check only the lines changed # by a diff piped to standard input. -flake8 --count --max-complexity=10 --max-line-length=150 --statistics --exclude=pyembroidery,__init__.py,build,src,dist,./*-metadata.py,./pyembroidery-format-descriptions.py "${@:-.}" +flake8 --count --max-complexity=10 --max-line-length=150 --statistics --exclude=__init__.py,build,src,dist,./*-metadata.py,./pystitch-format-descriptions.py "${@:-.}" diff --git a/lib/extensions/apply_threadlist.py b/lib/extensions/apply_threadlist.py index 5b831ff59..d01bd8e2f 100644 --- a/lib/extensions/apply_threadlist.py +++ b/lib/extensions/apply_threadlist.py @@ -10,7 +10,7 @@ from typing import List, Optional import inkex -import pyembroidery +import pystitch from ..i18n import _ from ..svg.tags import INKSTITCH_ATTRIBS @@ -105,7 +105,7 @@ class ApplyThreadlist(InkstitchExtension): def parse_color_format(self, path: str) -> List[List[Optional[str]]]: colors = [] - threads = pyembroidery.read(path).threadlist + threads = pystitch.read(path).threadlist for color in threads: if color.description is not None and color.description.startswith("Cut"): # there is a maximum of 4 needles, we can simply take the last element from the description string diff --git a/lib/extensions/batch_lettering.py b/lib/extensions/batch_lettering.py index 70beaaf7c..c0581e76d 100644 --- a/lib/extensions/batch_lettering.py +++ b/lib/extensions/batch_lettering.py @@ -14,7 +14,7 @@ from zipfile import ZipFile from inkex import Boolean, Group, errormsg from lxml import etree -import pyembroidery +import pystitch from ..extensions.lettering_along_path import TextAlongPath from ..i18n import _ @@ -69,7 +69,7 @@ class BatchLettering(InkstitchExtension): if not self.options.formats: errormsg(_("Please specify at least one output file format")) return - available_formats = [file_format['extension'] for file_format in pyembroidery.supported_formats()] + ['svg'] + available_formats = [file_format['extension'] for file_format in pystitch.supported_formats()] + ['svg'] file_formats = self.options.formats.split(',') file_formats = [file_format.strip().lower() for file_format in file_formats if file_format.strip().lower() in available_formats] if not file_formats: diff --git a/lib/extensions/zip.py b/lib/extensions/zip.py index 13cae7bdc..2cee5f048 100644 --- a/lib/extensions/zip.py +++ b/lib/extensions/zip.py @@ -13,7 +13,7 @@ from inkex import Boolean, errormsg from inkex.units import convert_unit from lxml import etree -import pyembroidery +import pystitch from ..i18n import _ from ..output import write_embroidery_file @@ -35,7 +35,7 @@ class Zip(InkstitchExtension): # it's kind of obnoxious that I have to do this... self.formats = [] - for format in pyembroidery.supported_formats(): + for format in pystitch.supported_formats(): if 'writer' in format and format['category'] in ['embroidery', 'color', 'image', 'stitch', 'quilting']: extension = format['extension'] self.arg_parser.add_argument('--format-%s' % extension, type=Boolean, default=False, dest=extension) diff --git a/lib/inx/extensions.py b/lib/inx/extensions.py index d69f0d75f..cab1ece67 100755 --- a/lib/inx/extensions.py +++ b/lib/inx/extensions.py @@ -5,14 +5,14 @@ import os -import pyembroidery +import pystitch from ..commands import (COMMANDS, GLOBAL_COMMANDS, LAYER_COMMANDS, OBJECT_COMMANDS) from ..extensions import Input, Output, extensions from ..lettering.categories import FONT_CATEGORIES from ..threads import ThreadCatalog -from .outputs import pyembroidery_output_formats +from .outputs import pystitch_output_formats from .utils import build_environment, write_inx_file @@ -31,8 +31,8 @@ def object_commands(): return [(command, COMMANDS[command]) for command in OBJECT_COMMANDS] -def pyembroidery_debug_formats(): - for format in pyembroidery.supported_formats(): +def pystitch_debug_formats(): + for format in pystitch.supported_formats(): if 'writer' in format and format['category'] not in ['embroidery', 'image', 'color', 'stitch']: yield format['extension'], format['description'] @@ -55,8 +55,8 @@ def generate_extension_inx_files(alter_data): name = extension.name() template = env.get_template(f'{name}.xml') write_inx_file(name, template.render(alter_data, - formats=pyembroidery_output_formats(), - debug_formats=pyembroidery_debug_formats(), + formats=pystitch_output_formats(), + debug_formats=pystitch_debug_formats(), threadcatalog=threadcatalog(), font_categories=FONT_CATEGORIES, layer_commands=layer_commands(), diff --git a/lib/inx/inputs.py b/lib/inx/inputs.py index cd8b57bda..667f71c97 100755 --- a/lib/inx/inputs.py +++ b/lib/inx/inputs.py @@ -3,13 +3,13 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -import pyembroidery +import pystitch from .utils import build_environment, write_inx_file -def pyembroidery_input_formats(): - for format in pyembroidery.supported_formats(): +def pystitch_input_formats(): + for format in pystitch.supported_formats(): if 'reader' in format and format['category'] in ['embroidery', 'color', 'stitch', 'quilting', 'debug']: yield format['extension'], format['description'] @@ -18,6 +18,6 @@ def generate_input_inx_files(alter_data): env = build_environment() template = env.get_template('input.xml') - for format, description in pyembroidery_input_formats(): + for format, description in pystitch_input_formats(): name = f"input_{format.upper()}" write_inx_file(name, template.render(alter_data, format=format, description=description)) diff --git a/lib/inx/outputs.py b/lib/inx/outputs.py index 0cf9ac847..51907f79f 100644 --- a/lib/inx/outputs.py +++ b/lib/inx/outputs.py @@ -3,13 +3,13 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -import pyembroidery +import pystitch from .utils import build_environment, write_inx_file -def pyembroidery_output_formats(): - for format in pyembroidery.supported_formats(): +def pystitch_output_formats(): + for format in pystitch.supported_formats(): if 'writer' in format: description = format['description'] if format['category'] == "color": @@ -30,6 +30,6 @@ def generate_output_inx_files(alter_data): env = build_environment() template = env.get_template('output.xml') - for format, description, mimetype, category in pyembroidery_output_formats(): + for format, description, mimetype, category in pystitch_output_formats(): name = f"output_{format.upper()}" write_inx_file(name, template.render(alter_data, format=format, mimetype=mimetype, description=description)) diff --git a/lib/output.py b/lib/output.py index 1b9c62a4a..ff187165b 100644 --- a/lib/output.py +++ b/lib/output.py @@ -8,9 +8,9 @@ import re import sys import inkex -from pyembroidery.exceptions import TooManyColorChangesError +from pystitch.exceptions import TooManyColorChangesError -import pyembroidery +import pystitch from .commands import global_command from .i18n import _ @@ -21,15 +21,15 @@ from .utils import Point def get_command(stitch): if stitch.jump: - return pyembroidery.JUMP + return pystitch.JUMP elif stitch.trim: - return pyembroidery.TRIM + return pystitch.TRIM elif stitch.color_change: - return pyembroidery.COLOR_CHANGE + return pystitch.COLOR_CHANGE elif stitch.stop: - return pyembroidery.STOP + return pystitch.STOP else: - return pyembroidery.NEEDLE_AT + return pystitch.NEEDLE_AT def get_origin(svg, bounding_box): @@ -47,18 +47,18 @@ def get_origin(svg, bounding_box): def jump_to_stop_point(pattern, svg): stop_position = global_command(svg, "stop_position") if stop_position: - pattern.add_stitch_absolute(pyembroidery.JUMP, stop_position.point.x, stop_position.point.y) + pattern.add_stitch_absolute(pystitch.JUMP, stop_position.point.x, stop_position.point.y) def write_embroidery_file(file_path, stitch_plan, svg, settings={}): # convert from pixels to millimeters - # also multiply by 10 to get tenths of a millimeter as required by pyembroidery + # also multiply by 10 to get tenths of a millimeter as required by pystitch scale = 10 / PIXELS_PER_MM origin = get_origin(svg, stitch_plan.bounding_box) # origin = origin * scale - pattern = pyembroidery.EmbPattern() + pattern = pystitch.EmbPattern() # For later use when writing .dst header title field. pattern.extras['name'] = os.path.splitext(svg.name)[0] @@ -66,7 +66,7 @@ def write_embroidery_file(file_path, stitch_plan, svg, settings={}): stitch = Stitch(0, 0) for color_block in stitch_plan: - pattern.add_thread(color_block.color.pyembroidery_thread) + pattern.add_thread(color_block.color.pystitch_thread) for stitch in color_block: if stitch.stop: @@ -74,21 +74,21 @@ def write_embroidery_file(file_path, stitch_plan, svg, settings={}): command = get_command(stitch) pattern.add_stitch_absolute(command, stitch.x, stitch.y) - pattern.add_stitch_absolute(pyembroidery.END, stitch.x, stitch.y) + pattern.add_stitch_absolute(pystitch.END, stitch.x, stitch.y) settings.update({ # correct for the origin "translate": -origin, # convert from pixels to millimeters - # also multiply by 10 to get tenths of a millimeter as required by pyembroidery + # also multiply by 10 to get tenths of a millimeter as required by pystitch "scale": (scale, scale), # This forces a jump at the start of the design and after each trim, # even if we're close enough not to need one. "full_jump": True, - # defaults to False in pyembroidery (see https://github.com/EmbroidePy/pyembroidery/issues/188) + # defaults to False in pystitch (see https://github.com/EmbroidePy/pyembroidery/issues/188) "trims": True, }) @@ -96,7 +96,7 @@ def write_embroidery_file(file_path, stitch_plan, svg, settings={}): settings['encode'] = True if file_path.endswith('.csv'): - # Special treatment for CSV: instruct pyembroidery not to do any post- + # Special treatment for CSV: instruct pystitch not to do any post- # processing. This will allow the user to match up stitch numbers seen # in the simulator with commands in the CSV. settings['max_stitch'] = float('inf') @@ -104,7 +104,7 @@ def write_embroidery_file(file_path, stitch_plan, svg, settings={}): settings['explicit_trim'] = False try: - pyembroidery.write(pattern, file_path, settings) + pystitch.write(pattern, file_path, settings) except IOError as e: # L10N low-level file error. %(error)s is (hopefully?) translated by # the user's system automatically. diff --git a/lib/stitch_plan/generate_stitch_plan.py b/lib/stitch_plan/generate_stitch_plan.py index cdd66d9ee..c9faff4f6 100644 --- a/lib/stitch_plan/generate_stitch_plan.py +++ b/lib/stitch_plan/generate_stitch_plan.py @@ -9,7 +9,7 @@ from html import escape import inkex -import pyembroidery +import pystitch from ..i18n import _ from ..svg import PIXELS_PER_MM, render_stitch_plan @@ -20,23 +20,23 @@ from .stitch_plan import StitchPlan def generate_stitch_plan(embroidery_file, import_commands="symbols"): # noqa: C901 validate_file_path(embroidery_file) - pattern = pyembroidery.read(embroidery_file) + pattern = pystitch.read(embroidery_file) stitch_plan = StitchPlan() color_block = None for raw_stitches, thread in pattern.get_as_colorblocks(): color_block = stitch_plan.new_color_block(thread) for x, y, command in raw_stitches: - if command == pyembroidery.STITCH: + if command == pystitch.STITCH: color_block.add_stitch(Stitch(x * PIXELS_PER_MM / 10.0, y * PIXELS_PER_MM / 10.0)) if len(color_block) > 0: - if import_commands == "none" and command in [pyembroidery.TRIM, pyembroidery.STOP]: + if import_commands == "none" and command in [pystitch.TRIM, pystitch.STOP]: # Importing commands is not wanted: # start a new color block without inserting the command color_block = stitch_plan.new_color_block(thread) - elif command == pyembroidery.TRIM: + elif command == pystitch.TRIM: color_block.add_stitch(trim=True) - elif command == pyembroidery.STOP: + elif command == pystitch.STOP: color_block.add_stitch(stop=True) color_block = stitch_plan.new_color_block(thread) diff --git a/lib/stitch_plan/read_file.py b/lib/stitch_plan/read_file.py index 56567f368..ada879582 100644 --- a/lib/stitch_plan/read_file.py +++ b/lib/stitch_plan/read_file.py @@ -3,7 +3,7 @@ # Copyright (c) 2010 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. -import pyembroidery +import pystitch from .stitch_plan import StitchPlan from ..svg import PIXELS_PER_MM @@ -11,7 +11,7 @@ from ..svg import PIXELS_PER_MM def stitch_plan_from_file(embroidery_file): """Read a machine embroidery file in any supported format and return a stitch plan.""" - pattern = pyembroidery.read(embroidery_file) + pattern = pystitch.read(embroidery_file) stitch_plan = StitchPlan() color_block = None @@ -20,7 +20,7 @@ def stitch_plan_from_file(embroidery_file): color_block = stitch_plan.new_color_block(thread) for x, y, command in raw_stitches: color_block.add_stitch(x * PIXELS_PER_MM / 10.0, y * PIXELS_PER_MM / 10.0, - jump=(command == pyembroidery.JUMP), - trim=(command == pyembroidery.TRIM)) + jump=(command == pystitch.JUMP), + trim=(command == pystitch.TRIM)) return stitch_plan diff --git a/lib/threads/color.py b/lib/threads/color.py index 335dc32b1..6644e5ec0 100644 --- a/lib/threads/color.py +++ b/lib/threads/color.py @@ -7,7 +7,7 @@ import colorsys from inkex import Color, ColorError -from pyembroidery.EmbThread import EmbThread +from pystitch.EmbThread import EmbThread class ThreadColor(object): @@ -89,7 +89,7 @@ class ThreadColor(object): return "#%s" % self.hex_digits @property - def pyembroidery_thread(self): + def pystitch_thread(self): return { "name": self.name, "id": self.number, diff --git a/mypy.ini b/mypy.ini index 4a06d5e33..3d3948859 100644 --- a/mypy.ini +++ b/mypy.ini @@ -25,6 +25,9 @@ disallow_untyped_defs = True [mypy-lib.tartan.*] ignore_errors = True +[mypy-lib.sew_stack.*] +ignore_errors = True + [mypy-tests.*] # The tests should be typechecked because they're all new code, and because they're tests we don't really care if they have perfect annotations. check_untyped_defs = True @@ -37,6 +40,6 @@ ignore_missing_imports = True ignore_missing_imports = True # ... And this one is ours but is missing type information for now anyway... -[mypy-pyembroidery.*] +[mypy-pystitch.*] ignore_missing_imports = True follow_imports = skip diff --git a/pyembroidery b/pyembroidery deleted file mode 160000 index 13e94dbfc..000000000 --- a/pyembroidery +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 13e94dbfc4a3b7de93ce2e771bf8ccf22e3551cb diff --git a/requirements.txt b/requirements.txt index ae7a5de03..6f51f7064 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,4 @@ -# Assuming pyembroidery is installed in parent directory of inkstitch. -# Maybe it would be better to install PyEmbroidery as a submodule and automatically update it, -# but the .gitignore file should be updated to ignore the build directory. -./pyembroidery +pystitch # For macOS and Windows our installer bundles the version specified here # but some Linux distros package Ink/Stitch as depending on the inkex that's bundled with Inkscape.