python-jira-plus 1.0.12__tar.gz → 1.0.14__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_jira_plus-1.0.12/python_jira_plus.egg-info → python_jira_plus-1.0.14}/PKG-INFO +1 -1
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus/jira_plus.py +54 -51
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14/python_jira_plus.egg-info}/PKG-INFO +1 -1
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/setup.py +1 -1
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/LICENSE +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/MANIFEST.in +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/README.md +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/pyproject.toml +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus/__init__.py +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus/describe_allowed_value.py +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus.egg-info/SOURCES.txt +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus.egg-info/dependency_links.txt +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus.egg-info/requires.txt +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus.egg-info/top_level.txt +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/requirements.txt +0 -0
- {python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/setup.cfg +0 -0
|
@@ -7,6 +7,7 @@ import time
|
|
|
7
7
|
from enum import Enum
|
|
8
8
|
from typing import Any, Union, Optional
|
|
9
9
|
import requests
|
|
10
|
+
from custom_python_logger import get_logger
|
|
10
11
|
from jira import JIRA, JIRAError, Issue
|
|
11
12
|
from jira.client import ResultList
|
|
12
13
|
from retrying import retry
|
|
@@ -26,17 +27,17 @@ class ServerType(Enum):
|
|
|
26
27
|
|
|
27
28
|
class JiraPlus:
|
|
28
29
|
def __init__(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
self, base_url: Optional[str] = None,
|
|
31
|
+
server_type: ServerType = ServerType.CLOUD,
|
|
32
|
+
urllib3_log_level: int = logging.WARNING,
|
|
33
|
+
jira_username: Optional[str] = None,
|
|
34
|
+
jira_token: Optional[str] = None, # Use API token (not PAT)
|
|
35
|
+
verify_ssl: bool = True,
|
|
36
|
+
sso: bool = False,
|
|
37
|
+
url_scheme: UrlScheme = UrlScheme.HTTPS
|
|
37
38
|
) -> None:
|
|
38
|
-
self.logger =
|
|
39
|
-
|
|
39
|
+
self.logger = get_logger(self.__class__.__name__)
|
|
40
|
+
get_logger("urllib3").setLevel(urllib3_log_level)
|
|
40
41
|
|
|
41
42
|
self.jira_username = jira_username or os.getenv('JIRA_USER_NAME')
|
|
42
43
|
self.jira_token = jira_token or os.getenv('JIRA_TOKEN')
|
|
@@ -51,8 +52,7 @@ class JiraPlus:
|
|
|
51
52
|
self.jira_client = self.create_connection()
|
|
52
53
|
self.check_client_connection()
|
|
53
54
|
|
|
54
|
-
@retry(stop_max_attempt_number=3,
|
|
55
|
-
wait_fixed=180000) # Retry 3 times with a 3-min (180000) delay between each attempt
|
|
55
|
+
@retry(stop_max_attempt_number=3, wait_fixed=180000)
|
|
56
56
|
def create_connection(self, timeout=580) -> Optional[JIRA]:
|
|
57
57
|
if self.server_type == ServerType.ON_PREMISE and not self.sso:
|
|
58
58
|
jira_client = JIRA(
|
|
@@ -99,10 +99,10 @@ class JiraPlus:
|
|
|
99
99
|
return False
|
|
100
100
|
|
|
101
101
|
def get_issue_by_key(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
self,
|
|
103
|
+
key: str,
|
|
104
|
+
specific_fields: str | list[str] = '*all',
|
|
105
|
+
json_result: bool = True
|
|
106
106
|
) -> None | Issue | dict[str, Any]:
|
|
107
107
|
try:
|
|
108
108
|
jira_issue = self.jira_client.issue(id=key, fields=specific_fields)
|
|
@@ -117,12 +117,12 @@ class JiraPlus:
|
|
|
117
117
|
return None
|
|
118
118
|
|
|
119
119
|
def get_objects_by_query(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
self,
|
|
121
|
+
query: str,
|
|
122
|
+
max_results: int = 5000,
|
|
123
|
+
specific_fields: Union[str, list[str]] = "*all",
|
|
124
|
+
jira_err_count: int = 3,
|
|
125
|
+
json_result: bool = True,
|
|
126
126
|
) -> Optional[Union[ResultList[Issue], dict]]:
|
|
127
127
|
return self._paginate_query(
|
|
128
128
|
query=query,
|
|
@@ -133,12 +133,12 @@ class JiraPlus:
|
|
|
133
133
|
)
|
|
134
134
|
|
|
135
135
|
def _paginate_query(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
self,
|
|
137
|
+
query: str,
|
|
138
|
+
max_results: int,
|
|
139
|
+
specific_fields: Union[str, list[str]],
|
|
140
|
+
jira_err_limit: int,
|
|
141
|
+
json_result: bool
|
|
142
142
|
) -> Union[ResultList[Issue] | list]:
|
|
143
143
|
start_at = 0
|
|
144
144
|
all_issues = []
|
|
@@ -162,6 +162,9 @@ class JiraPlus:
|
|
|
162
162
|
break
|
|
163
163
|
retries = 0 # reset on success
|
|
164
164
|
except JIRAError as err:
|
|
165
|
+
if err.status_code == 400:
|
|
166
|
+
self.logger.error(f"Bad Request: {err.text}")
|
|
167
|
+
raise JIRAError(f"Bad Request: {err.text}")
|
|
165
168
|
retries += 1
|
|
166
169
|
self.logger.warning(f"Retry {retries}/{jira_err_limit} after JIRAError: {err}")
|
|
167
170
|
if retries >= jira_err_limit:
|
|
@@ -190,10 +193,10 @@ class JiraPlus:
|
|
|
190
193
|
return meta, issue_meta
|
|
191
194
|
|
|
192
195
|
def get_allowed_values(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
196
|
+
self,
|
|
197
|
+
project_key: str,
|
|
198
|
+
issue_type: str,
|
|
199
|
+
field_id_or_name: str,
|
|
197
200
|
) -> Optional[list]:
|
|
198
201
|
"""
|
|
199
202
|
Returns the allowed values for a specific field in a project + issue type context.
|
|
@@ -253,10 +256,10 @@ class JiraPlus:
|
|
|
253
256
|
return {f.fieldId: f.raw for f in field_list}
|
|
254
257
|
|
|
255
258
|
def validate_fields(
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
259
|
+
self,
|
|
260
|
+
project_key: str,
|
|
261
|
+
issue_type: str,
|
|
262
|
+
fields: Optional[dict] = None
|
|
260
263
|
) -> None:
|
|
261
264
|
fields_metadata = self.get_project_fields_metadata(
|
|
262
265
|
project_key=project_key,
|
|
@@ -291,13 +294,13 @@ class JiraPlus:
|
|
|
291
294
|
# Add more field type checks as needed
|
|
292
295
|
|
|
293
296
|
def create_issue(
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
297
|
+
self,
|
|
298
|
+
project_key: str,
|
|
299
|
+
summary: str,
|
|
300
|
+
description: str,
|
|
301
|
+
issue_type: str,
|
|
302
|
+
assignee: Optional[str] = None,
|
|
303
|
+
custom_fields: Optional[dict] = None,
|
|
301
304
|
) -> Optional[Issue]:
|
|
302
305
|
issue_fields = {
|
|
303
306
|
"project": {"key": project_key},
|
|
@@ -318,9 +321,9 @@ class JiraPlus:
|
|
|
318
321
|
return issue
|
|
319
322
|
|
|
320
323
|
def update_issue(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
+
self,
|
|
325
|
+
issue_key: str,
|
|
326
|
+
fields_to_update: dict
|
|
324
327
|
) -> Optional[Issue]:
|
|
325
328
|
try:
|
|
326
329
|
issue = self.jira_client.issue(issue_key)
|
|
@@ -393,11 +396,11 @@ class JiraPlus:
|
|
|
393
396
|
self.logger.exception(f"Exception - Attachment {file_path} was not uploaded to issue {issue_key}\n{err}")
|
|
394
397
|
|
|
395
398
|
def transition_issue(
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
399
|
+
self,
|
|
400
|
+
issue_key: str,
|
|
401
|
+
transition_name: str,
|
|
402
|
+
fields: Optional[dict] = None,
|
|
403
|
+
comment: Optional[str] = None,
|
|
401
404
|
) -> bool:
|
|
402
405
|
try:
|
|
403
406
|
transitions = self.jira_client.transitions(issue_key)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus/describe_allowed_value.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_jira_plus-1.0.12 → python_jira_plus-1.0.14}/python_jira_plus.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|