python-jira-plus 2.0.6__py3-none-any.whl → 2.0.8__py3-none-any.whl

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.
@@ -8,7 +8,7 @@ pagination, metadata validation, and more.
8
8
  from dotenv import load_dotenv
9
9
 
10
10
  from python_jira_plus.describe_allowed_value import describe_allowed_value
11
- from python_jira_plus.jira_plus import JiraPlus, ServerType
11
+ from python_jira_plus.jira_plus import JiraPlus, ServerType, UrlScheme
12
12
 
13
13
  load_dotenv()
14
14
 
@@ -27,4 +27,4 @@ BASIC_FIELDS = [
27
27
  "resolution",
28
28
  "parent",
29
29
  ]
30
- __all__ = ["JiraPlus", "ServerType", "BASIC_FIELDS"]
30
+ __all__ = ["JiraPlus", "ServerType", "UrlScheme", "BASIC_FIELDS"]
@@ -11,17 +11,17 @@ def describe_allowed_value(value: Any, allowed_values: set = None) -> bool:
11
11
 
12
12
  @describe_allowed_value.register
13
13
  def _(value: int, allowed_values: list = None) -> bool:
14
- return value == allowed_values
14
+ return value in allowed_values
15
15
 
16
16
 
17
17
  @describe_allowed_value.register
18
18
  def _(value: float, allowed_values: list = None) -> bool:
19
- return value == allowed_values
19
+ return value in allowed_values
20
20
 
21
21
 
22
22
  @describe_allowed_value.register
23
23
  def _(value: str, allowed_values: list = None) -> bool:
24
- return value == allowed_values
24
+ return value in allowed_values
25
25
 
26
26
 
27
27
  @describe_allowed_value.register
@@ -12,7 +12,7 @@ from custom_python_logger import get_logger
12
12
  from jira import JIRA, Issue, JIRAError
13
13
  from jira.client import ResultList
14
14
  from retrying import retry
15
-
15
+ from packaging.version import Version
16
16
  from python_jira_plus.describe_allowed_value import describe_allowed_value
17
17
 
18
18
 
@@ -53,10 +53,12 @@ class JiraPlus:
53
53
 
54
54
  self.jira_client = self.create_connection()
55
55
  self.check_client_connection()
56
+ self.server_version = self.get_server_version()
57
+ self.use_legacy_api = self._resolve_use_legacy_api()
56
58
 
57
59
  @retry(stop_max_attempt_number=3, wait_fixed=180000)
58
- def create_connection(self, timeout: int = 580) -> JIRA | None:
59
- if self.server_type == ServerType.ON_PREMISE and not self.sso: # pylint: disable=W0160:
60
+ def create_connection(self, timeout: int = 580) -> JIRA:
61
+ if self.server_type == ServerType.ON_PREMISE and not self.sso:
60
62
  jira_client = JIRA(
61
63
  token_auth=self.jira_token, options={"server": self.server, "verify": self.verify_ssl}, timeout=timeout
62
64
  )
@@ -142,12 +144,16 @@ class JiraPlus:
142
144
  all_issues = []
143
145
  retries = 0
144
146
  page = None
145
- while True: # pylint: disable=W0149
147
+ while True:
146
148
  try:
149
+ next_token = None
150
+ if page is not None:
151
+ next_token = page.get('nextPageToken') if json_result else page.nextPageToken
152
+
147
153
  self.logger.debug(f"Fetching issues from startAt={len(all_issues)}")
