port-ocean 0.11.0__tar.gz → 0.12.1__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 (147) hide show
  1. {port_ocean-0.11.0 → port_ocean-0.12.1}/PKG-INFO +1 -1
  2. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +24 -13
  3. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/log/sensetive.py +1 -1
  4. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +36 -1
  5. port_ocean-0.12.1/port_ocean/tests/helpers/fixtures.py +46 -0
  6. port_ocean-0.12.1/port_ocean/tests/helpers/integration.py +31 -0
  7. port_ocean-0.12.1/port_ocean/tests/helpers/port_client.py +21 -0
  8. port_ocean-0.12.1/port_ocean/tests/helpers/smoke_test.py +82 -0
  9. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/tests/test_smoke.py +1 -1
  10. {port_ocean-0.11.0 → port_ocean-0.12.1}/pyproject.toml +4 -1
  11. port_ocean-0.11.0/port_ocean/tests/helpers/fixtures.py +0 -124
  12. {port_ocean-0.11.0 → port_ocean-0.12.1}/LICENSE.md +0 -0
  13. {port_ocean-0.11.0 → port_ocean-0.12.1}/README.md +0 -0
  14. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/__init__.py +0 -0
  15. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/bootstrap.py +0 -0
  16. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/__init__.py +0 -0
  17. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cli.py +0 -0
  18. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/__init__.py +0 -0
  19. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/defaults/__init___.py +0 -0
  20. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/defaults/clean.py +0 -0
  21. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/defaults/dock.py +0 -0
  22. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/defaults/group.py +0 -0
  23. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/list_integrations.py +0 -0
  24. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/main.py +0 -0
  25. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/new.py +0 -0
  26. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/pull.py +0 -0
  27. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/sail.py +0 -0
  28. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/commands/version.py +0 -0
  29. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/__init__.py +0 -0
  30. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/cookiecutter.json +0 -0
  31. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/extensions.py +0 -0
  32. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +0 -0
  33. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.dockerignore +0 -0
  34. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.env.example +0 -0
  35. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
  36. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
  37. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/blueprints.json +0 -0
  38. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/port-app-config.yml +0 -0
  39. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
  40. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
  41. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CONTRIBUTING.md +0 -0
  42. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/Dockerfile +0 -0
  43. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +0 -0
  44. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
  45. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
  46. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
  47. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
  48. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +0 -0
  49. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
  50. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py +0 -0
  51. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/test_sample.py +0 -0
  52. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/cli/utils.py +0 -0
  53. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/__init__.py +0 -0
  54. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/__init__.py +0 -0
  55. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/authentication.py +0 -0
  56. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/client.py +0 -0
  57. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/mixins/__init__.py +0 -0
  58. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/mixins/blueprints.py +0 -0
  59. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/mixins/entities.py +0 -0
  60. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/mixins/integrations.py +0 -0
  61. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/mixins/migrations.py +0 -0
  62. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/retry_transport.py +0 -0
  63. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/types.py +0 -0
  64. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/clients/port/utils.py +0 -0
  65. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/config/__init__.py +0 -0
  66. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/config/base.py +0 -0
  67. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/config/dynamic.py +0 -0
  68. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/config/settings.py +0 -0
  69. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/consumers/__init__.py +0 -0
  70. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/consumers/kafka_consumer.py +0 -0
  71. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/context/__init__.py +0 -0
  72. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/context/event.py +0 -0
  73. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/context/ocean.py +0 -0
  74. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/context/resource.py +0 -0
  75. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/__init__.py +0 -0
  76. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/defaults/__init__.py +0 -0
  77. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/defaults/clean.py +0 -0
  78. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/defaults/common.py +0 -0
  79. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/defaults/initialize.py +0 -0
  80. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/event_listener/__init__.py +0 -0
  81. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/event_listener/base.py +0 -0
  82. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/event_listener/factory.py +0 -0
  83. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/event_listener/http.py +0 -0
  84. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/event_listener/kafka.py +0 -0
  85. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/event_listener/once.py +0 -0
  86. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/event_listener/polling.py +0 -0
  87. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/__init__.py +0 -0
  88. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/base.py +0 -0
  89. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
  90. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entities_state_applier/base.py +0 -0
  91. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entities_state_applier/port/__init__.py +0 -0
  92. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entities_state_applier/port/applier.py +0 -0
  93. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +0 -0
  94. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
  95. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
  96. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/entity_processor/base.py +0 -0
  97. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
  98. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/port_app_config/api.py +0 -0
  99. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/port_app_config/base.py +0 -0
  100. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/port_app_config/models.py +0 -0
  101. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/resync_state_updater/__init__.py +0 -0
  102. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/handlers/resync_state_updater/updater.py +0 -0
  103. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/integrations/__init__.py +0 -0
  104. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/integrations/base.py +0 -0
  105. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/integrations/mixins/__init__.py +0 -0
  106. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/integrations/mixins/events.py +0 -0
  107. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/integrations/mixins/handler.py +0 -0
  108. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/integrations/mixins/sync.py +0 -0
  109. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/integrations/mixins/sync_raw.py +0 -0
  110. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/integrations/mixins/utils.py +0 -0
  111. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/models.py +0 -0
  112. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/ocean_types.py +0 -0
  113. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/core/utils.py +0 -0
  114. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/exceptions/__init__.py +0 -0
  115. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/exceptions/api.py +0 -0
  116. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/exceptions/base.py +0 -0
  117. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/exceptions/clients.py +0 -0
  118. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/exceptions/context.py +0 -0
  119. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/exceptions/core.py +0 -0
  120. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/exceptions/port_defaults.py +0 -0
  121. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/exceptions/utils.py +0 -0
  122. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/helpers/__init__.py +0 -0
  123. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/helpers/async_client.py +0 -0
  124. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/helpers/retry.py +0 -0
  125. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/log/__init__.py +0 -0
  126. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/log/handlers.py +0 -0
  127. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/log/logger_setup.py +0 -0
  128. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/middlewares.py +0 -0
  129. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/ocean.py +0 -0
  130. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/py.typed +0 -0
  131. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/run.py +0 -0
  132. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/sonar-project.properties +0 -0
  133. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/tests/__init__.py +0 -0
  134. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/tests/clients/port/mixins/test_entities.py +0 -0
  135. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/tests/conftest.py +0 -0
  136. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/tests/helpers/__init__.py +0 -0
  137. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/tests/helpers/ocean_app.py +0 -0
  138. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/__init__.py +0 -0
  139. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/async_http.py +0 -0
  140. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/async_iterators.py +0 -0
  141. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/cache.py +0 -0
  142. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/misc.py +0 -0
  143. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/queue_utils.py +0 -0
  144. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/repeat.py +0 -0
  145. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/signal.py +0 -0
  146. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/utils/time.py +0 -0
  147. {port_ocean-0.11.0 → port_ocean-0.12.1}/port_ocean/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.11.0
