omnata-plugin-runtime 0.5.0a113__py3-none-any.whl → 0.5.2__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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, PrivateAttr, validator # pylint: disable=no-name-in-module
11
+ from pydantic import BaseModel, Field, PrivateAttr, SerializationInfo, model_serializer, 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
@@ -110,16 +110,18 @@ class OutboundSyncAction(SubscriptableBaseModel, ABC):
110
110
  **STANDARD_OUTBOUND_SYNC_ACTIONS[data["action_name"]]().__dict__,
111
111
  }
112
112
  super().__init__(**data)
113
-
114
- def dict(self, *args, trim: bool = True, **kwargs) -> Dict[str, any]:
115
- """
116
- OutboundSyncStrategy objects can be serialized much smaller if the instance is of a Standard strategy that resides in the
117
- Omnata plugin runtime. This method trims out the unneeded attributes in these scenarios.
118
- This method also trims the actions for this strategy if it's a custom one.
119
-
120
- """
121
- excluded_fields = {} if not trim or self.custom_action else {"description"}
122
- return super().dict(exclude=excluded_fields)
113
+
114
+ @model_serializer(mode='wrap')
115
+ def ser_model(self,handler,info:SerializationInfo) -> Dict[str, Any]:
116
+ serialized:Dict[str,Any] = handler(self)
117
+ if not self.custom_action and (info.exclude_none is None or info.exclude_none == False):
118
+ return {k:v for k,v in serialized.items() if k not in [
119
+ "description"]}
120
+ return serialized
121
+
122
+ def model_dump_no_trim(self) -> Dict[str, Any]:
123
+ # we use our own special include value to signal not to trim
124
+ return self.model_dump(exclude_none=True)
123
125
 
124
126
 
125
127
  class CreateSyncAction(OutboundSyncAction):
@@ -221,13 +223,13 @@ class OutboundSyncStrategy(SubscriptableBaseModel, ABC):
221
223
  name: str
222
224
  description: str
223
225
  icon_source: str = ICON_URL_CODE
224
- action_on_record_create: Optional[OutboundSyncAction] = None
225
- action_on_record_update: Optional[OutboundSyncAction] = None
226
- action_on_record_delete: Optional[OutboundSyncAction] = None
227
- action_on_record_unchanged: Optional[OutboundSyncAction] = None
226
+ action_on_record_create: Optional[OutboundSyncAction] = Field(default=None)
227
+ action_on_record_update: Optional[OutboundSyncAction] = Field(default=None)
228
+ action_on_record_delete: Optional[OutboundSyncAction] = Field(default=None)
229
+ action_on_record_unchanged: Optional[OutboundSyncAction] = Field(default=None)
228
230
  custom_strategy: bool = True
229
231
 
230
- def __eq__(self, other):
232
+ def __eq__(self, other:OutboundSyncStrategy):
231
233
  if hasattr(other, 'custom_strategy') and hasattr(other, 'name'):
232
234
  return (
233
235
  self.custom_strategy == other.custom_strategy
@@ -251,27 +253,23 @@ class OutboundSyncStrategy(SubscriptableBaseModel, ABC):
251
253
  }
252
254
  super().__init__(**data)
253
255
 
254
- def dict(self, *args, trim: bool = True, **kwargs) -> Dict[str, any]:
255
- """
256
- OutboundSyncStrategy objects can be serialized much smaller if the instance is of a Standard strategy that resides in the
257
- Omnata plugin runtime. This method trims out the unneeded attributes in these scenarios.
258
- This method also trims the actions for this strategy if it's a custom one.
259
-
260
- """
261
- excluded_fields = (
262
- {}
263
- if not trim or self.custom_strategy
264
- else {
256
+ @model_serializer(mode='wrap')
257
+ def ser_model(self,handler,info:SerializationInfo) -> Dict[str, Any]:
258
+ serialized:Dict[str,Any] = handler(self)
259
+ if not self.custom_strategy and (info.exclude_none is None or info.exclude_none == False):
260
+ return {k:v for k,v in serialized.items() if k not in [
265
261
  "description",
266
262
  "icon_source",
267
263
  "action_on_record_create",
268
264
  "action_on_record_update",
269
265
  "action_on_record_delete",
270
- "action_on_record_unchanged",
271
- }
272
- )
273
- return super().dict(exclude=excluded_fields)
274
-
266
+ "action_on_record_unchanged"]}
267
+ return serialized
268
+
269
+ def model_dump_no_trim(self) -> Dict[str, Any]:
270
+ # we use our own special include value to signal not to trim
271
+ return self.model_dump(exclude_none=True)
272
+
275
273
 
