Different parsing of values in dictionary (string and list)

Hello all,

I would like to ask for some help, trying to figure out how extracting values from dictionary works, when they are provided in different formats. I am using a dictionary as an embedded keyword argument. One of the keys is “meetings”, which would accept a single or multiple times, for example:

  1. case: meetings = 13:00
  2. case: meetings = 8:30 10:00 13:00

I am not really sure what is the implementation to handle such inputs. It seems that in first case, the code parses value as a string ( “13:00” ). And in second case, it creates a list of strings ( [“8:30” “10:00” “13:00”] ).

I need a list of values (times) and was not able to find a simple solution. Eventually I ended up counting colons to determine whether there is one or multiple times present in the value:

IF    "${times}".count(":") == 1
    @{times}=    Evaluate    ["${times}"]
END

It is a very crude solution and I hope there is a way to avoid it altogether.
Can someone please explain why I am getting different instance types for different inputs. And what would be the most elegant way to make it consistent?

Thank you!
A

Hi Josh,

Fist I’ll suggest that

@{times}=     Create List     ${times}

is probably more readable than

@{times}=    Evaluate    ["${times}"]

I couldn’t find a keyword for getting a variable type, so came up with this which is might work for you:

    ${times}=     Set Variable     13:00

    TRY
        # if var is string exception will thowen
        Log     ${{ type(${my_string}) }}
    EXCEPT
        @{times}=     Create List     ${times}
    END

    Log     ${times}    console=true

Calling the python type on 13:00 gives an exception and calls the Create List keyword, if ${times} is already a list the Log keyword doesn’t throw an exception and the EXCEPT block is skipped

Dave.

1 Like

Thank you Dave

I will keep the IF solution just for fewer lines of code, even though it looks clumsy. I will however borrow your syntax for creating list, which is indeed much more readable.

Do you perhaps know why such behaviour occurs in the first place, just for me to understand? I mean parsing dictionary values with 2 different types.

Best,
A

1 Like

As with everything in IT, give 100 people the same problem and get 100 different valid answers… use what you want from my suggestions :+1:

I don’t know why it happens, how are you creating the dictionaries? are they defined in your robot file or from another source?

If creating the data in robot framework I normally construct the data using Create List and Create Dictionary to be sure the data is what I expect.

Dave.

Hi,

As Dave said it’s not clear how the variable/list is provided to your keyword.
But indeed if you require a dict as [Arguments] the unique value will work easily for extraction.
Here the value of key meetings is ‘13:00’ :

But in your second case ‘value’ for ‘key’ meetings contains ‘8:30 10:00 13:00’ which is a string:

I would use this then to rebuild a true list based on your variable key (split on separator=space):

  Meetings Test
      VAR    &{meet_time}    meetings=13:00
      Build Meeting    ${meet_time}
  
      VAR    &{meet_time}    meetings=8:30 10:00 13:00     
      Build Meeting    ${meet_time}
        
  *** Keywords ***
  Build Meeting
      [Arguments]    ${meet_time}
      ${extList}    Split String    ${meet_time.meetings}
  
      FOR  ${schedule}    IN    @{extList} 
          Log     ${schedule}
      END

That logs the correct extracted values:

${extList} = ['13:00']
13:00
${extList} = ['8:30', '10:00', '13:00']
8:30
10:00
13:00

Regards
Charlie

1 Like

If its quaranteed that the input strings are always separated with single space and there’s no trailing/leading spaces, simple Split String is the easiest way imho.

Example;

*** Settings ***
Library    String

*** Variables ***
${times_1}    13:00
${times_2}    8:30 10:00 13:00

*** Test Cases ***
Test Split

  @{t1}=   Split String  ${times_1}   ${SPACE}
  @{t2}=   Split String  ${times_2}   ${SPACE}

  FOR   ${time}  IN  @{t1}
      Log  t1:${time}     console=${True}
  END

  FOR   ${time}  IN  @{t2}
      Log  t2:${time}    console=${True}
  END

will print out:

Test Split                                                            ..t1:13:00
.t2:8:30
t2:10:00
t2:13:00
Test Split                                                            | PASS |

so t1 gets printed once as it should and t2 3 times, as it should, with correct times.

EDIT; Ah, @CharlieScene already said the same thing …

1 Like

Hi, I will try to summarize my setting in a brief way:

I have a keyword that accepts a dictionary as an argument:

Select settings with provided values:    [Arguments]    &{properties}

Which is called like this in test case file:

Example with one time provided

Select settings with provided values:
...    times=13:00

Example with multiple times provided

Select settings with provided values:
...    times=8:30 10:00 13:00

That is how I got into situation, when in case of one provided time is parsed as a string. And multiple provided times are parsed as a list of strings (times). This is why simple solutions of converting to list, or splitting a string, did not work for me and got me lost. And still I didn’t figure out, why it behaves that way or whether I did something wrong with passing the values to keyword.

That said, thank you all for providing tips and solutions!

1 Like