port-ocean 0.13.0__tar.gz → 0.14.0__tar.gz

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.

Files changed (149) hide show
  1. {port_ocean-0.13.0 → port_ocean-0.14.0}/PKG-INFO +1 -1
  2. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/defaults/clean.py +3 -1
  3. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/config/settings.py +1 -0
  4. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/defaults/clean.py +10 -3
  5. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/defaults/common.py +24 -8
  6. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/defaults/initialize.py +3 -1
  7. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/ocean.py +9 -1
  8. port_ocean-0.14.0/port_ocean/tests/core/defaults/test_common.py +166 -0
  9. {port_ocean-0.13.0 → port_ocean-0.14.0}/pyproject.toml +1 -1
  10. {port_ocean-0.13.0 → port_ocean-0.14.0}/LICENSE.md +0 -0
  11. {port_ocean-0.13.0 → port_ocean-0.14.0}/README.md +0 -0
  12. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/__init__.py +0 -0
  13. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/bootstrap.py +0 -0
  14. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/__init__.py +0 -0
  15. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cli.py +0 -0
  16. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/__init__.py +0 -0
  17. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/defaults/__init___.py +0 -0
  18. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/defaults/dock.py +0 -0
  19. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/defaults/group.py +0 -0
  20. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/list_integrations.py +0 -0
  21. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/main.py +0 -0
  22. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/new.py +0 -0
  23. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/pull.py +0 -0
  24. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/sail.py +0 -0
  25. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/commands/version.py +0 -0
  26. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/__init__.py +0 -0
  27. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/cookiecutter.json +0 -0
  28. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/extensions.py +0 -0
  29. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +0 -0
  30. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.dockerignore +0 -0
  31. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.env.example +0 -0
  32. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
  33. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
  34. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/blueprints.json +0 -0
  35. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/port-app-config.yml +0 -0
  36. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
  37. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
  38. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CONTRIBUTING.md +0 -0
  39. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/Dockerfile +0 -0
  40. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +0 -0
  41. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
  42. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
  43. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
  44. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
  45. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +0 -0
  46. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
  47. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py +0 -0
  48. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/test_sample.py +0 -0
  49. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/cli/utils.py +0 -0
  50. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/__init__.py +0 -0
  51. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/__init__.py +0 -0
  52. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/authentication.py +0 -0
  53. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/client.py +0 -0
  54. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/mixins/__init__.py +0 -0
  55. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/mixins/blueprints.py +0 -0
  56. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/mixins/entities.py +0 -0
  57. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/mixins/integrations.py +0 -0
  58. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/mixins/migrations.py +0 -0
  59. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/retry_transport.py +0 -0
  60. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/types.py +0 -0
  61. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/clients/port/utils.py +0 -0
  62. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/config/__init__.py +0 -0
  63. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/config/base.py +0 -0
  64. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/config/dynamic.py +0 -0
  65. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/consumers/__init__.py +0 -0
  66. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/consumers/kafka_consumer.py +0 -0
  67. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/context/__init__.py +0 -0
  68. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/context/event.py +0 -0
  69. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/context/ocean.py +0 -0
  70. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/context/resource.py +0 -0
  71. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/__init__.py +0 -0
  72. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/defaults/__init__.py +0 -0
  73. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/event_listener/__init__.py +0 -0
  74. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/event_listener/base.py +0 -0
  75. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/event_listener/factory.py +0 -0
  76. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/event_listener/http.py +0 -0
  77. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/event_listener/kafka.py +0 -0
  78. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/event_listener/once.py +0 -0
  79. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/event_listener/polling.py +0 -0
  80. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/__init__.py +0 -0
  81. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/base.py +0 -0
  82. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
  83. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entities_state_applier/base.py +0 -0
  84. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entities_state_applier/port/__init__.py +0 -0
  85. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entities_state_applier/port/applier.py +0 -0
  86. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +0 -0
  87. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
  88. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
  89. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entity_processor/base.py +0 -0
  90. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +0 -0
  91. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
  92. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/port_app_config/api.py +0 -0
  93. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/port_app_config/base.py +0 -0
  94. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/port_app_config/models.py +0 -0
  95. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/resync_state_updater/__init__.py +0 -0
  96. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/handlers/resync_state_updater/updater.py +0 -0
  97. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/integrations/__init__.py +0 -0
  98. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/integrations/base.py +0 -0
  99. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/integrations/mixins/__init__.py +0 -0
  100. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/integrations/mixins/events.py +0 -0
  101. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/integrations/mixins/handler.py +0 -0
  102. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/integrations/mixins/sync.py +0 -0
  103. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/integrations/mixins/sync_raw.py +0 -0
  104. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/integrations/mixins/utils.py +0 -0
  105. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/models.py +0 -0
  106. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/ocean_types.py +0 -0
  107. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/core/utils.py +0 -0
  108. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/exceptions/__init__.py +0 -0
  109. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/exceptions/api.py +0 -0
  110. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/exceptions/base.py +0 -0
  111. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/exceptions/clients.py +0 -0
  112. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/exceptions/context.py +0 -0
  113. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/exceptions/core.py +0 -0
  114. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/exceptions/port_defaults.py +0 -0
  115. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/exceptions/utils.py +0 -0
  116. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/helpers/__init__.py +0 -0
  117. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/helpers/async_client.py +0 -0
  118. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/helpers/retry.py +0 -0
  119. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/log/__init__.py +0 -0
  120. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/log/handlers.py +0 -0
  121. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/log/logger_setup.py +0 -0
  122. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/log/sensetive.py +0 -0
  123. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/middlewares.py +0 -0
  124. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/py.typed +0 -0
  125. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/run.py +0 -0
  126. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/sonar-project.properties +0 -0
  127. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/__init__.py +0 -0
  128. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/clients/port/mixins/test_entities.py +0 -0
  129. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/conftest.py +0 -0
  130. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +0 -0
  131. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/helpers/__init__.py +0 -0
  132. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/helpers/fixtures.py +0 -0
  133. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/helpers/integration.py +0 -0
  134. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/helpers/ocean_app.py +0 -0
  135. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/helpers/port_client.py +0 -0
  136. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/helpers/smoke_test.py +0 -0
  137. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/log/test_handlers.py +0 -0
  138. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/test_smoke.py +0 -0
  139. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/tests/utils/test_async_iterators.py +0 -0
  140. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/__init__.py +0 -0
  141. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/async_http.py +0 -0
  142. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/async_iterators.py +0 -0
  143. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/cache.py +0 -0
  144. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/misc.py +0 -0
  145. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/queue_utils.py +0 -0
  146. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/repeat.py +0 -0
  147. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/signal.py +0 -0
  148. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/utils/time.py +0 -0
  149. {port_ocean-0.13.0 → port_ocean-0.14.0}/port_ocean/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.13.0
