From d9660515585d632ae10da1c4913e13b1525c2eba Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 10 Feb 2016 15:23:17 +0100 Subject: [PATCH] Changing utils.all_from_module to really only load variables actually defined in the module in question (so will no longer include imports from other modules). Added utils.callables_from_module to handle the common case of only wanting callable functions from a module (used by lock funcs, inlinefuncs etc). --- evennia/locks/lockhandler.py | 7 +----- evennia/utils/inlinefunc.py | 2 +- evennia/utils/nested_inlinefuncs.py | 2 +- evennia/utils/utils.py | 34 +++++++++++++++++++++++++---- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/evennia/locks/lockhandler.py b/evennia/locks/lockhandler.py index eca347a79..ffe568269 100644 --- a/evennia/locks/lockhandler.py +++ b/evennia/locks/lockhandler.py @@ -140,12 +140,7 @@ def _cache_lockfuncs(): global _LOCKFUNCS _LOCKFUNCS = {} for modulepath in settings.LOCK_FUNC_MODULES: - mod = utils.mod_import(modulepath) - if mod: - for tup in (tup for tup in inspect.getmembers(mod) if callable(tup[1])): - _LOCKFUNCS[tup[0]] = tup[1] - else: - logger.log_err("Couldn't load %s from PERMISSION_FUNC_MODULES." % modulepath) + _LOCKFUNCS.update(utils.callables_from_module(modulepath)) # # pre-compiled regular expressions diff --git a/evennia/utils/inlinefunc.py b/evennia/utils/inlinefunc.py index 8cc14a958..547e41eba 100644 --- a/evennia/utils/inlinefunc.py +++ b/evennia/utils/inlinefunc.py @@ -132,7 +132,7 @@ def you(text, *args, **kwargs): # load functions from module (including this one, if using default settings) _INLINE_FUNCS = {} for module in utils.make_iter(settings.INLINEFUNC_MODULES): - _INLINE_FUNCS.update(utils.all_from_module(module)) + _INLINE_FUNCS.update(utils.callables_from_module(module)) _INLINE_FUNCS.pop("inline_func_parse", None) diff --git a/evennia/utils/nested_inlinefuncs.py b/evennia/utils/nested_inlinefuncs.py index d36c5a7f4..01fc3a642 100644 --- a/evennia/utils/nested_inlinefuncs.py +++ b/evennia/utils/nested_inlinefuncs.py @@ -166,7 +166,7 @@ _INLINE_FUNCS = {"nomatch": lambda *args, **kwargs: "", # load custom inline func modules. for module in utils.make_iter(settings.INLINEFUNC_MODULES): - _INLINE_FUNCS.update(utils.all_from_module(module)) + _INLINE_FUNCS.update(utils.callables_from_module(module)) # remove the core function if we include examples in this module itself #_INLINE_FUNCS.pop("inline_func_parse", None) diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index cf458bf19..c24d067e5 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -18,7 +18,7 @@ import re import textwrap import random from importlib import import_module -from inspect import ismodule, trace +from inspect import ismodule, trace, getmembers, getmodule from collections import defaultdict, OrderedDict from twisted.internet import threads, defer, reactor from django.conf import settings @@ -956,7 +956,7 @@ def mod_import(module): def all_from_module(module): """ - Return all global-level variables from a module. + Return all global-level variables defined in a module. Args: module (str, module): This can be either a Python path @@ -975,8 +975,34 @@ def all_from_module(module): mod = mod_import(module) if not mod: return {} - return dict((key, val) for key, val in mod.__dict__.items() - if not (key.startswith("_") or ismodule(val))) + # make sure to only return variables actually defined in this module (not imports) + members = getmembers(mod, predicate=lambda obj: getmodule(obj) == mod) + return dict((key, val) for key, val in members.iteritems() if not key.startswith("_")) + #return dict((key, val) for key, val in mod.__dict__.items() + # if not (key.startswith("_") or ismodule(val))) + + +def callables_from_module(module): + """ + Return all global-level callables defined in a module. + + Args: + module (str, module): A python-path to a module or an actual + module object. + + Returns: + callables (dict): A dict of {name: callable, ...} from the module. + + Notes: + Will ignore callables whose names start with underscore "_". + + """ + mod = mod_import(module) + if not mod: + return {} + # make sure to only return callables actually defined in this module (not imports) + members = getmembers(mod, predicate=lambda obj: callable(obj) and getmodule(obj) == mod) + return dict((key, val) for key, val in members.iteritems() if not key.startswith("_")) def variable_from_module(module, variable=None, default=None):