Robot Framework: Calling external Keyword from Python file - frameworks

I have a Keyword created in external python file which takes only one argument. When called in Ride, I get the error message (displayed below):
Keyword 'CustomUtilityLibrary.CUSTOM Get List Count' expected 1 argument, got 6.
This is the keyword definition
def CUSTOM_Get_List_Count(self, s1):
"""Returns the total number of elements in a list
"""
return len(s1)

This is likely due to an error in your test case. If robot is saying the function was called with six arguments, then it was called with six arguments.
It appears that your function takes a list as an argument. My guess is that you are calling it like this:
| | ${count}= | Get List Count | #{the_list}
The correct syntax for the last line in that example should use $ rather than #:
| | ${count}= | Get List Count | ${the_list}
The reason being, when you use #{some variable}, it expands the variable so that each element of the list is an argument. What you want instead is to pass the whole list as a single argument, and the syntax for that is to reference the list variable with $.
The robot framework user's guide has this to say about list variables:
When you use a list variable in test data, then the elements of the
list are inserted as new cells in the test data. Thus, if the list
variable contains two elements, the cell containing the list variable
is turned into two cells with the content of the list variable.
...
It is possible to use list variables as scalar variables containing
lists simply by replacing # with $

Related

why `echo HTTPS_PROXY=$HTTPS_PROXY` print an empty line when variable not set?

