omnata-plugin-runtime 0.5.7a129__tar.gz → 0.5.7a131__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/PKG-INFO +1 -1
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/pyproject.toml +1 -1
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/omnata_plugin.py +87 -1
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/LICENSE +0 -0
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/README.md +0 -0
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/__init__.py +0 -0
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/api.py +0 -0
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/configuration.py +0 -0
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/forms.py +0 -0
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/logging.py +0 -0
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/plugin_entrypoints.py +0 -0
- {omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/rate_limiting.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "omnata-plugin-runtime"
|
3
|
-
version = "0.5.7-
|
3
|
+
version = "0.5.7-a131"
|
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"
|
@@ -23,6 +23,11 @@ import threading
|
|
23
23
|
import time
|
24
24
|
import hashlib
|
25
25
|
import requests
|
26
|
+
import pkgutil
|
27
|
+
import inspect
|
28
|
+
import importlib
|
29
|
+
import sys
|
30
|
+
import os
|
26
31
|
from abc import ABC, abstractmethod
|
27
32
|
from decimal import Decimal
|
28
33
|
from functools import partial, wraps, reduce
|
@@ -2226,6 +2231,7 @@ def get_nested_value(nested_dict:Dict, keys:List[str]):
|
|
2226
2231
|
def consumer_udtf(param_docs: Dict[str, Dict[str, Any]]):
|
2227
2232
|
def class_decorator(cls):
|
2228
2233
|
# Get the original 'process' method from the class
|
2234
|
+
cls._is_omnata_consumer_udtf = True
|
2229
2235
|
original_process = getattr(cls, 'process')
|
2230
2236
|
sig = signature(original_process)
|
2231
2237
|
params = sig.parameters
|
@@ -2241,7 +2247,7 @@ def consumer_udtf(param_docs: Dict[str, Dict[str, Any]]):
|
|
2241
2247
|
fields = {
|
2242
2248
|
name: (param.annotation, param_docs.get(name, {}).get("default", param.default))
|
2243
2249
|
for name, param in params.items()
|
2244
|
-
if name != '
|
2250
|
+
if name != 'cls' and name != 'connection_parameters'
|
2245
2251
|
}
|
2246
2252
|
|
2247
2253
|
DynamicModel = create_model('DynamicModel', **fields)
|
@@ -2292,3 +2298,83 @@ def consumer_udtf(param_docs: Dict[str, Dict[str, Any]]):
|
|
2292
2298
|
|
2293
2299
|
return class_decorator
|
2294
2300
|
|
2301
|
+
def find_classes_with_attribute(attribute_name: str,path:str = '.'):
|
2302
|
+
# Get the directory's absolute path
|
2303
|
+
current_dir = os.path.abspath(path)
|
2304
|
+
|
2305
|
+
# List to hold the classes that match the attribute
|
2306
|
+
matching_classes = []
|
2307
|
+
|
2308
|
+
# Iterate over all modules in the current directory
|
2309
|
+
for _, module_name, _ in pkgutil.iter_modules([current_dir]):
|
2310
|
+
# Import the module
|
2311
|
+
module = importlib.import_module(module_name)
|
2312
|
+
|
2313
|
+
# Iterate over all members of the module
|
2314
|
+
for name, obj in inspect.getmembers(module, inspect.isclass):
|
2315
|
+
# Check if the class has the specified attribute
|
2316
|
+
if hasattr(obj, attribute_name):
|
2317
|
+
matching_classes.append(obj)
|
2318
|
+
|
2319
|
+
|
2320
|
+
def consumer_udf(param_docs: Dict[str, Dict[str, Any]]):
|
2321
|
+
def decorator(func):
|
2322
|
+
sig = signature(func)
|
2323
|
+
params = sig.parameters
|
2324
|
+
|
2325
|
+
# Ensure the first argument is mandatory and positional
|
2326
|
+
if list(params.keys())[0] != 'connection_parameters':
|
2327
|
+
raise ValueError("The first argument should be 'connection_parameters'.")
|
2328
|
+
|
2329
|
+
# Create a Pydantic model based on the function signature and the provided documentation
|
2330
|
+
fields = {
|
2331
|
+
name: (param.annotation, param_docs.get(name, {}).get("default", param.default))
|
2332
|
+
for name, param in params.items()
|
2333
|
+
if name != 'connection_parameters'
|
2334
|
+
}
|
2335
|
+
|
2336
|
+
DynamicModel = create_model('DynamicModel', **fields)
|
2337
|
+
|
2338
|
+
# Attach the documentation to the function
|
2339
|
+
func.__doc__ = func.__doc__ or ""
|
2340
|
+
func.__doc__ += "\n\nArgs:\n"
|
2341
|
+
for name, param in params.items():
|
2342
|
+
doc = param_docs.get(name, {})
|
2343
|
+
func.__doc__ += f" {name} ({param.annotation.__name__}): {doc.get('description', 'No description provided.')}\n"
|
2344
|
+
|
2345
|
+
@wraps(func)
|
2346
|
+
def wrapper(self, connection_parameters, *args, **kwargs):
|
2347
|
+
if connection_parameters is None:
|
2348
|
+
raise ValueError("Connection not found")
|
2349
|
+
|
2350
|
+
if not isinstance(connection_parameters, Dict):
|
2351
|
+
raise ValueError("The first argument must be an object, the result of calling PLUGIN_CONNECTION.")
|
2352
|
+
|
2353
|
+
try:
|
2354
|
+
# Validate the arguments using the dynamic Pydantic model
|
2355
|
+
validated_args = DynamicModel(**kwargs)
|
2356
|
+
except ValidationError as e:
|
2357
|
+
raise ValueError(f"Argument validation error: {e}")
|
2358
|
+
|
2359
|
+
# convert the connection parameters dictionary to a ConnectionConfigurationParameters object which includes the real secrets
|
2360
|
+
if 'other_secrets_name' in connection_parameters:
|
2361
|
+
# this is the new way, where the sync engine only passes the name of the secret
|
2362
|
+
oauth_secrets_name = None
|
2363
|
+
if 'oauth_secret_name' in connection_parameters:
|
2364
|
+
oauth_secrets_name = connection_parameters['oauth_secret_name']
|
2365
|
+
del connection_parameters['oauth_secret_name']
|
2366
|
+
result = get_secrets(oauth_secrets_name,connection_parameters['other_secrets_name'])
|
2367
|
+
connection_parameters['connection_secrets'] = result
|
2368
|
+
del connection_parameters['other_secrets_name']
|
2369
|
+
parameters = ConnectionConfigurationParameters.model_validate(connection_parameters)
|
2370
|
+
else:
|
2371
|
+
# deprecated way, where the sync engine passes the secrets directly
|
2372
|
+
parameters = ConnectionConfigurationParameters.model_validate(connection_parameters)
|
2373
|
+
|
2374
|
+
# Pass the validated arguments to the function
|
2375
|
+
return func(parameters, *args, **validated_args.dict())
|
2376
|
+
|
2377
|
+
wrapper._is_omnata_consumer_udf = True
|
2378
|
+
return wrapper
|
2379
|
+
|
2380
|
+
return decorator
|
File without changes
|
File without changes
|
File without changes
|
{omnata_plugin_runtime-0.5.7a129 → omnata_plugin_runtime-0.5.7a131}/src/omnata_plugin_runtime/api.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|