omnata-plugin-runtime 0.4.11__py3-none-any.whl → 0.5.0a112__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.
- omnata_plugin_runtime/api.py +8 -8
- omnata_plugin_runtime/configuration.py +10 -10
- omnata_plugin_runtime/forms.py +2 -2
- omnata_plugin_runtime/omnata_plugin.py +6 -9
- omnata_plugin_runtime/plugin_entrypoints.py +31 -45
- omnata_plugin_runtime/rate_limiting.py +20 -5
- {omnata_plugin_runtime-0.4.11.dist-info → omnata_plugin_runtime-0.5.0a112.dist-info}/METADATA +16 -15
- omnata_plugin_runtime-0.5.0a112.dist-info/RECORD +12 -0
- omnata_plugin_runtime-0.4.11.dist-info/RECORD +0 -12
- {omnata_plugin_runtime-0.4.11.dist-info → omnata_plugin_runtime-0.5.0a112.dist-info}/LICENSE +0 -0
- {omnata_plugin_runtime-0.4.11.dist-info → omnata_plugin_runtime-0.5.0a112.dist-info}/WHEEL +0 -0
omnata_plugin_runtime/api.py
CHANGED
@@ -67,8 +67,8 @@ class PluginMessageStreamProgressUpdate(BaseModel):
|
|
67
67
|
stream_total_counts: Dict[str, int]
|
68
68
|
completed_streams: List[str]
|
69
69
|
# older runtime versions didn't have these, so the sync engine can't expect it
|
70
|
-
stream_errors: Optional[Dict[str,str]]
|
71
|
-
total_records_estimate: Optional[Dict[str,int]]
|
70
|
+
stream_errors: Optional[Dict[str,str]] = None
|
71
|
+
total_records_estimate: Optional[Dict[str,int]] = None
|
72
72
|
|
73
73
|
|
74
74
|
class PluginMessageCancelledStreams(BaseModel):
|
@@ -120,14 +120,14 @@ class OutboundSyncRequestPayload(BaseModel):
|
|
120
120
|
logging_level: str
|
121
121
|
connection_method: str
|
122
122
|
connection_parameters: Dict[str, StoredConfigurationValue]
|
123
|
-
oauth_secret_name: Optional[str]
|
124
|
-
other_secrets_name: Optional[str]
|
123
|
+
oauth_secret_name: Optional[str] = None
|
124
|
+
other_secrets_name: Optional[str] = None
|
125
125
|
sync_direction: Literal["outbound"] = "outbound"
|
126
126
|
sync_strategy: OutboundSyncStrategy
|
127
127
|
sync_parameters: Dict[str, StoredConfigurationValue]
|
128
128
|
api_limit_overrides: List[ApiLimits]
|
129
129
|
rate_limits_state: Dict[int,Dict[str,Dict[str,RateLimitState]]]
|
130
|
-
field_mappings: Optional[StoredMappingValue]
|
130
|
+
field_mappings: Optional[StoredMappingValue] = None
|
131
131
|
time_limit_mins: int = 60 * 4
|
132
132
|
|
133
133
|
|
@@ -138,7 +138,7 @@ class InboundSyncRequestPayload(BaseModel):
|
|
138
138
|
|
139
139
|
sync_id: int # only used by log handler
|
140
140
|
sync_branch_name: str = 'main' # only used by rate limit updater
|
141
|
-
sync_branch_id: Optional[int] # only used by log handler
|
141
|
+
sync_branch_id: Optional[int] = None # only used by log handler
|
142
142
|
connection_id: int # only used by log handler
|
143
143
|
run_id: int # used by log handler and for reporting back run status updates
|
144
144
|
source_app_name: str # the name of the app which is invoking this plugin
|
@@ -147,8 +147,8 @@ class InboundSyncRequestPayload(BaseModel):
|
|
147
147
|
logging_level: str
|
148
148
|
connection_method: str
|
149
149
|
connection_parameters: Dict[str, StoredConfigurationValue]
|
150
|
-
oauth_secret_name: Optional[str]
|
151
|
-
other_secrets_name: Optional[str]
|
150
|
+
oauth_secret_name: Optional[str] = None
|
151
|
+
other_secrets_name: Optional[str] = None
|
152
152
|
sync_direction: Literal["inbound"] = "inbound"
|
153
153
|
sync_parameters: Dict[str, StoredConfigurationValue]
|
154
154
|
api_limit_overrides: List[ApiLimits]
|
@@ -8,7 +8,7 @@ from typing import Any, List, Dict, Literal, Union, Optional
|
|
8
8
|
from enum import Enum
|
9
9
|
|
10
10
|
from abc import ABC
|
11
|
-
from pydantic import BaseModel, Field, validator # pylint: disable=no-name-in-module
|
11
|
+
from pydantic import BaseModel, Field, PrivateAttr, validator # pylint: disable=no-name-in-module
|
12
12
|
|
13
13
|
if tuple(sys.version_info[:2]) >= (3, 9):
|
14
14
|
# Python 3.9 and above
|
@@ -424,8 +424,8 @@ class InboundSyncStreamsConfiguration(SubscriptableBaseModel):
|
|
424
424
|
"""
|
425
425
|
|
426
426
|
include_new_streams: bool
|
427
|
-
new_stream_sync_strategy: Optional[InboundSyncStrategy]
|
428
|
-
new_stream_storage_behaviour: Optional[InboundStorageBehaviour]
|
427
|
+
new_stream_sync_strategy: Optional[InboundSyncStrategy] = None
|
428
|
+
new_stream_storage_behaviour: Optional[InboundStorageBehaviour] = None
|
429
429
|
included_streams: Dict[str, StoredStreamConfiguration]
|
430
430
|
excluded_streams: List[str]
|
431
431
|
bulk_configuration: InboundSyncBulkConfiguration = InboundSyncBulkConfiguration.CUSTOMIZE
|
@@ -536,10 +536,10 @@ class ConnectionConfigurationParameters(SubscriptableBaseModel):
|
|
536
536
|
connection_secrets: Dict[str, StoredConfigurationValue] = None
|
537
537
|
ngrok_tunnel_settings: Optional[NgrokTunnelSettings] = None
|
538
538
|
access_token_secret_name: Optional[str] = None
|
539
|
-
_snowflake: Optional[Any] = None
|
540
539
|
|
541
|
-
|
542
|
-
|
540
|
+
_snowflake: Optional[Any] = PrivateAttr( # or use Any to annotate the type and use Field to initialize
|
541
|
+
default=None
|
542
|
+
)
|
543
543
|
|
544
544
|
@validator("ngrok_tunnel_settings", always=True)
|
545
545
|
def validate_ngrok_tunnel_settings(cls, v: str, values: dict[str, Any]) -> Optional[NgrokTunnelSettings]:
|
@@ -849,7 +849,7 @@ class StoredFieldMapping(SubscriptableBaseModel):
|
|
849
849
|
app_metadata: dict = Field(default_factory=dict)
|
850
850
|
|
851
851
|
|
852
|
-
StoredStreamConfiguration.
|
853
|
-
InboundSyncStreamsConfiguration.
|
854
|
-
StoredFieldMappings.
|
855
|
-
OutboundSyncConfigurationParameters.
|
852
|
+
StoredStreamConfiguration.model_rebuild()
|
853
|
+
InboundSyncStreamsConfiguration.model_rebuild()
|
854
|
+
StoredFieldMappings.model_rebuild()
|
855
|
+
OutboundSyncConfigurationParameters.model_rebuild()
|
omnata_plugin_runtime/forms.py
CHANGED
@@ -389,8 +389,8 @@ class NewOptionCreator(SubscriptableBaseModel):
|
|
389
389
|
return v.__name__ if isinstance(v, MethodType) else v
|
390
390
|
|
391
391
|
|
392
|
-
StaticFormOptionsDataSource.
|
393
|
-
DynamicFormOptionsDataSource.
|
392
|
+
StaticFormOptionsDataSource.model_rebuild()
|
393
|
+
DynamicFormOptionsDataSource.model_rebuild()
|
394
394
|
|
395
395
|
|
396
396
|
class FormFieldMappingSelector(FormFieldWithDataSource, BaseModel):
|
@@ -30,13 +30,10 @@ from typing import Any, Callable, Dict, Iterable, List, Literal, Optional, Type,
|
|
30
30
|
|
31
31
|
import jinja2
|
32
32
|
import pandas
|
33
|
-
import
|
34
|
-
import
|
35
|
-
from pydantic import Field, parse_obj_as, root_validator
|
33
|
+
from pydantic_core import to_jsonable_python
|
34
|
+
from pydantic import Field, TypeAdapter, root_validator, BaseModel
|
36
35
|
from dateutil.parser import parse
|
37
36
|
from jinja2 import Environment
|
38
|
-
from pydantic import BaseModel # pylint: disable=no-name-in-module
|
39
|
-
from pandas import set_option
|
40
37
|
from snowflake.connector.pandas_tools import write_pandas
|
41
38
|
from snowflake.connector.version import VERSION
|
42
39
|
from snowflake.snowpark import Session
|
@@ -127,7 +124,7 @@ class PluginInfo(BaseModel):
|
|
127
124
|
manifest: PluginManifest
|
128
125
|
anaconda_packages: List[str]
|
129
126
|
bundled_packages: List[str]
|
130
|
-
icon_source: Optional[str]
|
127
|
+
icon_source: Optional[str] = None
|
131
128
|
plugin_class_name: str
|
132
129
|
has_custom_validator: bool
|
133
130
|
plugin_runtime_version: str
|
@@ -368,7 +365,7 @@ class SyncRequest(ABC):
|
|
368
365
|
if update_rate_limit_result is not None:
|
369
366
|
sync_id:int = update_rate_limit_result["sync_id"]
|
370
367
|
sync_branch_name:str = update_rate_limit_result["sync_branch_name"]
|
371
|
-
latest_state
|
368
|
+
latest_state = TypeAdapter(Dict[int,Dict[str,Dict[str,RateLimitState]]]).validate_python(update_rate_limit_result["latest_state"])
|
372
369
|
(rate_limit_state_all, rate_limit_state_this_branch) = RateLimitState.collapse(latest_state,sync_id, sync_branch_name)
|
373
370
|
self.rate_limit_state_all = rate_limit_state_all
|
374
371
|
self.rate_limit_state_this_sync_and_branch = rate_limit_state_this_branch
|
@@ -466,7 +463,7 @@ class SyncRequest(ABC):
|
|
466
463
|
self._session.sql(
|
467
464
|
f"""call {self._source_app_name}.API.PLUGIN_MESSAGE(
|
468
465
|
{self._run_id},
|
469
|
-
PARSE_JSON($${json.dumps(message
|
466
|
+
PARSE_JSON($${json.dumps(to_jsonable_python(message))}$$))"""
|
470
467
|
).collect()
|
471
468
|
)
|
472
469
|
except Exception as e:
|
@@ -1955,7 +1952,7 @@ def managed_outbound_processing(concurrency: int, batch_size: int):
|
|
1955
1952
|
dataframe_arg = method_args[0]
|
1956
1953
|
if dataframe_arg.__class__.__name__ != "DataFrame" and not hasattr(dataframe_arg, "__next__"):
|
1957
1954
|
raise ValueError(
|
1958
|
-
f"The first argument to a @managed_outbound_processing method must be a DataFrame or DataFrame generator (from outbound_sync_request.get_records). Instead, a {
|
1955
|
+
f"The first argument to a @managed_outbound_processing method must be a DataFrame or DataFrame generator (from outbound_sync_request.get_records). Instead, a {dataframe_arg.__class__.__name__} was provided. Alternatively, you can provide these via the 'dataframe' or 'dataframe_generator' named arguments."
|
1959
1956
|
)
|
1960
1957
|
method_args = method_args[1:]
|
1961
1958
|
|
@@ -8,8 +8,8 @@ import time
|
|
8
8
|
import threading
|
9
9
|
from typing import Dict, List, Optional
|
10
10
|
|
11
|
-
from pydantic import BaseModel,
|
12
|
-
import
|
11
|
+
from pydantic import BaseModel,TypeAdapter # pylint: disable=no-name-in-module
|
12
|
+
from pydantic_core import to_jsonable_python
|
13
13
|
from snowflake.snowpark import Session
|
14
14
|
|
15
15
|
from .api import PluginMessageStreamProgressUpdate, SyncRequestPayload, handle_proc_result
|
@@ -69,7 +69,7 @@ class PluginEntrypoint:
|
|
69
69
|
|
70
70
|
def sync(self, sync_request: Dict):
|
71
71
|
logger.info("Entered sync method")
|
72
|
-
request =
|
72
|
+
request = TypeAdapter(SyncRequestPayload).validate_python(sync_request)
|
73
73
|
connection_secrets = self.get_secrets(
|
74
74
|
request.oauth_secret_name, request.other_secrets_name
|
75
75
|
)
|
@@ -93,7 +93,7 @@ class PluginEntrypoint:
|
|
93
93
|
connection_parameters.access_token_secret_name = request.oauth_secret_name
|
94
94
|
all_api_limits = self._plugin_instance.api_limits(connection_parameters)
|
95
95
|
logger.info(
|
96
|
-
f"Default API limits: {json.dumps(all_api_limits
|
96
|
+
f"Default API limits: {json.dumps(to_jsonable_python(all_api_limits))}"
|
97
97
|
)
|
98
98
|
all_api_limits_by_category = {
|
99
99
|
api_limit.endpoint_category: api_limit for api_limit in all_api_limits
|
@@ -109,7 +109,7 @@ class PluginEntrypoint:
|
|
109
109
|
api_limits = list(all_api_limits_by_category.values())
|
110
110
|
return_dict = {}
|
111
111
|
logger.info(
|
112
|
-
f"Rate limits state: {json.dumps(request.rate_limits_state
|
112
|
+
f"Rate limits state: {json.dumps(to_jsonable_python(request.rate_limits_state))}"
|
113
113
|
)
|
114
114
|
(rate_limit_state_all, rate_limit_state_this_branch) = RateLimitState.collapse(request.rate_limits_state,request.sync_id, request.sync_branch_name)
|
115
115
|
# if any endpoint categories have no state, give them an empty state
|
@@ -270,19 +270,15 @@ class PluginEntrypoint:
|
|
270
270
|
oauth_secret_name = normalise_nulls(oauth_secret_name)
|
271
271
|
other_secrets_name = normalise_nulls(other_secrets_name)
|
272
272
|
connection_secrets = self.get_secrets(oauth_secret_name, other_secrets_name)
|
273
|
-
connection_parameters =
|
274
|
-
Dict[str, StoredConfigurationValue]
|
275
|
-
|
276
|
-
|
277
|
-
Dict[str, StoredConfigurationValue], sync_parameters
|
278
|
-
)
|
273
|
+
connection_parameters = TypeAdapter(
|
274
|
+
Dict[str, StoredConfigurationValue]).validate_python(connection_parameters)
|
275
|
+
sync_parameters = TypeAdapter(
|
276
|
+
Dict[str, StoredConfigurationValue]).validate_python(sync_parameters)
|
279
277
|
form_parameters = None
|
280
278
|
if current_form_parameters is not None:
|
281
|
-
form_parameters =
|
282
|
-
Dict[str, StoredConfigurationValue], current_form_parameters
|
283
|
-
)
|
279
|
+
form_parameters = TypeAdapter(Dict[str, StoredConfigurationValue]).validate_python(current_form_parameters)
|
284
280
|
if sync_direction == "outbound":
|
285
|
-
sync_strat = OutboundSyncStrategy.
|
281
|
+
sync_strat = OutboundSyncStrategy.model_validate(sync_strategy) if sync_strategy is not None else None
|
286
282
|
parameters = OutboundSyncConfigurationParameters(
|
287
283
|
connection_parameters=connection_parameters,
|
288
284
|
connection_secrets=connection_secrets,
|
@@ -328,12 +324,10 @@ class PluginEntrypoint:
|
|
328
324
|
oauth_secret_name = normalise_nulls(oauth_secret_name)
|
329
325
|
other_secrets_name = normalise_nulls(other_secrets_name)
|
330
326
|
connection_secrets = self.get_secrets(oauth_secret_name, other_secrets_name)
|
331
|
-
connection_parameters =
|
332
|
-
Dict[str, StoredConfigurationValue]
|
333
|
-
|
334
|
-
|
335
|
-
Dict[str, StoredConfigurationValue], sync_parameters
|
336
|
-
)
|
327
|
+
connection_parameters = TypeAdapter(
|
328
|
+
Dict[str, StoredConfigurationValue]).validate_python(connection_parameters)
|
329
|
+
sync_parameters = TypeAdapter(
|
330
|
+
Dict[str, StoredConfigurationValue]).validate_python(sync_parameters)
|
337
331
|
parameters = InboundSyncConfigurationParameters(
|
338
332
|
connection_parameters=connection_parameters,
|
339
333
|
connection_secrets=connection_secrets,
|
@@ -360,9 +354,8 @@ class PluginEntrypoint:
|
|
360
354
|
stored_values: List[Dict],
|
361
355
|
):
|
362
356
|
logger.info("Entered construct_form_option method")
|
363
|
-
stored_values_parsed =
|
364
|
-
List[StoredConfigurationValue]
|
365
|
-
)
|
357
|
+
stored_values_parsed = TypeAdapter(
|
358
|
+
List[StoredConfigurationValue]).validate_python(stored_values)
|
366
359
|
the_function = getattr(
|
367
360
|
self._plugin_instance,
|
368
361
|
function_name,
|
@@ -382,7 +375,7 @@ class PluginEntrypoint:
|
|
382
375
|
|
383
376
|
def create_billing_events(self, session, event_request: Dict):
|
384
377
|
logger.info("Entered create_billing_events method")
|
385
|
-
request =
|
378
|
+
request = BillingEventRequest.model_validate(event_request)
|
386
379
|
events: List[SnowflakeBillingEvent] = self._plugin_instance.create_billing_events(
|
387
380
|
request
|
388
381
|
)
|
@@ -435,7 +428,7 @@ class PluginEntrypoint:
|
|
435
428
|
other_secrets = json.loads(secret_string_content)
|
436
429
|
connection_secrets = {
|
437
430
|
**connection_secrets,
|
438
|
-
**
|
431
|
+
**TypeAdapter(Dict[str, StoredConfigurationValue]).validate_python(other_secrets),
|
439
432
|
}
|
440
433
|
except Exception as exception:
|
441
434
|
logger.error(f"Error parsing secrets content for secret {other_secrets_name}: {str(exception)}")
|
@@ -454,9 +447,8 @@ class PluginEntrypoint:
|
|
454
447
|
oauth_secret_name = normalise_nulls(oauth_secret_name)
|
455
448
|
other_secrets_name = normalise_nulls(other_secrets_name)
|
456
449
|
connection_secrets = self.get_secrets(oauth_secret_name, other_secrets_name)
|
457
|
-
connection_parameters =
|
458
|
-
Dict[str, StoredConfigurationValue]
|
459
|
-
)
|
450
|
+
connection_parameters = TypeAdapter(
|
451
|
+
Dict[str, StoredConfigurationValue]).validate_python(connection_parameters)
|
460
452
|
parameters = ConnectionConfigurationParameters(
|
461
453
|
connection_method=connection_method,
|
462
454
|
connection_parameters=connection_parameters,
|
@@ -484,9 +476,8 @@ class PluginEntrypoint:
|
|
484
476
|
return self._plugin_instance.network_addresses(
|
485
477
|
ConnectionConfigurationParameters(
|
486
478
|
connection_method=method,
|
487
|
-
connection_parameters=
|
488
|
-
Dict[str, StoredConfigurationValue],
|
489
|
-
),
|
479
|
+
connection_parameters=TypeAdapter(
|
480
|
+
Dict[str, StoredConfigurationValue]).validate_python(connection_parameters),
|
490
481
|
connection_secrets={},
|
491
482
|
)
|
492
483
|
)
|
@@ -508,9 +499,8 @@ class PluginEntrypoint:
|
|
508
499
|
)
|
509
500
|
parameters = ConnectionConfigurationParameters(
|
510
501
|
connection_method=method,
|
511
|
-
connection_parameters=
|
512
|
-
Dict[str, StoredConfigurationValue],
|
513
|
-
),
|
502
|
+
connection_parameters=TypeAdapter(
|
503
|
+
Dict[str, StoredConfigurationValue]).validate_python(connection_parameters),
|
514
504
|
connection_secrets=connection_secrets
|
515
505
|
)
|
516
506
|
if oauth_secret_name is not None:
|
@@ -555,15 +545,14 @@ class PluginEntrypoint:
|
|
555
545
|
)
|
556
546
|
connection_parameters = ConnectionConfigurationParameters(
|
557
547
|
connection_method=method,
|
558
|
-
connection_parameters=
|
559
|
-
Dict[str, StoredConfigurationValue],
|
560
|
-
),
|
548
|
+
connection_parameters=TypeAdapter(
|
549
|
+
Dict[str, StoredConfigurationValue]).validate_python(connection_parameters),
|
561
550
|
connection_secrets=connection_secrets
|
562
551
|
)
|
563
552
|
if oauth_secret_name is not None:
|
564
553
|
connection_parameters.access_token_secret_name = oauth_secret_name
|
565
554
|
response: List[ApiLimits] = self._plugin_instance.api_limits(connection_parameters)
|
566
|
-
return [api_limit.
|
555
|
+
return [api_limit.model_dump() for api_limit in response]
|
567
556
|
|
568
557
|
def outbound_record_validator(
|
569
558
|
self,
|
@@ -573,12 +562,9 @@ class PluginEntrypoint:
|
|
573
562
|
source_types: Dict[str, str],
|
574
563
|
):
|
575
564
|
# There's a bit of parsing here that could possibly be done outside of the handler function, but this shouldn't be too expensive
|
576
|
-
sync_parameters: Dict[str, StoredConfigurationValue] =
|
577
|
-
Dict[str, StoredConfigurationValue]
|
578
|
-
)
|
579
|
-
field_mappings: StoredMappingValue = parse_obj_as(
|
580
|
-
StoredMappingValue, field_mappings
|
581
|
-
)
|
565
|
+
sync_parameters: Dict[str, StoredConfigurationValue] = TypeAdapter(
|
566
|
+
Dict[str, StoredConfigurationValue]).validate_python(sync_parameters)
|
567
|
+
field_mappings: StoredMappingValue = StoredMappingValue.model_validate(field_mappings)
|
582
568
|
return self._plugin_instance.outbound_record_validator(
|
583
569
|
sync_parameters, field_mappings, transformed_record, source_types
|
584
570
|
)
|
@@ -12,8 +12,8 @@ from typing import Any, List, Literal, Optional, Dict, Tuple
|
|
12
12
|
import requests
|
13
13
|
import time
|
14
14
|
import logging
|
15
|
-
from pydantic import Field, root_validator
|
16
|
-
from
|
15
|
+
from pydantic import Field, root_validator, PrivateAttr, field_serializer
|
16
|
+
from pydantic_core import to_jsonable_python
|
17
17
|
from .configuration import SubscriptableBaseModel
|
18
18
|
import pytz
|
19
19
|
from requests.adapters import HTTPAdapter
|
@@ -160,7 +160,7 @@ def epoch_milliseconds_to_datetime(epoch: int) -> datetime.datetime:
|
|
160
160
|
def datetimes_as_ints_encoder(obj):
|
161
161
|
if isinstance(obj, datetime.datetime):
|
162
162
|
return datetime_to_epoch_milliseconds(obj)
|
163
|
-
return
|
163
|
+
return to_jsonable_python(obj)
|
164
164
|
|
165
165
|
|
166
166
|
class RateLimitState(SubscriptableBaseModel):
|
@@ -178,7 +178,22 @@ class RateLimitState(SubscriptableBaseModel):
|
|
178
178
|
[],
|
179
179
|
description="A list of timestamps where previous requests have been made, used to calculate the next request time",
|
180
180
|
)
|
181
|
-
|
181
|
+
|
182
|
+
_request_timestamps_lock: threading.Lock = PrivateAttr( # or use Any to annotate the type and use Field to initialize
|
183
|
+
default_factory=lambda: threading.Lock()
|
184
|
+
)
|
185
|
+
|
186
|
+
@field_serializer('wait_until',when_used='always')
|
187
|
+
def serialize_wait_until(self, value:Optional[datetime.datetime]) -> Optional[int]:
|
188
|
+
# if a datetime is provided, convert it to epoch milliseconds
|
189
|
+
if value is not None:
|
190
|
+
return datetime_to_epoch_milliseconds(value)
|
191
|
+
|
192
|
+
@field_serializer('previous_request_timestamps',when_used='always')
|
193
|
+
def serialize_previous_request_timestamps(self, value:List[datetime.datetime]) -> List[int]:
|
194
|
+
# if a list of datetimes is provided, convert them to epoch milliseconds
|
195
|
+
return [datetime_to_epoch_milliseconds(ts) if ts else None for ts in value]
|
196
|
+
|
182
197
|
|
183
198
|
# Combined root validator
|
184
199
|
@root_validator(pre=True)
|
@@ -545,4 +560,4 @@ def too_many_requests_hook(
|
|
545
560
|
return hook
|
546
561
|
|
547
562
|
|
548
|
-
ApiLimits.
|
563
|
+
ApiLimits.model_rebuild()
|
{omnata_plugin_runtime-0.4.11.dist-info → omnata_plugin_runtime-0.5.0a112.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: omnata-plugin-runtime
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0a112
|
4
4
|
Summary: Classes and common runtime components for building and running Omnata Plugins
|
5
5
|
Author: James Weakley
|
6
6
|
Author-email: james.weakley@omnata.com
|
@@ -9,26 +9,27 @@ Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.8
|
10
10
|
Classifier: Programming Language :: Python :: 3.9
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
12
|
-
Requires-Dist: certifi (<=
|
12
|
+
Requires-Dist: certifi (<=2024.7.4)
|
13
13
|
Requires-Dist: charset-normalizer (<=2.0.4)
|
14
|
-
Requires-Dist: idna (<=3.
|
14
|
+
Requires-Dist: idna (<=3.7)
|
15
15
|
Requires-Dist: jinja2 (>=3.1.2,<=3.1.4)
|
16
16
|
Requires-Dist: markupsafe (<=2.1.3)
|
17
|
-
Requires-Dist: numpy (<=1.26.
|
18
|
-
Requires-Dist: packaging (<=
|
19
|
-
Requires-Dist: pandas (<=2.
|
17
|
+
Requires-Dist: numpy (<=1.26.4)
|
18
|
+
Requires-Dist: packaging (<=24.1)
|
19
|
+
Requires-Dist: pandas (<=2.2.2)
|
20
20
|
Requires-Dist: platformdirs (<=3.10.0)
|
21
|
-
Requires-Dist: pydantic (>=
|
22
|
-
Requires-Dist: pyjwt (<=2.
|
23
|
-
Requires-Dist: pyopenssl (<=
|
24
|
-
Requires-Dist: pytz (<=
|
25
|
-
Requires-Dist: requests (>=2,<=2.
|
21
|
+
Requires-Dist: pydantic (>=2,<=2.5.3)
|
22
|
+
Requires-Dist: pyjwt (<=2.8.0)
|
23
|
+
Requires-Dist: pyopenssl (<=24.0.0)
|
24
|
+
Requires-Dist: pytz (<=2024.1)
|
25
|
+
Requires-Dist: requests (>=2,<=2.32.2)
|
26
26
|
Requires-Dist: setuptools (<=69.5.1)
|
27
|
-
Requires-Dist: snowflake-
|
28
|
-
Requires-Dist:
|
27
|
+
Requires-Dist: snowflake-connector-python (>=3,<=3.12.0)
|
28
|
+
Requires-Dist: snowflake-snowpark-python (==1.19.0)
|
29
|
+
Requires-Dist: tenacity (>=8,<=8.2.3)
|
29
30
|
Requires-Dist: tomlkit (<=0.11.1)
|
30
|
-
Requires-Dist: urllib3 (<=2.
|
31
|
-
Requires-Dist: wheel (<=0.
|
31
|
+
Requires-Dist: urllib3 (<=2.2.2)
|
32
|
+
Requires-Dist: wheel (<=0.43.0)
|
32
33
|
Description-Content-Type: text/markdown
|
33
34
|
|
34
35
|
# omnata-plugin-runtime
|
@@ -0,0 +1,12 @@
|
|
1
|
+
omnata_plugin_runtime/__init__.py,sha256=MS9d1whnfT_B3-ThqZ7l63QeC_8OEKTuaYV5wTwRpBA,1576
|
2
|
+
omnata_plugin_runtime/api.py,sha256=FxzTqri4no8ClkOm7vZADG8aD47jcGBCTTQDEORmOJM,6326
|
3
|
+
omnata_plugin_runtime/configuration.py,sha256=LvQVIKwo8XlfHf-9Jkj1GDH0U6sOKDKi3IMDyAwAnHE,35781
|
4
|
+
omnata_plugin_runtime/forms.py,sha256=hV6jVaizex20Pb9NxPx11TBPK-Yy8pREAnTtCxHo4Qo,18409
|
5
|
+
omnata_plugin_runtime/logging.py,sha256=bn7eKoNWvtuyTk7RTwBS9UARMtqkiICtgMtzq3KA2V0,3272
|
6
|
+
omnata_plugin_runtime/omnata_plugin.py,sha256=zIk8dS5m4pXsVy_2im-Cd-t1uQV9hf1seosb1T2jGGs,110880
|
7
|
+
omnata_plugin_runtime/plugin_entrypoints.py,sha256=xlPTI25N5G3l0bRFSkga98TIHM44NRaN2g7T5jSsqX0,29181
|
8
|
+
omnata_plugin_runtime/rate_limiting.py,sha256=BzN8CkI8dxel1PERDpuSZek7vo6QeCHwbZEtcO21IR4,25479
|
9
|
+
omnata_plugin_runtime-0.5.0a112.dist-info/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
|
10
|
+
omnata_plugin_runtime-0.5.0a112.dist-info/METADATA,sha256=KIWIJS75ax78BJ4cIKQGU3qQtSrv7zRwgdA6duIT5so,1699
|
11
|
+
omnata_plugin_runtime-0.5.0a112.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
12
|
+
omnata_plugin_runtime-0.5.0a112.dist-info/RECORD,,
|
@@ -1,12 +0,0 @@
|
|
1
|
-
omnata_plugin_runtime/__init__.py,sha256=MS9d1whnfT_B3-ThqZ7l63QeC_8OEKTuaYV5wTwRpBA,1576
|
2
|
-
omnata_plugin_runtime/api.py,sha256=W79CsAcl127Dzy-XVS9CzvzsbS3IigVH4QAhFFDkaXg,6270
|
3
|
-
omnata_plugin_runtime/configuration.py,sha256=7cMekoY8CeZAJHpASU6tCMidF55Hzfr7CD74jtebqIY,35742
|
4
|
-
omnata_plugin_runtime/forms.py,sha256=pw_aKVsXSz47EP8PFBI3VDwdSN5IjvZxp8JTjO1V130,18421
|
5
|
-
omnata_plugin_runtime/logging.py,sha256=bn7eKoNWvtuyTk7RTwBS9UARMtqkiICtgMtzq3KA2V0,3272
|
6
|
-
omnata_plugin_runtime/omnata_plugin.py,sha256=SKdtUOsJWVG-WtartrdSxOJUPfZrnmp0sf0WQduj7gk,110997
|
7
|
-
omnata_plugin_runtime/plugin_entrypoints.py,sha256=JAGEdVcy9QEXv7TO5zt7co64LTP8nqGusOc0sJG9GtU,29149
|
8
|
-
omnata_plugin_runtime/rate_limiting.py,sha256=BOxyjERDG46iPY7coYu79jdZ9JqHMYPG-BNyXYOIJmk,24678
|
9
|
-
omnata_plugin_runtime-0.4.11.dist-info/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
|
10
|
-
omnata_plugin_runtime-0.4.11.dist-info/METADATA,sha256=HDZk_7-6eAWyKZXCZ7jzkO3Sbp0asC2Tu6QvbThbR5o,1647
|
11
|
-
omnata_plugin_runtime-0.4.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
12
|
-
omnata_plugin_runtime-0.4.11.dist-info/RECORD,,
|
{omnata_plugin_runtime-0.4.11.dist-info → omnata_plugin_runtime-0.5.0a112.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|