2012-12-30 26 views
12

Saga trwa dalej, przedłużona z original thread.NamedTuples w makrach szablonu Jinja2

Tak, mam coś, aby makra kodem Pythona:

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) 

Które mijam namedtuples pojedynczo, jak listy, lub jako dicts. Działa to podczas przekazywania listy (nie zostało jeszcze w pełni przetestowane jako dict), ale nie działa podczas przekazywania pojedynczej kostki nazwanej. Niezależnie od tego, jak dotąd, nazwa ta uciekła jako unicode.

Więc biorąc pod uwagę:

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

test_macro.return_callable(Anamedtuple) 

Powroty:

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

:

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

Jeśli mogę to zrobić w formie listy, .var sprawdzony normalnie.

Co się dzieje, czego mi brakuje i jak mogę to obejść? Pojedynczy namedtuple dostaje Escaped, ale lista nie. Mógłbym zrobić singiel jako listę i po prostu wyskoczyć pierwszy, może wydaje mi się nieczysty. Wszelkie sugestie dotyczące poprawy tego również się spodobały.

EDIT:

Proste rozwiązanie było po prostu wszystko, aby zmniejszyć zdanym na liście, wyeliminować pojedyncze i DICT opcje, po prostu zdać się na liście 1. Mimo to chciałbym się dowiedzieć, co się tam dzieje dokładnie.

EDIT2:

Głębsze explore wykazały, że wyjście sposób I namedtuple generowane wyniki widziałam IE -

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

skutkuje:

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

następuje:

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

skutkuje

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

Chyba namedtuples się czytać raz albo .... dobrze jakikolwiek szczegółowe wyjaśnienie doceniane.

+0

Mam symboliczną debugger dla Python i dużo wolnego czasu, można umieścić 1 pełny przykładowy plik (w tym imieniem tuple), a ja go przekręcę. – David

Odpowiedz

1

Być może nie to, co chcesz, ale ...

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 używając Pythona 2.7 z kolbą 0.10.1 (minęło trochę czasu).

Odsłonięcie było oczekiwaniem na coś, co nie jest jednoznacznie zdefiniowane. O ile nie przeoczyłem tego, nie ma żadnej różnicy między tym, jak podstawowe typy (int, str, itp.) I obiekty klasy w dowolnym miejscu w właściwości is_tuple() InternalMarco.Również dla zmiennej is_tuple wszystko jest złożone w jeden ciąg znaków i jest drukowane w buforze.

Zachowanie to różni się od for i in items który wypłukuje każdy dla ciała pętli {i} (przy założeniu, że to typo umieszczenie {1}) i nie wykonuje ciąg dodaje.

env/Python27/lib/site-packages/jinja2/parser.py gdzie Wierzę, że to się dzieje

Linia # 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') 
Powiązane problemy