haystack-ml-stack 0.4.8__tar.gz → 0.4.9__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.
Files changed (27) hide show
  1. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/PKG-INFO +1 -1
  2. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/README.md +0 -0
  3. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/pyproject.toml +1 -1
  4. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/__init__.py +0 -0
  5. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/_kafka.py +0 -0
  6. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/_serializers.py +2 -0
  7. haystack_ml_stack-0.4.9/src/haystack_ml_stack/_version.py +1 -0
  8. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/app.py +0 -0
  9. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/cache.py +0 -0
  10. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/exceptions.py +0 -0
  11. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/generated/__init__.py +0 -0
  12. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/generated/v1/__init__.py +0 -0
  13. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/generated/v1/features_pb2.py +34 -34
  14. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/generated/v1/features_pb2.pyi +5 -1
  15. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/model_store.py +0 -0
  16. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/settings.py +0 -0
  17. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/utils.py +2 -0
  18. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack.egg-info/PKG-INFO +1 -1
  19. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack.egg-info/SOURCES.txt +0 -0
  20. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack.egg-info/dependency_links.txt +0 -0
  21. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack.egg-info/requires.txt +0 -0
  22. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack.egg-info/top_level.txt +0 -0
  23. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/tests/test_serializers.py +61 -0
  24. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/tests/test_utils.py +0 -0
  25. haystack_ml_stack-0.4.8/src/haystack_ml_stack/_version.py +0 -1
  26. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/setup.cfg +0 -0
  27. {haystack_ml_stack-0.4.8 → haystack_ml_stack-0.4.9}/src/haystack_ml_stack/dynamo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haystack-ml-stack
3
- Version: 0.4.8
3
+ Version: 0.4.9
4
4
  Summary: Functions related to Haystack ML
5
5
  Author-email: Oscar Vega <oscar@haystack.tv>
6
6
  License: MIT
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "haystack-ml-stack"
8
- version = "0.4.8"
8
+ version = "0.4.9"
9
9
  description = "Functions related to Haystack ML"
10
10
  readme = "README.md"
11
11
  authors = [{ name = "Oscar Vega", email = "oscar@haystack.tv" }]
@@ -275,6 +275,8 @@ class UserPlaylistStatsSerializerV1(SimpleSerializer):
275
275
  category_msg.active_days = int(stats["active_days"])
276
276
  category_msg.total_watched = float(stats["total_watched"])
277
277
  category_msg.capped_total_watched = float(stats["capped_total_watched"])
278
+ category_msg.capped_total_log_watched = float(stats.get("capped_total_log_watched", 0.0))
279
+ category_msg.first_active_date = str(stats.get("first_active_date", ""))
278
280
  return root_msg
279
281
 
280
282
 
@@ -0,0 +1 @@
1
+ __version__ = "0.4.9"
@@ -24,7 +24,7 @@ _sym_db = _symbol_database.Default()
24
24
 
25
25
 
26
26
 
