stoobly-agent 1.9.5__py3-none-any.whl → 1.9.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.
stoobly_agent/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
1
  COMMAND = 'stoobly-agent'
2
- VERSION = '1.9.5'
2
+ VERSION = '1.9.6'
@@ -15,8 +15,18 @@ def ca_cert(ctx):
15
15
  pass
16
16
 
17
17
  @ca_cert.command()
18
- @click.option('--ca-certs-dir-path', default=DataDir.instance().ca_certs_dir_path, help='Path to ca certs directory used to sign SSL certs.')
19
- @click.option('--certs-dir-path', default=DataDir.instance().certs_dir_path, help='Output directory.')
18
+ @click.option(
19
+ '--ca-certs-dir-path',
20
+ default=DataDir.instance().ca_certs_dir_path,
21
+ help='Path to ca certs directory used to sign SSL certs.',
22
+ type=click.Path(exists=True, file_okay=False, dir_okay=True)
23
+ )
24
+ @click.option(
25
+ '--certs-dir-path',
26
+ default=DataDir.instance().certs_dir_path,
27
+ help='Output directory.',
28
+ type=click.Path(exists=True, file_okay=False, dir_okay=True)
29
+ )
20
30
  @click.argument('hostname')
21
31
  def mkcert(**kwargs):
22
32
  ca_certs_dir_path = kwargs['ca_certs_dir_path']
@@ -30,7 +40,12 @@ def mkcert(**kwargs):
30
40
  sys.exit(1)
31
41
 
32
42
  @ca_cert.command()
33
- @click.option('--ca-certs-dir-path', default=DataDir.instance().ca_certs_dir_path, help='Path to ca certs directory.')
43
+ @click.option(
44
+ '--ca-certs-dir-path',
45
+ default=DataDir.instance().ca_certs_dir_path,
46
+ help='Path to ca certs directory.',
47
+ type=click.Path(exists=True, file_okay=False, dir_okay=True)
48
+ )
34
49
  def install(**kwargs):
35
50
  ca_certs_dir_path = kwargs['ca_certs_dir_path']
36
51
  installer = CertificateAuthority(ca_certs_dir_path)
@@ -35,7 +35,7 @@ dockerfile_path=$(app_namespace_dir)/.Dockerfile.context
35
35
  exec_docker_compose_file_path=$(app_namespace_dir)/stoobly-ui/exec/.docker-compose.exec.yml
36
36
  exec_namespace=$(shell echo "$(workflow_namespace).$(context_dir)" | (md5 2>/dev/null || md5sum 2>/dev/null || shasum 2>/dev/null) | awk '{print $$1}')
37
37
  workflow_namespace=$(if $(namespace),$(namespace),$(workflow))
38
- workflow_script=.stoobly/tmp/$(workflow)/run.sh
38
+ workflow_script=.stoobly/tmp/$(workflow_namespace)/run.sh
39
39
 
40
40
  # Options
41
41
  certs_dir_options=--ca-certs-dir-path $(ca_certs_dir) --certs-dir-path $(certs_dir)
@@ -52,8 +52,8 @@ docker_command=docker
52
52
  docker_compose_command=$(docker_command) compose
53
53
  exec_down=$(docker_compose_command) -f "$(exec_docker_compose_file_path)" $(stoobly_exec_options) down
54
54
  exec_env=APP_DIR="$(app_dir)" CA_CERTS_DIR="$(ca_certs_dir)" USER_ID="$(USER_ID)"
55
- exec_up=$(docker_compose_command) -f "$(exec_docker_compose_file_path)" $(stoobly_exec_options) up --remove-orphans
56
- source_env=set -a; [ -f .env ] && source .env; set +a
55
+ exec_up=$(docker_compose_command) -f "$(exec_docker_compose_file_path)" $(stoobly_exec_options) up --abort-on-container-exit --remove-orphans
56
+ source_env=(set -a; [ -f .env ] && source .env; set +a)
57
57
 
58
58
  # Build base image
59
59
  stoobly_exec_build=$(docker_command) build $(stoobly_exec_build_args) $(app_namespace_dir)
