summaryrefslogtreecommitdiff
path: root/lib/debug_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/debug_utils.py')
-rw-r--r--lib/debug_utils.py96
1 files changed, 64 insertions, 32 deletions
diff --git a/lib/debug_utils.py b/lib/debug_utils.py
index 169fa4c5..ef8b364d 100644
--- a/lib/debug_utils.py
+++ b/lib/debug_utils.py
@@ -13,7 +13,7 @@ import configparser # to read DEBUG.ini
# - later sys.path may be modified that influences importing inkex (see prefere_pip_inkex)
-def write_offline_debug_script(debug_script_dir : Path, ini : configparser.ConfigParser):
+def write_offline_debug_script(debug_script_dir: Path, ini: configparser.ConfigParser):
'''
prepare Bash script for offline debugging from console
arguments:
@@ -22,9 +22,9 @@ def write_offline_debug_script(debug_script_dir : Path, ini : configparser.Confi
'''
# define names of files used by offline Bash script
- bash_file_base = ini.get("DEBUG","bash_file_base", fallback="debug_inkstitch")
+ bash_file_base = ini.get("DEBUG", "bash_file_base", fallback="debug_inkstitch")
bash_name = Path(bash_file_base).with_suffix(".sh") # Path object
- bash_svg = Path(bash_file_base).with_suffix(".svg") # Path object
+ bash_svg = Path(bash_file_base).with_suffix(".svg") # Path object
# check if input svg file exists in arguments, take argument that not start with '-' as file name
svgs = [arg for arg in sys.argv[1:] if not arg.startswith('-')]
@@ -34,47 +34,47 @@ def write_offline_debug_script(debug_script_dir : Path, ini : configparser.Confi
svg_file = Path(svgs[0])
if svg_file.exists() and bash_svg.exists() and bash_svg.samefile(svg_file):
- print(f"WARN: input svg file is same as output svg file. No script created in write debug script.", file=sys.stderr)
+ print("WARN: input svg file is same as output svg file. No script created in write debug script.", file=sys.stderr)
return
-
+
import shutil # to copy svg file
bash_file = debug_script_dir / bash_name
with open(bash_file, 'w') as f: # "w" text mode, automatic conversion of \n to os.linesep
- f.write(f'#!/usr/bin/env bash\n')
+ f.write('#!/usr/bin/env bash\n')
# cmd line arguments for debugging and profiling
f.write(bash_parser()) # parse cmd line arguments: -d -p
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
+ f.write(f'# script: {sys.argv[0]} arguments: {myargs}\n') # script name and arguments
# environment PATH
- f.write(f'# PATH:\n')
+ f.write('# PATH:\n')
f.write(f'# {os.environ.get("PATH","")}\n')
# for p in os.environ.get("PATH", '').split(os.pathsep): # PATH to list
# f.write(f'# {p}\n')
# python module path
- f.write(f'# python sys.path:\n')
+ f.write('# python sys.path:\n')
for p in sys.path:
f.write(f'# {p}\n')
# 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): # PYTHONPATH to list
+ f.write('# PYTHONPATH:\n')
+ for p in os.environ.get('PYTHONPATH', '').split(os.pathsep): # PYTHONPATH to list
f.write(f'# {p}\n')
f.write(f'# copy {svg_file} to {bash_svg}\n#\n')
shutil.copy(svg_file, debug_script_dir / bash_svg) # copy file to bash_svg
- myargs = myargs.replace(str(svg_file), str(bash_svg)) # replace file name with bash_svg
+ myargs = myargs.replace(str(svg_file), str(bash_svg)) # replace file name with bash_svg
# see void Extension::set_environment() in inkscape/src/extension/extension.cpp
f.write('# Export inkscape environment variables:\n')
- notexported = ['SELF_CALL'] # if an extension calls inkscape itself
- exported = ['INKEX_GETTEXT_DOMAIN', 'INKEX_GETTEXT_DIRECTORY',
+ 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:
@@ -84,7 +84,7 @@ def write_offline_debug_script(debug_script_dir : Path, ini : configparser.Confi
f.write(f'export {k}="{os.environ[k]}"\n')
f.write('# signal inkstitch.py that we are running from offline script\n')
- f.write(f'export INKSTITCH_OFFLINE_SCRIPT="True"\n')
+ f.write('export INKSTITCH_OFFLINE_SCRIPT="True"\n')
f.write('# call inkstitch\n')
f.write(f'python3 inkstitch.py {myargs}\n')
@@ -92,7 +92,7 @@ def write_offline_debug_script(debug_script_dir : Path, ini : configparser.Confi
def bash_parser():
- return '''
+ return r'''
set -e # exit on error
# parse cmd line arguments:
@@ -102,10 +102,10 @@ set -e # exit on error
while getopts ":dp" opt; do
case $opt in
d)
- arg_d="true"
+ export INKSTITCH_DEBUG_ENABLE="True"
;;
p)
- arg_p="true"
+ export INKSTITCH_PROFILE_ENABLE="True"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
@@ -118,14 +118,6 @@ while getopts ":dp" opt; do
esac
done
-# -v: check if variable is set
-if [[ -v arg_d ]]; then
- export INKSTITCH_DEBUG_ENABLE="True"
-fi
-if [[ -v arg_p ]]; then
- export INKSTITCH_PROFILE_ENABLE="True"
-fi
-
'''
@@ -152,19 +144,56 @@ def reorder_sys_path():
# add pythonpath to the end of sys.path
sys.path.extend(pythonpath)
+
+# -----------------------------------------------------------------------------
+# try to resolve debugger type from ini file or cmd line of bash
+def resole_debug_type(ini: configparser.ConfigParser):
+ # enable/disable debugger from bash: -d
+ if os.environ.get('INKSTITCH_DEBUG_ENABLE', '').lower() in ['true', '1', 'yes', 'y']:
+ debug_enable = True
+ else:
+ debug_enable = ini.getboolean("DEBUG", "debug_enable", fallback=False) # enable debugger on startup from ini
+
+ debug_type = ini.get("DEBUG", "debug_type", fallback="none") # debugger type vscode, pycharm, pydevd
+ if not debug_enable:
+ debug_type = 'none'
+
+ debug_to_file = ini.getboolean("DEBUG", "debug_to_file", fallback=False) # write debug output to file
+ if debug_to_file and debug_type == 'none':
+ debug_type = 'file'
+
+ return debug_type
+
+
+# try to resolve profiler type from ini file or cmd line of bash
+def resole_profile_type(ini: configparser.ConfigParser):
+ # enable/disable profiling from bash: -p
+ if os.environ.get('INKSTITCH_PROFILE_ENABLE', '').lower() in ['true', '1', 'yes', 'y']:
+ profile_enable = True
+ else:
+ profile_enable = ini.getboolean("PROFILE", "profile_enable", fallback=False) # read from ini
+
+ # specify profiler type
+ profiler_type = ini.get("PROFILE", "profiler_type", fallback="none") # profiler type cprofile, profile, pyinstrument
+ if not profile_enable:
+ profiler_type = 'none'
+
+ return profiler_type
+
# -----------------------------------------------------------------------------
+
# Profilers:
# currently supported profilers:
# - cProfile - standard python profiler
# - profile - standard python profiler
# - pyinstrument - profiler with nice html output
-
-def profile(profiler_type, profile_dir : Path, ini : configparser.ConfigParser, extension, remaining_args):
+
+def profile(profiler_type, profile_dir: Path, ini: configparser.ConfigParser, extension, remaining_args):
'''
profile with cProfile, profile or pyinstrument
'''
- profile_file_base = ini.get("PROFILE","profile_file_base", fallback="debug_profile")
+ profile_file_base = ini.get("PROFILE", "profile_file_base", fallback="debug_profile")
profile_file_path = profile_dir / profile_file_base # Path object
if profiler_type == 'cprofile':
@@ -176,6 +205,7 @@ def profile(profiler_type, profile_dir : Path, ini : configparser.ConfigParser,
else:
raise ValueError(f"unknown profiler type: '{profiler_type}'")
+
def with_cprofile(extension, remaining_args, profile_file_path):
'''
profile with cProfile
@@ -193,9 +223,10 @@ def with_cprofile(extension, remaining_args, profile_file_path):
stats = pstats.Stats(profiler, stream=stats_file)
stats.sort_stats(pstats.SortKey.CUMULATIVE)
stats.print_stats()
- print(f"Profiler: cprofile, stats written to '{profile_file_path.name}' and '{profile_file_path.name}.prof'. Use snakeviz to see it.",
+ print(f"Profiler: cprofile, stats written to '{profile_file_path.name}' and '{profile_file_path.name}.prof'. Use snakeviz to see it.",
file=sys.stderr)
+
def with_profile(extension, remaining_args, profile_file_path):
'''
profile with profile
@@ -211,9 +242,10 @@ def with_profile(extension, remaining_args, profile_file_path):
stats = pstats.Stats(profiler, stream=stats_file)
stats.sort_stats(pstats.SortKey.CUMULATIVE)
stats.print_stats()
- print(f"'Profiler: profile, stats written to '{profile_file_path.name}' and '{profile_file_path.name}.prof'. Use of snakeviz is broken.",
+ print(f"'Profiler: profile, stats written to '{profile_file_path.name}' and '{profile_file_path.name}.prof'. Use of snakeviz is broken.",
file=sys.stderr)
+
def with_pyinstrument(extension, remaining_args, profile_file_path):
'''
profile with pyinstrument