276
274
  class CreateSyncStrategy(OutboundSyncStrategy):
277
275
  """
@@ -424,8 +422,8 @@ class InboundSyncStreamsConfiguration(SubscriptableBaseModel):
424
422
  """
425
423
 
426
424
  include_new_streams: bool
427
- new_stream_sync_strategy: Optional[InboundSyncStrategy] = None
428
- new_stream_storage_behaviour: Optional[InboundStorageBehaviour] = None
425
+ new_stream_sync_strategy: Optional[InboundSyncStrategy] = Field(default=None)
426
+ new_stream_storage_behaviour: Optional[InboundStorageBehaviour] = Field(default=None)
429
427
  included_streams: Dict[str, StoredStreamConfiguration]
430
428
  excluded_streams: List[str]
431
429
  bulk_configuration: InboundSyncBulkConfiguration = InboundSyncBulkConfiguration.CUSTOMIZE
@@ -532,10 +530,10 @@ class ConnectionConfigurationParameters(SubscriptableBaseModel):
532
530
  """
533
531
 
534
532
  connection_method: str
535
- connection_parameters: Dict[str, StoredConfigurationValue] = None
536
- connection_secrets: Dict[str, StoredConfigurationValue] = None
537
- ngrok_tunnel_settings: Optional[NgrokTunnelSettings] = None
538
- access_token_secret_name: Optional[str] = None
533
+ connection_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
534
+ connection_secrets: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
535
+ ngrok_tunnel_settings: Optional[NgrokTunnelSettings] = Field(default=None)
536
+ access_token_secret_name: Optional[str] = Field(default=None)
539
537
 
540
538
  _snowflake: Optional[Any] = PrivateAttr( # or use Any to annotate the type and use Field to initialize
541
539
  default=None
@@ -608,10 +606,10 @@ class SyncConfigurationParameters(ConnectionConfigurationParameters):
608
606
  """
609
607
 
610
608
  connection_method: str
611
- connection_parameters: Dict[str, StoredConfigurationValue] = None
612
- connection_secrets: Dict[str, StoredConfigurationValue] = None
613
- sync_parameters: Dict[str, StoredConfigurationValue] = None
614
- current_form_parameters: Dict[str, StoredConfigurationValue] = None
609
+ connection_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
610
+ connection_secrets: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
611
+ sync_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
612
+ current_form_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
615
613
 
616
614
  def sync_parameter_exists(self, parameter_name: str) -> bool:
617
615
  """
@@ -688,12 +686,12 @@ class OutboundSyncConfigurationParameters(SyncConfigurationParameters):
688
686
  """
689
687
 
690
688
  connection_method: str
691
- connection_parameters: Dict[str, StoredConfigurationValue] = None
692
- connection_secrets: Dict[str, StoredConfigurationValue] = None
693
- sync_parameters: Dict[str, StoredConfigurationValue] = None
694
- current_form_parameters: Dict[str, StoredConfigurationValue] = None
695
- sync_strategy: OutboundSyncStrategy = None
696
- field_mappings: StoredMappingValue = None
689
+ connection_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
690
+ connection_secrets: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
691
+ sync_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
692
+ current_form_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
693
+ sync_strategy: Optional[OutboundSyncStrategy] = Field(default=None)
694
+ field_mappings: Optional[StoredMappingValue] = Field(default=None)
697
695
 
698
696
 
699
697
  class InboundSyncConfigurationParameters(SyncConfigurationParameters):
@@ -708,11 +706,11 @@ class InboundSyncConfigurationParameters(SyncConfigurationParameters):
708
706
  """
709
707
 
710
708
  connection_method: str
711
- connection_parameters: Dict[str, StoredConfigurationValue] = None
712
- connection_secrets: Dict[str, StoredConfigurationValue] = None
713
- sync_parameters: Dict[str, StoredConfigurationValue] = None
714
- current_form_parameters: Dict[str, StoredConfigurationValue] = None
715
- currently_selected_streams: List[str] = None
709
+ connection_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
710
+ connection_secrets: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
711
+ sync_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
712
+ current_form_parameters: Optional[Dict[str, StoredConfigurationValue]] = Field(default=None)
713
+ currently_selected_streams: Optional[List[str]] = Field(default=None)
716
714
 
717
715
 
718
716
  class StoredJinjaTemplate(SubscriptableBaseModel):
@@ -722,7 +720,7 @@ class StoredJinjaTemplate(SubscriptableBaseModel):
722
720
  """
