From 981cbf6ea418f19e2741a379442cebe9063bb530 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 13 May 2008 09:12:27 +0200 Subject: [PATCH] removed unused imports --HG-- branch : trunk --- TODO | 11 ---- docs/api.rst | 14 ++--- jinja2/environment.py | 44 ++++---------- jinja2/loaders.py | 2 +- jinja2/optimizer.py | 137 +++--------------------------------------- 5 files changed, 30 insertions(+), 178 deletions(-) diff --git a/TODO b/TODO index 2a022f4..a951936 100644 --- a/TODO +++ b/TODO @@ -3,17 +3,6 @@ Todo Before Release This has to be implemented before the release: -Drop special casing template globals ------------------------------------- - -The idea some time ago was to partially evaluate templates at compile time. -For that we decided to not allow globals being overridden by locals as the -static compiler could have changed semantics. Turns out that the static -compiler blows up the complexity to something nobody wants to support which -means that this restriction is kinda pointless. - -That should go for good. - Pull Attributes Onces --------------------- diff --git a/docs/api.rst b/docs/api.rst index 8d85242..5b9e5ad 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -81,8 +81,7 @@ High Level API .. attribute:: globals A dict of global variables. These variables are always available - in a template and (if the optimizer is enabled) may not be - overridden by templates. As long as no template was loaded it's safe + in a template. As long as no template was loaded it's safe to modify this dict. For more details see :ref:`global-namespace`. For valid object names have a look at :ref:`identifier-naming`. @@ -364,8 +363,9 @@ A template designer can then use the test like this: The Global Namespace -------------------- -Variables stored in the :attr:`Environment.globals` or :attr:`Template.globals` -dicts are special as they are available for imported templates too and will be -used by the optimizer in future releases to evaluates parts of the template at -compile time. This is the place where you can put variables and functions -that should be available all the time. +Variables stored in the :attr:`Environment.globals` dict are special as they +are available for imported templates too, even if they are imported without +context. This is the place where you can put variables and functions +that should be available all the time. Additionally :attr:`Template.globals` +exist that are variables available to a specific template that are available +to all :meth:`~Template.render` calls. diff --git a/jinja2/environment.py b/jinja2/environment.py index e104090..70fd344 100644 --- a/jinja2/environment.py +++ b/jinja2/environment.py @@ -310,17 +310,13 @@ class Environment(object): """ return self.lexer.tokeniter(source, filename) - def compile(self, source, name=None, filename=None, globals=None, - raw=False): + def compile(self, source, name=None, filename=None, raw=False): """Compile a node or template source code. The `name` parameter is the load name of the template after it was joined using :meth:`join_path` if necessary, not the filename on the file system. the `filename` parameter is the estimated filename of the template on the file system. If the template came from a database or memory this - can be omitted. The `globals` parameter can be used to provide extra - variables at compile time for the template. In the future the - optimizer will be able to evaluate parts of the template at compile - time based on those variables. + can be omitted. The return value of this method is a python code object. If the `raw` parameter is `True` the return value will be a string with python @@ -330,7 +326,7 @@ class Environment(object): if isinstance(source, basestring): source = self.parse(source, filename) if self.optimized: - node = optimize(source, self, globals or {}) + node = optimize(source, self) source = generate(node, self, name, filename) if raw: return source @@ -358,9 +354,8 @@ class Environment(object): If the `parent` parameter is not `None`, :meth:`join_path` is called to get the real template name before loading. - The `globals` parameter can be used to provide compile-time globals. - In the future this will allow the optimizer to render parts of the - templates at compile-time. + The `globals` parameter can be used to provide temlate wide globals. + These variables are available in the context at render time. If the template does not exist a :exc:`TemplateNotFound` exception is raised. @@ -387,8 +382,7 @@ class Environment(object): """ globals = self.make_globals(globals) cls = template_class or self.template_class - return cls.from_code(self, self.compile(source, globals=globals), - globals, None) + return cls.from_code(self, self.compile(source), globals, None) def make_globals(self, d): """Return a dict for the globals.""" @@ -513,24 +507,8 @@ class Template(object): raise exc_type, exc_value, tb def _generate(self, *args, **kwargs): - # assemble the context - context = dict(*args, **kwargs) - - # if the environment is using the optimizer locals may never - # override globals as optimizations might have happened - # depending on values of certain globals. This assertion goes - # away if the python interpreter is started with -O - if __debug__ and self.environment.optimized: - overrides = set(context) & set(self.globals) - if overrides: - plural = len(overrides) != 1 and 's' or '' - raise AssertionError('the per template variable%s %s ' - 'override%s global variable%s. ' - 'With an enabled optimizer this ' - 'will lead to unexpected results.' % - (plural, ', '.join(overrides), plural or ' a', plural)) - - return self.root_render_func(self.new_context(context)) + """Creates a new context and generates the template.""" + return self.root_render_func(self.new_context(dict(*args, **kwargs))) def new_context(self, vars=None, shared=False): """Create a new template context for this template. The vars @@ -668,8 +646,10 @@ class TemplateStream(object): while 1: try: while c_size < size: - push(next()) - c_size += 1 + c = next() + push(c) + if c: + c_size += 1 except StopIteration: if not c_size: return diff --git a/jinja2/loaders.py b/jinja2/loaders.py index a63cdbf..eb27f17 100644 --- a/jinja2/loaders.py +++ b/jinja2/loaders.py @@ -86,7 +86,7 @@ class BaseLoader(object): if globals is None: globals = {} source, filename, uptodate = self.get_source(environment, name) - code = environment.compile(source, name, filename, globals) + code = environment.compile(source, name, filename) return environment.template_class.from_code(environment, code, globals, uptodate) diff --git a/jinja2/optimizer.py b/jinja2/optimizer.py index 283d1fa..5b95c99 100644 --- a/jinja2/optimizer.py +++ b/jinja2/optimizer.py @@ -17,65 +17,14 @@ :license: GNU GPL. """ from jinja2 import nodes -from jinja2.visitor import NodeVisitor, NodeTransformer -from jinja2.runtime import LoopContext -from jinja2.utils import concat +from jinja2.visitor import NodeTransformer -def optimize(node, environment, context_hint=None): +def optimize(node, environment): """The context hint can be used to perform an static optimization based on the context given.""" optimizer = Optimizer(environment) - return optimizer.visit(node, ContextStack(context_hint)) - - -class ContextStack(object): - """Simple compile time context implementation.""" - undefined = object() - - def __init__(self, initial=None): - self.stack = [{}] - if initial is not None: - self.stack.insert(0, initial) - - def push(self): - self.stack.append({}) - - def pop(self): - self.stack.pop() - - def get(self, key, default=None): - try: - return self[key] - except KeyError: - return default - - def undef(self, name): - if name in self: - self[name] = self.undefined - - def __contains__(self, key): - try: - self[key] - except KeyError: - return False - return True - - def __getitem__(self, key): - for level in reversed(self.stack): - if key in level: - rv = level[key] - if rv is self.undefined: - raise KeyError(key) - return rv - raise KeyError(key) - - def __setitem__(self, key, value): - self.stack[-1][key] = value - - def blank(self): - """Return a new context with nothing but the root scope.""" - return ContextStack(self.stack[0]) + return optimizer.visit(node) class Optimizer(NodeTransformer): @@ -83,90 +32,24 @@ class Optimizer(NodeTransformer): def __init__(self, environment): self.environment = environment - def visit_Block(self, node, context): - block_context = context.blank() - for name in 'super', 'self': - block_context.undef(name) - return self.generic_visit(node, block_context) - - def visit_For(self, node, context): - context.push() - context.undef('loop') - try: - return self.generic_visit(node, context) - finally: - context.pop() - - def visit_Macro(self, node, context): - context.push() - for name in 'varargs', 'kwargs', 'caller': - context.undef(name) - try: - return self.generic_visit(node, context) - finally: - context.pop() - - def visit_CallBlock(self, node, context): - context.push() - for name in 'varargs', 'kwargs': - context.undef(name) - try: - return self.generic_visit(node, context) - finally: - context.pop() - - def visit_FilterBlock(self, node, context): - """Try to filter a block at compile time.""" - context.push() - try: - return self.generic_visit(node, context) - finally: - context.pop() - - def visit_If(self, node, context): + def visit_If(self, node): + """Eliminate dead code.""" try: - val = self.visit(node.test, context).as_const() + val = self.visit(node.test).as_const() except nodes.Impossible: - return self.generic_visit(node, context) + return self.generic_visit(node) if val: body = node.body else: body = node.else_ result = [] for node in body: - result.extend(self.visit_list(node, context)) + result.extend(self.visit_list(node)) return result - def visit_Name(self, node, context): - if node.ctx != 'load': - # something overwrote the variable, we can no longer use - # the constant from the context - context.undef(node.name) - return node - try: - return nodes.Const.from_untrusted(context[node.name], - lineno=node.lineno, - environment=self.environment) - except (KeyError, nodes.Impossible): - return node - - def visit_Import(self, node, context): - rv = self.generic_visit(node, context) - context.undef(node.target) - return rv - - def visit_FromImport(self, node, context): - rv = self.generic_visit(node, context) - for name in node.names: - if isinstance(name, tuple): - context.undef(name[1]) - else: - context.undef(name) - return rv - - def fold(self, node, context): + def fold(self, node): """Do constant folding.""" - node = self.generic_visit(node, context) + node = self.generic_visit(node) try: return nodes.Const.from_untrusted(node.as_const(), lineno=node.lineno, -- 2.26.2