PluginManager now marks plugins as managable

Managable currently pretty much only means "uninstallable".

Plugins are managable if their installation location is writable
and - if they are installed from an entry point and OctoPrint is
running in a virtual environment - within the bounds of the virtual
environment (because otherwise pip will not allow to uninstall).
This commit is contained in:
Gina Häußge 2015-09-30 13:28:58 +02:00
parent 7c5fe46f4a
commit 10db8c9577

View file

@ -133,6 +133,7 @@ class PluginInfo(object):
self.enabled = True
self.bundled = False
self.loaded = False
self.managable = True
self._name = name
self._version = version
@ -475,8 +476,25 @@ class PluginManager(object):
self.marked_plugins = defaultdict(list)
self._python_install_dir = None
self._python_virtual_env = False
self._detect_python_environment()
self.reload_plugins(startup=True, initialize_implementations=False)
def _detect_python_environment(self):
from distutils.command.install import install as cmd_install
from distutils.dist import Distribution
import sys
cmd = cmd_install(Distribution())
cmd.finalize_options()
self._python_install_dir = cmd.install_lib
self._python_prefix = sys.prefix
self._python_virtual_env = hasattr(sys, "real_prefix") \
or (hasattr(sys, "base_prefix") and sys.prefix != sys.base_prefix)
@property
def plugins(self):
plugins = dict(self.enabled_plugins)
@ -503,12 +521,13 @@ class PluginManager(object):
result = dict()
for folder in folders:
readonly = False
flagged_readonly = False
if isinstance(folder, (list, tuple)):
if len(folder) == 2:
folder, readonly = folder
folder, flagged_readonly = folder
else:
continue
actual_readonly = not os.access(folder, os.W_OK)
if not os.path.exists(folder):
self.logger.warn("Plugin folder {folder} could not be found, skipping it".format(folder=folder))
@ -531,8 +550,8 @@ class PluginManager(object):
plugin = self._import_plugin_from_module(key, folder=folder)
if plugin:
plugin.origin = FolderOrigin("folder", folder)
if readonly:
plugin.bundled = True
plugin.managable = not flagged_readonly and not actual_readonly
plugin.bundled = flagged_readonly
plugin.enabled = False
@ -578,6 +597,16 @@ class PluginManager(object):
plugin = self._import_plugin_from_module(key, **kwargs)
if plugin:
plugin.origin = EntryPointOrigin("entry_point", group, module_name, package_name, version)
# plugin is manageable if its location is writable and OctoPrint
# is either not running from a virtual env or the plugin is
# installed in that virtual env - the virtual env's pip will not
# allow us to uninstall stuff that is installed outside
# of the virtual env, so this check is necessary
plugin.managable = os.access(plugin.location, os.W_OK) \
and (not self._python_virtual_env
or plugin.location.startswith(self._python_prefix))
plugin.enabled = False
result[key] = plugin