Wie benutze ich das Ergebnis eines Ausdrucks als Argument zu einem Namenknoten programmgesteuert?Python

Python-Programme
Anonymous
 Wie benutze ich das Ergebnis eines Ausdrucks als Argument zu einem Namenknoten programmgesteuert?

Post by Anonymous »

Im Prozess der Entwicklung einer benutzerdefinierten Jinja2 -Erweiterung, die Namespaces mit dynamisch bewerteten Namen erstellt, muss ich das Ergebnis der Bewertung eines Template -Expression als Argument für einen -Namen verwenden Knoten. AST -Knoten. Das Problem ist jedoch, dass der AST aus der statischen Bewertung resultiert, während der Ausdruck eine Laufzeitbewertung erfordert (da Ausdrücke Variablen enthalten können, deren Wert zum Zeitpunkt der Analyse nicht bekannt ist). Gibt es eine Möglichkeit, diese Lücke zu überbrücken?

Code: Select all

{% set my_name = 'my_namespace' %}
{% namespace my_name %}
{# A namespace named 'my_namespace' should now exists #}
Natürlich kann ich den Namen problemlos analysieren und das Ergebnis seiner Bewertung mit einem Ausgang Knoten. Ich kann auch Namespaces mit vordefinierten wörtlichen Namen erstellen: < /p>

Code: Select all

from jinja2 import nodes
from jinja2.ext import Extension

class NamespaceExtension(Extension):

tags = {"namespace"}

def __init__(self, environment):
super().__init__(environment)

def parse(self, parser):

lineno = next(parser.stream).lineno
eval_context = nodes.EvalContext(self.environment)
name = parser.parse_expression()

##
## This obviously works as expected and outputs the result
## of evaluating `name` as an expression.
##

return nodes.Output([name]).set_lineno(lineno)

##
## This below also works — as a proof of concept — but we
## need the namespace name to be evaluated dynamically.
##

# return nodes.Assign(
#     nodes.Name('my_namespace', 'store'),
#     nodes.Call(nodes.Name('namespace', 'load'), [], [], None, None)
# ).set_lineno(lineno)

namespace = NamespaceExtension
< /code>
Die folgenden Versuche funktionieren jedoch nicht (ich hatte tatsächlich nur Hoffnung im ersten zu längeren Versuch, also nicht allzu überrascht in den meisten anderen, aber hier sind sie dennoch, wenn auch nur aus Vollständigkeit und Demonstration). < /p>
return nodes.Assign(
name,
nodes.Call(nodes.Name('namespace', 'load'), [], [], None, None)
).set_lineno(lineno)

# SyntaxError: cannot assign to function call
< /code>
Richtig, wir brauchen den Wert des Ausdrucks. < /p>
return nodes.Assign(
name.as_const(),
nodes.Call(nodes.Name('namespace', 'load'), [], [], None, None)
).set_lineno(lineno)

# RuntimeError: if no eval context is passed, the node must have an attached environment.
< /code>
Nun, ok, einfach genug. < /p>
return nodes.Assign(
name.as_const(eval_context),
nodes.Call(nodes.Name('namespace', 'load'), [], [], None, None)
).set_lineno(lineno)

# jinja2.nodes.Impossible
< /code>
Möglicherweise haben Sie ein besseres Glück, die Umgebung anzubringen. < /p>
name.set_environment(self.environment)
return nodes.Assign(
name.as_const(),
nodes.Call(nodes.Name('namespace', 'load'), [], [], None, None)
).set_lineno(lineno)

# jinja2.nodes.Impossible
Natürlich werden Ausdrücke standardmäßig mit einem "Laden" -Kontext analysiert und wir benötigen einen Namen Knoten mit einem "Speicher" -Kontext.

Code: Select all

name.set_ctx('store')
return nodes.Assign(
name,
nodes.Call(nodes.Name('namespace', 'load'), [], [], None, None)
).set_lineno(lineno)

# SyntaxError: cannot assign to function call
Wie wäre es mit dem Namen Ausdruck im 'Load' Kontext in einem Namen Knoten mit einem "Speicher" -Kontext?

Code: Select all

return nodes.Assign(
nodes.Name(name, 'store'),
nodes.Call(nodes.Name('namespace', 'load'), [], [], None, None)
).set_lineno(lineno)

# TypeError: '

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post