Executing a python script in snaplogic - snaplogic

I am trying to run a python script through script snap in snaplogic. I am facing some issues where it ask me to declare a script hook variable. Can you please help me on that.

With the script snap you should use the "Edit Script" button on the snap itself. This will open a script editor and generate a skeleton script in the language you've selected (Py in this case).
In the skeleton you can see the baseline methods and functions we define. In there you can see the usage and comments of the scripthook var. If you have an existing script I would recommend trying to write it into this skeleton's execute method than trying to implement scripthook in your existing code. You can also define your own methods and functions within the confines of the skeleton class and reference them with "this." notation.
For faster answers on SnapLogic related questions I'd recommend visiting the SnapLogic Community site.

As explained by #dwhite0101, within Script Snap when you click Edit Script you get an option to generate code template.
ScriptHook is an interface that is implemented as callback mechanism for Script Snap to call into the script.
It helps you to deal with input and output rows. The constructor below initializes the input, output, error and log variables.
self object is similar to this in c++ that holds the current row values.
class TransformScript(ScriptHook):
def __init__(self, input, output, error, log):
self.input = input
self.output = output
self.error = error
self.log = log
You can perform transformations in execute method:
def execute(self):
self.log.info("Executing Transform script")
while self.input.hasNext():
in_doc = self.input.next()
wrapper = java.util.HashMap()
for field in in_doc:
#your code
Next step is to store your results in an object and output it:
wrapper['original'] = result
self.output.write(result, wrapper)
Make sure to indent your code properly.

Related

Is there a better/more pythonic way to load an arbitrary set of functions from modules in another folder?

