How does zope/plone evaluate variables? - plone

Imagine this scenario:
I have a ZPT in Zope where I define, into a metal block, a global variable.
This variable takes its value from an expression like this
global myVar id | nothing;
global anotherVar 1;
where nothing could be replaced with python:0 or python:False or None and so on.
Now imagine that into another block, I'll do something like
global myVar2 myVar | anotherVar | nothing;
where nothing could be everything that I specified above.
Now suppose that id hasn't a value and so myVar took nothing (or the other possible values; it's makes not difference at all).
What I expected was that myVar2 took anotherVar's value, since anotherVar has a value. But with great surprise, I notice that this isn't true and myVar2 took myVar value; that means nothing.
If I understand what is happening, I'll suppose that this kind of statement only control over existence of that variable and not over it's value.
Obviously I can make that kind of statement into a pythonic way and, of course, it works "well" (namely, as I expected)
So, someone can confirm or disprove what I suppose there ?

What you are asking is not Plone or Zope specific, you are dealing with a TALES statement here, which, together with TAL and METAL form the page template language implemented by Zope Page Templates (and, incidentally, also by chameleon, plus several other implementations in different programming languages).
You are using a TALES path expression when you use the | character, and it is not the same as a Python or expression. Each path named in the expression will by resolved, and only if it doesn't exist will the next path be used. From the specification:
When a TALES path expression is evaluated, it attempts to traverse each path, from left to right, until it succeeds or runs out of paths.
Since all your paths resolve to existing variable names, they all exist and the first one will be used, regardless of it's value.
You want to use a python: expression instead:
myVar2 python:myVar or anotherVar or None;
Note that in TAL there rarely is a need for the global keyword. You probably want to define these items on your root element of your document instead; variables are visible within the same scope as the XML or HTML element they are defined on:
<html tal:define="myVar id | nothing; anotherVar 1;">
<!-- myVar and anotherVar are visible in the whole HTML document -->
</html>

Related

Can Roboframework user keyword contain Regexp?

It is very common to have a keyword that tests a similar behaviour, with a slightly different semantic like so:
The ${element_a} (gets updated with reference|has a reference) to the ${element_b}
However I wasn't able to find this feature documented anywhere. I know other libraries for testing such as Cucumber support matching steps through regexp, and I imagine since robotframework support embedded arguments in keyword names this can also work in robot.
Is there a way to write a keyword once and re-use it in slightly different situations?
*** Keywords ***
The ${element_a} ${updated_or_has} to the ${element_b}
IF """${update_or_has}""" == 'gets updated with reference'
Do Actions For Updated
ELSE IF """${update_or_has}""" == 'has a reference'
Do Other Actions
ELSE
Fail Unsupported value
END
That's one way to do it, branch the execution based on what string was part of the keyword name.
Calling it The element_a gets updated with reference to the element_b will have the keyword take one path, while The element_y has a reference to the element_z - a different one.
By the way, you might reconsider changing the verbing slightly, as the framework will have a bit hard time distinguishing what substring goes in the variable ${element_a} and what in ${updated_or_has} - put a static word, that'll be a part of the keyword name & act as a separator b/n the two vars.
Based on the comments, the branching is not needed, just a confirmation the caller used one of the two possible/supported values. This can be done with this check:
Run Keyword If """${update_or_has}""".lower() not in ('gets updated with reference', 'has a reference', ) Fail Unsupported value
You can specify an argument with a regular expression. So, you could treat part you want to match against as if it was an argument.
From the official user guide, in a section titled Using custom regular expressions:
A custom embedded argument regular expression is defined after the base name of the argument so that the argument and the regexp are separated with a colon.
In your particular case it might look something like this:
The ${element_a} ${foo:gets updated with reference|has a reference} to the ${element_b}
${foo} will be a variable that has whatever that little part is, which you can just ignore.
Here is a working example:
*** Keywords ***
The ${element_a} ${foo:gets updated with reference|has a reference} to the ${element_b}
log the foo argument is '${foo}'
*** Test Cases ***
Example
The foo gets updated with reference to the bar
The bar has a reference to the foo
# verify that the keyword only matches those two variations
Run keyword and expect error
... No keyword with name 'The something blah blah to the yada' found.
... The something blah blah to the yada

Is there a reason to put #static before if VERSION statements?

For example in front of this:
#static if v"0.2" <= VERSION < v"0.3-"
# do something specific to 0.2 release series
end
Is the #static necessary?
In addition to #DVNold's answer, here's a bit more explanation...
First, the difference between the two:
if in global scope the condition and whatever branch is selected are both evaluated when that code is run;
#static if evaluates the condition when the code is parsed (during macro expansion) and is replaced with the code for whichever branch the condition selects — no if is left after macro expansion.
In top-level global scope, there's not much difference between these two since evaluation happens only once, right after the code is parsed, macro expanded and lowered. There are, however, some situations where you can't syntactically put an if expression. A good example is if you want the presence or absence of a field in a structure to be conditional on something:
have_baz_field = rand(Bool)
struct Foo
bar::Int
#static if have_baz_field
baz::Int
end
end
Here are two different evaluations of this code:
julia> have_baz_field = rand(Bool)
false
julia> struct Foo
bar::Int
#static if have_baz_field
baz::Int
end
end
julia> fieldnames(Foo)
(:bar,)
julia> have_baz_field = rand(Bool)
true
julia> struct Foo
bar::Int
#static if have_baz_field
baz::Int
end
end
julia> fieldnames(Foo)
(:bar, :baz)
Of course, randomly having a field or not isn't very useful; in practice, you'd want to have a more meaningful condition for whether to have the field or not, probably something based on the platform you're on when trying to match the layout of a C struct.
In local scope, there's more difference between if and #static if since the code can be evaluated many times whereas it is parsed only once. Since the condition is evaluated at parse time in the global scope where the expression appears, the #static if form cannot access any local variables since they don't exist when the macro is being expanded. On the other hand, if the condition of a non-static if is based only on global constants, there's a strong chance that the compiler can predict the value of the condition, so there still may not be any effective difference since the compiler will eliminate all code but the taken branch anyway. However, if you want to make sure that this happens at parse / compile time, then you can use #static if to force it.
Hopefully that clarifies the difference. In short, you rarely need #static if because it's usually equivalent in top-level scope and even in local scope, in situations where you can use #static if the compiler will probably already do the equivalent anyway. There are a few situations where #static if is required in a global scope because a branch is not syntactically allowed. In local scope, it usually isn't necessary, but may be desirable to be really sure that the condition is not evaluated at run time. In most code, you don't need #static if. In the example given in the question, for example, I would personally just use if and omit the #static since the expression appears at the top level and the condition is only evaluated once either way.
Yes, in some contexts if statements are not allowed, but macros are, or you can't, for example, define a struct in an if statement. Inside functions it might often not be necessary, but sometimes you want to be absolutely sure that the if statement gets eliminated.

