Add type-safe Jira issue models with fluent builders#1634
Open
yechielb2000 wants to merge 7 commits intoatlassian-api:masterfrom
Open
Add type-safe Jira issue models with fluent builders#1634yechielb2000 wants to merge 7 commits intoatlassian-api:masterfrom
yechielb2000 wants to merge 7 commits intoatlassian-api:masterfrom
Conversation
Introduce a new `atlassian.models.jira` package that eliminates manual JSON/dictionary construction for Jira operations in favor of typed dataclasses, fluent builders, and a centralized serializer. Core modules: - fields.py: frozen value-object dataclasses (Project, Priority, User, etc.) with to_dict()/from_dict() for (de)serialization - issues.py: JiraIssue base + Task/Bug/Story/Epic/SubTask with __init_subclass__ auto-registry - builders.py: generic IssueBuilder[T] with per-type builders, ADF bridge pattern, and .validate() chaining - serializer.py: FieldMapping + serialize()/to_fields_dict()/bulk_serialize() - adf.py: ADFBuilder for Atlassian Document Format rich-text descriptions - validation.py: pre-flight validate()/validate_or_raise() - update.py: UpdateBuilder for issue_update with set/add/remove operations - transition.py: Transition model for set_issue_status() - comment.py: Comment + Visibility for issue_add_comment() Also adds py.typed marker, convenience import alias (atlassian.jira_models), and 86 tests covering all modules.
Add type-safe Jira issue models with fluent builders
Author
|
linked issue #1556 |
- Remove unused imports (CustomField in serializer.py, Any in validation.py) - Reduce cyclomatic complexity of serialize() and IssueFields.from_dict() by extracting helper functions - Apply black formatter (line-length=120, target py39/py310/py311) - All flake8 checks pass, all 86 tests pass
- Eliminate code duplication in fields.py: extract _NameIdEntity and _KeyIdEntity base classes for 6 near-identical value-object dataclasses - Eliminate duplication in update.py: extract _entity_op and _set_entity_list helpers for repetitive add/remove/set methods - Fix W0622: rename id params to id_ in builders.py and update.py - Fix D401: reword to_fields_dict docstring to imperative mood - Fix D212: all multi-line docstrings use summary-on-first-line style - Fix D105: all magic methods (__post_init__, __init__, etc.) have docstrings - Fix D416: all section headers end with colon - Fix R0913: reduce _entity_op args from 6 to 4 - Suppress R0902 on IssueFields (18 attrs inherent to Jira data model) - Suppress R0904 on IssueBuilder/UpdateBuilder (fluent builder pattern) - Suppress C0415 on circular import workaround in IssueFields.from_dict - All pylint scores 10.00/10, black/flake8/bandit clean, 86 tests pass Note: D203 (blank line before class docstring) conflicts with Black formatter which is enforced in project CI. Black removes these blank lines (D211 style). This is an unresolvable Codacy/Black conflict.
Fix code duplication, pylint issues, and Codacy compliance
- Deduplicate bullet_list/ordered_list in adf.py via shared _list_node - Fix D407: use rST code-block syntax (::) for Example/Usage sections in update.py, comment.py, and transition.py - Simplify test imports: use unified atlassian.models.jira package instead of importing from individual submodules
Fix ADF duplication, docstring sections, and simplify test imports
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Creating Jira issues today requires building raw dictionaries with no editor support, no validation, and no discoverability:
Problems with the current approach:
"sumary","issutype") silently produce 400 errors from Jiracustomfield_NNNNNIDs are embedded everywhereSolution
This PR introduces
atlassian.models.jira— a stdlib-only type-safe layer built on Python dataclasses. Zero new dependencies. Compatible with Python 3.9+.The same issue, with the new API:
Every method is typed, discoverable via autocomplete, and validated before hitting the API.
Features
1. Fluent Builders for all issue types
2. Rich-text descriptions with ADF Builder
No more hand-crafting Atlassian Document Format JSON:
Or use
ADFBuilderstandalone for any ADF field:3. Typed value objects with validation
Every Jira entity is a frozen dataclass that validates on construction:
4. Pre-flight validation
Catch mistakes before making API calls:
5. Custom field mapping
Different Jira instances use different custom field IDs. Map them once:
6. Issue updates
7. Transitions
8. Comments with visibility
9. Bulk create
10. Deserialization (API response → typed objects)
11. Auto-registry for custom issue types
Architecture
Design decisions
from __future__ import annotationsslots=Trueorkw_only=TrueIssueFieldsIssueBuilder[T]build()returns the concrete type (e.g.,Bug, notJiraIssue) for downstream type narrowing__init_subclass__registryfrom_dict()returns the correct class without manual wiringFieldMappinghandles per-instance custom field IDspy.typedmarkermypy/pyrightsupport out of the box (PEP 561)Tests
86 pytest tests covering all modules:
Categories:
to_dict(),from_dict()ClassVar,__post_init__, registry,from_dict()serialize(),to_fields_dict(),bulk_serialize(),FieldMappingbuild_dict(),build_payload(), ADF bridge,validate()UpdateBuilderset/add/remove operationsTransition,TransitionBuilderComment,VisibilityBreaking changes
None. This is purely additive — no existing code is modified.
Checklist
py.typedmarker)