* checkout from alex/cac * checkout from alex/cac * checkout from alex/cac * checkout from alex/cac * Add missing tests * Add missing files * Add missing tests * add missing file * missing file * missing file * sengrid low code connector * rename * doc * doc * remove broken test * rename * jinja dependency * Add comment * comment * comment * pyjq dependency * update import * rename file * delete unused file * Revert "delete unused file" This reverts commit758e939367. * fix * rename * abstract property * delete unused field * delete unused field * rename * pass kwargs directly * isort * Revert "isort" This reverts commit4a79223944. * isort * update state * fix imports * update * update dependency * remove dead code * remove dead code * format * rename file * decoder * Use decoder * Update comment * dict_state is actually backed by a dict * Add a comment * update state takes kwargs * move state out of offset paginator * fix * update jq parameter order * fix * pass config * update * update * remove incremental mixin * delete comment * start workin on yaml parser * fix test * progress * refer and overwrite partials * factory tests pass * fix * reset * Assert http_method is an enum value * fix auth * read lists works * fix test * comment * implement all streams * build connection checker * update comments * update comments * remove no_state * rename package * checkout from alex/cac * Add missing tests * Add missing files * missing file * rename * jinja dependency * Add comment * comment * comment * Revert "delete unused file" This reverts commit758e939367. * delete unused field * delete unused field * rename * pass kwargs directly * isort * Revert "isort" This reverts commit4a79223944. * format * decoder * better error handling * remove nostate * isort * remove print * move test * delete duplicates * update * delete dead code * Update mapping type to [str, Any] * add comment * Add comment * pass parameters through kwargs * pass parameters through kwargs * fix test * update interface * update interface to pass source in interface * update interface to pass source in interface * rename to stream_slicer * Allow passing a string or an enum * Define StateType enum * unit tests pass * update dict state * update * can read * fix test * fix from yaml update * elif * convert state_type if not of type type * convert state_type if not of type type * Add a test * Low code connectors: string interpolation with jinja (#12852) * checkout from alex/cac * Add missing tests * Add missing files * missing file * rename * jinja dependency * Add comment * comment * comment * Revert "delete unused file" This reverts commit758e939367. * delete unused field * delete unused field * rename * pass kwargs directly * isort * Revert "isort" This reverts commit4a79223944. * format * decoder * better error handling * remove nostate * isort * delete dead code * Update mapping type to [str, Any] * add comment * Add comment * pass parameters through kwargs * move test to right module * Add missing test * Use authbase instead of deprecated class * leverage generator * remove sendgrid specific code * update * update * delete comment * remove sendgrid specific file * remove unused file * Delete dead code * rename methods * rename to declarative * rename the classes too * select streams to check * nit * rename method * rename class * {} is faster than dict() * Update airbyte-cdk/python/airbyte_cdk/sources/declarative/parsers/yaml_parser.py Co-authored-by: Sherif A. Nada <snadalive@gmail.com> * more precise exception * rename class * add comment * Try to install packages to build jq * isort * only automake * Revert "only automake" This reverts commitc8fe154ffc. * remove git * rename file * create components in kwargs * Use tuple of strings * parser doesn't need to be stored * move file and delete duplicates * Revert "Use tuple of strings" This reverts commitab5a7afd08. * raise error if streams to check are not in the catalog * Revert "Revert "Use tuple of strings"" This reverts commit7c9fb8eb33. * traverse tree * rename to options * move docstring * Update airbyte-cdk/python/airbyte_cdk/sources/declarative/checks/check_stream.py Co-authored-by: Sherif A. Nada <snadalive@gmail.com> * fix tests and format * format * update * better error message * Add jq dependency * Use request header provider * rename * rename field * remove get_context method * rename * add a comment * format Co-authored-by: Sherif A. Nada <snadalive@gmail.com>
84 lines
3.0 KiB
Python
84 lines
3.0 KiB
Python
#
|
|
# Copyright (c) 2022 Airbyte, Inc., all rights reserved.
|
|
#
|
|
|
|
import inspect
|
|
|
|
from airbyte_cdk.sources.declarative.interpolation.interpolated_mapping import InterpolatedMapping
|
|
from airbyte_cdk.sources.declarative.interpolation.jinja import JinjaInterpolation
|
|
|
|
"""
|
|
Create a partial on steroids.
|
|
Returns a partial object which when called will behave like func called with the arguments supplied.
|
|
Parameters will be interpolated before the creation of the object
|
|
The interpolation will take in kwargs, and config as parameters that can be accessed through interpolating.
|
|
If any of the parameters are also create functions, they will also be created.
|
|
kwargs are propagated to the recursive method calls
|
|
:param func: Function
|
|
:param args:
|
|
:param keywords:
|
|
:return: partially created object
|
|
"""
|
|
|
|
|
|
def create(func, /, *args, **keywords):
|
|
def newfunc(*fargs, **fkeywords):
|
|
interpolation = JinjaInterpolation()
|
|
all_keywords = {**keywords}
|
|
all_keywords.update(fkeywords)
|
|
|
|
# config is a special keyword used for interpolation
|
|
config = all_keywords.pop("config", None)
|
|
|
|
# options is a special keyword used for interpolation and propagation
|
|
if "options" in all_keywords:
|
|
options = all_keywords.pop("options")
|
|
else:
|
|
options = dict()
|
|
|
|
# create object's partial parameters
|
|
fully_created = _create_inner_objects(all_keywords, options)
|
|
|
|
# interpolate the parameters
|
|
interpolated_keywords = InterpolatedMapping(fully_created, interpolation).eval(config, **{"options": options})
|
|
interpolated_keywords = {k: v for k, v in interpolated_keywords.items() if v is not None}
|
|
|
|
all_keywords.update(interpolated_keywords)
|
|
|
|
# if config is not none, add it back to the keywords mapping
|
|
if config is not None:
|
|
all_keywords["config"] = config
|
|
|
|
kwargs_to_pass_down = _get_kwargs_to_pass_to_func(func, options)
|
|
all_keywords_to_pass_down = _get_kwargs_to_pass_to_func(func, all_keywords)
|
|
try:
|
|
ret = func(*args, *fargs, **{**all_keywords_to_pass_down, **kwargs_to_pass_down})
|
|
except TypeError as e:
|
|
raise Exception(f"failed to create object of type {func} because {e}")
|
|
return ret
|
|
|
|
newfunc.func = func
|
|
newfunc.args = args
|
|
newfunc.kwargs = keywords
|
|
|
|
return newfunc
|
|
|
|
|
|
def _get_kwargs_to_pass_to_func(func, kwargs):
|
|
argspec = inspect.getfullargspec(func)
|
|
kwargs_to_pass_down = set(argspec.kwonlyargs)
|
|
args_to_pass_down = set(argspec.args)
|
|
all_args = args_to_pass_down.union(kwargs_to_pass_down)
|
|
kwargs_to_pass_down = {k: v for k, v in kwargs.items() if k in all_args}
|
|
return kwargs_to_pass_down
|
|
|
|
|
|
def _create_inner_objects(keywords, kwargs):
|
|
fully_created = dict()
|
|
for k, v in keywords.items():
|
|
if type(v) == type(create):
|
|
fully_created[k] = v(kwargs=kwargs)
|
|
else:
|
|
fully_created[k] = v
|
|
return fully_created
|