stoobly-agent 1.9.0__py3-none-any.whl → 1.9.1__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.0'
2
+ VERSION = '1.9.1'
@@ -8,6 +8,7 @@ from stoobly_agent.config.data_dir import DataDir
8
8
  from stoobly_agent.lib.logger import bcolors, Logger
9
9
 
10
10
  from .log_event import LogEvent
11
+ from .request_snapshot import RequestSnapshot
11
12
  from .snapshot_types import DELETE_ACTION, PUT_ACTION, Resource
12
13
 
13
14
  EVENT_DELIMITTER = "\n"
@@ -67,6 +68,25 @@ class Log():
67
68
  contents = self.read()
68
69
  return self.build_raw_events(contents)
69
70
 
71
+ @property
72
+ def scenario_inverted_index(self):
73
+ index = {}
74
+
75
+ def handle_snapshot(snapshot: RequestSnapshot):
76
+ request_uuid = snapshot.uuid
77
+ if not request_uuid in index:
78
+ index[request_uuid] = []
79
+
80
+ index[request_uuid].append(event.resource_uuid)
81
+
82
+ for event in self.target_events:
83
+ if not event.is_scenario():
84
+ continue
85
+
86
+ event.snapshot().iter_request_snapshots(handle_snapshot)
87
+
88
+ return index
89
+
70
90
  @property
71
91
  def unprocessed_events(self) -> List[LogEvent]:
72
92
  events = self.events
@@ -197,12 +217,18 @@ class Log():
197
217
 
198
218
  resource_index[event.resource_uuid].append(event)
199
219
 
220
+ scenario_inverted_index = self.scenario_inverted_index
221
+
200
222
  pruned_events = self.collapse(events)
201
223
  for event in pruned_events:
202
224
  snapshot = event.snapshot()
203
225
  snapshot_exists = snapshot.exists
204
226
 
205
227
  if event.action == DELETE_ACTION or not snapshot_exists:
228
+ if event.is_request() and event.resource_uuid in scenario_inverted_index:
229
+ # If a request is deleted, only prune if it's not also a part of a scenario
230
+ continue
231
+
206
232
  Logger.instance(LOG_ID).info(f"{bcolors.OKBLUE}Removing{bcolors.ENDC} {event.resource} {event.resource_uuid}")
207
233
 
208
234
  resource_events: List[LogEvent] = resource_index[event.resource_uuid]
@@ -218,8 +244,16 @@ class Log():
218
244
  removed_events[event.uuid] = True
219
245
 
220
246
  if event.action == DELETE_ACTION and snapshot_exists:
221
- if not dry_run:
247
+ if dry_run:
248
+ continue
249
+
250
+ if event.is_scenario():
251
+ # We still need to check each request in a scenario to make sure another scenario does not depend on it
252
+ snapshot.remove(lambda snapshot: self.remove_request_snapshot(snapshot, scenario_inverted_index))
253
+ elif event.is_request():
254
+ # We have already checked that a scenario does not depend on the request above
222
255
  snapshot.remove()
256
+
223
257
  Logger.instance(LOG_ID).info(f"Removing {event.resource} snapshot")
224
258
 
225
259
  def build_raw_events(self, contents: str) -> List[str]:
@@ -242,6 +276,8 @@ class Log():
242
276
  '''
243
277
  Remove DELETE events where the last processed event was a PUT
244
278
  '''
279
+
280
+ # Build an index such that if the last event is DELETE_ACTION, then it will NOT exist in the index
245
281
  index = {}
246
282
  for event in processed_events:
247
283
  if event.action == PUT_ACTION:
@@ -249,10 +285,18 @@ class Log():
249
285
  elif event.action == DELETE_ACTION:
250
286
  if event.resource_uuid in index:
251
287
  del index[event.resource_uuid]
288
+
289
+ scenario_inverted_index = self.scenario_inverted_index
290
+
291
+ def keep(e: LogEvent):
292
+ if e.action != DELETE_ACTION:
293
+ return True
294
+
295
+ return e.action == DELETE_ACTION and e.is_request() and e.resource_uuid in scenario_inverted_index
252
296
 
253
297
  return list(
254
298
  filter(
255
- lambda e: e.action != DELETE_ACTION or (e.action == DELETE_ACTION and e.resource_uuid in index),
299
+ keep,
256
300
  unprocessed_events
257
301
  )
258
302
  )
