port-ocean 0.10.11__py3-none-any.whl → 0.11.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.

Potentially problematic release.


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

@@ -1,11 +1,10 @@
1
1
  import asyncio
2
- import functools
3
2
  from asyncio import Task
4
3
  from dataclasses import dataclass, field
5
4
  from functools import lru_cache
6
5
  from typing import Any, Optional
7
6
 
8
- import pyjq as jq # type: ignore
7
+ import jq # type: ignore
9
8
  from loguru import logger
10
9
 
11
10
  from port_ocean.context.ocean import ocean
@@ -52,8 +51,8 @@ class JQEntityProcessor(BaseEntityProcessor):
52
51
  try:
53
52
  loop = asyncio.get_event_loop()
54
53
  compiled_pattern = self._compile(pattern)
55
- first_value_callable = functools.partial(compiled_pattern.first, data)
56
- return await loop.run_in_executor(None, first_value_callable)
54
+ func = compiled_pattern.input_value(data)
55
+ return await loop.run_in_executor(None, func.first)
57
56
  except Exception as exc:
58
57
  logger.debug(
59
58
  f"Failed to search for pattern {pattern} in data {data}, {exc}"
@@ -62,10 +61,18 @@ class JQEntityProcessor(BaseEntityProcessor):
62
61
 
63
62
  async def _search_as_bool(self, data: dict[str, Any], pattern: str) -> bool:
64
63
  loop = asyncio.get_event_loop()
64
+ start_time = loop.time()
65
65
  compiled_pattern = self._compile(pattern)
66
- first_value_callable = functools.partial(compiled_pattern.first, data)
67
- value = await loop.run_in_executor(None, first_value_callable)
68
-
66
+ func = compiled_pattern.input_value(data)
67
+ compile_time = loop.time() - start_time
68
+ value = await loop.run_in_executor(None, func.first)
69
+ execute_time = loop.time() - start_time - compile_time
70
+ logger.debug(
71
+ f"Search for pattern {execute_time:.2f} seconds, compile time {compile_time:.2f} seconds",
72
+ pattern=pattern,
73
+ compile_time=compile_time,
74
+ execute_time=execute_time,
75
+ )
69
76
  if isinstance(value, bool):
70
77
  return value
71
78
 
@@ -54,7 +54,7 @@ class BaseIntegration(SyncRawMixin, SyncMixin):
54
54
  """
55
55
  Initializes handlers, establishes integration at the specified port, and starts the event listener.
56
56
  """
57
- logger.info("Starting integration")
57
+ logger.info("Starting integration", integration_type=self.context.config.integration.type)
58
58
  if self.started:
59
59
  raise IntegrationAlreadyStartedException("Integration already started")
60
60
 
@@ -456,7 +456,8 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
456
456
 
457
457
  creation_results.append(await task)
458
458
  except asyncio.CancelledError as e:
459
- logger.warning("Resync aborted successfully")
459
+ logger.warning("Resync aborted successfully, skipping delete phase. This leads to an incomplete state")
460
+ raise
460
461
  else:
461
462
  if not did_fetched_current_state:
462
463
  logger.warning(
@@ -489,3 +490,4 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
489
490
  {"before": entities_at_port, "after": flat_created_entities},
490
491
  user_agent_type,
491
492
  )
493
+ logger.info("Resync finished successfully")
port_ocean/ocean.py CHANGED
@@ -82,6 +82,10 @@ class Ocean:
82
82
  try:
83
83
  await self.integration.sync_raw_all()
84
84
  await self.resync_state_updater.update_after_resync()
85
+ except asyncio.CancelledError:
86
+ logger.warning(
87
+ "resync was cancelled by the scheduled resync, skipping state update"
88
+ )
85
89
  except Exception as e:
86
90
  await self.resync_state_updater.update_after_resync(
87
91
  IntegrationStateStatus.Failed
@@ -92,7 +96,8 @@ class Ocean:
92
96
  loop = asyncio.get_event_loop()
93
97
  if interval is not None:
94
98
  logger.info(
95
- f"Setting up scheduled resync, the integration will automatically perform a full resync every {interval} minutes)"
99
+ f"Setting up scheduled resync, the integration will automatically perform a full resync every {interval} minutes)",
100
+ scheduled_interval=interval,
96
101
  )
97
102
  repeated_function = repeat_every(
98
103
  seconds=interval * 60,
@@ -0,0 +1,236 @@
1
+ from typing import Any
2
+ from unittest.mock import AsyncMock, Mock
3
+ import pytest
4
+
5
+ from port_ocean.context.ocean import PortOceanContext
6
+ from port_ocean.core.handlers.entity_processor.jq_entity_processor import (
7
+ JQEntityProcessor,
8
+ )
9
+ from port_ocean.core.ocean_types import CalculationResult
10
+ from port_ocean.exceptions.core import EntityProcessorException
11
+
12
+
13
+ @pytest.mark.asyncio
14
+ class TestJQEntityProcessor:
15
+
16
+ @pytest.fixture
17
+ def mocked_processor(self, monkeypatch: Any) -> JQEntityProcessor:
18
+ mock_context = AsyncMock()
19
+ monkeypatch.setattr(PortOceanContext, "app", mock_context)
20
+ return JQEntityProcessor(mock_context)
21
+
22
+ async def test_compile(self, mocked_processor: JQEntityProcessor) -> None:
23
+ pattern = ".foo"
24
+ compiled = mocked_processor._compile(pattern)
25
+ assert compiled is not None
26
+
27
+ async def test_search(self, mocked_processor: JQEntityProcessor) -> None:
28
+ data = {"foo": "bar"}
29
+ pattern = ".foo"
30
+ result = await mocked_processor._search(data, pattern)
31
+ assert result == "bar"
32
+
33
+ async def test_search_as_bool(self, mocked_processor: JQEntityProcessor) -> None:
34
+ data = {"foo": True}
35
+ pattern = ".foo"
36
+ result = await mocked_processor._search_as_bool(data, pattern)
37
+ assert result is True
38
+
39
+ async def test_search_as_object(self, mocked_processor: JQEntityProcessor) -> None:
40
+ data = {"foo": {"bar": "baz"}}
41
+ obj = {"foo": ".foo.bar"}
42
+ result = await mocked_processor._search_as_object(data, obj)
43
+ assert result == {"foo": "baz"}
44
+
45
+ async def test_get_mapped_entity(self, mocked_processor: JQEntityProcessor) -> None:
46
+ data = {"foo": "bar"}
47
+ raw_entity_mappings = {"foo": ".foo"}
48
+ selector_query = '.foo == "bar"'
49
+ result = await mocked_processor._get_mapped_entity(
50
+ data, raw_entity_mappings, selector_query
51
+ )
52
+ assert result.entity == {"foo": "bar"}
53
+ assert result.did_entity_pass_selector is True
54
+
55
+ async def test_calculate_entity(self, mocked_processor: JQEntityProcessor) -> None:
56
+ data = {"foo": "bar"}
57
+ raw_entity_mappings = {"foo": ".foo"}
58
+ selector_query = '.foo == "bar"'
59
+ result, errors = await mocked_processor._calculate_entity(
60
+ data, raw_entity_mappings, None, selector_query
61
+ )
62
+ assert len(result) == 1
63
+ assert result[0].entity == {"foo": "bar"}
64
+ assert result[0].did_entity_pass_selector is True
65
+ assert not errors
66
+
67
+ async def test_parse_items(self, mocked_processor: JQEntityProcessor) -> None:
68
+ mapping = Mock()
69
+ mapping.port.entity.mappings.dict.return_value = {
70
+ "identifier": ".foo",
71
+ "blueprint": ".foo",
72
+ "properties": {"foo": ".foo"},
73
+ }
74
+ mapping.port.items_to_parse = None
75
+ mapping.selector.query = '.foo == "bar"'
76
+ raw_results = [{"foo": "bar"}]
77
+ result = await mocked_processor._parse_items(mapping, raw_results)
78
+ assert isinstance(result, CalculationResult)
79
+ assert len(result.entity_selector_diff.passed) == 1
80
+ assert result.entity_selector_diff.passed[0].properties.get("foo") == "bar"
81
+ assert not result.errors
82
+
83
+ async def test_in_operator(self, mocked_processor: JQEntityProcessor) -> None:
84
+ data = {
85
+ "key": "GetPort_SelfService",
86
+ "name": "GetPort SelfService",
87
+ "desc": "Test",
88
+ "qualifier": "VW",
89
+ "visibility": "public",
90
+ "selectionMode": "NONE",
91
+ "subViews": [
92
+ {
93
+ "key": "GetPort_SelfService_Second",
94
+ "name": "GetPort SelfService Second",
95
+ "qualifier": "SVW",
96
+ "selectionMode": "NONE",
97
+ "subViews": [
98
+ {
99
+ "key": "GetPort_SelfService_Third",
100
+ "name": "GetPort SelfService Third",
101
+ "qualifier": "SVW",
102
+ "selectionMode": "NONE",
103
+ "subViews": [],
104
+ "referencedBy": [],
105
+ },
106
+ {
107
+ "key": "Port_Test",
108
+ "name": "Port Test",
109
+ "qualifier": "SVW",
110
+ "selectionMode": "NONE",
111
+ "subViews": [],
112
+ "referencedBy": [],
113
+ },
114
+ ],
115
+ "referencedBy": [],
116
+ },
117
+ {
118
+ "key": "Python",
119
+ "name": "Python",
120
+ "qualifier": "SVW",
121
+ "selectionMode": "NONE",
122
+ "subViews": [
123
+ {
124
+ "key": "Time",
125
+ "name": "Time",
126
+ "qualifier": "SVW",
127
+ "selectionMode": "NONE",
128
+ "subViews": [
129
+ {
130
+ "key": "port_*****",
131
+ "name": "port-*****",
132
+ "qualifier": "SVW",
133
+ "selectionMode": "NONE",
134
+ "subViews": [
135
+ {
136
+ "key": "port_*****:REferenced",
137
+ "name": "REferenced",
138
+ "qualifier": "VW",
139
+ "visibility": "public",
140
+ "originalKey": "REferenced",
141
+ }
142
+ ],
143
+ "referencedBy": [],
144
+ }
145
+ ],
146
+ "referencedBy": [],
147
+ }
148
+ ],
149
+ "referencedBy": [],
150
+ },
151
+ {
152
+ "key": "GetPort_SelfService:Authentication_Application",
153
+ "name": "Authentication Application",
154
+ "desc": "For auth services",
155
+ "qualifier": "APP",
156
+ "visibility": "private",
157
+ "selectedBranches": ["main"],
158
+ "originalKey": "Authentication_Application",
159
+ },
160
+ ],
161
+ "referencedBy": [],
162
+ }
163
+ pattern = '.subViews | map(select((.qualifier | IN("VW", "SVW"))) | .key)'
164
+ result = await mocked_processor._search(data, pattern)
165
+ assert result == ["GetPort_SelfService_Second", "Python"]
166
+
167
+ async def test_failure_of_jq_expression(
168
+ self, mocked_processor: JQEntityProcessor
169
+ ) -> None:
170
+ data = {"foo": "bar"}
171
+ pattern = ".foo."
172
+ result = await mocked_processor._search(data, pattern)
173
+ assert result is None
174
+
175
+ async def test_search_as_object_failure(
176
+ self, mocked_processor: JQEntityProcessor
177
+ ) -> None:
178
+ data = {"foo": {"bar": "baz"}}
179
+ obj = {"foo": ".foo.bar."}
180
+ result = await mocked_processor._search_as_object(data, obj)
181
+ assert result == {"foo": None}
182
+
183
+ async def test_double_quotes_in_jq_expression(
184
+ self, mocked_processor: JQEntityProcessor
185
+ ) -> None:
186
+ data = {"foo": "bar"}
187
+ pattern = '"shalom"'
188
+ result = await mocked_processor._search(data, pattern)
189
+ assert result == "shalom"
190
+
191
+ async def test_search_as_bool_failure(
192
+ self, mocked_processor: JQEntityProcessor
193
+ ) -> None:
194
+ data = {"foo": "bar"}
195
+ pattern = ".foo"
196
+ with pytest.raises(
197
+ EntityProcessorException,
198
+ match="Expected boolean value, got <class 'str'> instead",
199
+ ):
200
+ await mocked_processor._search_as_bool(data, pattern)
201
+
202
+ @pytest.mark.timeout(3)
203
+ async def test_search_performance_10000(
204
+ self, mocked_processor: JQEntityProcessor
205
+ ) -> None:
206
+ """
207
+ This test is to check the performance of the search method when called 10000 times.
208
+ """
209
+ data = {"foo": "bar"}
210
+ pattern = ".foo"
211
+ for _ in range(10000):
212
+ result = await mocked_processor._search(data, pattern)
213
+ assert result == "bar"
214
+
215
+ @pytest.mark.timeout(15)
216
+ async def test_parse_items_performance_10000(
217
+ self, mocked_processor: JQEntityProcessor
218
+ ) -> None:
219
+ """
220
+ This test is to check the performance of the parse_items method when called 10000 times.
221
+ """
222
+ mapping = Mock()
223
+ mapping.port.entity.mappings.dict.return_value = {
224
+ "identifier": ".foo",
225
+ "blueprint": ".foo",
226
+ "properties": {"foo": ".foo"},
227
+ }
228
+ mapping.port.items_to_parse = None
229
+ mapping.selector.query = '.foo == "bar"'
230
+ raw_results = [{"foo": "bar"}]
231
+ for _ in range(10000):
232
+ result = await mocked_processor._parse_items(mapping, raw_results)
233
+ assert isinstance(result, CalculationResult)
234
+ assert len(result.entity_selector_diff.passed) == 1
235
+ assert result.entity_selector_diff.passed[0].properties.get("foo") == "bar"
236
+ assert not result.errors
@@ -2,6 +2,7 @@ from os import environ, path
2
2
  from typing import Any, AsyncGenerator, Callable, List, Tuple, Union
3
3
 
4
4
  import pytest_asyncio
5
+ from loguru import logger
5
6
  from pydantic import BaseModel
6
7
 
7
8
  from port_ocean.clients.port.client import PortClient
@@ -33,15 +34,28 @@ def get_port_client_for_integration(
33
34
 
34
35
  async def cleanup_integration(client: PortClient, blueprints: List[str]) -> None:
35
36
  for blueprint in blueprints:
36
- bp = await client.get_blueprint(blueprint)
37
- if bp is not None:
38
- migration_id = await client.delete_blueprint(
39
- identifier=blueprint, delete_entities=True
40
- )
41
- if migration_id:
42
- await client.wait_for_migration_to_complete(migration_id=migration_id)
37
+ try:
38
+ bp = await client.get_blueprint(blueprint)
39
+ if bp is not None:
40
+ migration_id = await client.delete_blueprint(
41
+ identifier=blueprint, delete_entities=True
42
+ )
43
+ if migration_id:
44
+ await client.wait_for_migration_to_complete(
45
+ migration_id=migration_id
46
+ )
47
+ except Exception as bp_e:
48
+ logger.info(f"Skipping missing blueprint ({blueprint}): {bp_e}")
43
49
  headers = await client.auth.headers()
44
- await client.client.delete(f"{client.auth.api_url}/integrations", headers=headers)
50
+ try:
51
+ await client.client.delete(
52
+ f"{client.auth.api_url}/integrations/{client.integration_identifier}",
53
+ headers=headers,
54
+ )
55
+ except Exception as int_e:
56
+ logger.info(
57
+ f"Failed to delete integration ({client.integration_identifier}): {int_e}"
58
+ )
45
59
 
46
60
 
47
61
  class SmokeTestDetails(BaseModel):
@@ -7,6 +7,9 @@ from port_ocean.clients.port.types import UserAgentType
7
7
  from port_ocean.tests.helpers.fixtures import SmokeTestDetails
8
8
 
9
9
 
10
+ pytestmark = pytest.mark.smoke
11
+
12
+
10
13
  @pytest.mark.skipif(
11
14
  environ.get("SMOKE_TEST_SUFFIX", None) is None,
12
15
  reason="You need to run the fake integration once",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.10.11
3
+ Version: 0.11.0
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
@@ -28,11 +28,11 @@ Requires-Dist: cookiecutter (>=2.1.1,<3.0.0) ; extra == "cli"
28
28
  Requires-Dist: fastapi (>=0.100,<0.112)
29
29
  Requires-Dist: httpx (>=0.24.1,<0.28.0)
30
30
  Requires-Dist: jinja2-time (>=0.2.0,<0.3.0) ; extra == "cli"
31
+ Requires-Dist: jq (>=1.8.0,<2.0.0)
31
32
  Requires-Dist: loguru (>=0.7.0,<0.8.0)
32
33
  Requires-Dist: pydantic[dotenv] (>=1.10.8,<2.0.0)
33
34
  Requires-Dist: pydispatcher (>=2.0.7,<3.0.0)
34
35
  Requires-Dist: pyhumps (>=3.8.0,<4.0.0)
35
- Requires-Dist: pyjq (>=2.6.0,<3.0.0)
36
36
  Requires-Dist: python-dateutil (>=2.9.0.post0,<3.0.0)
37
37
  Requires-Dist: pyyaml (>=6.0,<7.0)
38
38
  Requires-Dist: rich (>=13.4.1,<14.0.0) ; extra == "cli"
@@ -81,7 +81,7 @@ port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py,sha
81
81
  port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py,sha256=82BvU8t5w9uhsxX8hbnwuRPuWhW3cMeuT_5sVIkip1I,1550
82
82
  port_ocean/core/handlers/entity_processor/__init__.py,sha256=FvFCunFg44wNQoqlybem9MthOs7p1Wawac87uSXz9U8,156
83
83
  port_ocean/core/handlers/entity_processor/base.py,sha256=udR0w5TstTOS5xOfTjAZIEdldn4xr6Oyb3DylatYX3Q,1869
84
- port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=_nQtlY0ZcCDf_Mpq4qcG7vVQ8LJS6DfkFMv-NHyFiJI,8421
84
+ port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=HQ3lnOqNITHxSn0_9TXZFaQYfMZvvPaJwnsvlNKGDKQ,8703
85
85
  port_ocean/core/handlers/port_app_config/__init__.py,sha256=8AAT5OthiVM7KCcM34iEgEeXtn2pRMrT4Dze5r1Ixbk,134
86
86
  port_ocean/core/handlers/port_app_config/api.py,sha256=6VbKPwFzsWG0IYsVD81hxSmfqtHUFqrfUuj1DBX5g4w,853
87
87
  port_ocean/core/handlers/port_app_config/base.py,sha256=4Nxt2g8voEIHJ4Y1Km5NJcaG2iSbCklw5P8-Kus7Y9k,3007
@@ -89,12 +89,12 @@ port_ocean/core/handlers/port_app_config/models.py,sha256=YvYtf_44KD_rN4xK-3xHtd
89
89
  port_ocean/core/handlers/resync_state_updater/__init__.py,sha256=kG6y-JQGpPfuTHh912L_bctIDCzAK4DN-d00S7rguWU,81
90
90
  port_ocean/core/handlers/resync_state_updater/updater.py,sha256=Yg9ET6ZV5B9GW7u6zZA6GlB_71kmvxvYX2FWgQNzMvo,3182
91
91
  port_ocean/core/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
92
- port_ocean/core/integrations/base.py,sha256=KHsRYFZ38ff3AkkqIQu45883ovgKOJn_fZfnTNy7HWY,2952
92
+ port_ocean/core/integrations/base.py,sha256=JxqQApEf7phi_Q_b4U0mKNomxIPdDyKPq3AbApFmhjU,3007
93
93
  port_ocean/core/integrations/mixins/__init__.py,sha256=FA1FEKMM6P-L2_m7Q4L20mFa4_RgZnwSRmTCreKcBVM,220
94
94
  port_ocean/core/integrations/mixins/events.py,sha256=Ddfx2L4FpghV38waF8OfVeOV0bHBxNIgjU-q5ffillI,2341
95
95
  port_ocean/core/integrations/mixins/handler.py,sha256=mZ7-0UlG3LcrwJttFbMe-R4xcOU2H_g33tZar7PwTv8,3771
96
96
  port_ocean/core/integrations/mixins/sync.py,sha256=B9fEs8faaYLLikH9GBjE_E61vo0bQDjIGQsQ1SRXOlA,3931
97
- port_ocean/core/integrations/mixins/sync_raw.py,sha256=nPYlUTQdh6HDIqBwh3jQ-hmraNx4CeSK9YQ98NTonbQ,18697
97
+ port_ocean/core/integrations/mixins/sync_raw.py,sha256=BGS5EnZ2N3ifcAi94Wo-ZassSJ-_Se9eFJMpBDT7pNY,18841
98
98
  port_ocean/core/integrations/mixins/utils.py,sha256=7y1rGETZIjOQadyIjFJXIHKkQFKx_SwiP-TrAIsyyLY,2303
99
99
  port_ocean/core/models.py,sha256=dJ2_olTdbjUpObQJNmg7e7EENU_zZiX6XOaknNp54B0,1342
100
100
  port_ocean/core/ocean_types.py,sha256=3_d8-n626f1kWLQ_Jxw194LEyrOVupz05qs_Y1pvB-A,990
@@ -115,18 +115,18 @@ port_ocean/log/handlers.py,sha256=k9G_Mb4ga2-Jke9irpdlYqj6EYiwv0gEsh4TgyqqOmI,28
115
115
  port_ocean/log/logger_setup.py,sha256=BaXt-mh9CVXhneh37H46d04lqOdIBixG1pFyGfotuZs,2328
116
116
  port_ocean/log/sensetive.py,sha256=wkyvkKMbyLTjZDSbvvLHL9bv4RvD0DPAyL3uWSttUOA,2916
117
117
  port_ocean/middlewares.py,sha256=9wYCdyzRZGK1vjEJ28FY_DkfwDNENmXp504UKPf5NaQ,2727
118
- port_ocean/ocean.py,sha256=0dtaiRxKgY3kYNm1ZI3uFCJRhnNoTMwVv-PkWlLJQrQ,4842
118
+ port_ocean/ocean.py,sha256=Oe4H3kKtkj52uNO4Rd_47iY3MBdrTtshXZ_16q7A8bM,5071
119
119
  port_ocean/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
120
120
  port_ocean/run.py,sha256=rTxBlrQd4yyrtgErCFJCHCEHs7d1OXrRiJehUYmIbN0,2212
121
121
  port_ocean/sonar-project.properties,sha256=X_wLzDOkEVmpGLRMb2fg9Rb0DxWwUFSvESId8qpvrPI,73
122
122
  port_ocean/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
123
  port_ocean/tests/clients/port/mixins/test_entities.py,sha256=A9myrnkLhKSQrnOLv1Zz2wiOVSxW65Q9RIUIRbn_V7w,1586
124
124
  port_ocean/tests/conftest.py,sha256=JXASSS0IY0nnR6bxBflhzxS25kf4iNaABmThyZ0mZt8,101
125
+ port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py,sha256=fqhlLTFkP0SS12bqViYWgqayNGXWZhqpDSJObHVRnNg,9472
125
126
  port_ocean/tests/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
126
- port_ocean/tests/helpers/fixtures.py,sha256=XGR8wjcAKBBYoIRKh_KzFg1PdqhlL9GqqR8z_q08nHA,3699
127
+ port_ocean/tests/helpers/fixtures.py,sha256=hnHC1Heey1FwlCb0gt6smD5dAz0M3XOvi9HkRN71LZk,4152
127
128
  port_ocean/tests/helpers/ocean_app.py,sha256=Dp1bwEDhWsx_G-KVxOfJX1eVIS4168ajLu39wAY275g,1693
128
- port_ocean/tests/test_sample.py,sha256=Ew5LA_G1k6DC5a2ygU2FoyjZQa0fRmPy73N0bio0d14,46
129
- port_ocean/tests/test_smoke.py,sha256=F-1MoEcdIT1smjWv3s1iaS7U5UxpKGf-AHc8mYHjOlw,2522
129
+ port_ocean/tests/test_smoke.py,sha256=LI_P1ZN56d5_FJaFHwjsWjqm8adGTpjlkgdVVh0fbXg,2555
130
130
  port_ocean/utils/__init__.py,sha256=KMGnCPXZJbNwtgxtyMycapkDz8tpSyw23MSYT3iVeHs,91
131
131
  port_ocean/utils/async_http.py,sha256=arnH458TExn2Dju_Sy6pHas_vF5RMWnOp-jBz5WAAcE,1226
132
132
  port_ocean/utils/async_iterators.py,sha256=iw3cUHxfQm3zUSPdw2FmSXDU8E1Ppnys4TGhswNuQ8s,1569
@@ -137,8 +137,8 @@ port_ocean/utils/repeat.py,sha256=0EFWM9d8lLXAhZmAyczY20LAnijw6UbIECf5lpGbOas,32
137
137
  port_ocean/utils/signal.py,sha256=K-6kKFQTltcmKDhtyZAcn0IMa3sUpOHGOAUdWKgx0_E,1369
138
138
  port_ocean/utils/time.py,sha256=pufAOH5ZQI7gXvOvJoQXZXZJV-Dqktoj9Qp9eiRwmJ4,1939
139
139
  port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
140
- port_ocean-0.10.11.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
141
- port_ocean-0.10.11.dist-info/METADATA,sha256=SffnArX7jyPJC_Tu_66jLqUtGwspuroiBDAycOH1RYY,6617
142
- port_ocean-0.10.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
143
- port_ocean-0.10.11.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
144
- port_ocean-0.10.11.dist-info/RECORD,,
140
+ port_ocean-0.11.0.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
141
+ port_ocean-0.11.0.dist-info/METADATA,sha256=wyTAEI3z-dSpeCraOy7_SmwOLiwjjXrda5Y_LJA9kNE,6614
142
+ port_ocean-0.11.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
143
+ port_ocean-0.11.0.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
144
+ port_ocean-0.11.0.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- def test_example() -> None:
2
- assert 1 == 1