prophecy-libs 2.0.6.dev99__tar.gz → 2.0.8.dev0__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.
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/PKG-INFO +1 -1
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/config/config_base.py +202 -4
- prophecy-libs-2.0.8.dev0/prophecy/config/utils.py +624 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy_libs.egg-info/PKG-INFO +1 -1
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy_libs.egg-info/SOURCES.txt +0 -1
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/setup.py +1 -1
- prophecy-libs-2.0.6.dev99/prophecy/config/config_base_test.py +0 -321
- prophecy-libs-2.0.6.dev99/prophecy/config/utils.py +0 -114
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/README.md +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/config/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/dbxsless/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/dbxsless/dbx_serverless_helper.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/componentruns/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/componentruns/component_run_service.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/componentruns/component_runs_dao.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/evolutions/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/evolutions/delta_metrics_storage_initializer.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/evolutions/hive_parquet_storage_initializer.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/evolutions/metrics_storage_initializer.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/evolutions/models.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/evolutions/package.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/execution_metrics_handler.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/in_memory_store.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/interims/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/interims/delta_interims.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/interims/hive_parquet_interims.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/interims/interims_table.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/logging_spark_session.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/models.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/package.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/pipelineruns/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/pipelineruns/pipeline_run_service.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/pipelineruns/pipeline_runs_dao.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/schemas/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/schemas/em.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/schemas/external.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/utils/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/utils/common.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/utils/constants.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/utils/external.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/utils/interim_store.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/workflow_parser.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/executionmetrics/zip_file.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/jsonrpc/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/jsonrpc/models.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/libs/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/libs/uc_shared_utils.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/libs/utils.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/lookups/LookupsBase.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/lookups/LookupsNative.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/lookups/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/random_data_creator.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/streaming/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/streaming/delta_lake_utils.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/test/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/test/base_test_case.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/test/utils.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/udfs/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/udfs/rest_api_udf.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/udfs/sample_udf.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/udfs/scala_udf_wrapper.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/constants.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/data_profiler.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/datasampleloader.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/diff.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/__diff.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/_dill.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/_objects.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/_shims.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/detect.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/logger.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/objtypes.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/pointers.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/session.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/settings.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/source.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/dill/temp.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/__main__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/cli.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/config.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/custom_typing.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/decode/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/decode/codes.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/documentor.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/exceptions.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/factory.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/generator.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/address/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/address/en/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/address/en_US/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/date_time/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/date_time/en_US/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/internet/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/internet/en_US/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/misc/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/misc/en_US/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/person/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/person/en_US/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/phone_number/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/phone_number/en_US/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/python/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/providers/python/en_US/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/proxy.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/utils/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/utils/checksums.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/utils/datasets.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/utils/decorators.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/utils/distribution.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/utils/loading.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/faker/utils/text.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/functions.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/gems_utils.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/httpclient.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/initial_python_code.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/json_rpc_layer.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/metagem_utils.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/monitoring_utils.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/pipeline_monitoring.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/request_processor.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/secrets.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/synthetic_data_generator.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/transpiler/__init__.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/transpiler/abi_base.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/transpiler/abi_core_fcns.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/transpiler/abi_fcn_wrapper.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/transpiler/dataframe_fcns.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/transpiler/dml_schema.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/transpiler/fixed_file_schema.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy/utils/utils.py +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy_libs.egg-info/dependency_links.txt +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy_libs.egg-info/not-zip-safe +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy_libs.egg-info/requires.txt +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/prophecy_libs.egg-info/top_level.txt +0 -0
- {prophecy-libs-2.0.6.dev99 → prophecy-libs-2.0.8.dev0}/setup.cfg +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# WARNING - Do not add import * in this module
|
|
2
|
+
from pyhocon import ConfigFactory, ConfigTree
|
|
2
3
|
from pyspark import Row
|
|
3
4
|
from pyspark.sql import SparkSession
|
|
4
5
|
from functools import lru_cache
|
|
@@ -6,11 +7,68 @@ from datetime import datetime, date
|
|
|
6
7
|
import os
|
|
7
8
|
import logging
|
|
8
9
|
|
|
10
|
+
from prophecy.config.utils import ConfigurationRecord
|
|
11
|
+
|
|
9
12
|
logger = logging.getLogger(__name__)
|
|
10
13
|
|
|
11
14
|
is_serverless = bool(int(os.environ.get("DATABRICKS_SERVERLESS_MODE_ENABLED", "0")))
|
|
12
15
|
logger.info(f'is_serverless is {is_serverless}')
|
|
13
16
|
|
|
17
|
+
|
|
18
|
+
class ProjectConfig:
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def get_merged_values(base_values, overridden_values):
|
|
22
|
+
def to_plain_dict(obj):
|
|
23
|
+
if isinstance(obj, dict):
|
|
24
|
+
return {k: to_plain_dict(v) for k, v in obj.items()}
|
|
25
|
+
elif isinstance(obj, list):
|
|
26
|
+
return [to_plain_dict(i) for i in obj]
|
|
27
|
+
else:
|
|
28
|
+
return obj
|
|
29
|
+
conf1 = ConfigFactory.from_dict(base_values)
|
|
30
|
+
conf2 = ConfigFactory.from_dict(overridden_values)
|
|
31
|
+
|
|
32
|
+
# Merge using pyhocon's built-in merge
|
|
33
|
+
return to_plain_dict(ConfigTree.merge_configs(conf1, conf2).as_plain_ordered_dict())
|
|
34
|
+
|
|
35
|
+
@staticmethod
|
|
36
|
+
def get_resolved_project_config_values(project_config_values, overridden_values):
|
|
37
|
+
merged_values = ProjectConfig.get_merged_values(project_config_values, overridden_values)
|
|
38
|
+
# Override with pipeline config values for fields that are present in config_values
|
|
39
|
+
for field_name, field_value in merged_values.items():
|
|
40
|
+
if field_name not in project_config_values:
|
|
41
|
+
# Delete those fields which are not in project config
|
|
42
|
+
del merged_values[field_name]
|
|
43
|
+
return merged_values
|
|
44
|
+
|
|
45
|
+
def __init__(self, config_schema: ConfigurationRecord, config_values: dict):
|
|
46
|
+
"""
|
|
47
|
+
:param config_schema: The schema.json of ProjectConfig variables.
|
|
48
|
+
:param config_values: The final values as a dictionary. Same as <instance>.json.
|
|
49
|
+
"""
|
|
50
|
+
self.config_schema = config_schema
|
|
51
|
+
self.config_values = config_values
|
|
52
|
+
|
|
53
|
+
def with_pipeline_overrides(self, overridden_values: dict):
|
|
54
|
+
self.config_values = self.get_resolved_values(overridden_values)
|
|
55
|
+
return self
|
|
56
|
+
|
|
57
|
+
def get_resolved_values(self, overridden_values: dict):
|
|
58
|
+
"""
|
|
59
|
+
Resolve project configuration values by overriding project config values with pipeline config values
|
|
60
|
+
for fields that are present in config_values.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
overridden_values: The project config values (project config)
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
dict: Resolved configuration values where pipeline config overrides project config
|
|
67
|
+
for fields present in config_values, but project config values are kept
|
|
68
|
+
for fields not present in config_values
|
|
69
|
+
"""
|
|
70
|
+
return ProjectConfig.get_resolved_project_config_values(self.config_values, overridden_values)
|
|
71
|
+
|
|
14
72
|
class ConfigBase:
|
|
15
73
|
|
|
16
74
|
class SecretValue:
|
|
@@ -195,11 +253,15 @@ class ConfigBase:
|
|
|
195
253
|
else:
|
|
196
254
|
return self.generate_object(override, cls)
|
|
197
255
|
|
|
198
|
-
def generate_config_object(self, spark, value, cls):
|
|
256
|
+
def generate_config_object(self, spark, value, cls, project_config: ProjectConfig=None):
|
|
257
|
+
# `project_config` will only be passed for subgraphs. It won't be passed for normal records.
|
|
199
258
|
if isinstance(value, list):
|
|
200
259
|
return [self.generate_config_object(spark, x, cls) for x in value]
|
|
201
260
|
elif isinstance(value, dict):
|
|
202
|
-
|
|
261
|
+
# No need to worry whether the generated code of the pipeline has the `prophecy_project_config` argument
|
|
262
|
+
# mentioned or not. **kwargs is present in all the calls class's __init__ methods. This will prevent throwing
|
|
263
|
+
# any exception.
|
|
264
|
+
return cls(**{**{"prophecy_spark": spark, "prophecy_project_config": project_config}, **value})
|
|
203
265
|
return value
|
|
204
266
|
|
|
205
267
|
def get_secret_config_object(self, spark, default, override, cls):
|
|
@@ -210,11 +272,12 @@ class ConfigBase:
|
|
|
210
272
|
else:
|
|
211
273
|
return self.get_config_object(spark, default, override, cls)
|
|
212
274
|
|
|
213
|
-
def get_config_object(self, spark, default, override, cls):
|
|
275
|
+
def get_config_object(self, spark, default, override, cls, project_config: ProjectConfig=None):
|
|
276
|
+
# project_config will only be passed for Subgraphs. Won't be passed for normal records
|
|
214
277
|
if override == None:
|
|
215
278
|
return default
|
|
216
279
|
else:
|
|
217
|
-
return self.generate_config_object(spark, override, cls)
|
|
280
|
+
return self.generate_config_object(spark, override, cls, project_config)
|
|
218
281
|
|
|
219
282
|
def to_dict(self):
|
|
220
283
|
to_ignore = ["spark", "prophecy_spark", "jvm", "secret_manager"]
|
|
@@ -318,3 +381,138 @@ class ConfigBase:
|
|
|
318
381
|
else:
|
|
319
382
|
setattr(result, k, copy.deepcopy(v, memo))
|
|
320
383
|
return result
|
|
384
|
+
|
|
385
|
+
def add_config_fields(self, config_record, config_values: dict):
|
|
386
|
+
"""
|
|
387
|
+
Add configuration fields to this ConfigBase instance based on a ConfigurationRecord
|
|
388
|
+
and a dictionary of key-value pairs.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
config_record: ConfigurationRecord object defining the schema
|
|
392
|
+
config_values: Dictionary with field names as keys and their values
|
|
393
|
+
"""
|
|
394
|
+
from prophecy.config.utils import (
|
|
395
|
+
StringElement, IntElement, LongElement, ShortElement,
|
|
396
|
+
FloatElement, DoubleElement, BooleanElement, DateElement,
|
|
397
|
+
TimestampElement, ArrayElement, ConfigurationRecord, SecretElement,
|
|
398
|
+
EnumElement, LookupElement, ValueElement, TableNameElement,
|
|
399
|
+
ColumnNameElement, SparkColumnElement, SparkExpressionElement
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
def convert_value(value, data_element):
|
|
403
|
+
"""Convert a value based on the DataElement type."""
|
|
404
|
+
element_type = data_element.get_name()
|
|
405
|
+
|
|
406
|
+
if element_type == "string":
|
|
407
|
+
return str(value) if value is not None else None
|
|
408
|
+
elif element_type == "spark_column":
|
|
409
|
+
return str(value) if value is not None else None
|
|
410
|
+
elif element_type == "spark_expression":
|
|
411
|
+
return str(value) if value is not None else None
|
|
412
|
+
elif element_type == "int":
|
|
413
|
+
return self.get_int_value(value)
|
|
414
|
+
elif element_type == "long":
|
|
415
|
+
return self.get_int_value(value) # Python doesn't distinguish int/long
|
|
416
|
+
elif element_type == "short":
|
|
417
|
+
return self.get_int_value(value) # Python doesn't distinguish int/short
|
|
418
|
+
elif element_type == "float":
|
|
419
|
+
return self.get_float_value(value)
|
|
420
|
+
elif element_type == "double":
|
|
421
|
+
return self.get_float_value(value) # Python doesn't distinguish float/double
|
|
422
|
+
elif element_type == "boolean":
|
|
423
|
+
return self.get_bool_value(value)
|
|
424
|
+
elif element_type == "date":
|
|
425
|
+
return self.get_date_value(value)
|
|
426
|
+
elif element_type == "timestamp":
|
|
427
|
+
return self.get_timestamp_value(value)
|
|
428
|
+
elif element_type == "array":
|
|
429
|
+
if isinstance(value, list):
|
|
430
|
+
return [convert_value(item, data_element.element_type) for item in value]
|
|
431
|
+
else:
|
|
432
|
+
return value
|
|
433
|
+
elif element_type == "record":
|
|
434
|
+
if isinstance(value, dict):
|
|
435
|
+
# Create a nested ConfigBase instance for record types
|
|
436
|
+
nested_config = type('NestedConfig', (ConfigBase,), {})()
|
|
437
|
+
nested_config.add_config_fields(data_element, value)
|
|
438
|
+
return nested_config
|
|
439
|
+
else:
|
|
440
|
+
return value
|
|
441
|
+
elif element_type == "enum":
|
|
442
|
+
# For enum, validate that the value is in the allowed values
|
|
443
|
+
if value in data_element.values:
|
|
444
|
+
return value
|
|
445
|
+
else:
|
|
446
|
+
raise ValueError(f"Value '{value}' is not in allowed enum values: {data_element.values}")
|
|
447
|
+
elif element_type == "secret":
|
|
448
|
+
# For secrets, create a SecretValue instance
|
|
449
|
+
if isinstance(value, dict):
|
|
450
|
+
return self.SecretValue(**value)
|
|
451
|
+
else:
|
|
452
|
+
return value
|
|
453
|
+
else:
|
|
454
|
+
# For unknown types, return as-is
|
|
455
|
+
return value
|
|
456
|
+
|
|
457
|
+
def process_fields(fields, values_dict):
|
|
458
|
+
"""Process configuration fields recursively."""
|
|
459
|
+
for field in fields:
|
|
460
|
+
field_name = field.name
|
|
461
|
+
field_kind = field.kind
|
|
462
|
+
|
|
463
|
+
# Skip if field is not in the provided values and is optional
|
|
464
|
+
if field_name not in values_dict:
|
|
465
|
+
if field.optional:
|
|
466
|
+
continue
|
|
467
|
+
else:
|
|
468
|
+
raise ValueError(f"Required field '{field_name}' is missing from config values")
|
|
469
|
+
|
|
470
|
+
field_value = values_dict[field_name]
|
|
471
|
+
|
|
472
|
+
# Convert the value based on the field type
|
|
473
|
+
converted_value = convert_value(field_value, field_kind)
|
|
474
|
+
|
|
475
|
+
# Set the field on this ConfigBase instance
|
|
476
|
+
setattr(self, field_name, converted_value)
|
|
477
|
+
|
|
478
|
+
# Process the configuration record fields
|
|
479
|
+
if hasattr(config_record, 'fields'):
|
|
480
|
+
process_fields(config_record.fields, config_values)
|
|
481
|
+
else:
|
|
482
|
+
raise ValueError("ConfigurationRecord must have a 'fields' attribute")
|
|
483
|
+
|
|
484
|
+
def add_project_config(self, project_config: ProjectConfig, overridden_values: dict):
|
|
485
|
+
self.prophecy_project_config = project_config
|
|
486
|
+
if project_config is not None and hasattr(self, 'add_config_fields'):
|
|
487
|
+
# Merge project_config.config_values with overridden_values
|
|
488
|
+
# Start with project config values
|
|
489
|
+
merged_values = ProjectConfig.get_resolved_project_config_values(project_config.config_values, overridden_values)
|
|
490
|
+
# Call add_config_fields with the merged values
|
|
491
|
+
self.add_config_fields(project_config.config_schema, merged_values)
|
|
492
|
+
|
|
493
|
+
def add_project_config(self, overridden_values: dict):
|
|
494
|
+
# Assumption here is that the `prophecy_project_config` is already part of the class variable.
|
|
495
|
+
self.add_project_config(self.prophecy_project_config, overridden_values)
|
|
496
|
+
|
|
497
|
+
def update_project_conf_values(self, project_config: ProjectConfig, overridden_values):
|
|
498
|
+
if project_config is None:
|
|
499
|
+
return None
|
|
500
|
+
return project_config.with_pipeline_overrides(overridden_values)
|
|
501
|
+
|
|
502
|
+
def update_and_add_project_config(self, project_config: ProjectConfig=None, overridden_values: dict=None):
|
|
503
|
+
"""
|
|
504
|
+
This will merge the overridden values with the project config values and then assign the new values along with
|
|
505
|
+
schema to `prophecy_project_config`.
|
|
506
|
+
:param project_config:
|
|
507
|
+
:param overridden_values:
|
|
508
|
+
:return:
|
|
509
|
+
"""
|
|
510
|
+
self.prophecy_project_config = project_config
|
|
511
|
+
if project_config is not None:
|
|
512
|
+
if overridden_values is None:
|
|
513
|
+
self.add_config_fields(project_config.config_schema, config_values=project_config.config_values)
|
|
514
|
+
else:
|
|
515
|
+
# Merge project_config.config_values with overridden_values
|
|
516
|
+
# Start with project config values
|
|
517
|
+
merged_values = ProjectConfig.get_resolved_project_config_values(project_config.config_values, overridden_values)
|
|
518
|
+
self.add_config_fields(project_config.config_schema, merged_values)
|