@@ -289,6 +333,12 @@ class Log():
289
333
  remaining_events = self.remove_dangling_events(processed_events, unprocessed_events)
290
334
  return list(filter(lambda e: e.uuid not in remaining_version_uuids, remaining_events))
291
335
 
336
+ def remove_request_snapshot(self, snapshot: RequestSnapshot, scenario_inverted_index: dict = None):
337
+ scenario_inverted_index = scenario_inverted_index or self.scenario_inverted_index
338
+
339
+ if snapshot.uuid not in scenario_inverted_index:
340
+ snapshot.remove()
341
+
292
342
  # Rotate log to history
293
343
  def rotate(self):
294
344
  if not os.path.exists(self.__log_file_path):
@@ -1,5 +1,4 @@
1
1
  import os
2
- import shutil
3
2
 
4
3
  from stoobly_agent.app.models.adapters.orm import JoinedRequestStringAdapter
5
4
  from stoobly_agent.lib.orm.request import Request
@@ -1,7 +1,6 @@
1
1
  import json
2
2
  import os
3
3
  import pdb
4
- import shutil
5
4
 
6
5
  from typing import Callable, List
7
6
 
@@ -128,12 +127,12 @@ class ScenarioSnapshot(Snapshot):
128
127
  if os.path.exists(metadata_file_path):
129
128
  os.remove(metadata_file_path)
130
129
 
131
- def remove_requests(self):
130
+ def remove_requests(self, handle_remove_request_snapshot = None):
132
131
  requests_file_path = self.requests_path
133
132
 
134
133
  if os.path.exists(requests_file_path):
135
134
  # A request only every belongs to one scenario
136
- self.iter_request_snapshots(self.__handle_remove_requests)
135
+ self.iter_request_snapshots(handle_remove_request_snapshot or self.__handle_remove_requests)
137
136
 
138
137
  os.remove(requests_file_path)
139
138
 
@@ -14,15 +14,17 @@ def snapshot_request(request: Request, **options: RequestSnapshotOptions):
14
14
  return
15
15
 
16
16
  snapshot = RequestSnapshot(request.uuid)
17
-
18
17
  snapshot.backup()
19
18
 
19
+ log = Log()
20
+
20
21
  if action == PUT_ACTION:
21
22
  snapshot.write(request, **options)
22
23
  elif action == DELETE_ACTION:
23
- snapshot.remove()
24
+ inverted_scenario_index = log.scenario_inverted_index
24
25
 
25
- log = Log()
26
+ # If a scenario currently depends on this request, we can't remove the snapshot until the scenario is also removed
27
+ log.remove_request_snapshot(snapshot, inverted_scenario_index)
26
28
 
27
29
  try:
28
30
  if action == PUT_ACTION:
@@ -40,7 +42,6 @@ def snapshot_scenario(scenario: Scenario, **options):
40
42
  return
41
43
 
42
44
  snapshot = ScenarioSnapshot(scenario.uuid)
43
-
44
45
  snapshot.backup_metadata()
45
46
 
46
47
  if action == PUT_ACTION:
@@ -50,13 +51,13 @@ def snapshot_scenario(scenario: Scenario, **options):
50
51
 
51
52
  snapshot.backup_requests()
52
53
 
54
+ log = Log()
55
+ inverted_scenario_index = log.scenario_inverted_index
53
56
  if action == PUT_ACTION:
54
- snapshot.remove_requests()
57
+ snapshot.remove_requests(lambda snapshot: log.remove_request_snapshot(snapshot, inverted_scenario_index))
55
58
  snapshot.write_requests(scenario, **options)
56
59
  elif action == DELETE_ACTION:
57
- snapshot.remove_requests()
58
-
59
- log = Log()
60
+ snapshot.remove_requests(lambda snapshot: log.remove_request_snapshot(snapshot, inverted_scenario_index))
60
61
 
61
62
  if action == PUT_ACTION:
62
63
  log.put(scenario)
@@ -1,5 +1,7 @@
1
1
  import pdb
2
2
 
3
+ from typing import List
4
+
3
5
  from stoobly_agent.app.models.factories.resource.local_db.helpers.log import Log
