port-ocean 0.16.0__py3-none-any.whl → 0.17.0__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.
Potentially problematic release.
This version of port-ocean might be problematic. Click here for more details.
- port_ocean/context/ocean.py +12 -3
- port_ocean/core/event_listener/__init__.py +8 -0
- port_ocean/core/event_listener/base.py +1 -0
- port_ocean/core/event_listener/factory.py +9 -1
- port_ocean/core/event_listener/webhooks_only.py +41 -0
- port_ocean/core/handlers/entity_processor/jq_entity_processor.py +47 -7
- port_ocean/core/integrations/base.py +5 -1
- port_ocean/core/integrations/mixins/sync_raw.py +2 -2
- port_ocean/core/ocean_types.py +11 -2
- port_ocean/run.py +0 -1
- port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +34 -0
- {port_ocean-0.16.0.dist-info → port_ocean-0.17.0.dist-info}/METADATA +1 -1
- {port_ocean-0.16.0.dist-info → port_ocean-0.17.0.dist-info}/RECORD +16 -15
- {port_ocean-0.16.0.dist-info → port_ocean-0.17.0.dist-info}/LICENSE.md +0 -0
- {port_ocean-0.16.0.dist-info → port_ocean-0.17.0.dist-info}/WHEEL +0 -0
- {port_ocean-0.16.0.dist-info → port_ocean-0.17.0.dist-info}/entry_points.txt +0 -0
port_ocean/context/ocean.py
CHANGED
|
@@ -23,6 +23,8 @@ if TYPE_CHECKING:
|
|
|
23
23
|
from port_ocean.ocean import Ocean
|
|
24
24
|
from port_ocean.clients.port.client import PortClient
|
|
25
25
|
|
|
26
|
+
from loguru import logger
|
|
27
|
+
|
|
26
28
|
|
|
27
29
|
class PortOceanContext:
|
|
28
30
|
def __init__(self, app: Union["Ocean", None]) -> None:
|
|
@@ -63,14 +65,21 @@ class PortOceanContext:
|
|
|
63
65
|
return self.app.port_client
|
|
64
66
|
|
|
65
67
|
@property
|
|
66
|
-
def event_listener_type(
|
|
68
|
+
def event_listener_type(
|
|
69
|
+
self,
|
|
70
|
+
) -> Literal["WEBHOOK", "KAFKA", "POLLING", "ONCE", "WEBHOOKS_ONLY"]:
|
|
67
71
|
return self.app.config.event_listener.type
|
|
68
72
|
|
|
69
73
|
def on_resync(
|
|
70
74
|
self,
|
|
71
75
|
kind: str | None = None,
|
|
72
|
-
) -> Callable[[RESYNC_EVENT_LISTENER], RESYNC_EVENT_LISTENER]:
|
|
73
|
-
def wrapper(function: RESYNC_EVENT_LISTENER) -> RESYNC_EVENT_LISTENER:
|
|
76
|
+
) -> Callable[[RESYNC_EVENT_LISTENER], RESYNC_EVENT_LISTENER | None]:
|
|
77
|
+
def wrapper(function: RESYNC_EVENT_LISTENER) -> RESYNC_EVENT_LISTENER | None:
|
|
78
|
+
if not self.app.config.event_listener.should_resync:
|
|
79
|
+
logger.debug(
|
|
80
|
+
"Webhook only event listener is used, resync events are ignored"
|
|
81
|
+
)
|
|
82
|
+
return None
|
|
74
83
|
return self.integration.on_resync(function, kind)
|
|
75
84
|
|
|
76
85
|
return wrapper
|
|
@@ -16,12 +16,18 @@ from port_ocean.core.event_listener.once import (
|
|
|
16
16
|
OnceEventListener,
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
+
from port_ocean.core.event_listener.webhooks_only import (
|
|
20
|
+
WebhooksOnlyEventListener,
|
|
21
|
+
WebhooksOnlyEventListenerSettings,
|
|
22
|
+
)
|
|
23
|
+
|
|
19
24
|
|
|
20
25
|
EventListenerSettingsType = (
|
|
21
26
|
HttpEventListenerSettings
|
|
22
27
|
| KafkaEventListenerSettings
|
|
23
28
|
| PollingEventListenerSettings
|
|
24
29
|
| OnceEventListenerSettings
|
|
30
|
+
| WebhooksOnlyEventListenerSettings
|
|
25
31
|
)
|
|
26
32
|
|
|
27
33
|
__all__ = [
|
|
@@ -34,4 +40,6 @@ __all__ = [
|
|
|
34
40
|
"PollingEventListenerSettings",
|
|
35
41
|
"OnceEventListener",
|
|
36
42
|
"OnceEventListenerSettings",
|
|
43
|
+
"WebhooksOnlyEventListener",
|
|
44
|
+
"WebhooksOnlyEventListenerSettings",
|
|
37
45
|
]
|
|
@@ -17,6 +17,10 @@ from port_ocean.core.event_listener.base import (
|
|
|
17
17
|
BaseEventListener,
|
|
18
18
|
EventListenerEvents,
|
|
19
19
|
)
|
|
20
|
+
from port_ocean.core.event_listener.webhooks_only import (
|
|
21
|
+
WebhooksOnlyEventListener,
|
|
22
|
+
WebhooksOnlyEventListenerSettings,
|
|
23
|
+
)
|
|
20
24
|
from port_ocean.exceptions.core import UnsupportedEventListenerTypeException
|
|
21
25
|
|
|
22
26
|
|
|
@@ -88,7 +92,11 @@ class EventListenerFactory:
|
|
|
88
92
|
config, OnceEventListenerSettings
|
|
89
93
|
), assert_message.format(type(config))
|
|
90
94
|
event_listener = OnceEventListener(wrapped_events, config)
|
|
91
|
-
|
|
95
|
+
case "webhooks_only":
|
|
96
|
+
assert isinstance(
|
|
97
|
+
config, WebhooksOnlyEventListenerSettings
|
|
98
|
+
), assert_message.format(type(config))
|
|
99
|
+
event_listener = WebhooksOnlyEventListener(wrapped_events, config)
|
|
92
100
|
case _:
|
|
93
101
|
raise UnsupportedEventListenerTypeException(
|
|
94
102
|
f"Event listener {_type} not supported"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
|
|
3
|
+
from loguru import logger
|
|
4
|
+
|
|
5
|
+
from port_ocean.core.event_listener.base import (
|
|
6
|
+
BaseEventListener,
|
|
7
|
+
EventListenerEvents,
|
|
8
|
+
EventListenerSettings,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WebhooksOnlyEventListenerSettings(EventListenerSettings):
|
|
13
|
+
"""
|
|
14
|
+
This class inherits from `EventListenerSettings`, which provides a foundation for creating event listener settings.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
type: Literal["WEBHOOKS_ONLY"]
|
|
18
|
+
should_resync: bool = False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class WebhooksOnlyEventListener(BaseEventListener):
|
|
22
|
+
"""
|
|
23
|
+
No resync event listener.
|
|
24
|
+
|
|
25
|
+
It is used to handle events exclusively through webhooks without supporting resync events.
|
|
26
|
+
|
|
27
|
+
Parameters:
|
|
28
|
+
events (EventListenerEvents): A dictionary containing event types and their corresponding event handlers.
|
|
29
|
+
event_listener_config (OnceEventListenerSettings): The event listener configuration settings.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
events: EventListenerEvents,
|
|
35
|
+
event_listener_config: WebhooksOnlyEventListenerSettings,
|
|
36
|
+
):
|
|
37
|
+
super().__init__(events)
|
|
38
|
+
self.event_listener_config = event_listener_config
|
|
39
|
+
|
|
40
|
+
async def _start(self) -> None:
|
|
41
|
+
logger.info("Starting Webhooks-only event listener")
|
|
@@ -34,6 +34,7 @@ class MappedEntity:
|
|
|
34
34
|
entity: dict[str, Any] = field(default_factory=dict)
|
|
35
35
|
did_entity_pass_selector: bool = False
|
|
36
36
|
raw_data: Optional[dict[str, Any]] = None
|
|
37
|
+
misconfigurations: dict[str, str] = field(default_factory=dict)
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
class JQEntityProcessor(BaseEntityProcessor):
|
|
@@ -95,21 +96,37 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
95
96
|
)
|
|
96
97
|
|
|
97
98
|
async def _search_as_object(
|
|
98
|
-
self,
|
|
99
|
+
self,
|
|
100
|
+
data: dict[str, Any],
|
|
101
|
+
obj: dict[str, Any],
|
|
102
|
+
misconfigurations: dict[str, str] | None = None,
|
|
99
103
|
) -> dict[str, Any | None]:
|
|
104
|
+
"""
|
|
105
|
+
Identify and extract the relevant value for the chosen key and populate it into the entity
|
|
106
|
+
:param data: the property itself that holds the key and the value, it is being passed to the task and we get back a task item,
|
|
107
|
+
if the data is a dict, we will recursively call this function again.
|
|
108
|
+
:param obj: the key that we want its value to be mapped into our entity.
|
|
109
|
+
:param misconfigurations: due to the recursive nature of this function,
|
|
110
|
+
we aim to have a dict that represents all of the misconfigured properties and when used recursively,
|
|
111
|
+
we pass this reference to misfoncigured object to add the relevant misconfigured keys.
|
|
112
|
+
:return: Mapped object with found value.
|
|
113
|
+
"""
|
|
114
|
+
|
|
100
115
|
search_tasks: dict[
|
|
101
116
|
str, Task[dict[str, Any | None]] | list[Task[dict[str, Any | None]]]
|
|
102
117
|
] = {}
|
|
103
118
|
for key, value in obj.items():
|
|
104
119
|
if isinstance(value, list):
|
|
105
120
|
search_tasks[key] = [
|
|
106
|
-
asyncio.create_task(
|
|
121
|
+
asyncio.create_task(
|
|
122
|
+
self._search_as_object(data, obj, misconfigurations)
|
|
123
|
+
)
|
|
107
124
|
for obj in value
|
|
108
125
|
]
|
|
109
126
|
|
|
110
127
|
elif isinstance(value, dict):
|
|
111
128
|
search_tasks[key] = asyncio.create_task(
|
|
112
|
-
self._search_as_object(data, value)
|
|
129
|
+
self._search_as_object(data, value, misconfigurations)
|
|
113
130
|
)
|
|
114
131
|
else:
|
|
115
132
|
search_tasks[key] = asyncio.create_task(self._search(data, value))
|
|
@@ -118,12 +135,20 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
118
135
|
for key, task in search_tasks.items():
|
|
119
136
|
try:
|
|
120
137
|
if isinstance(task, list):
|
|
121
|
-
|
|
138
|
+
result_list = []
|
|
139
|
+
for task in task:
|
|
140
|
+
task_result = await task
|
|
141
|
+
if task_result is None and misconfigurations is not None:
|
|
142
|
+
misconfigurations[key] = obj[key]
|
|
143
|
+
result_list.append(task_result)
|
|
144
|
+
result[key] = result_list
|
|
122
145
|
else:
|
|
123
|
-
|
|
146
|
+
task_result = await task
|
|
147
|
+
if task_result is None and misconfigurations is not None:
|
|
148
|
+
misconfigurations[key] = obj[key]
|
|
149
|
+
result[key] = task_result
|
|
124
150
|
except Exception:
|
|
125
151
|
result[key] = None
|
|
126
|
-
|
|
127
152
|
return result
|
|
128
153
|
|
|
129
154
|
async def _get_mapped_entity(
|
|
@@ -135,11 +160,15 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
135
160
|
) -> MappedEntity:
|
|
136
161
|
should_run = await self._search_as_bool(data, selector_query)
|
|
137
162
|
if parse_all or should_run:
|
|
138
|
-
|
|
163
|
+
misconfigurations: dict[str, str] = {}
|
|
164
|
+
mapped_entity = await self._search_as_object(
|
|
165
|
+
data, raw_entity_mappings, misconfigurations
|
|
166
|
+
)
|
|
139
167
|
return MappedEntity(
|
|
140
168
|
mapped_entity,
|
|
141
169
|
did_entity_pass_selector=should_run,
|
|
142
170
|
raw_data=data if should_run else None,
|
|
171
|
+
misconfigurations=misconfigurations,
|
|
143
172
|
)
|
|
144
173
|
|
|
145
174
|
return MappedEntity()
|
|
@@ -221,7 +250,11 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
221
250
|
passed_entities = []
|
|
222
251
|
failed_entities = []
|
|
223
252
|
examples_to_send: list[dict[str, Any]] = []
|
|
253
|
+
entity_misconfigurations: dict[str, str] = {}
|
|
254
|
+
missing_required_fields: bool = False
|
|
224
255
|
for result in calculated_entities_results:
|
|
256
|
+
if len(result.misconfigurations) > 0:
|
|
257
|
+
entity_misconfigurations |= result.misconfigurations
|
|
225
258
|
if result.entity.get("identifier") and result.entity.get("blueprint"):
|
|
226
259
|
parsed_entity = Entity.parse_obj(result.entity)
|
|
227
260
|
if result.did_entity_pass_selector:
|
|
@@ -233,6 +266,12 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
233
266
|
examples_to_send.append(result.raw_data)
|
|
234
267
|
else:
|
|
235
268
|
failed_entities.append(parsed_entity)
|
|
269
|
+
else:
|
|
270
|
+
missing_required_fields = True
|
|
271
|
+
if len(entity_misconfigurations) > 0:
|
|
272
|
+
logger.info(
|
|
273
|
+
f"The mapping resulted with invalid values for{" identifier, blueprint," if missing_required_fields else " "} properties. Mapping result: {entity_misconfigurations}"
|
|
274
|
+
)
|
|
236
275
|
if (
|
|
237
276
|
not calculated_entities_results
|
|
238
277
|
and raw_results
|
|
@@ -248,4 +287,5 @@ class JQEntityProcessor(BaseEntityProcessor):
|
|
|
248
287
|
return CalculationResult(
|
|
249
288
|
EntitySelectorDiff(passed=passed_entities, failed=failed_entities),
|
|
250
289
|
errors,
|
|
290
|
+
misonfigured_entity_keys=entity_misconfigurations,
|
|
251
291
|
)
|
|
@@ -54,13 +54,17 @@ class BaseIntegration(SyncRawMixin, SyncMixin):
|
|
|
54
54
|
"""
|
|
55
55
|
Initializes handlers, establishes integration at the specified port, and starts the event listener.
|
|
56
56
|
"""
|
|
57
|
-
logger.info(
|
|
57
|
+
logger.info(
|
|
58
|
+
"Starting integration",
|
|
59
|
+
integration_type=self.context.config.integration.type,
|
|
60
|
+
)
|
|
58
61
|
if self.started:
|
|
59
62
|
raise IntegrationAlreadyStartedException("Integration already started")
|
|
60
63
|
|
|
61
64
|
if (
|
|
62
65
|
not self.event_strategy["resync"]
|
|
63
66
|
and self.__class__._on_resync == BaseIntegration._on_resync
|
|
67
|
+
and self.context.config.event_listener.should_resync
|
|
64
68
|
):
|
|
65
69
|
raise NotImplementedError("on_resync is not implemented")
|
|
66
70
|
|
|
@@ -185,7 +185,7 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
185
185
|
send_raw_data_examples_amount = (
|
|
186
186
|
SEND_RAW_DATA_EXAMPLES_AMOUNT if ocean.config.send_raw_data_examples else 0
|
|
187
187
|
)
|
|
188
|
-
all_entities, register_errors = await self._register_resource_raw(
|
|
188
|
+
all_entities, register_errors,_ = await self._register_resource_raw(
|
|
189
189
|
resource_config,
|
|
190
190
|
raw_results,
|
|
191
191
|
user_agent_type,
|
|
@@ -202,7 +202,7 @@ class SyncRawMixin(HandlerMixin, EventsMixin):
|
|
|
202
202
|
0, send_raw_data_examples_amount - len(passed_entities)
|
|
203
203
|
)
|
|
204
204
|
|
|
205
|
-
entities, register_errors = await self._register_resource_raw(
|
|
205
|
+
entities, register_errors,_ = await self._register_resource_raw(
|
|
206
206
|
resource_config,
|
|
207
207
|
items,
|
|
208
208
|
user_agent_type,
|
port_ocean/core/ocean_types.py
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
|
|
1
|
+
from typing import (
|
|
2
|
+
TypedDict,
|
|
3
|
+
Any,
|
|
4
|
+
AsyncIterator,
|
|
5
|
+
Callable,
|
|
6
|
+
Awaitable,
|
|
7
|
+
NamedTuple,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from dataclasses import field
|
|
3
11
|
from port_ocean.core.models import Entity
|
|
4
12
|
|
|
5
13
|
RAW_ITEM = dict[Any, Any]
|
|
@@ -30,6 +38,7 @@ class EntitySelectorDiff(NamedTuple):
|
|
|
30
38
|
class CalculationResult(NamedTuple):
|
|
31
39
|
entity_selector_diff: EntitySelectorDiff
|
|
32
40
|
errors: list[Exception]
|
|
41
|
+
misonfigured_entity_keys: dict[str, str] = field(default_factory=dict)
|
|
33
42
|
|
|
34
43
|
|
|
35
44
|
class IntegrationEventsCallbacks(TypedDict):
|
port_ocean/run.py
CHANGED
|
@@ -57,7 +57,6 @@ def run(
|
|
|
57
57
|
# Override config with arguments
|
|
58
58
|
if initialize_port_resources is not None:
|
|
59
59
|
app.config.initialize_port_resources = initialize_port_resources
|
|
60
|
-
|
|
61
60
|
initialize_defaults(app.integration.AppConfigHandlerClass.CONFIG_CLASS, app.config)
|
|
62
61
|
|
|
63
62
|
uvicorn.run(app, host="0.0.0.0", port=application_settings.port)
|
|
@@ -269,3 +269,37 @@ class TestJQEntityProcessor:
|
|
|
269
269
|
assert len(result.entity_selector_diff.passed) == 1
|
|
270
270
|
assert result.entity_selector_diff.passed[0].properties.get("foo") == "bar"
|
|
271
271
|
assert not result.errors
|
|
272
|
+
|
|
273
|
+
async def test_parse_items_wrong_mapping(
|
|
274
|
+
self, mocked_processor: JQEntityProcessor
|
|
275
|
+
) -> None:
|
|
276
|
+
mapping = Mock()
|
|
277
|
+
mapping.port.entity.mappings.dict.return_value = {
|
|
278
|
+
"title": ".foo",
|
|
279
|
+
"identifier": ".ark",
|
|
280
|
+
"blueprint": ".baz",
|
|
281
|
+
"properties": {
|
|
282
|
+
"description": ".bazbar",
|
|
283
|
+
"url": ".foobar",
|
|
284
|
+
"defaultBranch": ".bar.baz",
|
|
285
|
+
},
|
|
286
|
+
}
|
|
287
|
+
mapping.port.items_to_parse = None
|
|
288
|
+
mapping.selector.query = "true"
|
|
289
|
+
raw_results = [
|
|
290
|
+
{
|
|
291
|
+
"foo": "bar",
|
|
292
|
+
"baz": "bazbar",
|
|
293
|
+
"bar": {"foobar": "barfoo", "baz": "barbaz"},
|
|
294
|
+
},
|
|
295
|
+
{"foo": "bar", "baz": "bazbar", "bar": {"foobar": "foobar"}},
|
|
296
|
+
]
|
|
297
|
+
result = await mocked_processor._parse_items(mapping, raw_results)
|
|
298
|
+
assert len(result.misonfigured_entity_keys) > 0
|
|
299
|
+
assert len(result.misonfigured_entity_keys) == 4
|
|
300
|
+
assert result.misonfigured_entity_keys == {
|
|
301
|
+
"identifier": ".ark",
|
|
302
|
+
"description": ".bazbar",
|
|
303
|
+
"url": ".foobar",
|
|
304
|
+
"defaultBranch": ".bar.baz",
|
|
305
|
+
}
|
|
@@ -63,20 +63,21 @@ port_ocean/consumers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
|
|
|
63
63
|
port_ocean/consumers/kafka_consumer.py,sha256=N8KocjBi9aR0BOPG8hgKovg-ns_ggpEjrSxqSqF_BSo,4710
|
|
64
64
|
port_ocean/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
65
65
|
port_ocean/context/event.py,sha256=tf254jMqBW1GBmYDhfXMCkOqHA7C_chaYp1OY3Dfnsg,5869
|
|
66
|
-
port_ocean/context/ocean.py,sha256=
|
|
66
|
+
port_ocean/context/ocean.py,sha256=xXVcvfC_mwC74u_NC6F8jk3UwBvw4xJYw3WJnabrcXg,4956
|
|
67
67
|
port_ocean/context/resource.py,sha256=yDj63URzQelj8zJPh4BAzTtPhpKr9Gw9DRn7I_0mJ1s,1692
|
|
68
68
|
port_ocean/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
69
|
port_ocean/core/defaults/__init__.py,sha256=8qCZg8n06WAdMu9s_FiRtDYLGPGHbOuS60vapeUoAks,142
|
|
70
70
|
port_ocean/core/defaults/clean.py,sha256=TOVe5b5FAjFspAkQuKA70k2BClCEFbrQ3xgiAoKXKYE,2427
|
|
71
71
|
port_ocean/core/defaults/common.py,sha256=zJsj7jvlqIMLGXhdASUlbKS8GIAf-FDKKB0O7jB6nx0,4166
|
|
72
72
|
port_ocean/core/defaults/initialize.py,sha256=eX5AMo3fug202lHvnwwGAuYlVbh3yDvUQaimTzre1do,8477
|
|
73
|
-
port_ocean/core/event_listener/__init__.py,sha256=
|
|
74
|
-
port_ocean/core/event_listener/base.py,sha256=
|
|
75
|
-
port_ocean/core/event_listener/factory.py,sha256=
|
|
73
|
+
port_ocean/core/event_listener/__init__.py,sha256=T3E52MKs79fNEW381p7zU9F2vOMvIiiTYWlqRUqnsg0,1135
|
|
74
|
+
port_ocean/core/event_listener/base.py,sha256=dZjz4y8PtiTJAU2fNbvUO7ibHY8mVIgwLUKC9_ydUJ4,2387
|
|
75
|
+
port_ocean/core/event_listener/factory.py,sha256=M4Qi05pI840sjDIbdjUEgYe9Gp5ckoCkX-KgLBxUpZg,4096
|
|
76
76
|
port_ocean/core/event_listener/http.py,sha256=N8HrfFqR3KGKz96pWdp_pP-m30jGtcz_1CkijovkBN8,2565
|
|
77
77
|
port_ocean/core/event_listener/kafka.py,sha256=ulidnp4sz-chXwHsbH9JayVjcxy_mG6ts_Im3YKmLpI,6983
|
|
78
78
|
port_ocean/core/event_listener/once.py,sha256=iL3NkujZOw-7LpxT-EAUJUcAuiAZPm4ZzjHTSt9EdHs,5918
|
|
79
79
|
port_ocean/core/event_listener/polling.py,sha256=d9E3oRLy-Ogb0oadZNxSDgSLIHe4z92uMVwztscZycg,3667
|
|
80
|
+
port_ocean/core/event_listener/webhooks_only.py,sha256=PTWnmbLtbJb3ySfotMpTWMYgDVy9zOSYIIGqNbWK0UU,1214
|
|
80
81
|
port_ocean/core/handlers/__init__.py,sha256=d7ShmS90gLRzGKJA6oNy2Zs_dF2yjkmYZInRhBnO9Rw,572
|
|
81
82
|
port_ocean/core/handlers/base.py,sha256=cTarblazu8yh8xz2FpB-dzDKuXxtoi143XJgPbV_DcM,157
|
|
82
83
|
port_ocean/core/handlers/entities_state_applier/__init__.py,sha256=kgLZDCeCEzi4r-0nzW9k78haOZNf6PX7mJOUr34A4c8,173
|
|
@@ -87,7 +88,7 @@ port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py,sha
|
|
|
87
88
|
port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py,sha256=lyv6xKzhYfd6TioUgR3AVRSJqj7JpAaj1LxxU2xAqeo,1720
|
|
88
89
|
port_ocean/core/handlers/entity_processor/__init__.py,sha256=FvFCunFg44wNQoqlybem9MthOs7p1Wawac87uSXz9U8,156
|
|
89
90
|
port_ocean/core/handlers/entity_processor/base.py,sha256=udR0w5TstTOS5xOfTjAZIEdldn4xr6Oyb3DylatYX3Q,1869
|
|
90
|
-
port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=
|
|
91
|
+
port_ocean/core/handlers/entity_processor/jq_entity_processor.py,sha256=X-up0HVdE8pkITxzvB1BC7W8Oq0C14WbT3WqV7p-wJc,11129
|
|
91
92
|
port_ocean/core/handlers/port_app_config/__init__.py,sha256=8AAT5OthiVM7KCcM34iEgEeXtn2pRMrT4Dze5r1Ixbk,134
|
|
92
93
|
port_ocean/core/handlers/port_app_config/api.py,sha256=6VbKPwFzsWG0IYsVD81hxSmfqtHUFqrfUuj1DBX5g4w,853
|
|
93
94
|
port_ocean/core/handlers/port_app_config/base.py,sha256=4Nxt2g8voEIHJ4Y1Km5NJcaG2iSbCklw5P8-Kus7Y9k,3007
|
|
@@ -95,15 +96,15 @@ port_ocean/core/handlers/port_app_config/models.py,sha256=YvYtf_44KD_rN4xK-3xHtd
|
|
|
95
96
|
port_ocean/core/handlers/resync_state_updater/__init__.py,sha256=kG6y-JQGpPfuTHh912L_bctIDCzAK4DN-d00S7rguWU,81
|
|
96
97
|
port_ocean/core/handlers/resync_state_updater/updater.py,sha256=Yg9ET6ZV5B9GW7u6zZA6GlB_71kmvxvYX2FWgQNzMvo,3182
|
|
97
98
|
port_ocean/core/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
98
|
-
port_ocean/core/integrations/base.py,sha256=
|
|
99
|
+
port_ocean/core/integrations/base.py,sha256=eS0WDOfCTim1UOQQrNuP14I6hvT_fr8dof_cr1ls01s,3107
|
|
99
100
|
port_ocean/core/integrations/mixins/__init__.py,sha256=FA1FEKMM6P-L2_m7Q4L20mFa4_RgZnwSRmTCreKcBVM,220
|
|
100
101
|
port_ocean/core/integrations/mixins/events.py,sha256=Ddfx2L4FpghV38waF8OfVeOV0bHBxNIgjU-q5ffillI,2341
|
|
101
102
|
port_ocean/core/integrations/mixins/handler.py,sha256=mZ7-0UlG3LcrwJttFbMe-R4xcOU2H_g33tZar7PwTv8,3771
|
|
102
103
|
port_ocean/core/integrations/mixins/sync.py,sha256=B9fEs8faaYLLikH9GBjE_E61vo0bQDjIGQsQ1SRXOlA,3931
|
|
103
|
-
port_ocean/core/integrations/mixins/sync_raw.py,sha256=
|
|
104
|
+
port_ocean/core/integrations/mixins/sync_raw.py,sha256=Wir4aTSCkIvG6Ny9Eo0Xf55OkSbh_6wHfNSaCffAKJQ,20279
|
|
104
105
|
port_ocean/core/integrations/mixins/utils.py,sha256=oN4Okz6xlaefpid1_Pud8HPSw9BwwjRohyNsknq-Myg,2309
|
|
105
106
|
port_ocean/core/models.py,sha256=O8nOKc4ORZz9tS5s6y5YgGLEBroXpvSPDqKuz48uKvs,1965
|
|
106
|
-
port_ocean/core/ocean_types.py,sha256=
|
|
107
|
+
port_ocean/core/ocean_types.py,sha256=j_-or1VxDy22whLLxwxgzIsE4wAhFLH19Xff9l4oJA8,1124
|
|
107
108
|
port_ocean/core/utils/entity_topological_sorter.py,sha256=MDUjM6OuDy4Xj68o-7InNN0w1jqjxeDfeY8U02vySNI,3081
|
|
108
109
|
port_ocean/core/utils/utils.py,sha256=QSRuF9wlhbOw6cELlDlek_UIX6ciIuKWml8QhBmHU_k,3703
|
|
109
110
|
port_ocean/debug_cli.py,sha256=gHrv-Ey3cImKOcGZpjoHlo4pa_zfmyOl6TUM4o9VtcA,96
|
|
@@ -125,13 +126,13 @@ port_ocean/log/sensetive.py,sha256=lVKiZH6b7TkrZAMmhEJRhcl67HNM94e56x12DwFgCQk,2
|
|
|
125
126
|
port_ocean/middlewares.py,sha256=9wYCdyzRZGK1vjEJ28FY_DkfwDNENmXp504UKPf5NaQ,2727
|
|
126
127
|
port_ocean/ocean.py,sha256=XxO-aRExs1hcy6aJY_nceu-QXRWB2ZLpkIPPuBkp-bQ,5247
|
|
127
128
|
port_ocean/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
128
|
-
port_ocean/run.py,sha256=
|
|
129
|
+
port_ocean/run.py,sha256=COoRSmLG4hbsjIW5DzhV0NYVegI9xHd1POv6sg4U1No,2217
|
|
129
130
|
port_ocean/sonar-project.properties,sha256=X_wLzDOkEVmpGLRMb2fg9Rb0DxWwUFSvESId8qpvrPI,73
|
|
130
131
|
port_ocean/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
131
132
|
port_ocean/tests/clients/port/mixins/test_entities.py,sha256=A9myrnkLhKSQrnOLv1Zz2wiOVSxW65Q9RIUIRbn_V7w,1586
|
|
132
133
|
port_ocean/tests/conftest.py,sha256=JXASSS0IY0nnR6bxBflhzxS25kf4iNaABmThyZ0mZt8,101
|
|
133
134
|
port_ocean/tests/core/defaults/test_common.py,sha256=sR7RqB3ZYV6Xn6NIg-c8k5K6JcGsYZ2SCe_PYX5vLYM,5560
|
|
134
|
-
port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py,sha256=
|
|
135
|
+
port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py,sha256=C2nLgapTdXRrzP5B4xBuHcc14L-NztFpxLIv8Iuv6Gg,12046
|
|
135
136
|
port_ocean/tests/core/handlers/mixins/test_sync_raw.py,sha256=RPrbw4Zs6bmhL9zMQviq7-qMfgP5_4nJDkfZiAukK-g,15782
|
|
136
137
|
port_ocean/tests/core/test_utils.py,sha256=Z3kdhb5V7Svhcyy3EansdTpgHL36TL6erNtU-OPwAcI,2647
|
|
137
138
|
port_ocean/tests/core/utils/test_entity_topological_sorter.py,sha256=zuq5WSPy_88PemG3mOUIHTxWMR_js1R7tOzUYlgBd68,3447
|
|
@@ -156,8 +157,8 @@ port_ocean/utils/repeat.py,sha256=0EFWM9d8lLXAhZmAyczY20LAnijw6UbIECf5lpGbOas,32
|
|
|
156
157
|
port_ocean/utils/signal.py,sha256=K-6kKFQTltcmKDhtyZAcn0IMa3sUpOHGOAUdWKgx0_E,1369
|
|
157
158
|
port_ocean/utils/time.py,sha256=pufAOH5ZQI7gXvOvJoQXZXZJV-Dqktoj9Qp9eiRwmJ4,1939
|
|
158
159
|
port_ocean/version.py,sha256=UsuJdvdQlazzKGD3Hd5-U7N69STh8Dq9ggJzQFnu9fU,177
|
|
159
|
-
port_ocean-0.
|
|
160
|
-
port_ocean-0.
|
|
161
|
-
port_ocean-0.
|
|
162
|
-
port_ocean-0.
|
|
163
|
-
port_ocean-0.
|
|
160
|
+
port_ocean-0.17.0.dist-info/LICENSE.md,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
161
|
+
port_ocean-0.17.0.dist-info/METADATA,sha256=nt5XdziRWQIYLJc1UCfeJWClrpOAyQoTKDD2Ge3O48Q,6673
|
|
162
|
+
port_ocean-0.17.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
163
|
+
port_ocean-0.17.0.dist-info/entry_points.txt,sha256=F_DNUmGZU2Kme-8NsWM5LLE8piGMafYZygRYhOVtcjA,54
|
|
164
|
+
port_ocean-0.17.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|