27
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x66\x65\x61tures.proto\x12\x1ahaystack_ml_stack.features\"7\n\x12\x45ntryContextCounts\x12\x10\n\x08\x61ttempts\x18\x01 \x01(\x05\x12\x0f\n\x07watched\x18\x02 \x01(\x05\"_\n\x0cSelectCounts\x12\x15\n\rtotal_selects\x18\x01 \x01(\x05\x12!\n\x19total_selects_and_watched\x18\x02 \x01(\x05\x12\x15\n\rtotal_browsed\x18\x03 \x01(\x05\"\xf3\x02\n\x14\x45ntryContextPWatched\x12@\n\x08\x61utoplay\x18\x01 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\x12\x41\n\tsel_thumb\x18\x02 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\x12\x43\n\x0b\x63hoose_next\x18\x03 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\x12@\n\x08\x63h_swtch\x18\x04 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\x12O\n\x17launch_first_in_session\x18\x05 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\"\x85\x02\n\x0fPositionPSelect\x12;\n\tfirst_pos\x18\x01 \x01(\x0b\x32(.haystack_ml_stack.features.SelectCounts\x12<\n\nsecond_pos\x18\x02 \x01(\x0b\x32(.haystack_ml_stack.features.SelectCounts\x12;\n\tthird_pos\x18\x03 \x01(\x0b\x32(.haystack_ml_stack.features.SelectCounts\x12:\n\x08rest_pos\x18\x04 \x01(\x0b\x32(.haystack_ml_stack.features.SelectCounts\"\xa9\x01\n\x1f\x42rowsedDebiasedPositionPSelects\x12\x44\n\x0fup_to_4_browsed\x18\x01 \x01(\x0b\x32+.haystack_ml_stack.features.PositionPSelect\x12@\n\x0b\x61ll_browsed\x18\x02 \x01(\x0b\x32+.haystack_ml_stack.features.PositionPSelect\"\xb8\x01\n\x16PlaylistStatsForGlobal\x12\x15\n\rwatched_count\x18\x01 \x01(\x05\x12\x19\n\x11not_watched_count\x18\x02 \x01(\x05\x12\x1b\n\x13\x63\x61pped_watched_secs\x18\x03 \x01(\x02\x12\x1f\n\x17\x63\x61pped_not_watched_secs\x18\x04 \x01(\x02\x12\x14\n\x0cwatched_secs\x18\x05 \x01(\x02\x12\x18\n\x10not_watched_secs\x18\x06 \x01(\x02\"\x88\x01\n\x14PlaylistStatsForUser\x12\x12\n\ntotal_days\x18\x01 \x01(\x05\x12\x12\n\nstart_days\x18\x02 \x01(\x05\x12\x13\n\x0b\x61\x63tive_days\x18\x03 \x01(\x05\x12\x15\n\rtotal_watched\x18\x04 \x01(\x02\x12\x1c\n\x14\x63\x61pped_total_watched\x18\x05 \x01(\x02\"C\n\x07\x43hannel\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0e\x63\x61tegory_group\x18\x02 \x01(\t\x12\x12\n\nstart_date\x18\x03 \x01(\x05\"k\n\rStreamPSelect\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12I\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32;.haystack_ml_stack.features.BrowsedDebiasedPositionPSelects\"a\n\x0eStreamPWatched\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12>\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x30.haystack_ml_stack.features.EntryContextPWatched\"_\n\x0cUserPWatched\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12>\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x30.haystack_ml_stack.features.EntryContextPWatched\"\xda\x01\n\x19UserPersonalizingPWatched\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12M\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32?.haystack_ml_stack.features.UserPersonalizingPWatched.DataEntry\x1a]\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.haystack_ml_stack.features.EntryContextPWatched:\x02\x38\x01\"i\n\x0bUserPSelect\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12I\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32;.haystack_ml_stack.features.BrowsedDebiasedPositionPSelects\"\xe3\x01\n\x18UserPersonalizingPSelect\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12L\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32>.haystack_ml_stack.features.UserPersonalizingPSelect.DataEntry\x1ah\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12J\n\x05value\x18\x02 \x01(\x0b\x32;.haystack_ml_stack.features.BrowsedDebiasedPositionPSelects:\x02\x38\x01\"\xa2\x01\n\x16StreamSimilarityScores\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12J\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32<.haystack_ml_stack.features.StreamSimilarityScores.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\"\xd0\x01\n\x13GlobalPlaylistStats\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12G\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x39.haystack_ml_stack.features.GlobalPlaylistStats.DataEntry\x1a_\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x41\n\x05value\x18\x02 \x01(\x0b\x32\x32.haystack_ml_stack.features.PlaylistStatsForGlobal:\x02\x38\x01\"\xca\x01\n\x11UserPlaylistStats\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12\x45\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x37.haystack_ml_stack.features.UserPlaylistStats.DataEntry\x1a]\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.haystack_ml_stack.features.PlaylistStatsForUser:\x02\x38\x01\"T\n\x0eGlobalChannels\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12\x31\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32#.haystack_ml_stack.features.Channelb\x06proto3')
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0e\x66\x65\x61tures.proto\x12\x1ahaystack_ml_stack.features\"7\n\x12\x45ntryContextCounts\x12\x10\n\x08\x61ttempts\x18\x01 \x01(\x05\x12\x0f\n\x07watched\x18\x02 \x01(\x05\"_\n\x0cSelectCounts\x12\x15\n\rtotal_selects\x18\x01 \x01(\x05\x12!\n\x19total_selects_and_watched\x18\x02 \x01(\x05\x12\x15\n\rtotal_browsed\x18\x03 \x01(\x05\"\xf3\x02\n\x14\x45ntryContextPWatched\x12@\n\x08\x61utoplay\x18\x01 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\x12\x41\n\tsel_thumb\x18\x02 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\x12\x43\n\x0b\x63hoose_next\x18\x03 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\x12@\n\x08\x63h_swtch\x18\x04 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\x12O\n\x17launch_first_in_session\x18\x05 \x01(\x0b\x32..haystack_ml_stack.features.EntryContextCounts\"\x85\x02\n\x0fPositionPSelect\x12;\n\tfirst_pos\x18\x01 \x01(\x0b\x32(.haystack_ml_stack.features.SelectCounts\x12<\n\nsecond_pos\x18\x02 \x01(\x0b\x32(.haystack_ml_stack.features.SelectCounts\x12;\n\tthird_pos\x18\x03 \x01(\x0b\x32(.haystack_ml_stack.features.SelectCounts\x12:\n\x08rest_pos\x18\x04 \x01(\x0b\x32(.haystack_ml_stack.features.SelectCounts\"\xa9\x01\n\x1f\x42rowsedDebiasedPositionPSelects\x12\x44\n\x0fup_to_4_browsed\x18\x01 \x01(\x0b\x32+.haystack_ml_stack.features.PositionPSelect\x12@\n\x0b\x61ll_browsed\x18\x02 \x01(\x0b\x32+.haystack_ml_stack.features.PositionPSelect\"\xb8\x01\n\x16PlaylistStatsForGlobal\x12\x15\n\rwatched_count\x18\x01 \x01(\x05\x12\x19\n\x11not_watched_count\x18\x02 \x01(\x05\x12\x1b\n\x13\x63\x61pped_watched_secs\x18\x03 \x01(\x02\x12\x1f\n\x17\x63\x61pped_not_watched_secs\x18\x04 \x01(\x02\x12\x14\n\x0cwatched_secs\x18\x05 \x01(\x02\x12\x18\n\x10not_watched_secs\x18\x06 \x01(\x02\"\xc5\x01\n\x14PlaylistStatsForUser\x12\x12\n\ntotal_days\x18\x01 \x01(\x05\x12\x12\n\nstart_days\x18\x02 \x01(\x05\x12\x13\n\x0b\x61\x63tive_days\x18\x03 \x01(\x05\x12\x15\n\rtotal_watched\x18\x04 \x01(\x02\x12\x1c\n\x14\x63\x61pped_total_watched\x18\x05 \x01(\x02\x12 \n\x18\x63\x61pped_total_log_watched\x18\x06 \x01(\x02\x12\x19\n\x11\x66irst_active_date\x18\x07 \x01(\t\"C\n\x07\x43hannel\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x16\n\x0e\x63\x61tegory_group\x18\x02 \x01(\t\x12\x12\n\nstart_date\x18\x03 \x01(\x05\"k\n\rStreamPSelect\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12I\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32;.haystack_ml_stack.features.BrowsedDebiasedPositionPSelects\"a\n\x0eStreamPWatched\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12>\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x30.haystack_ml_stack.features.EntryContextPWatched\"_\n\x0cUserPWatched\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12>\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x30.haystack_ml_stack.features.EntryContextPWatched\"\xda\x01\n\x19UserPersonalizingPWatched\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12M\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32?.haystack_ml_stack.features.UserPersonalizingPWatched.DataEntry\x1a]\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.haystack_ml_stack.features.EntryContextPWatched:\x02\x38\x01\"i\n\x0bUserPSelect\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12I\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32;.haystack_ml_stack.features.BrowsedDebiasedPositionPSelects\"\xe3\x01\n\x18UserPersonalizingPSelect\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12L\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32>.haystack_ml_stack.features.UserPersonalizingPSelect.DataEntry\x1ah\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12J\n\x05value\x18\x02 \x01(\x0b\x32;.haystack_ml_stack.features.BrowsedDebiasedPositionPSelects:\x02\x38\x01\"\xa2\x01\n\x16StreamSimilarityScores\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12J\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32<.haystack_ml_stack.features.StreamSimilarityScores.DataEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x01:\x02\x38\x01\"\xd0\x01\n\x13GlobalPlaylistStats\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12G\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x39.haystack_ml_stack.features.GlobalPlaylistStats.DataEntry\x1a_\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x41\n\x05value\x18\x02 \x01(\x0b\x32\x32.haystack_ml_stack.features.PlaylistStatsForGlobal:\x02\x38\x01\"\xca\x01\n\x11UserPlaylistStats\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12\x45\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x37.haystack_ml_stack.features.UserPlaylistStats.DataEntry\x1a]\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12?\n\x05value\x18\x02 \x01(\x0b\x32\x30.haystack_ml_stack.features.PlaylistStatsForUser:\x02\x38\x01\"T\n\x0eGlobalChannels\x12\x0f\n\x07version\x18\x01 \x01(\x05\x12\x31\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32#.haystack_ml_stack.features.Channelb\x06proto3')
28
28
 
