omnata-plugin-runtime 0.5.7a132__tar.gz → 0.5.7a134__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omnata-plugin-runtime
3
- Version: 0.5.7a132
3
+ Version: 0.5.7a134
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-a132"
3
+ version = "0.5.7-a134"
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"
@@ -38,6 +38,7 @@ import jinja2
38
38
  import pandas
39
39
  from pydantic_core import to_jsonable_python
40
40
  from pydantic import Field, TypeAdapter, ValidationError, create_model, root_validator, BaseModel
41
+ from pydantic.dataclasses import dataclass
41
42
  from dateutil.parser import parse
42
43
  from jinja2 import Environment
43
44
  from snowflake.connector.pandas_tools import write_pandas
@@ -2228,7 +2229,25 @@ def get_nested_value(nested_dict:Dict, keys:List[str]):
2228
2229
  keys = [keys]
2229
2230
  return reduce(lambda d, key: d.get(key) if isinstance(d, dict) else None, keys, nested_dict)
2230
2231
 
2231
- def consumer_udtf(param_docs: Dict[str, Dict[str, Any]]):
2232
+
2233
+ @dataclass
2234
+ class SnowflakeFunctionParameter:
2235
+ arg_name: str
2236
+ description: str
2237
+ arg_data_type: str
2238
+ has_default_value: bool = False
2239
+ default_value_clause: Optional[str] = None
2240
+
2241
+ @dataclass
2242
+ class SnowflakeUDTFResultColumn:
2243
+ column_name: str
2244
+ column_data_type: str
2245
+ description: str
2246
+
2247
+ def consumer_udtf(
2248
+ description: str,
2249
+ params: List[SnowflakeFunctionParameter],
2250
+ result_columns: List[SnowflakeUDTFResultColumn]):
2232
2251
  def class_decorator(cls):
2233
2252
  # Get the original 'process' method from the class
2234
2253
  cls._is_omnata_consumer_udtf = True
@@ -2242,21 +2261,14 @@ def consumer_udtf(param_docs: Dict[str, Dict[str, Any]]):
2242
2261
 
2243
2262
  if list(params.keys())[1] != 'connection_parameters':
2244
2263
  raise ValueError("The second argument should be 'connection_parameters'.")
2245
-
2246
- # Create a Pydantic model based on the function signature and the provided documentation
2247
- fields = {
2248
- name: (param.annotation, param_docs.get(name, {}).get("default", param.default))
2249
- for name, param in params.items()
2250
- if name != 'cls' and name != 'connection_parameters'
2251
- }
2264
+
2265
+ if params[list(params.keys())[1]].annotation != Dict:
2266
+ raise ValueError("The second argument must be a dict.")
2252
2267
 
2253
2268
  @wraps(original_process)
2254
2269
  def wrapped_process(self, connection_parameters, *args, **kwargs):
2255
2270
  if connection_parameters is None:
2256
2271
  raise ValueError("Connection not found")
2257
-
2258
- if not isinstance(connection_parameters, Dict):
2259
- raise ValueError("The first argument must be an object, the result of calling PLUGIN_CONNECTION.")
2260
2272
 
2261
2273
  # convert the connection parameters dictionary to a ConnectionConfigurationParameters object which includes the real secrets
2262
2274
  if 'other_secrets_name' in connection_parameters:
@@ -2282,7 +2294,7 @@ def consumer_udtf(param_docs: Dict[str, Dict[str, Any]]):
2282
2294
 
2283
2295
  return class_decorator
2284
2296
 
2285
- def find_classes_with_attribute(attribute_name: str,path:str = '.'):
2297
+ def find_consumer_udtf_classes(path:str = '.'):
2286
2298
  # Get the directory's absolute path
2287
2299
  current_dir = os.path.abspath(path)
2288
2300
 
@@ -2297,11 +2309,15 @@ def find_classes_with_attribute(attribute_name: str,path:str = '.'):
2297
2309
  # Iterate over all members of the module
2298
2310
  for name, obj in inspect.getmembers(module, inspect.isclass):
2299
2311
  # Check if the class has the specified attribute
2300
- if hasattr(obj, attribute_name):
2312
+ if hasattr(obj, '_is_omnata_consumer_udtf'):
2301
2313
  matching_classes.append(obj)
2314
+ return matching_classes
2302
2315
 
2303
2316
 
2304
- def consumer_udf(param_docs: Dict[str, Dict[str, Any]]):
2317
+ def consumer_udf(
2318
+ description: str,
2319
+ params: List[SnowflakeFunctionParameter],
2320
+ result_data_type: str):
2305
2321
  def decorator(func):
2306
2322
  sig = signature(func)
2307
2323
  params = sig.parameters
@@ -2309,14 +2325,14 @@ def consumer_udf(param_docs: Dict[str, Dict[str, Any]]):
2309
2325
  # Ensure the first argument is mandatory and positional
2310
2326
  if list(params.keys())[0] != 'connection_parameters':
2311
2327
  raise ValueError("The first argument should be 'connection_parameters'.")
2328
+ if params[list(params.keys())[0]].annotation != Dict:
2329
+ raise ValueError("The first argument must be a dict.")
2312
2330
 
2313
2331
  @wraps(func)
2314
2332
  def wrapper(self, connection_parameters, *args, **kwargs):
2315
2333
  if connection_parameters is None:
2316
2334
  raise ValueError("Connection not found")
2317
2335
 
2318
- if not isinstance(connection_parameters, Dict):
2319
- raise ValueError("The first argument must be an object, the result of calling PLUGIN_CONNECTION.")
2320
2336
 
2321
2337
  # convert the connection parameters dictionary to a ConnectionConfigurationParameters object which includes the real secrets
2322
2338
  if 'other_secrets_name' in connection_parameters:
@@ -2340,3 +2356,23 @@ def consumer_udf(param_docs: Dict[str, Dict[str, Any]]):
2340
2356
  return wrapper
2341
2357
 
2342
2358
  return decorator
2359
+
2360
+ def find_consumer_udf_functions(path:str = '.'):
2361
+ # Get the current directory's absolute path
2362
+ current_dir = os.path.abspath(path)
2363
+
2364
+ # List to hold the classes that match the attribute
2365
+ matching_classes = []
2366
+
2367
+ # Iterate over all modules in the current directory
2368
+ for _, module_name, _ in pkgutil.iter_modules([current_dir]):
2369
+ # Import the module
2370
+ module = importlib.import_module(module_name)
2371
+
2372
+ # Iterate over all members of the module
2373
+ for name, obj in inspect.getmembers(module, inspect.isfunction):
2374
+ # Check if the class has the specified attribute
2375
+ if hasattr(obj, '_is_omnata_consumer_udf'):
2376
+ matching_classes.append(obj)
2377
+
2378
+ return matching_classes