port-ocean 0.27.1__py3-none-any.whl → 0.27.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -111,6 +111,8 @@ class IntegrationConfiguration(BaseOceanSettings, extra=Extra.allow):
111
111
  upsert_entities_batch_max_length: int = 20
112
112
  upsert_entities_batch_max_size_in_bytes: int = 1024 * 1024
113
113
  lakehouse_enabled: bool = False
114
+ yield_items_to_parse: bool = False
115
+ yield_items_to_parse_batch_size: int = 10
114
116
 
115
117
  @validator("process_execution_mode")
116
118
  def validate_process_execution_mode(
@@ -242,19 +242,21 @@ class JQEntityProcessor(BaseEntityProcessor):
242
242
  data: dict[str, Any],
243
243
  raw_entity_mappings: dict[str, Any],
244
244
  items_to_parse: str | None,
245
+ items_to_parse_name: str,
245
246
  selector_query: str,
246
247
  parse_all: bool = False,
247
248
  ) -> tuple[list[MappedEntity], list[Exception]]:
248
249
  raw_data = [data.copy()]
249
- if items_to_parse:
250
- items = await self._search(data, items_to_parse)
251
- if not isinstance(items, list):
252
- logger.warning(
253
- f"Failed to parse items for JQ expression {items_to_parse}, Expected list but got {type(items)}."
254
- f" Skipping..."
255
- )
256
- return [], []
257
- raw_data = [{"item": item, **data} for item in items]
250
+ if not ocean.config.yield_items_to_parse:
251
+ if items_to_parse:
252
+ items = await self._search(data, items_to_parse)
253
+ if not isinstance(items, list):
254
+ logger.warning(
255
+ f"Failed to parse items for JQ expression {items_to_parse}, Expected list but got {type(items)}."
256
+ f" Skipping..."
257
+ )
258
+ return [], []
259
+ raw_data = [{items_to_parse_name: item, **data} for item in items]
258
260
 
