port-ocean 0.30.2__tar.gz → 0.30.4__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 (227) hide show
  1. {port_ocean-0.30.2 → port_ocean-0.30.4}/PKG-INFO +2 -1
  2. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/mixins/entities.py +35 -26
  3. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/helpers/async_client.py +29 -0
  4. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/helpers/stream.py +4 -1
  5. port_ocean-0.30.4/port_ocean/tests/clients/test_streaming_wrapper.py +85 -0
  6. {port_ocean-0.30.2 → port_ocean-0.30.4}/pyproject.toml +2 -1
  7. {port_ocean-0.30.2 → port_ocean-0.30.4}/LICENSE.md +0 -0
  8. {port_ocean-0.30.2 → port_ocean-0.30.4}/README.md +0 -0
  9. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/Dockerfile.Deb +0 -0
  10. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/Dockerfile.alpine +0 -0
  11. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/Dockerfile.base.builder +0 -0
  12. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/Dockerfile.base.runner +0 -0
  13. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/Dockerfile.dockerignore +0 -0
  14. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/Dockerfile.local +0 -0
  15. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/Makefile +0 -0
  16. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/README.md +0 -0
  17. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/entry_local.sh +0 -0
  18. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/grpcio.sh +0 -0
  19. {port_ocean-0.30.2 → port_ocean-0.30.4}/integrations/_infra/init.sh +0 -0
  20. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/__init__.py +0 -0
  21. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/bootstrap.py +0 -0
  22. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cache/__init__.py +0 -0
  23. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cache/base.py +0 -0
  24. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cache/disk.py +0 -0
  25. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cache/errors.py +0 -0
  26. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cache/memory.py +0 -0
  27. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/__init__.py +0 -0
  28. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cli.py +0 -0
  29. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/__init__.py +0 -0
  30. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/defaults/__init___.py +0 -0
  31. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/defaults/clean.py +0 -0
  32. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/defaults/dock.py +0 -0
  33. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/defaults/group.py +0 -0
  34. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/list_integrations.py +0 -0
  35. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/main.py +0 -0
  36. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/new.py +0 -0
  37. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/pull.py +0 -0
  38. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/sail.py +0 -0
  39. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/commands/version.py +0 -0
  40. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/__init__.py +0 -0
  41. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/cookiecutter.json +0 -0
  42. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/extensions.py +0 -0
  43. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +0 -0
  44. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.env.example +0 -0
  45. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
  46. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
  47. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/blueprints.json +0 -0
  48. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/port-app-config.yml +0 -0
  49. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
  50. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
  51. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CONTRIBUTING.md +0 -0
  52. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +0 -0
  53. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
  54. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
  55. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
  56. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
  57. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +0 -0
  58. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
  59. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py +0 -0
  60. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/test_sample.py +0 -0
  61. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/cli/utils.py +0 -0
  62. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/__init__.py +0 -0
  63. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/auth/__init__.py +0 -0
  64. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/auth/auth_client.py +0 -0
  65. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/auth/oauth_client.py +0 -0
  66. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/__init__.py +0 -0
  67. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/authentication.py +0 -0
  68. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/client.py +0 -0
  69. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/mixins/__init__.py +0 -0
  70. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/mixins/actions.py +0 -0
  71. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/mixins/blueprints.py +0 -0
  72. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/mixins/integrations.py +0 -0
  73. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/mixins/migrations.py +0 -0
  74. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/mixins/organization.py +0 -0
  75. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/retry_transport.py +0 -0
  76. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/types.py +0 -0
  77. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/clients/port/utils.py +0 -0
  78. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/config/__init__.py +0 -0
  79. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/config/base.py +0 -0
  80. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/config/dynamic.py +0 -0
  81. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/config/settings.py +0 -0
  82. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/consumers/__init__.py +0 -0
  83. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/consumers/kafka_consumer.py +0 -0
  84. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/context/__init__.py +0 -0
  85. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/context/event.py +0 -0
  86. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/context/metric_resource.py +0 -0
  87. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/context/ocean.py +0 -0
  88. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/context/resource.py +0 -0
  89. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/__init__.py +0 -0
  90. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/defaults/__init__.py +0 -0
  91. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/defaults/clean.py +0 -0
  92. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/defaults/common.py +0 -0
  93. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/defaults/initialize.py +0 -0
  94. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/__init__.py +0 -0
  95. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/actions_only.py +0 -0
  96. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/base.py +0 -0
  97. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/factory.py +0 -0
  98. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/http.py +0 -0
  99. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/kafka.py +0 -0
  100. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/once.py +0 -0
  101. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/polling.py +0 -0
  102. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/event_listener/webhooks_only.py +0 -0
  103. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/__init__.py +0 -0
  104. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/actions/__init__.py +0 -0
  105. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/actions/abstract_executor.py +0 -0
  106. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/actions/execution_manager.py +0 -0
  107. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/base.py +0 -0
  108. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
  109. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entities_state_applier/base.py +0 -0
  110. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entities_state_applier/port/__init__.py +0 -0
  111. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entities_state_applier/port/applier.py +0 -0
  112. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +0 -0
  113. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
  114. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
  115. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entity_processor/base.py +0 -0
  116. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +0 -0
  117. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/entity_processor/jq_input_evaluator.py +0 -0
  118. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
  119. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/port_app_config/api.py +0 -0
  120. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/port_app_config/base.py +0 -0
  121. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/port_app_config/models.py +0 -0
  122. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/queue/__init__.py +0 -0
  123. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/queue/abstract_queue.py +0 -0
  124. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/queue/group_queue.py +0 -0
  125. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/queue/local_queue.py +0 -0
  126. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/resync_state_updater/__init__.py +0 -0
  127. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/resync_state_updater/updater.py +0 -0
  128. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/webhook/__init__.py +0 -0
  129. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/webhook/abstract_webhook_processor.py +0 -0
  130. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/webhook/processor_manager.py +0 -0
  131. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/handlers/webhook/webhook_event.py +0 -0
  132. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/__init__.py +0 -0
  133. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/base.py +0 -0
  134. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/mixins/__init__.py +0 -0
  135. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/mixins/events.py +0 -0
  136. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/mixins/handler.py +0 -0
  137. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/mixins/live_events.py +0 -0
  138. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/mixins/sync.py +0 -0
  139. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/mixins/sync_raw.py +0 -0
  140. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/integrations/mixins/utils.py +0 -0
  141. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/models.py +0 -0
  142. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/ocean_types.py +0 -0
  143. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/utils/entity_topological_sorter.py +0 -0
  144. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/core/utils/utils.py +0 -0
  145. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/debug_cli.py +0 -0
  146. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/__init__.py +0 -0
  147. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/api.py +0 -0
  148. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/base.py +0 -0
  149. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/clients.py +0 -0
  150. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/context.py +0 -0
  151. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/core.py +0 -0
  152. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/execution_manager.py +0 -0
  153. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/port_defaults.py +0 -0
  154. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/utils.py +0 -0
  155. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/exceptions/webhook_processor.py +0 -0
  156. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/helpers/__init__.py +0 -0
  157. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/helpers/metric/metric.py +0 -0
  158. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/helpers/metric/utils.py +0 -0
  159. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/helpers/retry.py +0 -0
  160. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/log/__init__.py +0 -0
  161. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/log/handlers.py +0 -0
  162. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/log/logger_setup.py +0 -0
  163. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/log/sensetive.py +0 -0
  164. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/middlewares.py +0 -0
  165. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/ocean.py +0 -0
  166. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/py.typed +0 -0
  167. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/run.py +0 -0
  168. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/sonar-project.properties +0 -0
  169. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/__init__.py +0 -0
  170. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/cache/__init__.py +0 -0
  171. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/cache/test_disk_cache.py +0 -0
  172. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/cache/test_memory_cache.py +0 -0
  173. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/clients/__init__.py +0 -0
  174. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/clients/oauth/__init__.py +0 -0
  175. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/clients/oauth/test_oauth_client.py +0 -0
  176. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/clients/port/mixins/test_entities.py +0 -0
  177. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/clients/port/mixins/test_integrations.py +0 -0
  178. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/clients/port/mixins/test_organization_mixin.py +0 -0
  179. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/config/test_config.py +0 -0
  180. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/conftest.py +0 -0
  181. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/conftest.py +0 -0
  182. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/defaults/test_common.py +0 -0
  183. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/defaults/test_initialize.py +0 -0
  184. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/event_listener/test_kafka.py +0 -0
  185. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/actions/test_execution_manager.py +0 -0
  186. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/entities_state_applier/test_applier.py +0 -0
  187. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +0 -0
  188. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/entity_processor/test_jq_input_evaluator.py +0 -0
  189. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/mixins/test_live_events.py +0 -0
  190. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/mixins/test_sync_raw.py +0 -0
  191. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/port_app_config/test_api.py +0 -0
  192. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/port_app_config/test_base.py +0 -0
  193. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/queue/test_group_queue.py +0 -0
  194. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/queue/test_local_queue.py +0 -0
  195. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/webhook/test_abstract_webhook_processor.py +0 -0
  196. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/webhook/test_processor_manager.py +0 -0
  197. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/handlers/webhook/test_webhook_event.py +0 -0
  198. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/test_utils.py +0 -0
  199. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/utils/test_entity_topological_sorter.py +0 -0
  200. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/utils/test_get_port_diff.py +0 -0
  201. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/core/utils/test_resolve_entities_diff.py +0 -0
  202. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/helpers/__init__.py +0 -0
  203. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/helpers/fake_port_api.py +0 -0
  204. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/helpers/fixtures.py +0 -0
  205. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/helpers/integration.py +0 -0
  206. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/helpers/ocean_app.py +0 -0
  207. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/helpers/port_client.py +0 -0
  208. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/helpers/smoke_test.py +0 -0
  209. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/helpers/test_retry.py +0 -0
  210. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/log/test_handlers.py +0 -0
  211. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/test_metric.py +0 -0
  212. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/test_metrics_endpoints.py +0 -0
  213. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/test_ocean.py +0 -0
  214. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/test_smoke.py +0 -0
  215. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/utils/test_async_iterators.py +0 -0
  216. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/tests/utils/test_cache.py +0 -0
  217. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/__init__.py +0 -0
  218. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/async_http.py +0 -0
  219. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/async_iterators.py +0 -0
  220. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/cache.py +0 -0
  221. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/ipc.py +0 -0
  222. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/misc.py +0 -0
  223. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/queue_utils.py +0 -0
  224. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/repeat.py +0 -0
  225. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/signal.py +0 -0
  226. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/utils/time.py +0 -0
  227. {port_ocean-0.30.2 → port_ocean-0.30.4}/port_ocean/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.30.2
