stoobly-agent 1.4.2__py3-none-any.whl → 1.5.0__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.
Files changed (62) hide show
  1. stoobly_agent/__init__.py +1 -1
  2. stoobly_agent/app/cli/helpers/handle_mock_service.py +6 -2
  3. stoobly_agent/app/cli/helpers/request_facade.py +5 -1
  4. stoobly_agent/app/cli/scaffold/constants.py +1 -1
  5. stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py +1 -0
  6. stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py +19 -19
  7. stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context +1 -1
  8. stoobly_agent/app/cli/scaffold/templates/constants.py +3 -3
  9. stoobly_agent/app/cli/scaffold/templates/factory.py +5 -5
  10. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/configure +1 -8
  11. stoobly_agent/app/cli/scaffold/templates/workflow/mock/fixtures.yml +1 -1
  12. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/configure +1 -8
  13. stoobly_agent/app/cli/scaffold/templates/workflow/test/fixtures.yml +1 -1
  14. stoobly_agent/app/cli/scaffold/workflow_command.py +3 -3
  15. stoobly_agent/app/cli/scaffold/workflow_create_command.py +2 -2
  16. stoobly_agent/app/cli/scaffold_cli.py +5 -5
  17. stoobly_agent/app/proxy/context.py +4 -0
  18. stoobly_agent/app/proxy/handle_mock_service.py +81 -54
  19. stoobly_agent/app/proxy/handle_record_service.py +15 -3
  20. stoobly_agent/app/proxy/handle_replay_service.py +44 -18
  21. stoobly_agent/app/proxy/handle_test_service.py +75 -16
  22. stoobly_agent/app/proxy/intercept_handler.py +11 -16
  23. stoobly_agent/app/proxy/intercept_settings.py +17 -4
  24. stoobly_agent/app/proxy/mitmproxy/request_facade.py +5 -2
  25. stoobly_agent/app/proxy/mitmproxy/response_facade.py +5 -4
  26. stoobly_agent/app/proxy/mock/eval_fixtures_service.py +78 -14
  27. stoobly_agent/app/proxy/mock/eval_request_service.py +2 -2
  28. stoobly_agent/app/proxy/record/join_request_service.py +7 -8
  29. stoobly_agent/app/proxy/record/upload_request_service.py +2 -2
  30. stoobly_agent/app/proxy/replay/replay_request_service.py +4 -4
  31. stoobly_agent/app/proxy/test/helpers/upload_test_service.py +2 -2
  32. stoobly_agent/app/proxy/utils/allowed_request_service.py +3 -3
  33. stoobly_agent/app/proxy/utils/response_handler.py +0 -2
  34. stoobly_agent/app/proxy/utils/rewrite.py +72 -0
  35. stoobly_agent/app/settings/constants/request_component.py +4 -1
  36. stoobly_agent/cli.py +35 -28
  37. stoobly_agent/config/constants/intercept_policy.py +2 -0
  38. stoobly_agent/config/constants/mock_policy.py +4 -2
  39. stoobly_agent/config/constants/record_policy.py +4 -2
  40. stoobly_agent/config/constants/replay_policy.py +4 -2
  41. stoobly_agent/public/{18-es2015.583f191cc7ad512ee262.js → 18-es2015.503207073756a9c8211a.js} +1 -1
  42. stoobly_agent/public/{18-es5.583f191cc7ad512ee262.js → 18-es5.503207073756a9c8211a.js} +1 -1
  43. stoobly_agent/public/index.html +1 -1
  44. stoobly_agent/public/{main-es2015.2cc16523aa3fcaba51e5.js → main-es2015.d682619f3d6d53d64c6a.js} +1 -1
  45. stoobly_agent/public/{main-es5.2cc16523aa3fcaba51e5.js → main-es5.d682619f3d6d53d64c6a.js} +1 -1
  46. stoobly_agent/public/{runtime-es2015.b914470164e4d6e75d96.js → runtime-es2015.8c1efed946fc02c923fc.js} +1 -1
  47. stoobly_agent/public/{runtime-es5.b914470164e4d6e75d96.js → runtime-es5.8c1efed946fc02c923fc.js} +1 -1
  48. stoobly_agent/test/app/cli/helpers/openapi_endpoint_adapter_test.py +2 -1
  49. stoobly_agent/test/app/cli/scaffold/e2e_test.py +2 -2
  50. stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION +1 -1
  51. stoobly_agent/test/app/proxy/mock/eval_fixtures_service_test.py +140 -71
  52. stoobly_agent/test/cli/lifecycle_hooks_test.py +66 -0
  53. stoobly_agent/test/cli/mock_test.py +53 -29
  54. stoobly_agent/test/cli/record_test.py +67 -0
  55. stoobly_agent/test/mock_data/lifecycle_hooks.py +35 -0
  56. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.0.dist-info}/LICENSE +1 -1
  57. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.0.dist-info}/METADATA +7 -12
  58. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.0.dist-info}/RECORD +62 -58
  59. /stoobly_agent/app/cli/scaffold/templates/workflow/mock/{fixtures/.keep → public/.gitignore} +0 -0
  60. /stoobly_agent/app/cli/scaffold/templates/workflow/test/{fixtures/.keep → public/.gitignore} +0 -0
  61. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.0.dist-info}/WHEEL +0 -0
  62. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.0.dist-info}/entry_points.txt +0 -0
stoobly_agent/cli.py CHANGED
@@ -159,6 +159,7 @@ def run(**kwargs):
159
159
  @click.option('--format', type=click.Choice([RAW_FORMAT]), help='Format response')
160
160
  @click.option('-H', '--header', multiple=True, help='Pass custom header(s) to server')
161
161
  @click.option('--lifecycle-hooks-path', help='Path to lifecycle hooks script.')
