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/15] 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 8e1218d7..6f4c4d68 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/15] 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 6f4c4d68..0e9ab0a0 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/15] 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 fe57f3e8..d754f68e 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 8426628f..35586d1d 100644 --- a/src/octoprint/server/__init__.py +++ b/src/octoprint/server/__init__.py @@ -20,6 +20,7 @@ import os import logging import logging.config import atexit +import signal SUCCESS = {} NO_CONTENT = ("", 204) @@ -440,16 +441,27 @@ class Server(): # 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/15] 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 8a505372..913289de 100644 --- a/src/octoprint/plugin/core.py +++ b/src/octoprint/plugin/core.py @@ -1213,15 +1213,15 @@ class Plugin(object): 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 e0989a93..0a4195da 100644 --- a/src/octoprint/printer/__init__.py +++ b/src/octoprint/printer/__init__.py @@ -467,6 +467,6 @@ class PrinterCallback(object): """ 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 a3690f74..820089e4 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 4d789107..8a543e9f 100644 --- a/src/octoprint/slicing/exceptions.py +++ b/src/octoprint/slicing/exceptions.py @@ -33,7 +33,7 @@ __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agp __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 @@ class UnknownSlicer(SlicerException): 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 14ca4f59..65c99025 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -1982,9 +1982,9 @@ class TypedQueue(queue.Queue): 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/15] 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 d2b25466..7dd80f3b 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/15] 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 65c99025..8dd69332 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -1298,10 +1298,14 @@ class MachineCom(object): 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/15] 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 152d9b41..ab228763 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -510,22 +510,46 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin, 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/15] 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 6e855cce..9f238cf9 100644 --- a/src/octoprint/filemanager/storage.py +++ b/src/octoprint/filemanager/storage.py @@ -455,6 +455,9 @@ class LocalFileStorage(StorageInterface): 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/15] 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 04aa302c..8d0fb417 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 bc05691e..559817c0 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 49c2666b..a5d50f8b 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 50067e03..66adac4a 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/15] Updated changelog --- CHANGELOG.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d754f68e..8ef6e1c9 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/15] 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 ab228763..fe573713 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -520,25 +520,19 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin, 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/15] 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 fe573713..6c4e039b 100644 --- a/src/octoprint/plugins/pluginmanager/__init__.py +++ b/src/octoprint/plugins/pluginmanager/__init__.py @@ -55,6 +55,12 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin, 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 @@ __plugin_author__ = "Gina Häußge" __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/15] 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 f698a3ba..15cfbbbf 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 cbcbf3b8..a26a48e8 100644 --- a/src/octoprint/events.py +++ b/src/octoprint/events.py @@ -254,10 +254,11 @@ class CommandTrigger(GenericEventListener): 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 @@ class CommandTrigger(GenericEventListener): 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 @@ class CommandTrigger(GenericEventListener): 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 @@ class CommandTrigger(GenericEventListener): 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/15] 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 8ef6e1c9..b565dcb1 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)) From 0b3f94b6bd30474718e91c09051027940ee194af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Tue, 30 Jun 2015 10:11:17 +0200 Subject: [PATCH 15/15] maintenance branch is now 1.2.2-dev --- .versioneer-lookup | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.versioneer-lookup b/.versioneer-lookup index 0e9ab0a0..dd26fce5 100644 --- a/.versioneer-lookup +++ b/.versioneer-lookup @@ -10,10 +10,10 @@ # master shall not use the lookup table, only tags master -# maintenance is currently the branch for preparation of maintenance release 1.2.1 +# maintenance is currently the branch for preparation of maintenance release 1.2.2 # so are any fix/... branches -maintenance 1.2.1-dev cfa4cb2a7c5f1af10dc8 -fix/.* 1.2.1-dev cfa4cb2a7c5f1af10dc8 +maintenance 1.2.2-dev 9f8d30a66c2fcc5cd0e8984c72dc36f7e84fde10 +fix/.* 1.2.2-dev 9f8d30a66c2fcc5cd0e8984c72dc36f7e84fde10 # every other branch is a development branch and thus gets resolved to 1.3.0-dev for now .* 1.3.0-dev 198d3450d94be1a2