3
+ Version: 0.30.4
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
@@ -33,6 +33,7 @@ Requires-Dist: httpx (>=0.28.1,<0.29.0)
33
33
  Requires-Dist: ijson (>=3.4.0,<4.0.0)
34
34
  Requires-Dist: jinja2 (>=3.1.6)
35
35
  Requires-Dist: jinja2-time (>=0.2.0,<0.3.0) ; extra == "cli"
36
+ Requires-Dist: jmespath (>=1.0.1,<2.0.0)
36
37
  Requires-Dist: jq (>=1.8.0,<2.0.0)
37
38
  Requires-Dist: loguru (>=0.7.0,<0.8.0)
38
39
  Requires-Dist: prometheus-client (>=0.21.1,<0.22.0)
@@ -262,34 +262,36 @@ class EntityClientMixin:
262
262
  }
263
263
  error_entities = {error["index"]: error for error in result.get("errors", [])}
264
264
 
265
+ ocean.metrics.inc_metric(
266
+ name=MetricType.OBJECT_COUNT_NAME,
267
+ labels=[
268
+ ocean.metrics.current_resource_kind(),
269
+ MetricPhase.LOAD,
270
+ MetricPhase.LoadResult.LOADED,
271
+ ],
272
+ value=len(successful_entities),
273
+ )
274
+
275
+ ocean.metrics.inc_metric(
276
+ name=MetricType.OBJECT_COUNT_NAME,
277
+ labels=[
278
+ ocean.metrics.current_resource_kind(),
279
+ MetricPhase.LOAD,
280
+ MetricPhase.LoadResult.FAILED,
281
+ ],
282
+ value=len(error_entities),
283
+ )
284
+
265
285
  batch_results: list[tuple[bool | None, Entity]] = []
