2323from feathr .definition .settings import ObservationSettings
2424from feathr .definition .sink import Sink
2525from feathr .protobuf .featureValue_pb2 import FeatureValue
26- from feathr .registry .feature_registry import default_registry_client
2726from feathr .spark_provider ._databricks_submission import _FeathrDatabricksJobLauncher
2827from feathr .spark_provider ._localspark_submission import _FeathrLocalSparkJobLauncher
2928from feathr .spark_provider ._synapse_submission import _FeathrSynapseJobLauncher
3433from feathr .utils .feature_printer import FeaturePrinter
3534from feathr .utils .spark_job_params import FeatureGenerationJobParams , FeatureJoinJobParams
3635from feathr .definition .source import InputContext
36+ from azure .identity import DefaultAzureCredential
37+ from jinja2 import Template
38+ from loguru import logger
39+ from feathr .definition .config_helper import FeathrConfigHelper
40+ from pyhocon import ConfigFactory
41+ from feathr .registry ._feathr_registry_client import _FeatureRegistry
42+ from feathr .registry ._feature_registry_purview import _PurviewRegistry
3743from feathr .version import get_version
38-
3944class FeathrClient (object ):
4045 """Feathr client.
4146
@@ -170,10 +175,24 @@ def __init__(self, config_path:str = "./feathr_config.yaml", local_workspace_dir
170175
171176 self .secret_names = []
172177
173- # initialize registry
174- self .registry = default_registry_client ( self . project_name , config_path = config_path , credential = self . credential )
178+ # initialize config helper
179+ self .config_helper = FeathrConfigHelper ( )
175180
176- logger .info (f"Feathr Client { get_version ()} initialized successfully" )
181+ # initialize registry
182+ self .registry = None
183+ registry_endpoint = self .envutils .get_environment_variable_with_default ("feature_registry" , "api_endpoint" )
184+ azure_purview_name = self .envutils .get_environment_variable_with_default ('feature_registry' , 'purview' , 'purview_name' )
185+ if registry_endpoint :
186+ self .registry = _FeatureRegistry (self .project_name , endpoint = registry_endpoint , project_tags = project_registry_tag , credential = credential )
187+ elif azure_purview_name :
188+ registry_delimiter = self .envutils .get_environment_variable_with_default ('feature_registry' , 'purview' , 'delimiter' )
189+ # initialize the registry no matter whether we set purview name or not, given some of the methods are used there.
190+ self .registry = _PurviewRegistry (self .project_name , azure_purview_name , registry_delimiter , project_registry_tag , config_path = config_path , credential = credential )
191+ else :
192+ # no registry configured
193+ logger .info ("Feathr registry is not configured. Consider setting the Feathr registry component for richer feature store experience." )
194+
195+ logger .info (f"Feathr client { get_version ()} initialized successfully." )
177196
178197 def _check_required_environment_variables_exist (self ):
179198 """Checks if the required environment variables(form feathr_config.yaml) is set.
@@ -197,7 +216,7 @@ def register_features(self, from_context: bool = True):
197216 if from_context :
198217 # make sure those items are in `self`
199218 if 'anchor_list' in dir (self ) and 'derived_feature_list' in dir (self ):
200- self .registry .save_to_feature_config_from_context (self .anchor_list , self .derived_feature_list , self .local_workspace_dir )
219+ self .config_helper .save_to_feature_config_from_context (self .anchor_list , self .derived_feature_list , self .local_workspace_dir )
201220 self .registry .register_features (self .local_workspace_dir , from_context = from_context , anchor_list = self .anchor_list , derived_feature_list = self .derived_feature_list )
202221 else :
203222 raise RuntimeError ("Please call FeathrClient.build_features() first in order to register features" )
@@ -224,9 +243,8 @@ def build_features(self, anchor_list: List[FeatureAnchor] = [], derived_feature_
224243 else :
225244 source_names [anchor .source .name ] = anchor .source
226245
227- preprocessingPyudfManager = _PreprocessingPyudfManager ()
228246 _PreprocessingPyudfManager .build_anchor_preprocessing_metadata (anchor_list , self .local_workspace_dir )
229- self .registry .save_to_feature_config_from_context (anchor_list , derived_feature_list , self .local_workspace_dir )
247+ self .config_helper .save_to_feature_config_from_context (anchor_list , derived_feature_list , self .local_workspace_dir )
230248 self .anchor_list = anchor_list
231249 self .derived_feature_list = derived_feature_list
232250
@@ -470,7 +488,7 @@ def get_offline_features(self,
470488 # otherwise users will be confused on what are the available features
471489 # in build_features it will assign anchor_list and derived_feature_list variable, hence we are checking if those two variables exist to make sure the above condition is met
472490 if 'anchor_list' in dir (self ) and 'derived_feature_list' in dir (self ):
473- self .registry .save_to_feature_config_from_context (self .anchor_list , self .derived_feature_list , self .local_workspace_dir )
491+ self .config_helper .save_to_feature_config_from_context (self .anchor_list , self .derived_feature_list , self .local_workspace_dir )
474492 else :
475493 raise RuntimeError ("Please call FeathrClient.build_features() first in order to get offline features" )
476494
@@ -678,7 +696,7 @@ def materialize_features(self, settings: MaterializationSettings, execution_conf
678696 # otherwise users will be confused on what are the available features
679697 # in build_features it will assign anchor_list and derived_feature_list variable, hence we are checking if those two variables exist to make sure the above condition is met
680698 if 'anchor_list' in dir (self ) and 'derived_feature_list' in dir (self ):
681- self .registry .save_to_feature_config_from_context (self .anchor_list , self .derived_feature_list , self .local_workspace_dir )
699+ self .config_helper .save_to_feature_config_from_context (self .anchor_list , self .derived_feature_list , self .local_workspace_dir )
682700 else :
683701 raise RuntimeError ("Please call FeathrClient.build_features() first in order to materialize the features" )
684702
@@ -772,7 +790,7 @@ def _get_s3_config_str(self):
772790 # keys can't be only accessed through environment
773791 access_key = self .envutils .get_environment_variable ('S3_ACCESS_KEY' )
774792 secret_key = self .envutils .get_environment_variable ('S3_SECRET_KEY' )
775- # HOCCON format will be parsed by the Feathr job
793+ # HOCON format will be parsed by the Feathr job
776794 config_str = """
777795 S3_ENDPOINT: {S3_ENDPOINT}
778796 S3_ACCESS_KEY: "{S3_ACCESS_KEY}"
@@ -787,7 +805,7 @@ def _get_adls_config_str(self):
787805 # if ADLS Account is set in the feathr_config, then we need other environment variables
788806 # keys can't be only accessed through environment
789807 key = self .envutils .get_environment_variable ('ADLS_KEY' )
790- # HOCCON format will be parsed by the Feathr job
808+ # HOCON format will be parsed by the Feathr job
791809 config_str = """
792810 ADLS_ACCOUNT: {ADLS_ACCOUNT}
793811 ADLS_KEY: "{ADLS_KEY}"
@@ -801,7 +819,7 @@ def _get_blob_config_str(self):
801819 # if BLOB Account is set in the feathr_config, then we need other environment variables
802820 # keys can't be only accessed through environment
803821 key = self .envutils .get_environment_variable ('BLOB_KEY' )
804- # HOCCON format will be parsed by the Feathr job
822+ # HOCON format will be parsed by the Feathr job
805823 config_str = """
806824 BLOB_ACCOUNT: {BLOB_ACCOUNT}
807825 BLOB_KEY: "{BLOB_KEY}"
@@ -817,7 +835,7 @@ def _get_sql_config_str(self):
817835 driver = self .envutils .get_environment_variable ('JDBC_DRIVER' )
818836 auth_flag = self .envutils .get_environment_variable ('JDBC_AUTH_FLAG' )
819837 token = self .envutils .get_environment_variable ('JDBC_TOKEN' )
820- # HOCCON format will be parsed by the Feathr job
838+ # HOCON format will be parsed by the Feathr job
821839 config_str = """
822840 JDBC_TABLE: {JDBC_TABLE}
823841 JDBC_USER: {JDBC_USER}
@@ -834,7 +852,7 @@ def _get_monitoring_config_str(self):
834852 user = self .envutils .get_environment_variable_with_default ('monitoring' , 'database' , 'sql' , 'user' )
835853 password = self .envutils .get_environment_variable ('MONITORING_DATABASE_SQL_PASSWORD' )
836854 if url :
837- # HOCCON format will be parsed by the Feathr job
855+ # HOCON format will be parsed by the Feathr job
838856 config_str = """
839857 MONITORING_DATABASE_SQL_URL: "{url}"
840858 MONITORING_DATABASE_SQL_USER: {user}
@@ -852,7 +870,7 @@ def _get_snowflake_config_str(self):
852870 sf_role = self .envutils .get_environment_variable_with_default ('offline_store' , 'snowflake' , 'role' )
853871 sf_warehouse = self .envutils .get_environment_variable_with_default ('offline_store' , 'snowflake' , 'warehouse' )
854872 sf_password = self .envutils .get_environment_variable ('JDBC_SF_PASSWORD' )
855- # HOCCON format will be parsed by the Feathr job
873+ # HOCON format will be parsed by the Feathr job
856874 config_str = """
857875 JDBC_SF_URL: {JDBC_SF_URL}
858876 JDBC_SF_USER: {JDBC_SF_USER}
@@ -866,7 +884,7 @@ def _get_kafka_config_str(self):
866884 """Construct the Kafka config string. The endpoint, access key, secret key, and other parameters can be set via
867885 environment variables."""
868886 sasl = self .envutils .get_environment_variable ('KAFKA_SASL_JAAS_CONFIG' )
869- # HOCCON format will be parsed by the Feathr job
887+ # HOCON format will be parsed by the Feathr job
870888 config_str = """
871889 KAFKA_SASL_JAAS_CONFIG: "{sasl}"
872890 """ .format (sasl = sasl )
@@ -899,4 +917,4 @@ def _reshape_config_str(self, config_str:str):
899917 if self .spark_runtime == 'local' :
900918 return "'{" + config_str + "}'"
901919 else :
902- return config_str
920+ return config_str
0 commit comments