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

@@ -2,11 +2,12 @@ import os
2
2
 
3
3
 
4
4
  def handle_private_integration_flags():
5
+ print("{{ cookiecutter.is_private_integration }}")
5
6
  if "{{ cookiecutter.is_private_integration }}" == "True":
7
+ os.remove("sonar-project.properties")
8
+ if "{{ cookiecutter.is_private_integration }}" == "False":
6
9
  os.remove("Dockerfile")
7
10
  os.remove(".dockerignore")
8
- if "{{ cookiecutter.is_private_integration }}" == "False":
9
- os.remove("sonar-project.properties")
10
11
 
11
12
 
12
13
  if __name__ == "__main__":
@@ -19,7 +19,8 @@ towncrier = "^23.6.0"
19
19
  [tool.towncrier]
20
20
  directory = "changelog"
21
21
  filename = "CHANGELOG.md"
22
- package = "port_ocean"
22
+ title_format = "## {version} ({project_date})"
23
+ underlines = [""]
23
24
 
24
25
  [[tool.towncrier.type]]
25
26
  directory = "breaking"
port_ocean/config/base.py CHANGED
@@ -1,11 +1,11 @@
1
1
  import os
2
2
  import re
3
- from pathlib import Path
4
3
  from types import GenericAlias
5
4
  from typing import Any
6
5
 
7
6
  import yaml
8
7
  from humps import decamelize
8
+ from pathlib import Path
9
9
  from pydantic import BaseSettings
10
10
  from pydantic.env_settings import EnvSettingsSource, InitSettingsSource
11
11
  from pydantic.main import ModelMetaclass, BaseModel
@@ -14,13 +14,17 @@ PROVIDER_WRAPPER_PATTERN = r"{{ from (.*) }}"
14
14
  PROVIDER_CONFIG_PATTERN = r"^[a-zA-Z0-9]+ .*$"
15
15
 
16
16
 
17
- def read_yaml_config_settings_source(
18
- settings: "BaseOceanSettings", base_path: str
19
- ) -> dict[str, Any]:
20
- yaml_file = getattr(settings.__config__, "yaml_file", "")
17
+ def read_yaml_config_settings_source(settings: "BaseOceanSettings") -> dict[str, Any]:
18
+ yaml_file = getattr(settings.Config, "yaml_file", "")
21
19
 
22
20
  assert yaml_file, "Settings.yaml_file not properly configured"
23
- path = Path(base_path, yaml_file)
21
+ path = Path(
22
+ getattr(
23
+ settings,
24
+ "_base_path",
25
+ ),
26
+ yaml_file,
27
+ )
24
28
 
25
29
  if not path.exists():
26
30
  return {}
