You are viewing limited content. For full access, please sign in.

Question

Question

How do I parse multivalued inputs in a Python Script in LF Cloud?

asked on February 6 Show version history

This is a continuation of my previous question. I have a working Python script that generates a CSV. I can pass it inputs like name and email, and it works great for one row; however, as soon as I change inputs to be multivalued, I cannot figure out how to parse the multivalued inputs in my Python script. My end goal is to push the data from a lookup table to a CSV, but I need to be able to send multivalued inputs to the script in order to populate the CSV (more than 1 row).

See the attached picture. I send it a list of names and emails, but all I receive is names=System.Object[]. If I try to expand what I expect to be an array, it treats it like a string ("System.Object[]" gets put into each column only once). When I specify names[0], ... names[n], I just see S, y, s, t, e, m ... and so on.

Here's my script:

import csv,sys
from datetime import datetime

dt = datetime.today().strftime('%Y-%m-%d-%H%M%S')

csv_file_name = 'C:\\LF Import Agent Uploads\\AP\\APExport-'+dt+'.csv'

names = sys.argv[1]
emails = sys.argv[2]

data = [[names, emails]]

# Write to CSV file
with open(csv_file_name, 'w', newline='') as csv_file:
    csv_writer = csv.writer(csv_file)
    csv_writer.writerow(['Name', 'Email'])
    csv_writer.writerows(data)
    
print(f"names:{names}")
print(f"emails:{emails}")

 

lf-multivalued.png
0 0

Answer

SELECTED ANSWER
replied on February 20

I filed a bug for this (reference ID #509878).

 

Rewriting your code in C# is worth a shot. I don't know enough about the inner workings of Remote Agent to be able to say one way or another whether that will fix the issue.

2 0

Replies

replied on February 6

The problem doesn't seem to be with your program, it looks like it is being given the string value "System.Object[]" as a command line parameter. Backing up, it's not clear how a multi-value string would be passed to a command line program, though. Your code seems to expect `names` to be a string array, but the OS/process interface only supports flat strings - you would need to reverse whatever convention the calling program uses to pass an array.

Once you get past that, I don't think the csv will look the way you want in the case that `names` and `emails` are arrays - I would expect all of the names to be written out in one row, followed by all of the emails; you kind of have to rotate your data array.

2 0
replied on February 8

And after talking with Paolo, I think the main point is that your script should be inside a function with the signature he points to, "def YourScriptMethod(inputs: Dict[str, str]) -> Dict[str, str]:". The remote agent framework will deal with reading the command-line and call your function with the appropriate arguments. You can use that mirror.py as a test to inspect the inputs, as it just echos them back.

1 0
replied on February 14

Thanks for the response. I've been working on this on/off a bit this past week and I feel I'm close, but I'm still getting the same outputs using the provided sample code when I enable multivalued fields. I've removed the code dealing with generating a .csv and instead use the outputs as per the template. Here's how my code looks now:

import csv,sys
from datetime import datetime
from typing import List, Dict

def generate_csv(inputs: Dict[str, str]) -> Dict[str, str]:
    """
    This function generates the csv from the inputs provided by Laserfiche

    :param inputs: An object representing the input parameters passed to the script.
    :type inputs: dict[str, str]
    :return: An object representing the output parameters returned by the script.
    :rtype: dict[str, str]
    """

    # Retrieve your input parameters from process.argv after parser
    outputs: Dict[str, str] = {}
    for key, value in inputs.items():
        outputs[key] = value

    # Return your output parameters to the caller
    return outputs

def get_argument_map(argument_list: List[str]) -> Dict[str, str]:
    """
    Parses the argument list and returns a dictionary of key-value pairs.

    :param argument_list: A list of command-line arguments.
    :type argument_list: list[str]
    :return: A dictionary of key-value pairs representing the parsed arguments.
    :rtype: dict[str, str]
    :raises Exception: If the argument list is invalid.
    """
    argument_map = {}
    if argument_list is None:
        raise Exception("Invalid arguments.")
    for arg in argument_list[1:len(argument_list):1]:
        try:
            if arg is not None:
                kv = arg.split('=', 1)
                if len(kv) == 2:  # '=' exists
                    key = kv[0]
                    if key is not None and len(key) > 0:
                        value = kv[1]
                        argument_map[key] = value
        except Exception as e:
            sys.stderr.write(f"Could not parse arguments: {str(e)}")
            raise e
    return argument_map
    
if __name__ == "__main__":
    # Inputs can be automatically parsed with the provided function
    # Or parsed manually via 'sys.argv'
    inputs = get_argument_map(sys.argv)
    outputs = generate_csv(inputs)

    # Output can be printed to the console in `key:value` pairs format
    # remote agent will parse the output and return it to the caller
    for key, value in outputs.items():
        print(f"{key}:{value}")

This again works great when there's a single value, but I get the same System.Object[] when I select multivalued. Perhaps it's still not calling it right with how I have it setup?

lf-1.png
lf-2.png
lf-1.png (43.29 KB)
lf-2.png (49.93 KB)
0 0
replied on February 15 Show version history

Are you running this Python script from Laserfiche Remote Agent? What is calling this Python script?

 

This may be a bug in the product that is calling your code and not be in your code. The bug is likely a side effect of a bad design decision in C#: an object's ToString() method returns wildly different results depending on the object's type. For a basic string (i.e. a scalar value), the ToString() return value is the contents of the string itself. This matches human expectations and is why your single row case works.

string x = "foo";
Console.WriteLine(x.ToString());  // outputs "foo" as expected

However, once the object type becomes a collection of strings, the ToString() method becomes useless. Microsoft coded those collection classes to return the type of the collection as their ToString() instead of returning a string representation of the contents of the collection.

object[] x = new object[] { "foo", "bar" };
Console.WriteLine(x.ToString());  // unintuitively outputs "System.Object[]" instead of "foo,bar"

Since the bug is probably in the software that calls your code, changing your Python script won't fix it as your Python process is being passed the literal string "System.Object[]".

1 0
replied on February 16

That makes sense. I'm using the Laserfiche Remote Agent. Does that mean that Laserfiche will have to fix the bug? If that's the case, I'll see if I can get a similar code running in C# as I'm told that may work better.

0 0
SELECTED ANSWER
replied on February 20

I filed a bug for this (reference ID #509878).

 

Rewriting your code in C# is worth a shot. I don't know enough about the inner workings of Remote Agent to be able to say one way or another whether that will fix the issue.

2 0
replied on February 21

Thank you! I have rewritten it in C# and it seems to be working with some test data.

0 0
replied on February 8
0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.