723
721
 
724
722
  mapper_type: Literal["jinja_template"] = "jinja_template"
725
- additional_column_expressions: Dict[str, str] = {}
723
+ additional_column_expressions: Dict[str, str] = Field(default={})
726
724
  jinja_template: str
727
725
 
728
726
 
@@ -759,11 +757,11 @@ class SyncScheduleSnowflakeTask(SubscriptableBaseModel):
759
757
  mode: Literal["snowflake_task"] = "snowflake_task"
760
758
  sync_frequency: str
761
759
  sync_frequency_name: Literal["1 min", "5 mins", "15 mins", "Hourly", "Daily","Custom"]
762
- warehouse: str = None
760
+ warehouse: Optional[str] = Field(default=None)
763
761
  time_limit_mins: int = 60 * 4
764
- daily_hour: Optional[int] = None
765
- daily_minute: Optional[int] = None
766
- minute_of_hour: Optional[int] = None
762
+ daily_hour: Optional[int] = Field(default=None)
763
+ daily_minute: Optional[int] = Field(default=None)
764
+ minute_of_hour: Optional[int] = Field(default=None)
767
765
 
768
766
 
769
767
  class SyncScheduleDbt(SubscriptableBaseModel):
@@ -41,10 +41,10 @@ class FormOption(SubscriptableBaseModel):
41
41
  value: str
42
42
  label: str
43
43
  metadata: dict = Field(default_factory=dict)
44
- required: bool = False
45
- unique: bool = False
46
- default: bool = False
47
- disabled: bool = False
44
+ required: bool = Field(default=False)
45
+ unique: bool = Field(default=False)
46
+ default: bool = Field(default=False)
47
+ disabled: bool = Field(default=False)
48
48
  data_type_icon: str = "unknown"
49
49
 
50
50
 
@@ -55,12 +55,12 @@ class FormInputField(SubscriptableBaseModel):
55
55
 
56
56
  name: str
57
57
  label: str
58
- default_value: Union[str, bool] = ""
59
- required: bool = False
60
- depends_on: Optional[str] = None
61
- help_text: str = ""
62
- reload_on_change: bool = False
63
- secret: bool = False
58
+ default_value: Union[str, bool] = Field(default="")
59
+ required: bool = Field(default=False)
60
+ depends_on: Optional[str] = Field(default=None)
61
+ help_text: str = Field(default="")
62
+ reload_on_change: bool = Field(default=False)
63
+ secret: bool = Field(default=False)
64
64
  type: Literal["input"] = "input"
65
65
 
66
66
 
@@ -81,15 +81,15 @@ class FormTextAreaField(SubscriptableBaseModel):
81
81
 
82
82
  name: str
83
83
  label: str
84
- default_value: str = ""
85
- secret: bool = False
86
- required: bool = False
87
- depends_on: Optional[str] = None
88
- help_text: str = ""
89
- reload_on_change: bool = False
84
+ default_value: str = Field(default="")
85
+ secret: bool = Field(default=False)
86
+ required: bool = Field(default=False)
87
+ depends_on: Optional[str] = Field(default=None)
88
+ help_text: str = Field(default="")
89
+ reload_on_change: bool = Field(default=False)
90
90
  type: Literal["textarea"] = "textarea"
91
91
 
92
- variables: bool = False
92
+ variables: bool = Field(default=False)
93
93
 
94
94
  class InformationField(SubscriptableBaseModel):
95
95
  """
@@ -101,10 +101,10 @@ class InformationField(SubscriptableBaseModel):
101
101
  """
102
102
  name: str
103
103
  markdown_content: str
104
- depends_on: Optional[str] = None
104
+ depends_on: Optional[str] = Field(default=None)
105
105
  type: Literal["information"] = "information"
