diff --git a/docs/plugins/hooks.rst b/docs/plugins/hooks.rst index 37d6911c..735ec793 100644 --- a/docs/plugins/hooks.rst +++ b/docs/plugins/hooks.rst @@ -192,3 +192,38 @@ octoprint.comm.transport.serial.factory :rtype: A serial instance implementing implementing the methods ``readline(...)``, ``write(...)``, ``close()`` and optionally ``baudrate`` and ``timeout`` attributes as described above. +.. _sec-plugins-hook-filemanager-extensiontree: + +octoprint.filemanager.extension_tree +------------------------------------ + +.. py:function:: hook() + + Return additional entries for the tree of accepted file extensions for uploading/handling by the file manager. + + Should return a dictionary to merge with the existing extension tree, adding additional extension groups to + ``machinecode`` or ``model`` types. + + **Example:** + + The following handler would add a new file type "x3g" as accepted ``machinecode`` format, with extensions ``x3g`` + and ``s3g``: + + .. code-block:: python + :linenos: + + def support_x3g_machinecode(): + return dict( + machinecode=dict( + x3g=["x3g", "s3g"] + ) + ) + + .. note:: + + This will only add the supplied extensions to the extension tree, allowing the files to be uploaded and managed + through the file manager. Plugins will need to add further steps to ensure that the files will be processable + in the rest of the system (e.g. handling/preprocessing new machine code file types for printing etc)! + + :return: The partial extension tree to merge with the full extension tree. + :rtype: dict \ No newline at end of file diff --git a/src/octoprint/filemanager/__init__.py b/src/octoprint/filemanager/__init__.py index 068caa2e..04961254 100644 --- a/src/octoprint/filemanager/__init__.py +++ b/src/octoprint/filemanager/__init__.py @@ -9,6 +9,7 @@ import logging import os import octoprint.plugin +import octoprint.util from octoprint.events import eventManager, Events @@ -17,19 +18,35 @@ from .analysis import QueueEntry, AnalysisQueue from .storage import LocalFileStorage extensions = dict( - # extensions for 3d model files - model=dict( - stl=["stl"] - ), - # extensions for printable machine code - machinecode=dict( - gcode=["gcode", "gco", "g"] - ) ) +def full_extension_tree(): + result = dict( + # extensions for 3d model files + model=dict( + stl=["stl"] + ), + # extensions for printable machine code + machinecode=dict( + gcode=["gcode", "gco", "g"] + ) + ) + + extension_tree_hooks = octoprint.plugin.plugin_manager().get_hooks("octoprint.filemanager.extension_tree") + for name, hook in extension_tree_hooks.items(): + try: + hook_result = hook() + if hook_result is None or not isinstance(hook_result, dict): + continue + result = octoprint.util.dict_merge(result, hook_result) + except: + logging.getLogger(__name__).exception("Exception while retrieving additional extension tree entries from hook {name}".format(name=name)) + + return result + def get_extensions(type, subtree=None): if not subtree: - subtree = extensions + subtree = full_extension_tree() for key, value in subtree.items(): if key == type: @@ -43,7 +60,7 @@ def get_extensions(type, subtree=None): def get_all_extensions(subtree=None): if not subtree: - subtree = extensions + subtree = full_extension_tree() result = [] if isinstance(subtree, dict): @@ -58,7 +75,7 @@ def get_all_extensions(subtree=None): def get_path_for_extension(extension, subtree=None): if not subtree: - subtree = extensions + subtree = full_extension_tree() for key, value in subtree.items(): if isinstance(value, (list, tuple)) and extension in value: @@ -70,11 +87,9 @@ def get_path_for_extension(extension, subtree=None): return None -all_extensions = get_all_extensions() - def valid_extension(extension, type=None): if not type: - return extension in all_extensions + return extension in get_all_extensions() else: extensions = get_extensions(type) if extensions: diff --git a/src/octoprint/server/util/watchdog.py b/src/octoprint/server/util/watchdog.py index a335be05..0ea409b4 100644 --- a/src/octoprint/server/util/watchdog.py +++ b/src/octoprint/server/util/watchdog.py @@ -17,10 +17,8 @@ class GcodeWatchdogHandler(watchdog.events.PatternMatchingEventHandler): Takes care of automatically "uploading" files that get added to the watched folder. """ - patterns = map(lambda x: "*.%s" % x, octoprint.filemanager.get_all_extensions()) - def __init__(self, file_manager, printer): - watchdog.events.PatternMatchingEventHandler.__init__(self) + watchdog.events.PatternMatchingEventHandler.__init__(self, patterns=map(lambda x: "*.%s" % x, octoprint.filemanager.get_all_extensions())) self._logger = logging.getLogger(__name__) @@ -55,7 +53,7 @@ class GcodeWatchdogHandler(watchdog.events.PatternMatchingEventHandler): futureFilename = self._file_manager.sanitize_name(octoprint.filemanager.FileDestinations.LOCAL, file_wrapper.filename) except: futureFilename = None - if futureFilename is None or (len(self._file_manager.registered_slicers) == 0 and not octoprint.filemanager.valid_file_type(futureFilename, type="gcode")): + if futureFilename is None or (len(self._file_manager.registered_slicers) == 0 and not octoprint.filemanager.valid_file_type(futureFilename)): return # prohibit overwriting currently selected file while it's being printed