162
+ @click.option('-o', '--output', help='Write to file instead of stdout')
162
163
  @ConditionalDecorator(lambda f: click.option('--project-key')(f), is_remote)
163
164
  @click.option('--public-directory-path', help='Path to public files. Used for mocking requests.')
164
165
  @click.option('--response-fixtures-path', help='Path to response fixtures yaml. Used for mocking requests.')
@@ -169,16 +170,7 @@ def mock(**kwargs):
169
170
  if kwargs.get('remote_project_key'):
170
171
  validate_project_key(kwargs['remote_project_key'])
171
172
 
172
- if kwargs.get('scenario_key'):
173
- validate_scenario_key(kwargs['scenario_key'])
174
-
175
- request = __build_request_from_curl(**kwargs)
176
-
177
- context = ReplayContext.from_python_request(request)
178
- response: requests.Response = replay_request(context, {
179
- **kwargs,
180
- 'mode': mode.MOCK,
181
- })
173
+ response = __replay(mode.MOCK, **kwargs)
182
174
 
183
175
  if response.status_code == custom_response_codes.NOT_FOUND:
184
176
  content = response.content
@@ -186,10 +178,15 @@ def mock(**kwargs):
186
178
  sys.exit(1)
187
179
 
188
180
  if kwargs['format'] == RAW_FORMAT:
189
- print_raw_response(response)
181
+ print_raw_response(response, kwargs['output'])
190
182
  else:
191
183
  content = response.content
192
- print(decode(content), end='')
184
+
185
+ if not kwargs['output']:
186
+ print(decode(content), end='')
187
+ else:
188
+ with open(kwargs['output'], 'w') as fp:
189
+ fp.write(decode(content))
193
190
 
194
191
  @main.command(
195
192
  help="Record request"
@@ -197,30 +194,28 @@ def mock(**kwargs):
197
194
  @click.option('-d', '--data', default='', help='HTTP POST data')
198
195
  @click.option('--format', type=click.Choice([RAW_FORMAT]), help='Format response')
199
196
  @click.option('-H', '--header', multiple=True, help='Pass custom header(s) to server')
197
+ @click.option('--lifecycle-hooks-path', help='Path to lifecycle hooks script.')
198
+ @click.option('-o', '--output', help='Write to file instead of stdout')
200
199
  @ConditionalDecorator(lambda f: click.option('--project-key')(f), is_remote)
201
200
  @click.option('-X', '--request', default='GET', help='Specify request command to use')
202
201
  @click.option('--scenario-key')
203
202
  @click.argument('url')
204
203
  def record(**kwargs):
205
- if kwargs.get('scenario_key'):
206
- validate_scenario_key(kwargs['scenario_key'])
207
-
208
- request = __build_request_from_curl(**kwargs)
209
-
210
- context = ReplayContext.from_python_request(request)
211
- response: requests.Response = replay_request(context, {
212
- **kwargs,
213
- 'mode': mode.RECORD,
214
- })
204
+ response = __replay(mode.RECORD, **kwargs)
215
205
 
216
206
  if kwargs['format'] == RAW_FORMAT:
217
- print_raw_response(response)
207
+ print_raw_response(response, kwargs['output'])
218
208
  else:
219
- try:
220
- content = response.raw.data
221
- print(content.decode(json.detect_encoding(content)), end='')
222
- except UnicodeDecodeError:
223
- print('Warning: Binary output can mess up your terminal.')
209
+ content: bytes = response.raw.data
210
+
211
+ if not kwargs['output']:
212
+ try:
213
+ print(content.decode(json.detect_encoding(content)), end='')
214
+ except UnicodeDecodeError:
215
+ print('Warning: Binary output can mess up your terminal.')
216
+ else:
217
+ with open(kwargs['output'], 'w') as fp:
218
+ fp.write(content.decode(json.detect_encoding(content)))
224
219
 
225
220
  def __build_request_from_curl(**kwargs):
226
221
  headers = {}
@@ -238,3 +233,15 @@ def __build_request_from_curl(**kwargs):
238
233
  method=kwargs['request'],
239
234
  url=kwargs['url']
240
235
  )
236
+
237
+ def __replay(mode, **kwargs):
238
+ if kwargs.get('scenario_key'):
239
+ validate_scenario_key(kwargs['scenario_key'])
240
+
241
+ request = __build_request_from_curl(**kwargs)
242
+
243
+ context = ReplayContext.from_python_request(request)
244
+ return replay_request(context, {
245
+ **kwargs,
246
+ 'mode': mode,
247
+ })
@@ -0,0 +1,2 @@
1
+ ALL = 'all'
2
+ NONE = 'none'
@@ -1,3 +1,5 @@
1
- ALL = 'all'
2
- NONE = 'none'
1
+ from .intercept_policy import ALL as INTERCEPT_ALL, NONE as INTERCEPT_NONE
2
+
3
+ ALL = INTERCEPT_ALL
4
+ NONE = INTERCEPT_NONE
3
5
  FOUND = 'found'
@@ -1,5 +1,7 @@
1
- ALL = 'all'
1
+ from .intercept_policy import ALL as INTERCEPT_ALL, NONE as INTERCEPT_NONE
2
+
3
+ ALL = INTERCEPT_ALL
2
4
  FOUND = 'found'
3
- NONE = 'none'
5
+ NONE = INTERCEPT_NONE
4
6
  NOT_FOUND = 'not_found'
5
7
  OVERWRITE = 'overwrite'
@@ -1,2 +1,4 @@
1
- ALL = 'all'
2
- NONE = 'none'
1
+ from .intercept_policy import ALL as INTERCEPT_ALL, NONE as INTERCEPT_NONE
2
+
3
+ ALL = INTERCEPT_ALL
4
+ NONE = INTERCEPT_NONE