port-ocean 0.20.3__py3-none-any.whl → 0.20.4__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.

Potentially problematic release.


This version of port-ocean might be problematic. Click here for more details.

@@ -109,9 +109,9 @@ class AbstractWebhookProcessor(ABC):
109
109
  pass
110
110
 
111
111
  @abstractmethod
112
- def should_process_event(self, event: WebhookEvent) -> bool:
112
+ async def should_process_event(self, event: WebhookEvent) -> bool:
113
113
  pass
114
114
 
115
115
  @abstractmethod
116
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
116
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
117
117
  pass
@@ -47,7 +47,7 @@ class LiveEventsProcessorManager(LiveEventsMixin, EventsMixin):
47
47
  except Exception as e:
48
48
  logger.exception(f"Error starting queue processor for {path}: {str(e)}")
49
49
 
50
- def _extract_matching_processors(
50
+ async def _extract_matching_processors(
51
51
  self, webhook_event: WebhookEvent, path: str
52
52
  ) -> list[tuple[ResourceConfig, AbstractWebhookProcessor]]:
53
53
  """Find and extract the matching processor for an event"""
@@ -56,8 +56,8 @@ class LiveEventsProcessorManager(LiveEventsMixin, EventsMixin):
56
56
 
57
57
  for processor_class in self._processors_classes[path]:
58
58
  processor = processor_class(webhook_event.clone())
59
- if processor.should_process_event(webhook_event):
60
- kinds = processor.get_matching_kinds(webhook_event)
59
+ if await processor.should_process_event(webhook_event):
60
+ kinds = await processor.get_matching_kinds(webhook_event)
61
61
  for kind in kinds:
62
62
  for resource in event.port_app_config.resources:
63
63
  if resource.kind == kind:
@@ -92,26 +92,30 @@ class LiveEventsProcessorManager(LiveEventsMixin, EventsMixin):
92
92
  parent_override=webhook_event.event_context,
93
93
  ):
94
94
  matching_processors_with_resource = (
95
- self._extract_matching_processors(webhook_event, path)
95
+ await self._extract_matching_processors(webhook_event, path)
96
96
  )
97
97
  webhook_event_raw_results_for_all_resources = await asyncio.gather(
98
98
  *(
99
99
  self._process_single_event(processor, path, resource)
100
100
  for resource, processor in matching_processors_with_resource
101
- )
101
+ ),
102
+ return_exceptions=True,
102
103
  )
103
- if webhook_event_raw_results_for_all_resources and all(
104
- webhook_event_raw_results_for_all_resources
105
- ):
104
+
105
+ successful_raw_results: list[WebhookEventRawResults] = [
106
+ result
107
+ for result in webhook_event_raw_results_for_all_resources
108
+ if isinstance(result, WebhookEventRawResults)
109
+ ]
110
+
111
+ if successful_raw_results:
106
112
  logger.info(
107
113
  "Exporting raw event results to entities",
108
114
  webhook_event_raw_results_for_all_resources_length=len(
109
- webhook_event_raw_results_for_all_resources
115
+ successful_raw_results
110
116
  ),
111
117
  )
112
- await self.sync_raw_results(
113
- webhook_event_raw_results_for_all_resources
114
- )
118
+ await self.sync_raw_results(successful_raw_results)
115
119
  except asyncio.CancelledError:
116
120
  logger.info(f"Queue processor for {path} is shutting down")
117
121
  for _, processor in matching_processors_with_resource:
@@ -32,7 +32,7 @@ class ConcreteWebhookProcessor(AbstractWebhookProcessor):
32
32
  ) -> WebhookEventRawResults:
33
33
  return WebhookEventRawResults(updated_raw_results=[{}], deleted_raw_results=[])
34
34
 
35
- def should_process_event(self, webhook_event: WebhookEvent) -> bool:
35
+ async def should_process_event(self, webhook_event: WebhookEvent) -> bool:
36
36
  return True
37
37
 
38
38
  async def before_processing(self) -> None:
@@ -47,7 +47,7 @@ class ConcreteWebhookProcessor(AbstractWebhookProcessor):
47
47
  await super().cancel()
48
48
  self.cancel_called = True
49
49
 
50
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
50
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
51
51
  return ["test"]
52
52
 
53
53
 
