-
Notifications
You must be signed in to change notification settings - Fork 996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FeatureStore, FeatureView, Config, and BIgQuerySource classes for updated SDK #1364
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Copyright 2019 The Feast Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from typing import Dict, Optional | ||
|
||
|
||
class BigQuerySource: | ||
def __init__( | ||
self, | ||
table_ref: Optional[str], | ||
event_timestamp_column: str, | ||
created_timestamp_column: Optional[str], | ||
field_mapping: Optional[Dict[str, str]], | ||
query: Optional[str], | ||
): | ||
assert (table_ref is None) != (query is None), "Exactly one of table_ref and query should be specified" | ||
self.table_ref = table_ref | ||
self.event_timestamp_column = event_timestamp_column | ||
self.created_timestamp_column = created_timestamp_column | ||
self.field_mapping = field_mapping | ||
self.query = query | ||
return |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Copyright 2019 The Feast Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from typing import Optional | ||
from feast.feature_store_config import Config | ||
|
||
|
||
class FeatureStore: | ||
woop marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def __init__( | ||
self, | ||
config_path: Optional[str], | ||
config: Optional[Config], | ||
): | ||
assert (config_path is None or config is None), "You cannot specify both config_path and config" | ||
if config is not None: | ||
self.config = config | ||
elif config_path is not None: | ||
self.config = Config.from_config_path(config_path) | ||
else: | ||
self.config = Config() | ||
return | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need a return here? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Copyright 2019 The Feast Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from os.path import expanduser, join | ||
from typing import Optional | ||
import yaml | ||
|
||
|
||
class Config: | ||
woop marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def __init__( | ||
self, | ||
provider: Optional[str], | ||
online_store: Optional[str], | ||
metadata_store: Optional[str], | ||
): | ||
self.provider = provider if (provider is not None) else "local" | ||
self.online_store = online_store if (online_store is not None) else "local" | ||
self.metadata_store = metadata_store if (metadata_store is not None) else join(expanduser("~"), ".feast", "metadata_store") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to rather use the project repository as the local metadata store location? Using a shared folder across multiple projects seems like it can cause problems. |
||
return | ||
|
||
@classmethod | ||
def from_config_path(cls, config_path: str): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
with open(config_path, "r") as f: | ||
config_dict = yaml.safe_load(f) | ||
return cls( | ||
provider=config_dict.get("provider"), | ||
online_store=config_dict.get("online_store"), | ||
metadata_store=config_dict.get("metadata_store"), | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Copyright 2019 The Feast Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# https://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
from datetime import datetime | ||
from typing import Dict, List | ||
|
||
from feast.big_query_source import BigQuerySource | ||
from feast.entity import Entity | ||
from feast.feature import Feature | ||
|
||
|
||
class FeatureView: | ||
def __init__( | ||
self, | ||
name: str, | ||
entities: List[Entity], | ||
features: List[Feature], | ||
tags: Dict[str, str], | ||
ttl: str, | ||
online: bool, | ||
inputs: BigQuerySource, | ||
feature_start_time: datetime, | ||
): | ||
self.name = name | ||
self.entities = entities | ||
self.features = features | ||
self.tags = tags | ||
self.ttl = ttl | ||
self.online = online | ||
self.inputs = inputs | ||
self.feature_start_time = feature_start_time | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small nitpick, but generally I think we should avoid using assert for errors that we expect users will make in lieu of normal exceptions
https://stackoverflow.com/questions/40182944/whats-the-difference-between-raise-try-and-assert#:~:text=raise%20is%20typically%20used%20when,if%20a%20condition%20is%20met.&text=If%20production%20quality%20code%20raises,ve%20got%20a%20bigger%20problem.
Assert should normally be used for impossible to reach situations.