port-ocean 0.10.10__py3-none-any.whl → 0.10.12__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.
- port_ocean/core/integrations/mixins/sync_raw.py +3 -1
- port_ocean/ocean.py +4 -0
- port_ocean/tests/conftest.py +4 -0
- port_ocean/tests/helpers/__init__.py +0 -80
- port_ocean/tests/helpers/fixtures.py +110 -0
- port_ocean/tests/helpers/ocean_app.py +54 -0
- port_ocean/tests/test_smoke.py +71 -0
- {port_ocean-0.10.10.dist-info → port_ocean-0.10.12.dist-info}/METADATA +1 -1
- {port_ocean-0.10.10.dist-info → port_ocean-0.10.12.dist-info}/RECORD +12 -8
- {port_ocean-0.10.10.dist-info → port_ocean-0.10.12.dist-info}/LICENSE.md +0 -0
- {port_ocean-0.10.10.dist-info → port_ocean-0.10.12.dist-info}/WHEEL +0 -0
- {port_ocean-0.10.10.dist-info → port_ocean-0.10.12.dist-info}/entry_points.txt +0 -0
|
@@ -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
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
from inspect import getmembers
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from typing import Dict, List, Set, Tuple, Union
|
|
5
|
-
|
|
6
|
-
from yaml import safe_load
|
|
7
|
-
|
|
8
|
-
from port_ocean.bootstrap import create_default_app
|
|
9
|
-
from port_ocean.core.handlers.port_app_config.models import ResourceConfig
|
|
10
|
-
from port_ocean.core.ocean_types import RESYNC_RESULT
|
|
11
|
-
from port_ocean.ocean import Ocean
|
|
12
|
-
from port_ocean.utils.misc import get_spec_file, load_module
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def get_integration_ocean_app(integration_path: str) -> Ocean:
|
|
16
|
-
spec_file = get_spec_file(Path(integration_path))
|
|
17
|
-
|
|
18
|
-
config_factory = None if not spec_file else spec_file.get("configurations", [])
|
|
19
|
-
|
|
20
|
-
default_app = create_default_app(
|
|
21
|
-
integration_path,
|
|
22
|
-
config_factory,
|
|
23
|
-
{
|
|
24
|
-
"port": {
|
|
25
|
-
"client_id": "bla",
|
|
26
|
-
"client_secret": "bla",
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
)
|
|
30
|
-
main_path = f"{integration_path}/main.py"
|
|
31
|
-
sys.path.append(integration_path)
|
|
32
|
-
app_module = load_module(main_path)
|
|
33
|
-
app: Ocean = {name: item for name, item in getmembers(app_module)}.get(
|
|
34
|
-
"app", default_app
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
return app
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def get_integation_resource_configs(integration_path: str) -> List[ResourceConfig]:
|
|
41
|
-
with open(
|
|
42
|
-
f"{integration_path}/.port/resources/port-app-config.yml"
|
|
43
|
-
) as port_app_config_file:
|
|
44
|
-
resource_configs = safe_load(port_app_config_file)
|
|
45
|
-
|
|
46
|
-
return [ResourceConfig(**item) for item in resource_configs["resources"]]
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def get_integation_resource_config_by_name(
|
|
50
|
-
integration_path: str, kind: str
|
|
51
|
-
) -> Union[ResourceConfig, None]:
|
|
52
|
-
resource_configs = get_integation_resource_configs(integration_path)
|
|
53
|
-
|
|
54
|
-
relevant_configs = [x for x in resource_configs if x.kind == kind]
|
|
55
|
-
|
|
56
|
-
return relevant_configs[0] if len(relevant_configs) else None
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
async def get_raw_result_on_integration_sync_kinds(
|
|
60
|
-
integration_path: str, override_kinds: Union[Set[str], None] = None
|
|
61
|
-
) -> Dict[str, List[Tuple[RESYNC_RESULT, List[Exception]]]]:
|
|
62
|
-
app = get_integration_ocean_app(integration_path)
|
|
63
|
-
|
|
64
|
-
resource_configs = get_integation_resource_configs(integration_path)
|
|
65
|
-
|
|
66
|
-
if override_kinds:
|
|
67
|
-
resource_configs = [x for x in resource_configs if x.kind in override_kinds]
|
|
68
|
-
|
|
69
|
-
results: Dict[str, List[Tuple[RESYNC_RESULT, List[Exception]]]] = {}
|
|
70
|
-
|
|
71
|
-
for resource_config in resource_configs:
|
|
72
|
-
resource_result = await app.integration._get_resource_raw_results(
|
|
73
|
-
resource_config
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
results[resource_config.kind] = results.get(resource_config.kind, []) + [
|
|
77
|
-
resource_result
|
|
78
|
-
]
|
|
79
|
-
|
|
80
|
-
return results
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
from os import environ, path
|
|
2
|
+
from typing import Any, AsyncGenerator, Callable, List, Tuple, Union
|
|
3
|
+
|
|
4
|
+
import pytest_asyncio
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
from port_ocean.clients.port.client import PortClient
|
|
8
|
+
from port_ocean.core.handlers.port_app_config.models import ResourceConfig
|
|
9
|
+
from port_ocean.ocean import Ocean
|
|
10
|
+
from port_ocean.tests.helpers.ocean_app import (
|
|
11
|
+
get_integation_resource_configs,
|
|
12
|
+
get_integration_ocean_app,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_port_client_for_integration(
|
|
17
|
+
client_id: str,
|
|
18
|
+
client_secret: str,
|
|
19
|
+
integration_identifier: str,
|
|
20
|
+
integration_type: str,
|
|
21
|
+
integration_version: str,
|
|
22
|
+
base_url: Union[str, None],
|
|
23
|
+
) -> PortClient:
|
|
24
|
+
return PortClient(
|
|
25
|
+
base_url=base_url or "https://api.getport/io",
|
|
26
|
+
client_id=client_id,
|
|
27
|
+
client_secret=client_secret,
|
|
28
|
+
integration_identifier=integration_identifier,
|
|
29
|
+
integration_type=integration_type,
|
|
30
|
+
integration_version=integration_version,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def cleanup_integration(client: PortClient, blueprints: List[str]) -> None:
|
|
35
|
+
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)
|
|
43
|
+
headers = await client.auth.headers()
|
|
44
|
+
await client.client.delete(f"{client.auth.api_url}/integrations", headers=headers)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SmokeTestDetails(BaseModel):
|
|
48
|
+
integration_identifier: str
|
|
49
|
+
blueprint_department: str
|
|
50
|
+
blueprint_person: str
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@pytest_asyncio.fixture()
|
|
54
|
+
async def port_client_for_fake_integration() -> (
|
|
55
|
+
AsyncGenerator[Tuple[SmokeTestDetails, PortClient], None]
|
|
56
|
+
):
|
|
57
|
+
blueprint_department = "fake-department"
|
|
58
|
+
blueprint_person = "fake-person"
|
|
59
|
+
integration_identifier = "smoke-test-integration"
|
|
60
|
+
smoke_test_suffix = environ.get("SMOKE_TEST_SUFFIX")
|
|
61
|
+
client_id = environ.get("PORT_CLIENT_ID")
|
|
62
|
+
client_secret = environ.get("PORT_CLIENT_SECRET")
|
|
63
|
+
|
|
64
|
+
if not client_secret or not client_id:
|
|
65
|
+
assert False, "Missing port credentials"
|
|
66
|
+
|
|
67
|
+
base_url = environ.get("PORT_BASE_URL")
|
|
68
|
+
integration_version = "0.1.1-dev"
|
|
69
|
+
integration_type = "smoke-test"
|
|
70
|
+
if smoke_test_suffix is not None:
|
|
71
|
+
integration_identifier = f"{integration_identifier}-{smoke_test_suffix}"
|
|
72
|
+
blueprint_person = f"{blueprint_person}-{smoke_test_suffix}"
|
|
73
|
+
blueprint_department = f"{blueprint_department}-{smoke_test_suffix}"
|
|
74
|
+
|
|
75
|
+
client = get_port_client_for_integration(
|
|
76
|
+
client_id,
|
|
77
|
+
client_secret,
|
|
78
|
+
integration_identifier,
|
|
79
|
+
integration_type,
|
|
80
|
+
integration_version,
|
|
81
|
+
base_url,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
smoke_test_details = SmokeTestDetails(
|
|
85
|
+
integration_identifier=integration_identifier,
|
|
86
|
+
blueprint_person=blueprint_person,
|
|
87
|
+
blueprint_department=blueprint_department,
|
|
88
|
+
)
|
|
89
|
+
yield smoke_test_details, client
|
|
90
|
+
await cleanup_integration(client, [blueprint_department, blueprint_person])
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@pytest_asyncio.fixture
|
|
94
|
+
def get_mocked_ocean_app(request: Any) -> Callable[[], Ocean]:
|
|
95
|
+
test_dir = path.join(path.dirname(request.module.__file__), "..")
|
|
96
|
+
|
|
97
|
+
def get_ocean_app() -> Ocean:
|
|
98
|
+
return get_integration_ocean_app(test_dir)
|
|
99
|
+
|
|
100
|
+
return get_ocean_app
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@pytest_asyncio.fixture
|
|
104
|
+
def get_mock_ocean_resource_configs(request: Any) -> Callable[[], List[ResourceConfig]]:
|
|
105
|
+
module_dir = path.join(path.dirname(request.module.__file__), "..")
|
|
106
|
+
|
|
107
|
+
def get_ocean_resource_configs() -> List[ResourceConfig]:
|
|
108
|
+
return get_integation_resource_configs(module_dir)
|
|
109
|
+
|
|
110
|
+
return get_ocean_resource_configs
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
from inspect import getmembers
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import List, Tuple
|
|
5
|
+
|
|
6
|
+
from yaml import safe_load
|
|
7
|
+
|
|
8
|
+
from port_ocean.bootstrap import create_default_app
|
|
9
|
+
from port_ocean.core.handlers.port_app_config.models import ResourceConfig
|
|
10
|
+
from port_ocean.core.ocean_types import RESYNC_RESULT
|
|
11
|
+
from port_ocean.ocean import Ocean
|
|
12
|
+
from port_ocean.utils.misc import get_spec_file, load_module
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_integration_ocean_app(integration_path: str) -> Ocean:
|
|
16
|
+
spec_file = get_spec_file(Path(integration_path))
|
|
17
|
+
|
|
18
|
+
config_factory = None if not spec_file else spec_file.get("configurations", [])
|
|
19
|
+
|
|
20
|
+
default_app = create_default_app(
|
|
21
|
+
integration_path,
|
|
22
|
+
config_factory,
|
|
23
|
+
{
|
|
24
|
+
"port": {
|
|
25
|
+
"client_id": "bla",
|
|
26
|
+
"client_secret": "bla",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
)
|
|
30
|
+
main_path = f"{integration_path}/main.py"
|
|
31
|
+
sys.path.append(integration_path)
|
|
32
|
+
app_module = load_module(main_path)
|
|
33
|
+
app: Ocean = {name: item for name, item in getmembers(app_module)}.get(
|
|
34
|
+
"app", default_app
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
return app
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_integation_resource_configs(integration_path: str) -> List[ResourceConfig]:
|
|
41
|
+
with open(
|
|
42
|
+
f"{integration_path}/.port/resources/port-app-config.yml"
|
|
43
|
+
) as port_app_config_file:
|
|
44
|
+
resource_configs = safe_load(port_app_config_file)
|
|
45
|
+
|
|
46
|
+
return [ResourceConfig(**item) for item in resource_configs["resources"]]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def get_raw_result_on_integration_sync_resource_config(
|
|
50
|
+
app: Ocean, resource_config: ResourceConfig
|
|
51
|
+
) -> Tuple[RESYNC_RESULT, List[Exception]]:
|
|
52
|
+
resource_result = await app.integration._get_resource_raw_results(resource_config)
|
|
53
|
+
|
|
54
|
+
return resource_result
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
from os import environ
|
|
2
|
+
from typing import Tuple
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from port_ocean.clients.port.client import PortClient
|
|
6
|
+
from port_ocean.clients.port.types import UserAgentType
|
|
7
|
+
from port_ocean.tests.helpers.fixtures import SmokeTestDetails
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.mark.skipif(
|
|
11
|
+
environ.get("SMOKE_TEST_SUFFIX", None) is None,
|
|
12
|
+
reason="You need to run the fake integration once",
|
|
13
|
+
)
|
|
14
|
+
async def test_valid_fake_integration(
|
|
15
|
+
port_client_for_fake_integration: Tuple[SmokeTestDetails, PortClient],
|
|
16
|
+
) -> None:
|
|
17
|
+
_, port_client = port_client_for_fake_integration
|
|
18
|
+
current_integration = await port_client.get_current_integration()
|
|
19
|
+
assert current_integration is not None
|
|
20
|
+
assert current_integration.get("resyncState") is not None
|
|
21
|
+
assert current_integration.get("resyncState", {}).get("status") == "completed"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@pytest.mark.skipif(
|
|
25
|
+
environ.get("SMOKE_TEST_SUFFIX", None) is None,
|
|
26
|
+
reason="You need to run the fake integration once",
|
|
27
|
+
)
|
|
28
|
+
async def test_valid_fake_departments(
|
|
29
|
+
port_client_for_fake_integration: Tuple[SmokeTestDetails, PortClient],
|
|
30
|
+
) -> None:
|
|
31
|
+
details, port_client = port_client_for_fake_integration
|
|
32
|
+
entities = await port_client.search_entities(user_agent_type=UserAgentType.exporter)
|
|
33
|
+
assert len(entities)
|
|
34
|
+
departments = [
|
|
35
|
+
x for x in entities if f"{x.blueprint}" == details.blueprint_department
|
|
36
|
+
]
|
|
37
|
+
assert len(departments) == 5
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.skipif(
|
|
41
|
+
environ.get("SMOKE_TEST_SUFFIX", None) is None,
|
|
42
|
+
reason="You need to run the fake integration once",
|
|
43
|
+
)
|
|
44
|
+
async def test_valid_fake_persons(
|
|
45
|
+
port_client_for_fake_integration: Tuple[SmokeTestDetails, PortClient],
|
|
46
|
+
) -> None:
|
|
47
|
+
details, port_client = port_client_for_fake_integration
|
|
48
|
+
headers = await port_client.auth.headers()
|
|
49
|
+
fake_person_entities_result = await port_client.client.get(
|
|
50
|
+
f"{port_client.auth.api_url}/blueprints/{details.blueprint_person}/entities",
|
|
51
|
+
headers=headers,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
fake_person_entities = fake_person_entities_result.json()["entities"]
|
|
55
|
+
assert len(fake_person_entities)
|
|
56
|
+
|
|
57
|
+
fake_departments_result = await port_client.client.get(
|
|
58
|
+
f"{port_client.auth.api_url}/blueprints/{details.blueprint_department}/entities",
|
|
59
|
+
headers=headers,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
departments = [x["identifier"] for x in fake_departments_result.json()["entities"]]
|
|
63
|
+
|
|
64
|
+
for department in departments:
|
|
65
|
+
assert len(
|
|
66
|
+
[
|
|
67
|
+
x
|
|
68
|
+
for x in fake_person_entities
|
|
69
|
+
if x["relations"]["department"] == department
|
|
70
|
+
]
|
|
71
|
+
)
|
|
@@ -94,7 +94,7 @@ port_ocean/core/integrations/mixins/__init__.py,sha256=FA1FEKMM6P-L2_m7Q4L20mFa4
|
|
|
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=
|
|
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,14 +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=
|
|
118
|
+
port_ocean/ocean.py,sha256=fHF3nCIb2bfD3gMizXV9mwF11DR3fXoK6am172jrIt4,5025
|
|
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
|
-
port_ocean/tests/
|
|
124
|
+
port_ocean/tests/conftest.py,sha256=JXASSS0IY0nnR6bxBflhzxS25kf4iNaABmThyZ0mZt8,101
|
|
125
|
+
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/ocean_app.py,sha256=Dp1bwEDhWsx_G-KVxOfJX1eVIS4168ajLu39wAY275g,1693
|
|
125
128
|
port_ocean/tests/test_sample.py,sha256=Ew5LA_G1k6DC5a2ygU2FoyjZQa0fRmPy73N0bio0d14,46
|
|
129
|
+
port_ocean/tests/test_smoke.py,sha256=F-1MoEcdIT1smjWv3s1iaS7U5UxpKGf-AHc8mYHjOlw,2522
|
|
126
130
|
port_ocean/utils/__init__.py,sha256=KMGnCPXZJbNwtgxtyMycapkDz8tpSyw23MSYT3iVeHs,91
|
|
127
131
|
port_ocean/utils/async_http.py,sha256=arnH458TExn2Dju_Sy6pHas_vF5RMWnOp-jBz5WAAcE,1226
|
|
128
132
|
port_ocean/utils/async_iterators.py,sha256=iw3cUHxfQm3zUSPdw2FmSXDU8E1Ppnys4TGhswNuQ8s,1569
|
|
@@ -133,8 +137,8 @@ port_ocean/utils/repeat.py,sha256=0EFWM9d8lLXAhZmAyczY20LAnijw6UbIECf5lpGbOas,32
|
|
|
133
137
|
port_ocean/utils/signal.py,sha256=K-6kKFQTltcmKDhtyZAcn0IMa3sUpOHGOAUdWKgx0_E,1369
|
|
134
138
|
port_ocean/utils/time.py,sha256=pufAOH5ZQI7gXvOvJoQXZXZJV-Dqktoj9Qp9eiRwmJ4,1939
|
|
135
139
|
port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
|
|
136
|
-
port_ocean-0.10.
|
|
137
|
-
port_ocean-0.10.
|
|
138
|
-
port_ocean-0.10.
|
|
139
|
-
port_ocean-0.10.
|
|
140
|
-
port_ocean-0.10.
|
|
140
|
+
port_ocean-0.10.12.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
141
|
+
port_ocean-0.10.12.dist-info/METADATA,sha256=tttQQiBv4cQkkOpY3210bf0r_HlbdbshcCVt5JFfELs,6617
|
|
142
|
+
port_ocean-0.10.12.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
143
|
+
port_ocean-0.10.12.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
|
|
144
|
+
port_ocean-0.10.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|