I'm just basically asking:
if it's considered OK to use exec() in this context
if there's a better/more pythonic solution
for any input or comments on how my code could be improved
First, some context. I have main.py which basically takes input and checks to see if I've written a command. Let's say I type '/help'. The slash just tells it my input was supposed to be a command, so then it checks if a function called 'help' exists, and if so, that function will be run.
To keep things tidy in main.py, and to allow myself to add more commands easily, I have a 'commands' directory, with individual command files in it, such as help.py. help.py would look like this for example:
def help():
print("You've been helped")
So then of course, I need to import help() from help.py, which was trivial.
As I added more commands, I decided to add an init.py file where I'd keep all the command import lines of code, and then just do 'from init import *' in main.py. At first, each time I added a command, I'd add another line in init.py to import it. But that wasn't as flexible as I wanted, so I thought, there's got to be a way to just loop through all the .py files in my commands directory and import them. I struggled with this for a while but came up with a solution that works.
In the init.py snippet below, I loop through the commands directory (and a couple others, but they're irrelevant to the question), and you'll see I use the dreaded exec() function to actually import the commands.
loaded, failed = '', ''
for directory in command_directories:
command_list = os.listdir(directory)
command_list.sort()
for command_file in command_list:
if command_file.endswith(".py"):
command_name = command_file.split(".")[0]
try:
# Evil exec() hack to use variable-name directories/modules
# Haven't found a more... pythonic... way to do this
exec(f"from {directory}.{command_name} import {command_name}")
loaded = loaded + f" - Loaded: {command_name}\n"
except:
failed = failed + f" - Failed to load: {command_name}\n"
if debug == True:
for init_debug in [loaded, failed]: print(init_debug)
I use exec() because I don't know a better way to make a variable with the name of the function being loaded, so I use {command_name} in my exec string to arbitrarily evaluate the variable name that will store the function I'm importing. And... well, it works. The functions work perfectly when called from main.py, so I believe they are being imported in the correct namespace.
Obviously, exec() can be dangerous, but I'm not taking any user input into it, just file names. Filenames that I only I am creating. This program isn't being distributed, but if it was, then I believe using exec() would be bad since there's potential someone could exploit it.
If I'm wrong about something, I'd love to hear about it and get suggestions for a better implementation. Python has been very easy to pick up for me, but I'm probably missing some of the fundamentals.
I should note, I'm running python 3.10 on replit (until I move this project to another host).

How to Avoid Pylint Error For Not Passing Argument to Celery Bound Method?

The project is meant to serve a machine learning model via a REST API. Here is the celery task declaration, along with a unit test to check the function is running on a sample input.
#celery.task(bind=True)
def run_prediction(self, inpath: str) -> pandas.DataFrame:
'''
:param inpath File location of the input feature
'''
# Do a lot of stuffs
return output # type:pandas.DataFrame
if __name__=='__main__':
# Do a unit test with a sample inpath
pred:pandas.DataFrame=run_prediction(inpath=sample_inpath)
The run_prediction function can be triggered as a stand-alone normal function without caring about celery, and also as an asynchronous method with the apply_async provided by celery. (I did not expect it to have the functionality of a standalone function, so any explanation on that would be great.)
But the main issue is when I check the code via pylint (version 2.5.3), it throws an error and a warning, both saying the same thing.
model_utility.py:92:34: W0613: Unused argument 'self' (unused-argument)
model_utility.py:188:4: E1120: No value for argument 'self' in function call (no-value-for-parameter)
Does it mean somehow pylint is not aware of how to call the function? Can I update the code to have a 10/10 from pylint? Or should I change something about pylint itself?
For your information, using pylint as a package from my editor (Atom), if that is important to the discussion.

How to call an automation script from an automation script in Maximo

Could anyone tell me how to invoke an action automation script from an automation script in Maximo. I have achieved this before but can't remember/find the procedure used to call an action script.
When invoking another script, it doesn't matter if it is an action script or a script just sitting out there with no launch points (or even one already triggering on its own otherwise with, say, an object save launch point). The below code assumes Jython and Maximo of at least 7.6.0.x (I forget exactly what version added this feature).
First, you do need to make sure you import java.util.HashMap into your script. Then, you start by creating a new HashMap. This is the script context that you will put all of your implicit variables into for the other script. You then use the "invokeScript" method of the implicit service or script context (if this is in an integration script) object. The first parameter of that method is the name of the new script you want to invoke and the second parameter is your HashMap that is the context for the new script.
from java.util import HashMap
subScriptCtx = HashMap()
subScriptCtx.put("mbo", woMbo)
subScriptCtx.put("var1", someObject)
subScriptCtx.put("var2", MXServer.getMXServer().getDate())
...
service.invokeScript("OTHERSCRIPTNAME", subScriptCtx)

Load Steps into Console?

Is it possible to load the step definitions I have defined into the calabash-android console?
I would like to be able to use them when navigating the app within the console.
Thanks
No from the console you can not run a single step definition.
But you can start execution of a test at a specific line appending parameter to the call to start your test
:<linenumber>
This will start execution of your feature file from that specific line and it will run from there to the end of the file.
So while it is not what you are looking for at least it is something.
Did you try step('<step_name>') method?
To be honest I'm not sure if this will work. I know it's working insinde Ruby methods and step definitions - I wanted to post a comment but I can't with 28 points of reputation ;)
You can also try making ruby methods with code from within the step definition:
Then /^I do something$/ do
some code
goes here
end
def do_something
some code
goes here
# same code as in step definition
end
or just use step method:
def do_something
step('I do something')
end
and then call it in a calabash console (I prefer using binding.pry inside some script rather than calling "pure" calabash-console - it makes me sure that I will have all needed methods included).

python interpreter running shutdown code when I don't want it to

I'm using Python 3. I'm still learning but am, let's say, an intermediate at other programming languages. I'm building a simple GUI that just does simple things for now but will add on more things as I go. I've got some success. Then I had an idea, to have a function (or whatever it's called in Python) to run an external script, stored in my script folder. So I wrote this...
def runscript(scriptname):
from subprocess import call
call(['scripts/'+scriptname])
Then later on in my code I have this...
sdb = Button(topbar, text="Shutdown", command= runscript("shutdown.sh"), font=("Helvetica", 20), width=18)
shutdown.sh is a simple script that does what you might expect it to.
Now whenever I run the python script with python3 MyScript.py the machine instantly shuts down! I obviously only want it to shut down when I click the Shutdown button. From reading I gather it's to do with the fact that Python executes every line as it goes. So I don't understand why there are plenty of examples around on the internet for functions that will shutdown your PC, whereas my more general script-running code doesn't work in any useful way.
When you write the code runscript("shutdown.sh"), what should it do?
Obviously, the answer is that it should call the runscript function and pass it the argument "shutdown.sh".
So, when you write the code command=runscript("shutdown.sh"), what should it do?
Do you see the problem? You're executing the runscript function, and passing the result of that function to the command attribute. Instead, the command attribute takes a reference to a callable function. Since you are trying to pass in an explicit argument, one way to accomplish that is with lambda:
sdb = Button(..., command=lambda script="shutdown.sh": runscript(script))
Some people prefer functools.partial over lambda:
sdb = Button(..., command=functools.partial(runscript, "shutdown.sh"))

Resources