Skip to content

Commit 76619fd

Browse files
committed
🎉 Initial commit
0 parents  commit 76619fd

File tree

18 files changed

+1767
-0
lines changed

18 files changed

+1767
-0
lines changed

.editorconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# This file is for unifying the coding style for different editors and IDEs
2+
# editorconfig.org
3+
4+
root = true
5+
6+
[*]
7+
end_of_line = lf
8+
charset = utf-8
9+
insert_final_newline = true
10+
trim_trailing_whitespace = true
11+
12+
[**.py]
13+
indent_style = tab
14+
15+
[**.js]
16+
indent_style = space
17+
indent_size = 4

.github/workflows/ci-cd-pipeline.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: CI/CD pipeline
2+
on:
3+
push:
4+
branches:
5+
- master
6+
release:
7+
types: [published, prereleased]
8+
9+
jobs:
10+
build:
11+
name: 🔨 Build distribution
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
- name: 🏗 Set up Python 3.7
16+
uses: actions/setup-python@v1
17+
with:
18+
python-version: 3.7
19+
- name: 🏗 Install build dependencies
20+
run: >-
21+
python -m pip install wheel --user
22+
- name: 🔨 Build a binary wheel and a source tarball
23+
run: >-
24+
python setup.py sdist bdist_wheel
25+
- name: ⬆ Upload build result
26+
uses: actions/upload-artifact@v1
27+
with:
28+
name: dist
29+
path: dist
30+
31+
publish-on-testpypi:
32+
name: 📦 Publish on TestPyPI
33+
if: github.event_name == 'push'
34+
needs: build
35+
runs-on: ubuntu-latest
36+
steps:
37+
- name: ⬇ Download build result
38+
uses: actions/download-artifact@v1
39+
with:
40+
name: dist
41+
path: dist
42+
- name: 📦 Publish to index
43+
uses: pypa/gh-action-pypi-publish@master
44+
continue-on-error: true
45+
with:
46+
password: ${{ secrets.testpypi_password }}
47+
repository_url: https://test.pypi.org/legacy/
48+
49+
publish-on-pypi:
50+
name: 📦 Publish tagged releases to PyPI
51+
if: github.event_name == 'release'
52+
needs: build
53+
runs-on: ubuntu-latest
54+
steps:
55+
- name: ⬇ Download build result
56+
uses: actions/download-artifact@v1
57+
with:
58+
name: dist
59+
path: dist
60+
- name: 📦 Publish to index
61+
uses: pypa/gh-action-pypi-publish@master
62+
with:
63+
password: ${{ secrets.pypi_password }}

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.pyc
2+
*.swp
3+
.idea
4+
*.iml
5+
build
6+
dist
7+
*.egg*
8+
.DS_Store
9+
*.zip

LICENSE

Lines changed: 661 additions & 0 deletions
Large diffs are not rendered by default.