4
6
  from stoobly_agent.app.models.factories.resource.local_db.helpers.request_snapshot import RequestSnapshot
5
7
  from stoobly_agent.app.models.factories.resource.local_db.helpers.scenario_snapshot import ScenarioSnapshot
@@ -71,6 +73,7 @@ class Apply():
71
73
  if results:
72
74
  status = results[1]
73
75
  if status == 0 or status >= 400:
76
+ self.__logger(f"{bcolors.FAIL}Error{bcolors.ENDC} {results[0]}")
74
77
  completed = False
75
78
  break
76
79
 
@@ -218,14 +221,16 @@ class Apply():
218
221
 
219
222
  snapshot_requests = {}
220
223
 
221
- request_snapshots = snapshot.request_snapshots
224
+ request_snapshots: List[RequestSnapshot] = snapshot.request_snapshots
222
225
  for request_snapshot in request_snapshots:
223
226
  raw_request = request_snapshot.request
224
-
225
- toks = raw_request.split(REQUEST_STRING_CLRF, 1)
226
227
 
228
+ if not raw_request:
229
+ return f"{request_snapshot.path} is missing", 400
230
+
231
+ toks = raw_request.split(REQUEST_STRING_CLRF, 1)
227
232
  if len(toks) != 2:
228
- return f"{snapshot.requests_path} contains an invalid request", 400
233
+ return f"{request_snapshot.path} contains an invalid request", 400
229
234
 
230
235
  uuid = request_snapshot.uuid
231
236
  res, status = self.__put_request(uuid, raw_request, scenario_id=scenario['id'])
@@ -547,4 +547,146 @@ class TestApply():
547
547
  recreated_scenario = Scenario.find_by(uuid=created_scenario.uuid)
548
548
  assert recreated_scenario
549
549
 
