port-ocean 0.30.1__py3-none-any.whl → 0.30.3__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.
@@ -1,5 +1,5 @@
1
1
  import asyncio
2
- from typing import Type, Any
2
+ from typing import Any, Type
3
3
 
4
4
  import httpx
5
5
  from loguru import logger
@@ -114,12 +114,67 @@ async def _initialize_required_integration_settings(
114
114
  )
115
115
 
116
116
 
117
+ async def _mapped_blueprints_exist(
118
+ port_client: PortClient,
119
+ defaults: Defaults | None = None,
120
+ has_provision_feature_flag: bool = False,
121
+ ) -> bool:
122
+ if not defaults:
123
+ return True
124
+
125
+ integration = await port_client.get_current_integration(
126
+ should_log=False,
127
+ should_raise=False,
128
+ has_provision_feature_flag=has_provision_feature_flag,
129
+ )
130
+ integration_config = integration.get("config", {})
131
+ resources = integration_config.get("resources", [])
132
+
133
+ if not isinstance(resources, list):
134
+ return True
135
+
136
+ mapped_blueprints = []
137
+ for resource in resources:
138
+ blueprint = (
139
+ resource.get("port", {})
140
+ .get("entity", {})
141
+ .get("mappings", {})
142
+ .get("blueprint")
143
+ )
144
+ if blueprint:
145
+ if (
146
+ isinstance(blueprint, str)
147
+ and blueprint.startswith('"')
148
+ and blueprint.endswith('"')
149
+ ):
150
+ blueprint = blueprint.strip('"')
151
+ mapped_blueprints.append({"identifier": blueprint})
152
+
153
+ if not mapped_blueprints:
154
+ return True
155
+
156
+ existing_blueprints, _ = await gather_and_split_errors_from_results(
157
+ [
158
+ port_client.get_blueprint(blueprint["identifier"], should_log=False)
159
+ for blueprint in mapped_blueprints
160
+ ],
161
+ lambda item: isinstance(item, Blueprint),
162
+ )
163
+
164
+ if len(existing_blueprints) != len(mapped_blueprints):
165
+ return False
166
+
167
+ return True
168
+
169
+
117
170
  async def _create_resources(
118
171
  port_client: PortClient,
119
172
  defaults: Defaults | None = None,
173
+ has_provision_feature_flag: bool = False,
120
174
  ) -> None:
121
175
  if not defaults:
122
176
  return
177
+
123
178
  creation_stage, *blueprint_patches = deconstruct_blueprints_to_creation_steps(
124
179
  defaults.blueprints
125
180
  )
@@ -132,7 +187,13 @@ async def _create_resources(
132
187
  lambda item: isinstance(item, Blueprint),
133
188
  )
134
189
 
135
- if blueprints_results:
190
+ mapped_blueprints_exist = await _mapped_blueprints_exist(
191
+ port_client,
192
+ defaults,
193
+ has_provision_feature_flag,
194
+ )
195
+
196
+ if blueprints_results or mapped_blueprints_exist:
136
197
  logger.info(
137
198
  f"Blueprints already exist: {[result.identifier for result in blueprints_results]}. Skipping integration default creation..."
138
199
  )
@@ -184,15 +245,16 @@ async def _create_resources(
184
245
  )
185
246
  )
186
247
 
