Skip to content

Commit

Permalink
Merge deprecated 'pythonalgorithms.directories' key with new key...
Browse files Browse the repository at this point in the history
automatically and add old plugin location to base python.plugins key.
Avoids users seeing confusing warnings.
Refs #7103
  • Loading branch information
martyngigg committed May 16, 2013
1 parent fb30a48 commit 2876f29
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 48 deletions.
2 changes: 1 addition & 1 deletion Code/Mantid/Framework/Kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ endif ()

set ( PLUGINS ${MANTID_ROOT}/plugins )
set ( PYTHONALG_DIRS ${PLUGINS}/PythonAlgs ) # deprecated
set ( PYTHONPLUGIN_DIRS ${PLUGINS}/python )
set ( PYTHONPLUGIN_DIRS "${PLUGINS}/python;${PYTHONALG_DIRS}" )
set ( DATADIRS "" )
SET ( MANTIDPUBLISHER "http://upload.mantidproject.org/scriptrepository/payload/publish" )

Expand Down
5 changes: 0 additions & 5 deletions Code/Mantid/Framework/Properties/Mantid.properties.template
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ requiredpythonscript.directories = @REQUIREDSCRIPT_DIRS@
# This key is NOT recursive so sub-directories must be added in addition
pythonscripts.directories = @PYTHONSCRIPT_DIRS@

# The locations of Python algorithms that are to be loaded at startup (deprecated)
pythonalgorithms.directories =
# Require a copy of what they key used to look like so we know if a user had overridden it
pythonalgorithms.directories.deprecated = @PYTHONALG_DIRS@

# Setting this to 1 will allow python algorithms to be reloaded before execution.
pythonalgorithms.refresh.allowed = 0

Expand Down
44 changes: 6 additions & 38 deletions Code/Mantid/Framework/PythonInterface/mantid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,48 +88,16 @@ def apiVersion():
import simpleapi as _simpleapi
from kernel import plugins as _plugins

def _to_set(key):
s = set(kernel.config[key].split(";"))
if '' in s:
s.remove('')
return s

_plugins_key = 'python.plugins.directories'
_user_key = 'user.%s' % _plugins_key
plugin_dirs = _to_set(_plugins_key)
plugin_dirs.update(_to_set(_user_key))

# Check deprecated path too
# There are 2 situations that require handling:
# 2) Users defined new algorithms and placed them in other locations and added these
# locations to the pythonalgorithms.directories key in their user.props file. Tell them to update the
# and use the new keys
# 2) Users defined new algorithms and placed them in the deprecated location so the key is not in their
# user.properties file. Ask them to move the files to the new location
_deprecated_key = 'pythonalgorithms.directories'
_old_locs_key = '%s.deprecated' % (_deprecated_key)
# 1)
_user_file = config.getUserFilename()
_deprecated_locs = _to_set(_deprecated_key)
_msg="The Python algorithms key '%s' in '%s' has been deprecated. Please add '%s' to the '%s' key instead. " +\
"Future release will not check the old key."
for loc in _deprecated_locs:
loc = loc.rstrip("/")
if (not loc.endswith('PythonAPI/PythonAlgorithms')) and (not loc.endswith('PythonInterface/PythonAlgorithms')): # Avoid dev warning
logger.warning(_msg % (_deprecated_key,_user_file, loc,_user_key))
plugin_dirs.add(loc)

# 2)
_old_locs = _to_set(_old_locs_key)
_new_loc = _os.path.abspath(_os.path.join(_os.path.dirname(_bindir), '../plugins/python/algorithms'))
_msg="The packaged Python algorithms have been moved. You have extra algorithms in '%s', please move these files to '%s'. " +\
"Future releases will not check this location."
for loc in _old_locs:
loc = loc.rstrip("/")
if _plugins.check_for_plugins(loc):
if 'PythonAPI/PythonAlgorithms' not in loc: # Avoid a warning for developers until all old algorithms are gone
logger.warning(_msg % (loc,_new_loc))
plugin_dirs.add(loc)
plugin_dirs = _plugins.get_plugin_paths_as_set(_plugins_key)
plugin_dirs.update(_plugins.get_plugin_paths_as_set(_user_key))

