44import logging
55import os
66import re
7- from typing import TYPE_CHECKING , Any , BinaryIO , Literal , cast
7+ from typing import TYPE_CHECKING , Any , BinaryIO , Literal , cast , Iterable
88from warnings import warn
99
1010from deprecated import deprecated
@@ -145,7 +145,7 @@ def get_permissions(
145145
146146 return self .get (url , params = params )
147147
148- def get_all_permissions (self ):
148+ def get_all_permissions (self ) -> dict | None :
149149 """
150150 Returns all permissions that are present in the Jira instance -
151151 Global, Project and the global ones added by plugins
@@ -159,7 +159,9 @@ def get_all_permissions(self):
159159 Reference: https://docs.atlassian.com/software/jira/docs/api/REST/8.5.0/#api/2/application-properties
160160 """
161161
162- def get_property (self , key : T_id | None = None , permission_level : str | None = None , key_filter : str | None = None ):
162+ def get_property (
163+ self , key : T_id | None = None , permission_level : str | None = None , key_filter : str | None = None
164+ ) -> dict | None :
163165 """
164166 Returns an application property
165167 :param key: str
@@ -180,7 +182,7 @@ def get_property(self, key: T_id | None = None, permission_level: str | None = N
180182
181183 return self .get (url , params = params )
182184
183- def set_property (self , property_id : T_id , value : str ):
185+ def set_property (self , property_id : T_id , value : str ) -> dict | None :
184186 """
185187 Modify an application property via PUT. The "value" field present in the PUT will override the existing value.
186188 :param property_id:
@@ -207,15 +209,15 @@ def get_advanced_settings(self) -> dict | None:
207209 Reference: https://docs.atlassian.com/software/jira/docs/api/REST/8.5.0/#api/2/applicationrole
208210 """
209211
210- def get_all_application_roles (self ):
212+ def get_all_application_roles (self ) -> dict | None :
211213 """
212214 Returns all ApplicationRoles in the system
213215 :return:
214216 """
215217 url = self .resource_url ("applicationrole" )
216218 return self .get (url ) or {}
217219
218- def get_application_role (self , role_key : str ):
220+ def get_application_role (self , role_key : str ) -> dict | None :
219221 """
220222 Returns the ApplicationRole with passed key if it exists
221223 :param role_key: str
@@ -242,7 +244,7 @@ def get_attachments_ids_from_issue(self, issue: T_id) -> list[dict[str, str]]:
242244 list_attachments_id .append ({"filename" : attachment ["filename" ], "attachment_id" : attachment ["id" ]})
243245 return list_attachments_id
244246
245- def get_attachment (self , attachment_id : T_id ):
247+ def get_attachment (self , attachment_id : T_id ) -> dict | None :
246248 """
247249 Returns the meta-data for an attachment, including the URI of the actual attached file
248250 :param attachment_id: int
@@ -290,7 +292,7 @@ def download_attachments_from_issue(self, issue: T_id, path: str | None = None,
290292 except Exception as e :
291293 raise e
292294
293- def get_attachment_content (self , attachment_id : T_id ):
295+ def get_attachment_content (self , attachment_id : T_id ) -> dict | None :
294296 """
295297 Returns the content for an attachment
296298 :param attachment_id: int
@@ -300,7 +302,7 @@ def get_attachment_content(self, attachment_id: T_id):
300302 url = "{base_url}/content/{attachment_id}" .format (base_url = base_url , attachment_id = attachment_id )
301303 return self .get (url )
302304
303- def remove_attachment (self , attachment_id : T_id ):
305+ def remove_attachment (self , attachment_id : T_id ) -> dict | None :
304306 """
305307 Remove an attachment from an issue
306308 :param attachment_id: int
@@ -310,7 +312,7 @@ def remove_attachment(self, attachment_id: T_id):
310312 url = "{base_url}/{attachment_id}" .format (base_url = base_url , attachment_id = attachment_id )
311313 return self .delete (url )
312314
313- def get_attachment_meta (self ):
315+ def get_attachment_meta (self ) -> dict | None :
314316 """
315317 Returns the meta information for an attachments,
316318 specifically if they are enabled and the maximum upload size allowed
@@ -319,7 +321,7 @@ def get_attachment_meta(self):
319321 url = self .resource_url ("attachment/meta" )
320322 return self .get (url )
321323
322- def get_attachment_expand_human (self , attachment_id : T_id ):
324+ def get_attachment_expand_human (self , attachment_id : T_id ) -> dict | None :
323325 """
324326 Returns the information for an expandable attachment in human-readable format
325327 :param attachment_id: int
@@ -329,7 +331,7 @@ def get_attachment_expand_human(self, attachment_id: T_id):
329331 url = "{base_url}/{attachment_id}/expand/human" .format (base_url = base_url , attachment_id = attachment_id )
330332 return self .get (url )
331333
332- def get_attachment_expand_raw (self , attachment_id : T_id ):
334+ def get_attachment_expand_raw (self , attachment_id : T_id ) -> dict | None :
333335 """
334336 Returns the information for an expandable attachment in raw format
335337 :param attachment_id: int
@@ -351,7 +353,7 @@ def get_audit_records(
351353 filter : str | None = None ,
352354 from_date : str | None = None ,
353355 to_date : str | None = None ,
354- ):
356+ ) -> dict | None :
355357 """
356358 Returns auditing records filtered using provided parameters
357359 :param offset: the number of record from which search starts
@@ -381,7 +383,7 @@ def get_audit_records(
381383 url = self .resource_url ("auditing/record" )
382384 return self .get (url , params = params ) or {}
383385
384- def post_audit_record (self , audit_record : dict | str ):
386+ def post_audit_record (self , audit_record : dict | str ) -> dict | None :
385387 """
386388 Store a record in Audit Log
387389 :param audit_record: json with compat https://docs.atlassian.com/jira/REST/schema/audit-record#
@@ -395,7 +397,7 @@ def post_audit_record(self, audit_record: dict | str):
395397 Reference: https://docs.atlassian.com/software/jira/docs/api/REST/8.5.0/#api/2/avatar
396398 """
397399
398- def get_all_system_avatars (self , avatar_type : str = "user" ):
400+ def get_all_system_avatars (self , avatar_type : str = "user" ) -> dict | None :
399401 """
400402 Returns all system avatars of the given type.
401403 :param avatar_type:
@@ -411,11 +413,11 @@ def get_all_system_avatars(self, avatar_type: str = "user"):
411413 Reference: https://docs.atlassian.com/software/jira/docs/api/REST/8.5.0/#api/2/cluster
412414 """
413415
414- def get_cluster_all_nodes (self ):
416+ def get_cluster_all_nodes (self ) -> dict | None :
415417 url = self .resource_url ("cluster/nodes" )
416418 return self .get (url )
417419
418- def delete_cluster_node (self , node_id : T_id ):
420+ def delete_cluster_node (self , node_id : T_id ) -> dict | None :
419421 """
420422 Delete the node from the cluster if state of node is OFFLINE
421423 :param node_id: str
@@ -425,7 +427,7 @@ def delete_cluster_node(self, node_id: T_id):
425427 url = "{base_url}/{node_id}" .format (base_url = base_url , node_id = node_id )
426428 return self .delete (url )
427429
428- def set_node_to_offline (self , node_id : T_id ):
430+ def set_node_to_offline (self , node_id : T_id ) -> dict | None :
429431 """
430432 Change the node's state to offline if the node is reporting as active, but is not alive
431433 :param node_id: str
@@ -435,14 +437,15 @@ def set_node_to_offline(self, node_id: T_id):
435437 url = "{base_url}/{node_id}/offline" .format (base_url = base_url , node_id = node_id )
436438 return self .put (url )
437439
438- def get_cluster_alive_nodes (self ):
440+ def get_cluster_alive_nodes (self ) -> list :
439441 """
440442 Get cluster nodes where alive = True
441443 :return: list of node dicts
442444 """
443- return [_ for _ in self .get_cluster_all_nodes () if _ ["alive" ]]
445+ nodes = self .get_cluster_all_nodes ()
446+ return [_ for _ in nodes .values () if _ ["alive" ]] if nodes else []
444447
445- def request_current_index_from_node (self , node_id : T_id ):
448+ def request_current_index_from_node (self , node_id : T_id ) -> dict | None :
446449 """
447450 Request current index from node (the request is processed asynchronously)
448451 :return:
@@ -456,7 +459,7 @@ def request_current_index_from_node(self, node_id: T_id):
456459 Reference: https://confluence.atlassian.com/support/create-a-support-zip-using-the-rest-api-in-data-center-applications-952054641.html
457460 """
458461
459- def generate_support_zip_on_nodes (self , node_ids : list ):
462+ def generate_support_zip_on_nodes (self , node_ids : list ) -> dict | None :
460463 """
461464 Generate a support zip on targeted nodes of a cluster
462465 :param node_ids: list
@@ -466,7 +469,7 @@ def generate_support_zip_on_nodes(self, node_ids: list):
466469 url = "/rest/troubleshooting/latest/support-zip/cluster"
467470 return self .post (url , data = data )
468471
469- def check_support_zip_status (self , cluster_task_id : T_id ):
472+ def check_support_zip_status (self , cluster_task_id : T_id ) -> dict | None :
470473 """
471474 Check status of support zip creation task
472475 :param cluster_task_id: str
@@ -475,7 +478,7 @@ def check_support_zip_status(self, cluster_task_id: T_id):
475478 url = "/rest/troubleshooting/latest/support-zip/status/cluster/{}" .format (cluster_task_id )
476479 return self .get (url )
477480
478- def download_support_zip (self , file_name : str ):
481+ def download_support_zip (self , file_name : str ) -> bytes :
479482 """
480483 Download created support zip file
481484 :param file_name: str
@@ -489,12 +492,12 @@ def download_support_zip(self, file_name: str):
489492 Reference: https://docs.atlassian.com/software/jira/docs/api/REST/8.5.0/#api/2/cluster/zdu
490493 """
491494
492- def get_cluster_zdu_state (self ):
495+ def get_cluster_zdu_state (self ) -> dict | None :
493496 url = self .resource_url ("cluster/zdu/state" )
494497 return self .get (url )
495498
496499 # Issue Comments
497- def issue_get_comments (self , issue_id : T_id ):
500+ def issue_get_comments (self , issue_id : T_id ) -> dict | None :
498501 """
499502 Get Comments on an Issue.
500503 :param issue_id: Issue ID
@@ -505,7 +508,7 @@ def issue_get_comments(self, issue_id: T_id):
505508 url = "{base_url}/{issue_id}/comment" .format (base_url = base_url , issue_id = issue_id )
506509 return self .get (url )
507510
508- def issues_get_comments_by_id (self , * args ) :
511+ def issues_get_comments_by_id (self , * args : int ) -> dict | None :
509512 """
510513 Get Comments on Multiple Issues
511514 :param *args: int Issue ID's
@@ -840,7 +843,7 @@ def get_filter(self, filter_id: T_id):
840843 url = "{base_url}/{id}" .format (base_url = base_url , id = filter_id )
841844 return self .get (url )
842845
843- def update_filter (self , filter_id : T_id , jql : str , ** kwargs ):
846+ def update_filter (self , filter_id : T_id , jql : str , ** kwargs : Any ):
844847 """
845848 :param filter_id: int
846849 :param jql: str
@@ -1407,7 +1410,7 @@ def issue_field_value_append(self, issue_id_or_key: str, field: str, value: str,
14071410 params = params ,
14081411 )
14091412
1410- def get_issue_labels (self , issue_key : str ):
1413+ def get_issue_labels (self , issue_key : str ) -> dict | None :
14111414 """
14121415 Get issue labels.
14131416 :param issue_key:
@@ -1417,7 +1420,11 @@ def get_issue_labels(self, issue_key: str):
14171420 url = "{base_url}/{issue_key}?fields=labels" .format (base_url = base_url , issue_key = issue_key )
14181421 if self .advanced_mode :
14191422 return self .get (url )
1420- return (self .get (url ) or {}).get ("fields" ).get ("labels" )
1423+ d = self .get (url ) or {}
1424+ f = d .get ("fields" )
1425+ if f :
1426+ return f .get ("labels" )
1427+ return None
14211428
14221429 def update_issue (self , issue_key : T_id , update : dict | str ) -> dict | None :
14231430 """
@@ -1741,7 +1748,7 @@ def scrap_regex_from_issue(self, issue: str, regex: str):
17411748 except HTTPError as e :
17421749 if e .response .status_code == 404 :
17431750 # Raise ApiError as the documented reason is ambiguous
1744- log .error ("couldn't find issue: " , issue [ "key" ] )
1751+ log .error ("couldn't find issue: " , issue )
17451752 raise ApiNotFoundError (
17461753 "There is no content with the given issue ud,"
17471754 "or the calling user does not have permission to view the issue" ,
@@ -1882,7 +1889,7 @@ def update_issue_remote_link_by_id(
18821889 )
18831890 return self .put (url , data = data )
18841891
1885- def delete_issue_remote_link_by_id (self , issue_key : str , link_id : T_id ):
1892+ def delete_issue_remote_link_by_id (self , issue_key : str , link_id : T_id ) -> dict | None :
18861893 """
18871894 Deletes Remote Link on Issue
18881895 :param issue_key: str
@@ -1894,27 +1901,23 @@ def delete_issue_remote_link_by_id(self, issue_key: str, link_id: T_id):
18941901 )
18951902 return self .delete (url )
18961903
1897- def get_issue_transitions (self , issue_key : str ):
1904+ def get_issue_transitions (self , issue_key : str ) -> list [ dict ] :
18981905 if self .advanced_mode :
1899- return [
1900- {
1901- "name" : transition ["name" ],
1902- "id" : int (transition ["id" ]),
1903- "to" : transition ["to" ]["name" ],
1904- }
1905- for transition in (self .get_issue_transitions_full (issue_key ).json () or {}).get ("transitions" )
1906- ]
1906+ resp = cast (Response , self .get_issue_transitions_full (issue_key ))
1907+ d : dict [str , list ] = resp .json () or {}
19071908 else :
1908- return [
1909- {
1910- "name" : transition ["name" ],
1911- "id" : int (transition ["id" ]),
1912- "to" : transition ["to" ]["name" ],
1913- }
1914- for transition in (self .get_issue_transitions_full (issue_key ) or {}).get ("transitions" )
1915- ]
1909+ d = self .get_issue_transitions_full (issue_key ) or {}
1910+
1911+ return [
1912+ {
1913+ "name" : transition ["name" ],
1914+ "id" : int (transition ["id" ]),
1915+ "to" : transition ["to" ]["name" ],
1916+ }
1917+ for transition in cast (list [dict ], d .get ("transitions" ))
1918+ ]
19161919
1917- def issue_transition (self , issue_key : str , status : str ):
1920+ def issue_transition (self , issue_key : str , status : str ) -> dict | None :
19181921 return self .set_issue_status (issue_key , status )
19191922
19201923 def set_issue_status (
@@ -1970,12 +1973,12 @@ def set_issue_status_by_transition_id(self, issue_key: str, transition_id: T_id)
19701973 def get_issue_status (self , issue_key : str ):
19711974 base_url = self .resource_url ("issue" )
19721975 url = "{base_url}/{issue_key}?fields=status" .format (base_url = base_url , issue_key = issue_key )
1973- return ((( self .get (url ) or {}).get ("fields" ) or {}). get ("status" ) or {}). get ("name" ) or {}
1976+ return (self .get (url ) or {}).__getitem__ ("fields" ). __getitem__ ("status" ). __getitem__ ("name" )
19741977
1975- def get_issue_status_id (self , issue_key : str ):
1978+ def get_issue_status_id (self , issue_key : str ) -> str :
19761979 base_url = self .resource_url ("issue" )
19771980 url = "{base_url}/{issue_key}?fields=status" .format (base_url = base_url , issue_key = issue_key )
1978- return (self .get (url ) or {}).get ("fields" ).get ("status" ).get ("id" )
1981+ return (self .get (url ) or {}).__getitem__ ("fields" ).__getitem__ ("status" ).__getitem__ ("id" )
19791982
19801983 def get_issue_transitions_full (
19811984 self , issue_key : str , transition_id : T_id | None = None , expand : str | None = None
@@ -3161,7 +3164,7 @@ def get_assignable_users_for_issue(
31613164 def get_status_id_from_name (self , status_name : str ):
31623165 base_url = self .resource_url ("status" )
31633166 url = "{base_url}/{name}" .format (base_url = base_url , name = status_name )
3164- return int ((self .get (url ) or {}).get ("id" ))
3167+ return int ((self .get (url ) or {}).__getitem__ ("id" ))
31653168
31663169 def get_status_for_project (self , project_key : str ):
31673170 base_url = self .resource_url ("project" )
@@ -3879,7 +3882,7 @@ def get_issue_security_scheme(self, scheme_id: T_id, only_levels: bool = False):
38793882 url = "{base_url}/{scheme_id}" .format (base_url = base_url , scheme_id = scheme_id )
38803883
38813884 if only_levels is True :
3882- return self .get (url ). get ("levels" )
3885+ return ( self .get (url ) or {}). __getitem__ ("levels" )
38833886 else :
38843887 return self .get (url )
38853888
0 commit comments