550
- assert len(recreated_scenario.requests) == 0
550
+ assert len(recreated_scenario.requests) == 0
551
+
552
+ class TestWhenDeletingRequestWhileReferenced():
553
+
554
+ class TestWhenRemoveScenarioRequest():
555
+ '''
556
+ 1. Create scenario
557
+ 2. Add 2 requests to it
558
+ 3. Snapshot scenario
559
+ 4. Snapshot requests with action DELETE_ACTION
560
+ 5. Apply
561
+ 6. Expect scenario to have 1 request
562
+ '''
563
+
564
+ @pytest.fixture(scope='class')
565
+ def created_scenario(self, runner: CliRunner):
566
+ create_result = runner.invoke(scenario, ['create', 'test'])
567
+ assert create_result.exit_code == 0
568
+ return Scenario.last()
569
+
570
+ @pytest.fixture(scope='class', autouse=True)
571
+ def created_scenario_requests(self, runner: CliRunner, created_scenario: Scenario):
572
+ record_result = runner.invoke(record, ['--scenario-key', created_scenario.key(), DETERMINISTIC_GET_REQUEST_URL])
573
+ assert record_result.exit_code == 0
574
+
575
+ record_result = runner.invoke(record, ['--scenario-key', created_scenario.key(), NON_DETERMINISTIC_GET_REQUEST_URL])
576
+ assert record_result.exit_code == 0
577
+
578
+ return created_scenario.requests
579
+
580
+ @pytest.fixture(scope='class', autouse=True)
581
+ def delete_event(self, runner: CliRunner, created_scenario: Scenario, created_scenario_requests: List[Request]):
582
+ snapshot_result = runner.invoke(scenario, ['snapshot', created_scenario.key()])
583
+ assert snapshot_result.exit_code == 0
584
+
585
+ time.sleep(0.5) # So events do not have the same uuid
586
+
587
+ created_request = created_scenario_requests[1]
588
+ snapshot_result = runner.invoke(request, ['snapshot', created_request.key(), '--action', DELETE_ACTION])
589
+ assert snapshot_result.exit_code == 0
590
+
591
+ log = Log()
592
+ events = log.events
593
+ return events[len(events) - 1]
594
+
595
+ @pytest.fixture(scope='class')
596
+ def apply_result(self, runner: CliRunner, created_scenario: Scenario):
597
+ created_scenario = Scenario.find(created_scenario.id)
598
+ assert created_scenario.requests_count == 2
599
+ apply_result = runner.invoke(snapshot, ['apply'])
600
+
601
+ return apply_result
602
+
603
+ def test_it_updates_scenario(self, created_scenario: Scenario, apply_result):
604
+ assert apply_result.exit_code == 0
605
+
606
+ created_scenario = Scenario.find(created_scenario.id)
607
+ assert created_scenario.requests_count == 1
608
+
609
+ def test_it_maintains_requests(self, created_scenario: Scenario, created_scenario_requests: List[Request]):
610
+ created_scenario = Scenario.find(created_scenario.id)
611
+ assert len(created_scenario.requests) == 1
612
+
613
+ requests = created_scenario.requests
614
+
615
+ assert_orm_request_equivalent(requests[0], created_scenario_requests[0])
616
+
617
+ class TestWhenMovingScenarioRequest():
618
+ '''
619
+ 1. Create scenario one and scenario two
620
+ 2. Add 1 request to scenario one
621
+ 3. Snapshot scenario one
622
+ 4. Move scenario one request to scenario two
623
+ 5. Snapshot scenario two
624
+ 5. Apply
625
+ 6. Expect scenario one to have 0 requests
626
+ 7. Expect scenario two to have 1 request
627
+ '''
628
+
629
+ @pytest.fixture(scope='class')
630
+ def created_scenario_one(self, runner: CliRunner):
631
+ create_result = runner.invoke(scenario, ['create', 'test1'])
632
+ assert create_result.exit_code == 0
633
+ return Scenario.last()
634
+
635
+ @pytest.fixture(scope='class')
636
+ def created_scenario_two(self, runner: CliRunner):
637
+ create_result = runner.invoke(scenario, ['create', 'test2'])
638
+ assert create_result.exit_code == 0
639
+ return Scenario.last()
640
+
641
+ @pytest.fixture(scope='class', autouse=True)
642
+ def created_scenario_request(self, runner: CliRunner, created_scenario_one: Scenario):
643
+ record_result = runner.invoke(record, ['--scenario-key', created_scenario_one.key(), DETERMINISTIC_GET_REQUEST_URL])
644
+ assert record_result.exit_code == 0
645
+
646
+ return created_scenario_one.requests[0]
647
+
648
+ @pytest.fixture(scope='class', autouse=True)
649
+ def put_event_one(self, runner: CliRunner, created_scenario_one: Scenario, created_scenario_request: Request):
650
+ snapshot_result = runner.invoke(scenario, ['snapshot', created_scenario_one.key()])
651
+ assert snapshot_result.exit_code == 0
652
+
653
+ log = Log()
654
+ events = log.events
655
+ return events[len(events) - 1]
656
+
657
+ @pytest.fixture(scope='class', autouse=True)
658
+ def put_event_two(self, runner: CliRunner, created_scenario_two: Scenario, created_scenario_request: Request):
659
+ created_scenario_request.update(scenario_id=created_scenario_two.id)
660
+
661
+ snapshot_result = runner.invoke(scenario, ['snapshot', created_scenario_two.key()])
662
+ assert snapshot_result.exit_code == 0
663
+
664
+ log = Log()
665
+ events = log.events
666
+ return events[len(events) - 1]
667
+
668
+ @pytest.fixture(scope='class')
669
+ def apply_result(self, runner: CliRunner):
670
+ apply_result = runner.invoke(snapshot, ['apply'])
671
+
672
+ return apply_result
673
+
674
+ def test_it_removes_request_from_scenario_one(self, created_scenario_one: Scenario, apply_result):
675
+ assert apply_result.exit_code == 0
676
+
677
+ created_scenario_one = Scenario.find(created_scenario_one.id)
678
+ assert created_scenario_one.requests_count == 0
679
+
680
+ def test_it_adds_request_to_scenario_two(self, created_scenario_two: Scenario, apply_result):
681
+ assert apply_result.exit_code == 0
682
+
683
+ created_scenario_two = Scenario.find(created_scenario_two.id)
684
+ assert created_scenario_two.requests_count == 1
685
+
686
+ def test_it_maintains_requests(self, created_scenario_two: Scenario, created_scenario_request):
687
+ created_scenario_two = Scenario.find(created_scenario_two.id)
688
+ assert len(created_scenario_two.requests) == 1
689
+
690
+ requests = created_scenario_two.requests
691
+
692
+ assert_orm_request_equivalent(requests[0], created_scenario_request)
@@ -3,12 +3,14 @@ import pytest
3
3
  import time