shouldn't it be printing out HTTPS_PROXY= instead? (when $HTTPS_PROXY is not set)
I know I can work around using
echo HTTPS_PROXY=(echo $HTTPS_PROXY) or echo HTTPS_PROXY="$HTTPS_PROXY" , but I want to know why I need a work around in this case.
In fish, all variables are lists. When you concatenate a string and a variable, what it does is combine every list element with the string.
So
set bar 1 2 3
echo foo$bar
prints "foo1 foo2 foo3".
Now, when you have an undefined variable (or an empty one, set like set bar without values), this combines nothing with the string, which ends up eliminating it.
You can think of it like any variable expansion being a brace expansion - echo foo{1,2,3} is the same as echo foo$bar with bar set like above.
In many cases, that is exactly what you want. Imagine $bar being a list of directories. To go over all files in them you could use
for file in $bar/*
and if $bar was empty (there was no directory), the entire loop would be skipped instead of e.g. showing all files in "/".
The obvious solution is to quote the variable if you want to supress this. Quoting turns the variable into always exactly one argument, even if it's empty or has multiple elements, so
echo foo"$bar"
prints "foo1 2 3" (as one argument).
This is documented at https://fishshell.com/docs/current/#combining-lists-cartesian-product.

kdb: differences between value and eval

From KX: https://code.kx.com/q/ref/value/ says, when x is a list, value[x] will be result of evaluating list as a parse tree.
Q1. In code below, I understand (A) is a parse tree, given below definition. However, why does (B) also work? Is ("+";3;4) a valid parse tree?
q)value(+;3;4) / A
7
q)value("+";3;4) / B
7
q)eval(+;3;4) / C
7
q)eval("+";3;4) / D
'length
[0] eval("+";3;4)
Any other parse tree takes a form of a list, of which the first item
is a function and the remaining items are its arguments. Any of these
items can be parse trees. https://code.kx.com/q/basics/parsetrees/
Q2. In below code, value failed to return the result of what I think is a valid parse tree, but eval works fine, recursively evaluating the tree. Does this mean the topmost description is wrong?
q)value(+;3;(+;4;5))
'type
[0] value(+;3;(+;4;5))
^
q)eval(+;3;(+;4;5))
12
Q3. In general then, how do we choose whether to use value or eval?
put simply the difference between eval and value is that eval is specifically designed to evaluate parse trees, whereas value works on parse trees among other operations it does. For example value can be used to see the non-keyed values of dictionaries, or value strings, such as:
q)value"3+4"
7
Putting this string instead into the eval, we simply get the string back:
q)eval"3+4"
"3+4"
1 Following this, the first part of your question isn't too bad to answer. The format ("+";3;4) is not technically the parsed form of 3+4, we can see this through:
q)parse"3+4"
+
3
4
The good thing about value in this case is that it is valuing the string "+" into a the operator + and then valuing executing the parse tree. eval cannot understand the string "+" as this it outside the scope of the function. Which is why A, B and C work but not D.
2 In part two, your parse tree is indeed correct and once again we can see this with the parse function:
q)parse"3+(4+5)"
+
3
(+;4;5)
eval can always be used if your parse tree represents a valid statement to get the result you want. value will not work on all parse tree's only "simple" ones. So the nested list statement you have here cannot be evaluated by value.
3 In general eval is probably the best function of choice for evaluating your parse trees if you know them to be the correct parse tree format, as it can properly evaluate your statements, even if they are nested.

kdb/q question: How do I interpret this groupby in my functional selection?

I am new to kdb/q and am trying to figure out what this particular query means. The code is using functional select, which I am not overly comfortable with.
?[output;();b;a];
where output is some table which has columns size time symbol
the groupby filter dictionary b is defined as follows
key | value
---------------
ts | ("+";00:05:00v;("k){x*y div x:$[16h=abs[#x];"j"$x;x]}";00:05:00v;("%:";`time)))
sym | ("k){x'y}";"{`$(,/)("/" vs string x)}";`symbol)
For the sake of completeness, dictionary a is defined as
volume ("sum";`size)
In effect, the functional select seems to be bucketing the data into 5 minute buckets and doing some parsing in symbol. What baffles me is how to read the groupby dictionary. Especially the k)" part and the entire thing being in quotes. Can someone help me go through this or point me to resources that can help me understand? Any input will be appreciated.
The aggregation part of the function form takes a dictionary, the key being the output key column names and the values being parse tree functions.
A parse tree is an expression that is not immediately evaluated. The first argument as a function and subsequent elements are its arguments. The inner-most brackets are evaluated first and then it moves up the heirarchy, evaluating each one in turn. More detailed information can be found here and in the whitepaper linked on that page
You can use the function parse with a string argument to get the parse tree of a function. For example, the parse tree for 1+2+3 is (+;1;(+;2;3)):
q)parse "1+2+3"
+
1
(+;2;3)
The inner-most bracket (+;2;3) is evaluated first resulting in 5, before the result is propogated up to the outmost parse tree function (+;1;5) giving 6
The groupby part of the clause will evaluate one or more parse tree functions and then will collect together records with the same output from the grouping function.
Making the function a bit clearer to read:
(+;00:05:00v;({x*y div x:$[16h=abs[#x];"j"$x;x]}";00:05:00v;(%:;`time)))
Looking at the inner most bracket (%:;`time), it returns the result of %: applied on the time column. We can see that %: is k for the function ltime
q)ltime
%:
Moving up a level, the next function evaluated is the lambda function {x*y div x:$[16h=abs[#x];"j"$x;x]} with arguments 00:05:00v and the result of our previous evaluated function. The lambda rounds it down the the nearest 5 minute interval
({x*y div x:$[16h=abs[#x];"j"$x;x]};00:05:00v;(%:;`time))
Moving up once more to the whole expression it is equivalent to 00:05:00v + {x*y div x:$[16h=abs[#x];"j"$x;x]};00:05:00v;(%:;`time)), with 00:05:00 being added onto each result from the previous evaluation.
So essentially it first returns the local time of the timestamp, then
For the symbol aggregation
("k""{x'y}";{`$(,/)("/" vs string x)};`symbol)
The inner function {`$(,/)("/" vs string x)} strings a symbol, splits it at "/" character and then joins it back together, effectively removing the slash
The "k" is a function that evaluates the string using the k interpreter.
"k""{x'y}"" returns a function which itself takes a function x and argument y and modifies the function to use the each-both adverb '. This makes it so that the function x is applied on each symbol individually as opposed to the column as a whole.
This could be implemented in q instead of k like so:
({x#'y};{`$(,/)("/" vs string x)};`symbol)
The function {x#'y} takes the function argument {`$(,/)("/" vs string x)} and the symbol column as before, but we have to use # with the each-both adverb in q to apply the function on the arguments.
The aggregation function will then be applied to each group. In your case the function is a simple parse tree, which will return the sum of the size columns in each group, with the output column called volume
a:enlist[`volume]!enlist (sum;`size)

How to pass arguments by reference to robot framework keywords?

I have a keyword in robot framework; it takes an argument, performs some process on it and returns it after all:
My Keyword Name
[Arguments] ${arg}
# Some process on ${arg}
[Return] ${arg}
So it would be the usage:
${x} = My Keyword Name ${x}
Which implies that I gave the old value of ${x} to the keyword and it returned me the new value of it.
I want to make a call by reference on My Keyword Name, so I don't need to use an assignment for setting new value for ${x}. I have read the BuiltIn and UserGuide,
but there was no line about this subject. Can anyone help me on this?
If ${x} is a mutable type such as a list or dictionary, you can pass the object itself. If it represents a scalar value such as a string or int, you can't do what you want. Your only choice is to return the new value and re-assign it to the original variable.
It will work if you initialize the variable as
My Keyword Name
[Arguments] ${arg}
${arg} = Set Variable 56
[Return] ${arg}
Test
Log To Console \n\nin Test
${x} = Set Variable 0
${x} = My Keyword Name ${x}
Log To Console ${x}
Or
Can you explore whether you can make use of Set Global Variable or Set Test Variable?
I'd spent some time before i got the solution!
* Variables
${someVar} initial value
* Test Cases
[Check reference]
Set this \${someVar} new value
Should Be Equal ${someVar} new value
* Keywords
Set this
[Arguments] ${varName} ${value}
Set Test Variable ${varName} ${value}
The point is in the magic "\" char :)
It actually comes down to mutable/immutable variables in python, and how they are passed to functions.
Details here in this answer, but in RF context it boils down to - you can change lists and dictionaries, and not strings and numbers (int, float). Example:
A testcase
Log To Console \n
${var}= Create List member1
Log To Console ${var}
Mutate The List ${var}
Log To Console ${var}
*** Keywords ***
Mutate The List
[Arguments] ${lst}
Append To List ${lst} new one
The output when ran would be:
==============================================================================
A testcase
['member1']
['member1', 'new one']
| PASS |
, e.g. the variable defined in the case got changed by a keyword. The same can be done with dictionaries.
If you reassign the variable in the function though, it will not change; e.g. with a keyword like this:
Mutate The Dict
[Arguments] ${lst}
${lst}= Create List fsf
Append To List ${lst} bogus
, the original variable ${var} will not be changed.
Why so? In short, in python variables are just identifiers ("names") to memory addresses; when you assign ${lst} to a new list, the variable now points to a new address in the memory, and further interactions don't change the original one.
Welp I just ran into the same issue, as I was using a Run Keyword If statement in a For Loop. Knowing that if I used a keyword that returns a value, robot framework freaks out.
So I just thought of this as a potential solution. It'll use my example. It does have redundancy, but thats because you just have to in this case.
***Keywords***
| Increment | [Arguments] | ${var} |
| | ${var} | Evaluate | ${var} + 1 |
| | Set Test Variable | ${var} | ${var} |
Usage:
| Increment | ${idx} |
| Set Test Variable | ${idx} | ${var}
Now I'm not saying this is the best solution, but if you run into the scenario that you have to return a value to a variable with a keyword, and you're inside a "Run Keyword If", this should allow you to circumvent the issue. I don't really like it that much, but it gets the job done.

writing the input arguments for a function in matlab

I am using this function on matlab
[ProbData,HazData] = cdsbootstrap(ZeroData,MarketData,Settle,[],[],[],[],[],[],0.25)
and it is giving me an error because it dose not understand the [ ].
I want to keep the default inputs from 4-->9 and change the ninth input to 0.25. What should I put instead of the [ ]?
The function cdsbootstrap uses matlab's very common Name/Value pair syntax. Read the first few lines here:
Specify optional comma-separated pairs of Name,Value arguments. Name
is the argument name and Value is the corresponding value. Name must
appear inside single quotes (' '). You can specify several name and
value pair arguments in any order as Name1,Value1,...,NameN,ValueN.
So if you wanted ALL default values, you would use the call:
[ProbData,HazData] = cdsbootstrap(ZeroData,MarketData,Settle);
If you wanted to change one of these possiblities you would simply include the name and value, all names omitted are set to defaults. Based on your value of 0.25 I'm going to assume you are trying to set the RecoveryRate since 0.25 is close to the default.
[ProbData,HazData] = cdsbootstrap(ZeroData,MarketData,Settle,'RecoveryRate',0.25);
Ref:
http://www.mathworks.com/help/fininst/cdsbootstrap.html