Skip to content

Commit

Permalink
Add support for third party providers
Browse files Browse the repository at this point in the history
Signed-off-by: Tsotne Tabidze <tsotne@tecton.ai>
  • Loading branch information
Tsotne Tabidze committed Apr 23, 2021
1 parent cbb97d3 commit 1f101b2
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 1 deletion.
21 changes: 21 additions & 0 deletions sdk/python/feast/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,24 @@ def __init__(self, name, project=None):

class FeastProviderLoginError(Exception):
"""Error class that indicates a user has not authenticated with their provider."""
def __init__(self, project, name):
super().__init__(f"Feature table {name} does not exist in project {project}")


class ProviderNameParsingException(Exception):
def __init__(self, provider_name):
super().__init__(
f"Could not parse provider name '{provider_name}' into module and class names"
)


class ProviderModuleImportError(Exception):
def __init__(self, module_name):
super().__init__(f"Could not import provider module '{module_name}'")


class ProviderClassImportError(Exception):
def __init__(self, module_name, class_name):
super().__init__(
f"Could not import provider '{class_name}' from module '{module_name}'"
)
27 changes: 26 additions & 1 deletion sdk/python/feast/infra/provider.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import abc
import importlib
from datetime import datetime
from pathlib import Path
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union

import pandas
import pyarrow

from feast import errors
from feast.entity import Entity
from feast.feature_table import FeatureTable
from feast.feature_view import FeatureView
Expand Down Expand Up @@ -144,7 +146,30 @@ def get_provider(config: RepoConfig, repo_path: Path) -> Provider:

return LocalProvider(config, repo_path)
else:
raise ValueError(config)
if "." not in config.provider:
raise errors.ProviderNameParsingException(config.provider)
# Split provider into module and class names by finding the right-most dot.
# For example, provider 'foo.bar.MyProvider' will be parsed into 'foo.bar' and 'MyProvider'
module_name, class_name = config.provider.rsplit(".", 1)

# Try importing the module that contains the custom provider
try:
module = importlib.import_module(module_name)
except Exception as e:
# The original exception can be anything - either module not found,
# or any other kind of error happening during the module import time.
# So we should include the original error as well in the stack trace.
raise errors.ProviderModuleImportError(module_name) from e

# Try getting the provider class definition
try:
ProviderCls = getattr(module, class_name)
except AttributeError:
# This can only be one type of error, when class_name attribute does not exist in the module
# So we don't have to include the original exception here
raise errors.ProviderClassImportError(module_name, class_name) from None

return ProviderCls(config)


def _get_requested_feature_views_to_features_dict(
Expand Down

0 comments on commit 1f101b2

Please sign in to comment.