29
29
  _globals = globals()
30
30
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -54,37 +54,37 @@ if not _descriptor._USE_C_DESCRIPTORS:
54
54
  _globals['_PLAYLISTSTATSFORGLOBAL']._serialized_start=1011
55
55
  _globals['_PLAYLISTSTATSFORGLOBAL']._serialized_end=1195
56
56
  _globals['_PLAYLISTSTATSFORUSER']._serialized_start=1198
57
- _globals['_PLAYLISTSTATSFORUSER']._serialized_end=1334
58
- _globals['_CHANNEL']._serialized_start=1336
59
- _globals['_CHANNEL']._serialized_end=1403
60
- _globals['_STREAMPSELECT']._serialized_start=1405
61
- _globals['_STREAMPSELECT']._serialized_end=1512
62
- _globals['_STREAMPWATCHED']._serialized_start=1514
63
- _globals['_STREAMPWATCHED']._serialized_end=1611
64
- _globals['_USERPWATCHED']._serialized_start=1613
65
- _globals['_USERPWATCHED']._serialized_end=1708
66
- _globals['_USERPERSONALIZINGPWATCHED']._serialized_start=1711
67
- _globals['_USERPERSONALIZINGPWATCHED']._serialized_end=1929
68
- _globals['_USERPERSONALIZINGPWATCHED_DATAENTRY']._serialized_start=1836
69
- _globals['_USERPERSONALIZINGPWATCHED_DATAENTRY']._serialized_end=1929
70
- _globals['_USERPSELECT']._serialized_start=1931
71
- _globals['_USERPSELECT']._serialized_end=2036
72
- _globals['_USERPERSONALIZINGPSELECT']._serialized_start=2039
73
- _globals['_USERPERSONALIZINGPSELECT']._serialized_end=2266
74
- _globals['_USERPERSONALIZINGPSELECT_DATAENTRY']._serialized_start=2162
75
- _globals['_USERPERSONALIZINGPSELECT_DATAENTRY']._serialized_end=2266
76
- _globals['_STREAMSIMILARITYSCORES']._serialized_start=2269
77
- _globals['_STREAMSIMILARITYSCORES']._serialized_end=2431
78
- _globals['_STREAMSIMILARITYSCORES_DATAENTRY']._serialized_start=2388
79
- _globals['_STREAMSIMILARITYSCORES_DATAENTRY']._serialized_end=2431
80
- _globals['_GLOBALPLAYLISTSTATS']._serialized_start=2434
81
- _globals['_GLOBALPLAYLISTSTATS']._serialized_end=2642
82
- _globals['_GLOBALPLAYLISTSTATS_DATAENTRY']._serialized_start=2547
83
- _globals['_GLOBALPLAYLISTSTATS_DATAENTRY']._serialized_end=2642
84
- _globals['_USERPLAYLISTSTATS']._serialized_start=2645
85
- _globals['_USERPLAYLISTSTATS']._serialized_end=2847
86
- _globals['_USERPLAYLISTSTATS_DATAENTRY']._serialized_start=2754
87
- _globals['_USERPLAYLISTSTATS_DATAENTRY']._serialized_end=2847
88
- _globals['_GLOBALCHANNELS']._serialized_start=2849
89
- _globals['_GLOBALCHANNELS']._serialized_end=2933
57
+ _globals['_PLAYLISTSTATSFORUSER']._serialized_end=1395
58
+ _globals['_CHANNEL']._serialized_start=1397
59
+ _globals['_CHANNEL']._serialized_end=1464
60
+ _globals['_STREAMPSELECT']._serialized_start=1466
61
+ _globals['_STREAMPSELECT']._serialized_end=1573
62
+ _globals['_STREAMPWATCHED']._serialized_start=1575
63
+ _globals['_STREAMPWATCHED']._serialized_end=1672
64
+ _globals['_USERPWATCHED']._serialized_start=1674
65
+ _globals['_USERPWATCHED']._serialized_end=1769
66
+ _globals['_USERPERSONALIZINGPWATCHED']._serialized_start=1772
67
+ _globals['_USERPERSONALIZINGPWATCHED']._serialized_end=1990
68
+ _globals['_USERPERSONALIZINGPWATCHED_DATAENTRY']._serialized_start=1897
69
+ _globals['_USERPERSONALIZINGPWATCHED_DATAENTRY']._serialized_end=1990
70
+ _globals['_USERPSELECT']._serialized_start=1992
71
+ _globals['_USERPSELECT']._serialized_end=2097
72
+ _globals['_USERPERSONALIZINGPSELECT']._serialized_start=2100
73
+ _globals['_USERPERSONALIZINGPSELECT']._serialized_end=2327
74
+ _globals['_USERPERSONALIZINGPSELECT_DATAENTRY']._serialized_start=2223
75
+ _globals['_USERPERSONALIZINGPSELECT_DATAENTRY']._serialized_end=2327
76
+ _globals['_STREAMSIMILARITYSCORES']._serialized_start=2330
77
+ _globals['_STREAMSIMILARITYSCORES']._serialized_end=2492
78
+ _globals['_STREAMSIMILARITYSCORES_DATAENTRY']._serialized_start=2449
79
+ _globals['_STREAMSIMILARITYSCORES_DATAENTRY']._serialized_end=2492
80
+ _globals['_GLOBALPLAYLISTSTATS']._serialized_start=2495
81
+ _globals['_GLOBALPLAYLISTSTATS']._serialized_end=2703
82
+ _globals['_GLOBALPLAYLISTSTATS_DATAENTRY']._serialized_start=2608
83
+ _globals['_GLOBALPLAYLISTSTATS_DATAENTRY']._serialized_end=2703
84
+ _globals['_USERPLAYLISTSTATS']._serialized_start=2706
85
+ _globals['_USERPLAYLISTSTATS']._serialized_end=2908
86
+ _globals['_USERPLAYLISTSTATS_DATAENTRY']._serialized_start=2815
87
+ _globals['_USERPLAYLISTSTATS_DATAENTRY']._serialized_end=2908
88
+ _globals['_GLOBALCHANNELS']._serialized_start=2910
89
+ _globals['_GLOBALCHANNELS']._serialized_end=2994
90
90
  # @@protoc_insertion_point(module_scope)
