| Index: cms/converters.py |
| =================================================================== |
| --- a/cms/converters.py |
| +++ b/cms/converters.py |
| @@ -263,31 +263,40 @@ class TemplateConverter(Converter): |
| "linkify": self.linkify, |
| "toclist": self.toclist, |
| } |
| globals = { |
| "get_string": self.get_string, |
| } |
| - for filename in self._params["source"].list_files("filters"): |
| - root, ext = os.path.splitext(filename) |
| - if ext.lower() != ".py": |
| - continue |
| + for dirname, dictionary in [("filters", filters), ("globals", globals)]: |
| + for filename in self._params["source"].list_files(dirname): |
| + root, ext = os.path.splitext(filename) |
| + if ext.lower() != ".py": |
| + continue |
| - path = "%s/%s" % ("filters", filename) |
| - code = self._params["source"].read_file(path) |
| - module = imp.new_module(root.replace("/", ".")) |
| - exec code in module.__dict__ |
| + path = "%s/%s" % (dirname, filename) |
| + code = self._params["source"].read_file(path) |
| + module = imp.new_module(root.replace("/", ".")) |
| + exec code in module.__dict__ |
| - func = os.path.basename(root) |
| - if not hasattr(module, func): |
| - raise Exception("Expected function %s not found in filter file %s" % (func, filename)) |
| - filters[func] = getattr(module, func) |
| - filters[func].module_ref = module # Prevent garbage collection |
| + name = os.path.basename(root) |
| + if not hasattr(module, name): |
| + raise Exception("Expected symbol %s not found in %s file %s" % (name, dirname, filename)) |
| + dictionary[name] = getattr(module, name) |
| + |
| + # HACK: The module we created here can be garbage collected because it |
| + # isn't added to sys.modules. If a function is called and its module is |
| + # gone it might cause weird errors (imports and module variables |
| + # unavailable). We avoid this situation by explicitly referencing the |
| + # module from the function so they can only be garbage collected |
| + # together. |
| + if callable(dictionary[name]): |
| + dictionary[name].module_ref = module |
| self._env = jinja2.Environment(loader=self._SourceLoader(self._params["source"]), autoescape=True) |
| self._env.filters.update(filters) |
| self._env.globals.update(globals) |
| def get_html(self, source): |
| template = self._env.from_string(source) |
| module = template.make_module(self._params) |