3
+ Version: 0.12.1
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
@@ -47,37 +47,48 @@ class JQEntityProcessor(BaseEntityProcessor):
47
47
  pattern = "def env: {}; {} as $ENV | " + pattern
48
48
  return jq.compile(pattern)
49
49
 
50
+ @staticmethod
51
+ def _stop_iterator_handler(func: Any) -> Any:
52
+ """
53
+ Wrap the function to handle StopIteration exceptions.
54
+ Prevents StopIteration from stopping the thread and skipping further queue processing.
55
+ """
56
+
57
+ def inner() -> Any:
58
+ try:
59
+ return func()
60
+ except StopIteration:
61
+ return None
62
+
63
+ return inner
64
+
50
65
  async def _search(self, data: dict[str, Any], pattern: str) -> Any:
51
66
  try:
52
67
  loop = asyncio.get_event_loop()
53
68
  compiled_pattern = self._compile(pattern)
54
69
  func = compiled_pattern.input_value(data)
55
- return await loop.run_in_executor(None, func.first)
70
+ return await loop.run_in_executor(
71
+ None, self._stop_iterator_handler(func.first)
72
+ )
56
73
  except Exception as exc:
57
74
  logger.debug(
58
- f"Failed to search for pattern {pattern} in data {data}, {exc}"
75
+ f"Search failed for pattern '{pattern}' in data: {data}, Error: {exc}"
59
76
  )
