sunholo 0.60.7__py3-none-any.whl → 0.60.9__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.
- sunholo/agents/flask/qna_routes.py +6 -1
- sunholo/cli/chat_vac.py +2 -2
- sunholo/cli/cli.py +8 -1
- sunholo/cli/run_proxy.py +117 -33
- sunholo/database/lancedb.py +1 -1
- {sunholo-0.60.7.dist-info → sunholo-0.60.9.dist-info}/METADATA +2 -2
- {sunholo-0.60.7.dist-info → sunholo-0.60.9.dist-info}/RECORD +11 -11
- {sunholo-0.60.7.dist-info → sunholo-0.60.9.dist-info}/LICENSE.txt +0 -0
- {sunholo-0.60.7.dist-info → sunholo-0.60.9.dist-info}/WHEEL +0 -0
- {sunholo-0.60.7.dist-info → sunholo-0.60.9.dist-info}/entry_points.txt +0 -0
- {sunholo-0.60.7.dist-info → sunholo-0.60.9.dist-info}/top_level.txt +0 -0
|
@@ -41,9 +41,14 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
|
41
41
|
def home():
|
|
42
42
|
return jsonify("OK")
|
|
43
43
|
|
|
44
|
+
@app.route("/health")
|
|
45
|
+
def health():
|
|
46
|
+
return jsonify({"status": "healthy"})
|
|
47
|
+
|
|
44
48
|
@app.route('/vac/streaming/<vector_name>', methods=['POST'])
|
|
45
49
|
@observe()
|
|
46
50
|
def stream_qa(vector_name):
|
|
51
|
+
observed_stream_interpreter = observe()(stream_interpreter)
|
|
47
52
|
prep = prep_vac(request, vector_name)
|
|
48
53
|
log.debug(f"Processing prep: {prep}")
|
|
49
54
|
trace = prep["trace"]
|
|
@@ -69,7 +74,7 @@ def register_qna_routes(app, stream_interpreter, vac_interpreter):
|
|
|
69
74
|
|
|
70
75
|
for chunk in start_streaming_chat(question=all_input["user_input"],
|
|
71
76
|
vector_name=vector_name,
|
|
72
|
-
qna_func=
|
|
77
|
+
qna_func=observed_stream_interpreter,
|
|
73
78
|
chat_history=all_input["chat_history"],
|
|
74
79
|
wait_time=all_input["stream_wait_time"],
|
|
75
80
|
timeout=all_input["stream_timeout"],
|
sunholo/cli/chat_vac.py
CHANGED
|
@@ -186,7 +186,7 @@ def vac_command(args):
|
|
|
186
186
|
|
|
187
187
|
stream_chat_session(service_url, args.vac_name)
|
|
188
188
|
|
|
189
|
-
stop_proxy(agent_name)
|
|
189
|
+
stop_proxy(agent_name, stop_local=False)
|
|
190
190
|
|
|
191
191
|
|
|
192
192
|
def list_cloud_run_services(project, region):
|
|
@@ -296,6 +296,6 @@ def setup_vac_subparser(subparsers):
|
|
|
296
296
|
chat_parser.add_argument('user_input', help='User input for the VAC service when in headless mode.', nargs='?', default=None)
|
|
297
297
|
chat_parser.add_argument('--headless', action='store_true', help='Run in headless mode.')
|
|
298
298
|
chat_parser.add_argument('--chat_history', help='Chat history for headless mode (as JSON string).', default=None)
|
|
299
|
-
chat_parser.add_argument('--
|
|
299
|
+
chat_parser.add_argument('--no-proxy', action='store_true', help='Do not use the proxy and connect directly to the VAC service.')
|
|
300
300
|
|
|
301
301
|
vac_parser.set_defaults(func=vac_command)
|
sunholo/cli/cli.py
CHANGED
|
@@ -11,10 +11,17 @@ from ..utils.config import load_config_key
|
|
|
11
11
|
|
|
12
12
|
from ..logging import log
|
|
13
13
|
|
|
14
|
+
from .sun_rich import console
|
|
15
|
+
import sys
|
|
14
16
|
|
|
15
17
|
|
|
16
18
|
def load_default_gcp_config():
|
|
17
|
-
|
|
19
|
+
try:
|
|
20
|
+
gcp_config = load_config_key('gcp_config', 'global', kind="vacConfig")
|
|
21
|
+
except FileNotFoundError as e:
|
|
22
|
+
console.print(f"{e} - move config/ folder to working directory or set the _CONFIG_FOLDER environment variable to its location")
|
|
23
|
+
sys.exit(1)
|
|
24
|
+
|
|
18
25
|
if gcp_config:
|
|
19
26
|
return gcp_config.get('project_id', ''), gcp_config.get('location', 'europe-west1')
|
|
20
27
|
else:
|
sunholo/cli/run_proxy.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import subprocess
|
|
2
2
|
import os
|
|
3
|
+
import sys
|
|
3
4
|
import signal
|
|
4
5
|
import json
|
|
5
6
|
|
|
@@ -96,7 +97,7 @@ def save_proxies(proxies):
|
|
|
96
97
|
|
|
97
98
|
|
|
98
99
|
|
|
99
|
-
def start_proxy(service_name, region, project, port=None):
|
|
100
|
+
def start_proxy(service_name, region, project, port=None, local=False, app_type=None, app_folder=None, log_file=None):
|
|
100
101
|
"""
|
|
101
102
|
Starts the gcloud proxy to the Cloud Run service and stores the PID.
|
|
102
103
|
|
|
@@ -114,34 +115,48 @@ def start_proxy(service_name, region, project, port=None):
|
|
|
114
115
|
|
|
115
116
|
if not port:
|
|
116
117
|
port = get_next_available_port(proxies, DEFAULT_PORT)
|
|
117
|
-
|
|
118
|
-
command = [
|
|
119
|
-
"gcloud", "run", "services", "proxy", service_name,
|
|
120
|
-
"--region", region,
|
|
121
|
-
"--project", project,
|
|
122
|
-
"--port", str(port)
|
|
123
|
-
]
|
|
124
|
-
with open(os.devnull, 'w') as devnull:
|
|
125
|
-
process = subprocess.Popen(command, stdout=devnull, stderr=devnull, preexec_fn=os.setpgrp)
|
|
126
|
-
|
|
127
|
-
proxies[service_name] = {
|
|
128
|
-
"pid": process.pid,
|
|
129
|
-
"port": port
|
|
130
|
-
}
|
|
131
|
-
save_proxies(proxies)
|
|
132
118
|
|
|
133
|
-
|
|
134
|
-
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
if local:
|
|
122
|
+
start_local(service_name, port, app_type, app_folder, log_file)
|
|
123
|
+
else:
|
|
124
|
+
command = [
|
|
125
|
+
"gcloud", "run", "services", "proxy", service_name,
|
|
126
|
+
"--region", region,
|
|
127
|
+
"--project", project,
|
|
128
|
+
"--port", str(port)
|
|
129
|
+
]
|
|
130
|
+
if log_file:
|
|
131
|
+
log_file_path = os.path.join(app_folder, f"{service_name}_log.txt")
|
|
132
|
+
with open(log_file_path, 'a') as logf:
|
|
133
|
+
process = subprocess.Popen(command, stdout=logf, stderr=logf, preexec_fn=os.setpgrp)
|
|
134
|
+
else:
|
|
135
|
+
log_file_path = "No log file specified"
|
|
136
|
+
with open(os.devnull, 'w') as devnull:
|
|
137
|
+
process = subprocess.Popen(command, stdout=devnull, stderr=devnull, preexec_fn=os.setpgrp)
|
|
138
|
+
|
|
139
|
+
proxies[service_name] = {
|
|
140
|
+
"pid": process.pid,
|
|
141
|
+
"port": port,
|
|
142
|
+
"local": "No",
|
|
143
|
+
"logs": log_file_path
|
|
144
|
+
}
|
|
145
|
+
save_proxies(proxies)
|
|
146
|
+
|
|
147
|
+
console.print(f"Proxy for [bold orange]'{service_name}'[/bold orange] setup complete on port {port}")
|
|
148
|
+
list_proxies()
|
|
135
149
|
|
|
136
150
|
return f"http://127.0.0.1:{port}"
|
|
137
151
|
|
|
138
152
|
|
|
139
|
-
def stop_proxy(service_name):
|
|
153
|
+
def stop_proxy(service_name, stop_local=True):
|
|
140
154
|
"""
|
|
141
155
|
Stops the gcloud proxy to the Cloud Run service using the stored PID.
|
|
142
156
|
|
|
143
157
|
Args:
|
|
144
158
|
service_name (str): Name of the Cloud Run service.
|
|
159
|
+
stop_local (bool): Whether to stop locally running services or not. Defaults to True.
|
|
145
160
|
"""
|
|
146
161
|
proxies = clean_proxy_list()
|
|
147
162
|
|
|
@@ -149,16 +164,21 @@ def stop_proxy(service_name):
|
|
|
149
164
|
print(f"No proxy found for service: {service_name}")
|
|
150
165
|
return
|
|
151
166
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
167
|
+
if not stop_local:
|
|
168
|
+
local = proxies[service_name]["local"]
|
|
169
|
+
if local != "No":
|
|
170
|
+
console.print(f"Not stopping local VAC running on: {local}")
|
|
171
|
+
else:
|
|
172
|
+
pid = proxies[service_name]["pid"]
|
|
173
|
+
try:
|
|
174
|
+
os.kill(pid, signal.SIGTERM)
|
|
175
|
+
del proxies[service_name]
|
|
176
|
+
save_proxies(proxies)
|
|
177
|
+
console.print(f"Proxy for [bold orange]'{service_name}'[bold orange] stopped.")
|
|
178
|
+
except ProcessLookupError:
|
|
179
|
+
console.print(f"No process found with PID: {pid}")
|
|
180
|
+
except Exception as e:
|
|
181
|
+
console.print(f"[bold red]Error stopping proxy for {service_name}: {e}[/bold red]")
|
|
162
182
|
|
|
163
183
|
list_proxies()
|
|
164
184
|
|
|
@@ -192,18 +212,71 @@ def list_proxies():
|
|
|
192
212
|
if not proxies:
|
|
193
213
|
print("No proxies currently running.")
|
|
194
214
|
else:
|
|
195
|
-
table = Table(title="VAC Proxies")
|
|
215
|
+
table = Table(title="VAC Proxies - `sunholo proxy list`")
|
|
196
216
|
table.add_column("VAC")
|
|
197
217
|
table.add_column("Port")
|
|
198
218
|
table.add_column("PID")
|
|
199
219
|
table.add_column("URL")
|
|
220
|
+
table.add_column("Local")
|
|
221
|
+
table.add_column("Logs")
|
|
200
222
|
|
|
201
223
|
for service_name, info in proxies.items():
|
|
202
224
|
url = f"http://127.0.0.1:{info['port']}"
|
|
203
|
-
table.add_row(service_name,
|
|
225
|
+
table.add_row(service_name,
|
|
226
|
+
str(info['port']),
|
|
227
|
+
str(info['pid']),
|
|
228
|
+
url,
|
|
229
|
+
str(info['local']),
|
|
230
|
+
str(info['logs']) )
|
|
204
231
|
|
|
205
232
|
console.print(table)
|
|
206
233
|
|
|
234
|
+
def start_local(service_name, port, app_type, app_folder, log_file):
|
|
235
|
+
"""
|
|
236
|
+
Starts a local Flask or FastAPI VAC app.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
service_name (str): Name of the service.
|
|
240
|
+
port (int): Port to run the local app on.
|
|
241
|
+
app_type (str): Type of the app ('flask' or 'fastapi').
|
|
242
|
+
app_folder (str): Folder containing the app.
|
|
243
|
+
"""
|
|
244
|
+
proxies = clean_proxy_list()
|
|
245
|
+
|
|
246
|
+
if service_name in proxies:
|
|
247
|
+
console.print(f"Local VAC app [bold orange]'{service_name}'[/bold orange] is already running on port {proxies[service_name]['port']}.")
|
|
248
|
+
return
|
|
249
|
+
|
|
250
|
+
if app_type == 'flask':
|
|
251
|
+
command = [sys.executable, 'app.py']
|
|
252
|
+
elif app_type == 'fastapi':
|
|
253
|
+
command = ["uvicorn", "app:app", f"--port={port}"]
|
|
254
|
+
else:
|
|
255
|
+
print(f"[bold red]Unknown app type: {app_type}[/bold red]")
|
|
256
|
+
return
|
|
257
|
+
|
|
258
|
+
if log_file:
|
|
259
|
+
log_file_path = os.path.join(app_folder, f"{service_name}_log.txt")
|
|
260
|
+
with open(log_file_path, 'w') as logf:
|
|
261
|
+
process = subprocess.Popen(command, cwd=app_folder, stdout=logf, stderr=logf, preexec_fn=os.setpgrp)
|
|
262
|
+
else:
|
|
263
|
+
log_file_path = "No log file specified"
|
|
264
|
+
with open(os.devnull, 'a') as devnull:
|
|
265
|
+
process = subprocess.Popen(command, cwd=app_folder, stdout=devnull, stderr=devnull, preexec_fn=os.setpgrp)
|
|
266
|
+
|
|
267
|
+
proxies[service_name] = {
|
|
268
|
+
"pid": process.pid,
|
|
269
|
+
"port": port,
|
|
270
|
+
"local": f"{app_folder}/app.py - {app_type}",
|
|
271
|
+
"logs": log_file_path
|
|
272
|
+
}
|
|
273
|
+
save_proxies(proxies)
|
|
274
|
+
|
|
275
|
+
console.print(f"Local app [bold orange]'{service_name}'[/bold orange] started on port {port}")
|
|
276
|
+
list_proxies()
|
|
277
|
+
|
|
278
|
+
return f"http://127.0.0.1:{port}"
|
|
279
|
+
|
|
207
280
|
def setup_proxy_subparser(subparsers):
|
|
208
281
|
"""
|
|
209
282
|
Sets up an argparse subparser for the 'proxy' command.
|
|
@@ -218,8 +291,19 @@ def setup_proxy_subparser(subparsers):
|
|
|
218
291
|
start_parser = proxy_subparsers.add_parser('start', help='Start the proxy to the VAC Cloud Run service')
|
|
219
292
|
start_parser.add_argument('service_name', help='Name of the Cloud Run service.')
|
|
220
293
|
start_parser.add_argument('--port', type=int, help='Port to run the proxy on. Auto-assigns if not provided.')
|
|
221
|
-
start_parser.
|
|
222
|
-
|
|
294
|
+
start_parser.add_argument('--local', action='store_true', help='Run the service locally instead of proxying to Cloud Run.')
|
|
295
|
+
start_parser.add_argument('--app-type', choices=['flask', 'fastapi'], help='If local, type of the local app (flask or fastapi).')
|
|
296
|
+
start_parser.add_argument('--app-folder', help='If local, folder containing the local app.py')
|
|
297
|
+
start_parser.add_argument('--log-file', action='store_true', help='Whether to create a file containing proxy logs.')
|
|
298
|
+
start_parser.set_defaults(func=lambda args: start_proxy(args.service_name,
|
|
299
|
+
args.region,
|
|
300
|
+
args.project,
|
|
301
|
+
args.port,
|
|
302
|
+
args.local,
|
|
303
|
+
args.app_type,
|
|
304
|
+
args.app_folder,
|
|
305
|
+
args.log_file))
|
|
306
|
+
|
|
223
307
|
stop_parser = proxy_subparsers.add_parser('stop', help='Stop the proxy to the Cloud Run service.')
|
|
224
308
|
stop_parser.add_argument('service_name', help='Name of the Cloud Run service.')
|
|
225
309
|
stop_parser.set_defaults(func=lambda args: stop_proxy(args.service_name))
|
sunholo/database/lancedb.py
CHANGED
|
@@ -5,7 +5,7 @@ def create_lancedb_index(bucket, vector_name, num_partitions=256, num_sub_vector
|
|
|
5
5
|
import lancedb
|
|
6
6
|
#import tantivy
|
|
7
7
|
except ImportError:
|
|
8
|
-
raise ValueError("Could not import lancedb module, install via `pip
|
|
8
|
+
raise ValueError("Could not import lancedb module, install via `pip install sunholo[database]`")
|
|
9
9
|
|
|
10
10
|
try:
|
|
11
11
|
db = lancedb.connect(bucket)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: sunholo
|
|
3
|
-
Version: 0.60.
|
|
3
|
+
Version: 0.60.9
|
|
4
4
|
Summary: Large Language Model DevOps - a package to help deploy LLMs to the Cloud.
|
|
5
5
|
Home-page: https://github.com/sunholo-data/sunholo-py
|
|
6
|
-
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.60.
|
|
6
|
+
Download-URL: https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.60.9.tar.gz
|
|
7
7
|
Author: Holosun ApS
|
|
8
8
|
Author-email: multivac@sunholo.com
|
|
9
9
|
License: Apache License, Version 2.0
|
|
@@ -13,7 +13,7 @@ sunholo/agents/fastapi/base.py,sha256=clk76cHbUAvU0OYJrRfCWX_5f0ACbhDsIzYBhI3wyo
|
|
|
13
13
|
sunholo/agents/fastapi/qna_routes.py,sha256=DgK4Btu5XriOC1JaRQ4G_nWEjJfnQ0J5pyLanF6eF1g,3857
|
|
14
14
|
sunholo/agents/flask/__init__.py,sha256=uqfHNw2Ru3EJ4dJEcbp86h_lkquBQPMxZbjhV_xe3rs,72
|
|
15
15
|
sunholo/agents/flask/base.py,sha256=RUGWBYWeV60FatYF5sMRrxD-INU97Vodsi6JaB6i93s,763
|
|
16
|
-
sunholo/agents/flask/qna_routes.py,sha256=
|
|
16
|
+
sunholo/agents/flask/qna_routes.py,sha256=9xQUIadDtQIgTRa-nXIYJbzwQokqtVjeLp-tcSxGy9Y,8788
|
|
17
17
|
sunholo/archive/__init__.py,sha256=qNHWm5rGPVOlxZBZCpA1wTYPbalizRT7f8X4rs2t290,31
|
|
18
18
|
sunholo/archive/archive.py,sha256=C-UhG5x-XtZ8VheQp92IYJqgD0V3NFQjniqlit94t18,1197
|
|
19
19
|
sunholo/auth/__init__.py,sha256=4owDjSaWYkbTlPK47UHTOC0gCWbZsqn4ZIEw5NWZTlg,28
|
|
@@ -32,13 +32,13 @@ sunholo/chunker/pdfs.py,sha256=daCZ1xjn1YvxlifIyxskWNpLJLe-Q9D_Jq12MWx3tZo,2473
|
|
|
32
32
|
sunholo/chunker/publish.py,sha256=PoT8q3XJeFCg10WrLkYhuaaXIrGVkvUD3-R9IfoWoH4,2703
|
|
33
33
|
sunholo/chunker/splitter.py,sha256=FLkDhkePkg_zGQpFBK13Cznw575D-Rf9pcaCpc1HUxY,6726
|
|
34
34
|
sunholo/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
sunholo/cli/chat_vac.py,sha256=
|
|
36
|
-
sunholo/cli/cli.py,sha256=
|
|
35
|
+
sunholo/cli/chat_vac.py,sha256=_NUjwATKvzwfnBJRedP2GqPFNeaCF5F8OvdygXRH1LY,11379
|
|
36
|
+
sunholo/cli/cli.py,sha256=cogY1F5rcIGFYpZVFtbDNlAIElpfyPSCvSLC1ZIpHXg,2666
|
|
37
37
|
sunholo/cli/cli_init.py,sha256=JMZ9AX2cPDZ-_mv3adiv2ToFVNyRPtjk9Biszl1kiR0,2358
|
|
38
38
|
sunholo/cli/configs.py,sha256=QUM9DvKOdZmEQRM5uI3Nh887T0YDiSMr7O240zTLqws,4546
|
|
39
39
|
sunholo/cli/deploy.py,sha256=zxdwUsRTRMC8U5vyRv0JiKBLFn84Ug_Tc88-_h9hJSs,1609
|
|
40
40
|
sunholo/cli/merge_texts.py,sha256=U9vdMwKmcPoc6iPOWX5MKSxn49dNGbNzVLw8ui5PhEU,1823
|
|
41
|
-
sunholo/cli/run_proxy.py,sha256=
|
|
41
|
+
sunholo/cli/run_proxy.py,sha256=9ILCxSVHPzS-cSBvjdHhfZFlwsJ4Ttmu0vLtNoPCRgo,11469
|
|
42
42
|
sunholo/cli/sun_rich.py,sha256=UpMqeJ0C8i0pkue1AHnnyyX0bFJ9zZeJ7HBR6yhuA8A,54
|
|
43
43
|
sunholo/components/__init__.py,sha256=RJGNEihwvRIiDScKis04RHJv4yZGI1UpXlOmuCptNZI,208
|
|
44
44
|
sunholo/components/llm.py,sha256=T4we3tGmqUj4tPwxQr9M6AXv_BALqZV_dRSvINan-oU,10374
|
|
@@ -48,7 +48,7 @@ sunholo/components/vectorstore.py,sha256=dzspqOBtuxSjCFxem5_50sqwUUjbZ4oBYERtCwx
|
|
|
48
48
|
sunholo/database/__init__.py,sha256=Zz0Shcq-CtStf9rJGIYB_Ybzb8rY_Q9mfSj-nviM490,241
|
|
49
49
|
sunholo/database/alloydb.py,sha256=0zRLyeC9nACzj3v36ET9NqLeuzdwBJ2bE09CzgVTTFM,17098
|
|
50
50
|
sunholo/database/database.py,sha256=doY05kG8BZBLL-arh4hq5ef1ouWOtGHqdsDc6M2YHgk,7345
|
|
51
|
-
sunholo/database/lancedb.py,sha256=
|
|
51
|
+
sunholo/database/lancedb.py,sha256=2rAbJVusMrm5TPtVTsUtmwn0z1iZ_wvbKhc6eyT6ClE,708
|
|
52
52
|
sunholo/database/static_dbs.py,sha256=aOyU3AJ-Dzz3qSNjbuN2293cfYw5PhkcQuQxdwPMJ4w,435
|
|
53
53
|
sunholo/database/uuid.py,sha256=GtUL_uq80u2xkozPF9kwNpvhBf03hbZR3xUhO3NomBM,237
|
|
54
54
|
sunholo/database/sql/sb/create_function.sql,sha256=HuDyp3fxS5Etop3gGDy28_AuFuhgEgVcq9-q3oeecPU,1033
|
|
@@ -96,9 +96,9 @@ sunholo/utils/parsers.py,sha256=OrHmASqIbI45atVOhiGodgLvnfrzkvVzyHnSvAXD89I,3841
|
|
|
96
96
|
sunholo/utils/user_ids.py,sha256=SQd5_H7FE7vcTZp9AQuQDWBXd4FEEd7TeVMQe1H4Ny8,292
|
|
97
97
|
sunholo/vertex/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
98
98
|
sunholo/vertex/init_vertex.py,sha256=JDMUaBRdednzbKF-5p33qqLit2LMsvgvWW-NRz0AqO0,1801
|
|
99
|
-
sunholo-0.60.
|
|
100
|
-
sunholo-0.60.
|
|
101
|
-
sunholo-0.60.
|
|
102
|
-
sunholo-0.60.
|
|
103
|
-
sunholo-0.60.
|
|
104
|
-
sunholo-0.60.
|
|
99
|
+
sunholo-0.60.9.dist-info/LICENSE.txt,sha256=SdE3QjnD3GEmqqg9EX3TM9f7WmtOzqS1KJve8rhbYmU,11345
|
|
100
|
+
sunholo-0.60.9.dist-info/METADATA,sha256=HRCIwV9y1sAi8Ft3p73fUff0wkaxHQ7V9CSN-1jwSzE,8057
|
|
101
|
+
sunholo-0.60.9.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
102
|
+
sunholo-0.60.9.dist-info/entry_points.txt,sha256=bZuN5AIHingMPt4Ro1b_T-FnQvZ3teBes-3OyO0asl4,49
|
|
103
|
+
sunholo-0.60.9.dist-info/top_level.txt,sha256=wt5tadn5--5JrZsjJz2LceoUvcrIvxjHJe-RxuudxAk,8
|
|
104
|
+
sunholo-0.60.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|