3
+ Version: 0.14.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
@@ -51,4 +51,6 @@ def clean(path: str, force: bool, wait: bool) -> None:
51
51
  default_app,
52
52
  )
53
53
 
54
- clean_defaults(app.integration.AppConfigHandlerClass.CONFIG_CLASS, force, wait)
54
+ clean_defaults(
55
+ app.integration.AppConfigHandlerClass.CONFIG_CLASS, app.config, force, wait
56
+ )
@@ -78,6 +78,7 @@ class IntegrationConfiguration(BaseOceanSettings, extra=Extra.allow):
78
78
  default_factory=lambda: IntegrationSettings(type="", identifier="")
79
79
  )
80
80
  runtime: Runtime = Runtime.OnPrem
81
+ resources_path: str = Field(default=".port/resources")
81
82
 
82
83
  @root_validator()
83
84
  def validate_integration_config(cls, values: dict[str, Any]) -> dict[str, Any]:
@@ -4,6 +4,7 @@ from typing import Type
4
4
  import httpx
5
5
  from loguru import logger
6
6
 
7
+ from port_ocean.config.settings import IntegrationConfiguration
7
8
  from port_ocean.context.ocean import ocean
8
9
  from port_ocean.core.defaults.common import (
9
10
  get_port_integration_defaults,
@@ -14,12 +15,13 @@ from port_ocean.core.handlers.port_app_config.models import PortAppConfig
14
15
 
15
16
  def clean_defaults(
16
17
  config_class: Type[PortAppConfig],
18
+ integration_config: IntegrationConfiguration,
17
19
  force: bool,
18
20
  wait: bool,
19
21
  ) -> None:
20
22
  try:
21
23
  asyncio.new_event_loop().run_until_complete(
22
- _clean_defaults(config_class, force, wait)
24
+ _clean_defaults(config_class, integration_config, force, wait)
23
25
  )
24
26
 
25
27
  except Exception as e:
@@ -27,13 +29,18 @@ def clean_defaults(
27
29
 
28
30
 
29
31
  async def _clean_defaults(
30
- config_class: Type[PortAppConfig], force: bool, wait: bool
32
+ config_class: Type[PortAppConfig],
33
+ integration_config: IntegrationConfiguration,
34
+ force: bool,
35
+ wait: bool,
31
36
  ) -> None:
32
37
  port_client = ocean.port_client
33
38
  is_exists = await is_integration_exists(port_client)
34
39
  if not is_exists:
35
40
  return None
36
- defaults = get_port_integration_defaults(config_class)
41
+ defaults = get_port_integration_defaults(
42
+ config_class, integration_config.resources_path
43
+ )
37
44
  if not defaults:
38
45
  return None
39
46
 
@@ -3,6 +3,7 @@ from pathlib import Path
3
3
  from typing import Type, Any, TypedDict, Optional
4
4
 
5
5
  import httpx
6
+ from loguru import logger
6
7
  import yaml
7
8
  from pydantic import BaseModel, Field
8
9
  from starlette import status
@@ -77,18 +78,33 @@ def deconstruct_blueprints_to_creation_steps(
77
78
  )
78
79
 
79
80
 
81
+ def is_valid_dir(path: Path) -> bool:
82
+ return path.is_dir()
83
+
84
+
80
85
  def get_port_integration_defaults(
81
- port_app_config_class: Type[PortAppConfig], base_path: Path = Path(".")
86
+ port_app_config_class: Type[PortAppConfig],
87
+ custom_defaults_dir: Optional[str] = None,
88
+ base_path: Path = Path("."),
82
89
  ) -> Defaults | None:
83
- defaults_dir = base_path / ".port/resources"
84
- if not defaults_dir.exists():
85
- return None
86
-
87
- if not defaults_dir.is_dir():
88
- raise UnsupportedDefaultFileType(
89
- f"Defaults directory is not a directory: {defaults_dir}"
90
+ fallback_dir = base_path / ".port/resources"
91
+
92
+ if custom_defaults_dir and is_valid_dir(base_path / custom_defaults_dir):
93
+ defaults_dir = base_path / custom_defaults_dir
94
+ elif is_valid_dir(fallback_dir):
95
+ logger.info(
96
+ f"Could not find custom defaults directory {custom_defaults_dir}, falling back to {fallback_dir}",
97
+ fallback_dir=fallback_dir,
98
+ custom_defaults_dir=custom_defaults_dir,
99
+ )
100
+ defaults_dir = fallback_dir
101
+ else:
102
+ logger.warning(
103
+ f"Could not find defaults directory {fallback_dir}, skipping defaults"
90
104
  )
105
+ return None
91
106
 
107
+ logger.info(f"Loading defaults from {defaults_dir}", defaults_dir=defaults_dir)
92
108
  default_jsons = {}
93
109
  allowed_file_names = [
94
110
  field_model.alias for _, field_model in Defaults.__fields__.items()
@@ -198,7 +198,9 @@ async def _initialize_defaults(
198
198
  config_class: Type[PortAppConfig], integration_config: IntegrationConfiguration
199
199
  ) -> None:
200
200
  port_client = ocean.port_client
201
- defaults = get_port_integration_defaults(config_class)
201
+ defaults = get_port_integration_defaults(
202
+ config_class, integration_config.resources_path
203
+ )
202
204
  if not defaults:
203
205
  logger.warning("No defaults found. Skipping initialization...")
204
206
  return None
@@ -70,6 +70,8 @@ class Ocean:
70
70
  self.port_client, self.config.scheduled_resync_interval
71
71
  )
72
72
 
73
+ self.app_initialized = False
74
+
73
75
  def is_saas(self) -> bool:
74
76
  return self.config.runtime == Runtime.Saas
75
77
 
@@ -112,7 +114,7 @@ class Ocean:
112
114
  )
113
115
  await repeated_function()
114
116
 
115
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
117
+ def initialize_app(self) -> None:
116
118
  self.fast_api_app.include_router(self.integration_router, prefix="/integration")
117
119
 
118
120
  @asynccontextmanager
@@ -129,4 +131,10 @@ class Ocean:
129
131
  signal_handler.exit()
130
132
 
131
133
  self.fast_api_app.router.lifespan_context = lifecycle
134
+ self.app_initialized = True
135
+
136
+ async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
137
+ if not self.app_initialized:
138
+ self.initialize_app()
139
+
132
140
  await self.fast_api_app(scope, receive, send)
@@ -0,0 +1,166 @@
1
+ import pytest
2
+ import json
3
+ from unittest.mock import patch
4
+ from pathlib import Path
5
+ from port_ocean.core.handlers.port_app_config.models import PortAppConfig
6
+ from port_ocean.core.defaults.common import (
7
+ get_port_integration_defaults,
8
+ Defaults,
9
+ )
10
+
11
+
12
+ @pytest.fixture
13
+ def setup_mock_directories(tmp_path: Path) -> tuple[Path, Path, Path]:
14
+ # Create .port/resources with sample files
15
+ default_dir = tmp_path / ".port/resources"
16
+ default_dir.mkdir(parents=True, exist_ok=True)
17
+
18
+ # Create mock JSON and YAML files with expected content
19
+ (default_dir / "blueprints.json").write_text(
20
+ json.dumps(
21
+ [
22
+ {
23
+ "identifier": "mock-identifier",
24
+ "title": "mock-title",
25
+ "icon": "mock-icon",
26
+ "schema": {
27
+ "type": "object",
28
+ "properties": {"key": {"type": "string"}},
29
+ },
30
+ }
31
+ ]
32
+ )
33
+ )
34
+ (default_dir / "port-app-config.json").write_text(
35
+ json.dumps(
36
+ {
37
+ "resources": [
38
+ {
39
+ "kind": "mock-kind",
40
+ "selector": {"query": "true"},
41
+ "port": {
42
+ "entity": {
43
+ "mappings": {
44
+ "identifier": ".id",
45
+ "title": ".title",
46
+ "blueprint": '"mock-identifier"',
47
+ }
48
+ }
49
+ },
50
+ }
51
+ ]
52
+ }
53
+ )
54
+ )
55
+
56
+ # Create .port/custom_resources with different sample files
57
+ custom_resources_dir = tmp_path / ".port/custom_resources"
58
+ custom_resources_dir.mkdir(parents=True, exist_ok=True)
59
+
60
+ # Create mock JSON and YAML files with expected content
61
+ (custom_resources_dir / "blueprints.json").write_text(
62
+ json.dumps(
63
+ [
64
+ {
65
+ "identifier": "mock-custom-identifier",
66
+ "title": "mock-custom-title",
67
+ "icon": "mock-custom-icon",
68
+ "schema": {
69
+ "type": "object",
70
+ "properties": {"key": {"type": "string"}},
71
+ },
72
+ }
73
+ ]
74
+ )
75
+ )
76
+ (custom_resources_dir / "port-app-config.json").write_text(
77
+ json.dumps(
78
+ {
79
+ "resources": [
80
+ {
81
+ "kind": "mock-custom-kind",
82
+ "selector": {"query": "true"},
83
+ "port": {
84
+ "entity": {
85
+ "mappings": {
86
+ "identifier": ".id",
87
+ "title": ".title",
88
+ "blueprint": '"mock-custom-identifier"',
89
+ }
90
+ }
91
+ },
92
+ }
93
+ ]
94
+ }
95
+ )
96
+ )
97
+
98
+ # Define the non-existing directory path
99
+ non_existing_dir = tmp_path / ".port/do_not_exist"
100
+
101
+ return default_dir, custom_resources_dir, non_existing_dir
102
+
103
+
104
+ def test_custom_defaults_dir_used_if_valid(
105
+ setup_mock_directories: tuple[Path, Path, Path]
106
+ ) -> None:
107
+ # Arrange
108
+ _, custom_resources_dir, _ = setup_mock_directories
109
+
110
+ with (
111
+ patch("port_ocean.core.defaults.common.is_valid_dir") as mock_is_valid_dir,
112
+ patch(
113
+ "pathlib.Path.iterdir",
114
+ return_value=custom_resources_dir.iterdir(),
115
+ ),
116
+ ):
117
+ mock_is_valid_dir.side_effect = lambda path: path == custom_resources_dir
118
+
119
+ # Act
120
+ defaults = get_port_integration_defaults(
121
+ port_app_config_class=PortAppConfig,
122
+ custom_defaults_dir=".port/custom_resources",
123
+ base_path=custom_resources_dir.parent.parent,
124
+ )
125
+
126
+ # Assert
127
+ assert isinstance(defaults, Defaults)
128
+ assert defaults.blueprints[0].get("identifier") == "mock-custom-identifier"
129
+ assert defaults.port_app_config is not None
130
+ assert defaults.port_app_config.resources[0].kind == "mock-custom-kind"
131
+
132
+
133
+ def test_fallback_to_default_dir_if_custom_dir_invalid(
134
+ setup_mock_directories: tuple[Path, Path, Path]
135
+ ) -> None:
136
+ resources_dir, _, non_existing_dir = setup_mock_directories
137
+
138
+ # Arrange
139
+ with (
140
+ patch("port_ocean.core.defaults.common.is_valid_dir") as mock_is_valid_dir,
141
+ patch("pathlib.Path.iterdir", return_value=resources_dir.iterdir()),
142
+ ):
143
+
144
+ mock_is_valid_dir.side_effect = lambda path: path == resources_dir
145
+
146
+ # Act
147
+ custom_defaults_dir = str(non_existing_dir.relative_to(resources_dir.parent))
148
+ defaults = get_port_integration_defaults(
149
+ port_app_config_class=PortAppConfig,
150
+ custom_defaults_dir=custom_defaults_dir,
151
+ base_path=resources_dir.parent.parent,
152
+ )
153
+
154
+ # Assert
155
+ assert isinstance(defaults, Defaults)
156
+ assert defaults.blueprints[0].get("identifier") == "mock-identifier"
157
+ assert defaults.port_app_config is not None
158
+ assert defaults.port_app_config.resources[0].kind == "mock-kind"
159
+
160
+
161
+ def test_default_resources_path_does_not_exist() -> None:
162
+ # Act
163
+ defaults = get_port_integration_defaults(port_app_config_class=PortAppConfig)
164
+
165
+ # Assert
166
+ assert defaults is None
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "port-ocean"
3
- version = "0.13.0"
3
+ version = "0.14.0"
4
4
  description = "Port Ocean is a CLI tool for managing your Port projects."
5
5
  readme = "README.md"
6
6
  homepage = "https://app.getport.io"
File without changes
File without changes