I'm trying to create and pass a new record which contains a map from the jython processor in streamsets but getting this error? - jython

I want the newRecord to containt a map of column names and column values. I am getting the following error which I am not able to resolve -
Record1-Error Record1 SCRIPTING_04 - Script sent record to error: write(): 1st arg can't be coerced to com.streamsets.pipeline.stage.util.scripting.ScriptRecord : (View Stack Trace... )
from datetime import datetime
metadata_dict = {}
for metadata in sdc.records[0].value['XMLData']['Metadata'][0]['FieldDefinitions'][0]['FieldDefinition']:
metadata_dict [metadata['attr|id']] = metadata ['attr|alias']
for record in sdc.records:
try:
for row in record.value['XMLData']['Record']:
newRecord = sdc.createRecord(str(datetime.now()))
newRecord = sdc.createMap (False)
value = row ['Field']
for values in value:
column_id = values ['attr|id']
column_name = metadata_dict [column_id]
for a in values:
if a == 'value':
column_value = values ['value']
elif a == 'ListValues':
column_value = values ['ListValues']
elif a == 'Groups':
column_value = values ['Groups']
elif a == 'Users':
column_value = values ['Users']
newRecord[column_name] = column_value
sdc.output.write(newRecord)
except Exception as e:
sdc.error.write(record, str(e))