@@ -1,7 +1,6 @@
1
1
  import click
2
2
  import os
3
3
  import pdb
4
- import re
5
4
  import sys
6
5
 
7
6
  from io import TextIOWrapper
@@ -37,6 +36,7 @@ from stoobly_agent.config.data_dir import DataDir
37
36
  from stoobly_agent.lib.logger import bcolors, DEBUG, ERROR, INFO, Logger, WARNING
38
37
 
39
38
  from .helpers.print_service import FORMATS, print_services, select_print_options
39
+ from .validators.scaffold import validate_app_name, validate_hostname, validate_namespace, validate_service_name
40
40
 
41
41
  LOG_ID = 'Scaffold'
42
42
 
@@ -90,7 +90,7 @@ def hostname(ctx):
90
90
  @click.option('--network', help='App default network name. Defaults to app name.')
91
91
  @click.option('--quiet', is_flag=True, help='Disable log output.')
92
92
  @click.option('--ui-port', default=4200, type=click.IntRange(1, 65535), help='UI service port.')
93
- @click.argument('app_name')
93
+ @click.argument('app_name', callback=validate_app_name)
94
94
  def create(**kwargs):
95
95
  __validate_app_dir(kwargs['app_dir_path'])
96
96
 
@@ -129,7 +129,7 @@ def mkcert(**kwargs):
129
129
  @click.option('--app-dir-path', default=current_working_dir, help='Path to application directory.')
130
130
  @click.option('--detached', is_flag=True, help='Use isolated and non-persistent context directory.')
131
131
  @click.option('--env', multiple=True, help='Specify an environment variable.')
132
- @click.option('--hostname', help='Service hostname.')
132
+ @click.option('--hostname', callback=validate_hostname, help='Service hostname.')
133
133
  @click.option('--port', type=click.IntRange(1, 65535), help='Service port.')
134
134
  @click.option('--priority', default=5, type=click.FloatRange(1.0, 9.0), help='Determines the service run order. Lower values run first.')
135
135
  @click.option('--proxy-mode', help='''
@@ -141,7 +141,7 @@ def mkcert(**kwargs):
141
141
  @click.option('--quiet', is_flag=True, help='Disable log output.')
142
142
  @click.option('--scheme', type=click.Choice(['http', 'https']), help='Defaults to https if hostname is set.')
143
143
  @click.option('--workflow', multiple=True, type=click.Choice([WORKFLOW_MOCK_TYPE, WORKFLOW_RECORD_TYPE, WORKFLOW_TEST_TYPE]), help='Include pre-defined workflows.')
144
- @click.argument('service_name')
144
+ @click.argument('service_name', callback=validate_service_name)
145
145
  def create(**kwargs):
146
146
  __validate_app_dir(kwargs['app_dir_path'])
147
147
 
@@ -149,9 +149,6 @@ def create(**kwargs):
149
149
  print(f"Error: {kwargs['service_name']} is invalid. It cannot container '/", file=sys.stderr)
150
150
  sys.exit(1)
151
151
 
152
- if kwargs.get('hostname'):
153
- __validate_hostname(kwargs.get('hostname'))
154
-
155
152
  if kwargs.get("proxy_mode"):
156
153
  __validate_proxy_mode(kwargs.get("proxy_mode"))
157
154
 
@@ -214,7 +211,7 @@ def delete(**kwargs):
214
211
  help="Update a service config"
215
212
  )
216
213
  @click.option('--app-dir-path', default=current_working_dir, help='Path to application directory.')
217
- @click.option('--hostname', help='Service hostname.')
214
+ @click.option('--hostname', callback=validate_hostname, help='Service hostname.')
218
215
  @click.option('--port', type=click.IntRange(1, 65535), help='Service port.')
219
216
  @click.option('--priority', default=5, type=click.FloatRange(1.0, 9.0), help='Determines the service run order. Lower values run first.')
220
217
  @click.option('--scheme', type=click.Choice(['http', 'https']), help='Defaults to https if hostname is set.')
@@ -237,8 +234,6 @@ def update(**kwargs):
237
234
  service_config = ServiceConfig(service.dir_path)
238
235
 
239
236
  if kwargs['hostname']:
240
- __validate_hostname(kwargs['hostname'])
241
-
242
237
  old_hostname = service_config.hostname
243
238
 
244
239
  if old_hostname != kwargs['hostname']:
@@ -329,7 +324,7 @@ def copy(**kwargs):
329
324
  @click.option('--log-level', default=INFO, type=click.Choice([DEBUG, INFO, WARNING, ERROR]), help='''
330
325
  Log levels can be "debug", "info", "warning", or "error"
331
326
  ''')
332
- @click.option('--namespace', help='Workflow namespace.')
327
+ @click.option('--namespace', callback=validate_namespace, help='Workflow namespace.')
333
328
  @click.option('--network', help='Workflow network name.')
334
329
  @click.option('--rmi', is_flag=True, help='Remove images used by containers.')
335
330
  @click.option('--script-path', help='Path to intermediate script path.')
@@ -412,7 +407,7 @@ def down(**kwargs):
412
407
  @click.option('--log-level', default=INFO, type=click.Choice([DEBUG, INFO, WARNING, ERROR]), help='''
413
408
  Log levels can be "debug", "info", "warning", or "error"
414
409
  ''')
415
- @click.option('--namespace', help='Workflow namespace.')
410
+ @click.option('--namespace', callback=validate_namespace, help='Workflow namespace.')
416
411
  @click.option('--script-path', help='Path to intermediate script path.')
417
412
  @click.option('--service', multiple=True, help='Select which services to log. Defaults to all.')
418
413
  @click.argument('workflow_name')
@@ -474,7 +469,7 @@ def logs(**kwargs):
474
469
  Log levels can be "debug", "info", "warning", or "error"
475
470
  ''')
476
471
  @click.option('--mkcert', is_flag=True, help='Set to generate SSL certs for HTTPS services.')
477
- @click.option('--namespace', help='Workflow namespace.')
472
+ @click.option('--namespace', callback=validate_namespace, help='Workflow namespace.')
478
473
  @click.option('--network', help='Workflow network name.')
479
474
  @click.option('--no-build', is_flag=True, help='Do not build images before starting containers.')
480
475
  @click.option('--no-publish', is_flag=True, help='Do not publish all ports.')
@@ -677,7 +672,7 @@ def __build_script(**kwargs):
677
672
  script_path = kwargs['script_path']
678
673
  if not script_path:
679
674
  script_file_name = 'run.sh'
680
- script_path = os.path.join(data_dir.tmp_dir_path, kwargs['workflow_name'], script_file_name)
675
+ script_path = os.path.join(data_dir.tmp_dir_path, kwargs.get('namespace') or kwargs['workflow_name'] or '', script_file_name)
681
676
 
682
677
  script_dir = os.path.dirname(script_path)
683
678
  if not os.path.exists(script_dir):
@@ -818,12 +813,6 @@ def __validate_proxy_mode(proxy_mode: str) -> None:
818
813
 
819
814
  # TODO: validate SPEC
820
815
 
821
- def __validate_hostname(hostname: str) -> None:
822
- hostname_regex = re.compile(r'^[a-zA-Z0-9.-]+$')
823
- if not re.search(hostname_regex, hostname):
824
- print(f"Error: {hostname} is invalid.", file=sys.stderr)
825
- sys.exit(1)
826
-
827
816
  def __workflow_create(app, **kwargs):
828
817
  command = WorkflowCreateCommand(app, **kwargs)
829
818
 
@@ -0,0 +1,34 @@
1
+ import re
2
+ import sys
3
+
4
+ def validate_app_name(ctx, param, app_name: str) -> str:
5
+ app_name_regex = re.compile(r'^[a-zA-Z0-9._-]+$')
6
+ if not re.search(app_name_regex, app_name):
7
+ print(f"Error: app name {app_name} is invalid.", file=sys.stderr)
8
+ sys.exit(1)
9
+ return app_name
10
+
11
+ def validate_hostname(ctx, param, hostname: str) -> str:
12
+ if not hostname:
13
+ return
14
+ hostname_regex = re.compile(r'^[a-zA-Z0-9.-]+$')
15
+ if not re.search(hostname_regex, hostname):
16
+ print(f"Error: hostname {hostname} is invalid.", file=sys.stderr)
17
+ sys.exit(1)
18
+ return hostname
19
+
20
+ def validate_namespace(ctx, param, namespace: str) -> str:
21
+ if not namespace:
22
+ return
23
+ namespace_regex = re.compile(r'^[a-z0-9_-]+$')
24
+ if not re.search(namespace_regex, namespace) or namespace[0] in ['-', '_']:
25
+ print(f"Error: namespace {namespace} is invalid.", file=sys.stderr)
26
+ sys.exit(1)
27
+ return namespace
28
+
29
+ def validate_service_name(ctx, param, service_name: str) -> str:
30
+ service_name_regex = re.compile(r'^[a-zA-Z0-9._-]+$')
31
+ if not re.search(service_name_regex, service_name):
32
+ print(f"Error: service name {service_name} is invalid.", file=sys.stderr)
33
+ sys.exit(1)
34
+ return service_name
@@ -1 +1 @@
1
- 1.9.4
1
+ 1.9.6
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: stoobly-agent
3
- Version: 1.9.5
3
+ Version: 1.9.6
4
4
  Summary: Record, mock, and test HTTP(s) requests. CLI agent for Stoobly
5
5
  License: Apache-2.0
6
6
  Author: Matt Le
@@ -1,4 +1,4 @@
1
- stoobly_agent/__init__.py,sha256=IIieB06ghDX3rkbVoznhopSYzZNIgt8A-_fJzdVS7i4,44
1
+ stoobly_agent/__init__.py,sha256=UlQip9_Ul2fRC4UHN6HFN0lQDoz_AEInAcMSJiQnEow,44
2
2
  stoobly_agent/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  stoobly_agent/app/api/__init__.py,sha256=ctkB8KR-eXO0SFhj602huHiyvQ3PslFWd8fkcufgrAI,1000
4
4
  stoobly_agent/app/api/application_http_request_handler.py,sha256=Vvz53yB0bR7J-QqMAkLlhcZrA4P64ZEN7w8cMbgl6o0,5261
@@ -17,7 +17,7 @@ stoobly_agent/app/api/scenarios_controller.py,sha256=zJViyme9l36mlJDQONRu4N-A0kd
17
17
  stoobly_agent/app/api/simple_http_request_handler.py,sha256=ZdJ4kKEcPDpck74dJu--M7zw76wQzpo_AQArZwN9Bes,4466
18
18
  stoobly_agent/app/api/statuses_controller.py,sha256=gQsl28h-3mZ_bByEHpc4mRy3KFvUz5PeAgVB0cPx_Ao,1791
19
19
  stoobly_agent/app/cli/__init__.py,sha256=uS4KJgMAhm0JVnEUC-ONW-Bq6A8I9v7Fk-_Ka7gXlrU,470
20
- stoobly_agent/app/cli/ca_cert_cli.py,sha256=qwuNXRJTi4hLHObv8uVKd2XeSsS3A_T-OjztjVctrkI,1387
20
+ stoobly_agent/app/cli/ca_cert_cli.py,sha256=KVIUmmZcMHW2UXZJTmXqTVk2lEbp0YbxB6C4EL5t2Q4,1629
21
21
  stoobly_agent/app/cli/config_cli.py,sha256=Ljr2Ir8P0dhGXALQQcq7fwthrcipPlvxS2G_0bNE6fY,15727
22
22
  stoobly_agent/app/cli/decorators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  stoobly_agent/app/cli/decorators/config.py,sha256=AWrDGZm_gjCWFYlRwdla3iE6H7OSlM4FxkaXRNovBZA,2428
@@ -104,7 +104,7 @@ stoobly_agent/app/cli/scaffold/service_workflow.py,sha256=sQ_Edy_wGHKMXpD0DmhnOW
104
104
  stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py,sha256=xONRUtfC3IBd-Kr4wdUKWgx9ppSsbu2H72pb2VinizQ,11412
105
105
  stoobly_agent/app/cli/scaffold/templates/__init__.py,sha256=x8C_a0VoO_vUbosp4_6IC1U7Ge9NnUdVKDPpVMtMkeY,171
106
106
  stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context,sha256=Okk4Q0Fj7Wi5NU58gQfpjpFwAL3RUBJyRe56kteQfcA,158
107
- stoobly_agent/app/cli/scaffold/templates/app/.Makefile,sha256=zifPWDDZ9RPz0p872Kl00pnmFY3jMHulp84tYXhfSwg,9240
107
+ stoobly_agent/app/cli/scaffold/templates/app/.Makefile,sha256=4CTrKRHho9fl7NOGrQM0lJTfn-X09ddQKBq9Zsbjbww,9278
108
108
  stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.base.yml,sha256=6tFqXh3ine8vaD0FCL5TMoY5NjKx2wLUR8XpW3tJtew,245
109
109
  stoobly_agent/app/cli/scaffold/templates/app/.docker-compose.networks.yml,sha256=I4PbJpQjFHb5IbAUWNvYM6okDEtmwtKFDQg-yog05WM,141
110
110
  stoobly_agent/app/cli/scaffold/templates/app/Makefile,sha256=TEmPG7Bf0KZOnmfsgdzza3UdwcVMmM5Lj1YdLc4cgjA,79
@@ -203,7 +203,7 @@ stoobly_agent/app/cli/scaffold/workflow_env.py,sha256=x8V5pJmIiklD3f2q2-qq-CORf4
203
203
  stoobly_agent/app/cli/scaffold/workflow_log_command.py,sha256=Bke4lMOMxuDUFuAx9nlXHbKgYMO4KAg9ASHvjz4aVWc,1372
204
204
  stoobly_agent/app/cli/scaffold/workflow_run_command.py,sha256=eF3aaK4OIZXYuSBEAeBnhAL7EZrS1G4mSYrJbEiXt2o,11082
205
205
  stoobly_agent/app/cli/scaffold/workflow_validate_command.py,sha256=Uo_yo6rVR1ZR7xpvsQvlH48AyMBVLRupd4G-bRjzm_Q,5584
206
- stoobly_agent/app/cli/scaffold_cli.py,sha256=NXlLuqAwv9p0dflksswAtgJPTfojvJDDHIdJ71-BCSE,31965
206
+ stoobly_agent/app/cli/scaffold_cli.py,sha256=9NOSl3Qy7LN3PphuOqTFEM6t0PanVEHow8iyW-5eTW0,31958
207
207
  stoobly_agent/app/cli/scenario_cli.py,sha256=3J1EiJOvunkfWrEkOsanw-XrKkOk78ij_GjBlE9p7CE,8229
208
208
  stoobly_agent/app/cli/snapshot_cli.py,sha256=1Dw5JgDlmG6vctrawIRO7CdB73vAQk_wRBnPG2lVOrQ,11929
209
209
  stoobly_agent/app/cli/trace_cli.py,sha256=K7E-vx3JUcqEDSWOdIOi_AieKNQz7dBfmRrVvKDkzFI,4605
@@ -214,6 +214,7 @@ stoobly_agent/app/cli/types/request.py,sha256=QthojE5sfx7OvKu-vVNnSUfGk8n4pLzuBQ
214
214
  stoobly_agent/app/cli/types/scenario.py,sha256=28WxmOlbm2Bsek1uu7yc4hJGz-d5oHbYAro7LlFWRoc,81
215
215
  stoobly_agent/app/cli/types/snapshot_migration.py,sha256=4_Re46FKjsflcTOO3qhNsbWWmdEU67SFsF-XE_FKG3M,1859
216
216
  stoobly_agent/app/cli/types/test.py,sha256=1c458B7DFBWsEk5Q1CrZ2CUi84YzEzcs-W4qTcudwAk,714
