Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dict2resource function can create attributes with space in name #1865

Open
2 of 4 tasks
KarolTracz opened this issue May 29, 2024 · 1 comment
Open
2 of 4 tasks

dict2resource function can create attributes with space in name #1865

KarolTracz opened this issue May 29, 2024 · 1 comment
Labels
bug good first issue New contributors welcome !

Comments

@KarolTracz
Copy link

KarolTracz commented May 29, 2024

Bug summary

When dict2resource function is called and one of field name contain space in it, this make the attribute have a space in it also. As a result it is not callable.
As a example XRAY plugin for Jira as default use schema that contain name ' expected result'. This result in getting value from this field is not possible.
default schema for test step in XRAY:
{ "fields":{ "customfield_10004":{ "steps":[ { "index":1, "fields":{ "action":"Step 1", "data":"input Data 1", "expected result":"Excepted result 1" } }, { "index":2, "fields":{ "action":"Step 2", "data":"input Data 2", "expected result":"Excepted result 2" } }, { "index":3, "fields":{ "action":"Step 4", "data":"input Data 3", "expected result":"Excepted result 3" } } ] } } }

Is there an existing issue for this?

  • I have searched the existing issues

Jira Instance type

Jira Cloud (Hosted by Atlassian)

Jira instance version

No response

jira-python version

3.8.0

Python Interpreter version

3.11

Which operating systems have you used?

  • Linux
  • macOS
  • Windows

Reproduction steps

valid_response = {
   "fields":{
      "customfield_10004":{
         "steps":[
            {
               "index":1,
               "fields":{
                  "action":"Step 1",
                  "data":"input Data 1",
                  "expected result":"Excepted result 1"
               }
            },
            {
               "index":2,
               "fields":{
                  "action":"Step 2",
                  "data":"input Data 2",
                  "expected result":"Excepted result 2"
               }
            },
            {
               "index":3,
               "fields":{
                  "action":"Step 4",
                  "data":"input Data 3",
                  "expected result":"Excepted result 3"
               }
            }
         ]
      }
   }
}
from jira.resources import dict2resource

resource_object = dict2resource(valid_response)
for i in resource_object.fields.customfield_10004.steps:
    print(i.fields.action)
    print(i.fields.data)
    print(i.fields.expected_result)

Stack trace

Traceback (most recent call last):
  File "C:\Users\path\to\file\file.py", line 39, in <module>
    print(i.fields.expected_result)
          ^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'PropertyHolder' object has no attribute 'expected_result'. Did you mean: 'expected result'?

Expected behaviour

dict2resource function replace space character in names to underscore or concatenate into one string.

Fix proposal

I assume something like this should work:

def replace_spaces_in_keys(data: Dict[str, Any]) -> Dict[str, Any]:
    if isinstance(data, dict):
        return {replace_spaces_in_strings(k): replace_spaces_in_strings(v) for k, v in data.items()}
    elif isinstance(data, list):
        return [replace_spaces_in_strings(elem) for elem in data]
    elif isinstance(data, str):
        return data.replace(" ", "_")
    else:
        return data


def dict2resource(
    raw: dict[str, Any], top=None, options=None, session=None
) -> PropertyHolder | type[Resource]:
    """Convert a dictionary into a Jira Resource object.

    Recursively walks a dict structure, transforming the properties into attributes on a new ``Resource`` object of the appropriate type
    (if a ``self`` link is present) or a ``PropertyHolder`` object (if no ``self`` link is present).
    """
    if top is None:
        top = PropertyHolder()

    raw = replace_spaces_in_keys(raw)
    [...]

I don't have time to investigate it deeply and create PR. Works locally for me.

Additional Context

I got XRAY test steps schema from https://docs.getxray.app/display/XRAY/Tests+-+REST

@adehad adehad added bug good first issue New contributors welcome ! labels Jul 9, 2024
@dimitarOnGithub
Copy link

I'd personally be wary of introducing such a change in the library itself because of:

  1. It mutates the data received and the dict2resource (and the consequently called _parse_raw method in the Resource class) is widely used across the library, which might introduce unintended regression bugs;
  2. It would be very hard to account for which variables need to be mutated back to their JSON schema for any POST/PUT calls

I think it should be up to the user to handle the parsing using custom logic that fit their needs, otherwise you might find yourself in a situation where you have to keep introducing handling of edge cases such as this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug good first issue New contributors welcome !
Projects
None yet
Development

No branches or pull requests

3 participants