Skip to content

Commit 487764a

Browse files
nargokulAditi2424adishaamollyheamazon
authored
Feature store v3 (#5539)
* Feature store v3 (#5490) * feat: Add Feature Store Support to V3 * Add feature store tests --------- Co-authored-by: adishaa <adishaa@amazon.com> * Changes: - Add feature_store_functions_report.md documenting all 63 functions across feature_store module (excluding feature_processor) - Add comprehensive unit tests for get_feature_group_as_dataframe: * Session handling (provided, from region, from role) * Error cases (missing session/region, missing event_time) * Latest ingestion logic with event time * Query string manipulation and table placeholder * Verbose and silent logging modes * Kwargs passing to as_dataframe - Add comprehensive unit tests for prepare_fg_from_dataframe_or_file: * DataFrame and file path input handling * Session/region/role configuration * Record ID creation and validation * Event ID creation with timestamp * Duplicate record detection * Column name formatting * CSV kwargs passing * Feature definition loading * Fix * Fix * fix * Integ tests * Fix * Add feature store telemetry * Bug fix for GetRecordResponse not printable and error message for ingest_dataframe * Fix: DatasetBuilder.to_dataframe() docstring and instantiation * Fix unit test failures * fix unit test --------- Co-authored-by: Aditi Sharma <165942273+Aditi2424@users.noreply.github.com> Co-authored-by: adishaa <adishaa@amazon.com> Co-authored-by: Molly He <mollyhe@amazon.com>
1 parent 1752e7a commit 487764a

25 files changed

+5064
-0
lines changed

sagemaker-core/src/sagemaker/core/telemetry/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class Feature(Enum):
2828
MODEL_TRAINER = 14
2929
MODEL_CUSTOMIZATION = 15
3030
MLOPS = 16
31+
FEATURE_STORE = 17
3132

3233
def __str__(self): # pylint: disable=E0307
3334
"""Return the feature name."""

sagemaker-core/src/sagemaker/core/telemetry/telemetry_logging.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
str(Feature.MODEL_TRAINER): 14,
5757
str(Feature.MODEL_CUSTOMIZATION): 15,
5858
str(Feature.MLOPS): 16,
59+
str(Feature.FEATURE_STORE): 17,
5960
}
6061

6162
STATUS_TO_CODE = {
@@ -81,6 +82,9 @@ def wrapper(*args, **kwargs):
8182
if len(args) > 0 and hasattr(args[0], "sagemaker_session"):
8283
# Get the sagemaker_session from the instance method args
8384
sagemaker_session = args[0].sagemaker_session
85+
elif len(args) > 0 and hasattr(args[0], "_sagemaker_session"):
86+
# Get the sagemaker_session from the instance method args (private attribute)
87+
sagemaker_session = args[0]._sagemaker_session
8488
elif feature == Feature.REMOTE_FUNCTION:
8589
# Get the sagemaker_session from the function keyword arguments for remote function
8690
sagemaker_session = kwargs.get(

sagemaker-core/src/sagemaker/core/utils/utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,22 @@ def __new__(cls):
298298
cls._instance = super().__new__(cls)
299299
return cls._instance
300300

301+
def __repr__(self):
302+
"""Return clean representation for debugging."""
303+
return "Unassigned()"
304+
305+
def __str__(self):
306+
"""Return empty string for clean printing."""
307+
return ""
308+
309+
def __iter__(self):
310+
"""Return empty iterator to prevent iteration errors."""
311+
return iter([])
312+
313+
def __bool__(self):
314+
"""Return False for truthiness checks."""
315+
return False
316+
301317

302318
class SingletonMeta(type):
303319
"""

sagemaker-core/tests/unit/generated/test_utils.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,50 @@ def test_serialize_method_nested_shape():
371371
"StringValue": "string",
372372
},
373373
}
374+
375+
376+
class TestUnassignedBehavior:
377+
"""Test Unassigned class methods for proper behavior.
378+
379+
Bug fix: GetRecordResponse is not printable and cannot be parsed via iterator.
380+
Error: TypeError: 'Unassigned' object is not iterable
381+
"""
382+
383+
def test_unassigned_repr(self):
384+
"""Test that Unassigned has clean repr."""
385+
u = Unassigned()
386+
assert repr(u) == "Unassigned()"
387+
388+
def test_unassigned_str(self):
389+
"""Test that Unassigned converts to empty string."""
390+
u = Unassigned()
391+
assert str(u) == ""
392+
393+
def test_unassigned_bool(self):
394+
"""Test that Unassigned is falsy."""
395+
u = Unassigned()
396+
assert not u
397+
assert bool(u) is False
398+
399+
def test_unassigned_iter(self):
400+
"""Test that Unassigned is iterable and returns empty list."""
401+
u = Unassigned()
402+
result = list(u)
403+
assert result == []
404+
405+
def test_unassigned_singleton(self):
406+
"""Test that Unassigned is a singleton."""
407+
u1 = Unassigned()
408+
u2 = Unassigned()
409+
assert u1 is u2
410+
411+
def test_unassigned_in_conditional(self):
412+
"""Test that Unassigned works correctly in conditionals."""
413+
u = Unassigned()
414+
415+
# Should evaluate to False
416+
if u:
417+
pytest.fail("Unassigned should be falsy")
418+
419+
# Should work with not
420+
assert not u

0 commit comments

Comments
 (0)