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) |