2021-03-12 04:17:19 +00:00
|
|
|
# Authors: see git history
|
|
|
|
#
|
|
|
|
# Copyright (c) 2010 Authors
|
|
|
|
# Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details.
|
2023-12-17 22:03:39 +00:00
|
|
|
|
2018-10-24 00:08:46 +00:00
|
|
|
import os
|
2018-04-29 01:26:53 +00:00
|
|
|
import sys
|
2024-01-05 16:05:22 +00:00
|
|
|
from pathlib import Path # to work with paths as objects
|
2024-01-13 14:42:49 +00:00
|
|
|
from argparse import ArgumentParser # to parse arguments and remove --extension
|
2024-01-05 16:05:22 +00:00
|
|
|
|
2024-05-02 23:34:58 +00:00
|
|
|
if sys.version_info >= (3, 11):
|
|
|
|
import tomllib # built-in in Python 3.11+
|
|
|
|
else:
|
|
|
|
import tomli as tomllib
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
|
|
|
import lib.debug.utils as debug_utils
|
|
|
|
import lib.debug.logging as debug_logging
|
|
|
|
from lib.debug.utils import safe_get # mimic get method of dict with default value
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------------------------
|
2023-12-17 22:03:39 +00:00
|
|
|
|
|
|
|
SCRIPTDIR = Path(__file__).parent.absolute()
|
|
|
|
|
2024-05-02 23:34:58 +00:00
|
|
|
logger = logging.getLogger("inkstitch") # create module logger with name 'inkstitch'
|
|
|
|
|
|
|
|
# TODO --- temporary --- catch old DEBUG.ini file and inform user to reformat it to DEBUG.toml
|
|
|
|
old_debug_ini = SCRIPTDIR / "DEBUG.ini"
|
|
|
|
if old_debug_ini.exists():
|
|
|
|
print("ERROR: old DEBUG.ini exists, please reformat it to DEBUG.toml and remove DEBUG.ini file", file=sys.stderr)
|
|
|
|
exit(1)
|
|
|
|
# --- end of temporary ---
|
|
|
|
|
|
|
|
debug_toml = SCRIPTDIR / "DEBUG.toml"
|
|
|
|
if debug_toml.exists():
|
|
|
|
with debug_toml.open("rb") as f:
|
|
|
|
ini = tomllib.load(f) # read DEBUG.toml file if exists, otherwise use default values in ini object
|
|
|
|
else:
|
|
|
|
ini = {}
|
|
|
|
# --------------------------------------------------------------------------------------------
|
|
|
|
|
2024-01-05 16:05:22 +00:00
|
|
|
running_as_frozen = getattr(sys, 'frozen', None) is not None # check if running from pyinstaller bundle
|
|
|
|
|
2024-05-02 23:34:58 +00:00
|
|
|
if not running_as_frozen: # override running_as_frozen from DEBUG.toml - for testing
|
|
|
|
if safe_get(ini, "DEBUG", "force_frozen", default=False):
|
|
|
|
running_as_frozen = True
|
|
|
|
|
2023-12-17 22:03:39 +00:00
|
|
|
if len(sys.argv) < 2:
|
2023-12-29 15:25:17 +00:00
|
|
|
# no arguments - prevent accidentally running this script
|
2024-01-13 14:42:49 +00:00
|
|
|
msg = "No arguments given, exiting!" # without gettext localization see _()
|
|
|
|
if running_as_frozen: # we show dialog only when running from pyinstaller bundle - using wx
|
2024-01-05 16:05:22 +00:00
|
|
|
try:
|
|
|
|
import wx
|
|
|
|
app = wx.App()
|
|
|
|
dlg = wx.MessageDialog(None, msg, "Inkstitch", wx.OK | wx.ICON_ERROR)
|
|
|
|
dlg.ShowModal()
|
|
|
|
dlg.Destroy()
|
|
|
|
except ImportError:
|
2024-05-02 23:34:58 +00:00
|
|
|
print(msg, file=sys.stderr)
|
2024-01-05 16:05:22 +00:00
|
|
|
else:
|
2024-05-02 23:34:58 +00:00
|
|
|
print(msg, file=sys.stderr)
|
2024-01-05 16:05:22 +00:00
|
|
|
exit(1)
|
2023-12-25 18:54:52 +00:00
|
|
|
|
2024-05-02 23:34:58 +00:00
|
|
|
# activate logging - must be done before any logging is done
|
|
|
|
debug_logging.activate_logging(running_as_frozen, ini, SCRIPTDIR)
|
|
|
|
# --------------------------------------------------------------------------------------------
|
2023-12-29 15:25:17 +00:00
|
|
|
|
|
|
|
# check if running from inkscape, given by environment variable
|
|
|
|
if os.environ.get('INKSTITCH_OFFLINE_SCRIPT', '').lower() in ['true', '1', 'yes', 'y']:
|
|
|
|
running_from_inkscape = False
|
|
|
|
else:
|
|
|
|
running_from_inkscape = True
|
2023-12-17 22:03:39 +00:00
|
|
|
|
2024-05-02 23:34:58 +00:00
|
|
|
# initialize debug and profiler type
|
2023-12-17 22:03:39 +00:00
|
|
|
debug_active = bool((gettrace := getattr(sys, 'gettrace')) and gettrace()) # check if debugger is active on startup
|
|
|
|
debug_type = 'none'
|
2024-01-11 13:19:16 +00:00
|
|
|
profiler_type = 'none'
|
2023-12-17 22:03:39 +00:00
|
|
|
|
2024-01-13 14:42:49 +00:00
|
|
|
if not running_as_frozen: # debugging/profiling only in development mode
|
2023-12-29 15:25:17 +00:00
|
|
|
# specify debugger type
|
2024-01-13 14:42:49 +00:00
|
|
|
# but if script was already started from debugger then don't read debug type from ini file or cmd line
|
2023-12-29 15:25:17 +00:00
|
|
|
if not debug_active:
|
2024-05-02 23:34:58 +00:00
|
|
|
debug_type = debug_utils.resolve_debug_type(ini) # read debug type from ini file or cmd line
|
2023-12-25 18:54:52 +00:00
|
|
|
|
2024-05-02 23:34:58 +00:00
|
|
|
profiler_type = debug_utils.resolve_profiler_type(ini) # read profile type from ini file or cmd line
|
2023-12-25 18:54:52 +00:00
|
|
|
|
|
|
|
if running_from_inkscape:
|
2024-01-05 16:05:22 +00:00
|
|
|
# process creation of the Bash script - should be done before sys.path is modified, see below in prefere_pip_inkex
|
2024-05-02 23:34:58 +00:00
|
|
|
if safe_get(ini, "DEBUG", "create_bash_script", default=False): # create script only if enabled in DEBUG.toml
|
2024-01-05 16:05:22 +00:00
|
|
|
debug_utils.write_offline_debug_script(SCRIPTDIR, ini)
|
2024-01-13 14:42:49 +00:00
|
|
|
|
2023-12-29 15:25:17 +00:00
|
|
|
# disable debugger when running from inkscape
|
2024-05-02 23:34:58 +00:00
|
|
|
disable_from_inkscape = safe_get(ini, "DEBUG", "disable_from_inkscape", default=False)
|
2023-12-29 15:25:17 +00:00
|
|
|
if disable_from_inkscape:
|
2023-12-25 18:54:52 +00:00
|
|
|
debug_type = 'none' # do not start debugger when running from inkscape
|
|
|
|
|
2024-01-05 16:05:22 +00:00
|
|
|
# prefer pip installed inkex over inkscape bundled inkex, pip version is bundled with Inkstitch
|
|
|
|
# - must be be done before importing inkex
|
2024-05-02 23:34:58 +00:00
|
|
|
prefere_pip_inkex = safe_get(ini, "LIBRARY", "prefer_pip_inkex", default=True)
|
2023-12-25 18:54:52 +00:00
|
|
|
if prefere_pip_inkex and 'PYTHONPATH' in os.environ:
|
2024-01-05 16:05:22 +00:00
|
|
|
debug_utils.reorder_sys_path()
|
|
|
|
|
2024-05-02 23:34:58 +00:00
|
|
|
# enabling of debug depends on value of debug_type in DEBUG.toml file
|
2023-12-17 22:03:39 +00:00
|
|
|
if debug_type != 'none':
|
2024-05-02 23:34:58 +00:00
|
|
|
from lib.debug.debugger import init_debugger
|
|
|
|
init_debugger(debug_type, ini)
|
2023-12-17 22:03:39 +00:00
|
|
|
# check if debugger is really activated
|
|
|
|
debug_active = bool((gettrace := getattr(sys, 'gettrace')) and gettrace())
|
|
|
|
|
2024-05-02 23:34:58 +00:00
|
|
|
# activate logging for svg
|
|
|
|
# we need to import only after possible modification of sys.path, we disable here flake8 E402
|
2024-05-11 06:14:40 +00:00
|
|
|
from lib.debug.debug import debug # noqa: E402 # import global variable debug - don't import whole module
|
2024-05-02 23:34:58 +00:00
|
|
|
debug.enable() # perhaps it would be better to find a more relevant name; in fact, it's about logging and svg creation.
|
|
|
|
|
|
|
|
# log startup info
|
|
|
|
debug_logging.startup_info(logger, SCRIPTDIR, running_as_frozen, running_from_inkscape, debug_active, debug_type, profiler_type)
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------------------------
|
2018-11-15 01:23:06 +00:00
|
|
|
|
2023-12-17 22:03:39 +00:00
|
|
|
# pop '--extension' from arguments and generate extension class name from extension name
|
2024-01-05 16:05:22 +00:00
|
|
|
# example: --extension=params will instantiate Params() class from lib.extensions.
|
2024-01-13 14:42:49 +00:00
|
|
|
|
|
|
|
# we need to import only after possible modification of sys.path, we disable here flake8 E402
|
|
|
|
from lib import extensions # noqa: E402 # import all supported extensions of institch
|
|
|
|
|
2024-07-18 16:59:00 +00:00
|
|
|
# TODO: if we run this earlier the warnings ignore filter for releases will not work properly
|
|
|
|
if running_as_frozen and not debug_logging.frozen_debug_active():
|
|
|
|
debug_logging.disable_warnings()
|
|
|
|
|
2018-04-29 02:14:23 +00:00
|
|
|
parser = ArgumentParser()
|
|
|
|
parser.add_argument("--extension")
|
|
|
|
my_args, remaining_args = parser.parse_known_args()
|
2018-04-29 01:26:53 +00:00
|
|
|
|
2018-04-29 02:14:23 +00:00
|
|
|
extension_name = my_args.extension
|
2018-07-29 00:40:14 +00:00
|
|
|
|
|
|
|
# example: foo_bar_baz -> FooBarBaz
|
|
|
|
extension_class_name = extension_name.title().replace("_", "")
|
|
|
|
|
|
|
|
extension_class = getattr(extensions, extension_class_name)
|
2023-12-17 22:03:39 +00:00
|
|
|
extension = extension_class() # create instance of extension class - call __init__ method
|
|
|
|
|
2024-01-05 16:05:22 +00:00
|
|
|
# extension run(), we differentiate between debug and normal mode
|
|
|
|
# - in debug or profile mode we debug or profile extension.run() method
|
|
|
|
# - in normal mode we run extension.run() in try/except block to catch all exceptions and hide GTK spam
|
2024-01-11 13:19:16 +00:00
|
|
|
if debug_active or profiler_type != "none": # if debug or profile mode
|
|
|
|
if profiler_type == 'none': # only debugging
|
2023-12-17 22:03:39 +00:00
|
|
|
extension.run(args=remaining_args)
|
2024-01-05 16:05:22 +00:00
|
|
|
else: # do profiling
|
2024-01-11 13:19:16 +00:00
|
|
|
debug_utils.profile(profiler_type, SCRIPTDIR, ini, extension, remaining_args)
|
2022-06-30 17:22:33 +00:00
|
|
|
|
2023-12-17 22:03:39 +00:00
|
|
|
else: # if not debug nor profile mode
|
2024-01-13 14:42:49 +00:00
|
|
|
from lib.exceptions import InkstitchException, format_uncaught_exception
|
|
|
|
from inkex import errormsg # to show error message in inkscape
|
|
|
|
from lxml.etree import XMLSyntaxError # to catch XMLSyntaxError from inkex
|
|
|
|
from lib.i18n import _ # see gettext translation function _()
|
|
|
|
from lib.utils import restore_stderr, save_stderr # to hide GTK spam
|
|
|
|
|
|
|
|
save_stderr() # hide GTK spam
|
new extension: Auto-Route Satin Columns (#330)
**video demo:** https://www.youtube.com/watch?v=tbghtqziB1g
This branch adds a new extension, Auto-Route Satin Columns, implementing #214! This is a huge new feature that opens the door wide for exciting stuff like lettering (#142).
To use it, select some satin columns and run the extension. After a few seconds, it will replace your satins with a new set with a logical stitching order. Under-pathing and jump-stitches will be added as necessary, and satins will be broken to facilitate jumps. The resulting satins will retain all of the parameters you had set on the original satins, including underlay, zig-zag spacing, etc.
By default, it will choose the left-most extreme as the starting point and the right-most extreme as the ending point (even if these occur partway through a satin such as the left edge of a letter "o"). You can override this by attaching the new "Auto-route satin stitch starting/ending position" commands.
There's also an option to add trims instead of jump stitches. Any jump stitch over 1mm is trimmed. I might make this configurable in the future but in my tests it seems to do a good job. Trim commands are added to the SVG, so it's easy enough to modify/delete as you see fit.
2018-10-30 23:43:21 +00:00
|
|
|
exception = None
|
|
|
|
try:
|
2021-03-04 17:40:53 +00:00
|
|
|
extension.run(args=remaining_args)
|
new extension: Auto-Route Satin Columns (#330)
**video demo:** https://www.youtube.com/watch?v=tbghtqziB1g
This branch adds a new extension, Auto-Route Satin Columns, implementing #214! This is a huge new feature that opens the door wide for exciting stuff like lettering (#142).
To use it, select some satin columns and run the extension. After a few seconds, it will replace your satins with a new set with a logical stitching order. Under-pathing and jump-stitches will be added as necessary, and satins will be broken to facilitate jumps. The resulting satins will retain all of the parameters you had set on the original satins, including underlay, zig-zag spacing, etc.
By default, it will choose the left-most extreme as the starting point and the right-most extreme as the ending point (even if these occur partway through a satin such as the left edge of a letter "o"). You can override this by attaching the new "Auto-route satin stitch starting/ending position" commands.
There's also an option to add trims instead of jump stitches. Any jump stitch over 1mm is trimmed. I might make this configurable in the future but in my tests it seems to do a good job. Trim commands are added to the SVG, so it's easy enough to modify/delete as you see fit.
2018-10-30 23:43:21 +00:00
|
|
|
except (SystemExit, KeyboardInterrupt):
|
|
|
|
raise
|
2021-03-04 17:40:53 +00:00
|
|
|
except XMLSyntaxError:
|
|
|
|
msg = _("Ink/Stitch cannot read your SVG file. "
|
|
|
|
"This is often the case when you use a file which has been created with Adobe Illustrator.")
|
|
|
|
msg += "\n\n"
|
|
|
|
msg += _("Try to import the file into Inkscape through 'File > Import...' (Ctrl+I)")
|
|
|
|
errormsg(msg)
|
2023-09-07 17:25:47 +00:00
|
|
|
except InkstitchException as exc:
|
|
|
|
errormsg(str(exc))
|
new extension: Auto-Route Satin Columns (#330)
**video demo:** https://www.youtube.com/watch?v=tbghtqziB1g
This branch adds a new extension, Auto-Route Satin Columns, implementing #214! This is a huge new feature that opens the door wide for exciting stuff like lettering (#142).
To use it, select some satin columns and run the extension. After a few seconds, it will replace your satins with a new set with a logical stitching order. Under-pathing and jump-stitches will be added as necessary, and satins will be broken to facilitate jumps. The resulting satins will retain all of the parameters you had set on the original satins, including underlay, zig-zag spacing, etc.
By default, it will choose the left-most extreme as the starting point and the right-most extreme as the ending point (even if these occur partway through a satin such as the left edge of a letter "o"). You can override this by attaching the new "Auto-route satin stitch starting/ending position" commands.
There's also an option to add trims instead of jump stitches. Any jump stitch over 1mm is trimmed. I might make this configurable in the future but in my tests it seems to do a good job. Trim commands are added to the SVG, so it's easy enough to modify/delete as you see fit.
2018-10-30 23:43:21 +00:00
|
|
|
except Exception:
|
2023-09-07 17:25:47 +00:00
|
|
|
errormsg(format_uncaught_exception())
|
|
|
|
sys.exit(1)
|
new extension: Auto-Route Satin Columns (#330)
**video demo:** https://www.youtube.com/watch?v=tbghtqziB1g
This branch adds a new extension, Auto-Route Satin Columns, implementing #214! This is a huge new feature that opens the door wide for exciting stuff like lettering (#142).
To use it, select some satin columns and run the extension. After a few seconds, it will replace your satins with a new set with a logical stitching order. Under-pathing and jump-stitches will be added as necessary, and satins will be broken to facilitate jumps. The resulting satins will retain all of the parameters you had set on the original satins, including underlay, zig-zag spacing, etc.
By default, it will choose the left-most extreme as the starting point and the right-most extreme as the ending point (even if these occur partway through a satin such as the left edge of a letter "o"). You can override this by attaching the new "Auto-route satin stitch starting/ending position" commands.
There's also an option to add trims instead of jump stitches. Any jump stitch over 1mm is trimmed. I might make this configurable in the future but in my tests it seems to do a good job. Trim commands are added to the SVG, so it's easy enough to modify/delete as you see fit.
2018-10-30 23:43:21 +00:00
|
|
|
finally:
|
|
|
|
restore_stderr()
|
|
|
|
|
2023-09-07 17:25:47 +00:00
|
|
|
sys.exit(0)
|