port-ocean 0.24.20__tar.gz → 0.24.22__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.
Files changed (208) hide show
  1. {port_ocean-0.24.20 → port_ocean-0.24.22}/PKG-INFO +1 -1
  2. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/mixins/integrations.py +3 -1
  3. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/config/dynamic.py +27 -2
  4. port_ocean-0.24.22/port_ocean/tests/clients/port/mixins/test_integrations.py +205 -0
  5. port_ocean-0.24.22/port_ocean/tests/config/test_config.py +38 -0
  6. {port_ocean-0.24.20 → port_ocean-0.24.22}/pyproject.toml +1 -1
  7. {port_ocean-0.24.20 → port_ocean-0.24.22}/LICENSE.md +0 -0
  8. {port_ocean-0.24.20 → port_ocean-0.24.22}/README.md +0 -0
  9. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/Dockerfile.Deb +0 -0
  10. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/Dockerfile.alpine +0 -0
  11. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/Dockerfile.base.builder +0 -0
  12. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/Dockerfile.base.runner +0 -0
  13. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/Dockerfile.dockerignore +0 -0
  14. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/Dockerfile.local +0 -0
  15. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/Makefile +0 -0
  16. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/entry_local.sh +0 -0
  17. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/grpcio.sh +0 -0
  18. {port_ocean-0.24.20 → port_ocean-0.24.22}/integrations/_infra/init.sh +0 -0
  19. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/__init__.py +0 -0
  20. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/bootstrap.py +0 -0
  21. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cache/__init__.py +0 -0
  22. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cache/base.py +0 -0
  23. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cache/disk.py +0 -0
  24. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cache/errors.py +0 -0
  25. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cache/memory.py +0 -0
  26. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/__init__.py +0 -0
  27. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cli.py +0 -0
  28. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/__init__.py +0 -0
  29. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/defaults/__init___.py +0 -0
  30. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/defaults/clean.py +0 -0
  31. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/defaults/dock.py +0 -0
  32. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/defaults/group.py +0 -0
  33. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/list_integrations.py +0 -0
  34. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/main.py +0 -0
  35. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/new.py +0 -0
  36. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/pull.py +0 -0
  37. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/sail.py +0 -0
  38. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/commands/version.py +0 -0
  39. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/__init__.py +0 -0
  40. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/cookiecutter.json +0 -0
  41. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/extensions.py +0 -0
  42. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +0 -0
  43. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.env.example +0 -0
  44. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
  45. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
  46. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/blueprints.json +0 -0
  47. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/port-app-config.yml +0 -0
  48. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
  49. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
  50. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CONTRIBUTING.md +0 -0
  51. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +0 -0
  52. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
  53. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
  54. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
  55. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
  56. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +0 -0
  57. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
  58. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py +0 -0
  59. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/test_sample.py +0 -0
  60. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/cli/utils.py +0 -0
  61. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/__init__.py +0 -0
  62. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/auth/__init__.py +0 -0
  63. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/auth/auth_client.py +0 -0
  64. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/auth/oauth_client.py +0 -0
  65. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/__init__.py +0 -0
  66. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/authentication.py +0 -0
  67. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/client.py +0 -0
  68. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/mixins/__init__.py +0 -0
  69. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/mixins/blueprints.py +0 -0
  70. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/mixins/entities.py +0 -0
  71. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/mixins/migrations.py +0 -0
  72. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/mixins/organization.py +0 -0
  73. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/retry_transport.py +0 -0
  74. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/types.py +0 -0
  75. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/clients/port/utils.py +0 -0
  76. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/config/__init__.py +0 -0
  77. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/config/base.py +0 -0
  78. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/config/settings.py +0 -0
  79. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/consumers/__init__.py +0 -0
  80. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/consumers/kafka_consumer.py +0 -0
  81. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/context/__init__.py +0 -0
  82. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/context/event.py +0 -0
  83. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/context/metric_resource.py +0 -0
  84. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/context/ocean.py +0 -0
  85. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/context/resource.py +0 -0
  86. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/__init__.py +0 -0
  87. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/defaults/__init__.py +0 -0
  88. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/defaults/clean.py +0 -0
  89. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/defaults/common.py +0 -0
  90. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/defaults/initialize.py +0 -0
  91. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/event_listener/__init__.py +0 -0
  92. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/event_listener/base.py +0 -0
  93. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/event_listener/factory.py +0 -0
  94. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/event_listener/http.py +0 -0
  95. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/event_listener/kafka.py +0 -0
  96. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/event_listener/once.py +0 -0
  97. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/event_listener/polling.py +0 -0
  98. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/event_listener/webhooks_only.py +0 -0
  99. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/__init__.py +0 -0
  100. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/base.py +0 -0
  101. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
  102. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entities_state_applier/base.py +0 -0
  103. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entities_state_applier/port/__init__.py +0 -0
  104. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entities_state_applier/port/applier.py +0 -0
  105. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +0 -0
  106. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
  107. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
  108. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entity_processor/base.py +0 -0
  109. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +0 -0
  110. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
  111. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/port_app_config/api.py +0 -0
  112. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/port_app_config/base.py +0 -0
  113. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/port_app_config/models.py +0 -0
  114. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/queue/__init__.py +0 -0
  115. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/queue/abstract_queue.py +0 -0
  116. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/queue/local_queue.py +0 -0
  117. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/resync_state_updater/__init__.py +0 -0
  118. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/resync_state_updater/updater.py +0 -0
  119. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/webhook/__init__.py +0 -0
  120. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/webhook/abstract_webhook_processor.py +0 -0
  121. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/webhook/processor_manager.py +0 -0
  122. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/handlers/webhook/webhook_event.py +0 -0
  123. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/__init__.py +0 -0
  124. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/base.py +0 -0
  125. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/mixins/__init__.py +0 -0
  126. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/mixins/events.py +0 -0
  127. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/mixins/handler.py +0 -0
  128. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/mixins/live_events.py +0 -0
  129. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/mixins/sync.py +0 -0
  130. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/mixins/sync_raw.py +0 -0
  131. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/integrations/mixins/utils.py +0 -0
  132. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/models.py +0 -0
  133. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/ocean_types.py +0 -0
  134. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/utils/entity_topological_sorter.py +0 -0
  135. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/core/utils/utils.py +0 -0
  136. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/debug_cli.py +0 -0
  137. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/__init__.py +0 -0
  138. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/api.py +0 -0
  139. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/base.py +0 -0
  140. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/clients.py +0 -0
  141. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/context.py +0 -0
  142. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/core.py +0 -0
  143. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/port_defaults.py +0 -0
  144. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/utils.py +0 -0
  145. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/exceptions/webhook_processor.py +0 -0
  146. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/helpers/__init__.py +0 -0
  147. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/helpers/async_client.py +0 -0
  148. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/helpers/metric/metric.py +0 -0
  149. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/helpers/metric/utils.py +0 -0
  150. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/helpers/retry.py +0 -0
  151. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/log/__init__.py +0 -0
  152. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/log/handlers.py +0 -0
  153. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/log/logger_setup.py +0 -0
  154. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/log/sensetive.py +0 -0
  155. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/middlewares.py +0 -0
  156. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/ocean.py +0 -0
  157. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/py.typed +0 -0
  158. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/run.py +0 -0
  159. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/sonar-project.properties +0 -0
  160. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/__init__.py +0 -0
  161. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/cache/__init__.py +0 -0
  162. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/cache/test_disk_cache.py +0 -0
  163. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/cache/test_memory_cache.py +0 -0
  164. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/clients/__init__.py +0 -0
  165. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/clients/oauth/__init__.py +0 -0
  166. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/clients/oauth/test_oauth_client.py +0 -0
  167. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/clients/port/mixins/test_entities.py +0 -0
  168. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/clients/port/mixins/test_organization_mixin.py +0 -0
  169. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/conftest.py +0 -0
  170. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/conftest.py +0 -0
  171. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/defaults/test_common.py +0 -0
  172. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/entities_state_applier/test_applier.py +0 -0
  173. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +0 -0
  174. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/mixins/test_live_events.py +0 -0
  175. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/mixins/test_sync_raw.py +0 -0
  176. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/port_app_config/test_api.py +0 -0
  177. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/port_app_config/test_base.py +0 -0
  178. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/queue/test_local_queue.py +0 -0
  179. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/webhook/test_abstract_webhook_processor.py +0 -0
  180. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/webhook/test_processor_manager.py +0 -0
  181. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/handlers/webhook/test_webhook_event.py +0 -0
  182. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/test_utils.py +0 -0
  183. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/utils/test_entity_topological_sorter.py +0 -0
  184. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/core/utils/test_resolve_entities_diff.py +0 -0
  185. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/helpers/__init__.py +0 -0
  186. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/helpers/fake_port_api.py +0 -0
  187. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/helpers/fixtures.py +0 -0
  188. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/helpers/integration.py +0 -0
  189. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/helpers/ocean_app.py +0 -0
  190. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/helpers/port_client.py +0 -0
  191. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/helpers/smoke_test.py +0 -0
  192. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/log/test_handlers.py +0 -0
  193. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/test_metric.py +0 -0
  194. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/test_ocean.py +0 -0
  195. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/test_smoke.py +0 -0
  196. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/utils/test_async_iterators.py +0 -0
  197. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/tests/utils/test_cache.py +0 -0
  198. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/__init__.py +0 -0
  199. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/async_http.py +0 -0
  200. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/async_iterators.py +0 -0
  201. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/cache.py +0 -0
  202. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/ipc.py +0 -0
  203. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/misc.py +0 -0
  204. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/queue_utils.py +0 -0
  205. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/repeat.py +0 -0
  206. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/signal.py +0 -0
  207. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/utils/time.py +0 -0
  208. {port_ocean-0.24.20 → port_ocean-0.24.22}/port_ocean/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.24.20