4
4
 
5
5
  from click.testing import CliRunner
6
+ from typing import List
6
7
 
7
8
  from stoobly_agent.app.models.factories.resource.local_db.helpers.log import Log
8
9
  from stoobly_agent.app.models.factories.resource.local_db.helpers.log_event import DELETE_ACTION, LogEvent
9
- from stoobly_agent.cli import record, request, snapshot
10
+ from stoobly_agent.cli import record, request, scenario, snapshot
10
11
  from stoobly_agent.lib.orm.request import Request
11
- from stoobly_agent.test.test_helper import DETERMINISTIC_GET_REQUEST_URL, reset
12
+ from stoobly_agent.lib.orm.scenario import Scenario
13
+ from stoobly_agent.test.test_helper import assert_orm_request_equivalent, DETERMINISTIC_GET_REQUEST_URL, NON_DETERMINISTIC_GET_REQUEST_URL, reset
12
14
 
13
15
  @pytest.fixture(scope='module')
14
16
  def runner():
@@ -107,4 +109,71 @@ class TestPrune():
107
109
 
108
110
  apply_result = runner.invoke(snapshot, ['prune'])
109
111
  assert apply_result.exit_code == 0
110
- assert len(log.events) == 0
112
+ assert len(log.events) == 0
113
+
114
+ class TestWhenRemoveScenarioRequest():
115
+ '''
116
+ 1. Create scenario
117
+ 2. Add 2 requests to it
118
+ 3. Snapshot scenario
119
+ 4. Snapshot request with action DELETE_ACTION
120
+ 5. Prune, but because scenario depends on the request, should not be able to prune
121
+ 6. Apply
122
+ 7. Expect scenario to have 1 request
123
+ '''
124
+
125
+ @pytest.fixture(scope='class')
126
+ def created_scenario(self, runner: CliRunner):
127
+ create_result = runner.invoke(scenario, ['create', 'test'])
128
+ assert create_result.exit_code == 0
129
+ return Scenario.last()
130
+
131
+ @pytest.fixture(scope='class', autouse=True)
132
+ def created_scenario_requests(self, runner: CliRunner, created_scenario: Scenario):
133
+ record_result = runner.invoke(record, ['--scenario-key', created_scenario.key(), DETERMINISTIC_GET_REQUEST_URL])
134
+ assert record_result.exit_code == 0
135
+
136
+ record_result = runner.invoke(record, ['--scenario-key', created_scenario.key(), NON_DETERMINISTIC_GET_REQUEST_URL])
137
+ assert record_result.exit_code == 0
138
+
139
+ return created_scenario.requests
140
+
141
+ @pytest.fixture(scope='class', autouse=True)
142
+ def delete_event(self, runner: CliRunner, created_scenario: Scenario, created_scenario_requests: List[Request]):
143
+ snapshot_result = runner.invoke(scenario, ['snapshot', created_scenario.key()])
144
+ assert snapshot_result.exit_code == 0
145
+
146
+ time.sleep(0.5) # So events do not have the same uuid
147
+
148
+ created_request = created_scenario_requests[1]
149
+ snapshot_result = runner.invoke(request, ['snapshot', created_request.key(), '--action', DELETE_ACTION])
150
+ assert snapshot_result.exit_code == 0
151
+
152
+ log = Log()
153
+ events = log.events
154
+ return events[len(events) - 1]
155
+
156
+ @pytest.fixture(scope='class')
157
+ def apply_result(self, runner: CliRunner, created_scenario: Scenario):
158
+ prune_result = runner.invoke(snapshot, ['prune'])
159
+ assert prune_result.exit_code == 0
160
+
161
+ created_scenario = Scenario.find(created_scenario.id)
162
+ assert created_scenario.requests_count == 2
163
+ apply_result = runner.invoke(snapshot, ['apply'])
164
+
165
+ return apply_result
166
+
167
+ def test_it_updates_scenario(self, created_scenario: Scenario, apply_result):
168
+ assert apply_result.exit_code == 0
169
+
170
+ created_scenario = Scenario.find(created_scenario.id)
171
+ assert created_scenario.requests_count == 1
172
+
173
+ def test_it_maintains_requests(self, created_scenario: Scenario, created_scenario_requests: List[Request]):
174
+ created_scenario = Scenario.find(created_scenario.id)
175
+ assert len(created_scenario.requests) == 1
176
+
177
+ requests = created_scenario.requests
178
+
179
+ assert_orm_request_equivalent(requests[0], created_scenario_requests[0])
@@ -1 +1 @@
1
- 1.8.5
1
+ 1.9.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: stoobly-agent
3
- Version: 1.9.0
3
+ Version: 1.9.1
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=1zUUaHVU-BNUei6lrNgI-2kwbJnFfizP496P_Xekrwo,44
1
+ stoobly_agent/__init__.py,sha256=ehByLp1z2dzieXsaNQLADxDog0UyQfS9wSZ3n9PqZNs,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
@@ -258,14 +258,14 @@ stoobly_agent/app/models/factories/resource/local_db/body_adapter.py,sha256=lrnI
258
258
  stoobly_agent/app/models/factories/resource/local_db/header_adapter.py,sha256=NQdCErFtJL7sBaLpKLYfJSEA3AiaaVuU7LUcGJ-dHOI,3104
