diff --git a/inkstitch.py b/inkstitch.py index c00fcc042..d85eaba4e 100644 --- a/inkstitch.py +++ b/inkstitch.py @@ -47,7 +47,7 @@ if not running_as_frozen: # debugging/profiling only in development mode # specify debugger type # - if script was already started from debugger then don't read debug type from ini file or cmd line if not debug_active: - # enable/disable debugger + # enable/disable debugger from bash: -d if os.environ.get('INKSTITCH_DEBUG_ENABLE', '').lower() in ['true', '1', 'yes', 'y']: debug_enable = True else: @@ -61,7 +61,7 @@ if not running_as_frozen: # debugging/profiling only in development mode if debug_to_file and debug_type == 'none': debug_type = 'file' - # enbale/disable profiling + # enbale/disable profiling from bash: -p if os.environ.get('INKSTITCH_PROFILE_ENABLE', '').lower() in ['true', '1', 'yes', 'y']: profile_enable = True else: @@ -115,8 +115,8 @@ if running_as_frozen or not debug_active: import warnings warnings.filterwarnings('ignore') -# TODO - check if this is still for shapely needed, apparently, shapely uses only exceptions instead of io. -# all logs were removed from version 2.0.0, ensure that shapely is always >= 2.0.0 +# TODO - check if this is still needed for shapely, apparently shapely now uses only exceptions instead of io. +# all logs were removed from version 2.0.0 and above # ---- plan to remove this in future ---- # set logger for shapely - for old versions of shapely @@ -174,7 +174,7 @@ else: # if not debug nor profile mode finally: restore_stderr() - # if shapely_errors.tell(): + # if shapely_errors.tell(): # see above plan to remove this in future for shapely # errormsg(shapely_errors.getvalue()) sys.exit(0) diff --git a/lib/debug.py b/lib/debug.py index d3c19429d..93bb9629f 100644 --- a/lib/debug.py +++ b/lib/debug.py @@ -101,22 +101,54 @@ class Debug(object): self.log("Debug logging enabled.") def init_debugger(self): - # How to debug Ink/Stitch with LiClipse: + ### General debugging notes: + # 1. to enable debugging or profiling copy DEBUG_template.ini to DEBUG.ini and edit it + + ### How create bash script for offline debugging from console + # 1. in DEBUG.ini set create_bash_script = True + # 2. call inkstitch.py extension from inkscape to create bash script named by bash_file_base in DEBUG.ini + # 3. run bash script from console + + ### Enable debugging + # 1. set debug_type to one of - vscode, pycharm, pydev, see below for details + # debug_type = vscode - 'debugpy' for vscode editor + # debug_type = pycharm - 'pydevd-pycharm' for pycharm editor + # debug_type = pydev - 'pydevd' for eclipse editor + # 2. set debug_enable = True in DEBUG.ini + # or use command line argument -d in bash script + # or set environment variable INKSTITCH_DEBUG_ENABLE = True or 1 or yes or y + + ### Enable profiling + # 1. set profiler_type to one of - cprofile, profile, pyinstrument + # profiler_type = cprofile - 'cProfile' profiler + # profiler_type = profile - 'profile' profiler + # profiler_type = pyinstrument- 'pyinstrument' profiler + # 2. set profile_enable = True in DEBUG.ini + # or use command line argument -p in bash script + # or set environment variable INKSTITCH_PROFILE_ENABLE = True or 1 or yes or y + + ### Miscelaneous notes: + # - to disable debugger when running from inkscape set disable_from_inkscape = True in DEBUG.ini + # - to write debug output to file set debug_to_file = True in DEBUG.ini + # - to change various output file names see DEBUG.ini + # - to disable waiting for debugger to attach (vscode editor) set wait_attach = False in DEBUG.ini + # - to prefer inkscape version of inkex module over pip version set prefer_pip_inkex = False in DEBUG.ini + + ### + + + ### How to debug Ink/Stitch with LiClipse: # # 1. Install LiClipse (liclipse.com) -- no need to install Eclipse first # 2. Start debug server as described here: http://www.pydev.org/manual_adv_remote_debugger.html # * follow the "Note:" to enable the debug server menu item - # 3. Copy and edit a file named "DEBUG.ini" from "DEBUG_template.ini" next to inkstitch.py in your git clone. + # 3. Copy and edit a file named "DEBUG.ini" from "DEBUG_template.ini" next to inkstitch.py in your git clone + # and set debug_type = pydev # 4. Run any extension and PyDev will start debugging. - # debugger = vscode - 'debugpy' for vscode editor - # debugger = pycharm - 'pydevd-pycharm' for pycharm editor - # debugger = pydev - 'pydevd' for eclipse editor - # debugger = file - no debugger, only debug.log, debug.svg are used - ### - # To debug with PyCharm: + ### To debug with PyCharm: # You must use the PyCharm Professional Edition and _not_ the Community # Edition. Jetbrains has chosen to make remote debugging a Pro feature. @@ -137,7 +169,8 @@ class Debug(object): # configuration. Set "IDE host name:" to "localhost" and "Port:" to 5678. # You can leave the default settings for all other choices. # - # 3. Touch a file named "DEBUG.ini" at the top of your git repo, as above. + # 3. Touch a file named "DEBUG.ini" at the top of your git repo, as above + # set debug_type = pycharm # # 4. Create a symbolic link in the Inkscape extensions directory to the # top-level directory of your git repo. On a mac, for example: @@ -162,7 +195,7 @@ class Debug(object): ### - # To debug with VS Code + ### To debug with VS Code # see: https://code.visualstudio.com/docs/python/debugging#_command-line-debugging # https://code.visualstudio.com/docs/python/debugging#_debugging-by-attaching-over-a-network-connection # @@ -180,7 +213,8 @@ class Debug(object): # } # } # ] - # 3. Touch a file named "DEBUG.ini" at the top of your git repo, as above. + # 3. Touch a file named "DEBUG.ini" at the top of your git repo, as above + # set debug_type = vscode # 4. Start the debug server in VS Code by clicking on the debug icon in the left pane # select "Python: Attach" from the dropdown menu and click on the green arrow. # The debug server will start and connect to already running python processes, diff --git a/lib/debug_utils.py b/lib/debug_utils.py index ab2a6ca9e..169fa4c5b 100644 --- a/lib/debug_utils.py +++ b/lib/debug_utils.py @@ -53,7 +53,7 @@ def write_offline_debug_script(debug_script_dir : Path, ini : configparser.Confi # environment PATH f.write(f'# PATH:\n') - f.write(f'# {os.environ["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') @@ -67,17 +67,18 @@ def write_offline_debug_script(debug_script_dir : Path, ini : configparser.Confi 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') + 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 # 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', 'INKSCAPE_PROFILE_DIR', 'DOCUMENT_PATH', 'PYTHONPATH'] for k in notexported: if k in os.environ: - f.write(f'# export {k}="{os.environ[k]}"\n') + 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') @@ -159,21 +160,21 @@ def reorder_sys_path(): # - pyinstrument - profiler with nice html output -def profile(profile_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_path = profile_dir / profile_file_base # Path object - if profile_type == 'cprofile': + if profiler_type == 'cprofile': with_cprofile(extension, remaining_args, profile_file_path) - elif profile_type == 'profile': + elif profiler_type == 'profile': with_profile(extension, remaining_args, profile_file_path) - elif profile_type == 'pyinstrument': + elif profiler_type == 'pyinstrument': with_pyinstrument(extension, remaining_args, profile_file_path) else: - raise ValueError(f"unknown profiler type: '{profile_type}'") + raise ValueError(f"unknown profiler type: '{profiler_type}'") def with_cprofile(extension, remaining_args, profile_file_path): '''