187
- created_scorecards, scorecards_errors = (
188
- await gather_and_split_errors_from_results(
189
- (
190
- port_client.create_scorecard(
191
- blueprint_scorecards["blueprint"], action, should_log=False
192
- )
193
- for blueprint_scorecards in defaults.scorecards
194
- for action in blueprint_scorecards["data"]
248
+ (
249
+ created_scorecards,
250
+ scorecards_errors,
251
+ ) = await gather_and_split_errors_from_results(
252
+ (
253
+ port_client.create_scorecard(
254
+ blueprint_scorecards["blueprint"], action, should_log=False
195
255
  )
256
+ for blueprint_scorecards in defaults.scorecards
257
+ for action in blueprint_scorecards["data"]
196
258
  )
197
259
  )
198
260
 
@@ -286,7 +348,7 @@ async def _initialize_defaults(
286
348
  return
287
349
  try:
288
350
  logger.info("Found default resources, starting creation process")
289
- await _create_resources(port_client, defaults)
351
+ await _create_resources(port_client, defaults, has_provision_feature_flag)
290
352
  except AbortDefaultCreationError as e:
291
353
  logger.warning(
292
354
  f"Failed to create resources. Rolling back blueprints : {e.blueprints_to_rollback}"
@@ -5,6 +5,7 @@ from loguru import logger
5
5
 
6
6
  from port_ocean.helpers.retry import RetryTransport, RetryConfig
7
7
  from port_ocean.helpers.stream import Stream
8
+ from typing import AsyncGenerator, List, Dict
8
9
 
9
10
 
10
11
  class OceanAsyncClient(httpx.AsyncClient):
@@ -56,3 +57,31 @@ class OceanAsyncClient(httpx.AsyncClient):
56
57
  response = await self.send(req, stream=True)
57
58
  response.raise_for_status()
58
59
  return Stream(response)
60
+
61
+
62
+ class StreamingClientWrapper:
63
+ def __init__(self, http_client: OceanAsyncClient):
64
+ self._client = http_client
65
+
66
+ async def stream_json(
67
+ self,
68
+ url: str,
69
+ target_items_path: str,
70
+ **kwargs: Any,
71
+ ) -> AsyncGenerator[List[Dict[str, Any]], None]:
72
+ """
73
+ A wrapper that provides a unified async generator interface for both streaming
74
+ and non-streaming HTTP GET requests.
75
+
76
+ :param url: The URL to request.
77
+ :param target_items_path: A JMESPath string to extract the list of items
78
+ from the JSON response (e.g., 'results'). The wrapper
79
+ will automatically adapt this for the streaming parser.
80
+ :param kwargs: Additional arguments for the HTTP request.
81
+ """
82
+ # ijson needs a path to the items inside the array, e.g., "results.item"
83
+ streaming_path = f"{target_items_path}.item"
84
+ stream_response = await self._client.get_stream(url, **kwargs)
85
+ json_stream = stream_response.get_json_stream(target_items=streaming_path)
86
+ async for items_batch in json_stream:
87
+ yield items_batch
@@ -22,7 +22,10 @@ class Stream:
22
22
  if chunk_size is None:
23
23
  chunk_size = ocean_context.ocean.config.streaming.chunk_size
24
24
 
25
- file_name = f"{ocean_context.ocean.config.streaming.location}/{uuid.uuid4()}"
25
+ streaming_location = ocean_context.ocean.config.streaming.location
26
+ os.makedirs(streaming_location, exist_ok=True)
27
+
28
+ file_name = f"{streaming_location}/{uuid.uuid4()}"
26
29
 
27
30
  crypt = Fernet(Fernet.generate_key())
28
31
 
@@ -0,0 +1,85 @@
1
+ import pytest
2
+ from unittest.mock import AsyncMock
3
+ from typing import Any, AsyncGenerator
4
+
5
+
6
+ from port_ocean.helpers.async_client import OceanAsyncClient, StreamingClientWrapper
7
+ from port_ocean.helpers.stream import Stream
8
+
9
+
10
+ class MockStream:
11
+ """A mock of the port_ocean.helpers.stream.Stream class for testing."""
12
+
13
+ def __init__(self, data_chunks: list[list[dict[str, Any]]]) -> None:
14
+ self._data_chunks = data_chunks
15
+
16
+ async def get_json_stream(self, target_items: str) -> AsyncGenerator[Any, None]:
17
+ """An async generator that yields the data chunks."""
18
+ for chunk in self._data_chunks:
19
+ yield chunk
20
+
21
+
22
+ @pytest.mark.asyncio
23
+ async def test_stream_json_with_streaming_enabled() -> None:
24
+ """
25
+ Tests that when streaming is enabled, the wrapper uses the `get_stream` method
26
+ and yields data in batches.
27
+ """
28
+ # Arrange
29
+ mock_client = AsyncMock(spec=OceanAsyncClient)
30
+ # Simulate receiving the data in two separate chunks/batches
31
+ mock_stream_instance = MockStream(
32
+ [[{"id": 1, "name": "one"}], [{"id": 2, "name": "two"}]]
33
+ )
34
+ mock_client.get_stream.return_value = mock_stream_instance
35
+
36
+ wrapper = StreamingClientWrapper(http_client=mock_client)
37
+
38
+ # Act
39
+ results = [item async for item in wrapper.stream_json("http://test.com", "results")]
40
+
41
+ # Assert
42
+ mock_client.get_stream.assert_called_once_with("http://test.com")
43
+ mock_client.get.assert_not_called()
44
+ assert results == [[{"id": 1, "name": "one"}], [{"id": 2, "name": "two"}]]
45
+
46
+
47
+ @pytest.mark.asyncio
48
+ async def test_stream_json_with_empty_results_streaming() -> None:
49
+ """
50
+ Tests that the wrapper handles an empty stream correctly in streaming mode.
51
+ """
52
+ # Arrange
53
+ mock_client = AsyncMock(spec=OceanAsyncClient)
54
+ mock_stream_instance = MockStream([[]]) # Stream yields one empty batch
55
+ mock_client.get_stream.return_value = mock_stream_instance
56
+
57
+ wrapper = StreamingClientWrapper(http_client=mock_client)
58
+
59
+ # Act
60
+ results = [item async for item in wrapper.stream_json("http://test.com", "results")]
61
+
62
+ # Assert
63
+ assert results == [[]]
64
+
65
+
66
+ @pytest.mark.asyncio
67
+ async def test_stream_json_path_adaptation_for_streaming() -> None:
68
+ """
69
+ Tests that the wrapper correctly adapts the `target_items_path` for the
70
+ streaming parser (ijson) by appending `.item`.
71
+ """
72
+ # Arrange
73
+ mock_client = AsyncMock(spec=OceanAsyncClient)
74
+ mock_stream = AsyncMock(spec=Stream)
75
+ mock_client.get_stream.return_value = mock_stream
76
+
77
+ wrapper = StreamingClientWrapper(http_client=mock_client)
78
+
79
+ # Act
80
+ # We only need to trigger the call to check the arguments
81
+ _ = [item async for item in wrapper.stream_json("http://test.com", "results")]
82
+
83
+ # Assert
84
+ # Verify that get_json_stream was called with the modified path
85
+ mock_stream.get_json_stream.assert_called_once_with(target_items="results.item")
@@ -0,0 +1,219 @@
1
+ from typing import Any
2
+ from unittest.mock import AsyncMock, MagicMock
3
+
4
+ import pytest
5
+
6
+ from port_ocean.clients.port.client import PortClient
7
+ from port_ocean.clients.port.types import UserAgentType
8
+ from port_ocean.core.defaults.common import Defaults
9
+ from port_ocean.core.defaults.initialize import _create_resources
10
+ from port_ocean.core.models import Blueprint
11
+
12
+
13
+ @pytest.fixture
14
+ def mock_defaults() -> Defaults:
15
+ """Create a mock Defaults object with sample data."""
16
+ return Defaults(
17
+ blueprints=[
18
+ {
19
+ "identifier": "blueprint1",
20
+ "title": "Blueprint 1",
21
+ "icon": "Microservice",
22
+ "schema": {"type": "object", "properties": {}},
23
+ "relations": {},
24
+ "calculationProperties": {},
25
+ "mirrorProperties": {},
26
+ "aggregationProperties": {},
27
+ "teamInheritance": {},
28
+ "ownership": {},
29
+ },
30
+ {
31
+ "identifier": "blueprint2",
32
+ "title": "Blueprint 2",
33
+ "icon": "Microservice",
34
+ "schema": {"type": "object", "properties": {}},
35
+ "relations": {},
36
+ "calculationProperties": {},
37
+ "mirrorProperties": {},
38
+ "aggregationProperties": {},
39
+ "teamInheritance": {},
40
+ "ownership": {},
41
+ },
42
+ ],
43
+ actions=[
44
+ {"identifier": "action1", "title": "Action 1"},
45
+ {"identifier": "action2", "title": "Action 2"},
46
+ ],
47
+ scorecards=[
48
+ {"blueprint": "blueprint1", "data": [{"identifier": "scorecard1"}]},
49
+ ],
50
+ pages=[
51
+ {"identifier": "page1", "title": "Page 1"},
52
+ ],
53
+ )
54
+
55
+
56
+ @pytest.fixture
57
+ def mock_port_client() -> PortClient:
58
+ """Create a mock PortClient."""
59
+ mock_client = MagicMock(spec=PortClient)
60
+ mock_client.get_blueprint = AsyncMock()
61
+ mock_client.get_current_integration = AsyncMock()
62
+ mock_client.create_blueprint = AsyncMock()
63
+ mock_client.patch_blueprint = AsyncMock()
64
+ mock_client.create_action = AsyncMock()
65
+ mock_client.create_scorecard = AsyncMock()
66
+ mock_client.create_page = AsyncMock()
67
+ return mock_client
68
+
69
+
70
+ @pytest.mark.asyncio
71
+ async def test_create_resources_all_mapped_blueprints_exist(
72
+ mock_port_client: PortClient, mock_defaults: Defaults
73
+ ) -> None:
74
+ """
75
+ Test case 1: All mapped blueprints exist in Port and they are different from default ones.
76
+ Should skip creation of all resources.
77
+
78
+ Flow:
79
+ 1. Get_blueprint is called for creation_stage default blueprints
80
+ - These should NOT exist (raise exception) so blueprints_results = []
81
+ 2. _mapped_blueprints_exist calls get_blueprint for mapped blueprints
82
+ - These SHOULD exist (return Blueprint) so mapped_blueprints_exist = True
83
+ 3. Since mapped_blueprints_exist is True, we skip creation
84
+ """
85
+ mock_port_client.get_current_integration.return_value = { # type: ignore[attr-defined]
86
+ "config": {
87
+ "resources": [
88
+ {
89
+ "port": {
90
+ "entity": {
91
+ "mappings": {
92
+ "blueprint": "blueprint1test",
93
+ }
94
+ }
95
+ }
96
+ },
97
+ {
98
+ "port": {
99
+ "entity": {
100
+ "mappings": {
101
+ "blueprint": "blueprint2test",
102
+ }
103
+ }
104
+ }
105
+ },
106
+ ]
107
+ }
108
+ }
109
+
110
+ # Track call order: first 2 calls are for creation_stage, next 2 are for mapped blueprints
111
+ call_count = 0
112
+
113
+ async def get_blueprint_side_effect(
114
+ identifier: str, should_log: bool = True
115
+ ) -> Blueprint:
116
+ nonlocal call_count
117
+ call_count += 1
118
+
119
+ # First 2 calls are for creation_stage blueprints
120
+ # These should NOT exist to make blueprints_results = []
121
+ if call_count <= 2:
122
+ raise Exception(f"Blueprint {identifier} not found")
123
+
124
+ # Next 2 calls are for mapped blueprints
125
+ # These SHOULD exist to make mapped_blueprints_exist = True
126
+ return Blueprint.parse_obj(
127
+ {
128
+ "identifier": identifier,
129
+ "title": f"Blueprint {identifier}",
130
+ "team": None,
131
+ "schema": {"type": "object", "properties": {}},
132
+ "relations": {},
133
+ }
134
+ )
135
+
136
+ mock_port_client.get_blueprint.side_effect = get_blueprint_side_effect # type: ignore[attr-defined]
137
+
138
+ # Execute
139
+ await _create_resources(
140
+ mock_port_client, mock_defaults, has_provision_feature_flag=False
141
+ )
142
+
143
+ # Assert: Should not create any blueprints, actions, scorecards, or pages
144
+ mock_port_client.create_blueprint.assert_not_called() # type: ignore[attr-defined]
145
+ mock_port_client.patch_blueprint.assert_not_called() # type: ignore[attr-defined]
146
+ mock_port_client.create_action.assert_not_called() # type: ignore[attr-defined]
147
+ mock_port_client.create_scorecard.assert_not_called() # type: ignore[attr-defined]
148
+ mock_port_client.create_page.assert_not_called() # type: ignore[attr-defined]
149
+ assert mock_port_client.get_blueprint.call_count == 4 # type: ignore[attr-defined]
150
+
151
+
152
+ @pytest.mark.asyncio
153
+ async def test_create_resources_no_mapped_blueprints_exist(
154
+ mock_port_client: PortClient, mock_defaults: Defaults
155
+ ) -> None:
156
+ """
157
+ Test case 2: No mapped blueprints exist in Port (they are in config but don't exist).
158
+ Should create all blueprints, actions, scorecards, and pages from defaults.
159
+
160
+ Flow:
161
+ 1. Get_blueprint is called for creation_stage default blueprints
162
+ - These should NOT exist (raise exception) so blueprints_results = []
163
+ 2. _mapped_blueprints_exist calls get_blueprint for mapped blueprints
164
+ - These should NOT exist (raise exception) so mapped_blueprints_exist = False
165
+ 3. Since both are False/empty, we create all resources
166
+ """
167
+ mock_port_client.get_current_integration.return_value = { # type: ignore[attr-defined]
168
+ "config": {
169
+ "resources": [
170
+ {
171
+ "port": {
172
+ "entity": {
173
+ "mappings": {
174
+ "blueprint": "blueprint1",
175
+ }
176
+ }
177
+ }
178
+ },
179
+ {
180
+ "port": {
181
+ "entity": {
182
+ "mappings": {
183
+ "blueprint": "blueprint2",
184
+ }
185
+ }
186
+ }
187
+ },
188
+ ]
189
+ }
190
+ }
191
+
192
+ # Mock get_blueprint to always raise exception (blueprints don't exist)
193
+ # This simulates that no blueprints exist in Port
194
+ async def get_blueprint_side_effect(
195
+ identifier: str, should_log: bool = True
196
+ ) -> Blueprint:
197
+ raise Exception(f"Blueprint {identifier} not found")
198
+
199
+ mock_port_client.get_blueprint.side_effect = get_blueprint_side_effect # type: ignore[attr-defined]
200
+
201
+ # Mock create_blueprint to return created blueprint
202
+ async def create_blueprint_side_effect(
203
+ blueprint: dict[str, Any], user_agent_type: UserAgentType | None = None
204
+ ) -> dict[str, Any]:
205
+ return {"identifier": blueprint["identifier"], **blueprint}
206
+
207
+ mock_port_client.create_blueprint.side_effect = create_blueprint_side_effect # type: ignore[attr-defined]
208
+
209
+ # Execute
210
+ await _create_resources(
211
+ mock_port_client, mock_defaults, has_provision_feature_flag=False
212
+ )
213
+
214
+ # Assert
215
+ assert mock_port_client.create_blueprint.call_count == 2 # type: ignore[attr-defined]
216
+ assert mock_port_client.patch_blueprint.call_count >= 2 # type: ignore[attr-defined]
217
+ assert mock_port_client.create_action.call_count == 2 # type: ignore[attr-defined]
218
+ assert mock_port_client.create_scorecard.call_count == 1 # type: ignore[attr-defined]
219
+ assert mock_port_client.create_page.call_count == 1 # type: ignore[attr-defined]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.30.1
3
+ Version: 0.30.3
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
@@ -33,6 +33,7 @@ Requires-Dist: httpx (>=0.28.1,<0.29.0)
33
33
  Requires-Dist: ijson (>=3.4.0,<4.0.0)
34
34
  Requires-Dist: jinja2 (>=3.1.6)
35
35
  Requires-Dist: jinja2-time (>=0.2.0,<0.3.0) ; extra == "cli"
36
+ Requires-Dist: jmespath (>=1.0.1,<2.0.0)
36
37
  Requires-Dist: jq (>=1.8.0,<2.0.0)
37
38
  Requires-Dist: loguru (>=0.7.0,<0.8.0)
38
39
  Requires-Dist: prometheus-client (>=0.21.1,<0.22.0)
@@ -83,7 +83,7 @@ port_ocean/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
83
  port_ocean/core/defaults/__init__.py,sha256=8qCZg8n06WAdMu9s_FiRtDYLGPGHbOuS60vapeUoAks,142
84
84
  port_ocean/core/defaults/clean.py,sha256=_rL-NCl6Q_x3lUxDW5ACOM27IYilTCWl6ISUfRleuL0,2891
85
85
  port_ocean/core/defaults/common.py,sha256=FGB6sshNsU5tD1JLX1C__RiN7tJgQYZhUUxEQzK0sKE,4205
86
- port_ocean/core/defaults/initialize.py,sha256=KcWNoRu5Q8mzuVP-D6iQWfGtdp7T6yeOoZFPSrUmr2Q,11319
86
+ port_ocean/core/defaults/initialize.py,sha256=4nZB9oxwDrZxT-O86l1QfBf6kc_MxhzYQXVNDdNBYnw,13056
87
87
  port_ocean/core/event_listener/__init__.py,sha256=ijqQ0GLcQHzISQFzC4LD3Sfv28NyaHkgohpY-AXlnZU,1374
88
88
  port_ocean/core/event_listener/actions_only.py,sha256=9zDoWESJapn0ZuZ1-WWDd6VJdeP6P3dveALnrdW-FGA,1325
89
89
  port_ocean/core/event_listener/base.py,sha256=WHrlR8GxJDjPB_YgxonJaZ4sUKWpM85SvPQVmXoWeZw,3139
@@ -147,11 +147,11 @@ port_ocean/exceptions/port_defaults.py,sha256=2a7Koy541KxMan33mU-gbauUxsumG3NT4i
147
147
  port_ocean/exceptions/utils.py,sha256=gjOqpi-HpY1l4WlMFsGA9yzhxDhajhoGGdDDyGbLnqI,197
148
148
  port_ocean/exceptions/webhook_processor.py,sha256=4SnkVzVwiacH_Ip4qs1hRHa6GanhnojW_TLTdQQtm7Y,363
149
149
  port_ocean/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
- port_ocean/helpers/async_client.py,sha256=M8gKUjX8ZwRbmJ-U6KNq-p-nfGr0CwHdS0eN_pbZAJ0,2103
150
+ port_ocean/helpers/async_client.py,sha256=GDRNq9kqb-7o6pAxSNZvE7zGh5semTr0oHoADuNjP-E,3325
151
151
  port_ocean/helpers/metric/metric.py,sha256=9pxpDT-nP0nTZ2kIutCTFuF7IwOQcSJ3dkBA1CVSurc,14626
152
152
  port_ocean/helpers/metric/utils.py,sha256=1lAgrxnZLuR_wUNDyPOPzLrm32b8cDdioob2lvnPQ1A,1619
153
153
  port_ocean/helpers/retry.py,sha256=UiOUo89hUrY0VVLL8sMR8GAYg-UVf2Y3yJ-8hBU1I7E,20285
154
- port_ocean/helpers/stream.py,sha256=_UwsThzXynxWzL8OlBT1pmb2evZBi9HaaqeAGNuTuOI,2338
154
+ port_ocean/helpers/stream.py,sha256=i984XbY0hGWTuv7oe4k1byUkCd79D-HVBH3ijxsDgmM,2442
155
155
  port_ocean/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
156
156
  port_ocean/log/handlers.py,sha256=LJ1WAfq7wYCrBpeLPihMKmWjdSahKKXNHFMRYkbk0Co,3630
157
157
  port_ocean/log/logger_setup.py,sha256=wcr5WOkYRtng4pW6ZRl4Av3GqtZ2omSWIqYhB_8Duuc,2700
@@ -171,10 +171,12 @@ port_ocean/tests/clients/oauth/test_oauth_client.py,sha256=2XVMQUalDpiD539Z7_dk5
171
171
  port_ocean/tests/clients/port/mixins/test_entities.py,sha256=jOMJ3ICUlhjjPTo4q6qUrEjTKvXRLUE6KjqjdFiDRBY,10766
172
172
  port_ocean/tests/clients/port/mixins/test_integrations.py,sha256=vRt_EMsLozQC1LJNXxlvnHj3-FlOBGgAYxg5T0IAqtA,7621
173
173
  port_ocean/tests/clients/port/mixins/test_organization_mixin.py,sha256=zzKYz3h8dl4Z5A2QG_924m0y9U6XTth1XYOfwNrd_24,914
174
+ port_ocean/tests/clients/test_streaming_wrapper.py,sha256=uTc0uaNynG7UgbRKNFaHURh8GYdG1O_cbS89veCxk-U,2902
174
175
  port_ocean/tests/config/test_config.py,sha256=Rk4N-ldVSOfn1p23NzdVdfqUpPrqG2cMut4Sv-sAOrw,1023
175
176
  port_ocean/tests/conftest.py,sha256=JXASSS0IY0nnR6bxBflhzxS25kf4iNaABmThyZ0mZt8,101
176
177
  port_ocean/tests/core/conftest.py,sha256=0Oql7R1iTbjPyNdUoO6M21IKknLwnCIgDRz2JQ7nf0w,7748
177
178
  port_ocean/tests/core/defaults/test_common.py,sha256=sR7RqB3ZYV6Xn6NIg-c8k5K6JcGsYZ2SCe_PYX5vLYM,5560
179
+ port_ocean/tests/core/defaults/test_initialize.py,sha256=wx-DyV6ooV4HtwWH6RUaUlpLLK_6sRm7O9jrTtWMeb4,8244
178
180
  port_ocean/tests/core/event_listener/test_kafka.py,sha256=RN_JOCy4aRDUNvyQocO6WFvUMH2XeAZy-PIWHOYnD9M,2888
179
181
  port_ocean/tests/core/handlers/actions/test_execution_manager.py,sha256=5bOlcQ9qcXF_leoSFtw3FzTa7C1awUPo6TSss5e_76w,30753
180
182
  port_ocean/tests/core/handlers/entities_state_applier/test_applier.py,sha256=7XWgwUB9uVYRov4VbIz1A-7n2YLbHTTYT-4rKJxjB0A,10711
@@ -219,8 +221,8 @@ port_ocean/utils/repeat.py,sha256=U2OeCkHPWXmRTVoPV-VcJRlQhcYqPWI5NfmPlb1JIbc,32
219
221
  port_ocean/utils/signal.py,sha256=J1sI-e_32VHP_VUa5bskLMFoJjJOAk5isrnewKDikUI,2125
220
222
  port_ocean/utils/time.py,sha256=pufAOH5ZQI7gXvOvJoQXZXZJV-Dqktoj9Qp9eiRwmJ4,1939
221
223
  port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
222
- port_ocean-0.30.1.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
223
- port_ocean-0.30.1.dist-info/METADATA,sha256=yi01OJ2_QzuHHCv43m_K8j1JdM9cCwBbCMkBEG4ncfw,7054
224
- port_ocean-0.30.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
225
- port_ocean-0.30.1.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
226
- port_ocean-0.30.1.dist-info/RECORD,,
224
+ port_ocean-0.30.3.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
225
+ port_ocean-0.30.3.dist-info/METADATA,sha256=fgABnumshGTta5I9-Dm9mu1WHQa4uPmZrSx6E3VZ7do,7095
226
+ port_ocean-0.30.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
227
+ port_ocean-0.30.3.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
228
+ port_ocean-0.30.3.dist-info/RECORD,,