@@ -54,10 +54,10 @@ class MockProcessor(AbstractWebhookProcessor):
54
54
  ) -> WebhookEventRawResults:
55
55
  return WebhookEventRawResults(updated_raw_results=[], deleted_raw_results=[])
56
56
 
57
- def should_process_event(self, event: WebhookEvent) -> bool:
57
+ async def should_process_event(self, event: WebhookEvent) -> bool:
58
58
  return True
59
59
 
60
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
60
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
61
61
  return ["repository"]
62
62
 
63
63
 
@@ -75,10 +75,10 @@ class MockProcessorFalse(AbstractWebhookProcessor):
75
75
  ) -> WebhookEventRawResults:
76
76
  return WebhookEventRawResults(updated_raw_results=[], deleted_raw_results=[])
77
77
 
78
- def should_process_event(self, event: WebhookEvent) -> bool:
78
+ async def should_process_event(self, event: WebhookEvent) -> bool:
79
79
  return False
80
80
 
81
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
81
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
82
82
  return ["repository"]
83
83
 
84
84
 
@@ -110,10 +110,10 @@ class MockWebhookProcessor(AbstractWebhookProcessor):
110
110
  async def cancel(self) -> None:
111
111
  self.cancel_called = True
112
112
 
113
- def should_process_event(self, event: WebhookEvent) -> bool:
113
+ async def should_process_event(self, event: WebhookEvent) -> bool:
114
114
  return True
115
115
 
116
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
116
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
117
117
  return ["test"]
118
118
 
119
119
 
@@ -155,10 +155,10 @@ class MockWebhookHandlerForProcessWebhookRequest(AbstractWebhookProcessor):
155
155
  self.handled = True
156
156
  return WebhookEventRawResults(updated_raw_results=[], deleted_raw_results=[])
157
157
 
158
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
158
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
159
159
  return ["repository"]
160
160
 
161
- def should_process_event(self, event: WebhookEvent) -> bool:
161
+ async def should_process_event(self, event: WebhookEvent) -> bool:
162
162
  """Filter the event data before processing."""
163
163
  return True
164
164
 
@@ -329,16 +329,16 @@ async def test_extractMatchingProcessors_processorMatch(
329
329
 
330
330
  async with event_context(EventType.HTTP_REQUEST, trigger_type="request") as event:
331
331
  event.port_app_config = mock_port_app_config
332
- processors = processor_manager._extract_matching_processors(
332
+ processors = await processor_manager._extract_matching_processors(
333
333
  webhook_event, test_path
334
334
  )
335
335
 
336
- assert len(processors) == 1
337
- config, processor = processors[0]
338
- assert isinstance(processor, MockProcessor)
339
- assert config.kind == "repository"
340
- assert processor.event != webhook_event
341
- assert processor.event.payload == webhook_event.payload
336
+ assert len(processors) == 1
337
+ config, processor = processors[0]
338
+ assert isinstance(processor, MockProcessor)
339
+ assert config.kind == "repository"
340
+ assert processor.event != webhook_event
341
+ assert processor.event.payload == webhook_event.payload
342
342
 
343
343
 
344
344
  @pytest.mark.asyncio
@@ -355,7 +355,9 @@ async def test_extractMatchingProcessors_noMatch(
355
355
  EventType.HTTP_REQUEST, trigger_type="request"
356
356
  ) as event:
357
357
  event.port_app_config = mock_port_app_config
358
- processor_manager._extract_matching_processors(webhook_event, test_path)
358
+ await processor_manager._extract_matching_processors(
359
+ webhook_event, test_path
360
+ )
359
361
 
360
362
 
361
363
  @pytest.mark.asyncio
@@ -370,7 +372,7 @@ async def test_extractMatchingProcessors_multipleMatches(
370
372
 
371
373
  async with event_context(EventType.HTTP_REQUEST, trigger_type="request") as event:
372
374
  event.port_app_config = mock_port_app_config
373
- processors = processor_manager._extract_matching_processors(
375
+ processors = await processor_manager._extract_matching_processors(
374
376
  webhook_event, test_path
375
377
  )
376
378
 
@@ -391,7 +393,7 @@ async def test_extractMatchingProcessors_onlyOneMatches(
391
393
 
392
394
  async with event_context(EventType.HTTP_REQUEST, trigger_type="request") as event:
393
395
  event.port_app_config = mock_port_app_config
394
- processors = processor_manager._extract_matching_processors(
396
+ processors = await processor_manager._extract_matching_processors(
395
397
  webhook_event, test_path
396
398
  )
397
399
 
@@ -542,10 +544,10 @@ async def test_integrationTest_postRequestSent_webhookEventRawResultProcessed_en
542
544
  processed_events.append(event_data)
543
545
  return event_data
544
546
 
545
- def should_process_event(self, event: WebhookEvent) -> bool:
547
+ async def should_process_event(self, event: WebhookEvent) -> bool:
546
548
  return True
547
549
 
548
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
550
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
549
551
  return ["repository"]
550
552
 
551
553
  processing_complete = asyncio.Event()
@@ -649,10 +651,10 @@ async def test_integrationTest_postRequestSent_reachedTimeout_entityNotUpserted(
649
651
  updated_raw_results=[], deleted_raw_results=[]
650
652
  )
651
653
 
652
- def should_process_event(self, event: WebhookEvent) -> bool:
654
+ async def should_process_event(self, event: WebhookEvent) -> bool:
653
655
  return True
654
656
 
655
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
657
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
656
658
  return ["repository"]
657
659
 
658
660
  processing_complete = asyncio.Event()
@@ -766,20 +768,20 @@ async def test_integrationTest_postRequestSent_noMatchingHandlers_entityNotUpser
766
768
  )
767
769
  return event_data
768
770
 
769
- def should_process_event(self, event: WebhookEvent) -> bool:
771
+ async def should_process_event(self, event: WebhookEvent) -> bool:
770
772
  return False
771
773
 
772
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
774
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
773
775
  return ["repository"]
774
776
 
775
777
  processing_complete = asyncio.Event()
776
778
  original_process_data = LiveEventsProcessorManager._extract_matching_processors
777
779
 
778
- def patched_extract_matching_processors(
780
+ async def patched_extract_matching_processors(
779
781
  self: LiveEventsProcessorManager, event: WebhookEvent, path: str
780
782
  ) -> list[tuple[ResourceConfig, AbstractWebhookProcessor]]:
781
783
  try:
782
- return original_process_data(self, event, path)
784
+ return await original_process_data(self, event, path)
783
785
  except Exception as e:
784
786
  test_state["exception_thrown"] = e # type: ignore
785
787
  return []
@@ -882,10 +884,10 @@ async def test_integrationTest_postRequestSent_webhookEventRawResultProcessedFor
882
884
  processed_events.append(event_data)
883
885
  return event_data
884
886
 
885
- def should_process_event(self, event: WebhookEvent) -> bool:
887
+ async def should_process_event(self, event: WebhookEvent) -> bool:
886
888
  return True
887
889
 
888
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
890
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
889
891
  return ["repository"]
890
892
 
891
893
  class TestProcessorB(AbstractWebhookProcessor):
@@ -913,10 +915,10 @@ async def test_integrationTest_postRequestSent_webhookEventRawResultProcessedFor
913
915
  processed_events.append(event_data)
914
916
  return event_data
915
917
 
916
- def should_process_event(self, event: WebhookEvent) -> bool:
918
+ async def should_process_event(self, event: WebhookEvent) -> bool:
917
919
  return True
918
920
 
919
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
921
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
920
922
  return ["repository"]
921
923
 
922
924
  class TestProcessorFiltersOut(AbstractWebhookProcessor):
@@ -944,10 +946,10 @@ async def test_integrationTest_postRequestSent_webhookEventRawResultProcessedFor
944
946
  processed_events.append(event_data)
945
947
  return event_data
946
948
 
947
- def should_process_event(self, event: WebhookEvent) -> bool:
949
+ async def should_process_event(self, event: WebhookEvent) -> bool:
948
950
  return False
949
951
 
950
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
952
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
951
953
  return ["repository"]
952
954
 
953
955
  processing_complete = asyncio.Event()
@@ -1071,10 +1073,10 @@ async def test_integrationTest_postRequestSent_webhookEventRawResultProcessedwit
1071
1073
  processed_events.append(event_data)
1072
1074
  return event_data
1073
1075
 
1074
- def should_process_event(self, event: WebhookEvent) -> bool:
1076
+ async def should_process_event(self, event: WebhookEvent) -> bool:
1075
1077
  return True
1076
1078
 
1077
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
1079
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
1078
1080
  return ["repository"]
1079
1081
 
1080
1082
  processing_complete = asyncio.Event()
@@ -1195,10 +1197,10 @@ async def test_integrationTest_postRequestSent_webhookEventRawResultProcessedwit
1195
1197
  processed_events.append(event_data)
1196
1198
  return event_data
1197
1199
 
1198
- def should_process_event(self, event: WebhookEvent) -> bool:
1200
+ async def should_process_event(self, event: WebhookEvent) -> bool:
1199
1201
  return True
1200
1202
 
1201
- def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
1203
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
1202
1204
  return ["repository"]
1203
1205
 
1204
1206
  processing_complete = asyncio.Event()
@@ -1262,3 +1264,139 @@ async def test_integrationTest_postRequestSent_webhookEventRawResultProcessedwit
1262
1264
  mock_delete.assert_not_called()
1263
1265
 
1264
1266
  await mock_context.app.webhook_manager.shutdown()
1267
+
1268
+
1269
+ @pytest.mark.asyncio
1270
+ @patch(
1271
+ "port_ocean.core.handlers.entities_state_applier.port.applier.HttpEntitiesStateApplier.upsert"
1272
+ )
1273
+ @patch(
1274
+ "port_ocean.core.handlers.entities_state_applier.port.applier.HttpEntitiesStateApplier.delete"
1275
+ )
1276
+ async def test_integrationTest_postRequestSent_oneProcessorThrowsException_onlySuccessfulResultsProcessed(
1277
+ mock_delete: AsyncMock,
1278
+ mock_upsert: AsyncMock,
1279
+ mock_context: PortOceanContext,
1280
+ mock_port_app_config: PortAppConfig,
1281
+ monkeypatch: pytest.MonkeyPatch,
1282
+ ) -> None:
1283
+ """Integration test for webhook processing where one processor throws an exception"""
1284
+
1285
+ monkeypatch.setattr(
1286
+ "port_ocean.core.integrations.mixins.handler.ocean", mock_context
1287
+ )
1288
+ monkeypatch.setattr(
1289
+ "port_ocean.core.integrations.mixins.live_events.ocean", mock_context
1290
+ )
1291
+ processed_events: list[WebhookEventRawResults] = []
1292
+ mock_upsert.return_value = [entity]
1293
+
1294
+ class SuccessfulProcessor(AbstractWebhookProcessor):
1295
+ async def authenticate(
1296
+ self, payload: Dict[str, Any], headers: Dict[str, str]
1297
+ ) -> bool:
1298
+ return True
1299
+
1300
+ async def validate_payload(self, payload: Dict[str, Any]) -> bool:
1301
+ return True
1302
+
1303
+ async def handle_event(
1304
+ self, payload: EventPayload, resource: ResourceConfig
1305
+ ) -> WebhookEventRawResults:
1306
+ event_data = WebhookEventRawResults(
1307
+ updated_raw_results=[
1308
+ {
1309
+ "name": "repo-one",
1310
+ "links": {"html": {"href": "https://example.com/repo-one"}},
1311
+ "main_branch": "main",
1312
+ }
1313
+ ],
1314
+ deleted_raw_results=[],
1315
+ )
1316
+ processed_events.append(event_data)
1317
+ return event_data
1318
+
1319
+ async def should_process_event(self, event: WebhookEvent) -> bool:
1320
+ return True
1321
+
1322
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
1323
+ return ["repository"]
1324
+
1325
+ class FailingProcessor(AbstractWebhookProcessor):
1326
+ async def authenticate(
1327
+ self, payload: Dict[str, Any], headers: Dict[str, str]
1328
+ ) -> bool:
1329
+ return True
1330
+
1331
+ async def validate_payload(self, payload: Dict[str, Any]) -> bool:
1332
+ return True
1333
+
1334
+ async def handle_event(
1335
+ self, payload: EventPayload, resource: ResourceConfig
1336
+ ) -> WebhookEventRawResults:
1337
+ raise ValueError("Simulated failure in processor")
1338
+
1339
+ async def should_process_event(self, event: WebhookEvent) -> bool:
1340
+ return True
1341
+
1342
+ async def get_matching_kinds(self, event: WebhookEvent) -> list[str]:
1343
+ return ["repository"]
1344
+
1345
+ processing_complete = asyncio.Event()
1346
+ original_process_data = LiveEventsMixin.sync_raw_results
1347
+
1348
+ async def patched_export_single_resource(
1349
+ self: LiveEventsMixin, webhookEventRawResults: list[WebhookEventRawResults]
1350
+ ) -> None:
1351
+ try:
1352
+ await original_process_data(self, webhookEventRawResults)
1353
+ except Exception as e:
1354
+ raise e
1355
+ finally:
1356
+ processing_complete.set()
1357
+
1358
+ monkeypatch.setattr(
1359
+ LiveEventsMixin,
1360
+ "sync_raw_results",
1361
+ patched_export_single_resource,
1362
+ )
1363
+ test_path = "/webhook-test"
1364
+ mock_context.app.integration = BaseIntegration(ocean)
1365
+ mock_context.app.webhook_manager = LiveEventsProcessorManager(
1366
+ mock_context.app.integration_router, SignalHandler()
1367
+ )
1368
+
1369
+ # Register both processors
1370
+ mock_context.app.webhook_manager.register_processor(test_path, SuccessfulProcessor)
1371
+ mock_context.app.webhook_manager.register_processor(test_path, FailingProcessor)
1372
+ await mock_context.app.webhook_manager.start_processing_event_messages()
1373
+ mock_context.app.fast_api_app.include_router(
1374
+ mock_context.app.webhook_manager._router
1375
+ )
1376
+ client = TestClient(mock_context.app.fast_api_app)
1377
+
1378
+ test_payload = {"test": "data"}
1379
+
1380
+ async with event_context(EventType.HTTP_REQUEST, trigger_type="request") as event:
1381
+ mock_context.app.webhook_manager.port_app_config_handler.get_port_app_config = AsyncMock(return_value=mock_port_app_config) # type: ignore
1382
+ event.port_app_config = (
1383
+ await mock_context.app.webhook_manager.port_app_config_handler.get_port_app_config()
1384
+ )
1385
+
1386
+ response = client.post(
1387
+ test_path, json=test_payload, headers={"Content-Type": "application/json"}
1388
+ )
1389
+
1390
+ assert response.status_code == 200
1391
+ assert response.json() == {"status": "ok"}
1392
+
1393
+ try:
1394
+ await asyncio.wait_for(processing_complete.wait(), timeout=10.0)
1395
+ except asyncio.TimeoutError:
1396
+ pytest.fail("Event processing timed out")
1397
+
1398
+ assert len(processed_events) == 1
1399
+ assert mock_upsert.call_count == 1
1400
+ mock_delete.assert_not_called()
1401
+
1402
+ await mock_context.app.webhook_manager.shutdown()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.20.3
3
+ Version: 0.20.4
4
4
  Summary: Port Ocean is a CLI tool for managing your Port projects.
5
5
  Home-page: https://app.getport.io
6
6
  Keywords: ocean,port-ocean,port
@@ -103,8 +103,8 @@ port_ocean/core/handlers/queue/local_queue.py,sha256=EzqsGIX43xbVAcePwTcCg5QDrXA
103
103
  port_ocean/core/handlers/resync_state_updater/__init__.py,sha256=kG6y-JQGpPfuTHh912L_bctIDCzAK4DN-d00S7rguWU,81
104
104
  port_ocean/core/handlers/resync_state_updater/updater.py,sha256=Yg9ET6ZV5B9GW7u6zZA6GlB_71kmvxvYX2FWgQNzMvo,3182
105
105
  port_ocean/core/handlers/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
- port_ocean/core/handlers/webhook/abstract_webhook_processor.py,sha256=YRMr4M1m0XNZbxNGU0bzB3hEkPat1HCom66EU9NRffU,3879
107
- port_ocean/core/handlers/webhook/processor_manager.py,sha256=RoPV3cHjAv7jJ_vpC9y2fF2v9eb41h0VM6bNAPuzKdg,11779
106
+ port_ocean/core/handlers/webhook/abstract_webhook_processor.py,sha256=5KwZkdkDd5HdVkXPzKiqabodZKl-hOtMypkTKd8Hq3M,3891
107
+ port_ocean/core/handlers/webhook/processor_manager.py,sha256=Pmg81IT0i3MCFWC6648Ln4NfpAWvpyrPZwOFfdTPkDE,11928
108
108
  port_ocean/core/handlers/webhook/webhook_event.py,sha256=Iuw6IX3PPjwHECUeFgrJl6K249mJ-DPAGhP8OMxbc1c,4096
109
109
  port_ocean/core/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
110
110
  port_ocean/core/integrations/base.py,sha256=eS0WDOfCTim1UOQQrNuP14I6hvT_fr8dof_cr1ls01s,3107
@@ -156,8 +156,8 @@ port_ocean/tests/core/handlers/mixins/test_sync_raw.py,sha256=gxQ4e9hQuMS8-o5Ubi
156
156
  port_ocean/tests/core/handlers/port_app_config/test_api.py,sha256=eJZ6SuFBLz71y4ca3DNqKag6d6HUjNJS0aqQPwiLMTI,1999
157
157
  port_ocean/tests/core/handlers/port_app_config/test_base.py,sha256=tdjpFUnUZ6TNMxc3trKkzmMTGTb7oKIeu3rRXv_fV3g,6872
158
158
  port_ocean/tests/core/handlers/queue/test_local_queue.py,sha256=9Ly0HzZXbs6Rbl_bstsIdInC3h2bgABU3roP9S_PnJM,2582
159
- port_ocean/tests/core/handlers/webhook/test_abstract_webhook_processor.py,sha256=lLOVjjUCI973d9Ps_hugWOjyxNgEiPjqZVqN3qC2Rhs,3328
160
- port_ocean/tests/core/handlers/webhook/test_processor_manager.py,sha256=jwoimtQqrzro2Q2wBUmtKWN2bg9013GRpm7LEPCix80,44109
159
+ port_ocean/tests/core/handlers/webhook/test_abstract_webhook_processor.py,sha256=zKwHhPAYEZoZ5Z2UETp1t--mbkS8uyvlXThB0obZTTc,3340
160
+ port_ocean/tests/core/handlers/webhook/test_processor_manager.py,sha256=Nb-3VXVRol9fM5pLZQ1iGyPsZcHkWSNGG3bDHWjuR3Y,49285
161
161
  port_ocean/tests/core/handlers/webhook/test_webhook_event.py,sha256=oR4dEHLO65mp6rkfNfszZcfFoRZlB8ZWee4XetmsuIk,3181
162
162
  port_ocean/tests/core/test_utils.py,sha256=Z3kdhb5V7Svhcyy3EansdTpgHL36TL6erNtU-OPwAcI,2647
163
163
  port_ocean/tests/core/utils/test_entity_topological_sorter.py,sha256=zuq5WSPy_88PemG3mOUIHTxWMR_js1R7tOzUYlgBd68,3447
@@ -184,8 +184,8 @@ port_ocean/utils/repeat.py,sha256=U2OeCkHPWXmRTVoPV-VcJRlQhcYqPWI5NfmPlb1JIbc,32
184
184
  port_ocean/utils/signal.py,sha256=mMVq-1Ab5YpNiqN4PkiyTGlV_G0wkUDMMjTZp5z3pb0,1514
185
185
  port_ocean/utils/time.py,sha256=pufAOH5ZQI7gXvOvJoQXZXZJV-Dqktoj9Qp9eiRwmJ4,1939
186
186
  port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
187
- port_ocean-0.20.3.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
188
- port_ocean-0.20.3.dist-info/METADATA,sha256=etjLtg8n350AlzlWET_M8HSbFlYiDwx2mb9vYIbihJk,6669
189
- port_ocean-0.20.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
190
- port_ocean-0.20.3.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
191
- port_ocean-0.20.3.dist-info/RECORD,,
187
+ port_ocean-0.20.4.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
188
+ port_ocean-0.20.4.dist-info/METADATA,sha256=TTDuej8wAckEOTu_3qM4GmnO0ReLwaN2SY7SSZ74pXw,6669
189
+ port_ocean-0.20.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
190
+ port_ocean-0.20.4.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
191
+ port_ocean-0.20.4.dist-info/RECORD,,