From f09b8478b523e00d6d0ce1a5397c09fb3a2d5475 Mon Sep 17 00:00:00 2001 From: jesseward Date: Tue, 17 Mar 2015 01:27:45 -0400 Subject: [PATCH 1/3] Adds logic to support the notion of a 'child config directory'. Requested in issue #241. scriptpath now supports a command delimited list of directories. Example : scriptpath = /opt/bbs/bbs.jesseward.com/scripts,/usr/local/src/github/x84/x84/x84/default The highest preference directory location will reside at list index 0. If index 0 misses imp.find_module() iterates through the list until a hit is returned. --- docs/default_api.rst | 8 ++++- docs/web.rst | 3 +- x84/bbs/ini.py | 2 ++ x84/bbs/session.py | 66 +++++++++++++++++++++++++--------------- x84/webmodules/static.py | 2 +- x84/webserve.py | 5 +-- 6 files changed, 57 insertions(+), 29 deletions(-) diff --git a/docs/default_api.rst b/docs/default_api.rst index 35d7bfe4..36aae20a 100644 --- a/docs/default_api.rst +++ b/docs/default_api.rst @@ -2,7 +2,13 @@ Customizing your board ====================== -The ``default.ini`` file option, *scriptpath*, of section *[system]*, defines folder ``'default/'``, containing the scripts documented in this section. +The ``default.ini`` file option, *scriptpath*, of section *[system]*, defines folder ``'default/'``, containing the scripts documented in this section. *scriptpath* accepts a comma delimited list of directories in which to store your customizations. Noting that the left most entry is of the highest preference. + +For example. + + scriptpath = /opt/bbs/scripts,/usr/local/src/x84/x84/default + +x84 searches for scripts in ``/opt/bbs/scripts`` first and then ``/usr/local/src/x84/x84/default``. This allows you to keep any customizations outside of the main source tree and then fall back to x84 defaults if they're not present in your customizations directory. Additional scripts can be found at https://github.com/x84-extras diff --git a/docs/web.rst b/docs/web.rst index fbda161b..451deebf 100644 --- a/docs/web.rst +++ b/docs/web.rst @@ -51,7 +51,8 @@ Serving static files One of x/84's internal web modules is called ``static``. If you enable this module, x/84 will serve static file content from the ``www-static`` subdirectory -of your system's script path. If you wish to set the document root to some other +of your system's top-level ``scriptpath``. The top-level refers to the first +item in this array. If you wish to set the document root to some other location, use the ``document_root`` option in the ``[web]`` section of your configuration file. :: diff --git a/x84/bbs/ini.py b/x84/bbs/ini.py index 2e2a2ef4..93a39d2f 100644 --- a/x84/bbs/ini.py +++ b/x84/bbs/ini.py @@ -196,6 +196,8 @@ def init_bbs_ini(): cfg_bbs.set('web', 'chain', os.path.expanduser( os.path.join('~', '.x84', 'ca.cer'))) cfg_bbs.set('web', 'modules', 'msgserve') + cfg_bbs.set('web', 'static_files', os.path.abspath( + os.path.join(os.path.dirname(__file__), os.path.pardir, 'default'))) # default path if cmd argument is not absolute, cfg_bbs.add_section('door') diff --git a/x84/bbs/session.py b/x84/bbs/session.py index e8395592..f5f0fb5d 100644 --- a/x84/bbs/session.py +++ b/x84/bbs/session.py @@ -75,7 +75,7 @@ class Session(object): _decoder = None _activity = None _user = None - _script_module = None + _script_module = [] def __init__(self, terminal, sid, env, child_pipes, kind, addrport, matrix_args, matrix_kwargs): @@ -253,12 +253,23 @@ def show_traceback(self): @property def script_path(self): - """ Base filepath folder for all scripts. """ + """ Base filepath folder for all scripts. + + rtype: list + """ val = get_ini('system', 'scriptpath') - # ensure folder exists - assert os.path.isdir(val), ( - 'configuration section [system], value scriptpath: ' - 'not a folder: {!r}'.format(val)) + + # system.scriptpath setting. + # coerce scriptpath to a list. Multiple scriptpath values allow the + # ability to override the x84/default modules, without modifying the + # original source tree files. + val = val.split(',') + + # ensure all specified folders exist + for directory in val: + assert os.path.isdir(directory), ( + 'configuration section [system], value scriptpath: ' + 'not a folder: {!r}'.format(directory)) return val @property @@ -271,19 +282,25 @@ def current_script(self): @property def script_module(self): - """ Base python module instance for userland scripts. """ - if self._script_module is None: - # load default/__init__.py as 'default', - folder_name = os.path.basename(self.script_path) - - # put it in sys.path for relative imports - if self.script_path not in sys.path: - sys.path.insert(0, self.script_path) - - # discover import path to __init__.py, store result - lookup = imp.find_module('__init__', [self.script_path]) - self._script_module = imp.load_module(folder_name, *lookup) - self._script_module.__path__ = self.script_path + """ Base python module instance for userland scripts. + + rtype: list + """ + if not self._script_module: + + for directory in self.script_path: + # load default/__init__.py as 'default', + folder_name = os.path.basename(directory) + + # put it in sys.path for relative imports + if directory not in sys.path: + sys.path.insert(0, directory) + + # discover import path to __init__.py, store result + lookup = imp.find_module('__init__', [directory]) + scr_module = imp.load_module(folder_name, *lookup) + scr_module.__path__ = directory + self._script_module.append(scr_module) return self._script_module @property @@ -657,16 +674,17 @@ def runscript(self, script): # if given a script name such as 'extras.target', adjust the lookup # path to be extended by {default_scriptdir}/extras, and adjust # script_name to be just 'target'. - script_relpath = self.script_module.__path__ - lookup_paths = [script_relpath] + script_relpath = [ directory.__path__ for directory in self.script_module ] + lookup_paths = script_relpath[:] + if '.' not in script.name: script_name = script.name else: # build another system path, relative to `script_module' remaining, script_name = script.name.rsplit('.', 1) - _lookup_path = os.path.join(script_relpath, *remaining.split('.')) - lookup_paths.append(_lookup_path) - + for dir_relpath in script_relpath: + _lookup_path = os.path.join(dir_relpath, *remaining.split('.')) + lookup_paths.append(_lookup_path) lookup = imp.find_module(script_name, lookup_paths) module = imp.load_module(script_name, *lookup) diff --git a/x84/webmodules/static.py b/x84/webmodules/static.py index 32b463a2..cd60add1 100644 --- a/x84/webmodules/static.py +++ b/x84/webmodules/static.py @@ -44,7 +44,7 @@ def web_module(): # determine document root for web server static_root = (get_ini('web', 'document_root') - or os.path.join(get_ini('system', 'scriptpath'), + or os.path.join(get_ini('system', 'scriptpath').split(',')[0], 'www-static')) StaticApp.static_root = static_root diff --git a/x84/webserve.py b/x84/webserve.py index c58b7589..dc7c5abd 100755 --- a/x84/webserve.py +++ b/x84/webserve.py @@ -191,10 +191,11 @@ def main(background_daemon=True): log = logging.getLogger(__name__) - SCRIPT_PATH = get_ini(section='system', key='scriptpath') + SCRIPT_PATH = get_ini(section='system', key='scriptpath').split(',') # ensure the SCRIPT_PATH is in os environment PATH for module lookup. - sys.path.insert(0, os.path.expanduser(SCRIPT_PATH)) + for directory in SCRIPT_PATH: + sys.path.insert(0, os.path.expanduser(directory)) web_modules = get_ini(section='web', key='modules', split=True) From 3910cb320bb1f9d556a12239fc6eaaeea7ad0800 Mon Sep 17 00:00:00 2001 From: jesseward Date: Tue, 17 Mar 2015 01:36:41 -0400 Subject: [PATCH 2/3] Documenting scriptpath changes and bumping to 2.0.12 --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 78b31ed0..bd87a91c 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +2.0.12 + - enhancement: [system] option scriptpath now supports a comma + separated list of directories in which customizations are stored. 2.0.11 - bugfix: weather.py fix incorrect postal code return from Accu Weather. Changed the default to populate search by city/state instead of From 9f068dc4023e38e49a49047c31588c742ed41d53 Mon Sep 17 00:00:00 2001 From: jesseward Date: Tue, 17 Mar 2015 14:46:26 -0400 Subject: [PATCH 3/3] Second pass at child directory configuration change. Adding styling and syntax recommendations from jquast. --- x84/bbs/ini.py | 2 -- x84/bbs/session.py | 22 +++++++++------------- x84/webmodules/static.py | 4 ++-- x84/webserve.py | 2 +- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/x84/bbs/ini.py b/x84/bbs/ini.py index 93a39d2f..2e2a2ef4 100644 --- a/x84/bbs/ini.py +++ b/x84/bbs/ini.py @@ -196,8 +196,6 @@ def init_bbs_ini(): cfg_bbs.set('web', 'chain', os.path.expanduser( os.path.join('~', '.x84', 'ca.cer'))) cfg_bbs.set('web', 'modules', 'msgserve') - cfg_bbs.set('web', 'static_files', os.path.abspath( - os.path.join(os.path.dirname(__file__), os.path.pardir, 'default'))) # default path if cmd argument is not absolute, cfg_bbs.add_section('door') diff --git a/x84/bbs/session.py b/x84/bbs/session.py index f5f0fb5d..0de6488d 100644 --- a/x84/bbs/session.py +++ b/x84/bbs/session.py @@ -253,24 +253,19 @@ def show_traceback(self): @property def script_path(self): - """ Base filepath folder for all scripts. + """ + Base filepath folder for all scripts. - rtype: list + :rtype: list """ - val = get_ini('system', 'scriptpath') - - # system.scriptpath setting. - # coerce scriptpath to a list. Multiple scriptpath values allow the - # ability to override the x84/default modules, without modifying the - # original source tree files. - val = val.split(',') + scriptpath_dirs = get_ini('system', 'scriptpath', split=True) # ensure all specified folders exist - for directory in val: + for directory in scriptpath_dirs: assert os.path.isdir(directory), ( 'configuration section [system], value scriptpath: ' 'not a folder: {!r}'.format(directory)) - return val + return scriptpath_dirs @property def current_script(self): @@ -282,9 +277,10 @@ def current_script(self): @property def script_module(self): - """ Base python module instance for userland scripts. + """ + Base python module instance for userland scripts. - rtype: list + :rtype: list """ if not self._script_module: diff --git a/x84/webmodules/static.py b/x84/webmodules/static.py index cd60add1..82188a61 100644 --- a/x84/webmodules/static.py +++ b/x84/webmodules/static.py @@ -44,8 +44,8 @@ def web_module(): # determine document root for web server static_root = (get_ini('web', 'document_root') - or os.path.join(get_ini('system', 'scriptpath').split(',')[0], - 'www-static')) + or os.path.join(get_ini('system', 'scriptpath', + split=True)[0], 'www-static')) StaticApp.static_root = static_root return { diff --git a/x84/webserve.py b/x84/webserve.py index dc7c5abd..3463f8bd 100755 --- a/x84/webserve.py +++ b/x84/webserve.py @@ -191,7 +191,7 @@ def main(background_daemon=True): log = logging.getLogger(__name__) - SCRIPT_PATH = get_ini(section='system', key='scriptpath').split(',') + SCRIPT_PATH = get_ini(section='system', key='scriptpath', split=True) # ensure the SCRIPT_PATH is in os environment PATH for module lookup. for directory in SCRIPT_PATH: