stoobly-agent 1.9.11__py3-none-any.whl → 1.9.12__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.11'
2
+ VERSION = '1.9.12'
@@ -1,19 +1,9 @@
1
- import os
2
1
  import subprocess
3
2
  import sys
4
3
 
5
- from dotenv import load_dotenv
6
-
7
4
  DOTENV_PATH = 'STOOBLY_DOTENV_PATH'
8
5
 
9
6
  def exec_stream(command):
10
- dotenv_path = os.environ.get(DOTENV_PATH)
11
-
12
- if dotenv_path and os.path.exists(dotenv_path):
13
- load_dotenv(dotenv_path=dotenv_path)
14
- else:
15
- load_dotenv()
16
-
17
7
  # Start the process
18
8
  process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
19
9
 
@@ -18,6 +18,7 @@ CONFIG_FILE = '.config.yml'
18
18
  CONTEXT_DIR_ENV = 'CONTEXT_DIR'
19
19
  DOCKER_NAMESPACE = 'docker'
20
20
  DOTENV_FILE = '.env'
21
+ DOTENV_PATH_ENV = 'STOOBLY_DOTENV_PATH'
21
22
  NAMESERVERS_FILE = '.nameservers'
22
23
  PUBLIC_FOLDER_NAME = 'public'
23
24
  SERVICE_DETACHED = '${SERVICE_DETACHED}'
@@ -1,8 +1,8 @@
1
1
  import os
2
-
2
+ import shutil
3
3
 
4
4
  from .app import App
5
- from .constants import DOTENV_FILE, NAMESERVERS_FILE
5
+ from .constants import DOTENV_PATH_ENV, DOTENV_FILE, NAMESERVERS_FILE
6
6
 
7
7
  class WorkflowNamespace():
8
8
 
@@ -35,6 +35,12 @@ class WorkflowNamespace():
35
35
  def traefik_config_path(self):
36
36
  return os.path.join(self.path, 'traefik.yml')
37
37
 
38
+ def copy_dotenv(self):
39
+ dotenv_path = os.environ.get(DOTENV_PATH_ENV) or '.env'
40
+
41
+ if os.path.isfile(dotenv_path):
42
+ shutil.copy(dotenv_path, self.dotenv_path)
43
+
38
44
  def traefik_config_relative_path(self, path: str):
39
45
  if not path:
40
46
  return path
@@ -89,7 +89,7 @@ def hostname(ctx):
89
89
  help="Scaffold application"
90
90
  )
91
91
  @click.option('--app-dir-path', default=current_working_dir, help='Path to create the app scaffold.')
92
- @click.option('--docker-socket-path', default='/var/run/docker.sock', help='Path to Docker socket.')
92
+ @click.option('--docker-socket-path', default='/var/run/docker.sock', type=click.Path(exists=True, file_okay=True, dir_okay=False), help='Path to Docker socket.')
93
93
  @click.option('--quiet', is_flag=True, help='Disable log output.')
94
94
  @click.option('--ui-port', default=4200, type=click.IntRange(1, 65535), help='UI service port.')
95
95
  @click.argument('app_name', callback=validate_app_name)
@@ -339,7 +339,7 @@ def copy(**kwargs):
339
339
  @click.option('--service', multiple=True, help='Select which services to log. Defaults to all.')
340
340
  @click.option('--user-id', default=os.getuid(), help='OS user ID of the owner of context dir path.')
341
341
  @click.argument('workflow_name')
342
- def down(**kwargs):
342
+ def down(**kwargs):
343
343
  os.environ[env_vars.LOG_LEVEL] = kwargs['log_level']
344
344
 
345
345
  containerized = kwargs['containerized']
@@ -349,6 +349,7 @@ def down(**kwargs):
349
349
  __validate_app(app)
350
350
 
351
351
  __with_namespace_defaults(kwargs)
352
+ __with_workflow_namespace(app, kwargs['namespace'])
352
353
 
353
354
  services = __get_services(
354
355
  app, service=kwargs['service'], workflow=[kwargs['workflow_name']]
@@ -503,6 +504,7 @@ def up(**kwargs):
503
504
  __validate_app(app)
504
505
 
505
506
  __with_namespace_defaults(kwargs)
507
+ workflow_namespace = __with_workflow_namespace(app, kwargs['namespace'])
506
508
 
507
509
  services = __get_services(
508
510
  app, service=kwargs['service'], workflow=[kwargs['workflow_name']]
@@ -514,11 +516,7 @@ def up(**kwargs):
514
516
 
515
517
  # Gateway ports are dynamically set depending on the workflow run
516
518
  workflow = Workflow(kwargs['workflow_name'], app)
517
- configure_gateway(
518
- WorkflowNamespace(app, kwargs['namespace'] or workflow.workflow_name),
519
- workflow.service_paths_from_services(services),
520
- kwargs['no_publish']
521
- )
519
+ configure_gateway(workflow_namespace, workflow.service_paths_from_services(services), kwargs['no_publish'])
522
520
 
523
521
  commands: List[WorkflowRunCommand] = []
524
522
  for service in services:
@@ -840,3 +838,8 @@ def __workflow_create(app, **kwargs):
840
838
  template=kwargs['template'],
841
839
  workflow_decorators=workflow_decorators
842
840
  )
841
+
842
+ def __with_workflow_namespace(app: App, namespace: str):
843
+ workflow_namespace = WorkflowNamespace(app, namespace)
844
+ workflow_namespace.copy_dotenv()
845
+ return workflow_namespace
@@ -7,7 +7,7 @@ from io import BytesIO
7
7
  from mitmproxy.http import Request as MitmproxyRequest
8
8
  from requests import Response
9
9
  from requests.structures import CaseInsensitiveDict
10
- from typing import Union
10
+ from typing import Optional, Union
11
11
 
12
12
  from stoobly_agent.lib.logger import bcolors, Logger
13
13
  from stoobly_agent.config.constants.custom_headers import MOCK_FIXTURE_PATH
@@ -62,7 +62,7 @@ def eval_fixtures(request: MitmproxyRequest, **options: Options) -> Union[Respon
62
62
  with open(fixture_path, 'rb') as fp:
63
63
  response = Response()
64
64
 
65
- response.status_code = status_code
65
+ response.status_code = int(status_code)
66
66
  response.raw = BytesIO(fp.read())
67
67
  headers[MOCK_FIXTURE_PATH] = fixture_path
68
68
  response.headers = headers
@@ -71,6 +71,11 @@ def eval_fixtures(request: MitmproxyRequest, **options: Options) -> Union[Respon
71
71
  content_type = __guess_content_type(fixture_path)
72
72
  if content_type:
73
73
  response.headers['content-type'] = content_type
74
+ else:
75
+ # Default to highest priority accept header
76
+ content_type = __choose_highest_priority_content_type(request.headers.get('accept'))
77
+ if content_type:
78
+ response.headers['content-type'] = content_type
74
79
 
75
80
  Logger.instance(LOG_ID).debug(f"{bcolors.OKBLUE}Resolved{bcolors.ENDC} fixture {fixture_path}")
76
81
 
@@ -125,6 +130,32 @@ def __eval_response_fixtures(request: MitmproxyRequest, response_fixtures: Fixtu
125
130
  if path:
126
131
  return fixture
127
132
 
133
+ def __choose_highest_priority_content_type(accept_header: str) -> Optional[str]:
134
+ if not accept_header:
135
+ return None
136
+
137
+ types = []
138
+ for part in accept_header.split(","):
139
+ media_range = part.strip()
140
+ if ";" in media_range:
141
+ mime, *params = media_range.split(";")
142
+ q = 1.0 # default
143
+ for param in params:
144
+ param = param.strip()
145
+ if param.startswith("q="):
146
+ try:
147
+ q = float(param[2:])
148
+ except ValueError:
149
+ q = 0.0 # invalid q values treated as lowest
150
+ else:
151
+ mime = media_range
152
+ q = 1.0
153
+ types.append((mime.strip(), q))
154
+
155
+ # Sort by descending q
156
+ types.sort(key=lambda x: -x[1])
157
+ return types[0][0] if types else None
158
+
128
159
  def __parse_accept_header(accept_header):
129
160
  types = []
130
161
  for item in accept_header.split(","):
@@ -2,6 +2,7 @@ import os
2
2
  import pdb
3
3
  import pytest
4
4
  import requests
5
+ import shutil
5
6
 
6
7
  from click.testing import CliRunner
7
8
  from mitmproxy.http import Request as MitmproxyRequest
@@ -156,6 +157,14 @@ class TestEvalFixturesService():
156
157
  assert res != None
157
158
  return res
158
159
 
160
+ @pytest.fixture()
161
+ def public_directory_default_response(self, index_file_path: str, mitmproxy_request: MitmproxyRequest, public_directory: str):
162
+ path = os.path.join(public_directory, 'index')
163
+ shutil.move(index_file_path, path)
164
+ res: requests.Response = eval_fixtures(mitmproxy_request, public_directory_path=public_directory)
165
+ assert res != None
166
+ return res
167
+
159
168
  def test_it_sets_contents(
160
169
  self, public_directory_response: requests.Response, index_file_contents: str
161
170
  ):
@@ -164,5 +173,8 @@ class TestEvalFixturesService():
164
173
  def test_it_headers(self, public_directory_response: requests.Response):
165
174
  assert public_directory_response.headers['Content-Type'] == 'text/html'
166
175
 
167
- def test_it_sets_status_code(self, public_directory_response: requests.Response):
168
- assert public_directory_response.status_code == 200
176
+ def test_it_sets_status_code(self, public_directory_response: requests.Response):
177
+ assert public_directory_response.status_code == 200
178
+
179
+ def test_default_it_headers(self, public_directory_default_response: requests.Response):
180
+ assert public_directory_default_response.headers['Content-Type'] == 'application/json'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: stoobly-agent
3
- Version: 1.9.11
3
+ Version: 1.9.12
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=T0T5meojgC4kb3-HURdzQoFWyRESweACkhTLNw5Rsnk,45
1
+ stoobly_agent/__init__.py,sha256=xENhASdGvBATXYrZA-vmnaCPLgkr7RjAYnjGsnkvbrc,45
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
@@ -52,7 +52,7 @@ stoobly_agent/app/cli/helpers/request_synchronize_handler.py,sha256=wawAL8hoZLqO
52
52
  stoobly_agent/app/cli/helpers/run_command_service.py,sha256=w9CNDZDj_gxCCXAFFOLONuOVu6_W9f8z1RX3-5RKuTM,731
53
53
  stoobly_agent/app/cli/helpers/scenario_facade.py,sha256=nWcycEZBL87OFCCQx85-5QaK0Q9XXk2-RMeC1uef2_Y,3134
54
54
  stoobly_agent/app/cli/helpers/schema_builder.py,sha256=-R_oU_d8nPNdNA31WDp8lCh7XpCeazLm_1dl_Kq8DLU,1127
55
- stoobly_agent/app/cli/helpers/shell.py,sha256=pnztxQjm8kdeVZH40PlTSuiGB_yaSP8PXRS15MoUxtE,838
55
+ stoobly_agent/app/cli/helpers/shell.py,sha256=vnQuv-wvLepcgSIZrz7e4CsL5HuKhAVYfHKF0WuPrgg,633
56
56
  stoobly_agent/app/cli/helpers/synchronize_request_service.py,sha256=pwsILyrR6XPBJAIVaato0tRrbCT4z5-FymJgfeWTsVw,6018
57
57
  stoobly_agent/app/cli/helpers/tabulate_print_service.py,sha256=d4xtJgn9sueL8nAwOSIyiyzuY1ptsD1wxEdLQe0X2tc,964
58
58
  stoobly_agent/app/cli/helpers/test_facade.py,sha256=gRnbjYNxnzPmtvFp2J6TZgxaMSzDjpAWdb79kaFBt_I,2227
@@ -73,7 +73,7 @@ stoobly_agent/app/cli/scaffold/app_config.py,sha256=z4sxZcXZTEoXyUZajUuffuWQN8x8
73
73
  stoobly_agent/app/cli/scaffold/app_create_command.py,sha256=HOlXL6Ugid2qHagqDVGl3ksjLKE4WF_3Dji8FoQlpuM,1215
74
74
  stoobly_agent/app/cli/scaffold/command.py,sha256=G4Zp647cuviaEXUdcl7Rbx_qQAr0Z_DS7-Y3MWDC1Qc,281
75
75
  stoobly_agent/app/cli/scaffold/config.py,sha256=HZU5tkvr3dkPr4JMXZtrJlu2wxxO-134Em6jReFFcq0,688
76
- stoobly_agent/app/cli/scaffold/constants.py,sha256=VuCpzeGxlFEQuX6WEK5D_4ih8-S-iotwOny458K85_c,2612
76
+ stoobly_agent/app/cli/scaffold/constants.py,sha256=8d0YTcPp78mIVOjLeueJkWU6XzC_KxB8ZaU2B-LuDFs,2652
77
77
  stoobly_agent/app/cli/scaffold/containerized_app.py,sha256=dAjn4RwcZV3aEL0POUmrbF_DC-r9h6s1zx7gT2t45v0,175
78
78
  stoobly_agent/app/cli/scaffold/docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
79
  stoobly_agent/app/cli/scaffold/docker/app_builder.py,sha256=7z5pk5JKlRDHx2USxY-WurttLyyUkIVYfl34_u1x9dE,501
@@ -202,10 +202,10 @@ stoobly_agent/app/cli/scaffold/workflow_copy_command.py,sha256=wi8qHH_M2e6jXIPuu
202
202
  stoobly_agent/app/cli/scaffold/workflow_create_command.py,sha256=-fwsr6_LvGT8BbBWdGY3Qd8cSQhBOSJiMr1r8s2R86w,3390
203
203
  stoobly_agent/app/cli/scaffold/workflow_env.py,sha256=shPjoX1SWe7K6pGpZvw2fPVHWd6j_azTe58jvOjGUns,607
204
204
  stoobly_agent/app/cli/scaffold/workflow_log_command.py,sha256=Bke4lMOMxuDUFuAx9nlXHbKgYMO4KAg9ASHvjz4aVWc,1372
205
- stoobly_agent/app/cli/scaffold/workflow_namesapce.py,sha256=DXPCjfY6LAJDHy1ZlKVhVgp2aX97TmQK78lmgzBRN20,968
205
+ stoobly_agent/app/cli/scaffold/workflow_namesapce.py,sha256=VNaZrcqMMeqrzpPGhD9-oaZems1k0ebRc6wR74EvA8c,1170
206
206
  stoobly_agent/app/cli/scaffold/workflow_run_command.py,sha256=H9s0F8LaoB7ZLUVXWP6M6yPLYk5IE4JD8qgGXntwtMc,11138
207
207
  stoobly_agent/app/cli/scaffold/workflow_validate_command.py,sha256=Uo_yo6rVR1ZR7xpvsQvlH48AyMBVLRupd4G-bRjzm_Q,5584
208
- stoobly_agent/app/cli/scaffold_cli.py,sha256=v4b8jCopSbCUv8rpPqqeC-NeziqD8mWbiF3nOZWQ77Y,32598
208
+ stoobly_agent/app/cli/scaffold_cli.py,sha256=F93zXk9WNRLfiDJ-9MpMB4My7gAJJVHDvV_fKPLsxdA,32896
209
209
  stoobly_agent/app/cli/scenario_cli.py,sha256=3J1EiJOvunkfWrEkOsanw-XrKkOk78ij_GjBlE9p7CE,8229
210
210
  stoobly_agent/app/cli/snapshot_cli.py,sha256=1Dw5JgDlmG6vctrawIRO7CdB73vAQk_wRBnPG2lVOrQ,11929
211
211
  stoobly_agent/app/cli/trace_cli.py,sha256=K7E-vx3JUcqEDSWOdIOi_AieKNQz7dBfmRrVvKDkzFI,4605
@@ -331,7 +331,7 @@ stoobly_agent/app/proxy/mitmproxy/response_facade.py,sha256=0wCSzUULUhDDV93QXUgz
331
331
  stoobly_agent/app/proxy/mock/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
332
332
  stoobly_agent/app/proxy/mock/context.py,sha256=vDo5_3WBL73mVFnsmQWvcxvPg5nWtRJbigSrE3zGc-o,794
333
333
  stoobly_agent/app/proxy/mock/custom_not_found_response_builder.py,sha256=0KWB3KFxVrnJOKDaYxm5eoJEccw7IpJZRyUvBX61-8k,697
334
- stoobly_agent/app/proxy/mock/eval_fixtures_service.py,sha256=sVw8l916ouEBj2ViDtHFjgmEA4tLmZGvBfw8wD1Ab-c,4132
334
+ stoobly_agent/app/proxy/mock/eval_fixtures_service.py,sha256=J5CRp_RePD4cHuy0gtXqhA_8GJqXZL0NC0alT9TkjfU,5225
335
335
  stoobly_agent/app/proxy/mock/eval_request_service.py,sha256=A1tcE3wmrC1HwLpz0aRuRw-Nucn0dyHD_yHw5BeQEJU,8146
336
336
  stoobly_agent/app/proxy/mock/hashed_request_decorator.py,sha256=h1ma90fdaYI9LBWpMWMqWBz-RjNwI628O4VuS_uUBX4,5061
337
337
  stoobly_agent/app/proxy/mock/ignored_components_response_builder.py,sha256=E32_E1eSdmPn2SeM_e1jWnqu4xh5w_SnmOs32Shx99E,501
@@ -718,7 +718,7 @@ stoobly_agent/test/app/models/schemas/.stoobly/settings.yml,sha256=vLwMjweKOdod6
718
718
  stoobly_agent/test/app/models/schemas/.stoobly/tmp/options.json,sha256=OTRzarwus48CTrItedXCrgQttJHSEZonEYc7R_knvYg,2212
719
719
  stoobly_agent/test/app/models/schemas/request_test.py,sha256=9SF43KXbjO-vMr2uObPJlyLeop_JQstl6Jrh0M1A70c,1116
720
720
  stoobly_agent/test/app/proxy/mitmproxy/request_facade_test.py,sha256=sXlzjKVvpORJ8fxEs5Qfc4IC0itTWxqDIzMujGjlW7I,5765
721
- stoobly_agent/test/app/proxy/mock/eval_fixtures_service_test.py,sha256=LTn7iWtHyNVqezRfM2Uf_BiK4vFnS3hgoaIdrzjkcPk,5739
721
+ stoobly_agent/test/app/proxy/mock/eval_fixtures_service_test.py,sha256=bPKabyNUEiOV_F3RG6tiLmfc71qEw5SiUfhhdmphUxA,6333
722
722
  stoobly_agent/test/app/proxy/replay/body_parser_service_test.py,sha256=MTC4a3QxrptHzroHAfgrCEzCZ3Ur0Ijyj9_3k-bG0jQ,1228
723
723
  stoobly_agent/test/app/proxy/replay/rewrite_params_service_test.py,sha256=4KVaP48KjCeoZKqY3IdrFAP5Pnb3jO86k8L7ffvz2ZI,3770
724
724
  stoobly_agent/test/app/proxy/replay/trace_context_test.py,sha256=y0oBNC89sp3BG8biOBTiaTopk1LtqjThlA4d6BwAHzM,14462
@@ -753,8 +753,8 @@ stoobly_agent/test/mock_data/scaffold/docker-compose-local-service.yml,sha256=1W
753
753
  stoobly_agent/test/mock_data/scaffold/index.html,sha256=qJwuYajKZ4ihWZrJQ3BNObV5kf1VGnnm_vqlPJzdqLE,258
754
754
  stoobly_agent/test/mock_data/uspto.yaml,sha256=6U5se7C3o-86J4m9xpOk9Npias399f5CbfWzR87WKwE,7835
755
755
  stoobly_agent/test/test_helper.py,sha256=m_oAI7tmRYCNZdKfNqISWhMv3e44tjeYViQ3nTUfnos,1007
756
- stoobly_agent-1.9.11.dist-info/LICENSE,sha256=o93sj12cdoEOsTCjPaPFsw3Xq0SXs3pPcY-9reE2sEw,548
757
- stoobly_agent-1.9.11.dist-info/METADATA,sha256=BhaA2CQUDiNOSEBokPAeKi22VSZyNFl6A8Aqx5oPGUg,3088
758
- stoobly_agent-1.9.11.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
759
- stoobly_agent-1.9.11.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
760
- stoobly_agent-1.9.11.dist-info/RECORD,,
756
+ stoobly_agent-1.9.12.dist-info/LICENSE,sha256=o93sj12cdoEOsTCjPaPFsw3Xq0SXs3pPcY-9reE2sEw,548
757
+ stoobly_agent-1.9.12.dist-info/METADATA,sha256=NZ_3l89VkM5yyJDF7zXVnpiVKWVZeRXdzT54Km0tj8I,3088
758
+ stoobly_agent-1.9.12.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
759
+ stoobly_agent-1.9.12.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
760
+ stoobly_agent-1.9.12.dist-info/RECORD,,