@@ -119,15 +123,15 @@ def decamelize_config(
119
123
 
120
124
 
121
125
  def load_providers(
122
- settings: "BaseOceanSettings", existing_values: dict[str, Any], base_path: str
126
+ settings: "BaseOceanSettings", existing_values: dict[str, Any]
123
127
  ) -> dict[str, Any]:
124
- data = read_yaml_config_settings_source(settings, base_path)
128
+ data = read_yaml_config_settings_source(settings)
125
129
  snake_case_config = decamelize_config(settings, data)
126
130
  return parse_providers(settings, snake_case_config, existing_values)
127
131
 
128
132
 
129
133
  class BaseOceanSettings(BaseSettings):
130
- base_path: str
134
+ _base_path: str = "./"
131
135
 
132
136
  def get_sensitive_fields_data(self) -> set[str]:
133
137
  return _get_sensitive_information(self)
@@ -150,9 +154,7 @@ class BaseOceanSettings(BaseSettings):
150
154
  return (
151
155
  init_settings,
152
156
  env_settings,
153
- lambda s: load_providers(
154
- s, env_settings(s), init_settings.init_kwargs["base_path"]
155
- ),
157
+ lambda s: load_providers(s, {**env_settings(s), **init_settings(s)}),
156
158
  )
157
159
 
158
160
 
@@ -1,15 +1,16 @@
1
- from typing import Any, Literal
1
+ from typing import Any, Literal, Type
2
2
 
3
- from port_ocean.config.base import BaseOceanSettings, BaseOceanModel
4
- from port_ocean.core.event_listener import EventListenerSettingsType
5
- from port_ocean.core.models import Runtime
6
- from port_ocean.utils.misc import get_integration_name, get_spec_file
7
- from pydantic import Extra, AnyHttpUrl, parse_obj_as
3
+ from pydantic import Extra, AnyHttpUrl, parse_obj_as, parse_raw_as
8
4
  from pydantic.class_validators import root_validator, validator
9
5
  from pydantic.env_settings import InitSettingsSource, EnvSettingsSource, BaseSettings
10
6
  from pydantic.fields import Field
11
7
  from pydantic.main import BaseModel
12
8
 
9
+ from port_ocean.config.base import BaseOceanSettings, BaseOceanModel
10
+ from port_ocean.core.event_listener import EventListenerSettingsType
11
+ from port_ocean.core.models import Runtime
12
+ from port_ocean.utils.misc import get_integration_name, get_spec_file
13
+
13
14
  LogLevelType = Literal["ERROR", "WARNING", "INFO", "DEBUG", "CRITICAL"]
14
15
 
15
16
 
@@ -44,7 +45,7 @@ class PortSettings(BaseOceanModel, extra=Extra.allow):
44
45
  class IntegrationSettings(BaseOceanModel, extra=Extra.allow):
45
46
  identifier: str
46
47
  type: str
47
- config: dict[str, Any] | BaseModel = Field(default_factory=dict)
48
+ config: Any = Field(default_factory=dict)
48
49
 
49
50
  @root_validator(pre=True)
50
51
  def root_validator(cls, values: dict[str, Any]) -> dict[str, Any]:
@@ -62,6 +63,8 @@ class IntegrationSettings(BaseOceanModel, extra=Extra.allow):
62
63
 
63
64
 
64
65
  class IntegrationConfiguration(BaseOceanSettings, extra=Extra.allow):
66
+ _integration_config_model: BaseModel | None = None
67
+
65
68
  allow_environment_variables_jq_access: bool = True
66
69
  initialize_port_resources: bool = True
67
70
  scheduled_resync_interval: int | None = None
@@ -73,6 +76,27 @@ class IntegrationConfiguration(BaseOceanSettings, extra=Extra.allow):
73
76
  integration: IntegrationSettings = IntegrationSettings(type="", identifier="")
74
77
  runtime: Runtime = "OnPrem"
75
78
 
79
+ @root_validator()
80
+ def validate_integration_config(cls, values: dict[str, Any]) -> dict[str, Any]:
81
+ if not (config_model := values.get("_integration_config_model")):
82
+ return values
83
+
84
+ # Using the integration dynamic config model to parse the config
85
+ def parse_config(model: Type[BaseModel], config: Any) -> BaseModel:
86
+ # In some cases, the config is parsed as a string so we need to handle it
87
+ # Example: when the config is loaded from the environment variables and there is an object inside the config
88
+ if isinstance(config, str):
89
+ return parse_raw_as(model, config)
90
+ else:
91
+ return parse_obj_as(model, config)
92
+
93
+ integration_config = values["integration"]
94
+ integration_config.config = parse_config(
95
+ config_model, integration_config.config
96
+ )
97
+
98
+ return values
99
+
76
100
  @validator("runtime")
77
101
  def validate_runtime(cls, runtime: Literal["OnPrem", "Saas"]) -> Runtime:
78
102
  if runtime == "Saas":
@@ -311,10 +311,12 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
311
311
  resource for resource in config.resources if resource.kind == kind
312
312
  ]
313
313
 