# Check the deprecated key "pythonalgorithms.directories" and add those directories in.
# Also merge the new directories into the new user key & update the properties config
plugin_dirs = _plugins.cleanup_deprecated_key(plugin_dirs, _deprecated_key, _user_key)

# Load
plugin_files = []
Expand Down
73 changes: 70 additions & 3 deletions Code/Mantid/Framework/PythonInterface/mantid/kernel/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
"""
import os as _os
import imp as _imp
from mantid.kernel import logger, Logger, ConfigService
from mantid.kernel import logger, Logger, config

# String that separates paths (should be in the ConfigService)
PATH_SEPARATOR=";"

class PluginLoader(object):

Expand Down Expand Up @@ -36,6 +38,21 @@ def run(self):
return _imp.load_source(name, pathname)

#======================================================================================================================
# High-level functions to assist with loading
#======================================================================================================================

def get_plugin_paths_as_set(key):
"""
Returns the value of the given key in the config service
as a set. Raises an KeyError if the key is not defined
@param key The name of the key
@returns A set containing defined plugins paths
"""
s = set(config[key].split(PATH_SEPARATOR))
if '' in s:
s.remove('')
return s

def check_for_plugins(top_dir):
"""
Expand Down Expand Up @@ -89,8 +106,8 @@ def load(path):
will not included modules that will have attempted to be
reloaded but had not been changed
"""
if ";" in path:
path = path.split(";")
if PATH_SEPARATOR in path:
path = path.split(PATH_SEPARATOR)

loaded = []
if type(path) == list:
Expand Down Expand Up @@ -214,3 +231,53 @@ def contains_newapi_algorithm(filename):
break
file.close()
return alg_found

#======================================================================================================================

def cleanup_deprecated_key(plugin_dirs, deprecated_key, new_key):
"""
Checks whether the deprecated plugins key exists and adds any directories
that are not in the plugin dirs yet to the list. It then updates the new key
with these values and blanks the deprecated key's value. The config is then
saved out
@param plugin_dirs A set containing the list of existing plugin directories
@param deprecated_key A string containing the deprecated key name
@param new_key A string containing the new key name that will be updated.
@returns The updated set of plugins
"""
if not isinstance(plugin_dirs, set):
raise ValueError("plugin_dirs is expected to be a set type")

try:
dirs_depr_key = get_plugin_paths_as_set(deprecated_key)
except KeyError:
dirs_depr_key = set()
if len(dirs_depr_key) == 0:
logger.debug("No values from deprecated key '%s' to move" % deprecated_key)
return plugin_dirs

extra_dirs = dirs_depr_key.difference(plugin_dirs)
logger.debug("Additional directories found in deprecated key '%s'.\nMerging '%s' into new key '%s'" % (deprecated_key,str(extra_dirs),new_key))
plugin_dirs.update(extra_dirs)

# Update config service (key must exist or the above check would have returned
config[deprecated_key] = ""
try:
new_key_value = config[new_key]
except KeyError:
new_key_value = ""
if len(new_key_value) > 0 and not new_key_value.endswith(PATH_SEPARATOR):
new_key_value += PATH_SEPARATOR

for path in extra_dirs:
new_key_value += path + PATH_SEPARATOR

new_key_value = new_key_value.rstrip(PATH_SEPARATOR)
logger.debug("Updating ConfigService key '%s' with value '%s'" % (new_key, new_key_value))
config[new_key] = new_key_value
logger.debug("Saving config to '%s'" % config.getUserFilename())
config.saveConfig(config.getUserFilename())

return plugin_dirs

Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void export_ConfigService()
.def("saveConfig", &ConfigServiceImpl::saveConfig, "Saves the keys that have changed from their default to the given filename")

// Treat this as a dictionary
.def("__getitem__", getStringUsingCache)
.def("__getitem__", &getStringUsingCache)
.def("__setitem__", &ConfigServiceImpl::setString)
.def("__contains__", &ConfigServiceImpl::hasProperty)
.def("Instance", &ConfigService::Instance, return_value_policy<reference_existing_object>(),
Expand Down

0 comments on commit 2876f29

Please sign in to comment.