106
- reload_on_change: bool = False
107
- secret: bool = False
106
+ reload_on_change: bool = Field(default=False)
107
+ secret: bool = Field(default=False)
108
108
 
109
109
  class InformationBoxField(SubscriptableBaseModel):
110
110
  """
@@ -119,12 +119,12 @@ class InformationBoxField(SubscriptableBaseModel):
119
119
  """
120
120
  name: str
121
121
  markdown_content: str
122
- depends_on: Optional[str] = None
122
+ depends_on: Optional[str] = Field(default=None)
123
123
  type: Literal["information_box"] = "information_box"
124
- reload_on_change: bool = False
124
+ reload_on_change: bool = Field(default=False)
125
125
  box_type: Literal["info", "warning", "error"] = "info"
126
- box_icon: Optional[str] = None
127
- secret: bool = False
126
+ box_icon: Optional[str] = Field(default=None)
127
+ secret: bool = Field(default=False)
128
128
 
129
129
  class FormSshKeypair(SubscriptableBaseModel):
130
130
  """
@@ -132,21 +132,21 @@ class FormSshKeypair(SubscriptableBaseModel):
132
132
  """
133
133
  name: str
134
134
  label: str
135
- default_value: Optional[str] = None
136
- required: bool = False
137
- depends_on: Optional[str] = None
138
- help_text: str = ""
135
+ default_value: Optional[str] = Field(default=None)
136
+ required: bool = Field(default=False)
137
+ depends_on: Optional[str] = Field(default=None)
138
+ help_text: str = Field(default="")
139
139
  local_side: Literal["public", "private"] = "public"
140
140
  """
141
141
  The side of the keypair which belongs to Snowflake. This value will be stored as the secret value, and the other side
142
142
  can be copied/downloaded only during the connection process.
143
143
  """
144
- allow_user_provided: bool = True
144
+ allow_user_provided: bool = Field(default=True)
145
145
  """
146
146
  Allows the user to provide Snowflake's side of the keypair, for cases where one is generated on the outside
147
147
  """
148
148
  type: Literal["ssh_keypair"] = "ssh_keypair"
149
- secret: bool = True
149
+ secret: bool = Field(default=True)
150
150
 
151
151
  class FormX509Certificate(SubscriptableBaseModel):
152
152
  """
@@ -155,12 +155,12 @@ class FormX509Certificate(SubscriptableBaseModel):
155
155
  """
156
156
  name: str
157
157
  label: str
158
- default_value: Optional[str] = None
159
- required: bool = False
160
- depends_on: Optional[str] = None
161
- help_text: str = ""
158
+ default_value: Optional[str] = Field(default=None)
159
+ required: bool = Field(default=False)
160
+ depends_on: Optional[str] = Field(default=None)
161
+ help_text: str = Field(default="")
162
162
  type: Literal["x509_certificate"] = "x509_certificate"
163
- secret: bool = True
163
+ secret: bool = Field(default=True)
164
164
 
165
165
  class FormGpgKeypair(SubscriptableBaseModel):
166
166
  """
@@ -169,21 +169,21 @@ class FormGpgKeypair(SubscriptableBaseModel):
169
169
 
170
170
  name: str
171
171
  label: str
172
- default_value: Optional[str] = None
173
- required: bool = False
174
- depends_on: Optional[str] = None
175
- help_text: str = ""
172
+ default_value: Optional[str] = Field(default=None)
173
+ required: bool = Field(default=False)
174
+ depends_on: Optional[str] = Field(default=None)
175
+ help_text: str = Field(default="")
176
176
  local_side: Literal["public", "private"] = "public"
177
177
  """
178
178
  The side of the keypair which belongs to Snowflake. This value will be stored as the secret value, and the other side
179
179
  can be copied/downloaded only during the connection process.
180
180
  """
181
- allow_user_provided: bool = True
181
+ allow_user_provided: bool = Field(default=True)
182
182
  """
183
183
  Allows the user to provide Snowflake's side of the keypair, for cases where one is generated on the outside