259
261
  entities, errors = await gather_and_split_errors_from_results(
260
262
  [
@@ -303,6 +305,7 @@ class JQEntityProcessor(BaseEntityProcessor):
303
305
  self._calculate_entity,
304
306
  raw_entity_mappings,
305
307
  mapping.port.items_to_parse,
308
+ mapping.port.items_to_parse_name,
306
309
  mapping.selector.query,
307
310
  parse_all,
308
311
  )
@@ -39,6 +39,7 @@ class MappingsConfig(BaseModel):
39
39
  class PortResourceConfig(BaseModel):
40
40
  entity: MappingsConfig
41
41
  items_to_parse: str | None = Field(alias="itemsToParse")
42
+ items_to_parse_name: str | None = Field(alias="itemsToParseName", default="item")
42
43
 
43
44
 
44
45
  class Selector(BaseModel):
@@ -116,7 +116,7 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
116
116
  logger.info(
117
117
  f"Found async generator function for {resource_config.kind} name: {task.__qualname__}"
118
118
  )
119
- results.append(resync_generator_wrapper(task, resource_config.kind))
119
+ results.append(resync_generator_wrapper(task, resource_config.kind,resource_config.port.items_to_parse))
120
120
  else:
121
121
  logger.info(
122
122
  f"Found sync function for {resource_config.kind} name: {task.__qualname__}"
@@ -1,11 +1,13 @@
1
1
  from contextlib import contextmanager
2
- from typing import Awaitable, Generator, Callable
2
+ from typing import Awaitable, Generator, Callable, cast
3
3
 
4
4
  from loguru import logger
5
5
 
6
6
  import asyncio
7
7
  import multiprocessing
8
8
 
9
+ from port_ocean.core.handlers.entity_processor.jq_entity_processor import JQEntityProcessor
10
+ from port_ocean.core.handlers.port_app_config.models import ResourceConfig
9
11
  from port_ocean.core.ocean_types import (
10
12
  ASYNC_GENERATOR_RESYNC_TYPE,
11
13
  RAW_RESULT,
@@ -49,7 +51,7 @@ async def resync_function_wrapper(
49
51
 
50
52
 
51
53
  async def resync_generator_wrapper(
52
- fn: Callable[[str], ASYNC_GENERATOR_RESYNC_TYPE], kind: str
54
+ fn: Callable[[str], ASYNC_GENERATOR_RESYNC_TYPE], kind: str, items_to_parse: str | None = None
53
55
  ) -> ASYNC_GENERATOR_RESYNC_TYPE:
54
56
  generator = fn(kind)
55
57
  errors = []
@@ -58,7 +60,28 @@ async def resync_generator_wrapper(
58
60
  try:
59
61
  with resync_error_handling():
60
62
  result = await anext(generator)
61
- yield validate_result(result)
63
+ if not ocean.config.yield_items_to_parse:
64
+ yield validate_result(result)
65
+ else:
66
+ batch_size = ocean.config.yield_items_to_parse_batch_size
67
+ if items_to_parse:
68
+ for data in result:
69
+ items = await cast(JQEntityProcessor, ocean.app.integration.entity_processor)._search(data, items_to_parse)
70
+ if not isinstance(items, list):
71
+ logger.warning(
72
+ f"Failed to parse items for JQ expression {items_to_parse}, Expected list but got {type(items)}."
73
+ f" Skipping..."
74
+ )
75
+ yield []
76
+ raw_data = [{"item": item, **data} for item in items]
77
+ while True:
78
+ raw_data_batch = raw_data[:batch_size]
79
+ yield raw_data_batch
80
+ raw_data = raw_data[batch_size:]
81
+ if len(raw_data) == 0:
82
+ break
83
+ else:
84
+ yield validate_result(result)
62
85
  except OceanAbortException as error:
63
86
  errors.append(error)
64
87
  ocean.metrics.inc_metric(
@@ -60,7 +60,7 @@ class TestJQEntityProcessor:
60
60
  raw_entity_mappings = {"foo": ".foo"}
61
61
  selector_query = '.foo == "bar"'
62
62
  result, errors = await mocked_processor._calculate_entity(
63
- data, raw_entity_mappings, None, selector_query
63
+ data, raw_entity_mappings, None, "item", selector_query
64
64
  )
65
65
  assert len(result) == 1
66
66
  assert result[0].entity == {"foo": "bar"}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: port-ocean
3
- Version: 0.27.1
3
+ Version: 0.27.3
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
@@ -70,7 +70,7 @@ port_ocean/clients/port/utils.py,sha256=osFyAjw7Y5Qf2uVSqC7_RTCQfijiL1zS74JJM0go
70
70
  port_ocean/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
71
  port_ocean/config/base.py,sha256=x1gFbzujrxn7EJudRT81C6eN9WsYAb3vOHwcpcpX8Tc,6370
72
72
  port_ocean/config/dynamic.py,sha256=Lrk4JRGtR-0YKQ9DDGexX5NGFE7EJ6VoHya19YYhssM,2687
73
- port_ocean/config/settings.py,sha256=keRT2FJyzQ2G0LNlNP4mqYSwwTjbybL7Ire0oggwScw,7226
73
+ port_ocean/config/settings.py,sha256=-jgVUBiFbeVjd9GjkMH6cRLLQHhtvI9x1WNdVE5s_p0,7311
74
74
  port_ocean/consumers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
75
  port_ocean/consumers/kafka_consumer.py,sha256=N8KocjBi9aR0BOPG8hgKovg-ns_ggpEjrSxqSqF_BSo,4710
76
76
  port_ocean/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -101,11 +101,11 @@ port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py,sha
101
101
  port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py,sha256=lyv6xKzhYfd6TioUgR3AVRSJqj7JpAaj1LxxU2xAqeo,1720
102
102
  port_ocean/core/handlers/entity_processor/__init__.py,sha256=FvFCunFg44wNQoqlybem9MthOs7p1Wawac87uSXz9U8,156
103
103
  port_ocean/core/handlers/entity_processor/base.py,sha256=PsnpNRqjHth9xwOvDRe7gKu8cjnVV0XGmTIHGvOelX0,1867
104
- port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=GxK5BM0yzAoeYTK2-ALKh5qlAe9pebcN7vZfQCZjksM,12787
104
+ port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=qvPMbIH1XRvaZ-TvW7lw9k4W27ZPCHcXGSdqnZ0wblw,12970
105
105
  port_ocean/core/handlers/port_app_config/__init__.py,sha256=8AAT5OthiVM7KCcM34iEgEeXtn2pRMrT4Dze5r1Ixbk,134
106
106
  port_ocean/core/handlers/port_app_config/api.py,sha256=r_Th66NEw38IpRdnXZcRvI8ACfvxW_A6V62WLwjWXlQ,1044
107
107
  port_ocean/core/handlers/port_app_config/base.py,sha256=Sup4-X_a7JGa27rMy_OgqGIjFHMlKBpKevicaK3AeHU,2919
108
- port_ocean/core/handlers/port_app_config/models.py,sha256=pO7oI7GIYZ9c2ZxLu8EQ97U2IPqzsbJf3gRQxlizEjE,2933
108
+ port_ocean/core/handlers/port_app_config/models.py,sha256=M9NJRRacvpZQYCFgHGlRwrdgumbIIJ82WpCyvtOUf5w,3019
109
109
  port_ocean/core/handlers/queue/__init__.py,sha256=yzgicE_jAR1wtljFKxgyG6j-HbLcG_Zze5qw1kkALUI,171
110
110
  port_ocean/core/handlers/queue/abstract_queue.py,sha256=SaivrYbqg8qsX6wtQlJZyxgcbdMD5B9NZG3byN9AvrI,782
111
111
  port_ocean/core/handlers/queue/group_queue.py,sha256=JvvJOwz9z_aI4CjPr7yQX-0rOgqLI5wMdxWk2x5x-34,4989
@@ -123,8 +123,8 @@ port_ocean/core/integrations/mixins/events.py,sha256=2L7P3Jhp8XBqddh2_o9Cn4N261n
123
123
  port_ocean/core/integrations/mixins/handler.py,sha256=mZ7-0UlG3LcrwJttFbMe-R4xcOU2H_g33tZar7PwTv8,3771
124
124
  port_ocean/core/integrations/mixins/live_events.py,sha256=zM24dhNc7uHx9XYZ6toVhDADPA90EnpOmZxgDegFZbA,4196
125
125
  port_ocean/core/integrations/mixins/sync.py,sha256=Vm_898pLKBwfVewtwouDWsXoxcOLicnAy6pzyqqk6U8,4053
126
- port_ocean/core/integrations/mixins/sync_raw.py,sha256=6AHuroSoqIKvdx2BAKtILxfQFeYB_wikYaM4JaTeoGw,39315
127
- port_ocean/core/integrations/mixins/utils.py,sha256=N76dNu1Y6UEg0_pcSdF4RO6dQIZ8EBfX3xMelgWdMxM,3779
126
+ port_ocean/core/integrations/mixins/sync_raw.py,sha256=OptSievJ1c9vw-0PKmYuT2GgbCH6HC04yEyi0MUQF9k,39351
127
+ port_ocean/core/integrations/mixins/utils.py,sha256=r7VKatZDip5D0hu-chCK3IeuM1gItleOEJboNN0Zvdk,5309
128
128
  port_ocean/core/models.py,sha256=DNbKpStMINI2lIekKprTqBevqkw_wFuFayN19w1aDfQ,2893
129
129
  port_ocean/core/ocean_types.py,sha256=bkLlTd8XfJK6_JDl0eXUHfE_NygqgiInSMwJ4YJH01Q,1399
130
130
  port_ocean/core/utils/entity_topological_sorter.py,sha256=MDUjM6OuDy4Xj68o-7InNN0w1jqjxeDfeY8U02vySNI,3081
@@ -168,7 +168,7 @@ port_ocean/tests/conftest.py,sha256=JXASSS0IY0nnR6bxBflhzxS25kf4iNaABmThyZ0mZt8,
168
168
  port_ocean/tests/core/conftest.py,sha256=5shShx81LRuQTBwS2sDIjNJO2LSD6cUNz46SgNYzjGY,7686
169
169
  port_ocean/tests/core/defaults/test_common.py,sha256=sR7RqB3ZYV6Xn6NIg-c8k5K6JcGsYZ2SCe_PYX5vLYM,5560
170
170
  port_ocean/tests/core/handlers/entities_state_applier/test_applier.py,sha256=7XWgwUB9uVYRov4VbIz1A-7n2YLbHTTYT-4rKJxjB0A,10711
171
- port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py,sha256=AyzLclJFKz8YzSi2hiFYVdXRzCFmqQwTxnwNFTo9roU,14091
171
+ port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py,sha256=TjSj8ssIqH23VJlO5PGovbudCqDbuE2-54iNQsD9K-I,14099
172
172
  port_ocean/tests/core/handlers/mixins/test_live_events.py,sha256=6yUsYooBYchiZP_eYa8PN1IhiztJShBdPguoseyNMzY,12482
173
173
  port_ocean/tests/core/handlers/mixins/test_sync_raw.py,sha256=-Jd2rUG63fZM8LuyKtCp1tt4WEqO2m5woESjs1c91sU,44428
174
174
  port_ocean/tests/core/handlers/port_app_config/test_api.py,sha256=eJZ6SuFBLz71y4ca3DNqKag6d6HUjNJS0aqQPwiLMTI,1999
@@ -205,8 +205,8 @@ port_ocean/utils/repeat.py,sha256=U2OeCkHPWXmRTVoPV-VcJRlQhcYqPWI5NfmPlb1JIbc,32
205
205
  port_ocean/utils/signal.py,sha256=mMVq-1Ab5YpNiqN4PkiyTGlV_G0wkUDMMjTZp5z3pb0,1514
206
206
  port_ocean/utils/time.py,sha256=pufAOH5ZQI7gXvOvJoQXZXZJV-Dqktoj9Qp9eiRwmJ4,1939
207
207
  port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
208
- port_ocean-0.27.1.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
209
- port_ocean-0.27.1.dist-info/METADATA,sha256=lMu1khMLwRsJuGctmRMHCZMr6fGDaXpSK53uQ0Iby1Y,6887
210
- port_ocean-0.27.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
211
- port_ocean-0.27.1.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
212
- port_ocean-0.27.1.dist-info/RECORD,,
208
+ port_ocean-0.27.3.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
209
+ port_ocean-0.27.3.dist-info/METADATA,sha256=8q1fasdb2UPwIRETpBdDwk5m9IEDUOrBEBl5fSruMZ8,6887
210
+ port_ocean-0.27.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
211
+ port_ocean-0.27.3.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
212
+ port_ocean-0.27.3.dist-info/RECORD,,