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

@@ -9,6 +9,17 @@ from port_ocean.cli.commands.main import cli_start, print_logo, console
9
9
  from port_ocean.cli.utils import cli_root_path
10
10
 
11
11
 
12
+ def symlink_makefile(result: str, name: str) -> None:
13
+ infra_make_file = os.path.join(
14
+ os.path.dirname(result), "../integrations/_infra/Makefile"
15
+ )
16
+ target_link_make_file = os.path.join(
17
+ os.path.dirname(result), f"../integrations/{name}/Makefile"
18
+ )
19
+
20
+ os.link(infra_make_file, target_link_make_file)
21
+
22
+
12
23
  def add_vscode_configuration(result: str, name: str) -> None:
13
24
  vscode_entry_root_path = "${workspaceFolder}/integrations/" + name
14
25
  new_vscode_entry = {
@@ -66,6 +77,7 @@ def new(path: str, is_private_integration: bool) -> None:
66
77
 
67
78
  if not is_private_integration:
68
79
  add_vscode_configuration(result, name)
80
+ symlink_makefile(result, name)
69
81
 
70
82
  console.print(
71
83
  "\n🌊 Ahoy, Captain! Your project is ready to set sail into the vast ocean of possibilities!",
@@ -64,7 +64,6 @@ class BlueprintClientMixin:
64
64
  f"Deleting blueprint with id: {identifier} with all entities: {delete_entities}"
65
65
  )
66
66
  headers = await self.auth.headers(user_agent_type)
67
- response = None
68
67
 
69
68
  if not delete_entities:
70
69
  response = await self.client.delete(
@@ -82,7 +81,9 @@ class BlueprintClientMixin:
82
81
  handle_status_code(response, should_raise)
83
82
  return response.json().get("migrationId", "")
84
83
 
85
- async def create_action(self, action: dict[str, Any]) -> None:
84
+ async def create_action(
85
+ self, action: dict[str, Any], should_log: bool = True
86
+ ) -> None:
86
87
  logger.info(f"Creating action: {action}")
87
88
  response = await self.client.post(
88
89
  f"{self.auth.api_url}/actions",
@@ -90,12 +91,13 @@ class BlueprintClientMixin:
90
91
  headers=await self.auth.headers(),
91
92
  )
92
93
 
93
- handle_status_code(response)
94
+ handle_status_code(response, should_log=should_log)
94
95
 
95
96
  async def create_scorecard(
96
97
  self,
97
98
  blueprint_identifier: str,
98
99
  scorecard: dict[str, Any],
100
+ should_log: bool = True,
99
101
  ) -> None:
100
102
  logger.info(f"Creating scorecard: {scorecard}")
101
103
  response = await self.client.post(
@@ -104,11 +106,10 @@ class BlueprintClientMixin:
104
106
  headers=await self.auth.headers(),
105
107
  )
106
108
 
107
- handle_status_code(response)
109
+ handle_status_code(response, should_log=should_log)
108
110
 
109
111
  async def create_page(
110
- self,
111
- page: dict[str, Any],
112
+ self, page: dict[str, Any], should_log: bool = True
112
113
  ) -> dict[str, Any]:
113
114
  logger.info(f"Creating page: {page}")
114
115
  response = await self.client.post(
@@ -117,7 +118,7 @@ class BlueprintClientMixin:
117
118
  headers=await self.auth.headers(),
118
119
  )
119
120
 
120
- handle_status_code(response)
121
+ handle_status_code(response, should_log=should_log)
121
122
  return page
122
123
 
123
124
  async def delete_page(
@@ -120,7 +120,7 @@ async def _create_resources(
120
120
  )
121
121
  return
122
122
 
123
- created_blueprints, errors = await gather_and_split_errors_from_results(
123
+ created_blueprints, blueprint_errors = await gather_and_split_errors_from_results(
124
124
  (
125
125
  port_client.create_blueprint(
126
126
  blueprint, user_agent_type=UserAgentType.exporter
@@ -131,15 +131,17 @@ async def _create_resources(
131
131
 
132
132
  created_blueprints_identifiers = [bp["identifier"] for bp in created_blueprints]
133
133
 
134
- if errors:
135
- for error in errors:
134
+ if blueprint_errors:
135
+ for error in blueprint_errors:
136
136
  if isinstance(error, httpx.HTTPStatusError):
137
137
  logger.warning(
138
138
  f"Failed to create resources: {error.response.text}. Rolling back changes..."
139
139
  )
140
140
 
141
- raise AbortDefaultCreationError(created_blueprints_identifiers, errors)
142
- created_pages_identifiers = []
141
+ raise AbortDefaultCreationError(
142
+ created_blueprints_identifiers, blueprint_errors
143
+ )
144
+
143
145
  try:
144
146
  for patch_stage in blueprint_patches:
145
147
  await asyncio.gather(
@@ -153,44 +155,43 @@ async def _create_resources(
153
155
  )
154
156
  )
155
157
 
156
- await asyncio.gather(
157
- *(port_client.create_action(action) for action in defaults.actions)
158
+ except httpx.HTTPStatusError as err:
159
+ logger.error(f"Failed to create resources: {err.response.text}. continuing...")
160
+ raise AbortDefaultCreationError(created_blueprints_identifiers, [err])
161
+ try:
162
+ created_actions, actions_errors = await gather_and_split_errors_from_results(
163
+ (
164
+ port_client.create_action(action, should_log=False)
165
+ for action in defaults.actions
166
+ )
158
167
  )
159
168
 
160
- await asyncio.gather(
161
- *(
162
- port_client.create_scorecard(blueprint_scorecards["blueprint"], action)
163
- for blueprint_scorecards in defaults.scorecards
164
- for action in blueprint_scorecards["data"]
169
+ created_scorecards, scorecards_errors = (
170
+ await gather_and_split_errors_from_results(
171
+ (
172
+ port_client.create_scorecard(
173
+ blueprint_scorecards["blueprint"], action, should_log=False
174
+ )
175
+ for blueprint_scorecards in defaults.scorecards
176
+ for action in blueprint_scorecards["data"]
177
+ )
165
178
  )
166
179
  )
167
180
 
168
181
  created_pages, pages_errors = await gather_and_split_errors_from_results(
169
- (port_client.create_page(page) for page in defaults.pages)
182
+ (port_client.create_page(page, should_log=False) for page in defaults.pages)
170
183
  )
171
- created_pages_identifiers = [
172
- page.get("identifier", "") for page in created_pages
173
- ]
174
184
 
175
- if pages_errors:
176
- for error in pages_errors:
185
+ errors = actions_errors + scorecards_errors + pages_errors
186
+ if errors:
187
+ for error in errors:
177
188
  if isinstance(error, httpx.HTTPStatusError):
178
189
  logger.warning(
179
- f"Failed to create resources: {error.response.text}. Rolling back changes..."
190
+ f"Failed to create resource: {error.response.text}. continuing..."
180
191
  )
181
192
 
182
- raise AbortDefaultCreationError(
183
- created_blueprints_identifiers,
184
- pages_errors,
185
- created_pages_identifiers,
186
- )
187
- except httpx.HTTPStatusError as err:
188
- logger.error(
189
- f"Failed to create resources: {err.response.text}. Rolling back changes..."
190
- )
191
- raise AbortDefaultCreationError(
192
- created_blueprints_identifiers, [err], created_pages_identifiers
193
- )
193
+ except Exception as err:
194
+ logger.error(f"Failed to create resources: {err}. continuing...")
194
195
 
195
196
 
196
197
  async def _initialize_defaults(
@@ -227,19 +228,6 @@ async def _initialize_defaults(
227
228
  for identifier in e.blueprints_to_rollback
228
229
  )
229
230
  )
230
- if e.pages_to_rollback:
231
- logger.warning(
232
- f"Failed to create resources. Rolling back pages : {e.pages_to_rollback}"
233
- )
234
- await asyncio.gather(
235
- *(
236
- port_client.delete_page(
237
- identifier,
238
- )
239
- for identifier in e.pages_to_rollback
240
- )
241
- )
242
-
243
231
  raise ExceptionGroup(str(e), e.errors)
244
232
 
245
233
 
@@ -6,10 +6,8 @@ class AbortDefaultCreationError(BaseOceanException):
6
6
  self,
7
7
  blueprints_to_rollback: list[str],
8
8
  errors: list[Exception],
9
- pages_to_rollback: list[str] | None = None,
10
9
  ):
11
10
  self.blueprints_to_rollback = blueprints_to_rollback
12
- self.pages_to_rollback = pages_to_rollback
13
11
  self.errors = errors
14
12
  super().__init__("Aborting defaults creation")
15
13
 
@@ -0,0 +1,4 @@
1
+ # ruff: noqa
2
+ from port_ocean.tests.helpers.fixtures import (
3
+ port_client_for_fake_integration,
4
+ )
@@ -1,75 +0,0 @@
1
- import sys
2
- from inspect import getmembers
3
- from typing import Dict, List, Set, Tuple, Union
4
-
5
- from yaml import safe_load
6
-
7
- from port_ocean.bootstrap import create_default_app
8
- from port_ocean.core.handlers.port_app_config.models import ResourceConfig
9
- from port_ocean.core.ocean_types import RESYNC_RESULT
10
- from port_ocean.ocean import Ocean
11
- from port_ocean.utils.misc import load_module
12
-
13
-
14
- def get_integration_ocean_app(integration_path: str) -> Ocean:
15
- default_app = create_default_app(
16
- integration_path,
17
- None,
18
- {
19
- "port": {
20
- "client_id": "bla",
21
- "client_secret": "bla",
22
- },
23
- },
24
- )
25
- main_path = f"{integration_path}/main.py"
26
- sys.path.append(integration_path)
27
- app_module = load_module(main_path)
28
- app: Ocean = {name: item for name, item in getmembers(app_module)}.get(
29
- "app", default_app
30
- )
31
-
32
- return app
33
-
34
-
35
- def get_integation_resource_configs(integration_path: str) -> List[ResourceConfig]:
36
- with open(
37
- f"{integration_path}/.port/resources/port-app-config.yml"
38
- ) as port_app_config_file:
39
- resource_configs = safe_load(port_app_config_file)
40
-
41
- return [ResourceConfig(**item) for item in resource_configs["resources"]]
42
-
43
-
44
- def get_integation_resource_config_by_name(
45
- integration_path: str, kind: str
46
- ) -> Union[ResourceConfig, None]:
47
- resource_configs = get_integation_resource_configs(integration_path)
48
-
49
- relevant_configs = [x for x in resource_configs if x.kind == kind]
50
-
51
- return relevant_configs[0] if len(relevant_configs) else None
52
-
53
-
54
- async def get_raw_result_on_integration_sync_kinds(
55
- integration_path: str, override_kinds: Union[Set[str], None] = None
56
- ) -> Dict[str, List[Tuple[RESYNC_RESULT, List[Exception]]]]:
57
- app = get_integration_ocean_app(integration_path)
58
-
59
- resource_configs = get_integation_resource_configs(integration_path)
60
-
61
- if override_kinds:
62
- resource_configs = [x for x in resource_configs if x.kind in override_kinds]
63
-
64
- results: Dict[str, List[Tuple[RESYNC_RESULT, List[Exception]]]] = {}
65
-
66
- for resource_config in resource_configs:
67
- resource_result = await app.integration._get_resource_raw_results(
68
- resource_config
69
- )
70
-
71
- results[resource_config.kind] = results.get(resource_config.kind, []) + [
72
- resource_result
73
- ]
74
-
75
- 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
+ )
@@ -36,7 +36,7 @@ async def stream_async_iterators_tasks(
36
36
  :return: A stream of results
37
37
  """
38
38
  if not tasks:
39
- raise StopAsyncIteration("No tasks provided")
39
+ return
40
40
 
41
41
  if len(tasks) == 1:
42
42
  async for batch_items in tasks[0]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.10.8
3
+ Version: 0.10.11
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
@@ -9,7 +9,7 @@ port_ocean/cli/commands/defaults/dock.py,sha256=pFtHrU_LTvb5Ddrzj09Wxy-jg1Ym10wB
9
9
  port_ocean/cli/commands/defaults/group.py,sha256=hii_4CYoQ7jSMePbnP4AmruO_RKWCUcoV7dXXBlZafc,115
10
10
  port_ocean/cli/commands/list_integrations.py,sha256=DVVioFruGUE-_v6UUHlcemWNN6RlWwCrf1X4HmAXsf8,1134
11
11
  port_ocean/cli/commands/main.py,sha256=gj0lmuLep2XeLNuabB7Wk0UVYPT7_CD_rAw5AoUQWSE,1057
12
- port_ocean/cli/commands/new.py,sha256=3hefYQrFXJzwfoJgV8yHgnB0HYOVmk3-6XQeb694_Ao,3404
12
+ port_ocean/cli/commands/new.py,sha256=uNDzb2cmUdOHBGsBujWmlB9FrlJvB8CD9dnXY_btGUc,3777
13
13
  port_ocean/cli/commands/pull.py,sha256=VvrRjLNlfPuLIf7KzeIcbzzdi98Z0M9wCRpXC3QPxdI,2306
14
14
  port_ocean/cli/commands/sail.py,sha256=rY7rEMjfy_KXiWvtL0T72TTLgeQ3HW4SOzKkz9wL9nI,2282
15
15
  port_ocean/cli/commands/version.py,sha256=hEuIEIcm6Zkamz41Z9nxeSM_4g3oNlAgWwQyDGboh-E,536
@@ -27,7 +27,6 @@ port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml,sh
27
27
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md,sha256=XVSgyxfXJZoZmtwaGbQ8XmCapIthe4E7flfuJub-m_s,338
28
28
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CONTRIBUTING.md,sha256=ZQwD3K35q0wugHZmb1z5wnynmn0uuzwGFSpjm7GieZU,259
29
29
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/Dockerfile,sha256=LsH3vZqqEJkzeQG44cE7JkvPAuh_WPSqYam4YoMvG3M,328
30
- port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/Makefile,sha256=2eoJjrQj_zxapvuhX3ohVSgDGgWIF-VwgGvrWPfl5vw,1783
31
30
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md,sha256=5VZmgDRW9gO4d8UuzkujslOIDfIDBiAGL2Hd74HK770,468
32
31
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore,sha256=JAo-DTfS6GthQGP1NH6wLU-ZymwlTea4KHH_jZVTKn0,14
33
32
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py,sha256=_TRsA2s6GV2E3CTI8CHcsH-ZuH4_Eh5-juDXWaET0ho,65
@@ -43,7 +42,7 @@ port_ocean/clients/port/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
43
42
  port_ocean/clients/port/authentication.py,sha256=t3z6h4vld-Tzkpth15sstaMJg0rccX-pXXjNtOa-nCY,2949
44
43
  port_ocean/clients/port/client.py,sha256=Xd8Jk25Uh4WXY_WW-z1Qbv6F3ZTBFPoOolsxHMfozKw,3366
45
44
  port_ocean/clients/port/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
- port_ocean/clients/port/mixins/blueprints.py,sha256=8ZVC5i8K1WKQMJJiPqZmgcOlF3OyxWz1aAQ_WA5UW3c,4500
45
+ port_ocean/clients/port/mixins/blueprints.py,sha256=POBl4uDocrgJBw4rvCAzwRcD4jk-uBL6pDAuKMTajdg,4633
47
46
  port_ocean/clients/port/mixins/entities.py,sha256=WdqT1gyS81pByUl9xIfZz_xEHRaBfDuZ-ekKX53oBSE,8870
48
47
  port_ocean/clients/port/mixins/integrations.py,sha256=HnWXaJt41SUcha-bhvLdJW07j-l7xIo91GUzzwl2f_E,4859
49
48
  port_ocean/clients/port/mixins/migrations.py,sha256=A6896oJF6WbFL2WroyTkMzr12yhVyWqGoq9dtLNSKBY,1457
@@ -64,7 +63,7 @@ port_ocean/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
64
63
  port_ocean/core/defaults/__init__.py,sha256=8qCZg8n06WAdMu9s_FiRtDYLGPGHbOuS60vapeUoAks,142
65
64
  port_ocean/core/defaults/clean.py,sha256=S3UAfca-oU89WJKIB4OgGjGjPr0vxBQ2aRZsLTZhQ04,2185
66
65
  port_ocean/core/defaults/common.py,sha256=uVUg6VEn4RqtXQwLwMNGfkmT5zYRN_h5USfKw3poVyo,3561
67
- port_ocean/core/defaults/initialize.py,sha256=5po9QtZNIXwxH8c0QoTKp8ag4aHt4rmOsO5CKH7fft0,8713
66
+ port_ocean/core/defaults/initialize.py,sha256=qg4JLIWjp0c5-9w09X99muHRYX4k1cGZ_77vYo-tnpU,8422
68
67
  port_ocean/core/event_listener/__init__.py,sha256=mzJ33wRq0kh60fpVdOHVmvMTUQIvz3vxmifyBgwDn0E,889
69
68
  port_ocean/core/event_listener/base.py,sha256=1Nmpg00OfT2AD2L8eFm4VQEcdG2TClpSWJMhWhAjkEE,2356
70
69
  port_ocean/core/event_listener/factory.py,sha256=AYYfSHPAF7P5H-uQECXT0JVJjKDHrYkWJJBSL4mGkg8,3697
@@ -106,7 +105,7 @@ port_ocean/exceptions/base.py,sha256=uY4DX7fIITDFfemCJDWpaZi3bD51lcANc5swpoNvMJA
106
105
  port_ocean/exceptions/clients.py,sha256=LKLLs-Zy3caNG85rwxfOw2rMr8qqVV6SHUq4fRCZ99U,180
107
106
  port_ocean/exceptions/context.py,sha256=mA8HII6Rl4QxKUz98ppy1zX3kaziaen21h1ZWuU3ADc,372
108
107
  port_ocean/exceptions/core.py,sha256=Zmb1m6NnkSPWpAiQA5tgejm3zpDMt1WQEN47OJNo54A,856
109
- port_ocean/exceptions/port_defaults.py,sha256=pJ5im06ziDX2IVstSlYIjVHhs4JW-N0Vr0PqlDNhAb4,541
108
+ port_ocean/exceptions/port_defaults.py,sha256=45Bno5JEB-GXztvKsy8mw7TrydQmw13-4JAo2oQmXkE,438
110
109
  port_ocean/exceptions/utils.py,sha256=gjOqpi-HpY1l4WlMFsGA9yzhxDhajhoGGdDDyGbLnqI,197
111
110
  port_ocean/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
111
  port_ocean/helpers/async_client.py,sha256=SRlP6o7_FCSY3UHnRlZdezppePVxxOzZ0z861vE3K40,1783
@@ -122,11 +121,15 @@ port_ocean/run.py,sha256=rTxBlrQd4yyrtgErCFJCHCEHs7d1OXrRiJehUYmIbN0,2212
122
121
  port_ocean/sonar-project.properties,sha256=X_wLzDOkEVmpGLRMb2fg9Rb0DxWwUFSvESId8qpvrPI,73
123
122
  port_ocean/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
124
123
  port_ocean/tests/clients/port/mixins/test_entities.py,sha256=A9myrnkLhKSQrnOLv1Zz2wiOVSxW65Q9RIUIRbn_V7w,1586
125
- port_ocean/tests/helpers/__init__.py,sha256=XQBdAi54t9VavF11dGVLeS1jSoEKRjqRemKskLh-nSo,2377
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
126
128
  port_ocean/tests/test_sample.py,sha256=Ew5LA_G1k6DC5a2ygU2FoyjZQa0fRmPy73N0bio0d14,46
129
+ port_ocean/tests/test_smoke.py,sha256=F-1MoEcdIT1smjWv3s1iaS7U5UxpKGf-AHc8mYHjOlw,2522
127
130
  port_ocean/utils/__init__.py,sha256=KMGnCPXZJbNwtgxtyMycapkDz8tpSyw23MSYT3iVeHs,91
128
131
  port_ocean/utils/async_http.py,sha256=arnH458TExn2Dju_Sy6pHas_vF5RMWnOp-jBz5WAAcE,1226
129
- port_ocean/utils/async_iterators.py,sha256=buFBiPdsqkNMCk91h6ZG8hJa181j7RjgHajbfgeB8A8,1608
132
+ port_ocean/utils/async_iterators.py,sha256=iw3cUHxfQm3zUSPdw2FmSXDU8E1Ppnys4TGhswNuQ8s,1569
130
133
  port_ocean/utils/cache.py,sha256=3KItZDE2yVrbVDr-hoM8lNna8s2dlpxhP4ICdLjH4LQ,2231
131
134
  port_ocean/utils/misc.py,sha256=0q2cJ5psqxn_5u_56pT7vOVQ3shDM02iC1lzyWQ_zl0,2098
132
135
  port_ocean/utils/queue_utils.py,sha256=KWWl8YVnG-glcfIHhM6nefY-2sou_C6DVP1VynQwzB4,2762
@@ -134,8 +137,8 @@ port_ocean/utils/repeat.py,sha256=0EFWM9d8lLXAhZmAyczY20LAnijw6UbIECf5lpGbOas,32
134
137
  port_ocean/utils/signal.py,sha256=K-6kKFQTltcmKDhtyZAcn0IMa3sUpOHGOAUdWKgx0_E,1369
135
138
  port_ocean/utils/time.py,sha256=pufAOH5ZQI7gXvOvJoQXZXZJV-Dqktoj9Qp9eiRwmJ4,1939
136
139
  port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
137
- port_ocean-0.10.8.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
138
- port_ocean-0.10.8.dist-info/METADATA,sha256=RkH8PbV-aHXG36GanolJDtpHUZtdjtVn4_8cIId-St8,6616
139
- port_ocean-0.10.8.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
140
- port_ocean-0.10.8.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
141
- port_ocean-0.10.8.dist-info/RECORD,,
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,,
@@ -1,74 +0,0 @@
1
- ACTIVATE := . .venv/bin/activate
2
-
3
- define run_checks
4
- exit_code=0; \
5
- cd $1; \
6
- poetry check || exit_code=$$?;\
7
- mypy . || exit_code=$$?; \
8
- ruff check . || exit_code=$$?; \
9
- black --check . || exit_code=$$?; \
10
- if [ $$exit_code -eq 1 ]; then \
11
- echo "\033[0;31mOne or more checks failed with exit code $$exit_code\033[0m"; \
12
- else \
13
- echo "\033[0;32mAll checks executed successfully.\033[0m"; \
14
- fi; \
15
- exit $$exit_code
16
- endef
17
-
18
- define install_poetry
19
- if ! command -v poetry &> /dev/null; then \
20
- pip install --upgrade pip; \
21
- pip install poetry; \
22
- else \
23
- echo "Poetry is already installed."; \
24
- fi
25
- endef
26
-
27
- define deactivate_virtualenv
28
- if [ -n "$$VIRTUAL_ENV" ]; then \
29
- unset VIRTUAL_ENV; \
30
- unset PYTHONHOME; \
31
- unset -f pydoc >/dev/null 2>&1; \
32
- OLD_PATH="$$PATH"; \
33
- PATH=$$(echo -n "$$PATH" | awk -v RS=: -v ORS=: '/\/virtualenv\/bin$$/ {next} {print}'); \
34
- export PATH; \
35
- hash -r; \
36
- echo "Deactivated the virtual environment."; \
37
- fi
38
- endef
39
-
40
- .SILENT: install install/prod lint run test clean
41
-
42
- install:
43
- $(call deactivate_virtualenv) && \
44
- $(call install_poetry) && \
45
- poetry install --with dev
46
-
47
- install/prod:
48
- $(call install_poetry) && \
49
- poetry install --without dev --no-root --no-interaction --no-ansi --no-cache
50
-
51
- lint:
52
- $(ACTIVATE) && \
53
- $(call run_checks,.)
54
-
55
- run:
56
- $(ACTIVATE) && ocean sail
57
-
58
- test:
59
- $(ACTIVATE) && poetry run pytest -n auto
60
-
61
- clean:
62
- @find . -name '.venv' -type d -exec rm -rf {} \;
63
- @find . -name '*.pyc' -exec rm -rf {} \;
64
- @find . -name '__pycache__' -exec rm -rf {} \;
65
- @find . -name 'Thumbs.db' -exec rm -rf {} \;
66
- @find . -name '*~' -exec rm -rf {} \;
67
- rm -rf .cache
68
- rm -rf build
69
- rm -rf dist
70
- rm -rf *.egg-info
71
- rm -rf htmlcov
72
- rm -rf .tox/
73
- rm -rf docs/_build
74
- rm -rf dist/