Skip to content

Commit ff692bd

Browse files
[JIRA] Add search/jql and search/approximate-count APIs support for Jira Cloud (#1513)
* [JIRA] Add enhanced_search_issues and approximate_issue_count for Jira Cloud * Remove print statement
1 parent 4675ca6 commit ff692bd

File tree

3 files changed

+191
-1
lines changed

3 files changed

+191
-1
lines changed

README.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,23 @@ And here's another example of how to get issues from Jira using JQL Query:
7878
data = jira.jql(JQL)
7979
print(data)
8080
81+
The traditional jql method is deprecated for Jira Cloud users, as Atlassian has transitioned to a nextPageToken-based pagination approach instead of startAt. Use enhanced_jql for improved performance and future compatibility.
82+
83+
.. code-block:: python
84+
85+
from atlassian import Jira
86+
87+
jira = Jira(
88+
url='https://your-jira-instance.atlassian.net',
89+
username='your-email@example.com',
90+
password='your-api-token',
91+
cloud=True # Ensure this is set to True for Jira Cloud
92+
)
93+
JQL = 'project = DEMO AND status IN ("To Do", "In Progress") ORDER BY issuekey'
94+
# Fetch issues using the new enhanced_jql method
95+
data = jira.enhanced_jql(JQL)
96+
print(data)
97+
8198
Also, you can use the Bitbucket module e.g. for getting project list
8299

83100
.. code-block:: python

atlassian/jira.py

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3345,6 +3345,19 @@ def jql(
33453345
:param validate_query: OPTIONAL: Whether to validate the JQL query
33463346
:return:
33473347
"""
3348+
if self.cloud:
3349+
if start==0:
3350+
return self.enhanced_jql(
3351+
jql=jql,
3352+
fields=fields,
3353+
limit=limit,
3354+
expand=expand,
3355+
)
3356+
else:
3357+
raise ValueError(
3358+
"The `jql` method is deprecated in Jira Cloud. Use `enhanced_jql` method instead."
3359+
)
3360+
33483361
params = {}
33493362
if start is not None:
33503363
params["startAt"] = int(start)
@@ -3363,6 +3376,64 @@ def jql(
33633376
url = self.resource_url("search")
33643377
return self.get(url, params=params)
33653378

3379+
def enhanced_jql(
3380+
self,
3381+
jql,
3382+
fields="*all",
3383+
nextPageToken=None,
3384+
limit=None,
3385+
expand=None,
3386+
):
3387+
"""
3388+
Get issues from jql search result with all related fields
3389+
:param jql:
3390+
:param fields: list of fields, for example: ['priority', 'summary', 'customfield_10007']
3391+
:param nextPageToken (Optional[str]): Token for paginated results. Default: None.
3392+
:param limit: OPTIONAL: The limit of the number of issues to return, this may be restricted by
3393+
fixed system limits. Default by built-in method: 50
3394+
:param expand: OPTIONAL: expand the search result
3395+
:return:
3396+
"""
3397+
3398+
if not self.cloud:
3399+
raise ValueError("``enhanced_jql`` method is only available for Jira Cloud platform")
3400+
3401+
params = {}
3402+
if nextPageToken is not None:
3403+
params["nextPageToken"] = str(nextPageToken)
3404+
if limit is not None:
3405+
params["maxResults"] = int(limit)
3406+
if fields is not None:
3407+
if isinstance(fields, (list, tuple, set)):
3408+
fields = ",".join(fields)
3409+
params["fields"] = fields
3410+
if jql is not None:
3411+
params["jql"] = jql
3412+
if expand is not None:
3413+
params["expand"] = expand
3414+
3415+
url = self.resource_url("search/jql")
3416+
return self.get(url, params=params)
3417+
3418+
def approximate_issue_count(
3419+
self,
3420+
jql,
3421+
):
3422+
"""
3423+
Get an approximate count of issues matching a JQL search string.
3424+
3425+
:param jql: The JQL search string.
3426+
:return: The issue count.
3427+
"""
3428+
3429+
if not self.cloud:
3430+
raise ValueError("``approximate_issue_count`` method is only available for Jira Cloud platform")
3431+
3432+
data = {"jql": jql}
3433+
3434+
url = self.resource_url("search/approximate-count")
3435+
return self.post(url, data)
3436+
33663437
def jql_get_list_of_tickets(
33673438
self,
33683439
jql,
@@ -3383,6 +3454,19 @@ def jql_get_list_of_tickets(
33833454
:param validate_query: Whether to validate the JQL query
33843455
:return:
33853456
"""
3457+
if self.cloud:
3458+
if start==0:
3459+
return self.enhanced_jql_get_list_of_tickets(
3460+
jql=jql,
3461+
fields=fields,
3462+
limit=limit,
3463+
expand=expand,
3464+
)
3465+
else:
3466+
raise ValueError(
3467+
"The `jql_get_list_of_tickets` method is deprecated in Jira Cloud. Use `enhanced_jql_get_list_of_tickets` method instead."
3468+
)
3469+
33863470
params = {}
33873471
if limit is not None:
33883472
params["maxResults"] = int(limit)
@@ -3404,7 +3488,7 @@ def jql_get_list_of_tickets(
34043488
response = self.get(url, params=params)
34053489
if not response:
34063490
break
3407-
3491+
34083492
issues = response["issues"]
34093493
results.extend(issues)
34103494
total = int(response["total"])
@@ -3413,7 +3497,61 @@ def jql_get_list_of_tickets(
34133497
if limit is not None or total <= len(response["issues"]) + start:
34143498
break
34153499
start += len(issues)
3500+
return results
3501+
3502+
def enhanced_jql_get_list_of_tickets(
3503+
self,
3504+
jql,
3505+
fields="*all",
3506+
limit=None,
3507+
expand=None,
3508+
):
3509+
"""
3510+
Get issues from JQL search result with all related fields using nextPageToken pagination.
3511+
3512+
Applicable only for Jira Cloud.
3513+
3514+
:param jql: The JQL search string.
3515+
:param fields: List of fields, for example: ['priority', 'summary', 'customfield_10007']
3516+
:param limit: OPTIONAL: The limit of the number of issues to return, this may be restricted by
3517+
fixed system limits. Default by built-in method: 50
3518+
:param expand: OPTIONAL: Expand the search result.
3519+
:return: List of issues.
3520+
"""
3521+
3522+
if not self.cloud:
3523+
raise ValueError("``enhanced_jql_get_list_of_tickets`` is only available for Jira Cloud.")
3524+
3525+
params = {}
3526+
if limit is not None:
3527+
params["maxResults"] = int(limit)
3528+
if fields is not None:
3529+
if isinstance(fields, (list, tuple, set)):
3530+
fields = ",".join(fields)
3531+
params["fields"] = fields
3532+
if jql is not None:
3533+
params["jql"] = jql
3534+
if expand is not None:
3535+
params["expand"] = expand
34163536

3537+
url = self.resource_url("search/jql")
3538+
results = []
3539+
nextPageToken = None
3540+
3541+
while True:
3542+
if nextPageToken is not None:
3543+
params["nextPageToken"] = nextPageToken
3544+
3545+
response = self.get(url, params=params)
3546+
if not response:
3547+
break
3548+
3549+
issues = response["issues"]
3550+
results.extend(issues)
3551+
3552+
nextPageToken = response.get("nextPageToken")
3553+
if not nextPageToken or (limit is not None and len(results) >= limit):
3554+
break
34173555
return results
34183556

34193557
def csv(self, jql, limit=1000, all_fields=True, start=None, delimiter=None):
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# coding=utf-8
2+
"""
3+
Example: Using enhanced JQL search methods in Jira Cloud.
4+
5+
This script demonstrates:
6+
1. Fetching issues using `enhanced_jql` (nextPageToken-based pagination).
7+
2. Getting an approximate issue count with `approximate_issue_count`.
8+
3. Fetching issues using `enhanced_jql_get_list_of_tickets` (legacy startAt pagination for Data Center users).
9+
10+
⚠️ Note: `enhanced_jql` is recommended for Jira Cloud users as it aligns with Atlassian's new search API.
11+
"""
12+
13+
from atlassian import Jira
14+
15+
# Initialize Jira Cloud instance
16+
jira_cloud = Jira(
17+
cloud=True,
18+
url="https://your-jira-instance.atlassian.net",
19+
username="your-email@example.com",
20+
password="your-api-token",
21+
)
22+
23+
print("========== Fetching Issues Using enhanced_jql ==========")
24+
issues = jira_cloud.enhanced_jql("updated >= -1d ORDER BY updated DESC", limit=20, fields="*nav")
25+
print(issues)
26+
27+
print("========== Getting Approximate Issue Count ==========")
28+
issue_count = jira_cloud.approximate_issue_count("updated >= -1d ORDER BY updated DESC")
29+
print(issue_count)
30+
31+
print("========== Fetching Issues Using enhanced_jql_get_list_of_tickets ==========")
32+
issues_list = jira_cloud.enhanced_jql_get_list_of_tickets("updated >= -1d ORDER BY updated DESC", limit=300, fields="*nav")
33+
print(issues_list)
34+
35+
print("========== Done ==========")

0 commit comments

Comments
 (0)