atlassian-sdk-py 0.1.0__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.
- atlassian_sdk_py-0.1.0/PKG-INFO +216 -0
- atlassian_sdk_py-0.1.0/README.md +195 -0
- atlassian_sdk_py-0.1.0/pyproject.toml +42 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/__init__.py +93 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/auth.py +49 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/confluence/__init__.py +29 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/confluence/client.py +210 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/confluence/models.py +73 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/confluence/schemas.py +89 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/exceptions.py +65 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/http.py +158 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/jira/__init__.py +41 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/jira/client.py +229 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/jira/models.py +163 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/jira/schemas.py +86 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/mcp/__init__.py +14 -0
- atlassian_sdk_py-0.1.0/src/atlassian_sdk/mcp/server.py +581 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: atlassian-sdk-py
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python async SDK for Atlassian REST API (Jira + Confluence)
|
|
5
|
+
Author: kknaks
|
|
6
|
+
Requires-Python: >=3.11,<4.0
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: httpx (>=0.27,<1.0)
|
|
14
|
+
Requires-Dist: mcp (>=1.0,<2.0)
|
|
15
|
+
Requires-Dist: pydantic (>=2.0,<3.0)
|
|
16
|
+
Requires-Dist: pytest (>=9.0) ; extra == "dev"
|
|
17
|
+
Requires-Dist: pytest-asyncio (>=1.3) ; extra == "dev"
|
|
18
|
+
Requires-Dist: respx (>=0.22) ; extra == "dev"
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# atlassian-sdk-py
|
|
22
|
+
|
|
23
|
+
Atlassian REST API를 직접 호출하는 Python async SDK. Jira + Confluence를 하나의 패키지로 지원합니다.
|
|
24
|
+
|
|
25
|
+
> acli 바이너리 불필요 — httpx로 REST API 직접 호출
|
|
26
|
+
|
|
27
|
+
## 설치
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install atlassian-sdk-py
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 환경변수
|
|
34
|
+
|
|
35
|
+
```env
|
|
36
|
+
ATLASSIAN_SITE=your-site.atlassian.net
|
|
37
|
+
ATLASSIAN_EMAIL=user@example.com
|
|
38
|
+
ATLASSIAN_API_TOKEN=your-api-token
|
|
39
|
+
PYACLI_DEFAULT_PROJECT=WNVO
|
|
40
|
+
PYACLI_EPIC_MAP=frontend:WNVO-9,backend:WNVO-23,ai:WNVO-24
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Jira 사용법
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import asyncio
|
|
47
|
+
from atlassian_sdk import JiraClient
|
|
48
|
+
|
|
49
|
+
async def main():
|
|
50
|
+
client = JiraClient()
|
|
51
|
+
|
|
52
|
+
# 프로젝트 목록 조회
|
|
53
|
+
projects = await client.list_projects()
|
|
54
|
+
|
|
55
|
+
# 에픽 이름으로 이슈 생성 (epic map 사용)
|
|
56
|
+
issue = await client.create_issue(
|
|
57
|
+
summary="로그인 에러 수정",
|
|
58
|
+
epic="frontend", # → WNVO-9 밑에 생성
|
|
59
|
+
labels=["bug", "backend"],
|
|
60
|
+
)
|
|
61
|
+
print(issue.key) # WNVO-111
|
|
62
|
+
print(issue.url) # https://site.atlassian.net/browse/WNVO-111
|
|
63
|
+
|
|
64
|
+
# 이슈 조회
|
|
65
|
+
issue = await client.get_issue("WNVO-111")
|
|
66
|
+
|
|
67
|
+
# JQL 검색
|
|
68
|
+
issues = await client.search_issues(
|
|
69
|
+
jql="project = WNVO AND status = 'To Do'",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# 상태 변경
|
|
73
|
+
await client.transition_issue("WNVO-111", status="완료")
|
|
74
|
+
|
|
75
|
+
# 댓글
|
|
76
|
+
await client.add_comment("WNVO-111", body="수정 완료")
|
|
77
|
+
comments = await client.list_comments("WNVO-111")
|
|
78
|
+
|
|
79
|
+
asyncio.run(main())
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Confluence 사용법
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from atlassian_sdk import ConfluenceClient
|
|
86
|
+
|
|
87
|
+
async def main():
|
|
88
|
+
client = ConfluenceClient()
|
|
89
|
+
|
|
90
|
+
# 스페이스 목록
|
|
91
|
+
spaces = await client.list_spaces()
|
|
92
|
+
|
|
93
|
+
# 페이지 생성
|
|
94
|
+
page = await client.create_page(
|
|
95
|
+
space_id="12345",
|
|
96
|
+
title="회의록 2024-01-15",
|
|
97
|
+
body="<h1>회의 내용</h1><p>안건 논의</p>",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# 페이지 조회 / 수정
|
|
101
|
+
page = await client.get_page("67890")
|
|
102
|
+
updated = await client.update_page(
|
|
103
|
+
"67890",
|
|
104
|
+
title="회의록 (수정)",
|
|
105
|
+
body="<p>수정된 내용</p>",
|
|
106
|
+
version_number=2,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# 하위 페이지 / 댓글
|
|
110
|
+
children = await client.get_child_pages("67890")
|
|
111
|
+
await client.add_footer_comment("67890", body="확인했습니다")
|
|
112
|
+
|
|
113
|
+
# CQL 검색
|
|
114
|
+
results = await client.search(cql="type=page AND space=DEV")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Jira 계층 구조
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
Project (WNVO)
|
|
121
|
+
├── [에픽] 기능구현-프론트 1차 ← parent 없이 생성
|
|
122
|
+
│ ├── [작업] 로그인 에러 수정 ← parent = 에픽 키
|
|
123
|
+
│ │ ├── [하위작업] UI 구현 ← parent = 작업 키
|
|
124
|
+
│ │ └── [하위작업] API 연동
|
|
125
|
+
│ └── [작업] 회원가입 구현
|
|
126
|
+
└── [에픽] 기능구현-백엔드 1차
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Pydantic 입력 모델
|
|
130
|
+
|
|
131
|
+
파라미터가 많을 때 Request 모델을 사용할 수 있습니다:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from atlassian_sdk import JiraClient, CreateIssueRequest
|
|
135
|
+
|
|
136
|
+
client = JiraClient(project="WNVO")
|
|
137
|
+
|
|
138
|
+
req = CreateIssueRequest(
|
|
139
|
+
summary="복잡한 이슈",
|
|
140
|
+
description="상세 설명",
|
|
141
|
+
type="Bug",
|
|
142
|
+
assignee="user-account-id",
|
|
143
|
+
labels=["bug", "urgent"],
|
|
144
|
+
parent="WNVO-9",
|
|
145
|
+
)
|
|
146
|
+
issue = await client.create_issue(request=req)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## FastAPI 에러 자동 보고
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from fastapi import FastAPI, Request
|
|
153
|
+
from fastapi.responses import JSONResponse
|
|
154
|
+
from atlassian_sdk import JiraClient
|
|
155
|
+
import traceback
|
|
156
|
+
|
|
157
|
+
app = FastAPI()
|
|
158
|
+
client = JiraClient()
|
|
159
|
+
|
|
160
|
+
@app.middleware("http")
|
|
161
|
+
async def error_reporting(request: Request, call_next):
|
|
162
|
+
try:
|
|
163
|
+
return await call_next(request)
|
|
164
|
+
except Exception as exc:
|
|
165
|
+
tb = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))
|
|
166
|
+
issue = await client.create_issue(
|
|
167
|
+
summary=f"[AUTO-BUG] {type(exc).__name__}: {exc}",
|
|
168
|
+
description=f"Endpoint: {request.method} {request.url.path}",
|
|
169
|
+
issue_type="버그",
|
|
170
|
+
epic="backend",
|
|
171
|
+
)
|
|
172
|
+
await client.add_comment(issue.key, body=tb)
|
|
173
|
+
return JSONResponse(status_code=500, content={"jira": issue.key})
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## MCP 서버
|
|
177
|
+
|
|
178
|
+
Claude Desktop/Claude Code에서 Jira + Confluence를 사용할 수 있는 MCP 서버가 포함되어 있습니다.
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"mcpServers": {
|
|
183
|
+
"atlassian-sdk": {
|
|
184
|
+
"command": "python",
|
|
185
|
+
"args": ["-m", "atlassian_sdk.mcp"]
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
제공 도구 (20개):
|
|
192
|
+
- **Schema 도구**: `list_methods`, `get_method_info`, `get_models`
|
|
193
|
+
- **Jira 도구**: `list_projects`, `list_issue_types`, `get_issue`, `search_issues`, `create_issue`, `transition_issue`, `add_comment`, `list_comments`
|
|
194
|
+
- **Confluence 도구**: `create_page`, `get_page`, `update_page`, `list_spaces`, `get_pages_in_space`, `get_child_pages`, `get_footer_comments`, `add_footer_comment`, `search_confluence`
|
|
195
|
+
|
|
196
|
+
## 인증
|
|
197
|
+
|
|
198
|
+
| 환경 | 방식 |
|
|
199
|
+
|------|------|
|
|
200
|
+
| 로컬 개발 | `.env` 파일에 환경변수 설정 |
|
|
201
|
+
| Docker / CI | 환경변수 직접 주입 |
|
|
202
|
+
|
|
203
|
+
Basic Auth: `email + API token` → `Authorization: Basic base64(email:token)`
|
|
204
|
+
|
|
205
|
+
## 기술 스택
|
|
206
|
+
|
|
207
|
+
- Python 3.11+
|
|
208
|
+
- httpx (async HTTP)
|
|
209
|
+
- Pydantic v2
|
|
210
|
+
- MCP SDK
|
|
211
|
+
- Poetry
|
|
212
|
+
|
|
213
|
+
## 라이선스
|
|
214
|
+
|
|
215
|
+
MIT
|
|
216
|
+
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# atlassian-sdk-py
|
|
2
|
+
|
|
3
|
+
Atlassian REST API를 직접 호출하는 Python async SDK. Jira + Confluence를 하나의 패키지로 지원합니다.
|
|
4
|
+
|
|
5
|
+
> acli 바이너리 불필요 — httpx로 REST API 직접 호출
|
|
6
|
+
|
|
7
|
+
## 설치
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install atlassian-sdk-py
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 환경변수
|
|
14
|
+
|
|
15
|
+
```env
|
|
16
|
+
ATLASSIAN_SITE=your-site.atlassian.net
|
|
17
|
+
ATLASSIAN_EMAIL=user@example.com
|
|
18
|
+
ATLASSIAN_API_TOKEN=your-api-token
|
|
19
|
+
PYACLI_DEFAULT_PROJECT=WNVO
|
|
20
|
+
PYACLI_EPIC_MAP=frontend:WNVO-9,backend:WNVO-23,ai:WNVO-24
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Jira 사용법
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
import asyncio
|
|
27
|
+
from atlassian_sdk import JiraClient
|
|
28
|
+
|
|
29
|
+
async def main():
|
|
30
|
+
client = JiraClient()
|
|
31
|
+
|
|
32
|
+
# 프로젝트 목록 조회
|
|
33
|
+
projects = await client.list_projects()
|
|
34
|
+
|
|
35
|
+
# 에픽 이름으로 이슈 생성 (epic map 사용)
|
|
36
|
+
issue = await client.create_issue(
|
|
37
|
+
summary="로그인 에러 수정",
|
|
38
|
+
epic="frontend", # → WNVO-9 밑에 생성
|
|
39
|
+
labels=["bug", "backend"],
|
|
40
|
+
)
|
|
41
|
+
print(issue.key) # WNVO-111
|
|
42
|
+
print(issue.url) # https://site.atlassian.net/browse/WNVO-111
|
|
43
|
+
|
|
44
|
+
# 이슈 조회
|
|
45
|
+
issue = await client.get_issue("WNVO-111")
|
|
46
|
+
|
|
47
|
+
# JQL 검색
|
|
48
|
+
issues = await client.search_issues(
|
|
49
|
+
jql="project = WNVO AND status = 'To Do'",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# 상태 변경
|
|
53
|
+
await client.transition_issue("WNVO-111", status="완료")
|
|
54
|
+
|
|
55
|
+
# 댓글
|
|
56
|
+
await client.add_comment("WNVO-111", body="수정 완료")
|
|
57
|
+
comments = await client.list_comments("WNVO-111")
|
|
58
|
+
|
|
59
|
+
asyncio.run(main())
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Confluence 사용법
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from atlassian_sdk import ConfluenceClient
|
|
66
|
+
|
|
67
|
+
async def main():
|
|
68
|
+
client = ConfluenceClient()
|
|
69
|
+
|
|
70
|
+
# 스페이스 목록
|
|
71
|
+
spaces = await client.list_spaces()
|
|
72
|
+
|
|
73
|
+
# 페이지 생성
|
|
74
|
+
page = await client.create_page(
|
|
75
|
+
space_id="12345",
|
|
76
|
+
title="회의록 2024-01-15",
|
|
77
|
+
body="<h1>회의 내용</h1><p>안건 논의</p>",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# 페이지 조회 / 수정
|
|
81
|
+
page = await client.get_page("67890")
|
|
82
|
+
updated = await client.update_page(
|
|
83
|
+
"67890",
|
|
84
|
+
title="회의록 (수정)",
|
|
85
|
+
body="<p>수정된 내용</p>",
|
|
86
|
+
version_number=2,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# 하위 페이지 / 댓글
|
|
90
|
+
children = await client.get_child_pages("67890")
|
|
91
|
+
await client.add_footer_comment("67890", body="확인했습니다")
|
|
92
|
+
|
|
93
|
+
# CQL 검색
|
|
94
|
+
results = await client.search(cql="type=page AND space=DEV")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Jira 계층 구조
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
Project (WNVO)
|
|
101
|
+
├── [에픽] 기능구현-프론트 1차 ← parent 없이 생성
|
|
102
|
+
│ ├── [작업] 로그인 에러 수정 ← parent = 에픽 키
|
|
103
|
+
│ │ ├── [하위작업] UI 구현 ← parent = 작업 키
|
|
104
|
+
│ │ └── [하위작업] API 연동
|
|
105
|
+
│ └── [작업] 회원가입 구현
|
|
106
|
+
└── [에픽] 기능구현-백엔드 1차
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Pydantic 입력 모델
|
|
110
|
+
|
|
111
|
+
파라미터가 많을 때 Request 모델을 사용할 수 있습니다:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from atlassian_sdk import JiraClient, CreateIssueRequest
|
|
115
|
+
|
|
116
|
+
client = JiraClient(project="WNVO")
|
|
117
|
+
|
|
118
|
+
req = CreateIssueRequest(
|
|
119
|
+
summary="복잡한 이슈",
|
|
120
|
+
description="상세 설명",
|
|
121
|
+
type="Bug",
|
|
122
|
+
assignee="user-account-id",
|
|
123
|
+
labels=["bug", "urgent"],
|
|
124
|
+
parent="WNVO-9",
|
|
125
|
+
)
|
|
126
|
+
issue = await client.create_issue(request=req)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## FastAPI 에러 자동 보고
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from fastapi import FastAPI, Request
|
|
133
|
+
from fastapi.responses import JSONResponse
|
|
134
|
+
from atlassian_sdk import JiraClient
|
|
135
|
+
import traceback
|
|
136
|
+
|
|
137
|
+
app = FastAPI()
|
|
138
|
+
client = JiraClient()
|
|
139
|
+
|
|
140
|
+
@app.middleware("http")
|
|
141
|
+
async def error_reporting(request: Request, call_next):
|
|
142
|
+
try:
|
|
143
|
+
return await call_next(request)
|
|
144
|
+
except Exception as exc:
|
|
145
|
+
tb = "".join(traceback.format_exception(type(exc), exc, exc.__traceback__))
|
|
146
|
+
issue = await client.create_issue(
|
|
147
|
+
summary=f"[AUTO-BUG] {type(exc).__name__}: {exc}",
|
|
148
|
+
description=f"Endpoint: {request.method} {request.url.path}",
|
|
149
|
+
issue_type="버그",
|
|
150
|
+
epic="backend",
|
|
151
|
+
)
|
|
152
|
+
await client.add_comment(issue.key, body=tb)
|
|
153
|
+
return JSONResponse(status_code=500, content={"jira": issue.key})
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## MCP 서버
|
|
157
|
+
|
|
158
|
+
Claude Desktop/Claude Code에서 Jira + Confluence를 사용할 수 있는 MCP 서버가 포함되어 있습니다.
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"mcpServers": {
|
|
163
|
+
"atlassian-sdk": {
|
|
164
|
+
"command": "python",
|
|
165
|
+
"args": ["-m", "atlassian_sdk.mcp"]
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
제공 도구 (20개):
|
|
172
|
+
- **Schema 도구**: `list_methods`, `get_method_info`, `get_models`
|
|
173
|
+
- **Jira 도구**: `list_projects`, `list_issue_types`, `get_issue`, `search_issues`, `create_issue`, `transition_issue`, `add_comment`, `list_comments`
|
|
174
|
+
- **Confluence 도구**: `create_page`, `get_page`, `update_page`, `list_spaces`, `get_pages_in_space`, `get_child_pages`, `get_footer_comments`, `add_footer_comment`, `search_confluence`
|
|
175
|
+
|
|
176
|
+
## 인증
|
|
177
|
+
|
|
178
|
+
| 환경 | 방식 |
|
|
179
|
+
|------|------|
|
|
180
|
+
| 로컬 개발 | `.env` 파일에 환경변수 설정 |
|
|
181
|
+
| Docker / CI | 환경변수 직접 주입 |
|
|
182
|
+
|
|
183
|
+
Basic Auth: `email + API token` → `Authorization: Basic base64(email:token)`
|
|
184
|
+
|
|
185
|
+
## 기술 스택
|
|
186
|
+
|
|
187
|
+
- Python 3.11+
|
|
188
|
+
- httpx (async HTTP)
|
|
189
|
+
- Pydantic v2
|
|
190
|
+
- MCP SDK
|
|
191
|
+
- Poetry
|
|
192
|
+
|
|
193
|
+
## 라이선스
|
|
194
|
+
|
|
195
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "atlassian-sdk-py"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Python async SDK for Atlassian REST API (Jira + Confluence)"
|
|
5
|
+
authors = [
|
|
6
|
+
{name = "kknaks"}
|
|
7
|
+
]
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.11,<4.0"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"pydantic>=2.0,<3.0",
|
|
12
|
+
"httpx>=0.27,<1.0",
|
|
13
|
+
"mcp>=1.0,<2.0",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.optional-dependencies]
|
|
17
|
+
dev = [
|
|
18
|
+
"pytest>=9.0",
|
|
19
|
+
"pytest-asyncio>=1.3",
|
|
20
|
+
"respx>=0.22",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
atlassian-sdk-mcp = "atlassian_sdk.mcp:run"
|
|
25
|
+
|
|
26
|
+
[build-system]
|
|
27
|
+
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
|
28
|
+
build-backend = "poetry.core.masonry.api"
|
|
29
|
+
|
|
30
|
+
[tool.poetry]
|
|
31
|
+
packages = [{include = "atlassian_sdk", from = "src"}]
|
|
32
|
+
|
|
33
|
+
[tool.pytest.ini_options]
|
|
34
|
+
testpaths = ["tests"]
|
|
35
|
+
asyncio_mode = "auto"
|
|
36
|
+
|
|
37
|
+
[dependency-groups]
|
|
38
|
+
dev = [
|
|
39
|
+
"pytest (>=9.0.0,<10.0.0)",
|
|
40
|
+
"pytest-asyncio (>=1.3.0,<2.0.0)",
|
|
41
|
+
"respx (>=0.22.0,<1.0.0)",
|
|
42
|
+
]
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Atlassian SDK — Python async client for Jira and Confluence REST APIs."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
__version__ = "0.1.0"
|
|
5
|
+
|
|
6
|
+
from atlassian_sdk.auth import BasicAuth
|
|
7
|
+
from atlassian_sdk.exceptions import (
|
|
8
|
+
ApiError,
|
|
9
|
+
AuthError,
|
|
10
|
+
NotFoundError,
|
|
11
|
+
RateLimitError,
|
|
12
|
+
SdkError,
|
|
13
|
+
TimeoutError,
|
|
14
|
+
ValidationError,
|
|
15
|
+
)
|
|
16
|
+
from atlassian_sdk.http import AsyncHttpClient
|
|
17
|
+
from atlassian_sdk.jira.client import JiraClient
|
|
18
|
+
from atlassian_sdk.jira.models import (
|
|
19
|
+
Comment,
|
|
20
|
+
IssueType,
|
|
21
|
+
JiraIssue,
|
|
22
|
+
JiraProject,
|
|
23
|
+
ParentRef,
|
|
24
|
+
Priority,
|
|
25
|
+
Project,
|
|
26
|
+
Status,
|
|
27
|
+
StatusCategory,
|
|
28
|
+
Transition,
|
|
29
|
+
User,
|
|
30
|
+
)
|
|
31
|
+
from atlassian_sdk.jira.schemas import (
|
|
32
|
+
CreateIssueRequest,
|
|
33
|
+
SearchIssuesRequest,
|
|
34
|
+
TransitionIssueRequest,
|
|
35
|
+
)
|
|
36
|
+
from atlassian_sdk.confluence.client import ConfluenceClient
|
|
37
|
+
from atlassian_sdk.confluence.models import (
|
|
38
|
+
ConfluenceComment,
|
|
39
|
+
Page,
|
|
40
|
+
PageBody,
|
|
41
|
+
PageVersion,
|
|
42
|
+
Space,
|
|
43
|
+
)
|
|
44
|
+
from atlassian_sdk.confluence.schemas import (
|
|
45
|
+
CreateCommentRequest,
|
|
46
|
+
CreatePageRequest,
|
|
47
|
+
SearchConfluenceRequest,
|
|
48
|
+
UpdatePageRequest,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
__all__ = [
|
|
52
|
+
# Version
|
|
53
|
+
"__version__",
|
|
54
|
+
# Auth
|
|
55
|
+
"BasicAuth",
|
|
56
|
+
# HTTP
|
|
57
|
+
"AsyncHttpClient",
|
|
58
|
+
# Exceptions
|
|
59
|
+
"SdkError",
|
|
60
|
+
"ApiError",
|
|
61
|
+
"AuthError",
|
|
62
|
+
"NotFoundError",
|
|
63
|
+
"RateLimitError",
|
|
64
|
+
"TimeoutError",
|
|
65
|
+
"ValidationError",
|
|
66
|
+
# Jira
|
|
67
|
+
"JiraClient",
|
|
68
|
+
"JiraIssue",
|
|
69
|
+
"JiraProject",
|
|
70
|
+
"IssueType",
|
|
71
|
+
"Status",
|
|
72
|
+
"StatusCategory",
|
|
73
|
+
"Priority",
|
|
74
|
+
"User",
|
|
75
|
+
"Project",
|
|
76
|
+
"ParentRef",
|
|
77
|
+
"Transition",
|
|
78
|
+
"Comment",
|
|
79
|
+
"CreateIssueRequest",
|
|
80
|
+
"SearchIssuesRequest",
|
|
81
|
+
"TransitionIssueRequest",
|
|
82
|
+
# Confluence
|
|
83
|
+
"ConfluenceClient",
|
|
84
|
+
"Space",
|
|
85
|
+
"PageVersion",
|
|
86
|
+
"PageBody",
|
|
87
|
+
"Page",
|
|
88
|
+
"ConfluenceComment",
|
|
89
|
+
"CreatePageRequest",
|
|
90
|
+
"UpdatePageRequest",
|
|
91
|
+
"CreateCommentRequest",
|
|
92
|
+
"SearchConfluenceRequest",
|
|
93
|
+
]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import os
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from atlassian_sdk.exceptions import AuthError
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class BasicAuth:
|
|
12
|
+
"""Immutable container for Atlassian basic-auth credentials."""
|
|
13
|
+
|
|
14
|
+
email: str
|
|
15
|
+
api_token: str
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def header_value(self) -> str:
|
|
19
|
+
"""Return the ``Authorization`` header value (``Basic <b64>``)."""
|
|
20
|
+
raw = f"{self.email}:{self.api_token}".encode()
|
|
21
|
+
encoded = base64.b64encode(raw).decode()
|
|
22
|
+
return f"Basic {encoded}"
|
|
23
|
+
|
|
24
|
+
@classmethod
|
|
25
|
+
def from_env(cls) -> BasicAuth:
|
|
26
|
+
"""Create a :class:`BasicAuth` from environment variables.
|
|
27
|
+
|
|
28
|
+
Reads ``ATLASSIAN_EMAIL`` and ``ATLASSIAN_API_TOKEN``.
|
|
29
|
+
|
|
30
|
+
Raises:
|
|
31
|
+
AuthError: If either variable is missing.
|
|
32
|
+
"""
|
|
33
|
+
email = os.environ.get("ATLASSIAN_EMAIL")
|
|
34
|
+
api_token = os.environ.get("ATLASSIAN_API_TOKEN")
|
|
35
|
+
|
|
36
|
+
missing: list[str] = []
|
|
37
|
+
if not email:
|
|
38
|
+
missing.append("ATLASSIAN_EMAIL")
|
|
39
|
+
if not api_token:
|
|
40
|
+
missing.append("ATLASSIAN_API_TOKEN")
|
|
41
|
+
|
|
42
|
+
if missing:
|
|
43
|
+
raise AuthError(
|
|
44
|
+
f"Missing environment variable(s): {', '.join(missing)}",
|
|
45
|
+
status_code=401,
|
|
46
|
+
response_body="",
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return cls(email=email, api_token=api_token)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from atlassian_sdk.confluence.client import ConfluenceClient
|
|
4
|
+
from atlassian_sdk.confluence.models import (
|
|
5
|
+
ConfluenceComment,
|
|
6
|
+
Page,
|
|
7
|
+
PageBody,
|
|
8
|
+
PageVersion,
|
|
9
|
+
Space,
|
|
10
|
+
)
|
|
11
|
+
from atlassian_sdk.confluence.schemas import (
|
|
12
|
+
CreateCommentRequest,
|
|
13
|
+
CreatePageRequest,
|
|
14
|
+
SearchConfluenceRequest,
|
|
15
|
+
UpdatePageRequest,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"ConfluenceClient",
|
|
20
|
+
"ConfluenceComment",
|
|
21
|
+
"CreateCommentRequest",
|
|
22
|
+
"CreatePageRequest",
|
|
23
|
+
"Page",
|
|
24
|
+
"PageBody",
|
|
25
|
+
"PageVersion",
|
|
26
|
+
"SearchConfluenceRequest",
|
|
27
|
+
"Space",
|
|
28
|
+
"UpdatePageRequest",
|
|
29
|
+
]
|