Calling a function whos name is stored in a string - string

I have a function e.g.
function run()
print("hi")
end
I have a string called message which contains the word "run":
activity = message
print(activity) --returns run
However I am unable to use the string activity to run the function run(). I have tried:
func = loadstring(activity.."()")
func() -- I get an error on line 1 saying: attempt to call nil

Well, the function run is stored in _G so the simple answer:
_G[message]()

function run() print("hi") end
activity = "run"
loadstring(activity.."()")()
This works fine as long as loadstring is running in the same environment as run. In other words, the loadstring line is equivalent to _G[activity](). If the global run was created in some other environment, that'll evaluate to nil.
Given that Lua functions are first class values, just like strings, if at all possible it would be better to do this:
function run() print("hi") end
activity = run
activity()
Though if this is in a context where you're getting a string value from config file or something, that wouldn't work.

Related

QCheckbox issue [duplicate]

I am struggling to get this working.
I tried to transpose from a c++ post into python with no joy:
QMessageBox with a "Do not show this again" checkbox
my rough code goes like:
from PyQt5 import QtWidgets as qtw
...
mb = qtw.QMessageBox
cb = qtw.QCheckBox
# following 3 lines to get over runtime errors
# trying to pass the types it was asking for
# and surely messing up
mb.setCheckBox(mb(), cb())
cb.setText(cb(), "Don't show this message again")
cb.show(cb())
ret = mb.question(self,
'Close application',
'Do you really want to quit?',
mb.Yes | mb.No )
if ret == mb.No:
return
self.close()
the above executes with no errors but the checkbox ain't showing (the message box does).
consider that I am genetically stupid... and slow, very slow.
so please go easy on my learning curve
When trying to "port" code, it's important to know the basis of the source language and have a deeper knowledge of the target.
For instance, taking the first lines of your code and the referenced question:
QCheckBox *cb = new QCheckBox("Okay I understand");
The line above in C++ means that a new object (cb) of type QCheckBox is being created, and it's assigned the result of QCheckBox(...), which returns an instance of that class. To clarify how objects are declared, here's how a simple integer variable is created:
int mynumber = 10
This is because C++, like many languages, requires the object type for its declaration.
In Python, which is a dynamic typing language, this is not required (but it is possible since Python 3.6), but you still need to create the instance, and this is achieved by using the parentheses on the class (which results in calling it and causes both calling __new__ and then __init__). The first two lines of your code then should be:
mb = qtw.QMessageBox()
cb = qtw.QCheckBox()
Then, the problem is that you're calling the other methods with new instances of the above classes everytime.
An instance method (such as setCheckBox) is implicitly called with the instance as first argument, commonly known as self.
checkboxInstance = QCheckBox()
checkboxInstance.setText('My checkbox')
# is actually the result of:
QCheckBox.setText(checkboxInstance, 'My checkbox')
The last line means, more or less: call the setText function of the class QCheckBox, using the instance and the text as its arguments.
In fact, if QCheckBox was an actual python class, setText() would look like this:
class QCheckBox:
def setText(self, text):
self.text = text
When you did cb = qtw.QCheckBox you only created another reference to the class, and everytime you do cb() you create a new instance; the same happens for mb, since you created another reference to the message box class.
The following line:
mb.setCheckBox(mb(), cb())
is the same as:
QMessageBox.setCheckBox(QMessageBox(), QCheckBox())
Since you're creating new instances every time, the result is absolutely nothing: there's no reference to the new instances, and they will get immediately discarded ("garbage collected", aka, deleted) after that line is processed.
This is how the above should actually be done:
mb = qtw.QMessageBox()
cb = qtw.QCheckBox()
mb.setCheckBox(cb)
cb.setText("Don't show this message again")
Now, there's a fundamental flaw in your code: question() is a static method (actually, for Python, it's more of a class method). Static and class methods are functions that don't act on an instance, but only on/for a class. Static methods of QMessageBox like question or warning create a new instance of QMessageBox using the provided arguments, so everything you've done before on the instance you created is completely ignored.
These methods are convenience functions that allow simple creation of message boxes without the need to write too much code. Since those methods only allow customization based on their arguments (which don't include adding a check box), you obviously cannot use them, and you must code what they do "under the hood" explicitly.
Here is how the final code should look:
# create the dialog with a parent, which will make it *modal*
mb = qtw.QMessageBox(self)
mb.setWindowTitle('Close application')
mb.setText('Do you really want to quit?')
# you can set the text on a checkbox directly from its constructor
cb = qtw.QCheckBox("Don't show this message again")
mb.setCheckBox(cb)
mb.setStandardButtons(mb.Yes | mb.No)
ret = mb.exec_()
# call some function that stores the checkbox state
self.storeCloseWarning(cb.isChecked())
if ret == mb.No:
return
self.close()

Passing a function (with arguments) as an argument in Python

I am measuring performance of different sorting methods using Python built-in library timeit. I would like to pass a function and an integer as arguments to the statement being tested in timeit(). I tried the following:
def sort_1(l):
...
return l_sorted
def test(f: Callable, l_len: int):
l = np.random.rand(low=-1000, high=1000, size=l_len)
f(l)
timeit.timeit(stmt=test(sort_1, l_len=10), number=1000)
... with a ValueError saying that stmt is neither a string nor callable. The error doesn't occur when I call it like this:
timeit.timeit(stmt=test, number=1000)
... but then I cannot pass any argument to test(). What is a general solution if someone wants to pass arguments to a function given as an argument? (let's say, when a method is already implemented and there is not way to pass arguments in a separate argument)
Cheers
Edit:
#jonrsharpe, thanks! The solution looks like this:
timeit.timeit(stmt='test(f=sort_1, l_len=10)', number=100, globals=globals())

Drawing an image loaded from other files (love2d)

So I have a "load_assets.lua" file inside my game folder along with the "main.lua". Inside the "load_assets.lua" file I have a "love.graphics.newImage(image)"
and in the "main.lua" file I have the "love.graphics.draw(image)".
I've tried to create this function inside the "main.lua" file:
function love.draw(i)
love.graphics.draw(i)
end
and this function inside the "load_assets.lua" file:
image = love.graphics.newImage(image)
lovedraw(image)
but it still doesn't seem to work.
Of course, the code is a little more complex than this, but similar:
--in "main.lua" the function is actually:
function title(lvl0)
love.graphics.draw(lvl0)
end
--and in "load_assets" it's:
function love.load()
lvl0 = love.graphics.newImage("lvl0.png")
end
title(lvl0)
When I run the code I get this error:
Error
title.lua:3: bad argument #1 to 'draw' (Drawable expected, got nil)
Traceback
[C]: in function 'draw'
title.lua:3: in function 'title'
main.lua:16: in main chunk
[C]: in function 'require'
[C]: in function 'xpcall'
[C]: in function 'xpcall'
I don't know the specifics of your code, but the following worked for me:
load_assets.lua
function love.load()
lv10 = love.graphics.newImage("image.png")
end
main.lua
require("load_assets")
function title(lv10)
love.graphics.draw(lv10)
end
function love.draw()
title(lv10)
end
Love2d has several built in functions that you can override to create your program. Ideally, all your function calls happen from within these programs.
So, in load_assets.lua I override the love.load() function to create lv10. By default love.load() is called exactly once, at the start of the program.
In main.lua I define the title() function, then override love.draw() to call title(). By default, love.draw() is called every update cycle of the love engine (every frame).

how to use testrunner.fail in groovy class for soapui

I am trying to fail the test case if string values are not same.I have created a class and a method to compare the string values.
public class test1 {
public String onetwo(str1,str2)
{
def first = str1
def second=str2
if (first==second)
{
return "Strings are same"
}
else
{
testrunner.fail("String Values are not same")
}
}
public String fail(reason)
{
return "implementation of method1"+reason
}
}
def objone =new test1()
def result = objone.onetwo('Soapui','Soapui')
def result1 = objone.onetwo('Soapui','SoapuiPro')
while executing it i am getting below message for last line of above code
ERROR:groovy.lang.MissingPropertyException: No such property: testrunner for class: test1
Please suggest how to use testrunner.fail or any other way to fail the test case if strings are not same.
Thank You
It can't find SoapUI's testrunner because you're accessing it inside your own class. (Note that the error message is trying to find test1.testrunner, which of course does not exist.) If you accessed testrunner from the top level of the script (where you define your variables) it should work.
If you still want to have a reusable class/method, an easy fix would be to have it return a boolean or an error message, and then you call testrunner.fail if your method returns false/error. Something like this (although a boolean return might make for cleaner code):
public class test1 {
public String onetwo(str1,str2)
{
def first = str1
def second=str2
if (first==second)
{
return "Strings are same"
}
else
{
return "String Values are not same"
}
}
...
}
def objone =new test1()
def result = objone.onetwo('Soapui','Soapui')
def result1 = objone.onetwo('Soapui','SoapuiPro')
if (result != "Strings are same")
{
testrunner.fail(result)
}
...
This thread from another site also describes a much more complex solution of making reusable Groovy libraries for SoapUI.
If two strings are to be compared in groovy script test step, then it is not required to write a class, instead can be achieved with below statement.
Matching Samples - note that nothing happens on successful assertion
String compare and fail if not equal
assert 'Soapui' == 'Soapui', "Actual and expected does not match"
Another example - with boolen
def result = true;assert result, "Result is false"
Non-Matching example - test fails on failure
Strings not matching, and shows error message
assert 'Soapui' == 'SoapuiPro', "Actual and expected does not match"
Another example with non zero test
def number=0;assert number, "Number is zero"
If you need only example of the class and like to access testRunner object, then we need pass it either to the class or to the method where testRunner is needed. Otherwise, other class do not know about the objects that are available to groovy script.
Here is some more information on the objects availability at various level of test case hierarchy.
When soapUI is started, it initializes certain variables and are available at Project, Suite, Test case, Setup Script, Teardown script etc., If you open the script editor you would see the objects available there.
For instance, groovy script test step has log, context, testRunner, testCase objects. However, if some one creates a class with in Groovy Script test step, those objects are not available with in that user defined class.

Calling groovy method from script

I'm writing a program in groovy, I want it to run a script with dynamically changing variables. The script is supposed to execute a method with its variables. This method is located in the program that runs the script.
The script would contain something like this:
// getAttribute is a method in my main program, the program which also runs the script
value = getValue("java.lang:type=OperatingSystem", "FreePhysicalMemorySize")
// do something with the value
if (value > 9000) { output = "ERROR" }
// the same thing maybe a few more times
value = getValue(...
I want to keep it as simple as possible.
I was working with these examples: http://groovy.codehaus.org/Embedding+Groovy
I already tried to use the GroovyScriptEngine, but it seems like the script only accepts Strings as input values. It would be great if I could hand over method pointers.
Just trying to hand over an integer like this:
def roots = 'PATH\\script.groovy'
def groscreng = new GroovyScriptEngine(roots)
def binding = new Binding()
def input = 42
binding.setVariable("input", input)
groscreng.run("script.groovy", binding)
println binding.getVariable("output")
With this script.groovy
output = ${input}
results in this error:
Caught: groovy.lang.MissingMethodException: No signature of method: script.$() is applicable for argument types: (script$_run_closure1) values: [script$_run_closure1#fcf50]
Possible solutions: is(java.lang.Object), run(), run(), any(), any(groovy.lang.Closure), use([Ljava.lang.Object;)
Receiving the value in the script as a String like "${input}" works just fine.
I know it has to work somehow and I would appreciate any help or other suggestions!
output = ${input}
isn't valid groovy
Try:
output = input

Resources