314
- entities, errors = await asyncio.gather(
315
- *(
316
- self._unregister_resource_raw(resource, results, user_agent_type)
317
- for resource in resource_mappings
314
+ entities, errors = zip_and_sum(
315
+ await asyncio.gather(
316
+ *(
317
+ self._unregister_resource_raw(resource, results, user_agent_type)
318
+ for resource in resource_mappings
319
+ )
318
320
  )
319
321
  )
320
322
 
port_ocean/ocean.py CHANGED
@@ -2,7 +2,7 @@ import asyncio
2
2
  import sys
3
3
  import threading
4
4
  from contextlib import asynccontextmanager
5
- from typing import Callable, Any, Dict, AsyncIterator
5
+ from typing import Callable, Any, Dict, AsyncIterator, Type
6
6
 
7
7
  from fastapi import FastAPI, APIRouter
8
8
  from loguru import logger
@@ -32,7 +32,7 @@ class Ocean:
32
32
  app: FastAPI | None = None,
33
33
  integration_class: Callable[[PortOceanContext], BaseIntegration] | None = None,
34
34
  integration_router: APIRouter | None = None,
35
- config_factory: Callable[..., BaseModel] | None = None,
35
+ config_factory: Type[BaseModel] | None = None,
36
36
  config_override: Dict[str, Any] | None = None,
37
37
  ):
38
38
  initialize_port_ocean_context(self)
@@ -40,16 +40,11 @@ class Ocean:
40
40
  self.fast_api_app.middleware("http")(request_handler)
41
41
 
42
42
  self.config = IntegrationConfiguration(
43
- base_path="./", **(config_override or {})
43
+ # type: ignore
44
+ _integration_config_model=config_factory,
45
+ **(config_override or {}),
44
46
  )
45
47
 
46
- if config_factory:
47
- raw_config = (
48
- self.config.integration.config
49
- if isinstance(self.config.integration.config, dict)
50
- else self.config.integration.config.dict()
51
- )
52
- self.config.integration.config = config_factory(**raw_config)
53
48
  # add the integration sensitive configuration to the sensitive patterns to mask out
54
49
  sensitive_log_filter.hide_sensitive_strings(
55
50
  *self.config.get_sensitive_fields_data()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.9.7
3
+ Version: 0.9.10
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
@@ -16,7 +16,7 @@ port_ocean/cli/commands/version.py,sha256=hEuIEIcm6Zkamz41Z9nxeSM_4g3oNlAgWwQyDG
16
16
  port_ocean/cli/cookiecutter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  port_ocean/cli/cookiecutter/cookiecutter.json,sha256=N5UrAP2e5JbgEDz_WTQFIZlzSveME6x32sHeA7idjh0,481
18
18
  port_ocean/cli/cookiecutter/extensions.py,sha256=eQNjZvy2enDkJpvMbBGil77Xk9-38f862wfnmCjdoBc,446
19
- port_ocean/cli/cookiecutter/hooks/post_gen_project.py,sha256=4WpFM5O7FXuaqBMrhtnuz2LRqReMYzdVDoE5Ah6qoDI,358
19
+ port_ocean/cli/cookiecutter/hooks/post_gen_project.py,sha256=N-gcNPhVSMGBPI69etVU2QgyhvdzaxNMvUZbyYSdVM4,413
20
20
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.dockerignore,sha256=9Mz_WI7XBpKzlJ7ILb4vlcuzYkh98Ql3bP_5GHN1sRY,1034
21
21
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore,sha256=32p1lDW_g5hyBz486GWfDeR9m7ikFlASVri5a8vmNoo,2698
22
22
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore,sha256=kCpRPdl3S_jqYYZaOrc0-xa6-l3KqVjNRXc6jCkd_-Q,12
@@ -29,7 +29,7 @@ port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitigno
29
29
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py,sha256=_TRsA2s6GV2E3CTI8CHcsH-ZuH4_Eh5-juDXWaET0ho,65
30
30
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py,sha256=KxxtBrRygYOP0bulXySVYwX0fm_mm3QHqeEqwDwgXgY,1669
31
31
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml,sha256=kENq8nNmFPIzw9vySheyG4xHxAPuBSpZO1CYGD6G2NE,46
32
- port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml,sha256=zmkwpiBDiDhMKp1egULLnx6ftVBcVYh4ztGohs53rWA,1928
32
+ port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml,sha256=3uD4XEx_uQd6sYouLGwVeHO2R07ZPLYVs6ex0RavbOo,1970
33
33
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties,sha256=timmRpoSd50BdxLf45OcFUk2qs855z610kzz3yLAqJw,124
34
34
  port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  port_ocean/cli/utils.py,sha256=IUK2UbWqjci-lrcDdynZXqVP5B5TcjF0w5CpEVUks-k,54
@@ -46,9 +46,9 @@ port_ocean/clients/port/retry_transport.py,sha256=PtIZOAZ6V-ncpVysRUsPOgt8Sf01QL
46
46
  port_ocean/clients/port/types.py,sha256=nvlgiAq4WH5_F7wQbz_GAWl-faob84LVgIjZ2Ww5mTk,451
47
47
  port_ocean/clients/port/utils.py,sha256=O9mBu6zp4TfpS4SQ3qCPpn9ZVyYF8GKnji4UnYhM3yg,2373
48
48
  port_ocean/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
- port_ocean/config/base.py,sha256=J_FUvlo0D4FbEbr4mgJsbGB5JjW9I7zMwfekj6T30KY,6389
49
+ port_ocean/config/base.py,sha256=x1gFbzujrxn7EJudRT81C6eN9WsYAb3vOHwcpcpX8Tc,6370
50
50
  port_ocean/config/dynamic.py,sha256=qOFkRoJsn_BW7581omi_AoMxoHqasf_foxDQ_G11_SI,2030
51
- port_ocean/config/settings.py,sha256=Hm2glSmLPtBR2EUtnyOnBmP5rPpbK5d67jfzuPe9gJg,3183
51
+ port_ocean/config/settings.py,sha256=Uo52GefpahWoDi_BUCQNzNGTV4zc2gNDLVx9MJFpHOo,4148
52
52
  port_ocean/consumers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  port_ocean/consumers/kafka_consumer.py,sha256=N8KocjBi9aR0BOPG8hgKovg-ns_ggpEjrSxqSqF_BSo,4710
54
54
  port_ocean/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -88,7 +88,7 @@ port_ocean/core/integrations/mixins/__init__.py,sha256=FA1FEKMM6P-L2_m7Q4L20mFa4
88
88
  port_ocean/core/integrations/mixins/events.py,sha256=Ddfx2L4FpghV38waF8OfVeOV0bHBxNIgjU-q5ffillI,2341
89
89
  port_ocean/core/integrations/mixins/handler.py,sha256=mZ7-0UlG3LcrwJttFbMe-R4xcOU2H_g33tZar7PwTv8,3771
90
90
  port_ocean/core/integrations/mixins/sync.py,sha256=TKqRytxXONVhuCo3CB3rDvWNbITnZz33TYTDs3SWWVk,3880
91
- port_ocean/core/integrations/mixins/sync_raw.py,sha256=qgkxlh6_comyPNZ9p52ZhM9I7YQOwaEpn4kR0j20vbw,18103
91
+ port_ocean/core/integrations/mixins/sync_raw.py,sha256=-51SLY9jlNOBYQP1FWnKheJb3xkKQny9mP0Op_g04Dg,18158
92
92
  port_ocean/core/integrations/mixins/utils.py,sha256=7y1rGETZIjOQadyIjFJXIHKkQFKx_SwiP-TrAIsyyLY,2303
93
93
  port_ocean/core/models.py,sha256=4bDvMeydlSpG0YSXjE1Bo2AcZC0aQ2zqFhpsOvZat_A,1190
94
94
  port_ocean/core/ocean_types.py,sha256=3_d8-n626f1kWLQ_Jxw194LEyrOVupz05qs_Y1pvB-A,990
@@ -109,7 +109,7 @@ port_ocean/log/handlers.py,sha256=k9G_Mb4ga2-Jke9irpdlYqj6EYiwv0gEsh4TgyqqOmI,28
109
109
  port_ocean/log/logger_setup.py,sha256=BaXt-mh9CVXhneh37H46d04lqOdIBixG1pFyGfotuZs,2328
110
110
  port_ocean/log/sensetive.py,sha256=wkyvkKMbyLTjZDSbvvLHL9bv4RvD0DPAyL3uWSttUOA,2916
111
111
  port_ocean/middlewares.py,sha256=6GrhldYAazxSwK2TbS-J28XdZ-9wO3PgCcyIMhnnJvI,2480
112
- port_ocean/ocean.py,sha256=6-hldutAbUF2Ka02bKAgtpwJ6MvlC6f44ARVWRXPqYc,4266
112
+ port_ocean/ocean.py,sha256=jpWR9D9OVkEcKLky47pkrMBuuNtBZd5XKd8I9xr1gsE,4013
113
113
  port_ocean/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
114
  port_ocean/run.py,sha256=rTxBlrQd4yyrtgErCFJCHCEHs7d1OXrRiJehUYmIbN0,2212
115
115
  port_ocean/sonar-project.properties,sha256=X_wLzDOkEVmpGLRMb2fg9Rb0DxWwUFSvESId8qpvrPI,73
@@ -122,8 +122,8 @@ port_ocean/utils/queue_utils.py,sha256=KWWl8YVnG-glcfIHhM6nefY-2sou_C6DVP1VynQwz
122
122
  port_ocean/utils/repeat.py,sha256=0EFWM9d8lLXAhZmAyczY20LAnijw6UbIECf5lpGbOas,3231
123
123
  port_ocean/utils/signal.py,sha256=K-6kKFQTltcmKDhtyZAcn0IMa3sUpOHGOAUdWKgx0_E,1369
124
124
  port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
125
- port_ocean-0.9.7.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
126
- port_ocean-0.9.7.dist-info/METADATA,sha256=A16lG6rZE3WeGH9phYE6Iv2CRx0FmDuL_rjSsy78LJQ,6615
127
- port_ocean-0.9.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
128
- port_ocean-0.9.7.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
129
- port_ocean-0.9.7.dist-info/RECORD,,
125
+ port_ocean-0.9.10.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
126
+ port_ocean-0.9.10.dist-info/METADATA,sha256=dJEiCZBIoy0PErAsLASdKqs8VN-BHcU0qoPUmOLm3zc,6616
127
+ port_ocean-0.9.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
128
+ port_ocean-0.9.10.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
129
+ port_ocean-0.9.10.dist-info/RECORD,,