From a0f2079fb564b14555f21e15cf38080b695f3be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Thu, 25 Jun 2015 11:00:14 +0200 Subject: [PATCH 01/14] maintenance branch is 1.2.1-dev for now This branch is for preparing the next patch-releases of the current stable release on the master branch. --- .versioneer-lookup | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.versioneer-lookup b/.versioneer-lookup index 8e1218d79..6f4c4d688 100644 --- a/.versioneer-lookup +++ b/.versioneer-lookup @@ -7,12 +7,13 @@ # The file is processed from top to bottom, the first matching line wins. If or are left out, # the lookup table does not apply to the matched branches -# master and staging shall not use the lookup table +# master shall not use the lookup table, only tags master -staging -# fix/ branches are fixes for master, so we don't handle those either -fix/.* +# maintenance is currently the branch for preparation of maintenance release 1.2.1 +# so are any fix/... branches +maintenance 1.2.1-dev cfa4cb2a7c5f1af10dc8 +fix/.* 1.2.1-dev cfa4cb2a7c5f1af10dc8 # every other branch is a development branch and thus gets resolved to 1.2.0-dev for now .* 1.2.0-dev 50cf776e70b9 From 69e5f137a68d3d079670f7a26660da15a72ea715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Thu, 25 Jun 2015 10:50:54 +0200 Subject: [PATCH 02/14] Devel is now 1.3 (cherry picked from commit dd5bf2e) --- .versioneer-lookup | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.versioneer-lookup b/.versioneer-lookup index 6f4c4d688..0e9ab0a09 100644 --- a/.versioneer-lookup +++ b/.versioneer-lookup @@ -15,5 +15,5 @@ master maintenance 1.2.1-dev cfa4cb2a7c5f1af10dc8 fix/.* 1.2.1-dev cfa4cb2a7c5f1af10dc8 -# every other branch is a development branch and thus gets resolved to 1.2.0-dev for now -.* 1.2.0-dev 50cf776e70b9 +# every other branch is a development branch and thus gets resolved to 1.3.0-dev for now +.* 1.3.0-dev 198d3450d94be1a2 From 401ebcf68559999beb97da7179704a5bc9e613ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Thu, 25 Jun 2015 15:18:33 +0200 Subject: [PATCH 03/14] Fix: Cleanly exit on SIGTERM --- CHANGELOG.md | 7 +++++++ src/octoprint/server/__init__.py | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe57f3e8f..d754f68e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # OctoPrint Changelog +## 1.2.1 (unreleased) + +### Bug Fixes + +* [IRC] - OctoPrint will now exit cleanly on `SIGTERM`, calling the shutdown functions provided by plugins. + Thanks @Salandora for the heads-up. + ## 1.2.0 (2015-06-25) ### Note for Upgraders diff --git a/src/octoprint/server/__init__.py b/src/octoprint/server/__init__.py index 8426628fd..35586d1dd 100644 --- a/src/octoprint/server/__init__.py +++ b/src/octoprint/server/__init__.py @@ -20,6 +20,7 @@ import logging import logging.config import atexit +import signal SUCCESS = {} NO_CONTENT = ("", 204) @@ -440,16 +441,27 @@ def call_on_after_startup(name, plugin): # prepare our shutdown function def on_shutdown(): - self._logger.info("Goodbye!") + # will be called on clean system exit and shutdown the watchdog observer and call the on_shutdown methods + # on all registered ShutdownPlugins + self._logger.info("Shutting down...") observer.stop() observer.join() octoprint.plugin.call_plugin(octoprint.plugin.ShutdownPlugin, "on_shutdown") + self._logger.info("Goodbye!") atexit.register(on_shutdown) + def sigterm_handler(*args, **kwargs): + # will stop tornado on SIGTERM, making the program exit cleanly + def shutdown_tornado(): + ioloop.stop() + ioloop.add_callback_from_signal(shutdown_tornado) + signal.signal(signal.SIGTERM, sigterm_handler) + try: + # this is the main loop - as long as tornado is running, OctoPrint is running ioloop.start() - except KeyboardInterrupt: + except (KeyboardInterrupt, SystemExit): pass except: self._logger.fatal("Now that is embarrassing... Something really really went wrong here. Please report this including the stacktrace below in OctoPrint's bugtracker. Thanks!") From 0c54eaf1763149eedee7755ffe53058ca344a669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sun, 28 Jun 2015 02:19:28 +0200 Subject: [PATCH 04/14] Fix: Use Exception, not BaseException Custom exception should be derived from Exception, not BaseException. Not only is this specified in the python documentation, but also tornado will be able to handle Exceptions in requests perfectly fine and return an HTTP 500 for them, but crash hard (as in, server shut down follows) for BaseExceptions. (cherry picked from commit 29b047b) --- src/octoprint/plugin/core.py | 8 ++++---- src/octoprint/printer/__init__.py | 2 +- src/octoprint/server/api/languages.py | 2 +- src/octoprint/slicing/exceptions.py | 6 +++--- src/octoprint/util/comm.py | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/octoprint/plugin/core.py b/src/octoprint/plugin/core.py index 8a5053724..913289de8 100644 --- a/src/octoprint/plugin/core.py +++ b/src/octoprint/plugin/core.py @@ -1213,15 +1213,15 @@ def on_plugin_disabled(self): class RestartNeedingPlugin(Plugin): pass -class PluginNeedsRestart(BaseException): +class PluginNeedsRestart(Exception): def __init__(self, name): - BaseException.__init__(self) + Exception.__init__(self) self.name = name self.message = "Plugin {name} cannot be enabled or disabled after system startup".format(**locals()) -class PluginLifecycleException(BaseException): +class PluginLifecycleException(Exception): def __init__(self, name, reason, message): - BaseException.__init__(self) + Exception.__init__(self) self.name = name self.reason = reason diff --git a/src/octoprint/printer/__init__.py b/src/octoprint/printer/__init__.py index e0989a936..0a4195da4 100644 --- a/src/octoprint/printer/__init__.py +++ b/src/octoprint/printer/__init__.py @@ -467,6 +467,6 @@ def on_printer_send_current_data(self, data): """ pass -class UnknownScript(BaseException): +class UnknownScript(Exception): def __init__(self, name, *args, **kwargs): self.name = name diff --git a/src/octoprint/server/api/languages.py b/src/octoprint/server/api/languages.py index a3690f741..820089e47 100644 --- a/src/octoprint/server/api/languages.py +++ b/src/octoprint/server/api/languages.py @@ -143,5 +143,5 @@ def _validate_archive_name(name): raise InvalidLanguagePack("Provided language pack contains invalid name {name}".format(**locals())) -class InvalidLanguagePack(BaseException): +class InvalidLanguagePack(Exception): pass diff --git a/src/octoprint/slicing/exceptions.py b/src/octoprint/slicing/exceptions.py index 4d7891073..8a543e9fa 100644 --- a/src/octoprint/slicing/exceptions.py +++ b/src/octoprint/slicing/exceptions.py @@ -33,7 +33,7 @@ __copyright__ = "Copyright (C) 2015 The OctoPrint Project - Released under terms of the AGPLv3 License" -class SlicingException(BaseException): +class SlicingException(Exception): """ Base exception of all slicing related exceptions. """ @@ -73,7 +73,7 @@ def __init__(self, slicer, *args, **kwargs): SlicerException.__init__(self, slicer, *args, **kwargs) self.message = "No such slicer: {slicer}".format(slicer=slicer) -class ProfileException(BaseException): +class ProfileException(Exception): """ Base exception of all slicing profile related exceptions. @@ -86,7 +86,7 @@ class ProfileException(BaseException): Identifier of the profile for which the exception was raised. """ def __init__(self, slicer, profile, *args, **kwargs): - BaseException.__init__(self, *args, **kwargs) + Exception.__init__(self, *args, **kwargs) self.slicer = slicer self.profile = profile diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 14ca4f594..65c99025a 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -1982,9 +1982,9 @@ def _get(self): return item -class TypeAlreadyInQueue(BaseException): +class TypeAlreadyInQueue(Exception): def __init__(self, t, *args, **kwargs): - BaseException.__init__(self, *args, **kwargs) + Exception.__init__(self, *args, **kwargs) self.type = t From 4b110325679fcb8b8ea3da2c0533858862a03223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sun, 28 Jun 2015 02:21:30 +0200 Subject: [PATCH 05/14] Fix: Slicing profiles now can always be set as default Previously depended on the slicer being already configured, which is not really necessary. Closes #956 (cherry picked from commit 13ac06c) --- src/octoprint/server/api/slicing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/octoprint/server/api/slicing.py b/src/octoprint/server/api/slicing.py index d2b254667..7dd80f3bc 100644 --- a/src/octoprint/server/api/slicing.py +++ b/src/octoprint/server/api/slicing.py @@ -57,7 +57,7 @@ def slicingListSlicerProfiles(slicer): @api.route("/slicing//profiles/", methods=["GET"]) def slicingGetSlicerProfile(slicer, name): try: - profile = slicingManager.load_profile(slicer, name) + profile = slicingManager.load_profile(slicer, name, require_configured=False) except UnknownSlicer: return make_response("Unknown slicer {slicer}".format(**locals()), 404) except UnknownProfile: @@ -106,7 +106,7 @@ def slicingPatchSlicerProfile(slicer, name): return make_response("Expected content-type JSON", 400) try: - profile = slicingManager.load_profile(slicer, name) + profile = slicingManager.load_profile(slicer, name, require_configured=False) except UnknownSlicer: return make_response("Unknown slicer {slicer}".format(**locals()), 404) except UnknownProfile: From 4dc9d0a5366238372dc9c384f1d5b1f640bf8f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sun, 28 Jun 2015 16:32:07 +0200 Subject: [PATCH 06/14] Fix: SD card errors shouldn't not cause disconnect If the SD card fails to initialize with a volume.init failure, that's not a reason to break off all diplomatic relations with the printer. (cherry picked from commit 9caf13d) --- src/octoprint/util/comm.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 65c99025a..8dd693327 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -1298,10 +1298,14 @@ def _handleErrors(self, line): if self._regex_minMaxError.match(line): line = line.rstrip() + self._readline() - #Skip the communication errors, as those get corrected. if 'line number' in line.lower() or 'checksum' in line.lower() or 'expected line' in line.lower(): + #Skip the communication errors, as those get corrected. self._lastCommError = line[6:] if line.startswith("Error:") else line[2:] pass + elif 'volume.init' in line.lower() or "openroot" in line.lower() or 'workdir' in line.lower()\ + or "error writing to file" in line.lower(): + #Also skip errors with the SD card + pass elif not self.isError(): self._errorValue = line[6:] if line.startswith("Error:") else line[2:] self._changeState(self.STATE_ERROR) From 016bdd542a660d67a8a5156d5f34de9fe1e31cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 29 Jun 2015 10:13:44 +0200 Subject: [PATCH 07/14] Fix: More flexibility when parsing plugin compatibility If compatibility information is provided only as a version number it's prefixed with >= for the check (so stating a compatibility of only 1.2.0 will now make the plugin compatible to all versions that follow too). Alternatively the compatibility information may now contain stuff like ">=1.2,<1.3" in which case the plugin will only be shown as compatible to OctoPrint versions 1.2 and up but not 1.3 or anything above that. (cherry picked from commit d5692d7) --- .../plugins/pluginmanager/__init__.py | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/octoprint/plugins/pluginmanager/__init__.py b/src/octoprint/plugins/pluginmanager/__init__.py index 152d9b415..ab2287632 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -510,22 +510,46 @@ def map_repository_entry(entry): if "compatibility" in entry: if "octoprint" in entry["compatibility"] and entry["compatibility"]["octoprint"] is not None and len(entry["compatibility"]["octoprint"]): - import semantic_version - for octo_compat in entry["compatibility"]["octoprint"]: - s = semantic_version.Spec("=={}".format(octo_compat)) - if semantic_version.Version(octoprint_version) in s: - break - else: - result["is_compatible"]["octoprint"] = False + result["is_compatible"]["octoprint"] = self._is_octoprint_compatible(octoprint_version, entry["compatibility"]["octoprint"]) if "os" in entry["compatibility"] and entry["compatibility"]["os"] is not None and len(entry["compatibility"]["os"]): - result["is_compatible"]["os"] = current_os in entry["compatibility"]["os"] + result["is_compatible"]["os"] = self._is_os_compatible(current_os, entry["compatibility"]["os"]) return result self._repository_plugins = map(map_repository_entry, repo_data) return True + def _is_octoprint_compatible(self, octoprint_version, compatibility_entries): + """ + Tests if the current ``octoprint_version`` is compatible to any of the provided ``compatibility_entries``. + """ + import semantic_version + + for octo_compat in compatibility_entries: + for version_string in (octo_compat, ">={}".format(octo_compat)): + try: + s = semantic_version.Spec(version_string) + if semantic_version.Version(octoprint_version) in s: + break + except ValueError: + # that just means that octo_compat directly wasn't a valid version spec string, so we try + # prefixing that with ">=" next and check again + pass + else: + continue + break + else: + return False + + return True + + def _is_os_compatible(self, current_os, compatibility_entries): + """ + Tests if the ``current_os`` matches any of the provided ``compatibility_entries``. + """ + return current_os in compatibility_entries + def _get_os(self): if sys.platform == "win32": return "windows" From 1ead6e2d20105e9a2152cf0d08774deb6b0ea296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 29 Jun 2015 10:34:55 +0200 Subject: [PATCH 08/14] Fix: Ensure correct "upload date" for all added files Local file storage implementation will now "touch" added files to set modification date to current date, ensuring that files that are just moved through a custom implementation of file object (e.g. through the watched folder mechanism) will show with "now" as the upload date. (cherry picked from commit 5f0c89c) --- src/octoprint/filemanager/storage.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/octoprint/filemanager/storage.py b/src/octoprint/filemanager/storage.py index 6e855cce6..9f238cf93 100644 --- a/src/octoprint/filemanager/storage.py +++ b/src/octoprint/filemanager/storage.py @@ -455,6 +455,9 @@ def add_file(self, path, file_object, printer_profile=None, links=None, allow_ov self._add_links(name, path, links) + # touch the file to set last access and modification time to now + os.utime(file_path, None) + return self.path_in_storage((path, name)) def remove_file(self, path): From b3e547c60f93734ab7a6b65cc78c79fd8921cbea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 29 Jun 2015 17:39:56 +0200 Subject: [PATCH 09/14] Fix: Don't reload page on search form submits Both file search and plugin repository search reloaded the page when hitting enter in the search field. This fixes that. (cherry picked from commit 60043cc) --- .../plugins/pluginmanager/static/js/pluginmanager.js | 6 +++++- .../pluginmanager/templates/pluginmanager_settings.jinja2 | 2 +- src/octoprint/static/js/app/viewmodels/files.js | 6 +++++- src/octoprint/templates/sidebar/files.jinja2 | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/octoprint/plugins/pluginmanager/static/js/pluginmanager.js b/src/octoprint/plugins/pluginmanager/static/js/pluginmanager.js index 04aa302c4..8d0fb4177 100644 --- a/src/octoprint/plugins/pluginmanager/static/js/pluginmanager.js +++ b/src/octoprint/plugins/pluginmanager/static/js/pluginmanager.js @@ -147,7 +147,11 @@ $(function() { } }); - self.performRepositorySearch = function() { + self.performRepositorySearch = function(e) { + if (e !== undefined) { + e.preventDefault(); + } + var query = self.repositorySearchQuery(); if (query !== undefined && query.trim() != "") { self.repositoryplugins.changeSearchFunction(function(entry) { diff --git a/src/octoprint/plugins/pluginmanager/templates/pluginmanager_settings.jinja2 b/src/octoprint/plugins/pluginmanager/templates/pluginmanager_settings.jinja2 index bc05691e6..559817c06 100644 --- a/src/octoprint/plugins/pluginmanager/templates/pluginmanager_settings.jinja2 +++ b/src/octoprint/plugins/pluginmanager/templates/pluginmanager_settings.jinja2 @@ -83,7 +83,7 @@ - diff --git a/src/octoprint/static/js/app/viewmodels/files.js b/src/octoprint/static/js/app/viewmodels/files.js index 49c2666bb..a5d50f8ba 100644 --- a/src/octoprint/static/js/app/viewmodels/files.js +++ b/src/octoprint/static/js/app/viewmodels/files.js @@ -308,7 +308,11 @@ $(function() { return output; }; - self.performSearch = function() { + self.performSearch = function(e) { + if (e !== undefined) { + e.preventDefault(); + } + var query = self.searchQuery(); if (query !== undefined && query.trim() != "") { self.listHelper.changeSearchFunction(function(entry) { diff --git a/src/octoprint/templates/sidebar/files.jinja2 b/src/octoprint/templates/sidebar/files.jinja2 index 50067e036..66adac4a6 100644 --- a/src/octoprint/templates/sidebar/files.jinja2 +++ b/src/octoprint/templates/sidebar/files.jinja2 @@ -1,4 +1,4 @@ -
From a5b87a9067a1e23e1e5a1a317330dca2d402568e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 29 Jun 2015 17:49:19 +0200 Subject: [PATCH 10/14] Updated changelog --- CHANGELOG.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d754f68e4..8ef6e1c92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,26 @@ ## 1.2.1 (unreleased) +### Improvements + +* More flexibility when interpreting compatibility data from plugin repository. If compatibility information is provided + only as a version number it's prefixed with `>=` for the check (so stating a compatibility of only + `1.2.0` will now make the plugin compatible to OctoPrint 1.2.0+, not only 1.2.0). Alternatively the compatibility + information may now contain stuff like `>=1.2,<1.3` in which case the plugin will only be shown as compatible + to OctoPrint versions 1.2.0 and up but not 1.3.0 or anything above that. See also + [the requirement specification format of the `semantic_version` package](http://python-semanticversion.readthedocs.org/en/latest/#requirement-specification). + ### Bug Fixes -* [IRC] - OctoPrint will now exit cleanly on `SIGTERM`, calling the shutdown functions provided by plugins. - Thanks @Salandora for the heads-up. +* [#956](https://github.com/foosel/OctoPrint/issues/956) - Fixed server crash when trying to configure a default + slicing profile for a still unconfigured slicer. +* [IRC] - Clean exit on `SIGTERM`, calling the shutdown functions provided by plugins. +* [IRC] - No longer reloading the page when the return key is pressed in either the file or the plugin search field. +* Don't disconnect on `volume.init` errors from the firmware. +* `touch` uploaded files on local file storage to ensure proper "uploaded date" even for files that are just moved from + other locations of the file system (e.g. when being added from the `watched` folder). + +([Commits](https://github.com/foosel/OctoPrint/compare/1.2.0...1.2.1)) ## 1.2.0 (2015-06-25) From b8209e8e09d16d883c186d8c564dff14fa4c7abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 29 Jun 2015 18:08:34 +0200 Subject: [PATCH 11/14] Switch to pkg_resources for compatibility check Plugin Manager now internally uses pkg_resources.parse_version and pkg_resources.parse_requirements to check for version compatibility with plugins from the repository. That will allow to directly use the OctoPrint version string once it's PEP440 compatible. (cherry picked from commit 8eb61a9) --- .../plugins/pluginmanager/__init__.py | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/octoprint/plugins/pluginmanager/__init__.py b/src/octoprint/plugins/pluginmanager/__init__.py index ab2287632..fe5737133 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -520,25 +520,19 @@ def map_repository_entry(entry): self._repository_plugins = map(map_repository_entry, repo_data) return True - def _is_octoprint_compatible(self, octoprint_version, compatibility_entries): + def _is_octoprint_compatible(self, octoprint_version_string, compatibility_entries): """ Tests if the current ``octoprint_version`` is compatible to any of the provided ``compatibility_entries``. """ - import semantic_version + octoprint_version = pkg_resources.parse_version(octoprint_version_string) for octo_compat in compatibility_entries: - for version_string in (octo_compat, ">={}".format(octo_compat)): - try: - s = semantic_version.Spec(version_string) - if semantic_version.Version(octoprint_version) in s: - break - except ValueError: - # that just means that octo_compat directly wasn't a valid version spec string, so we try - # prefixing that with ">=" next and check again - pass - else: - continue - break + if not any(octo_compat.startswith(c) for c in ("<", "<=", "!=", "==", ">=", ">", "~=", "===")): + octo_compat = ">={}".format(octo_compat) + + s = next(pkg_resources.parse_requirements("OctoPrint" + octo_compat)) + if octoprint_version in s: + break else: return False From bb0bfaee56377bc504339428c7bc07a2118ee40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 29 Jun 2015 20:59:46 +0200 Subject: [PATCH 12/14] Fix: Increase max body size for plugin archives Closes #957 (cherry picked from commit af89097) --- src/octoprint/plugins/pluginmanager/__init__.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/octoprint/plugins/pluginmanager/__init__.py b/src/octoprint/plugins/pluginmanager/__init__.py index fe5737133..6c4e039b0 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -55,6 +55,12 @@ def initialize(self): self._pip_caller.on_log_stdout = self._log_stdout self._pip_caller.on_log_stderr = self._log_stderr + ##~~ Body size hook + + def increase_upload_bodysize(self, current_max_body_sizes, *args, **kwargs): + # set a maximum body size of 50 MB for plugin archive uploads + return [("POST", r"/upload_archive", 50 * 1024 * 1024)] + ##~~ StartupPlugin def on_startup(self, host, port): @@ -580,4 +586,12 @@ def _to_external_representation(self, plugin): __plugin_url__ = "https://github.com/foosel/OctoPrint/wiki/Plugin:-Plugin-Manager" __plugin_description__ = "Allows installing and managing OctoPrint plugins" __plugin_license__ = "AGPLv3" -__plugin_implementation__ = PluginManagerPlugin() + +def __plugin_load__(): + global __plugin_implementation__ + __plugin_implementation__ = PluginManagerPlugin() + + global __plugin_hooks__ + __plugin_hooks__ = { + "octoprint.server.http.bodysize": __plugin_implementation__.increase_upload_bodysize + } From 2a8eea086c7cb25fc2d09a22799e1f7dd0ad690e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Mon, 29 Jun 2015 20:54:13 +0200 Subject: [PATCH 13/14] Only print command of event handler to log when debug flag is present (cherry picked from commit 49d28c5) --- docs/configuration/config_yaml.rst | 21 +++++++++++++++++++++ src/octoprint/events.py | 27 ++++++++++++++------------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/docs/configuration/config_yaml.rst b/docs/configuration/config_yaml.rst index f698a3ba8..15cfbbbf4 100644 --- a/docs/configuration/config_yaml.rst +++ b/docs/configuration/config_yaml.rst @@ -366,6 +366,27 @@ Use the following settings to add shell/gcode commands to be executed on certain type: gcode enabled: False +.. note:: + + For debugging purposes, you can also add an additional property ``debug`` to your event subscription definitions + that if set to true will make the event handler print a log line with your subscription's command after performing + all placeholder replacements. Example: + + .. code-block:: yaml + + events: + subscriptions: + - event: Startup + command: "logger 'OctoPrint started up'" + type: system + debug: true + + This will be logged in OctoPrint's logfile as + + .. code-block:: none + + Executing System Command: logger 'OctoPrint started up' + .. _sec-configuration-config_yaml-feature: Feature diff --git a/src/octoprint/events.py b/src/octoprint/events.py index cbcbf3b82..a26a48e8f 100644 --- a/src/octoprint/events.py +++ b/src/octoprint/events.py @@ -254,10 +254,11 @@ def _initSubscriptions(self): event = subscription["event"] command = subscription["command"] commandType = subscription["type"] + debug = subscription["debug"] if "debug" in subscription else False if not event in self._subscriptions.keys(): self._subscriptions[event] = [] - self._subscriptions[event].append((command, commandType)) + self._subscriptions[event].append((command, commandType, debug)) if not event in eventsToSubscribe: eventsToSubscribe.append(event) @@ -275,7 +276,7 @@ def eventCallback(self, event, payload): if not event in self._subscriptions: return - for command, commandType in self._subscriptions[event]: + for command, commandType, debug in self._subscriptions[event]: try: if isinstance(command, (tuple, list, set)): processedCommand = [] @@ -283,19 +284,20 @@ def eventCallback(self, event, payload): processedCommand.append(self._processCommand(c, payload)) else: processedCommand = self._processCommand(command, payload) - self.executeCommand(processedCommand, commandType) + self.executeCommand(processedCommand, commandType, debug=debug) except KeyError, e: self._logger.warn("There was an error processing one or more placeholders in the following command: %s" % command) - def executeCommand(self, command, commandType): + def executeCommand(self, command, commandType, debug=False): if commandType == "system": - self._executeSystemCommand(command) + self._executeSystemCommand(command, debug=debug) elif commandType == "gcode": - self._executeGcodeCommand(command) + self._executeGcodeCommand(command, debug=debug) - def _executeSystemCommand(self, command): + def _executeSystemCommand(self, command, debug=False): def commandExecutioner(command): - self._logger.info("Executing system command: %s" % command) + if debug: + self._logger.info("Executing system command: %s" % command) subprocess.Popen(command, shell=True) try: @@ -306,16 +308,15 @@ def commandExecutioner(command): commandExecutioner(command) except subprocess.CalledProcessError, e: self._logger.warn("Command failed with return code %i: %s" % (e.returncode, str(e))) - except Exception, ex: + except: self._logger.exception("Command failed") - def _executeGcodeCommand(self, command): + def _executeGcodeCommand(self, command, debug=False): commands = [command] if isinstance(command, (list, tuple, set)): - self._logger.debug("Executing GCode commands: %r" % command) commands = list(command) - else: - self._logger.debug("Executing GCode command: %s" % command) + if debug: + self._logger.info("Executing GCode commands: %r" % command) self._printer.commands(commands) def _processCommand(self, command, payload): From 9f8d30a66c2fcc5cd0e8984c72dc36f7e84fde10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Tue, 30 Jun 2015 08:42:16 +0200 Subject: [PATCH 14/14] Preparing release of 1.2.1 --- CHANGELOG.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ef6e1c92..b565dcb17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # OctoPrint Changelog -## 1.2.1 (unreleased) +## 1.2.1 (2015-06-30) ### Improvements @@ -9,17 +9,20 @@ `1.2.0` will now make the plugin compatible to OctoPrint 1.2.0+, not only 1.2.0). Alternatively the compatibility information may now contain stuff like `>=1.2,<1.3` in which case the plugin will only be shown as compatible to OctoPrint versions 1.2.0 and up but not 1.3.0 or anything above that. See also - [the requirement specification format of the `semantic_version` package](http://python-semanticversion.readthedocs.org/en/latest/#requirement-specification). + [the requirement specification format of the `pkg_resources` package](https://pythonhosted.org/setuptools/pkg_resources.html#requirements-parsing). +* Only print the commands of configured event handlers to the log when a new `debug` flag is present in the config + (see [the docs](http://docs.octoprint.org/en/master/configuration/config_yaml.html#events)). Reduces risk of disclosing sensitive data when sharing log files. ### Bug Fixes * [#956](https://github.com/foosel/OctoPrint/issues/956) - Fixed server crash when trying to configure a default slicing profile for a still unconfigured slicer. -* [IRC] - Clean exit on `SIGTERM`, calling the shutdown functions provided by plugins. -* [IRC] - No longer reloading the page when the return key is pressed in either the file or the plugin search field. -* Don't disconnect on `volume.init` errors from the firmware. -* `touch` uploaded files on local file storage to ensure proper "uploaded date" even for files that are just moved from - other locations of the file system (e.g. when being added from the `watched` folder). +* [#957](https://github.com/foosel/OctoPrint/issues/957) - Increased maximum allowed body size for plugin archive uploads. +* Bugs without tickets: + * Clean exit on `SIGTERM`, calling the shutdown functions provided by plugins. + * Don't disconnect on `volume.init` errors from the firmware. + * `touch` uploaded files on local file storage to ensure proper "uploaded date" even for files that are just moved + from other locations of the file system (e.g. when being added from the `watched` folder). ([Commits](https://github.com/foosel/OctoPrint/compare/1.2.0...1.2.1))