184
184
  """
185
185
  type: Literal["gpg_keypair"] = "gpg_keypair"
186
- secret: bool = True
186
+ secret: bool = Field(default=True)
187
187
 
188
188
 
189
189
  class FormCheckboxField(SubscriptableBaseModel):
@@ -193,12 +193,12 @@ class FormCheckboxField(SubscriptableBaseModel):
193
193
 
194
194
  name: str
195
195
  label: str
196
- default_value: bool = False
197
- required: bool = False
198
- secret: bool = False
199
- depends_on: Optional[str] = None
200
- help_text: str = ""
201
- reload_on_change: bool = False
196
+ default_value: bool = Field(default=False)
197
+ required: bool = Field(default=False)
198
+ secret: bool = Field(default=False)
199
+ depends_on: Optional[str] = Field(default=None)
200
+ help_text: str = Field(default="")
201
+ reload_on_change: bool = Field(default=False)
202
202
  type: Literal["checkbox"] = "checkbox"
203
203
 
204
204
 
@@ -209,17 +209,17 @@ class FormSliderField(SubscriptableBaseModel):
209
209
 
210
210
  name: str
211
211
  label: str
212
- default_value: Optional[str] = None
213
- secret: bool = False
214
- required: bool = False
215
- depends_on: Optional[str] = None
216
- help_text: str = ""
217
- reload_on_change: bool = False
212
+ default_value: Optional[str] = Field(default=None)
213
+ secret: bool = Field(default=False)
214
+ required: bool = Field(default=False)
215
+ depends_on: Optional[str] = Field(default=None)
216
+ help_text: str = Field(default="")
217
+ reload_on_change: bool = Field(default=False)
218
218
  type: Literal["slider"] = "slider"
219
219
 
220
- min_value: int = 0
221
- max_value: int = 100
222
- step_size: int = 1
220
+ min_value: int = Field(default=0)
221
+ max_value: int = Field(default=100)
222
+ step_size: int = Field(default=1)
223
223
 
224
224
 
225
225
  class FormJinjaTemplate(SubscriptableBaseModel):
@@ -229,7 +229,7 @@ class FormJinjaTemplate(SubscriptableBaseModel):
229
229
 
230
230
  mapper_type: Literal["jinja_template"] = "jinja_template"
231
231
  label: str = "Jinja Template"
232
- depends_on: Optional[str] = None
232
+ depends_on: Optional[str] = Field(default=None)
233
233
 
234
234
 
235
235
  # ----------------------------------------------------------------------------
@@ -249,7 +249,7 @@ class StaticFormOptionsDataSource(SubscriptableBaseModel):
249
249
  """
250
250
 
251
251
  values: List[FormOption] = Field(default_factory=list)
252
- new_option_creator: Optional[NewOptionCreator] = None
252
+ new_option_creator: Optional[NewOptionCreator] = Field(default=None)
253
253
  type: Literal["static"] = "static"
254
254
 
255
255
 
@@ -261,7 +261,7 @@ class DynamicFormOptionsDataSource(SubscriptableBaseModel):
261
261
  source_function: Union[
262
262
  Callable[[SyncConfigurationParameters], List[FormOption]], str
263
263
  ]
264
- new_option_creator: Optional[NewOptionCreator] = None
264
+ new_option_creator: Optional[NewOptionCreator] = Field(default=None)
265
265
  type: Literal["dynamic"] = "dynamic"
266
266
 
267
267
  @validator("source_function", always=True)
@@ -299,12 +299,12 @@ class FormRadioField(FormFieldWithDataSource, BaseModel):
299
299
 
300
300
  name: str
301
301
  label: str
302
- default_value: Optional[str] = None
303
- required: bool = False
304
- secret: bool = False
305
- depends_on: Optional[str] = None
306
- help_text: str = ""
307
- reload_on_change: bool = False
302
+ default_value: Optional[str] = Field(default=None)
303
+ required: bool = Field(default=False)
304
+ secret: bool = Field(default=False)
305
+ depends_on: Optional[str] = Field(default=None)
306
+ help_text: str = Field(default="")
307
+ reload_on_change: bool = Field(default=False)
308
308
  type: Literal["radio"] = "radio"
309
309
 
310
310
 
@@ -316,15 +316,15 @@ class FormDropdownField(FormFieldWithDataSource, BaseModel):
316
316
 
317
317
  name: str
318
318
  label: str
