env update from inkscape, bash names for script

pull/2653/head
karnigen 2023-12-25 19:54:52 +01:00
rodzic 746768d849
commit fe323375e4
2 zmienionych plików z 78 dodań i 60 usunięć

Wyświetl plik

@ -11,11 +11,17 @@ from pathlib import Path
SCRIPTDIR = Path(__file__).parent.absolute()
if len(sys.argv) < 2:
exit(1) # no arguments - prevent uncidentally running this script
exit(1) # no arguments - prevent accidentally running this script
prefere_pip_inkex = True # prefer pip installed inkex over inkscape bundled inkex
# define names of files used by offline Bash script
bash_name = ".ink.sh"
bash_svg = ".ink.svg"
running_as_frozen = getattr(sys, 'frozen', None) is not None # check if running from pyinstaller bundle
running_from_inkscape = '.ink.svg' not in sys.argv # inkscape never starts extension with .ink.svg file in args
# running_from_inkscape = True # for testing
# we assume that if arguments contain svg file (=.ink.svg) then we are running not from inkscape
running_from_inkscape = bash_svg not in sys.argv
debug_active = bool((gettrace := getattr(sys, 'gettrace')) and gettrace()) # check if debugger is active on startup
debug_file = SCRIPTDIR / "DEBUG"
@ -24,53 +30,59 @@ debug_type = 'none'
profile_file = SCRIPTDIR / "PROFILE"
profile_type = 'none'
# print(f"debug_type:'{debug_type}' profile_type:'{profile_type}'", file=sys.stderr) # for testing
if not running_as_frozen: # debugging/profiling only in development mode
# parse debug file
# - if script was already started from debugger then don't read debug file
if not debug_active and os.path.exists(debug_file):
debug_type = debug_utils.parse_file(debug_file) # read type of debugger from debug_file DEBUG
if debug_type == 'none': # for better backward compatibility
print(f"Debug file exists but no debugger type found in '{debug_file.name}'", file=sys.stderr)
# if script was already started from debugger then don't read debug file
if not running_as_frozen and not debug_active and os.path.exists(debug_file):
debug_type = debug_utils.parse_file(debug_file) # read type of debugger from debug_file DEBUG
if debug_type == 'none': # for better backward compatibility
print(f"Debug file exists but no debugger type found in '{debug_file.name}'", file=sys.stderr)
# parse profile file
if os.path.exists(profile_file):
profile_type = debug_utils.parse_file(profile_file) # read type of profiler from profile_file PROFILE
if profile_type == 'none': # for better backward compatibility
print(f"Profile file exists but no profiler type found in '{profile_file.name}'", file=sys.stderr)
if os.path.exists(profile_file):
profile_type = debug_utils.parse_file(profile_file) # read type of profiler from profile_file PROFILE
if profile_type == 'none': # for better backward compatibility
print(f"Profile file exists but no profiler type found in '{profile_file.name}'", file=sys.stderr)
# process creation of the Bash script
if running_from_inkscape:
if debug_type.endswith('-script'): # if offline debugging just create script for later debugging
debug_utils.write_offline_debug_script(SCRIPTDIR, bash_name, bash_svg)
debug_type = 'none' # do not start debugger when running from inkscape
else: # not running from inkscape
if debug_type.endswith('-script'): # remove '-script' to propely initialize debugger packages for each editor
debug_type = debug_type.replace('-script', '')
if running_from_inkscape:
if debug_type.endswith('-script'): # if offline debugging just create script for later debugging
debug_utils.write_offline_debug_script(SCRIPTDIR)
debug_type = 'none' # do not start debugger when running from inkscape
else: # not running from inkscape
if debug_type.endswith('-script'): # remove '-script' to propely initialize debugger packages for each editor
debug_type = debug_type.replace('-script', '')
if prefere_pip_inkex and 'PYTHONPATH' in os.environ:
# see static void set_extensions_env() in inkscape/src/inkscape-main.cpp
if not running_as_frozen:
# When running in development mode, we prefer inkex installed by pip, not the one bundled with Inkscape.
# - move inkscape extensions path to the end of sys.path
# - we compare PYTHONPATH with sys.path and move PYTHONPATH to the end of sys.path
# - also user inkscape extensions path is moved to the end of sys.path - may cause problems?
# - path for deprecated-simple are removed from sys.path, will be added later by importing inkex
# When running in development mode, we prefer inkex installed by pip, not the one bundled with Inkscape.
# - move inkscape extensions path to the end of sys.path
# - we compare PYTHONPATH with sys.path and move PYTHONPATH to the end of sys.path
# - also user inkscape extensions path is moved to the end of sys.path - may cause problems?
# - path for deprecated-simple are removed from sys.path, will be added later by importing inkex
# PYTHONPATH to list
pythonpath = os.environ.get('PYTHONPATH', '').split(os.pathsep)
# remove pythonpath from sys.path
sys.path = [p for p in sys.path if p not in pythonpath]
# remove deprecated-simple, it will be added later by importing inkex
pythonpath = [p for p in pythonpath if not p.endswith('deprecated-simple')]
# add pythonpath to the end of sys.path
sys.path.extend(pythonpath)
# PYTHONPATH to list
pythonpath = os.environ.get('PYTHONPATH', '').split(os.pathsep)
# remove pythonpath from sys.path
sys.path = [p for p in sys.path if p not in pythonpath]
# remove deprecated-simple, it will be added later by importing inkex
pythonpath = [p for p in pythonpath if not p.endswith('deprecated-simple')]
# remove nonexisting paths
pythonpath = [p for p in pythonpath if os.path.exists(p)]
# add pythonpath to the end of sys.path
sys.path.extend(pythonpath)
# >> should be removed after previous code was tested <<
# if sys.platform == "darwin":
# extensions_path = "/Applications/Inkscape.app/Contents/Resources/share/inkscape/extensions" # Mac
# else:
# extensions_path = "/usr/share/inkscape/extensions" # Linux
# # windows not solved
# move inkscape extensions path to the end of sys.path
# sys.path.remove(extensions_path)
# sys.path.append(extensions_path)
# >> ------------------------------------------------- <<
# >> should be removed after previous code was tested <<
# if sys.platform == "darwin":
# extensions_path = "/Applications/Inkscape.app/Contents/Resources/share/inkscape/extensions" # Mac
# else:
# extensions_path = "/usr/share/inkscape/extensions" # Linux
# # windows ?
# move inkscape extensions path to the end of sys.path
# sys.path.remove(extensions_path)
# sys.path.append(extensions_path)
# >> ------------------------------------------------- <<
import logging
from argparse import ArgumentParser
@ -122,7 +134,7 @@ extension = extension_class() # create instance of extension class - call __ini
# extension run(), but we differentiate between debug and normal mode
# - in debug or profile mode we run extension or profile extension
# - in normal mode we run extension in try/except block to catch all exceptions
# - in normal mode we run extension in try/except block to catch all exceptions and hide GTK spam
if debug_active or profile_type != "none": # if debug or profile mode
print(f"Extension:'{extension_name}' Debug active:{debug_active} type:'{debug_type}' "
f"Profile type:'{profile_type}'", file=sys.stderr)

