2012-12-30 14 views
12

Die Saga geht weiter, erweitert von der original thread.NamedTuples in Jinja2 Vorlage Makros

So habe ich eine etwas Makros in Python-Code zu machen:

from flask import get_template_attribute 
from jinja2 import Template 

    class InternalMacro(object): 
     """ 
     Creates a macro given a name, internal macro text, and content to fill(as namedtuple(t.var), dict(k,v), list(i), or other) 
     """ 
     def __init__(self, name = None, 
          text = None, 
          content_is = None): 
      self.name = name 
      self.macro_name = "{}_template".format(self.name) 
      self.macro_var = "{}_macro".format(self.name) 
      self.text = text 
      self.content_is = content_is 
      self.macro_txt = self.format_text 

     @property 
     def is_tuple(self): 
      return "{{% macro {0}(t) %}}{1}{{% endmacro %}}".format(self.macro_var, self.text) 

     @property 
     def is_dict(self): 
      return "{{% macro {0}(items) %}}{{% for k,v in items.iteritems() %}}{1}{{% endfor %}}{{% endmacro %}}".format(self.macro_var, self.text) 

     @property 
     def is_list(self): 
      return "{{% macro {0}(items) %}}{{% for i in items %}}{1}{{% endfor %}}{{% endmacro %}}".format(self.macro_var, self.text) 

     @property 
     def format_text(self): 
      return getattr(self, self.content_is) 

     @property 
     def return_template(self): 
      return Template(self.macro_txt) 

     @property 
     def return_callable(self): 
      return get_template_attribute(self.return_template, self.macro_var) 

Was ich namedtuples einzeln, als Listen oder als dicts passieren. Dies funktioniert beim Übergeben einer Liste (noch nicht vollständig als dict getestet), funktioniert aber nicht, wenn Sie ein einzelnes namedtuple übergeben. Was auch immer, bisher wird das namedtuple als Unicode entkernt.

So gegeben:

test_macro = InternalMacro('test', '{{ t }} <div id="divvy">{{ t.var }}</div>', 'is_tuple') 

test_macro.return_callable(Anamedtuple) 

kehrt:

u'Anamedtuple(var="A VAR VALUE") <div id="divvy"></div>' 

nicht:

u'Anamedtuple(var="A VAR VALUE")' <div id="divvy">A VAR VALUE</div> 

Wenn ich dies als Liste zu tun, in der Regel genannt .var zu bekommen.

Was passiert, dass ich vermisse und wie umgehe ich das? Das einzelne benannteTupel wird mit Escapezeichen versehen, eine Liste jedoch nicht. Ich könnte die Single als Liste machen und einfach die erste knipsen, scheint mir vielleicht unrein zu sein. Alle Vorschläge zur Verbesserung werden ebenfalls geschätzt.

EDIT:

Einfache Lösung war einfach alles ein in der Liste geführt zu reduzieren, Einzel- und dict Optionen zu beseitigen, in einer Liste von 1. passieren nur noch würde Ich mag, um herauszufinden, was dort vor sich geht genau.

EDIT2:

Ein tiefer zeigte explore, dass die Art, wie ich Ausgabe der namedtuple die Ergebnisse erzeugt ich sah also -

test_macro = InternalMacro('test', '{{ t }} <div id="divvy">{{ t.var }}</div>', 'is_tuple') 

Ergebnisse in:

u'Anamedtuple(var="A VAR VALUE") <div id="divvy"></div>' 

während:

test_macro = InternalMacro('test', '<div id="divvy">{{ t.var }}</div>', 'is_tuple') 

Ergebnisse in

'<div id="divvy">A VAR VALUE</div>' 

denke ich, dass die namedtuples einmal erhalten lesen oder .... gut jede detaillierte Erklärung geschätzt.

+0

Ich habe einen symbolischen Debugger für Python und viel freie Zeit geschieht, können Sie eine 1 vollständige Datei Beispiel (einschließlich der Namen schreiben Tupel) und ich werde es drehen. – David

Antwort

1

Möglicherweise nicht das, was Sie wollen, aber ...

from collections import namedtuple 

x = namedtuple("Foo", "var") 
z = x(var = 123) 
with app.app_context(): 
    test_macro = InternalMacro('test', "'{{ t }}' <div id=\"divvy\">{{ t.var }}</div>", 'is_tuple') 
    returnVal = test_macro.return_callable(z) 

print returnVal 
#'Foo(var=123)' &lt;div id="divvy"&gt;123&lt;/div&gt; 

'Foo (var = 123)' < div id = "divvy"/div >

repr(returnVal) 
'u\'\\\'Foo(var=123)\\\' <div id="divvy">123</div>\'' 

I‘ m mit Python 2.7 mit Flask 0.10.1 (es ist eine Weile her).

Der Tipp war die Erwartung von etwas, das nicht explizit definiert ist. Wenn ich es nicht verpasse, gibt es keine Unterscheidung zwischen grundlegenden Typen (int, str usw.) und Klassenobjekten irgendwo in der Eigenschaft is_tuple() von InternalMarco.Auch für ein is_tuple wird alles in einer Zeichenkette zusammengefügt und auf Puffer gedruckt.

Das Verhalten unterscheidet sich von for i in items, die jeweils für die Schleifenkörper spült {i} (vorausgesetzt, es ist ein Tippfehler war ein {1} setzen) und führt keine Zeichenfolge anfügt.

env/Python27/lib/site-packages/jinja2/parser.py ist, wo ich glaube, dass dieses

Linie # 869

elif token.type == 'block_begin': 
    flush_data() 
    next(self.stream) 
    if end_tokens is not None and \ 
        self.stream.current.test_any(*end_tokens): 
    return body 
    rv = self.parse_statement() 
    if isinstance(rv, list): 
    body.extend(rv) 
    else: 
    body.append(rv) 
    self.stream.expect('block_end') 
Verwandte Themen