148
154
  page = self.jira_client.enhanced_search_issues(
149
155
  jql_str=query,
150
- nextPageToken=page['nextPageToken'] if page else None,
156
+ nextPageToken=next_token,
151
157
  maxResults=max_results,
152
158
  fields=specific_fields,
153
159
  json_result=json_result,
@@ -156,7 +162,8 @@ class JiraPlus:
156
162
  break
157
163
 
158
164
  all_issues += page["issues"] if json_result else page
159
- if page['isLast']:
165
+ is_last = page['isLast'] if json_result else page.isLast
166
+ if is_last:
160
167
  break
161
168
  retries = 0 # reset on success
162
169
  except JIRAError as err:
@@ -268,18 +275,16 @@ class JiraPlus:
268
275
  def get_server_version(self) -> tuple[int, ...]:
269
276
  return tuple(self.jira_client.server_info()["versionNumbers"])
270
277
 
271
- def check_server_createmeta_compatibility(self) -> bool:
272
- server_version = self.get_server_version()
273
- if self.server_type == ServerType.ON_PREMISE and "".join(str(x) for x in server_version) > "9.0.0":
274
- self.logger.warning(
275
- f"JIRA server version {server_version} is below the minimum required version (9.0.0). "
276
- "Some features may not work as expected."
277
- )
278
- return False
278
+ def _resolve_use_legacy_api(self) -> bool:
279
+ if self.server_type == ServerType.ON_PREMISE:
280
+ use_legacy = Version(".".join(str(x) for x in self.server_version)) < Version("9.0.0")
281
+ self.logger.debug(f"Using {'legacy createmeta' if use_legacy else 'project_issue_types'} API (ON_PREMISE {self.server_version})")
282
+ return use_legacy
283
+ self.logger.debug("Using legacy createmeta API (Cloud)")
279
284
  return True
280
285
 
281
286
  def get_project_fields_metadata(self, project_key: str, issue_type: str) -> dict:
282
- if self.check_server_createmeta_compatibility():
287
+ if self.use_legacy_api:
283
288
  _, issue_meta = self._fetch_metadata(project_key=project_key, issue_type=issue_type)
284
289
  return issue_meta["fields"]
285
290
  _project_issue_types = self.jira_client.project_issue_types(project_key)
@@ -288,7 +293,7 @@ class JiraPlus:
288
293
  return {f.fieldId: f.raw for f in field_list}
289
294
 
290
295
  def validate_fields( # pylint: disable=R1260
291
- self, project_key: str, issue_type: str, fields: dict | None = None
296
+ self, project_key: str, issue_type: str, fields: dict
292
297
  ) -> None:
293
298
  fields_metadata = self.get_project_fields_metadata(project_key=project_key, issue_type=issue_type)
294
299
  for custom_field, value in fields.items():
@@ -367,7 +372,7 @@ class JiraPlus:
367
372
 
368
373
  def delete_issue(self, issue_key: str) -> bool:
369
374
  try:
370
- issue = self.get_issue_by_key(key=issue_key)
375
+ issue = self.get_issue_by_key(key=issue_key, json_result=False)
371
376
  issue.delete()
372
377
  self.logger.info(f"Issue {issue_key} deleted successfully.")
373
378
  return True
@@ -452,10 +457,13 @@ class JiraPlus:
452
457
  return False
453
458
 
454
459
  def get_account_data(self, user_mail: str) -> list[dict]:
455
- jira_rst_url = (
456
- f"https://{self.jira_username}:{self.jira_token}@{self.base_url}/rest/api/{3}/user/search?query={user_mail}"
460
+ response = requests.get(
461
+ f"{self.server}/rest/api/3/user/search",
462
+ params={"query": user_mail},
463
+ auth=(self.jira_username, self.jira_token),
464
+ timeout=30,
457
465
  )
458
- response = requests.get(jira_rst_url)
466
+ response.raise_for_status()
459
467
  return response.json()
460
468
 
461
469
  def get_account_id(self, user_mail: str) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-jira-plus
3
- Version: 2.0.6
3
+ Version: 2.0.8
4
4
  Summary: Enhanced Python client for JIRA with better error handling, pagination, and metadata validation.
5
5
  Author: Avi Zaguri
6
6
  License: MIT
@@ -17,14 +17,16 @@ Requires-Python: >=3.12
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  Requires-Dist: custom-python-logger>=2.0.10
20
- Requires-Dist: dotenv>=0.9.9
20
+ Requires-Dist: python-dotenv>=1.0.0
21
21
  Requires-Dist: jira>=3.10.5
22
- Requires-Dist: pre-commit>=4.5.0
23
- Requires-Dist: pytest>=9.0.1
22
+ Requires-Dist: packaging>=26.2
24
23
  Requires-Dist: requests>=2.32.5
25
24
  Requires-Dist: retrying>=1.4.2
26
- Requires-Dist: setuptools>=80.9.0
27
- Requires-Dist: wheel>=0.45.1
25
+ Provides-Extra: dev
26
+ Requires-Dist: pre-commit>=4.5.0; extra == "dev"
27
+ Requires-Dist: pytest>=9.0.1; extra == "dev"
28
+ Requires-Dist: setuptools>=80.9.0; extra == "dev"
29
+ Requires-Dist: wheel>=0.45.1; extra == "dev"
28
30
  Dynamic: license-file
29
31
 
30
32
  ![PyPI version](https://img.shields.io/pypi/v/python-jira-plus)
@@ -59,7 +61,7 @@ pip install python-jira-plus
59
61
  ---
60
62
 
61
63
  ## Requirements
62
- - Python 3.9+
64
+ - Python 3.12+
63
65
  - `jira` package
64
66
  - `retrying` package
65
67
  - `custom-python-logger` package
@@ -0,0 +1,8 @@
1
+ python_jira_plus/__init__.py,sha256=BUKjGxQfkxWyZs-mKZs2bAgGnsYHQ4uOFjuB8MPmhfg,616
2
+ python_jira_plus/describe_allowed_value.py,sha256=fWfq0DkvJ2zmNIUXPH5rO5OgcY69bUqBIfTPQyxBt5E,1287
3
+ python_jira_plus/jira_plus.py,sha256=TNJkwFdDbkaVrsEaO3kBRGHi_GDFVhRcpoX6bAgyRTs,19568
4
+ python_jira_plus-2.0.8.dist-info/licenses/LICENSE,sha256=cSikHY6SZFsPZSBizCDAJ0-Bjjzxt-JtX6TVbKxwimo,1067
5
+ python_jira_plus-2.0.8.dist-info/METADATA,sha256=AdZUwcmuzp3qtoFVuaB1En8QQqjKxFz6_3U99X6G-o8,4285
6
+ python_jira_plus-2.0.8.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
7
+ python_jira_plus-2.0.8.dist-info/top_level.txt,sha256=3DxBdmf_naggoqDHSvLstG_GX3bW2XXYYorBDybBUiA,17
8
+ python_jira_plus-2.0.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (81.0.0)
2
+ Generator: setuptools (82.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,8 +0,0 @@
1
- python_jira_plus/__init__.py,sha256=hi4PadXJu9vYDqslH0zxAm-UsU_zfVFHCImqbchHbDU,592
2
- python_jira_plus/describe_allowed_value.py,sha256=ZU3SN0d3Xy_4qPaVhkhqQYabt3Q_tN64J2yJ3mV0Abc,1287
3
- python_jira_plus/jira_plus.py,sha256=ZswRdySAqM0me5FEI9jSEdv3oxRklHYLGcAY2beQ9iI,19251
4
- python_jira_plus-2.0.6.dist-info/licenses/LICENSE,sha256=cSikHY6SZFsPZSBizCDAJ0-Bjjzxt-JtX6TVbKxwimo,1067
5
- python_jira_plus-2.0.6.dist-info/METADATA,sha256=3Fdm_jE2laIs9VjSBymL2DW8t84WX2CSX8HDci7Kt10,4162
6
- python_jira_plus-2.0.6.dist-info/WHEEL,sha256=YLJXdYXQ2FQ0Uqn2J-6iEIC-3iOey8lH3xCtvFLkd8Q,91
7
- python_jira_plus-2.0.6.dist-info/top_level.txt,sha256=3DxBdmf_naggoqDHSvLstG_GX3bW2XXYYorBDybBUiA,17
8
- python_jira_plus-2.0.6.dist-info/RECORD,,