diff options
Diffstat (limited to 'lib/debug_utils.py')
| -rw-r--r-- | lib/debug_utils.py | 96 |
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 |
