diff options
Diffstat (limited to 'lib/debug')
| -rw-r--r-- | lib/debug/debugger.py | 10 | ||||
| -rw-r--r-- | lib/debug/logging.py | 7 | ||||
| -rw-r--r-- | lib/debug/utils.py | 32 |
3 files changed, 41 insertions, 8 deletions
diff --git a/lib/debug/debugger.py b/lib/debug/debugger.py index 11293c8a..c58ddb3e 100644 --- a/lib/debug/debugger.py +++ b/lib/debug/debugger.py @@ -125,6 +125,10 @@ # to see flask server url routes: # - comment out the line self.disable_logging() in run() of lib/api/server.py +# We have some ignores so you don't see errors if you don't have one or more of the debugger libraries installed. +# But in turn those ignores will cause unused-ignore errors if those libraries aren't installed... +# mypy: disable-error-code="unused-ignore" + import os import sys @@ -148,11 +152,11 @@ def init_debugger(debug_type:str, ini: dict): try: if debugger == 'vscode': - import debugpy + import debugpy # type: ignore[import-untyped, import-not-found] elif debugger == 'pycharm': - import pydevd_pycharm + import pydevd_pycharm # type: ignore[import-untyped, import-not-found] elif debugger == 'pydev': - import pydevd + import pydevd # type: ignore[import-untyped, import-not-found] elif debugger == 'file': pass else: diff --git a/lib/debug/logging.py b/lib/debug/logging.py index fa474348..c46140ec 100644 --- a/lib/debug/logging.py +++ b/lib/debug/logging.py @@ -69,6 +69,7 @@ import os import sys from pathlib import Path +from typing import Dict, Any if sys.version_info >= (3, 11): import tomllib # built-in in Python 3.11+ @@ -139,7 +140,7 @@ def disable_warnings(): # in development mode we want to use configuration from some LOGGING.toml file def activate_for_development(ini: dict, SCRIPTDIR: Path): logging_config_file = safe_get(ini, "LOGGING", "log_config_file", default=None) - vars = {'SCRIPTDIR': SCRIPTDIR} # dynamic data for logging configuration + vars: Dict[str, Any] = {'SCRIPTDIR': SCRIPTDIR} # dynamic data for logging configuration if logging_config_file is not None: logging_config_file = Path(logging_config_file) @@ -157,7 +158,7 @@ def activate_for_development(ini: dict, SCRIPTDIR: Path): logger.info("Running in development mode") logger.info(f"Using logging configuration from file: {logging_config_file}") - logger.debug(f"Logging configuration: {devel_config = }") + logger.debug(f"Logging configuration: {devel_config=}") # -------------------------------------------------------------------------------------------- @@ -177,7 +178,7 @@ def configure_logging(config: dict, ini: dict, vars: dict): disable_logging = safe_get(ini, "LOGGING", "disable_logging", default=False) if disable_logging: - logger.warning(f"Logging is disabled by configuration in ini file. {disable_logging = }") + logger.warning(f"Logging is disabled by configuration in ini file. {disable_logging=}") logging.disable() # globally disable all logging of all loggers diff --git a/lib/debug/utils.py b/lib/debug/utils.py index 10d840d9..a758ab3b 100644 --- a/lib/debug/utils.py +++ b/lib/debug/utils.py @@ -14,6 +14,10 @@ import logging logger = logging.getLogger("inkstitch") +# We have some ignores so you don't see errors if you don't have one or more of the profiling libraries installed. +# But in turn those ignores will cause unused-ignore errors if those libraries aren't installed... +# mypy: disable-error-code="unused-ignore" + # safe_get - get value from nested dictionary, return default if key does not exist # - to read nested values from dict - mimic get method of dict with default value @@ -67,7 +71,7 @@ def write_offline_debug_script(debug_script_dir: Path, ini: dict): # environment PATH f.write('# PATH:\n') - f.write(f'# {os.environ.get("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') @@ -217,6 +221,8 @@ def profile(profiler_type, profile_dir: Path, ini: dict, extension, remaining_ar with_profile(extension, remaining_args, profile_file_path) elif profiler_type == 'pyinstrument': with_pyinstrument(extension, remaining_args, profile_file_path) + elif profiler_type == 'monkeytype': + with_monkeytype(extension, remaining_args, profile_file_path) else: raise ValueError(f"unknown profiler type: '{profiler_type}'") @@ -265,7 +271,7 @@ def with_pyinstrument(extension, remaining_args, profile_file_path: Path): ''' profile with pyinstrument ''' - import pyinstrument + import pyinstrument # type: ignore[import-untyped,import-not-found] profiler = pyinstrument.Profiler() profiler.start() @@ -276,3 +282,25 @@ def with_pyinstrument(extension, remaining_args, profile_file_path: Path): with open(profile_file_path, 'w') as stats_file: stats_file.write(profiler.output_html()) print(f"Profiler: pyinstrument, stats written to '{profile_file_path.name}'. Use browser to see it.", file=sys.stderr) + + +def with_monkeytype(extension, remaining_args, profile_file_path: Path) -> None: + ''' + 'profile' with monkeytype to get type information. This may be handy for anyone who wants to + add type annotations to older parts of our code that don't have them. + + See https://monkeytype.readthedocs.io/en/stable/generation.html for usage instructions. + ''' + import monkeytype # type: ignore[import-not-found] + + # Monkeytype will use these environment variables for the db path and to filter the modules respectively. + # This is easier than using monkeytype's actual config API, anyway. + dbpath = profile_file_path.with_suffix('.sqlite') + os.environ["MT_DB_PATH"] = str(dbpath) + os.environ["MONKEYTYPE_TRACE_MODULES"] = str(Path(__file__).parents[2].name) + + with monkeytype.trace(): + extension.run(args=remaining_args) + + print(f"Profiler: monkeytype, db written to '{dbpath}'.\n\n" + + f"Run 'MT_DB_PATH={dbpath} monkeytype ...' from the inkstitch repo directory.", file=sys.stderr) |
