Is there a way to write single prepare function for all the KPIs in Gramex - gramex

I have a common function which needs to be evaluated before executing all the KPIs. So I wrote a prepare function but prepare function is calling for all the KPIs separately. Instead I want a prepare function to be executed once for the each endpoint. My endpoint is like this
project-test:
pattern: /$YAMLURL/test
handler: FormHandler
kwargs:
auth: &AUTH
login_url: /$YAMLURL/login
kpi1:
prepare: validations.validate_request(args, handler)
url: $CONNECTION_STRING
queryfunction: queries.query1(args)
kpi2:
prepare: validations.validate_request(args, handler)
url: $CONNECTION_STRING
queryfunction: queries.query2(args)
modify: project.refactor(data, handler)
I tried to giving prepare function in the kwargs but getting
AttributeError: 'str' object has no attribute 'get'

The approach you shared is correct. The error may be in one of the custom functions, e.g. validations.validate_request, queries.query* or project.refactor
To test this, I created the following data1.csv
a,b
1,2
3,4
... and data2.csv
a,b
4,5
6,7
This is my gramex.yaml
url:
project-test:
pattern: /$YAMLURL/test
handler: FormHandler
kwargs:
kpi1:
prepare: validations.validate_request(args, handler)
url: data1.csv
kpi2:
prepare: validations.validate_request(args, handler)
url: data2.csv
... and this is my validations.py:
def validate_request(args, handler):
print(args, handler)
args['_c'] = ['a'] # Filter column 'a' alone
When I visit /test, the output only shows column 'a':
{"kpi1":[{"a":1},{"a":3}],"kpi2":[{"a":4},{"a":6}]}
... and the command prompt shows that the prepare function is called once for each dataset:
{'_limit': [10000]} <gramex.services.FormHandler object at 0x000001B1C14A43C8>
{'_limit': [10000]} <gramex.services.FormHandler object at 0x000001B1C14A43C8>
Perhaps you could share the full error message about where the AttributeError appeared? That might help.

I guess this is more of a prepare function issue. Could you please check if you are trying to access a string using its key. Just a quick hypothesis - check if any of your dict is in json/ string format.

Related

How to set each startup parameter '--' to accept multiple https parametersfunction second-instance?

In second-instance, I want to receive data with double URL like
The actual operation effect is as follows
there is a solution in github https://github.com/electron/electron/issues/34195
But it needs an extra parameter --
I can't do it by electron.lnk
Every time I open the program with cmd, I can't add this parameter.
Is there any way to implement it through code.
actual parameters
[
"electron.exe",
"--allow-file-access-from-files",
"https://github.com/1",
"https://github.com/2",
"3"
]
I tried below method but it didn't work
const args = []
args.push('--')
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, args)

How to set startup parameters when electron is turned on and use it when it is turned on for the second time. function second-instance

In second-instance,
I want to receive data with double URL like
[
"electron.exe",
"--allow-file-access-from-files",
"https://github.com/1",
"https://github.com/2",
"3"
]
But it needs an extra parameter --
How can I add parameter -- by default in my program, not when it is called externally
I tried below method but it didn't work
const args = []
args.push('--')
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, args)
And I can't do it by electron.lnk ,Is there any way to implement it through code

How to access Global variable/ functions in vars/*.groovy Jenkins Library without call method?

Noob in Shared library,
I am puzzled with Jenkins document section 'Loading Libraries dynamically'.
Followed the Stackoverflow_answer, but I have some different needs, just wanted to call a function from library to pipeline with an argument.
Note: Jenkins library configuration is correct and library access is already checked with another example with call method
vars/foo.groovy contains function
//{Root}/vars/foo.groovy
def Foo_Func(Body){
Body= Body + "This is a Message from Shared Lib."
return Body
}
Body Variable is already defined into main Pipeline 'bar.jenkinsfile'
My real problem is how to call the function from foo.groovy without using call method,
I have tried following -
//somefolder_in_scm/bar.jenkinsfile
#Library('jenkins-shared-libs') _
def Body_Main=""
deg SUBJECT="Title 1"
def NativeReceivers = "abc#xyz.com"
pipeline{
node any
stage{
script {
/*Some script*/
}
}
post {
always {
script {
foo.Foo_Func(Body_Main)
// send email
emailext attachLog: true,
mimeType: 'text/html',
subject: SUBJECT,
body: Body_Main,
to: NativeReceivers
}
}
}
}
Since I have used _, I expect that no import needed.
Error which is occurred after triggering pipeline,
groovy.lang.MissingMethodException: No signature of method: java.lang.Class.Foo_Func() is applicable for argument types:
In the error, why function Foo_Func is treated as a class? It might possible that the argument need to be given in different way.
Any help is appreciated.
Have you tried declaring a Field ?
#groovy.transform.Field
def myVar = "something"
script.myScript.myVar
Assuming your file is myScript.groovy.
I am writing an shared lib too.
I think the problem is in the:
def Foo_Func(Body)
what works for me is:
def Foo_Func(Map Body)
so if you try:
def Foo_Func(String Body)
it should work. I think it can't find the function with the right signature.