Wyświetl plik

@ -17,6 +17,7 @@ import sys
# as "vscode-script" or "pycharm-script" or "pydev-script"
# - in that case running from inkscape will not start debugger
# but prepare script for offline debugging from console
# - valid for "none-script" too
# - backward compatibilty is broken due to confusion
# debug_type = 'pydev' # default debugger backwards compatibility
# if 'PYCHARM_REMOTE_DEBUG' in os.environ: # backwards compatibility
@ -44,14 +45,14 @@ def parse_file(filename):
break
return value_type
def write_offline_debug_script(SCRIPTDIR):
def write_offline_debug_script(SCRIPTDIR, bash_name, bash_svg):
# prepare script for offline debugging from console
# - only tested on linux
import shutil
ink_file = os.path.join(SCRIPTDIR, ".ink.sh")
ink_file = os.path.join(SCRIPTDIR, bash_name)
with open(ink_file, 'w') as f:
f.write(f"#!/usr/bin/env bash\n\n")
f.write(f"# version: {sys.version}\n") # python version
f.write(f"# python version: {sys.version}\n") # python version
myargs = " ".join(sys.argv[1:])
f.write(f'# script: {sys.argv[0]} arguments: {myargs}\n') # script name and arguments
@ -61,24 +62,29 @@ def write_offline_debug_script(SCRIPTDIR):
for p in sys.path:
f.write(f"# {p}\n")
# print PYTHONPATH one per line
# see static void set_extensions_env() in inkscape/src/inkscape-main.cpp
f.write(f"# PYTHONPATH:\n")
for p in os.environ.get('PYTHONPATH', '').split(os.pathsep):
for p in os.environ.get('PYTHONPATH', '').split(os.pathsep): # PYTHONPATH to list
f.write(f"# {p}\n")
# take argument that not start with '-' as file name
svg_file = " ".join([arg for arg in sys.argv[1:] if not arg.startswith('-')])
f.write(f"# copy {svg_file} to .ink.svg\n")
# check if filer are not the same
if svg_file != '.ink.svg':
shutil.copy(svg_file, f'{SCRIPTDIR}/.ink.svg') # copy file to .ink.svg
myargs = myargs.replace(svg_file, '.ink.svg') # replace file name with .ink.svg
f.write(f"# copy {svg_file} to {bash_svg}\n")
# check if files are not the same
if svg_file != bash_svg:
shutil.copy(svg_file, SCRIPTDIR / bash_svg) # copy file to bash_svg
myargs = myargs.replace(svg_file, bash_svg) # replace file name with bash_svg
# export INK*|PYTHON* environment variables
for k, v in sorted(os.environ.items()):
if k.startswith('INK') or k.startswith('PYTHON'):
f.write(f'export {k}="{v}"\n')
# see void Extension::set_environment() in inkscape/src/extension/extension.cpp
notexported = ["SELF_CALL"] # if an extension calls inkscape itself
exported = ["INKEX_GETTEXT_DOMAIN", "INKEX_GETTEXT_DIRECTORY",
"INKSCAPE_PROFILE_DIR", "DOCUMENT_PATH", "PYTHONPATH"]
for k in notexported:
if k in os.environ:
f.write(f'# export {k}="{os.environ[k]}"\n')
for k in exported:
if k in os.environ:
f.write(f'export {k}="{os.environ[k]}"\n')
# f.write(f"# python3 -m debugpy --listen 5678 --wait-for-client inkstitch.py {myargs}\n")
f.write(f"python3 inkstitch.py {myargs}\n")
os.chmod(ink_file, 0o0755) # make file executable