319
- default_value: Optional[str] = None
320
- required: bool = False
321
- secret: bool = False
322
- depends_on: Optional[str] = None
323
- help_text: str = ""
324
- reload_on_change: bool = False
319
+ default_value: Optional[str] = Field(default=None)
320
+ required: bool = Field(default=False)
321
+ secret: bool = Field(default=False)
322
+ depends_on: Optional[str] = Field(default=None)
323
+ help_text: str = Field(default="")
324
+ reload_on_change: bool = Field(default=False)
325
325
  type: Literal["dropdown"] = "dropdown"
326
326
 
327
- multi_select: bool = False
327
+ multi_select: bool = Field(default=False)
328
328
 
329
329
 
330
330
  FormFieldBase = Annotated[
@@ -374,7 +374,7 @@ class NewOptionCreator(SubscriptableBaseModel):
374
374
  construct_form_option: Union[
375
375
  Callable[[StoredConfigurationValue], FormOption], str
376
376
  ]
377
- allow_create: bool = True
377
+ allow_create: bool = Field(default=True)
378
378
 
379
379
  @validator("creation_form_function", always=True)
380
380
  def function_name_convertor(cls, v) -> str:
@@ -404,7 +404,7 @@ class FormFieldMappingSelector(FormFieldWithDataSource, BaseModel):
404
404
 
405
405
  mapper_type: Literal["field_mapping_selector"] = "field_mapping_selector"
406
406
  label: str = "Field Mappings"
407
- depends_on: Optional[str] = None
407
+ depends_on: Optional[str] = Field(default=None)
408
408
 
409
409
 
410
410
  Mapper = Annotated[
@@ -420,7 +420,7 @@ class OutboundSyncConfigurationForm(ConfigurationFormBase):
420
420
  to map Snowflake columns to app fields/payloads.
421
421
  """
422
422
 
423
- mapper: Optional[Mapper] = None
423
+ mapper: Optional[Mapper] = Field(default=None)
424
424
 
425
425
 
426
426
  class InboundSyncConfigurationForm(ConfigurationFormBase):
@@ -436,24 +436,24 @@ class SecurityIntegrationTemplateAuthorizationCode(BaseModel):
436
436
  Provides values used to populate a security integration instructions template, which
437
437
  in turn allows the customer to create an OAuth based secret object
438
438
  """
439
- oauth_docs_url: Optional[str] = None
439
+ oauth_docs_url: Optional[str] = Field(default=None)
440
440
  oauth_grant: Literal["authorization_code"] = "authorization_code"
441
- oauth_client_id: str = '<client id>'
442
- oauth_client_secret: str = '<client secret>'
443
- oauth_token_endpoint: str = '<token endpoint>'
444
- oauth_authorization_endpoint: str = '<authorization endpoint>'
445
- oauth_allowed_scopes: List[str] = []
441
+ oauth_client_id: str = Field(default='<client id>')
442
+ oauth_client_secret: str = Field(default='<client secret>')
443
+ oauth_token_endpoint: str = Field(default='<token endpoint>')
444
+ oauth_authorization_endpoint: str = Field(default='<authorization endpoint>')
445
+ oauth_allowed_scopes: List[str] = Field(default=[])
446
446
 
447
447
  class SecurityIntegrationTemplateClientCredentials(BaseModel):
448
448
  """
449
449
  Provides values used to populate a security integration instructions template, which
450
450
  in turn allows the customer to create an OAuth based secret object
451
451
  """
452
- oauth_docs_url: Optional[str] = None
452
+ oauth_docs_url: Optional[str] = Field(default=None)
453
453
  oauth_grant: Literal["client_credentials"] = "client_credentials"
454
- oauth_client_id: str = '<client id>'
455
- oauth_client_secret: str = '<client secret>'
456
- oauth_token_endpoint: str = '<token endpoint>'
454
+ oauth_client_id: str = Field(default='<client id>')
455
+ oauth_client_secret: str = Field(default='<client secret>')
456
+ oauth_token_endpoint: str = Field(default='<token endpoint>')
457
457
  oauth_allowed_scopes: List[str] = []
458
458
 
459
459
  SecurityIntegrationTemplate = Annotated[
@@ -465,7 +465,7 @@ class NGrokMTLSTunnel(SubscriptableBaseModel):
465
465
  """
466
466
  Designates a ConnectionMethod as connecting via an ngrok tunnel.
467
467
  """
468
- SupportEdgeTermination: bool = True
468
+ SupportEdgeTermination: bool = Field(default=True)
469
469
  post_tunnel_fields_function: Union[
470
470
  Callable[[ConnectionConfigurationParameters], List[FormFieldBase]], str
471
471
  ]
@@ -488,6 +488,6 @@ class ConnectionMethod(SubscriptableBaseModel):
488
488
 
489
489
  name: str
490
490
  fields: List[FormFieldBase]
491
- oauth_template: Optional[SecurityIntegrationTemplate] = None
492
- ngrok_tunnel_configuration: Optional[NGrokMTLSTunnel] = None
493
- description: str = ""
491
+ oauth_template: Optional[SecurityIntegrationTemplate] = Field(default=None)
492
+ ngrok_tunnel_configuration: Optional[NGrokMTLSTunnel] = Field(default=None)
493
+ description: str = Field(default="")
@@ -32,6 +32,7 @@ from .omnata_plugin import (
32
32
  OutboundSyncRequest,
33
33
  DeadlineReachedException,
34
34
  )
35
+ from pydantic import TypeAdapter
35
36
  from .rate_limiting import ApiLimits, RateLimitState
36
37
 
37
38
  # set the logger class to our custom logger so that pydantic errors are handled correctly
@@ -233,7 +234,7 @@ class PluginEntrypoint:
233
234
  stream_errors=omnata_log_handler.stream_global_errors,
234
235
  total_records_estimate=inbound_sync_request._total_records_estimate
235
236
  )
236
- return_dict["final_progress_update"] = final_progress_update.dict()
237
+ return_dict["final_progress_update"] = final_progress_update.model_dump()
237
238
  if inbound_sync_request.deadline_reached:
238
239
  # if we actually hit the deadline, this is flagged by the cancellation checking worker and the cancellation
239
240
  # token is set. We throw it here as an error since that's currently how it flows back to the engine with a DELAYED state
@@ -305,10 +306,10 @@ class PluginEntrypoint:
305
306
  )
306
307
  script_result = the_function(parameters)
307
308
  if isinstance(script_result, BaseModel):
308
- script_result = script_result.dict()
309
+ script_result = script_result.model_dump()
309
310
  elif isinstance(script_result, List):
310
311
  if len(script_result) > 0 and isinstance(script_result[0], BaseModel):
311
- script_result = [r.dict() for r in script_result]
312
+ script_result = [r.model_dump() for r in script_result]
312
313
  return script_result
313
314
 
314
315
  def inbound_list_streams(
@@ -341,10 +342,10 @@ class PluginEntrypoint:
341
342
 
342
343
  script_result = self._plugin_instance.inbound_stream_list(parameters)
343
344
  if isinstance(script_result, BaseModel):
344
- script_result = script_result.dict()
345
+ script_result = script_result.model_dump()
345
346
  elif isinstance(script_result, List):
346
347
  if len(script_result) > 0 and isinstance(script_result[0], BaseModel):
347
- script_result = [r.dict() for r in script_result]
348
+ script_result = [r.model_dump() for r in script_result]
348
349
  return script_result
349
350
 
350
351
 
@@ -365,17 +366,17 @@ class PluginEntrypoint:
365
366
  script_result = the_function(stored_value)
366
367
  if not isinstance(script_result, FormOption):
367
368
  raise ValueError(f"Expected a FormOption from function {function_name}, got {type(script_result)}")
368
- results.append(script_result.dict())
369
+ results.append(script_result.model_dump())
369
370
  return results
370
371
 
371
372
  def connection_form(self):
372
373
  logger.info("Entered connection_form method")
373
374
  form: List[ConnectionMethod] = self._plugin_instance.connection_form()
374
- return [f.dict() for f in form]
375
+ return [f.model_dump() for f in form]
375
376
 
376
377
  def create_billing_events(self, session, event_request: Dict):
377
378
  logger.info("Entered create_billing_events method")
378
- request = BillingEventRequest.model_validate(event_request)
379
+ request = TypeAdapter(BillingEventRequest).validate_python(event_request)
379
380
  events: List[SnowflakeBillingEvent] = self._plugin_instance.create_billing_events(
380
381
  request
381
382
  )
@@ -408,7 +409,7 @@ class PluginEntrypoint:
408
409
  logger.warn('Billing event creation failed due to running internally to Omnata')
409
410
  else:
410
411
  raise e
411
- return [e.dict() for e in events]
412
+ return [e.model_dump() for e in events]
412
413
 
413
414
  def get_secrets(
414
415
  self, oauth_secret_name: Optional[str], other_secrets_name: Optional[str]
@@ -461,7 +462,7 @@ class PluginEntrypoint:
461
462
  script_result = the_function(parameters)
462
463
  if isinstance(script_result, List):
463
464
  if len(script_result) > 0 and isinstance(script_result[0], BaseModel):
464
- script_result = [r.dict() for r in script_result]
465
+ script_result = [r.model_dump() for r in script_result]
465
466
  else:
466
467
  raise ValueError(f"Expected a List from function {function_name}, got {type(script_result)}")
467
468
  return script_result
@@ -531,7 +532,7 @@ class PluginEntrypoint:
531
532
  f"alter network rule {network_rule_name} set value_list = ({rule_values_string})"
532
533
  ).collect()
533
534
 
534
- return connect_response.dict()
535
+ return connect_response.model_dump()
535
536
 
536
537
  def api_limits(self,
537
538
  method:str,
@@ -564,7 +565,7 @@ class PluginEntrypoint:
564
565
  # There's a bit of parsing here that could possibly be done outside of the handler function, but this shouldn't be too expensive
565
566
  sync_parameters: Dict[str, StoredConfigurationValue] = TypeAdapter(
566
567
  Dict[str, StoredConfigurationValue]).validate_python(sync_parameters)
567
- field_mappings: StoredMappingValue = StoredMappingValue.model_validate(field_mappings)
568
+ field_mappings: StoredMappingValue = TypeAdapter(StoredMappingValue).validate_python(field_mappings)
568
569
  return self._plugin_instance.outbound_record_validator(
569
570
  sync_parameters, field_mappings, transformed_record, source_types
570
571
  )
@@ -178,10 +178,9 @@ 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
-
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
- )
181
+ # can't set this as a class variable because it's not serializable
182
+ # TODO: probably shouldn't mix models with functionality like this
183
+ _request_timestamps_lock: Optional[threading.Lock] = None
185
184
 
186
185
  @field_serializer('wait_until',when_used='always')
187
186
  def serialize_wait_until(self, value:Optional[datetime.datetime]) -> Optional[int]:
@@ -253,6 +252,8 @@ class RateLimitState(SubscriptableBaseModel):
253
252
  You only need to use this if your HTTP requests are not automatically being
254
253
  registered, which happens if http.client.HTTPConnection is not being used.
255
254
  """
255
+ if self._request_timestamps_lock is None:
256
+ self._request_timestamps_lock = threading.Lock()
256
257
  with self._request_timestamps_lock:
257
258
  append_time = datetime.datetime.now(datetime.timezone.utc)
258
259
  if self.previous_request_timestamps is None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omnata-plugin-runtime
3
- Version: 0.5.0a113
3
+ Version: 0.5.2
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
@@ -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=4eKYhw6_l-RUVUwNU5NlTpPwL7xZRs6VLaCKf8OIKuY,36420
4
+ omnata_plugin_runtime/forms.py,sha256=42o3DJnnxJ-W92pNaF5MuawvDPUK5O0azvn80HDxTZM,19744
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=JirYUbPBaN0UMh9t_uAHDdhaQZ7NUhdMJ11eHRKOoNY,29302
8
+ omnata_plugin_runtime/rate_limiting.py,sha256=DVQ_bc-mVLBkrU1PTns1MWXhHiLpSB5HkWCcdePtJ2A,25611
9
+ omnata_plugin_runtime-0.5.2.dist-info/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
10
+ omnata_plugin_runtime-0.5.2.dist-info/METADATA,sha256=RlhKCVUmdUudXbUqZTcZnN1n4Ta2tSQrc9Gt6Yh1yTY,1884
11
+ omnata_plugin_runtime-0.5.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
12
+ omnata_plugin_runtime-0.5.2.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=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.0a113.dist-info/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
10
- omnata_plugin_runtime-0.5.0a113.dist-info/METADATA,sha256=Y5WpUCj7G4AHMfwIkzlFqgk9OEHdesZ4tWREqMKfGYQ,1888
11
- omnata_plugin_runtime-0.5.0a113.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
12
- omnata_plugin_runtime-0.5.0a113.dist-info/RECORD,,