@@ -81,12 +81,16 @@ class PlaylistStatsForUser(_message.Message):
81
81
  ACTIVE_DAYS_FIELD_NUMBER: _ClassVar[int]
82
82
  TOTAL_WATCHED_FIELD_NUMBER: _ClassVar[int]
83
83
  CAPPED_TOTAL_WATCHED_FIELD_NUMBER: _ClassVar[int]
84
+ CAPPED_TOTAL_LOG_WATCHED_FIELD_NUMBER: _ClassVar[int]
85
+ FIRST_ACTIVE_DATE_FIELD_NUMBER: _ClassVar[int]
84
86
  total_days: int
85
87
  start_days: int
86
88
  active_days: int
87
89
  total_watched: float
88
90
  capped_total_watched: float
89
- def __init__(self, total_days: _Optional[int] = ..., start_days: _Optional[int] = ..., active_days: _Optional[int] = ..., total_watched: _Optional[float] = ..., capped_total_watched: _Optional[float] = ...) -> None: ...
91
+ capped_total_log_watched: float
92
+ first_active_date: str
93
+ def __init__(self, total_days: _Optional[int] = ..., start_days: _Optional[int] = ..., active_days: _Optional[int] = ..., total_watched: _Optional[float] = ..., capped_total_watched: _Optional[float] = ..., capped_total_log_watched: _Optional[float] = ..., first_active_date: _Optional[str] = ...) -> None: ...
90
94
 