60
77
  return None
61
78
 
62
79
  async def _search_as_bool(self, data: dict[str, Any], pattern: str) -> bool:
63
80
  loop = asyncio.get_event_loop()
64
- start_time = loop.time()
81
+
65
82
  compiled_pattern = self._compile(pattern)
66
83
  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,
84
+
85
+ value = await loop.run_in_executor(
86
+ None, self._stop_iterator_handler(func.first)
75
87
  )
76
88
  if isinstance(value, bool):
77
89
  return value
78
-
79
90
  raise EntityProcessorException(
80
- f"Expected boolean value, got {type(value)} instead"
91
+ f"Expected boolean value, got value:{value} of type: {type(value)} instead"
81
92
  )
82
93
 
83
94
  async def _search_as_object(
@@ -21,7 +21,7 @@ secret_patterns = {
21
21
  "GitHub": r"[g|G][i|I][t|T][h|H][u|U][b|B].*['|\"][0-9a-zA-Z]{35,40}['|\"]",
22
22
  "Google Cloud Platform API Key": r"AIza[0-9A-Za-z\\-_]{35}",
23
23
  "Google Cloud Platform OAuth": r"[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com",
24
- "Google (GCP) Service-account": r'"type": "service_account"',
24
+ "Google (GCP) Service-account": f'"type":{" "}"service_account"',
25
25
  "Google OAuth Access Token": r"ya29\\.[0-9A-Za-z\\-_]+",
26
26
  "Connection String": r"[a-zA-Z]+:\/\/[^/\s]+:[^/\s]+@[^/\s]+\/[^/\s]+",
27
27
  }
@@ -195,10 +195,45 @@ class TestJQEntityProcessor:
195
195
  pattern = ".foo"
196
196
  with pytest.raises(
197
197
  EntityProcessorException,
198
- match="Expected boolean value, got <class 'str'> instead",
198
+ match="Expected boolean value, got value:bar of type: <class 'str'> instead",
199
199
  ):
200
200
  await mocked_processor._search_as_bool(data, pattern)
201
201
 
202
+ @pytest.mark.parametrize(
203
+ "pattern, expected",
204
+ [
205
+ ('.parameters[] | select(.name == "not_exists") | .value', None),
206
+ (
207
+ '.parameters[] | select(.name == "parameter_name") | .value',
208
+ "parameter_value",
209
+ ),
210
+ (
211
+ '.parameters[] | select(.name == "another_parameter") | .value',
212
+ "another_value",
213
+ ),
214
+ ],
215
+ )
216
+ async def test_search_fails_on_stop_iteration(
217
+ self, mocked_processor: JQEntityProcessor, pattern: str, expected: Any
218
+ ) -> None:
219
+ data = {
220
+ "parameters": [
221
+ {"name": "parameter_name", "value": "parameter_value"},
222
+ {"name": "another_parameter", "value": "another_value"},
223
+ {"name": "another_parameter", "value": "another_value2"},
224
+ ]
225
+ }
226
+ result = await mocked_processor._search(data, pattern)
227
+ assert result == expected
228
+
229
+ async def test_return_a_list_of_values(
230
+ self, mocked_processor: JQEntityProcessor
231
+ ) -> None:
232
+ data = {"parameters": ["parameter_value", "another_value", "another_value2"]}
233
+ pattern = ".parameters"
234
+ result = await mocked_processor._search(data, pattern)
235
+ assert result == ["parameter_value", "another_value", "another_value2"]
236
+
202
237
  @pytest.mark.timeout(3)
203
238
  async def test_search_performance_10000(
204
239
  self, mocked_processor: JQEntityProcessor
@@ -0,0 +1,46 @@
1
+ from os import path
2
+ from typing import Any, Callable, List, Tuple
3
+
4
+ import pytest
5
+ import pytest_asyncio
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
+ from port_ocean.tests.helpers.smoke_test import (
15
+ SmokeTestDetails,
16
+ get_port_client_for_fake_integration,
17
+ get_smoke_test_details,
18
+ )
19
+
20
+
21
+ @pytest.fixture
22
+ def port_client_for_fake_integration() -> Tuple[SmokeTestDetails, PortClient]:
23
+ smoke_test_details = get_smoke_test_details()
24
+ port_client = get_port_client_for_fake_integration()
25
+
26
+ return smoke_test_details, port_client
27
+
28
+
29
+ @pytest_asyncio.fixture
30
+ def get_mocked_ocean_app(request: Any) -> Callable[[], Ocean]:
31
+ test_dir = path.join(path.dirname(request.module.__file__), "..")
32
+
33
+ def get_ocean_app() -> Ocean:
34
+ return get_integration_ocean_app(test_dir)
35
+
36
+ return get_ocean_app
37
+
38
+
39
+ @pytest_asyncio.fixture
40
+ def get_mock_ocean_resource_configs(request: Any) -> Callable[[], List[ResourceConfig]]:
41
+ module_dir = path.join(path.dirname(request.module.__file__), "..")
42
+
43
+ def get_ocean_resource_configs() -> List[ResourceConfig]:
44
+ return get_integation_resource_configs(module_dir)
45
+
46
+ return get_ocean_resource_configs
@@ -0,0 +1,31 @@
1
+ from typing import List
2
+
3
+ from loguru import logger
4
+
5
+ from port_ocean.clients.port.client import PortClient
6
+
7
+
8
+ async def cleanup_integration(client: PortClient, blueprints: List[str]) -> None:
9
+ for blueprint in blueprints:
10
+ try:
11
+ bp = await client.get_blueprint(blueprint)
12
+ if bp is not None:
13
+ migration_id = await client.delete_blueprint(
14
+ identifier=blueprint, delete_entities=True
15
+ )
16
+ if migration_id:
17
+ await client.wait_for_migration_to_complete(
18
+ migration_id=migration_id
19
+ )
20
+ except Exception as bp_e:
21
+ logger.info(f"Skipping missing blueprint ({blueprint}): {bp_e}")
22
+ headers = await client.auth.headers()
23
+ try:
24
+ await client.client.delete(
25
+ f"{client.auth.api_url}/integrations/{client.integration_identifier}",
26
+ headers=headers,
27
+ )
28
+ except Exception as int_e:
29
+ logger.info(
30
+ f"Failed to delete integration ({client.integration_identifier}): {int_e}"
31
+ )
@@ -0,0 +1,21 @@
1
+ from typing import Union
2
+
3
+ from port_ocean.clients.port.client import PortClient
4
+
5
+
6
+ def get_port_client_for_integration(
7
+ client_id: str,
8
+ client_secret: str,
9
+ integration_identifier: str,
10
+ integration_type: str,
11
+ integration_version: str,
12
+ base_url: Union[str, None],
13
+ ) -> PortClient:
14
+ return PortClient(
15
+ base_url=base_url or "https://api.getport/io",
16
+ client_id=client_id,
17
+ client_secret=client_secret,
18
+ integration_identifier=integration_identifier,
19
+ integration_type=integration_type,
20
+ integration_version=integration_version,
21
+ )
@@ -0,0 +1,82 @@
1
+ from os import environ
2
+ from port_ocean.clients.port.client import PortClient
3
+
4
+ from loguru import logger
5
+ from pydantic import BaseModel
6
+
7
+ from port_ocean.tests.helpers.integration import cleanup_integration
8
+ from port_ocean.tests.helpers.port_client import get_port_client_for_integration
9
+
10
+
11
+ class SmokeTestDetails(BaseModel):
12
+ integration_identifier: str
13
+ blueprint_department: str
14
+ blueprint_person: str
15
+ integration_type: str
16
+ integration_version: str
17
+
18
+
19
+ def get_smoke_test_details() -> SmokeTestDetails:
20
+ blueprint_department = "fake-department"
21
+ blueprint_person = "fake-person"
22
+ integration_identifier = "smoke-test-integration"
23
+ smoke_test_suffix = environ.get("SMOKE_TEST_SUFFIX")
24
+ if smoke_test_suffix is not None:
25
+ integration_identifier = f"{integration_identifier}-{smoke_test_suffix}"
26
+ blueprint_person = f"{blueprint_person}-{smoke_test_suffix}"
27
+ blueprint_department = f"{blueprint_department}-{smoke_test_suffix}"
28
+
29
+ return SmokeTestDetails(
30
+ integration_identifier=integration_identifier,
31
+ blueprint_person=blueprint_person,
32
+ blueprint_department=blueprint_department,
33
+ integration_version="0.1.4-dev",
34
+ integration_type="smoke-test",
35
+ )
36
+
37
+
38
+ async def cleanup_smoke_test() -> None:
39
+ smoke_test_details = get_smoke_test_details()
40
+ client_id = environ.get("PORT_CLIENT_ID")
41
+ client_secret = environ.get("PORT_CLIENT_SECRET")
42
+
43
+ if not client_secret or not client_id:
44
+ assert False, "Missing port credentials"
45
+
46
+ base_url = environ.get("PORT_BASE_URL")
47
+ client = get_port_client_for_integration(
48
+ client_id,
49
+ client_secret,
50
+ smoke_test_details.integration_identifier,
51
+ smoke_test_details.integration_type,
52
+ smoke_test_details.integration_version,
53
+ base_url,
54
+ )
55
+
56
+ logger.info("Cleaning up fake integration")
57
+ await cleanup_integration(
58
+ client,
59
+ [smoke_test_details.blueprint_department, smoke_test_details.blueprint_person],
60
+ )
61
+ logger.info("Cleaning up fake integration complete")
62
+
63
+
64
+ def get_port_client_for_fake_integration() -> PortClient:
65
+ smoke_test_details = get_smoke_test_details()
66
+ client_id = environ.get("PORT_CLIENT_ID")
67
+ client_secret = environ.get("PORT_CLIENT_SECRET")
68
+
69
+ if not client_secret or not client_id:
70
+ assert False, "Missing port credentials"
71
+
72
+ base_url = environ.get("PORT_BASE_URL")
73
+ client = get_port_client_for_integration(
74
+ client_id,
75
+ client_secret,
76
+ smoke_test_details.integration_identifier,
77
+ smoke_test_details.integration_type,
78
+ smoke_test_details.integration_version,
79
+ base_url,
80
+ )
81
+
82
+ return client
@@ -4,7 +4,7 @@ import pytest
4
4
 
5
5
  from port_ocean.clients.port.client import PortClient
6
6
  from port_ocean.clients.port.types import UserAgentType
7
- from port_ocean.tests.helpers.fixtures import SmokeTestDetails
7
+ from port_ocean.tests.helpers.smoke_test import SmokeTestDetails
8
8
 
9
9
 
10
10
  pytestmark = pytest.mark.smoke
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "port-ocean"
3
- version = "0.11.0"
3
+ version = "0.12.1"
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"
@@ -176,3 +176,6 @@ exclude = '''
176
176
  asyncio_mode = "auto"
177
177
  asyncio_default_fixture_loop_scope = "function"
178
178
  addopts = "-vv -n auto --durations=10 --color=yes --ignore-glob='./integrations/*' ./port_ocean/tests"
179
+ markers = [
180
+ "smoke: Smoke tests (deselect with '-m \"not smoke\"')"
181
+ ]
@@ -1,124 +0,0 @@
1
- from os import environ, path
2
- from typing import Any, AsyncGenerator, Callable, List, Tuple, Union
3
-
4
- import pytest_asyncio
5
- from loguru import logger
6
- from pydantic import BaseModel
7
-
8
- from port_ocean.clients.port.client import PortClient
9
- from port_ocean.core.handlers.port_app_config.models import ResourceConfig
10
- from port_ocean.ocean import Ocean
11
- from port_ocean.tests.helpers.ocean_app import (
12
- get_integation_resource_configs,
13
- get_integration_ocean_app,
14
- )
15
-
16
-
17
- def get_port_client_for_integration(
18
- client_id: str,
19
- client_secret: str,
20
- integration_identifier: str,
21
- integration_type: str,
22
- integration_version: str,
23
- base_url: Union[str, None],
24
- ) -> PortClient:
25
- return PortClient(
26
- base_url=base_url or "https://api.getport/io",
27
- client_id=client_id,
28
- client_secret=client_secret,
29
- integration_identifier=integration_identifier,
30
- integration_type=integration_type,
31
- integration_version=integration_version,
32
- )
33
-
34
-
35
- async def cleanup_integration(client: PortClient, blueprints: List[str]) -> None:
36
- for blueprint in blueprints:
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}")
49
- headers = await client.auth.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
- )
59
-
60
-
61
- class SmokeTestDetails(BaseModel):
62
- integration_identifier: str
63
- blueprint_department: str
64
- blueprint_person: str
65
-
66
-
67
- @pytest_asyncio.fixture()
68
- async def port_client_for_fake_integration() -> (
69
- AsyncGenerator[Tuple[SmokeTestDetails, PortClient], None]
70
- ):
71
- blueprint_department = "fake-department"
72
- blueprint_person = "fake-person"
73
- integration_identifier = "smoke-test-integration"
74
- smoke_test_suffix = environ.get("SMOKE_TEST_SUFFIX")
75
- client_id = environ.get("PORT_CLIENT_ID")
76
- client_secret = environ.get("PORT_CLIENT_SECRET")
77
-
78
- if not client_secret or not client_id:
79
- assert False, "Missing port credentials"
80
-
81
- base_url = environ.get("PORT_BASE_URL")
82
- integration_version = "0.1.1-dev"
83
- integration_type = "smoke-test"
84
- if smoke_test_suffix is not None:
85
- integration_identifier = f"{integration_identifier}-{smoke_test_suffix}"
86
- blueprint_person = f"{blueprint_person}-{smoke_test_suffix}"
87
- blueprint_department = f"{blueprint_department}-{smoke_test_suffix}"
88
-
89
- client = get_port_client_for_integration(
90
- client_id,
91
- client_secret,
92
- integration_identifier,
93
- integration_type,
94
- integration_version,
95
- base_url,
96
- )
97
-
98
- smoke_test_details = SmokeTestDetails(
99
- integration_identifier=integration_identifier,
100
- blueprint_person=blueprint_person,
101
- blueprint_department=blueprint_department,
102
- )
103
- yield smoke_test_details, client
104
- await cleanup_integration(client, [blueprint_department, blueprint_person])
105
-
106
-
107
- @pytest_asyncio.fixture
108
- def get_mocked_ocean_app(request: Any) -> Callable[[], Ocean]:
109
- test_dir = path.join(path.dirname(request.module.__file__), "..")
110
-
111
- def get_ocean_app() -> Ocean:
112
- return get_integration_ocean_app(test_dir)
113
-
114
- return get_ocean_app
115
-
116
-
117
- @pytest_asyncio.fixture
118
- def get_mock_ocean_resource_configs(request: Any) -> Callable[[], List[ResourceConfig]]:
119
- module_dir = path.join(path.dirname(request.module.__file__), "..")
120
-
121
- def get_ocean_resource_configs() -> List[ResourceConfig]:
122
- return get_integation_resource_configs(module_dir)
123
-
124
- return get_ocean_resource_configs
File without changes
File without changes