diff --git a/.gitignore b/.gitignore index 2bc23f69f..4b87b0495 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ klippy/.version ci_build/ ci_cache/ _test_.* +klippy/plugins/* +!klippy/plugins/__init__.py diff --git a/README.md b/README.md index e871693ad..1879415c8 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,13 @@ Features merged into the master branch: - [retraction: z_hop while retracting](https://github.com/DangerKlippers/danger-klipper/pull/83) ([klipper#6311](https://github.com/Klipper3d/klipper/pull/6311)) +- [core: git-untracked folder, plugins for user-plugins](https://github.com/DangerKlippers/danger-klipper/pull/82) + +- [danger_options: allow plugins to override conflicting extras](https://github.com/DangerKlippers/danger-klipper/pull/82) + If you're feeling adventurous, take a peek at the extra features in the bleeding-edge branch: -- [dmbutyugin's advanced-features branch](https://github.com/DangerKlippers/danger-klipper/pull/69) [dmbutyugin/advanced-features](https://github.com/dmbutyugin/klipper/commits/advanced-features) + - [dmbutyugin's advanced-features branch](https://github.com/DangerKlippers/danger-klipper/pull/69) [dmbutyugin/advanced-features](https://github.com/dmbutyugin/klipper/commits/advanced-features) - [stepper: high precision stepping protocol](https://github.com/DangerKlippers/danger-klipper/pull/69) diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index 35288f2a5..90a48d8b0 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -97,6 +97,10 @@ log_bed_mesh_at_startup: True # Most of it is overly-verbose and fluff and we still get a stack trace # for normal exceptions, so setting to False can help save time while developing log_shutdown_info: True + +# Allows modules in `plugins` to override modules of the same name in `extras` +allow_plugin_override: False + ``` ## Common kinematic settings diff --git a/klippy/extras/danger_options.py b/klippy/extras/danger_options.py index c1724223c..909063478 100644 --- a/klippy/extras/danger_options.py +++ b/klippy/extras/danger_options.py @@ -12,6 +12,10 @@ def __init__(self, config): "error_on_unused_config_options", True ) + self.allow_plugin_override = config.getboolean( + "allow_plugin_override", False + ) + def load_config(config): return DangerOptions(config) diff --git a/klippy/klippy.py b/klippy/klippy.py index 65c3ee527..2405a5381 100644 --- a/klippy/klippy.py +++ b/klippy/klippy.py @@ -66,6 +66,7 @@ def __init__(self, main_reactor, bglogger, start_args): self.run_result = None self.event_handlers = {} self.objects = collections.OrderedDict() + self.danger_options = None # Init printer components that must be setup prior to config for m in [gcode, webhooks]: m.add_early_printer_objects(self) @@ -129,17 +130,47 @@ def load_object(self, config, section, default=configfile.sentinel): return self.objects[section] module_parts = section.split() module_name = module_parts[0] - py_name = os.path.join( + extras_py_name = os.path.join( os.path.dirname(__file__), "extras", module_name + ".py" ) - py_dirname = os.path.join( + extras_py_dirname = os.path.join( os.path.dirname(__file__), "extras", module_name, "__init__.py" ) - if not os.path.exists(py_name) and not os.path.exists(py_dirname): + + plugins_py_dirname = os.path.join( + os.path.dirname(__file__), "plugins", module_name, "__init__.py" + ) + plugins_py_name = os.path.join( + os.path.dirname(__file__), "plugins", module_name + ".py" + ) + + found_in_extras = os.path.exists(extras_py_name) or os.path.exists( + extras_py_dirname + ) + found_in_plugins = os.path.exists(plugins_py_name) + if not found_in_extras and not found_in_plugins: if default is not configfile.sentinel: return default raise self.config_error("Unable to load module '%s'" % (section,)) - mod = importlib.import_module("extras." + module_name) + + if ( + found_in_extras + and found_in_plugins + and not self.danger_options.allow_plugin_override + ): + raise self.config_error( + "Module '%s' found in both extras and plugins!" % (section,) + ) + + if found_in_plugins: + mod_spec = importlib.util.spec_from_file_location( + "extras." + module_name, plugins_py_name + ) + mod = importlib.util.module_from_spec(mod_spec) + mod_spec.loader.exec_module(mod) + else: + mod = importlib.import_module("extras." + module_name) + init_func = "load_config" if len(module_parts) > 1: init_func = "load_config_prefix" @@ -154,10 +185,10 @@ def load_object(self, config, section, default=configfile.sentinel): def _read_config(self): self.objects["configfile"] = pconfig = configfile.PrinterConfig(self) config = pconfig.read_main_config() - danger_options = self.load_object(config, "danger_options") + self.danger_options = self.load_object(config, "danger_options") if ( self.bglogger is not None - and danger_options.log_config_file_at_startup + and self.danger_options.log_config_file_at_startup ): pconfig.log_config(config) # Create printer components @@ -168,7 +199,7 @@ def _read_config(self): for m in [toolhead]: m.add_printer_objects(config) # Validate that there are no undefined parameters in the config file - error_on_unused = danger_options.error_on_unused_config_options + error_on_unused = self.danger_options.error_on_unused_config_options pconfig.check_unused_options(config, error_on_unused) def _build_protocol_error_message(self, e): @@ -437,32 +468,8 @@ def main(): logging.info("Starting Klippy...") git_info = util.get_git_version() git_vers = git_info["version"] - extra_files = [ - fname - for code, fname in git_info["file_status"] - if ( - code in ("??", "!!") - and fname.endswith(".py") - and ( - fname.startswith("klippy/kinematics/") - or fname.startswith("klippy/extras/") - ) - ) - ] - modified_files = [ - fname for code, fname in git_info["file_status"] if code == "M" - ] + extra_git_desc = "" - if extra_files: - if not git_vers.endswith("-dirty"): - git_vers = git_vers + "-dirty" - if len(extra_files) > 10: - extra_files[10:] = ["(+%d files)" % (len(extra_files) - 10,)] - extra_git_desc += "\nUntracked files: %s" % (", ".join(extra_files),) - if modified_files: - if len(modified_files) > 10: - modified_files[10:] = ["(+%d files)" % (len(modified_files) - 10,)] - extra_git_desc += "\nModified files: %s" % (", ".join(modified_files),) extra_git_desc += "\nBranch: %s" % (git_info["branch"]) extra_git_desc += "\nRemote: %s" % (git_info["remote"]) extra_git_desc += "\nTracked URL: %s" % (git_info["url"]) diff --git a/klippy/plugins/__init__.py b/klippy/plugins/__init__.py new file mode 100644 index 000000000..62f5df7b2 --- /dev/null +++ b/klippy/plugins/__init__.py @@ -0,0 +1,5 @@ +# Package definition for the plugin directory +# +# Copyright (C) 2023 Brandon Nance +# +# This file may be distributed under the terms of the GNU GPLv3 license. diff --git a/test/klippy/danger_options.cfg b/test/klippy/danger_options.cfg index 17e4e97d7..f6fbac8a2 100644 --- a/test/klippy/danger_options.cfg +++ b/test/klippy/danger_options.cfg @@ -6,6 +6,7 @@ log_config_file_at_startup: False error_on_unused_config_options: False log_bed_mesh_at_startup: False log_shutdown_info: False +allow_plugin_override: True [stepper_x] step_pin: PF0