You have a bug in your code:
newRecord = sdc.createMap (False)
Here, you create a map and place it into a newRecord variable.
sdc.output.write(newRecord)
Here, you're trying to write a map, not a record, into the output.
You should do something like:
newRecord = sdc.createRecord(...
myMap = sdc.createMap(...)
myMap['foo'] = 'bar'
newRecord.value = myMap

Related

Return table value index via metatable

I'm looking for a way to retrive index value via metatable. This is my attempt:
local mt = { __index =
{
index = function(t, value)
local value = 0
for k, entry in ipairs(t) do
if (entry == value) then
value = k
end
end
return value
end
}
}
t = {
"foo", "bar"
}
setmetatable(t,mt)
print(t.index(t,"foo"))
Result is 0 instead of 1. Where I'm wrong?
My attempt:
local mt = {
__index = function(t,value)
for index, val in pairs(t) do
if value == val then
return index
end
end
end
}
t = {
"foo",
"bar",
"aaa",
"bbb",
"aaa"
}
setmetatable(t,mt)
print(t["aaa"]) -- 3
print(t["asd"]) -- nil
print(t["bbb"]) -- 4
print(t["aaa"]) -- 3
print(t["bar"]) -- 2
print(t["foo"]) -- 1
Result is 0 instead of 1. Where [am I] wrong?
The code for the index function is wrong; the problem is not related to the (correct) metatable usage. You're shadowing the parameter value when you declare local value = 0. Subsequent entry == value comparisons yield false as the strings don't equal 0. Rename either the parameter or the local variable:
index = function(t, value)
local res = 0
for k, entry in ipairs(t) do
if entry == value then
res = k
end
end
return res
end
An early return instead of using a local variable in the first place works as well and helps improve performance.
To prevent such errors from happening again, consider getting a linter like Luacheck, which will warn you if you shadow variables. Some editors support Luacheck out of the box; otherwise there are usually decent plugins available.

using paste0 in file name in exams2moodle

I am trying to create a loop to automatize exams generation using the examspackage....
I have created a series of exercices like this
gr1 <- c("ae1_IntroEst_1.Rmd","ae1_IntroEst_2.Rmd","ae1_IntroEst_3.Rmd","ae1_IntroEst_4.Rmd")
gr2 <- c("ae1_IntroProcEst_1.Rmd","ae1_IntroProcEst_2.Rmd","ae1_IntroProcEst_3.Rmd","ae1_IntroProcEst_4.Rmd")
...etc...
Now, I am creating a loop to export all the exercices to moodle xml:
for (i in 1:2){
grupo <- paste0("gr",i)
exams2moodle(grupo, name = paste0("mt1_",i, "_M"), dir = "nops_moodle", encoding = "UTF-8", schoice = list(answernumbering = "none", eval = ee))
}
But I am getting this error:
Error in xexams(file, n = n, nsamp = nsamp, driver = list(sweave = list(quiet = quiet, : The following files cannot be found: gr11.
If I replace "grupo" by "gr1" then it works... (but I am generating 20 exercices). I can't figure it out...
Any ideas?
Thanks!
Because grupo is a string: "gr1". The exams2moodle's first parameter is a string (in your case) and not the list of files (as you want).
If you want use a variable which name is in a string variable, you should use get (get: Return the Value of a Named Object)
Check the sample code:
> x <- 'foo'
> foo <- 'bar'
> x
[1] "foo"
> get(x)
[1] "bar"
>
In your case:
for (i in 1:2){
grupo <- paste0("gr",i)
exams2moodle(get(grupo), name = paste0("mt1_",i, "_M"), dir = "nops_moodle", encoding = "UTF-8", schoice = list(answernumbering = "none", eval = ee))
}

Call dynamic method without naming parameters

I'm calling a method of a class dynamically like this, and it works:
CALL METHOD (gc_zcl_mapping_methods)=>(<ls_import_params>-attr_logic_method)
EXPORTING
iv_dats = <lv_value>
RECEIVING
rv_timestamp = <ls_import_params>-attr_value.
The problem is that I'm naming the two parameters iv_dats and rv_timestamp.
Not every method has these parameter names so I'm looking for a way to call them without naming the parameters.
I tried like this, but I get many syntax errors.
<ls_import_params>-attr_value = (gc_zcl_mapping_methods)=>(<ls_import_params>-attr_logic_method)(<lv_value>).
Is there a correct syntax for my goal to omit the parameter names?
Unfortunately, you have to name the returning parameter and other parameters too.
The full dynamic calling is explained here in the ABAP documentation
For your example code, that will give this code :
DATA(ptab) = VALUE abap_parmbind_tab(
( name = 'IV_DATS'
kind = cl_abap_objectdescr=>exporting
value = REF #( <lv_value> ) )
( name = 'RV_TIMESTAMP'
kind = cl_abap_objectdescr=>receiving
value = REF #( <ls_import_params>-attr_value ) ) ).
DATA(etab) = VALUE abap_excpbind_tab( ).
CALL METHOD (gc_zcl_mapping_methods)=>(<ls_import_params>-attr_logic_method)
PARAMETER-TABLE ptab
EXCEPTION-TABLE etab.
You may get the name of the returning parameter by using RTTI (here, I suppose that the class is global), you may also adapt it to get other parameter names:
DATA(rtti_class) = CAST cl_abap_objectdescr(
cl_abap_typedescr=>describe_by_name( '\CLASS=' && gc_zcl_mapping_methods ) ).
DATA(method) = rtti_class->methods[ name = <ls_import_params>-attr_logic_method ].
DATA(returning_parameter) = method-parameters[ parm_kind = cl_abap_objectdescr=>returning ].
DATA(returning_parameter_name) = returning_parameter-name.
I let you add the handling of exceptions.
ADDENDUM : Minimal, Complete, and Verifiable Example :
Let's say this static call is to be done dynamically :
DATA(result) = VALUE sychar01( ).
DATA(ltxttab) = VALUE rslinltab( ( kind = 'E' numb = 1 param = 'MSGID' value = 'MESSAGEGY9' )
( kind = 'E' numb = 1 param = 'PRAGMA' value = '##DUMMY' ) ).
cl_abap_syntax_message=>long_text_exists(
EXPORTING
p_kind = 'E'
p_number = 1
p_ltxttab = ltxttab
RECEIVING
p_result = result
EXCEPTIONS
message_not_found = 1 ).
Dynamic version (also, the RECEIVING parameter is being determined dynamically at runtime, but usually it's not needed because its name is known at compile time) :
DATA(rtti_class) = CAST cl_abap_objectdescr(
cl_abap_typedescr=>describe_by_name( '\CLASS=' && 'CL_ABAP_SYNTAX_MESSAGE' ) ).
DATA(method) = rtti_class->methods[ name = 'LONG_TEXT_EXISTS' ].
DATA(returning_parameter) = method-parameters[ parm_kind = cl_abap_objectdescr=>returning ].
DATA(returning_parameter_name) = returning_parameter-name.
ASSERT returning_parameter_name = 'P_RESULT'. " <=== just for the demo
DATA(ptab) = VALUE abap_parmbind_tab(
( name = 'P_KIND'
kind = cl_abap_objectdescr=>exporting
value = REF #( 'E' ) )
( name = 'P_NUMBER'
kind = cl_abap_objectdescr=>exporting
value = REF #( 1 ) )
( name = 'P_LTXTTAB'
kind = cl_abap_objectdescr=>exporting
value = REF #( ltxttab ) )
( name = returning_parameter_name
kind = cl_abap_objectdescr=>receiving
value = REF #( result ) ) ).
DATA(etab) = VALUE abap_excpbind_tab(
( name = 'MESSAGE_NOT_FOUND' value = 1 ) ).
CALL METHOD ('CL_ABAP_SYNTAX_MESSAGE')=>('LONG_TEXT_EXISTS')
PARAMETER-TABLE ptab
EXCEPTION-TABLE etab.

How can I read All Items in table of table with lua api?

I have a table in a lua file.
This is the table:
main = {}
main["first"] = {
{name = "sammy", type = "dog", age = 2, color = "blue"},
{name = "tom", type = "cat", age = 3, color = "orange"},
.
.
.
.
}
main["second"] = {
{name = "grim", type = "cow", age = 1, color = "green"},
{name = "jerry", type = "horse", age = 2, color = "grey"},
.
.
.
.
}
The table has two tables. I want to read all tables in main. So I wrote this code. (I use delphi. plua_state means pointer of lua_state)
This is my code:
procedure TForm1.PrintTable(l: Plua_State);
var
TempStr : String;
begin
lua_pushnil(l);
TempStr := '';
while lua_next(l,-2) <> 0 do
begin
case lua_type(l,-1) of
LUA_TTABLE :
PrintTable(l);
else
TempStr := TempStr + lual_checkstring(L, -2) + '='
+ lua_typename(L, lua_type(L, -1)) + ',';
end;
lua_pop(l,1);
end;
fStringList.Add(TempStr);
end;
This code prints the key and value type in the main table.However, If I change lua_typename(L, lua_type(L, -1)) to lual_checkstring(L, -1), It does not work. I want to print the key and value.
How can I print the value?
You must be careful when using lua_next as several string API functions will alter the value on the stack which confuses lua_next. From the manual:
While traversing a table, do not call lua_tolstring directly on a key, unless you know that the key is actually a string. Recall that lua_tolstring may change the value at the given index; this confuses the next call to lua_next.
So, calling lua_tostring, lua_tolstring, or luaL_checklstring on a key pushed by lua_next will change the key into a string.
As you have discovered it is best to use lua_type to make sure the value is indeed a string before calling lua_tolstring (or any API function that calls it), or push a copy of the key which can be popped leaving the original key returned by lua_next unmodified.

Easiest way of defining and using of Global Variable

"first part" &&&& fun _ ->
let ident
"second part" &&&& fun _ ->
ident ....
I need to use variable "ident".
I just need to pass value of variable from first part of test to second one...
I want to ask you if there is any easy way how to define and use global variable or even if you have better (and easy) idea of doing that
Keep in mind, please, that I am a beginner, so I would prefer easier ones.
Global variables will often make your code difficult to work with - particularly if they are mutable.
Instead, consider returning the values you need to keep track of as composite values. An easy data type to start with would be a tuple:
let ``first part`` id =
let someOtherValue = "Foo"
someOtherValue, id + 1
This function takes an int (the current ID) as input, and returns string * int (a tuple where the first element is a string, and the second element and int) as output.
You can call it like this:
> let other, newId = ``first part`` 42;;
val other : string = "Foo"
val newId : int = 43
Notice that you can use pattern matching to immediately destructure the values into two named symbols: other and newId.
Your second function could also take an ID as input:
let ``second part`` id otherArgument =
// use id here, if you need it
"Bar"
You can call it like this, with the newId value from above:
> let result = ``second part`` newId "Baz";;
val result : string = "Bar"
If you find yourself doing this a lot, you can define a record for the purpose:
type Identifiable<'a> = { Id : int; Value : 'a }
Now you can begin to define higher-order functions to deal with such a type, such as e.g. a map function:
module Identifiable =
let map f x = { Id = x.Id; Value = f x.Value }
// Other functions go here...
This is a function that maps the Value of an Identifiable from one value to another, but preserves the identity.
Here's a simple example of using it:
> let original = { Id = 42; Value = "1337" };;
val original : Identifiable<string> = {Id = 42;
Value = "1337";}
> let result' = original |> Identifiable.map System.Int32.Parse;;
val result' : Identifiable<int> = {Id = 42;
Value = 1337;}
As you can see, it preserves the value 42, but changes the Value from a string to an int.
You can still change the ID explicitly, if you want to do that:
> let result'' = { result' with Id = 7 };;
val result'' : Identifiable<int> = {Id = 7;
Value = 1337;}
Since this was getting out of hand for comments this is how I would do it for an example
let mutable t = 0
let first =
t <- 1 + 1
//other stuff
let second =
//can use t here and it will have a value of 2
In some cases you have to use a ref:
let t = ref 0
let first =
t := 1 + 1
//other stuff
let second =
//can use t here and it will have a value of 2 -
// you use "!t" to get the value
If you define ident at the top of your file like this :
let ident = "foo"
// rest of your code using ident
ident are global and you can use in the next part of your file.
EDIT :
If ident wil change in the next part of your code, use this :
let ident = ref "foo"