266
286
  for entity_index, original_entity in index_to_entity.items():
267
287
  reduced_entity = self._reduce_entity(original_entity)
268
288
  if entity_index in successful_entities:
269
- ocean.metrics.inc_metric(
270
- name=MetricType.OBJECT_COUNT_NAME,
271
- labels=[
272
- ocean.metrics.current_resource_kind(),
273
- MetricPhase.LOAD,
274
- MetricPhase.LoadResult.LOADED,
275
- ],
276
- value=1,
277
- )
278
289
  success_entity = successful_entities[entity_index]
279
290
  # Create a copy of the original entity with the new identifier
280
291
  updated_entity = reduced_entity.copy()
281
292
  updated_entity.identifier = success_entity["identifier"]
282
293
  batch_results.append((True, updated_entity))
283
294
  elif entity_index in error_entities:
284
- ocean.metrics.inc_metric(
285
- name=MetricType.OBJECT_COUNT_NAME,
286
- labels=[
287
- ocean.metrics.current_resource_kind(),
288
- MetricPhase.LOAD,
289
- MetricPhase.LoadResult.FAILED,
290
- ],
291
- value=1,
292
- )
293
295
  error = error_entities[entity_index]
294
296
  if (
295
297
  error.get("identifier") == "unknown"
@@ -357,16 +359,23 @@ class EntityClientMixin:
357
359
  blueprint = entities[0].blueprint
358
360
 
359
361
  identifier_counts = Counter((e.blueprint, e.identifier) for e in entities)
360
- duplicate_count = sum(
361
- count - 1 for count in identifier_counts.values() if count > 1
362
- )
362
+ duplicates: dict[tuple[str, str], int] = {
363
+ key: cnt for key, cnt in identifier_counts.items() if cnt > 1
364
+ }
365
+
366
+ if duplicates:
367
+ # Total number of *extra* occurrences beyond the first appearance of each entity
368
+ duplicate_count = sum(cnt - 1 for cnt in duplicates.values())
369
+
370
+ # Show up to 5 example (blueprint, identifier) pairs to avoid noisy logs
371
+ duplicate_examples = list(duplicates)[:5]
363
372
 
364
- if duplicate_count:
365
- duplicate_examples = [
366
- key for key, cnt in identifier_counts.items() if cnt > 1
367
- ][:5]
368
373
  logger.warning(
369
- f"Detected {duplicate_count} duplicate entities (by blueprint and identifier) that may not be ingested because an identical identifier existed. Examples: {duplicate_examples}"
374
+ "Detected duplicate entities (by blueprint and identifier) that may not be ingested because an identical identifier existed",
375
+ extra={
376
+ "duplicate_examples": duplicate_examples,
377
+ "duplicate_count": duplicate_count,
378
+ },
370
379
  )
371
380
 
372
381
  bulk_size = self.calculate_entities_batch_size(entities)
@@ -5,6 +5,7 @@ from loguru import logger
5
5
 
6
6
  from port_ocean.helpers.retry import RetryTransport, RetryConfig
7
7
  from port_ocean.helpers.stream import Stream
8
+ from typing import AsyncGenerator, List, Dict
8
9
 
9
10
 
10
11
  class OceanAsyncClient(httpx.AsyncClient):
@@ -56,3 +57,31 @@ class OceanAsyncClient(httpx.AsyncClient):
56
57
  response = await self.send(req, stream=True)
57
58
  response.raise_for_status()
58
59
  return Stream(response)
60
+
61
+
62
+ class StreamingClientWrapper:
63
+ def __init__(self, http_client: OceanAsyncClient):
64
+ self._client = http_client
65
+
66
+ async def stream_json(
67
+ self,
68
+ url: str,
69
+ target_items_path: str,
70
+ **kwargs: Any,
71
+ ) -> AsyncGenerator[List[Dict[str, Any]], None]:
72
+ """
73
+ A wrapper that provides a unified async generator interface for both streaming
74
+ and non-streaming HTTP GET requests.
75
+
76
+ :param url: The URL to request.
77
+ :param target_items_path: A JMESPath string to extract the list of items
78
+ from the JSON response (e.g., 'results'). The wrapper
79
+ will automatically adapt this for the streaming parser.
80
+ :param kwargs: Additional arguments for the HTTP request.
81
+ """
82
+ # ijson needs a path to the items inside the array, e.g., "results.item"
83
+ streaming_path = f"{target_items_path}.item"
84
+ stream_response = await self._client.get_stream(url, **kwargs)
85
+ json_stream = stream_response.get_json_stream(target_items=streaming_path)
86
+ async for items_batch in json_stream:
87
+ yield items_batch
@@ -22,7 +22,10 @@ class Stream:
22
22
  if chunk_size is None:
23
23
  chunk_size = ocean_context.ocean.config.streaming.chunk_size
24
24
 
25
- file_name = f"{ocean_context.ocean.config.streaming.location}/{uuid.uuid4()}"
25
+ streaming_location = ocean_context.ocean.config.streaming.location
26
+ os.makedirs(streaming_location, exist_ok=True)
27
+
28
+ file_name = f"{streaming_location}/{uuid.uuid4()}"
26
29
 
27
30
  crypt = Fernet(Fernet.generate_key())
28
31
 
@@ -0,0 +1,85 @@
1
+ import pytest
2
+ from unittest.mock import AsyncMock
3
+ from typing import Any, AsyncGenerator
4
+
5
+
6
+ from port_ocean.helpers.async_client import OceanAsyncClient, StreamingClientWrapper
7
+ from port_ocean.helpers.stream import Stream
8
+
9
+
10
+ class MockStream:
11
+ """A mock of the port_ocean.helpers.stream.Stream class for testing."""
12
+
13
+ def __init__(self, data_chunks: list[list[dict[str, Any]]]) -> None:
14
+ self._data_chunks = data_chunks
15
+
16
+ async def get_json_stream(self, target_items: str) -> AsyncGenerator[Any, None]:
17
+ """An async generator that yields the data chunks."""
18
+ for chunk in self._data_chunks:
19
+ yield chunk
20
+
21
+
22
+ @pytest.mark.asyncio
23
+ async def test_stream_json_with_streaming_enabled() -> None:
24
+ """
25
+ Tests that when streaming is enabled, the wrapper uses the `get_stream` method
26
+ and yields data in batches.
27
+ """
28
+ # Arrange
29
+ mock_client = AsyncMock(spec=OceanAsyncClient)
30
+ # Simulate receiving the data in two separate chunks/batches
31
+ mock_stream_instance = MockStream(
32
+ [[{"id": 1, "name": "one"}], [{"id": 2, "name": "two"}]]
33
+ )
34
+ mock_client.get_stream.return_value = mock_stream_instance
35
+
36
+ wrapper = StreamingClientWrapper(http_client=mock_client)
37
+
38
+ # Act
39
+ results = [item async for item in wrapper.stream_json("http://test.com", "results")]
40
+
41
+ # Assert
42
+ mock_client.get_stream.assert_called_once_with("http://test.com")
43
+ mock_client.get.assert_not_called()
44
+ assert results == [[{"id": 1, "name": "one"}], [{"id": 2, "name": "two"}]]
45
+
46
+
47
+ @pytest.mark.asyncio
48
+ async def test_stream_json_with_empty_results_streaming() -> None:
49
+ """
50
+ Tests that the wrapper handles an empty stream correctly in streaming mode.
51
+ """
52
+ # Arrange
53
+ mock_client = AsyncMock(spec=OceanAsyncClient)
54
+ mock_stream_instance = MockStream([[]]) # Stream yields one empty batch
55
+ mock_client.get_stream.return_value = mock_stream_instance
56
+
57
+ wrapper = StreamingClientWrapper(http_client=mock_client)
58
+
59
+ # Act
60
+ results = [item async for item in wrapper.stream_json("http://test.com", "results")]
61
+
62
+ # Assert
63
+ assert results == [[]]
64
+
65
+
66
+ @pytest.mark.asyncio
67
+ async def test_stream_json_path_adaptation_for_streaming() -> None:
68
+ """
69
+ Tests that the wrapper correctly adapts the `target_items_path` for the
70
+ streaming parser (ijson) by appending `.item`.
71
+ """
72
+ # Arrange
73
+ mock_client = AsyncMock(spec=OceanAsyncClient)
74
+ mock_stream = AsyncMock(spec=Stream)
75
+ mock_client.get_stream.return_value = mock_stream
76
+
77
+ wrapper = StreamingClientWrapper(http_client=mock_client)
78
+
79
+ # Act
80
+ # We only need to trigger the call to check the arguments
81
+ _ = [item async for item in wrapper.stream_json("http://test.com", "results")]
82
+
83
+ # Assert
84
+ # Verify that get_json_stream was called with the modified path
85
+ mock_stream.get_json_stream.assert_called_once_with(target_items="results.item")
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "port-ocean"
3
- version = "0.30.2"
3
+ version = "0.30.4"
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"
@@ -69,6 +69,7 @@ pytest-cov = "^6.0.0"
69
69
  ijson = "^3.4.0"
70
70
  aiofiles = "^24.1.0"
71
71
  cryptography = "^44.0.1"
72
+ jmespath = "^1.0.1"
72
73
 
73
74
  [tool.poetry.extras]
74
75
  cli = ["click", "rich", "cookiecutter", "jinja2-time"]
File without changes
File without changes