259
259
  stoobly_agent/app/models/factories/resource/local_db/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
260
260
  stoobly_agent/app/models/factories/resource/local_db/helpers/create_request_columns_service.py,sha256=HABMelW-cvhm2WXaywbQcd4PQhzSrz4vAbN7uOdetXM,1541
261
- stoobly_agent/app/models/factories/resource/local_db/helpers/log.py,sha256=0a3XRfrnbChCVrGpm5gqSlZ3zVK1S7nbWYwXTJawx58,9216
261
+ stoobly_agent/app/models/factories/resource/local_db/helpers/log.py,sha256=T0PCrMX2s7PMwZSMdr436PzNa0QQTCBDBshosgZ24BI,10899
262
262
  stoobly_agent/app/models/factories/resource/local_db/helpers/log_event.py,sha256=30wWhqibTWgnpibosclaB9OCWzArL7R4krGS8WW2bGY,3584
263
263
  stoobly_agent/app/models/factories/resource/local_db/helpers/request_builder.py,sha256=PyVvsYmi5bBQ6PsUPxQ4nJM9rhhjGVOTd7ipuc2tMMM,3227
264
- stoobly_agent/app/models/factories/resource/local_db/helpers/request_snapshot.py,sha256=XvUAqa9icAUPmktcAt30VnQspJVQZhA1K5n6ZVMRZIk,2686
265
- stoobly_agent/app/models/factories/resource/local_db/helpers/scenario_snapshot.py,sha256=mv_79PgvG6Q7rwYXdV0wZMneb4eC_PPjBk612cQPLqo,4914
264
+ stoobly_agent/app/models/factories/resource/local_db/helpers/request_snapshot.py,sha256=Tpuu7sZ4A2Vc5e5OAyU9pSKzbOpLpZoI-4E2Ty7n4Ac,2672
265
+ stoobly_agent/app/models/factories/resource/local_db/helpers/scenario_snapshot.py,sha256=f5psNwbl_mXF8rLNogqgfiHJudu2C9N9F35DZ_zgn6o,4973
266
266
  stoobly_agent/app/models/factories/resource/local_db/helpers/search.py,sha256=A7KVcmxj9c3CT2rh26YH6khiEPkB_4U1UHhiYelNaws,782
267
267
  stoobly_agent/app/models/factories/resource/local_db/helpers/snapshot.py,sha256=_8WPNE2NnvLlDbqnCfgnQveppDWfFZnqCBcX6THb1AU,742
268
- stoobly_agent/app/models/factories/resource/local_db/helpers/snapshot_service.py,sha256=fbqh5J5sMj0n_YFQFei2xhXLrSGU9vNmSX_uifA3U3M,1671
268
+ stoobly_agent/app/models/factories/resource/local_db/helpers/snapshot_service.py,sha256=szL70Vubqg2JbxZ-rnlrxiqEgyPIcKAO9SsyyFxQ6ow,2106
269
269
  stoobly_agent/app/models/factories/resource/local_db/helpers/snapshot_types.py,sha256=1pX0jrg13632g_yv_sF1ABzPR7LY7r2HC9g1a5zR1qI,379