91
95
  class Channel(_message.Message):
92
96
  __slots__ = ()
@@ -715,6 +715,8 @@ def _complete_features_for_channels(
715
715
  "active_days",
716
716
  "total_watched",
717
717
  "capped_total_watched",
718
+ "capped_total_log_watched",
719
+ "first_active_date",
718
720
  ]
719
721
 
720
722
  for ch in channels:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: haystack-ml-stack
3
- Version: 0.4.8
3
+ Version: 0.4.9
4
4
  Summary: Functions related to Haystack ML
5
5
  Author-email: Oscar Vega <oscar@haystack.tv>
6
6
  License: MIT
@@ -150,3 +150,64 @@ def test_user_bias_serializers():
150
150
  "User pselect serialization does not match expected value."
151
151
  )
152
152
  return
153
+
154
+
155
+ def test_user_playlist_stats_serializer_backward_compatibility():
156
+ serializer = SerializerRegistry[("USER", "PLAYLIST_CATEGORY_STATS#3M", "v1")]
157
+
158
+ # Case 1: true old binary — built without fields 6 and 7, identical to what
159
+ # the old serializer would have written before the proto change
160
+ old_msg = features_pb2_v1.UserPlaylistStats()
161
+ old_msg.version = 1
162
+ entry = old_msg.data["sports"]
163
+ entry.total_days = 30
164
+ entry.start_days = 5
165
+ entry.active_days = 10
166
+ entry.total_watched = 120.5
167
+ entry.capped_total_watched = 100.0
168
+ old_binary = old_msg.SerializeToString()
169
+
170
+ result = serializer.deserialize(old_binary)
171
+ assert result.data["sports"].total_days == 30
172
+ assert result.data["sports"].capped_total_watched == 100.0
173
+ assert result.data["sports"].capped_total_log_watched == 0.0
174
+ assert result.data["sports"].first_active_date == ""
175
+
176
+ # Case 2: new data with new fields — full round-trip
177
+ new_data = {
178
+ "version": 1,
179
+ "data": {
180
+ "sports": {
181
+ "total_days": 30,
182
+ "start_days": 5,
183
+ "active_days": 10,
184
+ "total_watched": 120.5,
185
+ "capped_total_watched": 100.0,
186
+ "capped_total_log_watched": 4.8,
187
+ "first_active_date": "2024-01-15",
188
+ }
189
+ },
190
+ }
191
+ binary = serializer.serialize(new_data)
192
+ result = serializer.deserialize(binary)
193
+ assert abs(result.data["sports"].capped_total_log_watched - 4.8) < 1e-6
194
+ assert result.data["sports"].first_active_date == "2024-01-15"
195
+
196
+ # Case 3: old-format dict missing the new fields — .get() fallback
197
+ old_format_data = {
198
+ "version": 1,
199
+ "data": {
200
+ "sports": {
201
+ "total_days": 30,
202
+ "start_days": 5,
203
+ "active_days": 10,
204
+ "total_watched": 120.5,
205
+ "capped_total_watched": 100.0,
206
+ }
207
+ },
208
+ }
209
+ binary = serializer.serialize(old_format_data)
210
+ result = serializer.deserialize(binary)
211
+ assert result.data["sports"].total_days == 30
212
+ assert result.data["sports"].capped_total_log_watched == 0.0
213
+ assert result.data["sports"].first_active_date == ""
@@ -1 +0,0 @@
1
- __version__ = "0.4.8"