suite-py 1.41.3__py3-none-any.whl → 1.41.4__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.
- suite_py/__version__.py +1 -1
- suite_py/cli.py +60 -192
- suite_py/commands/aggregator.py +3 -5
- suite_py/commands/ask_review.py +3 -5
- suite_py/commands/batch_job.py +1 -2
- suite_py/commands/bump.py +1 -2
- suite_py/commands/check.py +3 -5
- suite_py/commands/context.py +26 -0
- suite_py/commands/create_branch.py +1 -2
- suite_py/commands/deploy.py +3 -5
- suite_py/commands/docker.py +1 -2
- suite_py/commands/generator.py +1 -2
- suite_py/commands/id.py +1 -2
- suite_py/commands/ip.py +1 -2
- suite_py/commands/login.py +4 -173
- suite_py/commands/merge_pr.py +3 -4
- suite_py/commands/open_pr.py +4 -5
- suite_py/commands/project_lock.py +3 -5
- suite_py/commands/release.py +3 -5
- suite_py/commands/secret.py +1 -2
- suite_py/commands/set_token.py +1 -2
- suite_py/commands/status.py +3 -4
- suite_py/lib/handler/captainhook_handler.py +16 -9
- suite_py/lib/handler/metrics_handler.py +8 -6
- suite_py/lib/handler/okta_handler.py +81 -0
- suite_py/lib/logger.py +1 -0
- suite_py/lib/metrics.py +4 -2
- suite_py/lib/oauth.py +156 -0
- suite_py/lib/tokens.py +4 -0
- {suite_py-1.41.3.dist-info → suite_py-1.41.4.dist-info}/METADATA +2 -4
- suite_py-1.41.4.dist-info/RECORD +54 -0
- suite_py/commands/qa.py +0 -424
- suite_py/lib/handler/qainit_handler.py +0 -259
- suite_py-1.41.3.dist-info/RECORD +0 -53
- /suite_py/{commands/templates → templates}/login.html +0 -0
- {suite_py-1.41.3.dist-info → suite_py-1.41.4.dist-info}/WHEEL +0 -0
- {suite_py-1.41.3.dist-info → suite_py-1.41.4.dist-info}/entry_points.txt +0 -0
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
|
2
|
-
import json
|
|
3
|
-
import sys
|
|
4
|
-
|
|
5
|
-
import requests
|
|
6
|
-
from github.GithubException import UnknownObjectException
|
|
7
|
-
from halo import Halo
|
|
8
|
-
|
|
9
|
-
from suite_py.lib import logger
|
|
10
|
-
from suite_py.lib.handler import prompt_utils
|
|
11
|
-
from suite_py.lib.handler.git_handler import GitHandler
|
|
12
|
-
from suite_py.lib.handler.github_handler import GithubHandler
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class QainitHandler:
|
|
16
|
-
|
|
17
|
-
scope_mapping = {
|
|
18
|
-
"admin": [
|
|
19
|
-
"update:user-quota",
|
|
20
|
-
"delete:others-qa",
|
|
21
|
-
"create:qa",
|
|
22
|
-
"delete:qa",
|
|
23
|
-
"describe:qa",
|
|
24
|
-
"describe:others-qa",
|
|
25
|
-
"update:qa",
|
|
26
|
-
"update:others-qa",
|
|
27
|
-
"list:qa",
|
|
28
|
-
"list:others-qa",
|
|
29
|
-
"access:captainhook",
|
|
30
|
-
],
|
|
31
|
-
"dev": [
|
|
32
|
-
"create:qa",
|
|
33
|
-
"delete:qa",
|
|
34
|
-
"describe:qa",
|
|
35
|
-
"describe:others-qa",
|
|
36
|
-
"update:qa",
|
|
37
|
-
"update:others-qa",
|
|
38
|
-
"list:qa",
|
|
39
|
-
"list:others-qa",
|
|
40
|
-
"access:captainhook",
|
|
41
|
-
],
|
|
42
|
-
"external": ["create:qa", "delete:qa", "describe:qa", "list:qa", "update:qa"],
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
def __init__(self, project, config, tokens):
|
|
46
|
-
self._project = project
|
|
47
|
-
self._token = tokens.drone
|
|
48
|
-
self._config = config
|
|
49
|
-
self.url = self._config.qainit["url"]
|
|
50
|
-
self.okta_tenant = self._config.okta["tenant"]
|
|
51
|
-
self.okta_token = self._config.get_cache(f"{self.okta_tenant}_okta_token")
|
|
52
|
-
self._github = GithubHandler(tokens)
|
|
53
|
-
self._git = GitHandler(project, config)
|
|
54
|
-
|
|
55
|
-
if "url" not in config.qainit:
|
|
56
|
-
self.usage()
|
|
57
|
-
sys.exit(-1)
|
|
58
|
-
|
|
59
|
-
def usage(self):
|
|
60
|
-
logger.warning(
|
|
61
|
-
"Unable to use QA commands: missing qainit config in ~/.suite_py/config.yml"
|
|
62
|
-
)
|
|
63
|
-
logger.warning(
|
|
64
|
-
"Update your config.yml as: https://github.com/primait/suite_py/blob/master/.config.yml.dist"
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
def user_info(self):
|
|
68
|
-
r = self._execute("GET", "/api/v1/user")
|
|
69
|
-
|
|
70
|
-
if r.status_code == 401:
|
|
71
|
-
return None
|
|
72
|
-
|
|
73
|
-
logger.debug(json.dumps(r.json(), indent=2))
|
|
74
|
-
|
|
75
|
-
return r.json()
|
|
76
|
-
|
|
77
|
-
def update_user_quota(self, username, quota):
|
|
78
|
-
body = {"github_username": f"{username}", "quota": f"{quota}"}
|
|
79
|
-
logger.debug(json.dumps(body))
|
|
80
|
-
r = self._execute(
|
|
81
|
-
"POST",
|
|
82
|
-
"/api/v1/user/quota",
|
|
83
|
-
body=json.dumps(body),
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
logger.info("Quota updated.")
|
|
87
|
-
logger.debug(json.dumps(r.json(), indent=2))
|
|
88
|
-
|
|
89
|
-
def create(self, name, card, services):
|
|
90
|
-
srv_list = self.create_services_body(services)
|
|
91
|
-
body = {"name": name, "card": card, "services": srv_list}
|
|
92
|
-
|
|
93
|
-
logger.debug(json.dumps(body))
|
|
94
|
-
r = self._execute(
|
|
95
|
-
"POST",
|
|
96
|
-
"/api/v1/qa",
|
|
97
|
-
body=json.dumps(body),
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
logger.info(f"QA creation initiated. Your namespace hash: {r.json()['hash']}")
|
|
101
|
-
logger.debug(json.dumps(r.json(), indent=2))
|
|
102
|
-
|
|
103
|
-
def update(self, qa_hash, services):
|
|
104
|
-
srv_list = self.create_services_body(services)
|
|
105
|
-
|
|
106
|
-
body = {"services": srv_list}
|
|
107
|
-
logger.debug(json.dumps(body))
|
|
108
|
-
|
|
109
|
-
r = self._execute(
|
|
110
|
-
"PUT",
|
|
111
|
-
f"/api/v1/qa/{qa_hash}",
|
|
112
|
-
body=json.dumps(body),
|
|
113
|
-
)
|
|
114
|
-
self.handle_call_result(r, "update", qa_hash)
|
|
115
|
-
|
|
116
|
-
def list(self, params, page=1, page_size=10):
|
|
117
|
-
filters = []
|
|
118
|
-
status_values = '"created","creating","updated","updating","failed","frozen","freezing","unfreezing"'
|
|
119
|
-
if len(params["status"]) > 0:
|
|
120
|
-
status_values = ",".join([f'"{status}"' for status in params["status"]])
|
|
121
|
-
filters.append(f"status=[{status_values}]")
|
|
122
|
-
|
|
123
|
-
if params["user"] is not None:
|
|
124
|
-
filters.append(f"user={params['user']}")
|
|
125
|
-
|
|
126
|
-
if params["card"] is not None:
|
|
127
|
-
filters.append(f"card={params['card']}")
|
|
128
|
-
|
|
129
|
-
filters_string = "&".join(filters)
|
|
130
|
-
|
|
131
|
-
return self._execute(
|
|
132
|
-
"GET",
|
|
133
|
-
f"/api/v1/qa?{filters_string}&page_size={page_size}&page={page}",
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
def delete(self, qa_hash, force=False):
|
|
137
|
-
r = self._execute(
|
|
138
|
-
"DELETE",
|
|
139
|
-
f"/api/v1/qa/{qa_hash}",
|
|
140
|
-
)
|
|
141
|
-
logger.debug(json.dumps(r.json(), indent=2))
|
|
142
|
-
if r.ok:
|
|
143
|
-
logger.info(f"QA {qa_hash} deletion initiated")
|
|
144
|
-
else:
|
|
145
|
-
logger.error(
|
|
146
|
-
f"QA {qa_hash} deletion has failed{', try running this command with --force flag' if not force else ''}."
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
def describe(self, qa_hash):
|
|
150
|
-
r = self._execute(
|
|
151
|
-
"GET",
|
|
152
|
-
f"/api/v1/qa/{qa_hash}",
|
|
153
|
-
).json()
|
|
154
|
-
logger.debug(json.dumps(r, indent=2))
|
|
155
|
-
|
|
156
|
-
return r
|
|
157
|
-
|
|
158
|
-
def create_services_body(self, prj_list):
|
|
159
|
-
srv_list = []
|
|
160
|
-
ref = self._git.current_branch_name()
|
|
161
|
-
for prj in prj_list:
|
|
162
|
-
with Halo(text="Loading branches...", spinner="dots", color="magenta"):
|
|
163
|
-
choices = [
|
|
164
|
-
{"name": branch.name, "value": branch.name}
|
|
165
|
-
for branch in self._github.get_branches(prj)
|
|
166
|
-
]
|
|
167
|
-
if choices:
|
|
168
|
-
choices.sort(key=lambda x: x["name"])
|
|
169
|
-
ref = prompt_utils.ask_choices(
|
|
170
|
-
f"Select branch for project - {prj}: ", choices, default_text=ref
|
|
171
|
-
)
|
|
172
|
-
try:
|
|
173
|
-
self._github.get_raw_content(prj, ref, ".service.yml")
|
|
174
|
-
except UnknownObjectException:
|
|
175
|
-
logger.error(
|
|
176
|
-
f".service.yml missing for project: {prj}, can't add microservice to QA"
|
|
177
|
-
)
|
|
178
|
-
sys.exit(-1)
|
|
179
|
-
srv_list.append(
|
|
180
|
-
{
|
|
181
|
-
"name": prj,
|
|
182
|
-
"ref": ref,
|
|
183
|
-
}
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
return srv_list
|
|
187
|
-
|
|
188
|
-
def freeze(self, qa_hash):
|
|
189
|
-
body = {"operation": "freeze"}
|
|
190
|
-
logger.debug(json.dumps(body))
|
|
191
|
-
r = self._execute("PUT", f"/api/v1/qa/{qa_hash}", body=json.dumps(body))
|
|
192
|
-
self.handle_call_result(r, "freezing", qa_hash)
|
|
193
|
-
|
|
194
|
-
def unfreeze(self, qa_hash):
|
|
195
|
-
body = {"operation": "unfreeze"}
|
|
196
|
-
logger.debug(json.dumps(body))
|
|
197
|
-
r = self._execute("PUT", f"/api/v1/qa/{qa_hash}", body=json.dumps(body))
|
|
198
|
-
self.handle_call_result(r, "unfreezing", qa_hash)
|
|
199
|
-
|
|
200
|
-
def maintenance(self):
|
|
201
|
-
r = self._execute("POST", "/api/v1/maintenance")
|
|
202
|
-
if r.json()["success"]:
|
|
203
|
-
maintenance = r.json()["maintenance"]
|
|
204
|
-
logger.info(
|
|
205
|
-
f"Maintenance mode is now {'enabled' if maintenance else 'disabled'}"
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
logger.debug(json.dumps(r.json(), indent=2))
|
|
209
|
-
|
|
210
|
-
def force_update(self, qa_hash):
|
|
211
|
-
r = self._execute("POST", f"/api/v1/qa/shit-shoveler/force-update/{qa_hash}")
|
|
212
|
-
if r.status_code == 400:
|
|
213
|
-
msg = r.json()["message"]
|
|
214
|
-
if msg == "instance_not_force_updated":
|
|
215
|
-
logger.error("Failed to force update QA.")
|
|
216
|
-
return False
|
|
217
|
-
if msg == "not_in_stale_state":
|
|
218
|
-
logger.warning("QA is not in a stale state.")
|
|
219
|
-
return True
|
|
220
|
-
raise ValueError(
|
|
221
|
-
"Unexpected return type from qa init shit-shoveler endpoint."
|
|
222
|
-
)
|
|
223
|
-
if r.status_code == 500:
|
|
224
|
-
logger.error("Something went wrong")
|
|
225
|
-
return False
|
|
226
|
-
logger.info("QA has been forced to update")
|
|
227
|
-
logger.debug(json.dumps(r.json(), indent=2))
|
|
228
|
-
return True
|
|
229
|
-
|
|
230
|
-
def _execute(self, request_method, api_endpoint, body=None):
|
|
231
|
-
api_url = self.url + api_endpoint
|
|
232
|
-
okta_token = self._config.get_cache(f"{self.okta_tenant}_okta_token")
|
|
233
|
-
|
|
234
|
-
headers = {
|
|
235
|
-
"Content-Type": "application/json",
|
|
236
|
-
"Authorization": f"Bearer {okta_token}",
|
|
237
|
-
}
|
|
238
|
-
logger.debug(request_method)
|
|
239
|
-
logger.debug(api_url)
|
|
240
|
-
logger.debug(headers)
|
|
241
|
-
logger.debug(body)
|
|
242
|
-
# pylint: disable-next=missing-timeout
|
|
243
|
-
r = requests.request(request_method, api_url, headers=headers, data=body)
|
|
244
|
-
|
|
245
|
-
if r.ok:
|
|
246
|
-
logger.debug("Call to qainit-evo executed successfully")
|
|
247
|
-
else:
|
|
248
|
-
logger.error("Some issue during call to qainit-evo: ")
|
|
249
|
-
logger.error(f"Status code: {r.status_code}, response: {r.text}")
|
|
250
|
-
logger.debug(api_endpoint)
|
|
251
|
-
|
|
252
|
-
return r
|
|
253
|
-
|
|
254
|
-
def handle_call_result(self, req, operation, qa_hash):
|
|
255
|
-
if req.ok:
|
|
256
|
-
logger.info(f"QA {operation} initiated")
|
|
257
|
-
else:
|
|
258
|
-
logger.debug(json.dumps(req.json(), indent=2))
|
|
259
|
-
logger.info(f"Run suite-py qa describe {qa_hash} to check the status")
|
suite_py-1.41.3.dist-info/RECORD
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
suite_py/__init__.py,sha256=REmi3D0X2G1ZWnYpKs8Ffm3NIj-Hw6dMuvz2b9NW344,142
|
|
2
|
-
suite_py/__version__.py,sha256=ErvX9hHDekczivYu3uXp5wDAoVhpd94tE5QF6bHx_Bk,49
|
|
3
|
-
suite_py/cli.py,sha256=0N1N2u_9p4x1hB_cuWXEaN7WGooSr4XnxQYHvxmldvk,18699
|
|
4
|
-
suite_py/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
suite_py/commands/aggregator.py,sha256=2bPjtg0p_2oBLR5-wzy0borjiNSv93rsiirgRFqSXUg,5839
|
|
6
|
-
suite_py/commands/ask_review.py,sha256=Bc3Nf2ZtK0E0gf8ub_I-oCWQQloNnAaUbbbQvB8oHcE,3872
|
|
7
|
-
suite_py/commands/batch_job.py,sha256=zqF7aPM_tzPAHmq1kyLaMd1Md7NTcMXDFQwKfqhjqqI,7474
|
|
8
|
-
suite_py/commands/bump.py,sha256=E-WbS5wsqVwjF-58RZRkwaZuaVEDiNxYLkqAApKpXos,5430
|
|
9
|
-
suite_py/commands/check.py,sha256=Lz1j6a-x42NQOYlkaVVwGCLYNKsDG36t5CYzuXgVaWk,4158
|
|
10
|
-
suite_py/commands/common.py,sha256=aWCEvO3hqdheuMUmZcHuc9EGZPQTk7VkzkHJk283MxQ,566
|
|
11
|
-
suite_py/commands/create_branch.py,sha256=NTXWPEembys8g_CFx_0TWy4KnEFXOEEI2SJdF41O3Oc,4448
|
|
12
|
-
suite_py/commands/deploy.py,sha256=ma33WxyHBjpR0k9lwdM7tM90L3mzBgNrpYlpJxD0ppE,8172
|
|
13
|
-
suite_py/commands/docker.py,sha256=J7pyOSD0B0doPjMeqJKxClwOL6GQ8lDcTh_hG7_vrqU,2956
|
|
14
|
-
suite_py/commands/generator.py,sha256=1ysn75QxpiwjVuJaO-EcvUm751kGVKx3zQvt7EJEuXs,8534
|
|
15
|
-
suite_py/commands/id.py,sha256=u66ALNOZy3cv3CJnbmTOv1J2tbjWBh97XGV5JUzyHC4,2022
|
|
16
|
-
suite_py/commands/ip.py,sha256=KV4asKVwU1q4_64Y490jLP01RYjqkAk4euz4VZ3Ko6w,2420
|
|
17
|
-
suite_py/commands/login.py,sha256=FW-Q5FJfPcrGxynUE7X74tzZF-Pvo-ZdNxcNbqwqxqM,6039
|
|
18
|
-
suite_py/commands/merge_pr.py,sha256=BsHXW_t165f73wcwt__M-FtlTO1AetWAjcSrabXMCpA,5697
|
|
19
|
-
suite_py/commands/open_pr.py,sha256=gNT3XuLNrjhiaLHX3Vw50XfIx7HT1wqFU_cBmLU17ow,7220
|
|
20
|
-
suite_py/commands/project_lock.py,sha256=Lck7UMuZQY0DWPSotufsxuhglrlOfxluNjE1DnwkVhE,2024
|
|
21
|
-
suite_py/commands/qa.py,sha256=TQxu7HE6ryr_zpXb3bXcOXFHv5HrLRCKXtw8SzsEN1A,16251
|
|
22
|
-
suite_py/commands/release.py,sha256=dfXV0FL28AMsLJXamGN2BpqnZxOAturSGyMl3TJTttY,16718
|
|
23
|
-
suite_py/commands/secret.py,sha256=K8VxC5tL-_64TxiDrYlSUfwZB2eDzKaaRutr3YWhQq4,8019
|
|
24
|
-
suite_py/commands/set_token.py,sha256=2DYdJUtpvrcdlGZLUfZcMvTFDDtATE0gLgy4P5Hgti0,1532
|
|
25
|
-
suite_py/commands/status.py,sha256=ph3_vdnyoa6L4Zv_pL5LxR6glnac8sJ3ow76D9nhsH4,1136
|
|
26
|
-
suite_py/commands/templates/login.html,sha256=fJLls2SB84oZTSrxTdA5q1PqfvIHcCD4fhVWfyco7Ig,861
|
|
27
|
-
suite_py/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
suite_py/lib/config.py,sha256=4uKXAav8E-VXlXGPnkYQ_fZYyi6058S0FM2JmyV8L2k,3970
|
|
29
|
-
suite_py/lib/handler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
-
suite_py/lib/handler/aws_handler.py,sha256=dRvRDicikfRbuFtCLPbevaX-yC-fO4LwXFdyqLPJ8OI,8815
|
|
31
|
-
suite_py/lib/handler/captainhook_handler.py,sha256=X6q3VVMFhpexIOqy6xU6pRVpQD4HLsoJOYDW2LeUVk4,3121
|
|
32
|
-
suite_py/lib/handler/changelog_handler.py,sha256=-ppnRl3smBA_ys8tPqXmytS4eyntlwfawC2fiXFcwlw,4818
|
|
33
|
-
suite_py/lib/handler/drone_handler.py,sha256=rmtzu30OQyG3vRPlbZKsQhHN9zbguPtXO0RpDjYOTPA,8967
|
|
34
|
-
suite_py/lib/handler/frequent_reviewers_handler.py,sha256=EIJX5FEMWzrxuXS9A17hu1vfxgJSOHSBX_ahCEZ2FVA,2185
|
|
35
|
-
suite_py/lib/handler/git_handler.py,sha256=boxhl9lQz6fjEJ10ib1KrDW-geCVjhA_6nKwv2ll01g,11333
|
|
36
|
-
suite_py/lib/handler/github_handler.py,sha256=AnFL54yOZ5GDIU91wQat4s-d1WTcmg_B_5M7-Rop3wA,2900
|
|
37
|
-
suite_py/lib/handler/metrics_handler.py,sha256=j8ajrLJLcT_DgrikwaGHA6EWQTqD3tcyIrdwvz9PWuw,2992
|
|
38
|
-
suite_py/lib/handler/prompt_utils.py,sha256=vgk1O7h-iYEAZv1sXtMh8xIgH1djI398rzxRIgZWZcg,2474
|
|
39
|
-
suite_py/lib/handler/qainit_handler.py,sha256=F1sDQ7ktvSkQ73xH7DlZO3J728BSGQ8l5pJabniQniw,8632
|
|
40
|
-
suite_py/lib/handler/vault_handler.py,sha256=r4osw7qwz3ZFmLg2U1oFPdtRFcXzDXiaWBZC01cYK_w,871
|
|
41
|
-
suite_py/lib/handler/version_handler.py,sha256=DXTx4yCAbFVC6CdMqPJ-LiN5YM-dT2zklG8POyKTP5A,6774
|
|
42
|
-
suite_py/lib/handler/youtrack_handler.py,sha256=eTGBBXjlN_ay1cawtnZ2IG6l78dDyKdMN1x6PxcvtA0,7499
|
|
43
|
-
suite_py/lib/logger.py,sha256=cs0XH4pwP3IOjvsOpoY9DEDKsn4p3LwKmvfW-NEoL4U,781
|
|
44
|
-
suite_py/lib/metrics.py,sha256=HpLki7K2thKa_zrU3oe942EdYSKWuU43rtag1YVQ1QQ,1502
|
|
45
|
-
suite_py/lib/requests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
|
-
suite_py/lib/requests/auth.py,sha256=wN_WtGFmDUWRFilWzOmUaRBvP2n3EPpPMqex9Zjddko,228
|
|
47
|
-
suite_py/lib/requests/session.py,sha256=P32H3cWnCWunu91WIj2iDM5U3HzaBglg60VN_C9JBL4,267
|
|
48
|
-
suite_py/lib/symbol.py,sha256=z3QYBuNIwD3qQ3zF-cLOomIr_-C3bO_u5UIDAHMiyTo,60
|
|
49
|
-
suite_py/lib/tokens.py,sha256=BPmNEP8-YGwyE6EK4vBgLwc-AU3wwqpsM2a1xJYtz7g,5449
|
|
50
|
-
suite_py-1.41.3.dist-info/METADATA,sha256=CJuhC_3eGJLwHO4znm7i0bBbPX0aKmfx3PhNRVL-l9w,1596
|
|
51
|
-
suite_py-1.41.3.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
52
|
-
suite_py-1.41.3.dist-info/entry_points.txt,sha256=dVKLC-9Infy-dHJT_MkK6LcDjOgBCJ8lfPkURJhBjxE,46
|
|
53
|
-
suite_py-1.41.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|