270
270
  stoobly_agent/app/models/factories/resource/local_db/helpers/tiebreak_scenario_request.py,sha256=BajElzsTE115hWBT6v67eyNFnrHGz-sU6WBNCzWp7Fg,1237
271
271
  stoobly_agent/app/models/factories/resource/local_db/local_db_adapter.py,sha256=Zeem6abkSHXRXTvE3XwzOkUY6fbNm9wocPP2qSX3zQ8,1439
@@ -287,7 +287,7 @@ stoobly_agent/app/models/factories/resource/stoobly/request_adapter.py,sha256=Zr
287
287
  stoobly_agent/app/models/factories/resource/stoobly/scenario_adapter.py,sha256=HnM4g5Qdv16QXj8u4JCiJm2Dbw9OhAxmn9e_R8oaHG4,1105
288
288
  stoobly_agent/app/models/header_model.py,sha256=m91upRZr8GfE5um0d5dguUESKigBMWhSyu_X3HFk28Y,1406
289
289
  stoobly_agent/app/models/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
290
- stoobly_agent/app/models/helpers/apply.py,sha256=SQ5uBn2qGEaVIbgUVFWeTyqPg_wJVBjRte9-A6DTvzY,8293
290
+ stoobly_agent/app/models/helpers/apply.py,sha256=ev8QmDvV7flFo82JUA6kBkofYCJ_lNXQGVIpknB94g8,8501
291
291
  stoobly_agent/app/models/helpers/create_request_params_service.py,sha256=o_VB2FsTGBX55UBBw1yQ8MtsJ4-0YXcxd4kNQ9l21nM,2070
292
292
  stoobly_agent/app/models/model.py,sha256=77ZTByQmH5sWBcSrCF3kG_C4muHggcFyH1DWsOhIgvg,1180
293
293
  stoobly_agent/app/models/query_param_model.py,sha256=EBj76phSJ9_45KgP0vIZGbkkG6-tSn_U1fNW_7qLy_4,1455
@@ -688,10 +688,10 @@ stoobly_agent/test/app/cli/scenario/scenario_reset_test.py,sha256=QOyytOoFu1FALn
688
688
  stoobly_agent/test/app/cli/scenario/scenario_snapshot_test.py,sha256=IAe1l69Smd8a9E6I0CVs8lgqnC4mI4M1EFfUjC4ZHs8,3396
689
689
  stoobly_agent/test/app/cli/scenario/scenario_test_integration_test.py,sha256=BdXGe1xfb79tCCTKtp4sqI6CkZL_KamvQKLK8Wwb4u0,5543
690
690
  stoobly_agent/test/app/cli/snapshot/lifecycle_hooks_migrate.py,sha256=x3x5vHfZ1xmoOpZ0yRSB3kbWbPjfbLk2PJFSa1xOLoU,316
691
- stoobly_agent/test/app/cli/snapshot/snapshot_apply_test.py,sha256=p0Nyv66agEPOKY23lMNBZQNAXNL1zoYJz2N5ev4rvO0,21729
691
+ stoobly_agent/test/app/cli/snapshot/snapshot_apply_test.py,sha256=YIcaCxJV8CcTnCX08vq9HQyuyYf6YIwVVA3Hhx_RG2A,27752
692
692
  stoobly_agent/test/app/cli/snapshot/snapshot_copy_test.py,sha256=Yg78-FhSiG_r6Jpm-sN8sn0LjVXTwTOXt6hg8ni2GIY,1953
693
693
  stoobly_agent/test/app/cli/snapshot/snapshot_migrate_test.py,sha256=voEvblK6CMGCrSJDTHVmkUkLXj0auNb78jxlGiiBBQQ,7370
694
- stoobly_agent/test/app/cli/snapshot/snapshot_prune_test.py,sha256=Hi8-rpQ9ryy1Jdl_KB9ERXgbLHLKmuFQZaxn5EVFj9I,3752
694
+ stoobly_agent/test/app/cli/snapshot/snapshot_prune_test.py,sha256=G3vrXQRMoDedNpAuKgDivNMqLK-5xsCAAl80xsgeVaU,6690
695
695
  stoobly_agent/test/app/cli/snapshot/snapshot_update_test.py,sha256=fILsX2M5j4wuLRP6LJTHe4CPB8gvaEbsSoYmFCHmKVk,4514
