From a0105bcb2fc5e08dc98b633470c6ca6028345cab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Tue, 1 Apr 2014 20:40:55 +0200 Subject: [PATCH 1/4] Better error handling for capture issues during timelapsing Should help debugging issue #425 and any future problems in that area. (cherry picked from commit 1a7a468) --- src/octoprint/timelapse.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/octoprint/timelapse.py b/src/octoprint/timelapse.py index 2c3b2c82..3a3ad906 100644 --- a/src/octoprint/timelapse.py +++ b/src/octoprint/timelapse.py @@ -236,10 +236,13 @@ class Timelapse(object): return filename def _captureWorker(self, filename): - eventManager().fire(Events.CAPTURE_START, {"file": filename}); - urllib.urlretrieve(self._snapshotUrl, filename) - self._logger.debug("Image %s captured from %s" % (filename, self._snapshotUrl)) - eventManager().fire(Events.CAPTURE_DONE, {"file": filename}); + eventManager().fire(Events.CAPTURE_START, {"file": filename}) + try: + urllib.urlretrieve(self._snapshotUrl, filename) + self._logger.debug("Image %s captured from %s" % (filename, self._snapshotUrl)) + except: + self._logger.exception("Could not capture image %s from %s" % (filename, self._snapshotUrl)) + eventManager().fire(Events.CAPTURE_DONE, {"file": filename}) def _createMovie(self, success=True): ffmpeg = settings().get(["webcam", "ffmpeg"]) From fb1575170317c3ab96fc4f613a7ffa8cf20a2891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Tue, 1 Apr 2014 22:32:10 +0200 Subject: [PATCH 2/4] Decrease image counter if an image could not be captured from webcam Should keep rendering of timelapse from breaking if only a couple of images couldn't be captured due to whatever reason. Suggested by @midopple in #344 (cherry picked from commit bf9d5ef) --- src/octoprint/timelapse.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/octoprint/timelapse.py b/src/octoprint/timelapse.py index 3a3ad906..5474a4d3 100644 --- a/src/octoprint/timelapse.py +++ b/src/octoprint/timelapse.py @@ -241,7 +241,8 @@ class Timelapse(object): urllib.urlretrieve(self._snapshotUrl, filename) self._logger.debug("Image %s captured from %s" % (filename, self._snapshotUrl)) except: - self._logger.exception("Could not capture image %s from %s" % (filename, self._snapshotUrl)) + self._logger.exception("Could not capture image %s from %s, decreasing image counter again" % (filename, self._snapshotUrl)) + self._imageNumber -= 1 eventManager().fire(Events.CAPTURE_DONE, {"file": filename}) def _createMovie(self, success=True): From 51341f6722f99b7909dc07fdd386fe2662bc502b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Tue, 4 Nov 2014 10:36:35 +0100 Subject: [PATCH 3/4] Added removal of pyc files (and their parent folders if they are empty after that) to the python setup.py clean command (cherry picked from commit 9e014eb) --- setup.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/setup.py b/setup.py index d06296ea..b09d8352 100644 --- a/setup.py +++ b/setup.py @@ -27,6 +27,26 @@ def package_data_dirs(source, sub_folders): return dirs +def _recursively_handle_files(directory, file_matcher, folder_handler=None, file_handler=None): + applied_handler = False + + for filename in os.listdir(directory): + path = os.path.join(directory, filename) + + if file_handler is not None and file_matcher(filename): + file_handler(path) + applied_handler = True + + elif os.path.isdir(path): + sub_applied_handler = _recursively_handle_files(path, file_matcher, folder_handler=folder_handler, file_handler=file_handler) + if sub_applied_handler: + applied_handler = True + + if folder_handler is not None: + folder_handler(path, sub_applied_handler) + + return applied_handler + class CleanCommand(Command): description = "clean build artifacts" user_options = [] @@ -39,14 +59,37 @@ class CleanCommand(Command): pass def run(self): + # build folder if os.path.exists('build'): print "Deleting build directory" shutil.rmtree('build') + + # eggs eggs = glob.glob('OctoPrint*.egg-info') for egg in eggs: print "Deleting %s directory" % egg shutil.rmtree(egg) + # pyc files + def delete_folder_if_empty(path, applied_handler): + if not applied_handler: + return + if len(os.listdir(path)) == 0: + shutil.rmtree(path) + print "Deleted %s since it was empty" % path + + def delete_file(path): + os.remove(path) + print "Deleted %s" % path + + import fnmatch + _recursively_handle_files( + os.path.abspath("src"), + lambda name: fnmatch.fnmatch(name.lower(), "*.pyc"), + folder_handler=delete_folder_if_empty, + file_handler=delete_file + ) + def get_cmdclass(): cmdclass = versioneer.get_cmdclass() From a30e41f0b42c51c9943b73492ee3aef8346f46d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Sun, 28 Dec 2014 00:12:19 +0100 Subject: [PATCH 4/4] Timelapses: Do not try to use image counter if still set to None and synchronize decrementing of image counter via mutex as well Possible fixes for #693, the latter maybe also for #690 --- CHANGELOG.md | 12 ++++++++++++ src/octoprint/timelapse.py | 9 +++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58e4a7c5..e12f3ae8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,23 @@ ## 1.1.2 (Unreleased) +### Improvements + +* Added deletion of `*.pyc` files to `python setup.py clean` command, should help tremendously when switching branches (backported + from [9e014eb](https://github.com/foosel/OctoPrint/commit/9e014eba1feffde11ed0601d9c911b8cac9f3fb0)) + ### Bug Fixes * [#634](https://github.com/foosel/OctoPrint/pull/634) - Fixed missing `branch` fields in version dicts generated by versioneer * [IRC] Don't hiccup on slic3r filament_diameter comments generated for multi extruder setups +* Small fixes for timelapse creation: + - [#344](https://github.com/foosel/OctoPrint/issues/344) - Made timelapses capable of coping with missing captures in between by decrementing the image counter again if there + was an error fetching the latest image from the snapshot URL (backport of [1a7a468](https://github.com/foosel/OctoPrint/commit/1a7a468eb65fdf2a13b4c7a7723280e822c9c34b) + and [bf9d5ef](https://github.com/foosel/OctoPrint/commit/bf9d5efe43a1e57aacd8512125082ddca06b4efc)) + - [#693](https://github.com/foosel/OctoPrint/issues/693) - Try not to capture an image if image counter is still unset + - [unreported] Synchronize image counter decrementing as well as incrementing to prevent rare race conditions when generating the + image file names ## 1.1.1 (2014-10-27) diff --git a/src/octoprint/timelapse.py b/src/octoprint/timelapse.py index 5474a4d3..c27fb1a9 100644 --- a/src/octoprint/timelapse.py +++ b/src/octoprint/timelapse.py @@ -226,8 +226,12 @@ class Timelapse(object): self._logger.warn("Cannot capture image, capture directory is unset") return + if self._imageNumber is None: + self._logger.warn("Cannot capture image, image number is unset") + return + with self._captureMutex: - filename = os.path.join(self._captureDir, "tmp_%05d.jpg" % (self._imageNumber)) + filename = os.path.join(self._captureDir, "tmp_%05d.jpg" % self._imageNumber) self._imageNumber += 1 self._logger.debug("Capturing image to %s" % filename) captureThread = threading.Thread(target=self._captureWorker, kwargs={"filename": filename}) @@ -242,7 +246,8 @@ class Timelapse(object): self._logger.debug("Image %s captured from %s" % (filename, self._snapshotUrl)) except: self._logger.exception("Could not capture image %s from %s, decreasing image counter again" % (filename, self._snapshotUrl)) - self._imageNumber -= 1 + with self._captureMutex: + self._imageNumber -= 1 eventManager().fire(Events.CAPTURE_DONE, {"file": filename}) def _createMovie(self, success=True):