Fix: More resilience against missing plugin assets

Two changes:

  * Asset existence will now be checked before they get included
    in the assets to bundle by webassets, logging a warning if a
    file isn't present.
  * Monkey-patched webassets filter chain to not die when a file
    doesn't exist, but to log an error instead and just return
    an empty file instead.
This commit is contained in:
Gina Häußge 2015-07-08 16:26:08 +02:00
parent 377607cf12
commit 2a5ec3364e
2 changed files with 48 additions and 0 deletions

View file

@ -544,6 +544,9 @@ class Server():
},
"tornado.general": {
"level": "INFO"
},
"octoprint.server.util.flask": {
"level": "WARN"
}
},
"root": {
@ -712,6 +715,7 @@ class Server():
global pluginManager
util.flask.fix_webassets_cache()
util.flask.fix_webassets_filtertool()
base_folder = settings().getBaseFolder("generated")

View file

@ -19,6 +19,7 @@ import uuid
import threading
import logging
import netaddr
import os
from octoprint.settings import settings
import octoprint.server
@ -174,6 +175,34 @@ def fix_webassets_cache():
cache.FilesystemCache.set = fixed_set
cache.FilesystemCache.get = fixed_get
def fix_webassets_filtertool():
from webassets.merge import FilterTool, log, MemoryHunk
error_logger = logging.getLogger(__name__ + ".fix_webassets_filtertool")
def fixed_wrap_cache(self, key, func):
"""Return cache value ``key``, or run ``func``.
"""
if self.cache:
if not self.no_cache_read:
log.debug('Checking cache for key %s', key)
content = self.cache.get(key)
if not content in (False, None):
log.debug('Using cached result for %s', key)
return MemoryHunk(content)
try:
content = func().getvalue()
if self.cache:
log.debug('Storing result in cache with key %s', key,)
self.cache.set(key, content)
return MemoryHunk(content)
except:
error_logger.exception("Got an exception while trying to apply filter, ignoring file")
return MemoryHunk("")
FilterTool._wrap_cache = fixed_wrap_cache
#~~ passive login helper
def passive_login():
@ -535,6 +564,8 @@ class SettingsCheckUpdater(webassets.updater.BaseUpdater):
##~~ plugin assets collector
def collect_plugin_assets(enable_gcodeviewer=True, enable_timelapse=True, preferred_stylesheet="css"):
logger = logging.getLogger(__name__ + ".collect_plugin_assets")
supported_stylesheets = ("css", "less")
assets = dict(
js=[],
@ -578,13 +609,24 @@ def collect_plugin_assets(enable_gcodeviewer=True, enable_timelapse=True, prefer
for implementation in asset_plugins:
name = implementation._identifier
all_assets = implementation.get_assets()
basefolder = implementation.get_asset_folder()
def asset_exists(category, asset):
exists = os.path.exists(os.path.join(basefolder, asset))
if not exists:
logger.warn("Plugin {} is referring to non existing {} asset {}".format(name, category, asset))
return exists
if "js" in all_assets:
for asset in all_assets["js"]:
if not asset_exists("js", asset):
continue
assets["js"].append('plugin/{name}/{asset}'.format(**locals()))
if preferred_stylesheet in all_assets:
for asset in all_assets[preferred_stylesheet]:
if not asset_exists(preferred_stylesheet, asset):
continue
assets[preferred_stylesheet].append('plugin/{name}/{asset}'.format(**locals()))
else:
for stylesheet in supported_stylesheets:
@ -592,6 +634,8 @@ def collect_plugin_assets(enable_gcodeviewer=True, enable_timelapse=True, prefer
continue
for asset in all_assets[stylesheet]:
if not asset_exists(stylesheet, asset):
continue
assets[stylesheet].append('plugin/{name}/{asset}'.format(**locals()))
break