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

fix: Use field translation in Jira.issue method #1864

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 48 additions & 17 deletions jira/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1800,12 +1800,15 @@ def issue(

params = {}
if fields is not None:
params["fields"] = fields
fields_list = self._translate_fields_name_to_id(fields)
params["fields"] = ",".join(fields_list)
if expand is not None:
params["expand"] = expand
if properties is not None:
params["properties"] = properties

issue.find(id, params=params)
self._untranslate_issues_fields_id_to_fields_name([issue])
return issue

def create_issue(
Expand Down Expand Up @@ -3547,14 +3550,7 @@ def search_issues(
elif fields is None:
fields = ["*all"]

# this will translate JQL field names to REST API Name
# most people do know the JQL names so this will help them use the API easier
untranslate = {} # use to add friendly aliases when we get the results back
if self._fields_cache:
for i, field in enumerate(fields):
if field in self._fields_cache:
untranslate[self._fields_cache[field]] = fields[i]
fields[i] = self._fields_cache[field]
fields = self._translate_fields_name_to_id(fields)

search_params = {
"jql": jql_str,
Expand Down Expand Up @@ -3590,16 +3586,51 @@ def search_issues(
use_post=use_post,
)

if untranslate:
iss: Issue
for iss in issues:
for k, v in untranslate.items():
if iss.raw:
if k in iss.raw.get("fields", {}):
iss.raw["fields"][v] = iss.raw["fields"][k]

self._untranslate_issues_fields_id_to_fields_name(issues)
return issues

def _translate_fields_name_to_id(self, fields: list[str] | str) -> list[str]:
"""Translate fields names to JIRA's REST API field id.

Args:
fields (list[str] | str): comma-separated string or list of issue fields to be translated

Returns:
tuple[list[str], dict[str, str]]: Returns translated fields and dictionary {field_id: field_name}
with translation needed to decode ids into names.
Translated fields variable is always List type
"""
translated_fields: list[str]
if isinstance(fields, str):
translated_fields = fields.split(",")
elif isinstance(fields, list):
translated_fields = fields.copy()
else:
raise NotImplementedError(
"Translating fields for <%s> type is unsupported", type(fields)
)

if self._fields_cache:
for i, field_name in enumerate(translated_fields):
if field_name in self._fields_cache:
translated_fields[i] = self._fields_cache[field_name]

return translated_fields

def _untranslate_issues_fields_id_to_fields_name(self, issues: list[Issue]) -> None:
"""Untranslate issues fields names from JIRA's REST API field id.

Args:
issues (list[Issue]): list of issues to be untranslated
"""
for issue in issues:
if not issue.raw:
return
for field_name, field_id in self._fields_cache.items():
if field_id in issue.raw.get("fields", {}):
issue.raw["fields"][field_name] = issue.raw["fields"][field_id]
setattr(issue.fields, field_name, issue.raw["fields"][field_id])

# Security levels
def security_level(self, id: str) -> SecurityLevel:
"""Get a security level Resource.
Expand Down
20 changes: 20 additions & 0 deletions tests/resources/test_issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ def test_issue_search_only_includes_provided_fields(self):
self.assertTrue(hasattr(issues[0].fields, "assignee"))
self.assertFalse(hasattr(issues[0].fields, "reporter"))

def test_find_issue_fields_translating(self):
issues = self.jira.search_issues(f"key={self.issue_1}", fields="due")
issue = issues[0]
self.assertTrue(hasattr(issue.fields, "due"))
self.assertTrue(hasattr(issue.fields, "duedate"))
self.assertTrue(issue.fields.due == issue.fields.duedate)

def test_issue_search_default_behaviour_included_fields(self):
search_str = f"key={self.issue_1}"
issues = self.jira.search_issues(search_str)
Expand Down Expand Up @@ -91,6 +98,19 @@ def test_issue_expand(self):
# testing for changelog is not reliable because it may exist or not based on test order
# self.assertFalse(hasattr(issue, 'changelog'))

def test_find_issue_fields_limiting(self):
issue = self.jira.issue(self.issue_1, fields="summary, comment")
self.assertTrue(hasattr(issue.fields, "summary"))
self.assertTrue(hasattr(issue.fields, "comment"))
self.assertFalse(hasattr(issue.fields, "reporter"))
self.assertFalse(hasattr(issue.fields, "progress"))

def test_search_issues_fields_translating(self):
issue = self.jira.issue(self.issue_1, fields="due")
self.assertTrue(hasattr(issue.fields, "due"))
self.assertTrue(hasattr(issue.fields, "duedate"))
self.assertTrue(issue.fields.due == issue.fields.duedate)

def test_create_issue_with_fieldargs(self):
issue = self.jira.create_issue(
summary="Test issue created",
Expand Down
Loading