Can a handlebars partial result be used as a helper's argument?

Can a handlebars partial evaluation result be used as a helper's argument?
I was hoping subexpressions would do the trick, something like:
{{myHelper otherArgument (> myPartial)}}
Needles to say, this doesn't work and I've been scratching my head for other solutions for a while now...
Surely there must be some helper that can evaluate partials?
[edit # 2020-04-04]
The background for wanting this was to be able to interpolate a partial's output into a sentence template by an internationalization hbs helper.
Though #76484's suggestion comes close to a viable solution, I've already admitted defeat because, while an answer was pending I tried recreating the partial as an hbs helper and found that no amount of Handlebars.SafeString(...) wrapping can prevent the result from getting escaped anyway after it was interpolated; so, short of modifying the i18n helper itself, it's not going to fly.

KEYWORD_SET in IDL

I am new to IDL and find the KEYWORD_SET difficult to grasp. I understand that it is a go no go switch. I think its the knocking on and off part that I am having difficulty with. I have written a small program to master this as such
Pro get_this_done, keyword1 = keyword1
WW=[3,6,8]
PRINT,'WW'
print,WW
y= WW*3
IF KEYWORD_Set(keyword1) Then BEGIN
print,'y'
print,y
ENDIF
Return
END
WW prints but print, y is restricted by the keyword. How do I knock off the keyword to allow y to print.
Silly little question, but if somebody can indulge me, it would be great.
After compiling the routine, type something like
get_this_done,KEYWORD1=1b
where the b after the one sets the numeric value to a BYTE type integer (also equivalent to TRUE). That should cause the y-variable to be printed to the screen.
The KEYWORD_SET function will return a TRUE for lots of different types of inputs that are basically either defined or not zero. The IF loop executes when the argument is TRUE.
Keywords are simply passed as arguments to the function:
get_this_done, KEYWORD1='whatever'
or also
get_this_done, /KEYWORD1
which will give KEYWORD1 the INT value of 1 inside the function. Inside the function KEYWORD_SET will return 1 (TRUE) when the keyword was passed any kind of value - no matter whether it makes sense or not.
Thus as a side note to the question: It often is advisable to NOT use KEYWORD_SET, but instead resort to a type query:
IF SIZE(variable, /TNAME) EQ 'UNDEFINED' THEN $
variable = 'default value'
It has the advantage that you can actually check for the correct type of the keyword and handle unexpected or even different variable types:
IF SIZE(variable, /TNAME) NE 'LONG' THEN BEGIN
IF SIZE(variable, /TNAME) EQ 'STRING' THEN $
PRINT, "We need a number here... sure that the cast to LONG works?"
variable = LONG(variable)
ENDIF

TCL global stumping me

I have a script where I am doing what appears to be the exact same thing, but it works in that one and not this one. I'm hoping that a few more pairs of eyes will be able to help me find out the issue, I've already spent an hour and a half on it.
I have a proc that edits the global var, it's more complex that this but I'll use this for simplicity's sake:
proc myCustomProc { var } {
global __myGlobal
set __myGlobal [ expr $__myGlobal + 1 ]
}
I have defined a variable globally in my "main" proc:
proc FOO {} {
global __myGlobal
...
...
myCustomProc 5
puts $__myGlobal
Then I get can't read "__myGlobal": no such variable
I have the exact code with a different varname working in a different script, so I'm stumped. Obviously it's NOT identical, I just cannot find the issue.
Edit: both procs are in the same .tcl file
You can't read from a variable that is unset, and that's true whether that variable is global or not. Thus, in the code:
set __myGlobal [ expr $__myGlobal + 1 ]
It first reads the value from the global variable, then adds one to that value, then writes the result back to the global variable. (Actually, it is interpreting the contents of the variable as an expression fragment, which I'd lay good money on being something you don't want as it is slow and unsafe; put the whole expression in braces please.)
For adding one to an integer (and from Tcl 8.5 onwards) you should just use the incr command instead, as that interprets a non-existent value as if it was zero:
incr __myGlobal
But if you're doing something more complex (or working in 8.4 or before), you should instead put a check with info exists like this in front:
if {![info exists __myGlobal]} {
set __myGlobal "the default value"; # Or whatever default you want
}
You could also use a more complex expression like this:
set __myGlobal [expr {[info exists __myGlobal] ? $__myGlobal+1 : 1}]
But I usually try to avoid the ternary operator; it's often not that readable.
The short answer is, you are using $__myGlobal in the expr command before it has been set.

Resources