MANIFEST.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include README.md
2+
recursive-include octoprint_file_check/templates *
3+
recursive-include octoprint_file_check/translations *
4+
recursive-include octoprint_file_check/static *

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# File Check
2+
3+
The File Check plugin tries to detect common issues in uploaded files that are known to cause
4+
issues while printing and which in the past have caused support requests on OctoPrint's Community
5+
Forums.
6+
7+
![Screenshot](https://raw.githubusercontent.com/OctoPrint/OctoPrint-FileCheck/master/extras/screenshot.png)
8+
9+
It currently detects and warns about the following issues:
10+
11+
* Outdated placeholder `{travel_speed}` left in the GCODE generated by the slicer. See
12+
[here](https://faq.octoprint.org/file-check-travel-speed) for details on this.
13+
14+
## Setup
15+
16+
The plugin is part of the core dependencies of OctoPrint 1.4.1+ and will be installed automatically alongside it.
17+
18+
In case you want to manually install it into an older version for whatever reason, install via the bundled
19+
[Plugin Manager](https://docs.octoprint.org/en/master/bundledplugins/pluginmanager.html)
20+
or manually using this URL:
21+
22+
https://github.com/OctoPrint/OctoPrint-GcodeValidator/archive/master.zip

babel.cfg

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[python: */**.py]
2+
[jinja2: */**.jinja2]
3+
extensions=jinja2.ext.autoescape, jinja2.ext.with_
4+
5+
[javascript: */**.js]
6+
extract_messages = gettext, ngettext

extras/screenshot.png

20.9 KB
Loading

octoprint_file_check/__init__.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# -*- coding: utf-8 -*-
2+
from __future__ import absolute_import, division, print_function, unicode_literals
3+
4+
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
5+
__copyright__ = "Copyright (C) 2020 The OctoPrint Project - Released under terms of the AGPLv3 License"
6+
7+
import octoprint.plugin
8+
import octoprint.events
9+
10+
import sarge
11+
import io
12+
import re
13+
14+
from flask_babel import gettext
15+
16+
# noinspection PyCompatibility
17+
from concurrent.futures import ThreadPoolExecutor
18+
19+
class FileCheckPlugin(octoprint.plugin.AssetPlugin,
20+
octoprint.plugin.EventHandlerPlugin):
21+
def __init__(self):
22+
self._executor = ThreadPoolExecutor()
23+
24+
##~~ AssetPlugin API
25+
26+
def get_assets(self):
27+
return dict(js=("js/file_check.js",))
28+
29+
##~~ EventHandlerPlugin API
30+
31+
def on_event(self, event, payload):
32+
if event == octoprint.events.Events.FILE_ADDED:
33+
self._executor.submit(self._validate_file, payload["storage"], payload["path"], payload["type"])
34+
35+
##~~ SoftwareUpdate hook
36+
37+
def get_update_information(self):
38+
return dict(
39+
file_check=dict(
40+
displayName="File Check Plugin",
41+
displayVersion=self._plugin_version,
42+
43+
# version check: github repository
44+
type="github_release",
45+
user="OctoPrint",
46+
repo="OctoPrint-FileCheck",
47+
current=self._plugin_version,
48+
49+
# update method: pip
50+
pip="https://github.com/OctoPrint/OctoPrint-FileCheck/archive/{target_version}.zip"
51+
)
52+
)
53+
54+
##~~ Internal logic & helpers
55+
56+
def _validate_file(self, storage, path, file_type):
57+
try:
58+
path_on_disk = self._file_manager.path_on_disk(storage, path)
59+
except NotImplementedError:
60+
# storage doesn't support path_on_disk, ignore
61+
return
62+
63+
if file_type[-1] == "gcode":
64+
if self._search_through_file(path_on_disk, "{travel_speed}"):
65+
self._notify("travel_speed", storage, path)
66+
67+
def _search_through_file(self, path, term):
68+
try:
69+
# try native grep
70+
result = sarge.run(["grep", "-q", re.escape(term), path])
71+
return result.returncode == 0
72+
except ValueError as exc:
73+
if 'Command not found' in str(exc):
74+
try:
75+
# try python only approach
76+
with io.open(path, mode="r", encoding="utf8", errors="replace") as f:
77+
for line in f:
78+
if term in line:
79+
return True
80+
return False
81+
except:
82+
self._logger.exception("Something unexpectedly went wrong while trying to "
83+
"search for {} in {} via native python".format(term, path))
84+
else:
85+
self._logger.exception("Something unexpectedly went wrong while trying to "
86+
"search for {} in {} via grep".format(term, path))
87+
88+
return False
89+
90+
def _notify(self, notification_type, storage, path):
91+
self._logger.warning("File check identified an issue: {} for {}:{}, see "
92+
"https://faq.octoprint.org/file-check-{} for details".format(notification_type,
93+
storage,
94+
path,
95+
notification_type.replace("_", "-")))
96+
self._plugin_manager.send_plugin_message(self._identifier, dict(type=notification_type,
97+
storage=storage,
98+
path=path))
99+
100+
101+
__plugin_name__ = "File Check"
102+
__plugin_pycompat__ = ">2.7,<4"
103+
__plugin_disabling_discouraged__ = gettext("Without this plugin OctoPrint will no longer be able to "
104+
"check if uploaded files contain common problems and inform you "
105+
"about that fact.")
106+
107+
__plugin_implementation__ = FileCheckPlugin()
108+
__plugin_hooks__ = {
109+
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
110+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* View model for OctoPrint-FileCheck
3+
*
4+
* Author: Gina Häußge
5+
* License: AGPLv3
6+
*/
7+
$(function() {
8+
function FileCheckViewModel(parameters) {
9+
var self = this;
10+
11+
var issues = {
12+
travel_speed: gettext("Your sliced file still contains a place holder <code>{travel_speed}</code>. "
13+
+ "This is a common issue when using old start/stop GCODE code snippets in current versions of "
14+
+ "Cura, as the placeholder name switched to <code>{speed_travel}</code> at some point and "
15+
+ "no longer gets replaced in current versions. You need to fix this in your slicer and reslice "
16+
+ "your file, do not print it like it is as it will cause issues!")
17+
}
18+
19+
self.onDataUpdaterPluginMessage = function(plugin, data) {
20+
if (plugin !== "file_check") {
21+
return;
22+
}
23+
24+
var message = issues[data["type"]];
25+
if (!message) {
26+
return;
27+
}
28+
29+
var faq = "<a href='https://faq.octoprint.org/file-check-"
30+
+ data["type"].replace("_", "-") + "' target='_blank' rel='noreferrer noopener'>"
31+
+ gettext("Read more...") + "</a>";
32+
33+
new PNotify({
34+
title: _.sprintf(gettext('File Check detected issues with %(storage)s:%(path)s!'), data),
35+
text: "<p>" + message + "</p><p>" + faq + "</p>",
36+
hide: false
37+
});
38+
}
39+
}
40+
41+
OCTOPRINT_VIEWMODELS.push({
42+
construct: FileCheckViewModel
43+
});
44+
});

0 commit comments

Comments
 (0)