python-backlog 0.7.4__py3-none-any.whl → 0.7.6__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.
- backlog/attachment.py +6 -4
- backlog/base.py +52 -55
- backlog/issue.py +1 -1
- backlog/project.py +12 -5
- backlog/user.py +4 -4
- backlog/wiki.py +18 -1
- {python_backlog-0.7.4.dist-info → python_backlog-0.7.6.dist-info}/METADATA +18 -3
- python_backlog-0.7.6.dist-info/RECORD +15 -0
- {python_backlog-0.7.4.dist-info → python_backlog-0.7.6.dist-info}/WHEEL +1 -1
- python_backlog-0.7.4.dist-info/RECORD +0 -15
- {python_backlog-0.7.4.dist-info → python_backlog-0.7.6.dist-info/licenses}/LICENSE +0 -0
- {python_backlog-0.7.4.dist-info → python_backlog-0.7.6.dist-info}/top_level.txt +0 -0
backlog/attachment.py
CHANGED
|
@@ -20,10 +20,12 @@ class Attachment(object):
|
|
|
20
20
|
|
|
21
21
|
_uri = "space/attachment"
|
|
22
22
|
_method = "POST"
|
|
23
|
-
|
|
24
|
-
'file': (os.path.basename(filename), open(filename, 'rb'), mimetypes.guess_type(filename))
|
|
25
|
-
}
|
|
23
|
+
_content_type = mimetypes.guess_type(filename)[0] or "application/octet-stream"
|
|
26
24
|
|
|
27
|
-
|
|
25
|
+
with open(filename, 'rb') as f:
|
|
26
|
+
_files = {
|
|
27
|
+
'file': (os.path.basename(filename), f, _content_type)
|
|
28
|
+
}
|
|
29
|
+
resp = self.api.invoke_method(_method, _uri, files=_files)
|
|
28
30
|
|
|
29
31
|
return resp.json()
|
backlog/base.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import re
|
|
4
4
|
import requests
|
|
5
5
|
from backlog.wiki import Wiki
|
|
6
6
|
from backlog.attachment import Attachment
|
|
@@ -13,6 +13,12 @@ from backlog.custom_field import CustomField
|
|
|
13
13
|
|
|
14
14
|
BACKLOG_BASE_URL = "https://{space}.backlog.jp"
|
|
15
15
|
BACKLOG_URI_PREFIX = "/api/v2/"
|
|
16
|
+
BACKLOG_API_KEY_HEADER = "Backlog-API-Key"
|
|
17
|
+
DEFAULT_TIMEOUT = 30
|
|
18
|
+
|
|
19
|
+
# Space keys consist of alphanumerics and hyphens. Validating it prevents the
|
|
20
|
+
# base URL (and therefore the API key) from being pointed at an arbitrary host.
|
|
21
|
+
_SPACE_PATTERN = re.compile(r"^[A-Za-z0-9][A-Za-z0-9-]*$")
|
|
16
22
|
|
|
17
23
|
|
|
18
24
|
class BacklogError(Exception):
|
|
@@ -20,9 +26,18 @@ class BacklogError(Exception):
|
|
|
20
26
|
|
|
21
27
|
|
|
22
28
|
class BaseAPI(object):
|
|
23
|
-
def __init__(self, space, api_key=None):
|
|
29
|
+
def __init__(self, space, api_key=None, timeout=DEFAULT_TIMEOUT):
|
|
30
|
+
"""
|
|
31
|
+
:param space: Backlog space key (the "xxx" of https://xxx.backlog.jp)
|
|
32
|
+
:param api_key: API key. It is sent in the "Backlog-API-Key" request header.
|
|
33
|
+
:param timeout: Default timeout (seconds) passed to the HTTP client.
|
|
34
|
+
Can be overridden per request with the "timeout" keyword argument. None disables it.
|
|
35
|
+
"""
|
|
36
|
+
if not isinstance(space, str) or not _SPACE_PATTERN.match(space):
|
|
37
|
+
raise ValueError("Invalid space key: {!r}".format(space))
|
|
24
38
|
self.space = space
|
|
25
39
|
self.api_key = api_key
|
|
40
|
+
self.timeout = timeout
|
|
26
41
|
self.base_url = BACKLOG_BASE_URL.format(space=space) + BACKLOG_URI_PREFIX
|
|
27
42
|
self.api = None
|
|
28
43
|
self._build_api()
|
|
@@ -30,7 +45,18 @@ class BaseAPI(object):
|
|
|
30
45
|
def _build_api(self):
|
|
31
46
|
self.api = None
|
|
32
47
|
|
|
33
|
-
def
|
|
48
|
+
def _build_headers(self, headers=None):
|
|
49
|
+
"""
|
|
50
|
+
Merge authentication headers into the given headers without mutating it.
|
|
51
|
+
"""
|
|
52
|
+
_headers = {}
|
|
53
|
+
if self.api_key is not None:
|
|
54
|
+
_headers[BACKLOG_API_KEY_HEADER] = self.api_key
|
|
55
|
+
if headers:
|
|
56
|
+
_headers.update(headers)
|
|
57
|
+
return _headers
|
|
58
|
+
|
|
59
|
+
def invoke_method(self, method, uri, query_param=None, request_param=None, headers=None, **kwargs):
|
|
34
60
|
"""
|
|
35
61
|
Delegate requests to get/post/delete method.
|
|
36
62
|
Each method implements by any http client, default client is requests.
|
|
@@ -39,10 +65,14 @@ class BaseAPI(object):
|
|
|
39
65
|
:param uri: API Endpoint. 'uri' expects a URI excluded '/api/v2/' prefix
|
|
40
66
|
:param query_param: dict of URL parameter. this will be url-encoded string
|
|
41
67
|
:param request_param: dict of body parameter. this will use when invoke post request
|
|
42
|
-
:param headers: HTTP Header dict.
|
|
68
|
+
:param headers: HTTP Header dict. Authentication headers are added automatically.
|
|
43
69
|
:return: http response object
|
|
44
70
|
"""
|
|
45
|
-
|
|
71
|
+
# Copy the arguments so that neither the caller's dicts nor any shared state are mutated.
|
|
72
|
+
query_param = dict(query_param or {})
|
|
73
|
+
request_param = dict(request_param or {})
|
|
74
|
+
headers = self._build_headers(headers)
|
|
75
|
+
kwargs.setdefault("timeout", self.timeout)
|
|
46
76
|
|
|
47
77
|
method = method.lower()
|
|
48
78
|
|
|
@@ -100,64 +130,31 @@ class BacklogAPI(BaseAPI):
|
|
|
100
130
|
self.category = Category(self)
|
|
101
131
|
self.custom_field = CustomField(self)
|
|
102
132
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if
|
|
106
|
-
resp = requests.get(_url, params=query_param, headers=headers, **kwargs)
|
|
107
|
-
else:
|
|
108
|
-
resp = requests.get(_url, params=query_param, **kwargs)
|
|
109
|
-
|
|
110
|
-
if resp.status_code // 100 == 2:
|
|
133
|
+
@staticmethod
|
|
134
|
+
def _raise_for_status(resp, ok):
|
|
135
|
+
if ok(resp.status_code):
|
|
111
136
|
return resp
|
|
112
|
-
|
|
113
137
|
raise BacklogError("Http response {status}: {message}".format(status=resp.status_code, message=resp.text))
|
|
114
138
|
|
|
115
|
-
def
|
|
116
|
-
_url = self.base_url + uri
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
else:
|
|
120
|
-
resp = requests.post(_url, data=request_param, **kwargs)
|
|
121
|
-
|
|
122
|
-
if resp.status_code // 100 == 2:
|
|
123
|
-
return resp
|
|
139
|
+
def get(self, method, uri, query_param, request_param, headers, **kwargs):
|
|
140
|
+
_url = self.base_url + uri
|
|
141
|
+
resp = requests.get(_url, params=query_param, headers=headers, **kwargs)
|
|
142
|
+
return self._raise_for_status(resp, lambda code: code // 100 == 2)
|
|
124
143
|
|
|
125
|
-
|
|
144
|
+
def post(self, method, uri, query_param, request_param, headers, **kwargs):
|
|
145
|
+
_url = self.base_url + uri
|
|
146
|
+
resp = requests.post(_url, params=query_param, data=request_param, headers=headers, **kwargs)
|
|
147
|
+
return self._raise_for_status(resp, lambda code: code // 100 == 2)
|
|
126
148
|
|
|
127
149
|
def delete(self, method, uri, query_param, request_param, headers, **kwargs):
|
|
128
|
-
_url = self.base_url + uri
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
else:
|
|
132
|
-
resp = requests.delete(_url, **kwargs)
|
|
133
|
-
|
|
134
|
-
if resp.status_code == 200:
|
|
135
|
-
return resp
|
|
136
|
-
|
|
137
|
-
raise BacklogError("Http response {status}: {message}".format(status=resp.status_code, message=resp.text))
|
|
150
|
+
_url = self.base_url + uri
|
|
151
|
+
resp = requests.delete(_url, params=query_param, data=request_param, headers=headers, **kwargs)
|
|
152
|
+
return self._raise_for_status(resp, lambda code: code // 100 == 2)
|
|
138
153
|
|
|
139
154
|
def patch(self, method, uri, query_param, request_param, headers, **kwargs):
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
:param method:
|
|
144
|
-
:param uri:
|
|
145
|
-
:param query_param:
|
|
146
|
-
:param request_param:
|
|
147
|
-
:param headers:
|
|
148
|
-
:param kwargs:
|
|
149
|
-
:return:
|
|
150
|
-
"""
|
|
151
|
-
_url = self.base_url + uri + "?" + urlencode(query_param)
|
|
152
|
-
if headers is not None:
|
|
153
|
-
resp = requests.ptach(_url, data=request_param, headers=headers, **kwargs)
|
|
154
|
-
else:
|
|
155
|
-
resp = requests.patch(_url, data=request_param, **kwargs)
|
|
156
|
-
|
|
157
|
-
if resp.status_code == 200:
|
|
158
|
-
return resp
|
|
159
|
-
|
|
160
|
-
raise BacklogError("Http response {status}: {message}".format(status=resp.status_code, message=resp.text))
|
|
155
|
+
_url = self.base_url + uri
|
|
156
|
+
resp = requests.patch(_url, params=query_param, data=request_param, headers=headers, **kwargs)
|
|
157
|
+
return self._raise_for_status(resp, lambda code: code // 100 == 2)
|
|
161
158
|
|
|
162
159
|
|
|
163
160
|
class BacklogObject(object):
|
backlog/issue.py
CHANGED
|
@@ -124,7 +124,7 @@ class Issue(object):
|
|
|
124
124
|
if attachmentId is not None:
|
|
125
125
|
_data.update([("attachmentId[]", attachmentId)])
|
|
126
126
|
|
|
127
|
-
resp = self.api.invoke_method(_method, _uri, _data)
|
|
127
|
+
resp = self.api.invoke_method(_method, _uri, request_param=_data)
|
|
128
128
|
|
|
129
129
|
return resp.json()
|
|
130
130
|
|
backlog/project.py
CHANGED
|
@@ -72,6 +72,7 @@ class Project(object):
|
|
|
72
72
|
useOriginalImageSizeAtWiki: Optional[bool] = None,
|
|
73
73
|
textFormattingRule: Optional[TextFormattingRule] = None,
|
|
74
74
|
useDevAttributes: Optional[bool] = None,
|
|
75
|
+
chartEnabled: Optional[bool] = None,
|
|
75
76
|
) -> AddProjectResponse:
|
|
76
77
|
"""Add project
|
|
77
78
|
https://developer.nulab.com/docs/backlog/api/2/add-project/#form-parameters
|
|
@@ -80,8 +81,10 @@ class Project(object):
|
|
|
80
81
|
:type name: str
|
|
81
82
|
:param key: Project Key (Uppercase letters (A-Z), numbers (0-9) and underscore (_) can be used.)
|
|
82
83
|
:type key: str
|
|
83
|
-
:param chatEnabled:
|
|
84
|
+
:param chatEnabled: Deprecated alias of chartEnabled, kept for backward compatibility
|
|
84
85
|
:type chatEnabled: bool
|
|
86
|
+
:param chartEnabled: Enable chart
|
|
87
|
+
:type chartEnabled: bool
|
|
85
88
|
:param useResolvedForChart: Consider Resolved and statuses after as Closed
|
|
86
89
|
:type useResolvedForChart: bool
|
|
87
90
|
:param subtaskingEnabled: Enable subtasking
|
|
@@ -109,10 +112,14 @@ class Project(object):
|
|
|
109
112
|
"""
|
|
110
113
|
_path = "projects"
|
|
111
114
|
_method = "POST"
|
|
115
|
+
if chartEnabled is not None and chatEnabled is not None and chartEnabled != chatEnabled:
|
|
116
|
+
raise ValueError("chartEnabled and its deprecated alias chatEnabled have conflicting values")
|
|
117
|
+
if chartEnabled is None:
|
|
118
|
+
chartEnabled = chatEnabled
|
|
112
119
|
request_param = {
|
|
113
120
|
"name": name,
|
|
114
121
|
"key": key,
|
|
115
|
-
"chartEnabled":
|
|
122
|
+
"chartEnabled": chartEnabled,
|
|
116
123
|
"useResolvedForChart": useResolvedForChart,
|
|
117
124
|
"subtaskingEnabled": subtaskingEnabled,
|
|
118
125
|
"projectLeaderCanEditProjectLeader": projectLeaderCanEditProjectLeader,
|
|
@@ -241,7 +248,7 @@ class Project(object):
|
|
|
241
248
|
_uri = "projects/{project_id_or_key}/users".format(project_id_or_key=projectIdOrKey)
|
|
242
249
|
_method = "GET"
|
|
243
250
|
_query_param = {
|
|
244
|
-
"excludeGroupMembers": "
|
|
251
|
+
"excludeGroupMembers": "true" if excludeGroupMembers else "false"
|
|
245
252
|
}
|
|
246
253
|
|
|
247
254
|
resp = self.api.invoke_method(_method, _uri, query_param=_query_param)
|
|
@@ -361,7 +368,7 @@ class Project(object):
|
|
|
361
368
|
)
|
|
362
369
|
_method = "POST"
|
|
363
370
|
|
|
364
|
-
resp = self.api.invoke_method(_method, _uri)
|
|
371
|
+
resp = self.api.invoke_method(_method, _uri, request_param={"name": name})
|
|
365
372
|
|
|
366
373
|
return resp.json()
|
|
367
374
|
|
|
@@ -380,7 +387,7 @@ class Project(object):
|
|
|
380
387
|
)
|
|
381
388
|
_method = "PATCH"
|
|
382
389
|
|
|
383
|
-
resp = self.api.invoke_method(_method, _uri)
|
|
390
|
+
resp = self.api.invoke_method(_method, _uri, request_param={"name": name})
|
|
384
391
|
|
|
385
392
|
return resp.json()
|
|
386
393
|
|
backlog/user.py
CHANGED
|
@@ -51,7 +51,7 @@ class User(object):
|
|
|
51
51
|
_method = "POST"
|
|
52
52
|
params = dict(
|
|
53
53
|
userId=userId,
|
|
54
|
-
|
|
54
|
+
password=password,
|
|
55
55
|
name=name,
|
|
56
56
|
mailAddress=mailAddress,
|
|
57
57
|
roleType=roleType
|
|
@@ -61,7 +61,7 @@ class User(object):
|
|
|
61
61
|
|
|
62
62
|
return resp.json()
|
|
63
63
|
|
|
64
|
-
def update(self, userId, password, name, mailAddress, roleType):
|
|
64
|
+
def update(self, userId, password=None, name=None, mailAddress=None, roleType=None):
|
|
65
65
|
"""
|
|
66
66
|
https://developer.nulab.com/ja/docs/backlog/api/2/update-user/
|
|
67
67
|
|
|
@@ -75,12 +75,12 @@ class User(object):
|
|
|
75
75
|
_uri = "users/{user_id}".format(user_id=userId)
|
|
76
76
|
_method = "PATCH"
|
|
77
77
|
params = dict(
|
|
78
|
-
|
|
79
|
-
passowrd=password,
|
|
78
|
+
password=password,
|
|
80
79
|
name=name,
|
|
81
80
|
mailAddress=mailAddress,
|
|
82
81
|
roleType=roleType
|
|
83
82
|
)
|
|
83
|
+
params = {k: v for k, v in params.items() if v is not None}
|
|
84
84
|
|
|
85
85
|
resp = self.api.invoke_method(_method, _uri, request_param=params)
|
|
86
86
|
|
backlog/wiki.py
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
|
+
from email.message import Message
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _filename_from_response(resp):
|
|
7
|
+
"""
|
|
8
|
+
Extract the file name from the Content-Disposition header (supports RFC 6266 filename*).
|
|
9
|
+
|
|
10
|
+
:return: file name, or None if the header does not contain one
|
|
11
|
+
"""
|
|
12
|
+
_content_disposition = resp.headers.get("Content-Disposition")
|
|
13
|
+
if not _content_disposition:
|
|
14
|
+
return None
|
|
15
|
+
_message = Message()
|
|
16
|
+
_message["Content-Disposition"] = _content_disposition
|
|
17
|
+
return _message.get_filename()
|
|
18
|
+
|
|
19
|
+
|
|
3
20
|
class Wiki(object):
|
|
4
21
|
def __init__(self, api):
|
|
5
22
|
"""
|
|
@@ -146,7 +163,7 @@ class Wiki(object):
|
|
|
146
163
|
|
|
147
164
|
return {
|
|
148
165
|
"id": attachmentId,
|
|
149
|
-
"name":
|
|
166
|
+
"name": _filename_from_response(resp),
|
|
150
167
|
"data": resp.content
|
|
151
168
|
}
|
|
152
169
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: python-backlog
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.6
|
|
4
4
|
Summary: Backlog API v2 wrapper
|
|
5
5
|
Home-page: https://github.com/hassaku63/pbl
|
|
6
6
|
Author: hassaku63
|
|
@@ -18,7 +18,20 @@ Classifier: Natural Language :: Japanese
|
|
|
18
18
|
Requires-Python: >=3.8
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE
|
|
21
|
-
Requires-Dist: requests
|
|
21
|
+
Requires-Dist: requests~=2.32.2
|
|
22
|
+
Dynamic: author
|
|
23
|
+
Dynamic: author-email
|
|
24
|
+
Dynamic: classifier
|
|
25
|
+
Dynamic: description
|
|
26
|
+
Dynamic: description-content-type
|
|
27
|
+
Dynamic: home-page
|
|
28
|
+
Dynamic: keywords
|
|
29
|
+
Dynamic: license
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
Dynamic: project-url
|
|
32
|
+
Dynamic: requires-dist
|
|
33
|
+
Dynamic: requires-python
|
|
34
|
+
Dynamic: summary
|
|
22
35
|
|
|
23
36
|
# pbl
|
|
24
37
|
|
|
@@ -44,6 +57,8 @@ def main():
|
|
|
44
57
|
"""
|
|
45
58
|
Initialize API Object
|
|
46
59
|
"""
|
|
60
|
+
# The API key is sent in the "Backlog-API-Key" request header.
|
|
61
|
+
# Requests time out after 30 seconds by default (configurable with `timeout=`).
|
|
47
62
|
api = BacklogAPI("your-space", "your-api-key")
|
|
48
63
|
|
|
49
64
|
"""
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
backlog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
backlog/attachment.py,sha256=_Ex_ob7NC0ZMrt_5OM3MqLzIQrswx8SceKhOYNY5Wgs,872
|
|
3
|
+
backlog/base.py,sha256=CnZ0LLGcHb8yJm6v4gXmVUcki_M1U3Wv8kNgZgyLGoc,6120
|
|
4
|
+
backlog/category.py,sha256=DQ06yhOCXxtDbPMZ1Ig1QD8n7Ht_ZFrp8PJzO18IeZk,2530
|
|
5
|
+
backlog/custom_field.py,sha256=dJ-XnrYv0rlpLvPhIkZEgcyNjZB8GR3352Or8HUPKlc,12243
|
|
6
|
+
backlog/git.py,sha256=mazfvwn1Ekga0eeigk22Xf3vhXEo-P5Irfyq6r_QbaA,3056
|
|
7
|
+
backlog/issue.py,sha256=E7bhNLLQd1KkSEilGcrmKYlkfi_w8rVfRF6xI-PGEtc,6650
|
|
8
|
+
backlog/project.py,sha256=SCNbxjpzKwK5eijN58su9jHnBnIT8XcLqU8kv_vuE3s,14348
|
|
9
|
+
backlog/user.py,sha256=kSEkInekQ8aGgYs5ygCdA5tsUYK3cxO9_Aay-sfaC2A,2890
|
|
10
|
+
backlog/wiki.py,sha256=ThfWC-OlnHDHMYeARYJega92fd3QhZ817mhWF1OegT4,5943
|
|
11
|
+
python_backlog-0.7.6.dist-info/licenses/LICENSE,sha256=1teWq4411yGkUz_9lD1V74mcHFRix2IqOAoFaghKYwo,1073
|
|
12
|
+
python_backlog-0.7.6.dist-info/METADATA,sha256=zQYcB_HEpAJsShHe0HjN1GjWMWay4WlfCv_fxc7n9a0,2591
|
|
13
|
+
python_backlog-0.7.6.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
14
|
+
python_backlog-0.7.6.dist-info/top_level.txt,sha256=qzHRU2P6F24ntkXGiIBl4Qf_AlV0BRebSc5tuLlcOIE,8
|
|
15
|
+
python_backlog-0.7.6.dist-info/RECORD,,
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
backlog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
backlog/attachment.py,sha256=RpaAcTnr_2CsJUDeeJHT1YSH0TwPImH5C0uwUOpDlHs,764
|
|
3
|
-
backlog/base.py,sha256=-EUjAZr20vq3i8ekPe9LwbGvwJZ6PGhGCV8TsqZqIrs,5632
|
|
4
|
-
backlog/category.py,sha256=DQ06yhOCXxtDbPMZ1Ig1QD8n7Ht_ZFrp8PJzO18IeZk,2530
|
|
5
|
-
backlog/custom_field.py,sha256=dJ-XnrYv0rlpLvPhIkZEgcyNjZB8GR3352Or8HUPKlc,12243
|
|
6
|
-
backlog/git.py,sha256=mazfvwn1Ekga0eeigk22Xf3vhXEo-P5Irfyq6r_QbaA,3056
|
|
7
|
-
backlog/issue.py,sha256=of0DQ_1fsBPJ2aU6TS7IWlw0DzZIJRzo4fCGuKv2JY8,6636
|
|
8
|
-
backlog/project.py,sha256=TOBDLV6eSpeQRxcjZ1ArrEE8lHRE7JIyaCJUQALSdSg,13839
|
|
9
|
-
backlog/user.py,sha256=fgd1X1fom1mTPKDU6DFqBspPauq6UuhxrbFd9CCrptU,2829
|
|
10
|
-
backlog/wiki.py,sha256=NjMkHopNb-9oic1yziiypzzpIHSdXcRfePZhOBKtDok,5431
|
|
11
|
-
python_backlog-0.7.4.dist-info/LICENSE,sha256=1teWq4411yGkUz_9lD1V74mcHFRix2IqOAoFaghKYwo,1073
|
|
12
|
-
python_backlog-0.7.4.dist-info/METADATA,sha256=mo6ZGBZstyo9QaRCpGCKbP8Nff3Mo0Nci7-rVaERduw,2166
|
|
13
|
-
python_backlog-0.7.4.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
14
|
-
python_backlog-0.7.4.dist-info/top_level.txt,sha256=qzHRU2P6F24ntkXGiIBl4Qf_AlV0BRebSc5tuLlcOIE,8
|
|
15
|
-
python_backlog-0.7.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|