696
696
  stoobly_agent/test/app/models/adapters/orm/joined_request_string_adapter_test.py,sha256=a2IHTk3l7aiLyYF7vtqissrk0MFTF2wlUBiaKWyJKfU,2667
697
697
  stoobly_agent/test/app/models/adapters/orm/request/orm_mitmproxy_request_adapter_test.py,sha256=PbJsAaxPUEbF9vM7DX4z858biWf4qlGnvE8KBuy8SgY,2763
@@ -707,7 +707,7 @@ stoobly_agent/test/app/models/factories/resource/local_db/helpers/log_test.py,sh
707
707
  stoobly_agent/test/app/models/factories/resource/local_db/helpers/tiebreak_scenario_request_test.py,sha256=a1SFLyEyRRLuADvAw6ckQQKORFXvyK1lyrbkaLWx8oU,3399
708
708
  stoobly_agent/test/app/models/factories/resource/local_db/request_adapter_test.py,sha256=Pzq1cBPnP9oSWG-p0c-VoymoHxgp483QmNwmV1b78RA,8453
709
709
  stoobly_agent/test/app/models/factories/resource/local_db/response_adapter_test.py,sha256=9P95EKH5rZGOrmRkRIDlQZqtiLJHk9735og18Ffwpfw,2204
710
- stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION,sha256=vBPve_ulWPaMP-stw3TjfbPykk0t0aSluYQaVmn0ZJA,5
710
+ stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION,sha256=dxfL-Qxjo7CWAIdjoCBmI5kW-pkW-YJU0ao7JHCDD80,5
711
711
  stoobly_agent/test/app/models/schemas/.stoobly/db/stoobly_agent.sqlite3,sha256=ch8gNx6zIelLKQx65gwFx_LRNqUD3EC5xcHZ0ukIQiU,188416
712
712
  stoobly_agent/test/app/models/schemas/.stoobly/settings.yml,sha256=vLwMjweKOdod6tSLtIlyBefPQuNXq9wio4kBaODKtAU,726
713
713
  stoobly_agent/test/app/models/schemas/.stoobly/tmp/options.json,sha256=OTRzarwus48CTrItedXCrgQttJHSEZonEYc7R_knvYg,2212
@@ -748,8 +748,8 @@ stoobly_agent/test/mock_data/scaffold/docker-compose-local-service.yml,sha256=1W
748
748
  stoobly_agent/test/mock_data/scaffold/index.html,sha256=qJwuYajKZ4ihWZrJQ3BNObV5kf1VGnnm_vqlPJzdqLE,258
749
749
  stoobly_agent/test/mock_data/uspto.yaml,sha256=6U5se7C3o-86J4m9xpOk9Npias399f5CbfWzR87WKwE,7835
750
750
  stoobly_agent/test/test_helper.py,sha256=m_oAI7tmRYCNZdKfNqISWhMv3e44tjeYViQ3nTUfnos,1007
751
- stoobly_agent-1.9.0.dist-info/LICENSE,sha256=o93sj12cdoEOsTCjPaPFsw3Xq0SXs3pPcY-9reE2sEw,548
752
- stoobly_agent-1.9.0.dist-info/METADATA,sha256=XWWvk4MTuiKUjQ9RvRoI6r5yPRdV8Mgyzu1r1kQc9oc,3087
753
- stoobly_agent-1.9.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
754
- stoobly_agent-1.9.0.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
755
- stoobly_agent-1.9.0.dist-info/RECORD,,
751
+ stoobly_agent-1.9.1.dist-info/LICENSE,sha256=o93sj12cdoEOsTCjPaPFsw3Xq0SXs3pPcY-9reE2sEw,548
752
+ stoobly_agent-1.9.1.dist-info/METADATA,sha256=wlI-HxrR6hqRTUREg2Oo4NJNTsLXe7NPKrnO4mHThs0,3087
753
+ stoobly_agent-1.9.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
754
+ stoobly_agent-1.9.1.dist-info/entry_points.txt,sha256=aq5wix5oC8MDQtmyPGU0xaFrsjJg7WH28NmXh2sc3Z8,56
755
+ stoobly_agent-1.9.1.dist-info/RECORD,,