3
+ Version: 0.24.22
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
@@ -228,9 +228,11 @@ class IntegrationClientMixin:
228
228
  async def put_integration_sync_metrics(self, kind_metrics: dict[str, Any]) -> None:
229
229
  logger.debug("starting PUT metrics request", kind_metrics=kind_metrics)
230
230
  metrics_attributes = await self.get_metrics_attributes()
231
+ event_id = quote_plus(kind_metrics["eventId"])
232
+ kind_identifier = quote_plus(kind_metrics["kindIdentifier"])
231
233
  url = (
232
234
  metrics_attributes["ingestUrl"]
233
- + f"/syncMetrics/resync/{kind_metrics['eventId']}/kind/{kind_metrics['kindIdentifier']}"
235
+ + f"/syncMetrics/resync/{event_id}/kind/{kind_identifier}"
234
236
  )
235
237
  headers = await self.auth.headers()
236
238
  response = await self.client.put(
@@ -2,12 +2,37 @@ import json
2
2
  from typing import Type, Any, Optional
3
3
 
4
4
  from humps import decamelize
5
- from pydantic import BaseModel, AnyUrl, create_model, Extra, parse_obj_as, validator
5
+ from pydantic import (
6
+ BaseConfig,
7
+ BaseModel,
8
+ AnyUrl,
9
+ create_model,
10
+ Extra,
11
+ parse_obj_as,
12
+ validator,
13
+ )
6
14
  from pydantic.fields import ModelField, Field
7
15
 
8
16
  from port_ocean.config.base import BaseOceanModel
9
17
 
10
18
 
19
+ class NoTrailingSlashUrl(AnyUrl):
20
+ @classmethod
21
+ def validate(cls, value: Any, field: ModelField, config: BaseConfig) -> "AnyUrl":
22
+ if value is not None:
23
+ if isinstance(value, (bytes, bytearray)):
24
+ try:
25
+ value = value.decode()
26
+ except UnicodeDecodeError as exc:
27
+ raise ValueError("URL bytes must be valid UTF-8") from exc
28
+ else:
29
+ value = str(value)
30
+
31
+ if value != "/":
32
+ value = value.rstrip("/")
33
+ return super().validate(value, field, config)
34
+
35
+
11
36
  class Configuration(BaseModel, extra=Extra.allow):
12
37
  name: str
13
38
  type: str
@@ -39,7 +64,7 @@ def default_config_factory(configurations: Any) -> Type[BaseModel]:
39
64
  case "object":
40
65
  field_type = dict
41
66
  case "url":
42
- field_type = AnyUrl
67
+ field_type = NoTrailingSlashUrl
43
68
  case "string":
44
69
  field_type = str
45
70
  case "integer":
@@ -0,0 +1,205 @@
1
+ from typing import Any
2
+ from unittest.mock import MagicMock, patch, AsyncMock
3
+
4
+ import pytest
5
+ import httpx
6
+
7
+ from port_ocean.clients.port.mixins.integrations import IntegrationClientMixin
8
+
9
+
10
+ TEST_INTEGRATION_IDENTIFIER = "test-integration"
11
+ TEST_INTEGRATION_VERSION = "1.0.0"
12
+ TEST_INGEST_URL = "https://api.example.com"
13
+
14
+ BASIC_KIND_METRICS = {
15
+ "eventId": "event-123",
16
+ "kindIdentifier": "service",
17
+ "metrics": {"count": 5},
18
+ }
19
+
20
+ KIND_METRICS_WITH_SLASH = {
21
+ "eventId": "event-456",
22
+ "kindIdentifier": "kind/kind1",
23
+ "metrics": {"count": 10},
24
+ }
25
+
26
+ EVENT_METRICS_WITH_SLASH = {
27
+ "eventId": "event/123",
28
+ "kindIdentifier": "service",
29
+ "metrics": {"count": 15},
30
+ }
31
+
32
+ BOTH_METRICS_WITH_SLASH = {
33
+ "eventId": "namespace/event/123",
34
+ "kindIdentifier": "app/service/v1",
35
+ "metrics": {"count": 20},
36
+ }
37
+
38
+ COMPLEX_KIND_METRICS = {
39
+ "eventId": "complete/test/123",
40
+ "kindIdentifier": "complex/kind/identifier",
41
+ "syncStart": "2024-01-01T00:00:00Z",
42
+ "syncEnd": "2024-01-01T01:00:00Z",
43
+ "metrics": {"totalEntities": 100, "successfulEntities": 95, "failedEntities": 5},
44
+ }
45
+
46
+
47
+ @pytest.fixture
48
+ def integration_client(monkeypatch: Any) -> IntegrationClientMixin:
49
+ """Create an IntegrationClientMixin instance with mocked dependencies."""
50
+ auth = MagicMock()
51
+ auth.headers = AsyncMock()
52
+ auth.headers.return_value = {"Authorization": "Bearer test-token"}
53
+
54
+ client = MagicMock()
55
+ client.put = AsyncMock()
56
+ client.put.return_value = MagicMock()
57
+ client.put.return_value.status_code = 200
58
+ client.put.return_value.is_error = False
59
+
60
+ integration_client = IntegrationClientMixin(
61
+ integration_identifier=TEST_INTEGRATION_IDENTIFIER,
62
+ integration_version=TEST_INTEGRATION_VERSION,
63
+ auth=auth,
64
+ client=client,
65
+ )
66
+
67
+ mock_get_metrics_attributes = AsyncMock()
68
+ mock_get_metrics_attributes.return_value = {"ingestUrl": TEST_INGEST_URL}
69
+ monkeypatch.setattr(
70
+ integration_client, "get_metrics_attributes", mock_get_metrics_attributes
71
+ )
72
+
73
+ return integration_client
74
+
75
+
76
+ async def test_put_integration_sync_metrics_basic(
77
+ integration_client: IntegrationClientMixin,
78
+ ) -> None:
79
+ """Test basic functionality of put_integration_sync_metrics."""
80
+ with patch(
81
+ "port_ocean.clients.port.mixins.integrations.handle_port_status_code"
82
+ ) as mock_handle:
83
+ await integration_client.put_integration_sync_metrics(BASIC_KIND_METRICS)
84
+
85
+ integration_client.get_metrics_attributes.assert_called_once()
86
+
87
+ integration_client.auth.headers.assert_called_once()
88
+
89
+ integration_client.client.put.assert_called_once()
90
+ call_args = integration_client.client.put.call_args
91
+
92
+ expected_url = f"{TEST_INGEST_URL}/syncMetrics/resync/event-123/kind/service"
93
+ assert call_args[0][0] == expected_url
94
+
95
+ expected_headers = {"Authorization": "Bearer test-token"}
96
+ assert call_args[1]["headers"] == expected_headers
97
+
98
+ expected_json = {"syncKindMetrics": BASIC_KIND_METRICS}
99
+ assert call_args[1]["json"] == expected_json
100
+
101
+ mock_handle.assert_called_once_with(
102
+ integration_client.client.put.return_value, should_log=False
103
+ )
104
+
105
+
106
+ async def test_put_integration_sync_metrics_with_slash_in_kind_identifier(
107
+ integration_client: IntegrationClientMixin,
108
+ ) -> None:
109
+ """Test put_integration_sync_metrics with forward slash in kindIdentifier."""
110
+ with patch("port_ocean.clients.port.mixins.integrations.handle_port_status_code"):
111
+ await integration_client.put_integration_sync_metrics(KIND_METRICS_WITH_SLASH)
112
+
113
+ integration_client.client.put.assert_called_once()
114
+ call_args = integration_client.client.put.call_args
115
+
116
+ expected_url = (
117
+ f"{TEST_INGEST_URL}/syncMetrics/resync/event-456/kind/kind%2Fkind1"
118
+ )
119
+ assert call_args[0][0] == expected_url
120
+
121
+ expected_json = {"syncKindMetrics": KIND_METRICS_WITH_SLASH}
122
+ assert call_args[1]["json"] == expected_json
123
+
124
+
125
+ async def test_put_integration_sync_metrics_with_slash_in_event_id(
126
+ integration_client: IntegrationClientMixin,
127
+ ) -> None:
128
+ """Test put_integration_sync_metrics with forward slash in eventId."""
129
+ with patch("port_ocean.clients.port.mixins.integrations.handle_port_status_code"):
130
+ await integration_client.put_integration_sync_metrics(EVENT_METRICS_WITH_SLASH)
131
+
132
+ integration_client.client.put.assert_called_once()
133
+ call_args = integration_client.client.put.call_args
134
+
135
+ expected_url = f"{TEST_INGEST_URL}/syncMetrics/resync/event%2F123/kind/service"
136
+ assert call_args[0][0] == expected_url
137
+
138
+
139
+ async def test_put_integration_sync_metrics_with_slashes_in_both_fields(
140
+ integration_client: IntegrationClientMixin,
141
+ ) -> None:
142
+ """Test put_integration_sync_metrics with forward slashes in both eventId and kindIdentifier."""
143
+ with patch("port_ocean.clients.port.mixins.integrations.handle_port_status_code"):
144
+ await integration_client.put_integration_sync_metrics(BOTH_METRICS_WITH_SLASH)
145
+
146
+ integration_client.client.put.assert_called_once()
147
+ call_args = integration_client.client.put.call_args
148
+
149
+ expected_url = f"{TEST_INGEST_URL}/syncMetrics/resync/namespace%2Fevent%2F123/kind/app%2Fservice%2Fv1"
150
+ assert call_args[0][0] == expected_url
151
+
152
+
153
+ async def test_put_integration_sync_metrics_with_special_characters(
154
+ integration_client: IntegrationClientMixin,
155
+ ) -> None:
156
+ """Test put_integration_sync_metrics with various special characters that need URL encoding."""
157
+ special_metrics = {
158
+ "eventId": "event@123#test",
159
+ "kindIdentifier": "kind with spaces+symbols",
160
+ "metrics": {"count": 25},
161
+ }
162
+
163
+ with patch("port_ocean.clients.port.mixins.integrations.handle_port_status_code"):
164
+ await integration_client.put_integration_sync_metrics(special_metrics)
165
+
166
+ integration_client.client.put.assert_called_once()
167
+ call_args = integration_client.client.put.call_args
168
+
169
+ expected_url = f"{TEST_INGEST_URL}/syncMetrics/resync/event%40123%23test/kind/kind+with+spaces%2Bsymbols"
170
+ assert call_args[0][0] == expected_url
171
+
172
+
173
+ async def test_put_integration_sync_metrics_complete_flow(
174
+ integration_client: IntegrationClientMixin,
175
+ ) -> None:
176
+ """Test the complete flow of put_integration_sync_metrics method."""
177
+ with patch("port_ocean.clients.port.mixins.integrations.handle_port_status_code"):
178
+ await integration_client.put_integration_sync_metrics(COMPLEX_KIND_METRICS)
179
+
180
+ integration_client.get_metrics_attributes.assert_called_once()
181
+ integration_client.auth.headers.assert_called_once()
182
+ integration_client.client.put.assert_called_once()
183
+
184
+ call_args = integration_client.client.put.call_args
185
+ assert "complete%2Ftest%2F123" in call_args[0][0]
186
+ assert "complex%2Fkind%2Fidentifier" in call_args[0][0]
187
+
188
+ assert call_args[1]["json"]["syncKindMetrics"] == COMPLEX_KIND_METRICS
189
+
190
+
191
+ async def test_put_integration_sync_metrics_error_handling(
192
+ integration_client: IntegrationClientMixin,
193
+ monkeypatch: Any,
194
+ ) -> None:
195
+ """Test that put_integration_sync_metrics properly handles errors."""
196
+ mock_get_metrics_attributes = AsyncMock()
197
+ mock_get_metrics_attributes.side_effect = httpx.HTTPStatusError(
198
+ message="Test error", request=MagicMock(), response=MagicMock()
199
+ )
200
+ monkeypatch.setattr(
201
+ integration_client, "get_metrics_attributes", mock_get_metrics_attributes
202
+ )
203
+
204
+ with pytest.raises(httpx.HTTPStatusError):
205
+ await integration_client.put_integration_sync_metrics(BASIC_KIND_METRICS)
@@ -0,0 +1,38 @@
1
+ import pytest
2
+ from pydantic import BaseModel
3
+ from port_ocean.config.dynamic import NoTrailingSlashUrl
4
+ from typing import cast
5
+
6
+
7
+ class TestClass(BaseModel):
8
+ url: NoTrailingSlashUrl | None
9
+
10
+
11
+ def as_no_trailing_slash_url(value: str | None) -> NoTrailingSlashUrl:
12
+ # mypy casting
13
+ return cast(NoTrailingSlashUrl, value)
14
+
15
+
16
+ def test_trailing_slash_valid() -> None:
17
+ cls = TestClass(url=as_no_trailing_slash_url("http://example"))
18
+ assert cls.url == "http://example"
19
+
20
+
21
+ def test_trailing_slash_valid_remove_slash() -> None:
22
+ cls = TestClass(url=as_no_trailing_slash_url("http://example/"))
23
+ assert cls.url == "http://example"
24
+
25
+
26
+ def test_trailing_slash_not_valid() -> None:
27
+ with pytest.raises(ValueError):
28
+ TestClass(url=as_no_trailing_slash_url("/"))
29
+
30
+
31
+ def test_trailing_slash_not_valid_no_domain() -> None:
32
+ with pytest.raises(ValueError):
33
+ TestClass(url=as_no_trailing_slash_url("http:///"))
34
+
35
+
36
+ def test_trailing_empty() -> None:
37
+ cls = TestClass(url=None)
38
+ assert cls.url is None
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "port-ocean"
3
- version = "0.24.20"
3
+ version = "0.24.22"
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