Why is 'name' nil for debug.getinfo(1)

I'm trying to put together a lua testing framework that lets you know the function that had the problem, but when I switched from loadstring to _G, (I switched so my test harness could see the results of the function call) my functions started using 'nil' for the function name
Why can _G not detect the name of the current function in the following code? Also, how can I get the return results from loadstring (ie the 'false' from the blah call) or set the function name when using _G (ie. Tell the lua interpreter what the function name should be)?
function run_test(one, two)
if one ~= two then
print(debug.getinfo(2).name..' Failed')
end
end
function blah()
run_test(false, true)
return false
end
local fname = 'blah'
local status, result = pcall(_G[fname]) -- Outputs 'nil'; result is 'false'
local status, result = pcall(loadstring(fname..'()')) -- Outputs 'blah', result is 'nil'
The main thing I need is a way to call a function using a string of the function name, be able to see the function name inside the call (for test failures to point to the function that failed, like fname = 'blah' in the code above) and be able to get the return value
local fname = 'blah'
status, result = pcall(??Call fname somehow??)
assert(status)
assert(not result)
--stdout should be "blah Failed"
This is a limitation of the heuristics used by Lua to provide names for functions.
In Lua, all functions are anonymous. A given function can be the value of several variables: global, local, and table fields. The Lua debug system tries to find a reasonable name for a value based on where it came from by looking into the bytecode being executed.
Consider the simpler example
blah()
pcall(blah)
In the first call, the debug system sees that the function being called comes from the global blah and debug.getinfo(1).name gives the expected result, blah.
In the second call, the debug system sees that the function being called comes from the first argument to pcall but it does not look further to see where that argument came from, and debug.getinfo(1).name gives nil.
The same thing happens when you call _G[name](). All the debug system sees is a field of a table and the name of the field is too far off.
Try adding print(debug.traceback()) as the first line of blah to see another take on this explanation.

How to handle un-named parameters when one can be piped

I want my Powershell script to be able to handle two parameter sets as shown below.
Set 1:
Param1: GroupName via pipe
Param2: FilePath
Called like: "GROUPNAME" | script.ps1 FilePath
Set 2:
Param1: GroupName
Param2: FilePath
Called like: script.ps1 GroupName FilePath
In both cases both arguments are mandatory.
I have tried everything I can think of and the closest I think I have gotten is this:
[CmdletBinding(DefaultParameterSetName="Pipe")]
param (
[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$false,HelpMessage="AD Group Name",ParameterSetName="Param")]
[Parameter(Mandatory=$true,ValueFromPipeline=$true,HelpMessage="AD Group Name",ParameterSetName="Pipe")]
[ValidateNotNullOrEmpty()]
[String]$GroupName,
[Parameter(Mandatory=$true,Position=1,ValueFromPipeline=$false,HelpMessage="Path to CSV",ParameterSetName="Param")]
[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$false,HelpMessage="Path to CSV",ParameterSetName="Pipe")]
[ValidateNotNullOrEmpty()]
[String]$FilePath
)
This does not work, as it always expect the second argument at position 1; any ideas?
You don't need two parameter sets. ValueFromPipeline=$true makes the function accept input from the pipeline, but doesn't require that it come from the pipeline - it can be specified as an argument just as well.

Resources