217
+ stoobly_agent/app/cli/validators/scaffold.py,sha256=mjLdb1lO8_SKOspwQSONSA8upXANg6HOvtttkHEqhrk,1187
217
218
  stoobly_agent/app/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
219
  stoobly_agent/app/models/adapters/__init__.py,sha256=cEEE--Bvrvk6DAsHx_uPgFhLnZJETP4zSBtWjMqyIKc,233
219
220
  stoobly_agent/app/models/adapters/joined_request_adapter.py,sha256=fSq16n3AAlxi8KJdBESHp3JGio_M9uzMnHbnQU8VI3w,3598
@@ -708,7 +709,7 @@ stoobly_agent/test/app/models/factories/resource/local_db/helpers/log_test.py,sh
708
709
  stoobly_agent/test/app/models/factories/resource/local_db/helpers/tiebreak_scenario_request_test.py,sha256=a1SFLyEyRRLuADvAw6ckQQKORFXvyK1lyrbkaLWx8oU,3399
709
710
  stoobly_agent/test/app/models/factories/resource/local_db/request_adapter_test.py,sha256=Pzq1cBPnP9oSWG-p0c-VoymoHxgp483QmNwmV1b78RA,8453
710
711
  stoobly_agent/test/app/models/factories/resource/local_db/response_adapter_test.py,sha256=9P95EKH5rZGOrmRkRIDlQZqtiLJHk9735og18Ffwpfw,2204
711
- stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION,sha256=MvlkhO5KUUDkZHqygfa1PgGkfddFw7TZAu1qTt_cq-g,5
712
+ stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION,sha256=0vY2lU8oU9tB_UhSABsgfVlYkLE7wf6JMFZoxaKHBS0,6
712
713
  stoobly_agent/test/app/models/schemas/.stoobly/db/stoobly_agent.sqlite3,sha256=ch8gNx6zIelLKQx65gwFx_LRNqUD3EC5xcHZ0ukIQiU,188416
713
714
  stoobly_agent/test/app/models/schemas/.stoobly/settings.yml,sha256=vLwMjweKOdod6tSLtIlyBefPQuNXq9wio4kBaODKtAU,726
714
715
  stoobly_agent/test/app/models/schemas/.stoobly/tmp/options.json,sha256=OTRzarwus48CTrItedXCrgQttJHSEZonEYc7R_knvYg,2212
@@ -749,8 +750,8 @@ stoobly_agent/test/mock_data/scaffold/docker-compose-local-service.yml,sha256=1W
749
750
  stoobly_agent/test/mock_data/scaffold/index.html,sha256=qJwuYajKZ4ihWZrJQ3BNObV5kf1VGnnm_vqlPJzdqLE,258
750
751
  stoobly_agent/test/mock_data/uspto.yaml,sha256=6U5se7C3o-86J4m9xpOk9Npias399f5CbfWzR87WKwE,7835
751
752
  stoobly_agent/test/test_helper.py,sha256=m_oAI7tmRYCNZdKfNqISWhMv3e44tjeYViQ3nTUfnos,1007
752
- stoobly_agent-1.9.5.dist-info/LICENSE,sha256=o93sj12cdoEOsTCjPaPFsw3Xq0SXs3pPcY-9reE2sEw,548
753
- stoobly_agent-1.9.5.dist-info/METADATA,sha256=Ar6dgljQ63YgEG_psjAkNEVUpGuRpudvTxCY4fAebgQ,3087
754
- stoobly_agent-1.9.5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
755
- stoobly_agent-1.9.5.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
756
- stoobly_agent-1.9.5.dist-info/RECORD,,
753
+ stoobly_agent-1.9.6.dist-info/LICENSE,sha256=o93sj12cdoEOsTCjPaPFsw3Xq0SXs3pPcY-9reE2sEw,548
754
+ stoobly_agent-1.9.6.dist-info/METADATA,sha256=uLLTaIvuC4eHvFOImTS-phj_G1HeK2F0qjhOYpPiyrM,3087
755
+ stoobly_agent-1.9.6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
756
+ stoobly_agent-1.9.6.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
757
+ stoobly_agent-1.9.6.dist-info/RECORD,,