omnata-plugin-runtime 0.5.7a148__tar.gz → 0.5.7a150__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omnata-plugin-runtime
3
- Version: 0.5.7a148
3
+ Version: 0.5.7a150
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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "omnata-plugin-runtime"
3
- version = "0.5.7-a148"
3
+ version = "0.5.7-a150"
4
4
  description = "Classes and common runtime components for building and running Omnata Plugins"
5
5
  authors = ["James Weakley <james.weakley@omnata.com>"]
6
6
  readme = "README.md"
@@ -2381,56 +2381,68 @@ def omnata_udtf(
2381
2381
  """
2382
2382
  def class_decorator(cls):
2383
2383
  # Get the original 'process' method from the class
2384
+ if not hasattr(cls, 'process'):
2385
+ raise ValueError("The class must have a 'process' method.")
2384
2386
  original_process = getattr(cls, 'process')
2385
2387
  sig = signature(original_process)
2386
2388
  function_params = sig.parameters
2387
- if len(function_params) < 2:
2388
- raise ValueError("The function must have the self parameter, plus at least the mandatory 'connection_parameters' parameter.")
2389
- # Ensure the first argument is mandatory and positional
2389
+ if len(function_params) < 1:
2390
+ raise ValueError("The 'process' function must have at least one parameter.")
2391
+
2390
2392
  first_param_name = list(function_params.keys())[0]
2391
-
2392
2393
  if first_param_name != 'self':
2393
- raise ValueError(f"The first argument should be 'self', instead it was '{first_param_name}'.")
2394
+ raise ValueError(f"The first argument for the 'process' function should be 'self', instead it was '{first_param_name}'.")
2394
2395
 
2395
- second_param_name = list(function_params.keys())[1]
2396
+ cls._is_omnata_udtf = True
2397
+ cls._omnata_udtf_name = name
2398
+ cls._omnata_udtf_description = description
2399
+ cls._omnata_udtf_params = params
2400
+ cls._omnata_udtf_result_columns = result_columns
2401
+ cls._omnata_udtf_expose_to_consumer = expose_to_consumer
2396
2402
 
2403
+ if not expose_to_consumer:
2404
+ # If not exposing to the consumer, there are no further requirements
2405
+ return cls
2406
+
2407
+ if len(function_params) < 2:
2408
+ raise ValueError("When exposing the udtf to consumers, the 'process' function must have the self parameter, plus at least the mandatory 'connection_parameters' parameter.")
2409
+ second_param_name = list(function_params.keys())[1]
2397
2410
  if second_param_name != 'connection_parameters':
2398
2411
  raise ValueError(f"The second argument should be 'connection_parameters', instead it was {second_param_name}.")
2399
-
2400
-
2401
2412
  if function_params[second_param_name].annotation != ConnectionConfigurationParameters:
2402
2413
  raise ValueError(f"The second argument must be a ConnectionConfigurationParameters, instead it was a {function_params[second_param_name].annotation}.")
2403
2414
 
2404
- @wraps(original_process)
2405
- def wrapped_process(self, connection_parameters, *args, **kwargs):
2406
- if connection_parameters is None:
2407
- raise ValueError("Connection not found")
2415
+ if params[0].name.upper() != 'CONNECTION_PARAMETERS':
2416
+ params_new = [SnowflakeFunctionParameter(
2417
+ name='CONNECTION_PARAMETERS',
2418
+ data_type='OBJECT',
2419
+ description='The connection object, obtained from calling PLUGIN.PLUGIN_CONNECTION.')] + params
2420
+ cls._omnata_udtf_params = params_new
2421
+ if len(params) != len(function_params) -1:
2422
+ raise ValueError(f"You must document all the parameters of the 'process' function in the @omnata_udtf decorator in the same order ('connection_parameters' will be included automatically).")
2408
2423
 
2424
+ @wraps(original_process)
2425
+ def wrapped_process(self, connection_parameter_arg, *args, **kwargs):
2426
+ if connection_parameter_arg is None:
2427
+ raise ValueError("Connection not found")
2428
+
2409
2429
  # convert the connection parameters dictionary to a ConnectionConfigurationParameters object which includes the real secrets
2410
- if 'other_secrets_name' in connection_parameters:
2430
+ if 'other_secrets_name' in connection_parameter_arg:
2411
2431
  # this is the new way, where the sync engine only passes the name of the secret
2412
2432
  oauth_secrets_name = None
2413
- if 'oauth_secret_name' in connection_parameters:
2414
- oauth_secrets_name = connection_parameters['oauth_secret_name']
2415
- del connection_parameters['oauth_secret_name']
2416
- result = get_secrets(oauth_secrets_name,connection_parameters['other_secrets_name'])
2417
- connection_parameters['connection_secrets'] = result
2418
- del connection_parameters['other_secrets_name']
2419
- parameters = ConnectionConfigurationParameters.model_validate(connection_parameters)
2420
- else:
2421
- # deprecated way, where the sync engine passes the secrets directly
2422
- parameters = ConnectionConfigurationParameters.model_validate(connection_parameters)
2433
+ if 'oauth_secret_name' in connection_parameter_arg:
2434
+ oauth_secrets_name = connection_parameter_arg['oauth_secret_name']
2435
+ del connection_parameter_arg['oauth_secret_name']
2436
+ result = get_secrets(oauth_secrets_name,connection_parameter_arg['other_secrets_name'])
2437
+ connection_parameter_arg['connection_secrets'] = result
2438
+ del connection_parameter_arg['other_secrets_name']
2439
+
2440
+ parameters = ConnectionConfigurationParameters.model_validate(connection_parameter_arg)
2423
2441
 
2424
2442
  # Pass the validated arguments to the function
2425
2443
  return original_process(self, parameters, *args, **kwargs)
2426
2444
  # Replace the original 'process' method with the wrapped version
2427
2445
  setattr(cls, 'process', wrapped_process)
2428
- cls._is_omnata_udtf = True
2429
- cls._omnata_udtf_name = name
2430
- cls._omnata_udtf_description = description
2431
- cls._omnata_udtf_params = params
2432
- cls._omnata_udtf_result_columns = result_columns
2433
- cls._omnata_udtf_expose_to_consumer = expose_to_consumer
2434
2446
  return cls
2435
2447
 
2436
2448
  return class_decorator
@@ -2457,9 +2469,7 @@ def find_udtf_classes(path:str = '.') -> List[PythonUDTFDefinition | JavaUDTFDef
2457
2469
  matching_classes.append(PythonUDTFDefinition(
2458
2470
  name=obj._omnata_udtf_name,
2459
2471
  description=obj._omnata_udtf_description,
2460
- params=[SnowflakeFunctionParameter(name='CONNECTION_PARAMETERS',
2461
- data_type='OBJECT',
2462
- description='The connection object, obtained from calling PLUGIN.PLUGIN_CONNECTION')]+obj._omnata_udtf_params,
2472
+ params=obj._omnata_udtf_params,
2463
2473
  result_columns=obj._omnata_udtf_result_columns,
2464
2474
  expose_to_consumer=obj._omnata_udtf_expose_to_consumer,
2465
2475
  handler=obj.__module__+'.'+obj.__name__
@@ -2477,11 +2487,22 @@ def omnata_udf(
2477
2487
  result_data_type: str,
2478
2488
  expose_to_consumer: bool):
2479
2489
  """
2480
- A decorator for a function which should be automatically exposed to the consumer as a UDF
2490
+ A decorator for a function which will be created in the native application.
2481
2491
  """
2482
2492
  def decorator(func):
2483
2493
  sig = signature(func)
2484
2494
  function_params = sig.parameters
2495
+
2496
+ if not expose_to_consumer:
2497
+ # If not exposing to the consumer, there are no further requirements
2498
+ func._is_omnata_udf = True
2499
+ func._omnata_udf_name = name
2500
+ func._omnata_udf_description = description
2501
+ func._omnata_udf_params = params
2502
+ func._omnata_udf_result_data_type = result_data_type
2503
+ func._omnata_udf_expose_to_consumer = expose_to_consumer
2504
+ return func
2505
+
2485
2506
  if len(function_params) == 0:
2486
2507
  raise ValueError("The function must have at least one parameter.")
2487
2508
  # Ensure the first argument is mandatory and positional
@@ -2490,27 +2511,29 @@ def omnata_udf(
2490
2511
  raise ValueError(f"The first argument should be 'connection_parameters', instead it was '{first_param_name}'.")
2491
2512
  if function_params[first_param_name].annotation != ConnectionConfigurationParameters:
2492
2513
  raise ValueError(f"The first argument must be a ConnectionConfigurationParameters, instead it was a {function_params[first_param_name].annotation}.")
2514
+ if params[0].name.upper() != 'CONNECTION_PARAMETERS':
2515
+ params_new = [SnowflakeFunctionParameter(
2516
+ name='CONNECTION_PARAMETERS',
2517
+ data_type='OBJECT',
2518
+ description='The connection object, obtained from calling PLUGIN.PLUGIN_CONNECTION.')] + params
2519
+ func._omnata_udf_params = params_new
2520
+ if len(params_new) != len(function_params):
2521
+ raise ValueError(f"You must document all the parameters of the function in the @omnata_udf decorator in the same order ('connection_parameters' will be included automatically).")
2493
2522
 
2494
2523
  @wraps(func)
2495
- def wrapper(self, connection_parameters, *args, **kwargs):
2496
- if connection_parameters is None:
2497
- raise ValueError("Connection not found")
2498
-
2499
-
2524
+ def wrapper(connection_parameter_arg, *args, **kwargs):
2500
2525
  # convert the connection parameters dictionary to a ConnectionConfigurationParameters object which includes the real secrets
2501
- if 'other_secrets_name' in connection_parameters:
2526
+ if 'other_secrets_name' in connection_parameter_arg:
2502
2527
  # this is the new way, where the sync engine only passes the name of the secret
2503
2528
  oauth_secrets_name = None
2504
- if 'oauth_secret_name' in connection_parameters:
2505
- oauth_secrets_name = connection_parameters['oauth_secret_name']
2506
- del connection_parameters['oauth_secret_name']
2507
- result = get_secrets(oauth_secrets_name,connection_parameters['other_secrets_name'])
2508
- connection_parameters['connection_secrets'] = result
2509
- del connection_parameters['other_secrets_name']
2510
- parameters = ConnectionConfigurationParameters.model_validate(connection_parameters)
2511
- else:
2512
- # deprecated way, where the sync engine passes the secrets directly
2513
- parameters = ConnectionConfigurationParameters.model_validate(connection_parameters)
2529
+ if 'oauth_secret_name' in connection_parameter_arg:
2530
+ oauth_secrets_name = connection_parameter_arg['oauth_secret_name']
2531
+ del connection_parameter_arg['oauth_secret_name']
2532
+ result = get_secrets(oauth_secrets_name,connection_parameter_arg['other_secrets_name'])
2533
+ connection_parameter_arg['connection_secrets'] = result
2534
+ del connection_parameter_arg['other_secrets_name']
2535
+
2536
+ parameters = ConnectionConfigurationParameters.model_validate(connection_parameter_arg)
2514
2537
 
2515
2538
  # Pass the validated arguments to the function
2516
2539
  return func(parameters, *args, **kwargs)
@@ -2547,9 +2570,7 @@ def find_udf_functions(path:str = '.') -> List[PythonUDFDefinition | JavaUDFDefi
2547
2570
  matching_classes.append(PythonUDFDefinition(
2548
2571
  name=obj._omnata_udf_name,
2549
2572
  description=obj._omnata_udf_description,
2550
- params=[SnowflakeFunctionParameter(name='CONNECTION_PARAMETERS',
2551
- data_type='OBJECT',
2552
- description='The connection object, obtained from calling PLUGIN.PLUGIN_CONNECTION')] + obj._omnata_udf_params,
2573
+ params=obj._omnata_udf_params,
2553
2574
  result_data_type=obj._omnata_udf_result_data_type,
2554
2575
  expose_to_consumer=obj._omnata_udf_expose_to_consumer,
2555
2576
  packages=[],