gitlabds 2.1.7__tar.gz → 2.1.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 (29) hide show
  1. {gitlabds-2.1.7/gitlabds.egg-info → gitlabds-2.1.9}/PKG-INFO +151 -11
  2. gitlabds-2.1.7/PKG-INFO → gitlabds-2.1.9/README.md +131 -23
  3. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/__init__.py +15 -0
  4. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/memory_optimization.py +3 -5
  5. gitlabds-2.1.9/gitlabds/serving_features.py +386 -0
  6. gitlabds-2.1.7/README.md → gitlabds-2.1.9/gitlabds.egg-info/PKG-INFO +163 -3
  7. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds.egg-info/SOURCES.txt +3 -2
  8. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds.egg-info/requires.txt +6 -1
  9. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds.egg-info/top_level.txt +0 -1
  10. gitlabds-2.1.9/pyproject.toml +48 -0
  11. gitlabds-2.1.9/setup.py +11 -0
  12. gitlabds-2.1.7/setup.py +0 -41
  13. gitlabds-2.1.7/tests/__init__.py +0 -0
  14. {gitlabds-2.1.7 → gitlabds-2.1.9}/LICENSE +0 -0
  15. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/baselines.py +0 -0
  16. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/config_generator.py +0 -0
  17. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/dummy.py +0 -0
  18. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/feature_reduction.py +0 -0
  19. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/insights.py +0 -0
  20. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/missing.py +0 -0
  21. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/missing_check.py +0 -0
  22. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/missing_fill.py +0 -0
  23. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/model_evaluator.py +0 -0
  24. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/monitoring_metrics.py +0 -0
  25. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/outliers.py +0 -0
  26. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/split_data.py +0 -0
  27. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds/trends.py +0 -0
  28. {gitlabds-2.1.7 → gitlabds-2.1.9}/gitlabds.egg-info/dependency_links.txt +0 -0
  29. {gitlabds-2.1.7 → gitlabds-2.1.9}/setup.cfg +0 -0
@@ -1,25 +1,37 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: gitlabds
3
- Version: 2.1.7
4
- Summary: Gitlab Data Science and Modeling Tools
5
- Home-page: https://gitlab.com/gitlab-data/gitlabds
6
- Author: Kevin Dietz
7
- Author-email: kdietz@gitlab.com
3
+ Version: 2.1.9
4
+ Summary: GitLab Data Science Tools
5
+ Author-email: Kevin Dietz <kdietz@gitlab.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://gitlab.com/gitlab-data/gitlabds
8
8
  Classifier: Development Status :: 5 - Production/Stable
9
9
  Classifier: Intended Audience :: Developers
10
10
  Classifier: Intended Audience :: Science/Research
11
- Classifier: License :: OSI Approved :: MIT License
12
11
  Classifier: Programming Language :: Python :: 3
13
12
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
13
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
15
14
  Classifier: Topic :: Software Development :: Libraries
16
15
  Classifier: Topic :: Utilities
17
- Requires-Python: >=3.10
16
+ Requires-Python: >=3.11
18
17
  Description-Content-Type: text/markdown
19
18
  License-File: LICENSE
19
+ Requires-Dist: pandas>=1.5.3
20
+ Requires-Dist: numpy>=1.23.5
21
+ Requires-Dist: scipy>=1.13.1
22
+ Requires-Dist: scikit-learn>=1.1.1
23
+ Requires-Dist: imbalanced-learn>=0.9.1
24
+ Requires-Dist: seaborn>=0.13.2
25
+ Requires-Dist: shap>=0.50.0
26
+ Requires-Dist: tqdm>=4.66.2
27
+ Requires-Dist: xgboost>=1.6.1
28
+ Provides-Extra: feature-store
29
+ Requires-Dist: snowflake-snowpark-python; extra == "feature-store"
30
+ Requires-Dist: snowflake-ml-python; extra == "feature-store"
31
+ Dynamic: license-file
20
32
 
21
33
  [![PyPI version](https://badge.fury.io/py/gitlabds.svg)](https://badge.fury.io/py/gitlabds)
22
- [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
34
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
23
35
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
24
36
 
25
37
  # gitlabds
@@ -35,7 +47,7 @@ pip install gitlabds
35
47
 
36
48
  ### Requirements
37
49
 
38
- - Python 3.10 or later
50
+ - Python 3.11 or later
39
51
  - Core dependencies:
40
52
  - pandas>=1.5.3
41
53
  - numpy>=1.23.5
@@ -43,8 +55,27 @@ pip install gitlabds
43
55
  - scikit-learn>=1.1.1
44
56
  - imbalanced-learn>=0.9.1
45
57
  - seaborn>=0.13.2
46
- - shap>=0.41.0
58
+ - shap>=0.50.0
47
59
  - tqdm>=4.66.2
60
+ - xgboost>=1.6.1
61
+
62
+ ### Optional Dependencies
63
+
64
+ #### Snowflake Feature Store
65
+
66
+ The `serve_features` and `clear_feature_serving_locks` functions require additional Snowflake dependencies.
67
+
68
+ To use these functions, install with:
69
+
70
+ ```bash
71
+ pip install gitlabds[feature-store]
72
+ ```
73
+
74
+ This will install:
75
+ - `snowflake-snowpark-python`
76
+ - `snowflake-ml-python`
77
+
78
+ If you try to use these functions without installing the optional dependencies, you'll get an error message with installation instructions.
48
79
 
49
80
  ## Main Features by Category
50
81
 
@@ -903,6 +934,115 @@ feature_drift = results['feature_drift']
903
934
  ```
904
935
  </details>
905
936
 
937
+ ### Deployment
938
+
939
+ #### Feature Serving
940
+
941
+ <details><summary> Serve Features </summary>
942
+
943
+ #### Description
944
+ Serve features from Snowflake Feature Store with built-in distributed locking and retry logic. This function orchestrates feature retrieval from multiple feature views with support for point-in-time lookups and flexible parameter customization.
945
+
946
+ `gitlabds.serve_features(session, feature_store, feature_views_dict, spine_df=None, feature_date=None, spine_timestamp_col=None, include_feature_view_timestamp_col=False, lookback_window_value=None, lookback_window_unit=None, lock_timeout_seconds=300):`
947
+
948
+ #### Parameters:
949
+ - **_session_** : Active Snowflake Session object
950
+ - **_feature_store_** : Initialized FeatureStore instance
951
+ - **_feature_views_dict_** : Dictionary mapping feature view names to versions (e.g., {"sales_activities": "1.0"})
952
+ - **_spine_df_** : One of the following:
953
+ - SQL query string to generate the spine DataFrame
954
+ - pandas DataFrame (will be converted to Snowpark DataFrame)
955
+ - Snowpark DataFrame (used directly)
956
+ - **_feature_date_** : Date for feature retrieval (e.g., '2025-04-08'). If None, uses UDF default.
957
+ - **_spine_timestamp_col_** : Name of timestamp column in spine DataFrame for point-in-time lookup. Used for when multiple feature_dates may be present in the feature view. If only one feature_date is present, can set value to None for faster execution.
958
+ - **_include_feature_view_timestamp_col_** : Whether to include timestamp column from feature views in output. Default is False.
959
+ - **_lookback_window_value_** : Either a global integer value (e.g., 6) or a dict with feature-view-specific values
960
+ - **_lookback_window_unit_** : Either a global string value (e.g., 'months') or a dict with feature-view-specific values
961
+ - **_lock_timeout_seconds_** : Timeout in seconds for acquiring the Snowflake lock. Default is 300.
962
+
963
+ #### Returns
964
+ - DataFrame with combined features from all feature views
965
+
966
+ #### Requirements
967
+ This function requires Snowflake packages. Install with:
968
+ ```bash
969
+ pip install snowflake-snowpark-python snowflake-ml-python
970
+ ```
971
+
972
+ #### Examples:
973
+
974
+ ```python
975
+ # Basic usage with SQL spine
976
+ import gitlabds
977
+ from snowflake.snowpark import Session
978
+ from snowflake.ml.feature_store import FeatureStore
979
+
980
+ session = Session.builder.configs(...).create()
981
+ fs = FeatureStore(session, ...)
982
+
983
+ spine_sql = "SELECT account_id FROM accounts WHERE active = TRUE"
984
+ features = gitlabds.serve_features(
985
+ session=session,
986
+ feature_store=fs,
987
+ feature_views_dict={"sales_activities": "1.0", "marketing_activity": "2.1"},
988
+ spine_df=spine_sql,
989
+ feature_date=None
990
+ )
991
+ ```
992
+
993
+ ```python
994
+ # With per-feature-view parameters
995
+ features = gitlabds.serve_features(
996
+ session=session,
997
+ feature_store=fs,
998
+ feature_views_dict={"sales_activities": "1.0", "product_stage": "2.1"},
999
+ spine_df=spine_df,
1000
+ lookback_window_value={"sales_activities": 3, "product_stage": 6},
1001
+ lookback_window_unit={"sales_activities": "days", "product_stage": "months"}
1002
+ )
1003
+ ```
1004
+
1005
+ ```python
1006
+ # With point-in-time lookup
1007
+ features = gitlabds.serve_features(
1008
+ session=session,
1009
+ feature_store=fs,
1010
+ feature_views_dict={"sales_activities": "1.0"},
1011
+ spine_df=spine_df,
1012
+ spine_timestamp_col="snapshot_date",
1013
+ feature_date="2025-04-08"
1014
+ )
1015
+ ```
1016
+
1017
+ </details>
1018
+
1019
+ <details><summary> Clear Feature Serving Locks </summary>
1020
+
1021
+ #### Description
1022
+ Utility function to manually clear all feature serving locks. Use this if locks get stuck due to killed processes.
1023
+
1024
+ `gitlabds.clear_feature_serving_locks(session):`
1025
+
1026
+ #### Parameters:
1027
+ - **_session_** : Active Snowflake Session object
1028
+
1029
+ #### Returns
1030
+ - int: Number of locks cleared
1031
+
1032
+ #### Examples:
1033
+
1034
+ ```python
1035
+ # Clear stuck locks
1036
+ import gitlabds
1037
+ from snowflake.snowpark import Session
1038
+
1039
+ session = Session.builder.configs(...).create()
1040
+ locks_cleared = gitlabds.clear_feature_serving_locks(session)
1041
+ print(f"Cleared {locks_cleared} locks")
1042
+ ```
1043
+
1044
+ </details>
1045
+
906
1046
  ### SQL and Trend Analysis
907
1047
 
908
1048
  <details><summary> SQL Trend Query Generator </summary>
@@ -1,25 +1,5 @@
1
- Metadata-Version: 2.1
2
- Name: gitlabds
3
- Version: 2.1.7
4
- Summary: Gitlab Data Science and Modeling Tools
5
- Home-page: https://gitlab.com/gitlab-data/gitlabds
6
- Author: Kevin Dietz
7
- Author-email: kdietz@gitlab.com
8
- Classifier: Development Status :: 5 - Production/Stable
9
- Classifier: Intended Audience :: Developers
10
- Classifier: Intended Audience :: Science/Research
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
14
- Classifier: Topic :: Scientific/Engineering :: Information Analysis
15
- Classifier: Topic :: Software Development :: Libraries
16
- Classifier: Topic :: Utilities
17
- Requires-Python: >=3.10
18
- Description-Content-Type: text/markdown
19
- License-File: LICENSE
20
-
21
1
  [![PyPI version](https://badge.fury.io/py/gitlabds.svg)](https://badge.fury.io/py/gitlabds)
22
- [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
2
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
23
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
24
4
 
25
5
  # gitlabds
@@ -35,7 +15,7 @@ pip install gitlabds
35
15
 
36
16
  ### Requirements
37
17
 
38
- - Python 3.10 or later
18
+ - Python 3.11 or later
39
19
  - Core dependencies:
40
20
  - pandas>=1.5.3
41
21
  - numpy>=1.23.5
@@ -43,8 +23,27 @@ pip install gitlabds
43
23
  - scikit-learn>=1.1.1
44
24
  - imbalanced-learn>=0.9.1
45
25
  - seaborn>=0.13.2
46
- - shap>=0.41.0
26
+ - shap>=0.50.0
47
27
  - tqdm>=4.66.2
28
+ - xgboost>=1.6.1
29
+
30
+ ### Optional Dependencies
31
+
32
+ #### Snowflake Feature Store
33
+
34
+ The `serve_features` and `clear_feature_serving_locks` functions require additional Snowflake dependencies.
35
+
36
+ To use these functions, install with:
37
+
38
+ ```bash
39
+ pip install gitlabds[feature-store]
40
+ ```
41
+
42
+ This will install:
43
+ - `snowflake-snowpark-python`
44
+ - `snowflake-ml-python`
45
+
46
+ If you try to use these functions without installing the optional dependencies, you'll get an error message with installation instructions.
48
47
 
49
48
  ## Main Features by Category
50
49
 
@@ -903,6 +902,115 @@ feature_drift = results['feature_drift']
903
902
  ```
904
903
  </details>
905
904
 
905
+ ### Deployment
906
+
907
+ #### Feature Serving
908
+
909
+ <details><summary> Serve Features </summary>
910
+
911
+ #### Description
912
+ Serve features from Snowflake Feature Store with built-in distributed locking and retry logic. This function orchestrates feature retrieval from multiple feature views with support for point-in-time lookups and flexible parameter customization.
913
+
914
+ `gitlabds.serve_features(session, feature_store, feature_views_dict, spine_df=None, feature_date=None, spine_timestamp_col=None, include_feature_view_timestamp_col=False, lookback_window_value=None, lookback_window_unit=None, lock_timeout_seconds=300):`
915
+
916
+ #### Parameters:
917
+ - **_session_** : Active Snowflake Session object
918
+ - **_feature_store_** : Initialized FeatureStore instance
919
+ - **_feature_views_dict_** : Dictionary mapping feature view names to versions (e.g., {"sales_activities": "1.0"})
920
+ - **_spine_df_** : One of the following:
921
+ - SQL query string to generate the spine DataFrame
922
+ - pandas DataFrame (will be converted to Snowpark DataFrame)
923
+ - Snowpark DataFrame (used directly)
924
+ - **_feature_date_** : Date for feature retrieval (e.g., '2025-04-08'). If None, uses UDF default.
925
+ - **_spine_timestamp_col_** : Name of timestamp column in spine DataFrame for point-in-time lookup. Used for when multiple feature_dates may be present in the feature view. If only one feature_date is present, can set value to None for faster execution.
926
+ - **_include_feature_view_timestamp_col_** : Whether to include timestamp column from feature views in output. Default is False.
927
+ - **_lookback_window_value_** : Either a global integer value (e.g., 6) or a dict with feature-view-specific values
928
+ - **_lookback_window_unit_** : Either a global string value (e.g., 'months') or a dict with feature-view-specific values
929
+ - **_lock_timeout_seconds_** : Timeout in seconds for acquiring the Snowflake lock. Default is 300.
930
+
931
+ #### Returns
932
+ - DataFrame with combined features from all feature views
933
+
934
+ #### Requirements
935
+ This function requires Snowflake packages. Install with:
936
+ ```bash
937
+ pip install snowflake-snowpark-python snowflake-ml-python
938
+ ```
939
+
940
+ #### Examples:
941
+
942
+ ```python
943
+ # Basic usage with SQL spine
944
+ import gitlabds
945
+ from snowflake.snowpark import Session
946
+ from snowflake.ml.feature_store import FeatureStore
947
+
948
+ session = Session.builder.configs(...).create()
949
+ fs = FeatureStore(session, ...)
950
+
951
+ spine_sql = "SELECT account_id FROM accounts WHERE active = TRUE"
952
+ features = gitlabds.serve_features(
953
+ session=session,
954
+ feature_store=fs,
955
+ feature_views_dict={"sales_activities": "1.0", "marketing_activity": "2.1"},
956
+ spine_df=spine_sql,
957
+ feature_date=None
958
+ )
959
+ ```
960
+
961
+ ```python
962
+ # With per-feature-view parameters
963
+ features = gitlabds.serve_features(
964
+ session=session,
965
+ feature_store=fs,
966
+ feature_views_dict={"sales_activities": "1.0", "product_stage": "2.1"},
967
+ spine_df=spine_df,
968
+ lookback_window_value={"sales_activities": 3, "product_stage": 6},
969
+ lookback_window_unit={"sales_activities": "days", "product_stage": "months"}
970
+ )
971
+ ```
972
+
973
+ ```python
974
+ # With point-in-time lookup
975
+ features = gitlabds.serve_features(
976
+ session=session,
977
+ feature_store=fs,
978
+ feature_views_dict={"sales_activities": "1.0"},
979
+ spine_df=spine_df,
980
+ spine_timestamp_col="snapshot_date",
981
+ feature_date="2025-04-08"
982
+ )
983
+ ```
984
+
985
+ </details>
986
+
987
+ <details><summary> Clear Feature Serving Locks </summary>
988
+
989
+ #### Description
990
+ Utility function to manually clear all feature serving locks. Use this if locks get stuck due to killed processes.
991
+
992
+ `gitlabds.clear_feature_serving_locks(session):`
993
+
994
+ #### Parameters:
995
+ - **_session_** : Active Snowflake Session object
996
+
997
+ #### Returns
998
+ - int: Number of locks cleared
999
+
1000
+ #### Examples:
1001
+
1002
+ ```python
1003
+ # Clear stuck locks
1004
+ import gitlabds
1005
+ from snowflake.snowpark import Session
1006
+
1007
+ session = Session.builder.configs(...).create()
1008
+ locks_cleared = gitlabds.clear_feature_serving_locks(session)
1009
+ print(f"Cleared {locks_cleared} locks")
1010
+ ```
1011
+
1012
+ </details>
1013
+
906
1014
  ### SQL and Trend Analysis
907
1015
 
908
1016
  <details><summary> SQL Trend Query Generator </summary>
@@ -10,3 +10,18 @@ from .monitoring_metrics import calculate_monitoring_metrics, calculate_baseline
10
10
  from .outliers import mad_outliers, apply_outliers
11
11
  from .split_data import split_data
12
12
  from .trends import generate_sql_trend_query, trend_analysis
13
+
14
+ # Optional imports for Snowflake feature serving
15
+ try:
16
+ from .serving_features import clear_feature_serving_locks, serve_features
17
+ except ImportError as e:
18
+ # Snowflake packages not installed - create placeholder functions with helpful error messages
19
+ def _snowflake_not_installed(*args, **kwargs):
20
+ raise ImportError(
21
+ "Snowflake feature serving functions require additional dependencies. "
22
+ "Install them with: pip install snowflake-snowpark-python snowflake-ml-python\n\n"
23
+ )
24
+
25
+ clear_feature_serving_locks = _snowflake_not_installed
26
+ serve_features = _snowflake_not_installed
27
+
@@ -809,11 +809,9 @@ def memory_optimization(
809
809
  if sparsity > sparse_threshold:
810
810
  try:
811
811
  if isinstance(df_result, pd.Series):
812
- df_result = pd.Series.sparse.from_dense(
813
- df_result, fill_value=fill_value
814
- )
815
- else:
816
- df_result[col] = pd.Series.sparse.from_dense(
812
+
813
+ df_result = pd.arrays.SparseArray(df_result, fill_value=fill_value)
814
+ df_result[col] = pd.arrays.SparseArray(
817
815
  df_result[col], fill_value=fill_value
818
816
  )
819
817
 
@@ -0,0 +1,386 @@
1
+ """
2
+ Feature serving functionality for Snowflake Feature Store integration.
3
+
4
+ This module provides utilities for serving features from Snowflake Feature Store
5
+ in production environments, including distributed locking mechanisms and retry logic.
6
+
7
+ Note: This module requires snowflake-snowpark-python and snowflake-ml-python packages.
8
+ """
9
+
10
+ import time
11
+ import uuid
12
+ from typing import Dict, Optional, Union
13
+ import pandas as pd
14
+
15
+ # Optional imports with graceful fallback
16
+ try:
17
+ from snowflake.snowpark import Session, DataFrame as SnowparkDataFrame
18
+ from snowflake.ml.feature_store import FeatureStore
19
+ SNOWFLAKE_AVAILABLE = True
20
+ except ImportError:
21
+ SNOWFLAKE_AVAILABLE = False
22
+ SnowparkDataFrame = None
23
+ Session = None
24
+ FeatureStore = None
25
+
26
+
27
+ def _check_snowflake_available():
28
+ """Check if Snowflake packages are available."""
29
+ if not SNOWFLAKE_AVAILABLE:
30
+ raise ImportError(
31
+ "Snowflake packages are required for feature serving. "
32
+ "Install with: pip install snowflake-snowpark-python snowflake-ml-python"
33
+ )
34
+
35
+
36
+ def clear_feature_serving_locks(session: 'Session') -> int:
37
+ """
38
+ Utility function to manually clear all feature serving locks.
39
+
40
+ Use this if locks get stuck due to killed processes. This function checks
41
+ for existing locks, cleans up expired ones, and provides detailed status
42
+ information.
43
+
44
+ Args:
45
+ session: Snowflake Session object
46
+ Returns:
47
+ Number of locks cleared
48
+ """
49
+ _check_snowflake_available()
50
+
51
+ # Constants - these are safe, not user-controlled
52
+ LOCK_TABLE = "FEATURE_SERVING_LOCKS"
53
+ LOCK_NAME = "FEATURE_SERVING"
54
+
55
+ try:
56
+ # Check existing locks first
57
+ existing_locks = session.sql(f"""
58
+ SELECT session_id, acquired_at, expires_at,
59
+ CASE WHEN expires_at > CURRENT_TIMESTAMP() THEN 'ACTIVE' ELSE 'EXPIRED' END as status
60
+ FROM {LOCK_TABLE}
61
+ WHERE lock_name = '{LOCK_NAME}'
62
+ ORDER BY acquired_at DESC
63
+ """).collect()
64
+
65
+ if existing_locks:
66
+ print("🔍 Current feature serving locks:")
67
+ for lock in existing_locks:
68
+ print(f" Session: {lock['SESSION_ID']}, "
69
+ f"Acquired: {lock['ACQUIRED_AT']}, "
70
+ f"Expires: {lock['EXPIRES_AT']}, "
71
+ f"Status: {lock['STATUS']}")
72
+ else:
73
+ print("✅ No existing locks found")
74
+ return 0
75
+
76
+ # Clear all locks
77
+ session.sql(f"""
78
+ DELETE FROM {LOCK_TABLE}
79
+ WHERE lock_name = '{LOCK_NAME}'
80
+ """).collect()
81
+
82
+ locks_cleared = len(existing_locks)
83
+ print(f"🧹 Cleared {locks_cleared} feature serving locks")
84
+ return locks_cleared
85
+
86
+ except Exception as e:
87
+ print(f"❌ Error clearing locks: {e}")
88
+ return 0
89
+
90
+ def serve_features(
91
+ session: 'Session',
92
+ feature_store: 'FeatureStore',
93
+ feature_views_dict: Dict[str, str],
94
+ spine_df: Optional[Union[str, pd.DataFrame, 'SnowparkDataFrame']] = None,
95
+ feature_date: Optional[str] = None,
96
+ spine_timestamp_col: Optional[str] = None,
97
+ include_feature_view_timestamp_col: bool = False,
98
+ lookback_window_value: Optional[Union[int, Dict[str, int]]] = None,
99
+ lookback_window_unit: Optional[Union[str, Dict[str, str]]] = None,
100
+ lock_timeout_seconds: int = 300
101
+ ) -> pd.DataFrame:
102
+ """
103
+ Serve features using simplified workflow with Snowflake-based locking and retry mechanism.
104
+
105
+ This function orchestrates feature serving from Snowflake Feature Store with built-in
106
+ distributed locking to prevent concurrent executions and automatic retry logic for
107
+ robustness. It supports flexible spine DataFrame inputs and per-feature-view parameter
108
+ customization.
109
+
110
+ Parameters
111
+ ----------
112
+ session : snowflake.snowpark.Session
113
+ Active Snowflake Session object
114
+ feature_store : snowflake.ml.feature_store.FeatureStore
115
+ Initialized FeatureStore instance
116
+ feature_views_dict : Dict[str, str]
117
+ Dictionary mapping feature view names to versions (e.g., {"sales_activities": "1.0"})
118
+ spine_df : Union[str, pd.DataFrame, snowflake.snowpark.DataFrame], optional
119
+ One of the following:
120
+ - SQL query string to generate the spine DataFrame
121
+ - pandas DataFrame (will be converted to Snowpark DataFrame)
122
+ - Snowpark DataFrame (used directly)
123
+ - None will raise an error (spine is required by Feature Store SDK)
124
+ feature_date : str, optional
125
+ Snapshot date for features (e.g., '2025-04-08'). If None, uses UDF default.
126
+ spine_timestamp_col : str, optional
127
+ Name of timestamp column in spine DataFrame for point-in-time lookup.
128
+ If None, point-in-time lookup is disabled.
129
+ include_feature_view_timestamp_col : bool, default=False
130
+ Whether to include timestamp column from feature views in output
131
+ lookback_window_value : Union[int, Dict[str, int]], optional
132
+ Either a global integer value (e.g., 6) or a dict with feature-view-specific values
133
+ (e.g., {"sales_activities_by_account": 3, "product_stage_by_namespace": 2})
134
+ lookback_window_unit : Union[str, Dict[str, str]], optional
135
+ Either a global string value (e.g., 'months') or a dict with feature-view-specific values
136
+ (e.g., {"sales_activities_by_account": 'days', "product_stage_by_namespace": 'weeks'})
137
+ lock_timeout_seconds : int, default=300
138
+ Timeout in seconds for acquiring the Snowflake lock
139
+
140
+ Returns
141
+ -------
142
+ pd.DataFrame
143
+ DataFrame with combined features from all feature views, with column names
144
+ converted to lowercase
145
+ """
146
+ _check_snowflake_available()
147
+
148
+ # Constants - these are safe, not user-controlled
149
+ LOCK_TABLE = "FEATURE_SERVING_LOCKS"
150
+ LOCK_NAME = "FEATURE_SERVING"
151
+ session_id = f"session_{uuid.uuid4().hex[:8]}"
152
+
153
+ # Retry configuration
154
+ max_attempts = 10
155
+ retry_interval_seconds = 60
156
+
157
+ for attempt in range(1, max_attempts + 1):
158
+ try:
159
+ # Try to acquire lock using lock table approach
160
+ if attempt == 1:
161
+ print(f"🔒 [{session_id}] Attempting to acquire Snowflake lock: {LOCK_NAME}")
162
+ else:
163
+ print(f"🔒 [{session_id}] Retry attempt {attempt}/{max_attempts} to acquire lock: {LOCK_NAME}")
164
+
165
+ # Create lock table if it doesn't exist
166
+ session.sql(f"""
167
+ CREATE TABLE IF NOT EXISTS {LOCK_TABLE} (
168
+ lock_name VARCHAR,
169
+ session_id VARCHAR,
170
+ acquired_at TIMESTAMP_NTZ DEFAULT CURRENT_TIMESTAMP(),
171
+ expires_at TIMESTAMP_NTZ
172
+ )
173
+ """).collect()
174
+
175
+ # Clean up expired locks first (this handles killed processes)
176
+ session.sql(f"""
177
+ DELETE FROM {LOCK_TABLE}
178
+ WHERE expires_at < CURRENT_TIMESTAMP()
179
+ """).collect()
180
+ print(f"🧹 [{session_id}] Cleaned up expired locks")
181
+
182
+ # Try to acquire lock - session_id is UUID-generated, safe from injection
183
+ session.sql(f"""
184
+ INSERT INTO {LOCK_TABLE} (lock_name, session_id, expires_at)
185
+ SELECT '{LOCK_NAME}', '{session_id}', DATEADD(second, {lock_timeout_seconds}, CURRENT_TIMESTAMP())
186
+ WHERE NOT EXISTS (
187
+ SELECT 1 FROM {LOCK_TABLE}
188
+ WHERE lock_name = '{LOCK_NAME}'
189
+ AND expires_at > CURRENT_TIMESTAMP()
190
+ )
191
+ """).collect()
192
+
193
+ # Check if we got the lock - session_id is UUID-generated, safe from injection
194
+ lock_check = session.sql(f"""
195
+ SELECT COUNT(*) as lock_count
196
+ FROM {LOCK_TABLE}
197
+ WHERE lock_name = '{LOCK_NAME}'
198
+ AND session_id = '{session_id}'
199
+ AND expires_at > CURRENT_TIMESTAMP()
200
+ """).collect()
201
+
202
+ if lock_check[0]['LOCK_COUNT'] > 0:
203
+ # Successfully acquired lock
204
+ print(f"✅ [{session_id}] Acquired Snowflake lock: {LOCK_NAME}")
205
+ break
206
+ else:
207
+ # Lock is held by another session
208
+ existing_locks = session.sql(f"""
209
+ SELECT session_id, acquired_at, expires_at,
210
+ DATEDIFF(second, CURRENT_TIMESTAMP(), expires_at) as seconds_until_expiry
211
+ FROM {LOCK_TABLE}
212
+ WHERE lock_name = '{LOCK_NAME}'
213
+ AND expires_at > CURRENT_TIMESTAMP()
214
+ """).collect()
215
+
216
+ if existing_locks:
217
+ lock_info = existing_locks[0]
218
+ if attempt < max_attempts:
219
+ print(f"⏳ [{session_id}] Lock held by session {lock_info['SESSION_ID']} "
220
+ f"(expires in {lock_info['SECONDS_UNTIL_EXPIRY']} seconds). "
221
+ f"Retrying in {retry_interval_seconds} seconds... (attempt {attempt}/{max_attempts})")
222
+ time.sleep(retry_interval_seconds)
223
+ continue
224
+ else:
225
+ raise TimeoutError(f"Could not acquire lock after {max_attempts} attempts over {max_attempts * retry_interval_seconds // 60} minutes. "
226
+ f"Lock is held by session {lock_info['SESSION_ID']}, "
227
+ f"acquired at {lock_info['ACQUIRED_AT']}, expires in {lock_info['SECONDS_UNTIL_EXPIRY']} seconds. "
228
+ f"Please try again later.")
229
+ else:
230
+ if attempt < max_attempts:
231
+ print(f"⏳ [{session_id}] Could not acquire lock (unknown reason). "
232
+ f"Retrying in {retry_interval_seconds} seconds... (attempt {attempt}/{max_attempts})")
233
+ time.sleep(retry_interval_seconds)
234
+ continue
235
+ else:
236
+ raise TimeoutError(f"Could not acquire lock after {max_attempts} attempts for unknown reason. Please try again later.")
237
+
238
+ except TimeoutError:
239
+ # Re-raise TimeoutError to exit the retry loop
240
+ raise
241
+ except ValueError:
242
+ # Re-raise specific exceptions that shouldn't be retried
243
+ raise
244
+ except Exception as e:
245
+ if attempt < max_attempts:
246
+ print(f"❌ [{session_id}] Error during lock acquisition attempt {attempt}/{max_attempts}: {e}")
247
+ print(f"⏳ [{session_id}] Retrying in {retry_interval_seconds} seconds...")
248
+ time.sleep(retry_interval_seconds)
249
+ continue
250
+ else:
251
+ raise Exception(f"Failed to acquire lock after {max_attempts} attempts. Last error: {e}")
252
+
253
+ # If we get here, we have the lock - proceed with feature serving
254
+ try:
255
+ feature_views_list = []
256
+
257
+ # Loop over all feature views to create the dynamic views
258
+ for fv_name, version in feature_views_dict.items():
259
+ fv = feature_store.get_feature_view(fv_name, version)
260
+ feature_views_list.append(fv)
261
+
262
+ # Derive dynamic view and UDF names from feature view name using naming convention
263
+ # Convention: feature_view_name -> feature_view_name_dynamic (view) and feature_view_name_udf (function)
264
+ dynamic_view = f"{fv_name.upper()}_DYNAMIC"
265
+ udf_name = f"{fv_name.upper()}_UDF"
266
+
267
+ # Extract metadata from FeatureView
268
+ entity_id = fv.entities[0].join_keys[0]
269
+ timestamp_col = fv.timestamp_col
270
+
271
+ print(f"[{session_id}] {fv_name} v{version}:")
272
+ print(f" Dynamic View: {dynamic_view}")
273
+ print(f" UDF: {udf_name}")
274
+ print(f" Entity: {entity_id}")
275
+ print(f" Timestamp: {timestamp_col}")
276
+
277
+ # Build parameters in the new order: SNAPSHOT_DATE, LOOKBACK_WINDOW_VALUE, LOOKBACK_WINDOW_UNIT
278
+ udf_params = []
279
+
280
+ # First parameter: SNAPSHOT_DATE (feature_date) - pass as DATE type, not string
281
+ if feature_date:
282
+ date_str = str(feature_date)
283
+ udf_params.append(f"'{date_str}'::DATE")
284
+ print(f" Using snapshot date: {date_str}")
285
+ else:
286
+ print(f" Using UDF default snapshot date")
287
+
288
+ # Second parameter: LOOKBACK_WINDOW_VALUE
289
+ if lookback_window_value is not None:
290
+ if isinstance(lookback_window_value, dict):
291
+ if fv_name in lookback_window_value:
292
+ value_param = lookback_window_value[fv_name]
293
+ udf_params.append(str(value_param))
294
+ print(f" Using per-UDF lookback window value: {value_param}")
295
+ else:
296
+ print(f" Using UDF default lookback window value")
297
+ else:
298
+ # Global value
299
+ udf_params.append(str(lookback_window_value))
300
+ print(f" Using global lookback window value: {lookback_window_value}")
301
+ else:
302
+ print(f" Using UDF default lookback window value")
303
+
304
+ # Third parameter: LOOKBACK_WINDOW_UNIT
305
+ if lookback_window_unit is not None:
306
+ if isinstance(lookback_window_unit, dict):
307
+ if fv_name in lookback_window_unit:
308
+ unit_param = lookback_window_unit[fv_name]
309
+ udf_params.append(f"'{unit_param}'")
310
+ print(f" Using per-UDF lookback window unit: {unit_param}")
311
+ else:
312
+ print(f" Using UDF default lookback window unit")
313
+ else:
314
+ # Global value
315
+ udf_params.append(f"'{lookback_window_unit}'")
316
+ print(f" Using global lookback window unit: {lookback_window_unit}")
317
+ else:
318
+ print(f" Using UDF default lookback window unit")
319
+
320
+ # Create the UDF call with parameters in the correct order
321
+ params_str = ', '.join(udf_params) if udf_params else ''
322
+ update_view_sql = f"""
323
+ CREATE OR REPLACE VIEW {dynamic_view} AS
324
+ SELECT * FROM TABLE({udf_name}({params_str}))
325
+ """
326
+
327
+ print(f" {update_view_sql.strip()}")
328
+
329
+ session.sql(update_view_sql).collect()
330
+ print(f" [{session_id}] Updated {dynamic_view}")
331
+
332
+ # Handle spine_df - convert to Snowpark DataFrame as needed
333
+ if spine_df is None:
334
+ raise ValueError("spine_df is required - the Snowflake Feature Store SDK requires a spine DataFrame")
335
+ elif isinstance(spine_df, str):
336
+ # SQL query string
337
+ snowpark_spine_df = session.sql(spine_df)
338
+ print(f"[{session_id}] Created spine from SQL query")
339
+ elif isinstance(spine_df, pd.DataFrame):
340
+ # pandas DataFrame - convert to Snowpark
341
+ snowpark_spine_df = session.create_dataframe(spine_df)
342
+ print(f"[{session_id}] Created spine from pandas DataFrame")
343
+ elif SNOWFLAKE_AVAILABLE and isinstance(spine_df, SnowparkDataFrame):
344
+ # Already a Snowpark DataFrame
345
+ snowpark_spine_df = spine_df
346
+ print(f"[{session_id}] Using provided Snowpark DataFrame")
347
+ else:
348
+ raise TypeError(f"spine_df must be a SQL query string, pandas DataFrame, or Snowpark DataFrame. Got: {type(spine_df)}")
349
+
350
+ print(f"[{session_id}] Spine contains {snowpark_spine_df.count()} entities")
351
+
352
+ # Build retrieve_feature_values arguments conditionally
353
+ retrieve_kwargs = {
354
+ "spine_df": snowpark_spine_df,
355
+ "features": feature_views_list,
356
+ "include_feature_view_timestamp_col": include_feature_view_timestamp_col
357
+ }
358
+
359
+ # Only include spine_timestamp_col if provided
360
+ if spine_timestamp_col is not None:
361
+ retrieve_kwargs["spine_timestamp_col"] = spine_timestamp_col
362
+ print(f"[{session_id}] Using point-in-time lookup with timestamp column: {spine_timestamp_col}")
363
+ else:
364
+ print(f"[{session_id}] Point-in-time lookup disabled (no spine_timestamp_col)")
365
+
366
+ # Retrieve combined features
367
+ print(f"[{session_id}] Starting retrieve_feature_values (this may take a while)...")
368
+ combined_features = feature_store.retrieve_feature_values(**retrieve_kwargs)
369
+
370
+ combined_features = combined_features.to_arrow().to_pandas()
371
+ combined_features.columns = map(str.lower, combined_features.columns)
372
+
373
+ print(f"✅ [{session_id}] Feature serving completed successfully")
374
+ return combined_features
375
+
376
+ finally:
377
+ # Always release the lock
378
+ try:
379
+ session.sql(f"""
380
+ DELETE FROM {LOCK_TABLE}
381
+ WHERE lock_name = '{LOCK_NAME}'
382
+ AND session_id = '{session_id}'
383
+ """).collect()
384
+ print(f"🔓 [{session_id}] Released Snowflake lock: {LOCK_NAME}")
385
+ except Exception as e:
386
+ print(f"⚠️ [{session_id}] Error releasing lock: {e}")
@@ -1,5 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: gitlabds
3
+ Version: 2.1.9
4
+ Summary: GitLab Data Science Tools
5
+ Author-email: Kevin Dietz <kdietz@gitlab.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://gitlab.com/gitlab-data/gitlabds
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
13
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Classifier: Topic :: Utilities
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: pandas>=1.5.3
20
+ Requires-Dist: numpy>=1.23.5
21
+ Requires-Dist: scipy>=1.13.1
22
+ Requires-Dist: scikit-learn>=1.1.1
23
+ Requires-Dist: imbalanced-learn>=0.9.1
24
+ Requires-Dist: seaborn>=0.13.2
25
+ Requires-Dist: shap>=0.50.0
26
+ Requires-Dist: tqdm>=4.66.2
27
+ Requires-Dist: xgboost>=1.6.1
28
+ Provides-Extra: feature-store
29
+ Requires-Dist: snowflake-snowpark-python; extra == "feature-store"
30
+ Requires-Dist: snowflake-ml-python; extra == "feature-store"
31
+ Dynamic: license-file
32
+
1
33
  [![PyPI version](https://badge.fury.io/py/gitlabds.svg)](https://badge.fury.io/py/gitlabds)
2
- [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
34
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
3
35
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
36
 
5
37
  # gitlabds
@@ -15,7 +47,7 @@ pip install gitlabds
15
47
 
16
48
  ### Requirements
17
49
 
18
- - Python 3.10 or later
50
+ - Python 3.11 or later
19
51
  - Core dependencies:
20
52
  - pandas>=1.5.3
21
53
  - numpy>=1.23.5
@@ -23,8 +55,27 @@ pip install gitlabds
23
55
  - scikit-learn>=1.1.1
24
56
  - imbalanced-learn>=0.9.1
25
57
  - seaborn>=0.13.2
26
- - shap>=0.41.0
58
+ - shap>=0.50.0
27
59
  - tqdm>=4.66.2
60
+ - xgboost>=1.6.1
61
+
62
+ ### Optional Dependencies
63
+
64
+ #### Snowflake Feature Store
65
+
66
+ The `serve_features` and `clear_feature_serving_locks` functions require additional Snowflake dependencies.
67
+
68
+ To use these functions, install with:
69
+
70
+ ```bash
71
+ pip install gitlabds[feature-store]
72
+ ```
73
+
74
+ This will install:
75
+ - `snowflake-snowpark-python`
76
+ - `snowflake-ml-python`
77
+
78
+ If you try to use these functions without installing the optional dependencies, you'll get an error message with installation instructions.
28
79
 
29
80
  ## Main Features by Category
30
81
 
@@ -883,6 +934,115 @@ feature_drift = results['feature_drift']
883
934
  ```
884
935
  </details>
885
936
 
937
+ ### Deployment
938
+
939
+ #### Feature Serving
940
+
941
+ <details><summary> Serve Features </summary>
942
+
943
+ #### Description
944
+ Serve features from Snowflake Feature Store with built-in distributed locking and retry logic. This function orchestrates feature retrieval from multiple feature views with support for point-in-time lookups and flexible parameter customization.
945
+
946
+ `gitlabds.serve_features(session, feature_store, feature_views_dict, spine_df=None, feature_date=None, spine_timestamp_col=None, include_feature_view_timestamp_col=False, lookback_window_value=None, lookback_window_unit=None, lock_timeout_seconds=300):`
947
+
948
+ #### Parameters:
949
+ - **_session_** : Active Snowflake Session object
950
+ - **_feature_store_** : Initialized FeatureStore instance
951
+ - **_feature_views_dict_** : Dictionary mapping feature view names to versions (e.g., {"sales_activities": "1.0"})
952
+ - **_spine_df_** : One of the following:
953
+ - SQL query string to generate the spine DataFrame
954
+ - pandas DataFrame (will be converted to Snowpark DataFrame)
955
+ - Snowpark DataFrame (used directly)
956
+ - **_feature_date_** : Date for feature retrieval (e.g., '2025-04-08'). If None, uses UDF default.
957
+ - **_spine_timestamp_col_** : Name of timestamp column in spine DataFrame for point-in-time lookup. Used for when multiple feature_dates may be present in the feature view. If only one feature_date is present, can set value to None for faster execution.
958
+ - **_include_feature_view_timestamp_col_** : Whether to include timestamp column from feature views in output. Default is False.
959
+ - **_lookback_window_value_** : Either a global integer value (e.g., 6) or a dict with feature-view-specific values
960
+ - **_lookback_window_unit_** : Either a global string value (e.g., 'months') or a dict with feature-view-specific values
961
+ - **_lock_timeout_seconds_** : Timeout in seconds for acquiring the Snowflake lock. Default is 300.
962
+
963
+ #### Returns
964
+ - DataFrame with combined features from all feature views
965
+
966
+ #### Requirements
967
+ This function requires Snowflake packages. Install with:
968
+ ```bash
969
+ pip install snowflake-snowpark-python snowflake-ml-python
970
+ ```
971
+
972
+ #### Examples:
973
+
974
+ ```python
975
+ # Basic usage with SQL spine
976
+ import gitlabds
977
+ from snowflake.snowpark import Session
978
+ from snowflake.ml.feature_store import FeatureStore
979
+
980
+ session = Session.builder.configs(...).create()
981
+ fs = FeatureStore(session, ...)
982
+
983
+ spine_sql = "SELECT account_id FROM accounts WHERE active = TRUE"
984
+ features = gitlabds.serve_features(
985
+ session=session,
986
+ feature_store=fs,
987
+ feature_views_dict={"sales_activities": "1.0", "marketing_activity": "2.1"},
988
+ spine_df=spine_sql,
989
+ feature_date=None
990
+ )
991
+ ```
992
+
993
+ ```python
994
+ # With per-feature-view parameters
995
+ features = gitlabds.serve_features(
996
+ session=session,
997
+ feature_store=fs,
998
+ feature_views_dict={"sales_activities": "1.0", "product_stage": "2.1"},
999
+ spine_df=spine_df,
1000
+ lookback_window_value={"sales_activities": 3, "product_stage": 6},
1001
+ lookback_window_unit={"sales_activities": "days", "product_stage": "months"}
1002
+ )
1003
+ ```
1004
+
1005
+ ```python
1006
+ # With point-in-time lookup
1007
+ features = gitlabds.serve_features(
1008
+ session=session,
1009
+ feature_store=fs,
1010
+ feature_views_dict={"sales_activities": "1.0"},
1011
+ spine_df=spine_df,
1012
+ spine_timestamp_col="snapshot_date",
1013
+ feature_date="2025-04-08"
1014
+ )
1015
+ ```
1016
+
1017
+ </details>
1018
+
1019
+ <details><summary> Clear Feature Serving Locks </summary>
1020
+
1021
+ #### Description
1022
+ Utility function to manually clear all feature serving locks. Use this if locks get stuck due to killed processes.
1023
+
1024
+ `gitlabds.clear_feature_serving_locks(session):`
1025
+
1026
+ #### Parameters:
1027
+ - **_session_** : Active Snowflake Session object
1028
+
1029
+ #### Returns
1030
+ - int: Number of locks cleared
1031
+
1032
+ #### Examples:
1033
+
1034
+ ```python
1035
+ # Clear stuck locks
1036
+ import gitlabds
1037
+ from snowflake.snowpark import Session
1038
+
1039
+ session = Session.builder.configs(...).create()
1040
+ locks_cleared = gitlabds.clear_feature_serving_locks(session)
1041
+ print(f"Cleared {locks_cleared} locks")
1042
+ ```
1043
+
1044
+ </details>
1045
+
886
1046
  ### SQL and Trend Analysis
887
1047
 
888
1048
  <details><summary> SQL Trend Query Generator </summary>
@@ -1,5 +1,6 @@
1
1
  LICENSE
2
2
  README.md
3
+ pyproject.toml
3
4
  setup.py
4
5
  gitlabds/__init__.py
5
6
  gitlabds/baselines.py
@@ -14,11 +15,11 @@ gitlabds/missing_fill.py
14
15
  gitlabds/model_evaluator.py
15
16
  gitlabds/monitoring_metrics.py
16
17
  gitlabds/outliers.py
18
+ gitlabds/serving_features.py
17
19
  gitlabds/split_data.py
18
20
  gitlabds/trends.py
19
21
  gitlabds.egg-info/PKG-INFO
20
22
  gitlabds.egg-info/SOURCES.txt
21
23
  gitlabds.egg-info/dependency_links.txt
22
24
  gitlabds.egg-info/requires.txt
23
- gitlabds.egg-info/top_level.txt
24
- tests/__init__.py
25
+ gitlabds.egg-info/top_level.txt
@@ -4,5 +4,10 @@ scipy>=1.13.1
4
4
  scikit-learn>=1.1.1
5
5
  imbalanced-learn>=0.9.1
6
6
  seaborn>=0.13.2
7
- shap>=0.41.0
7
+ shap>=0.50.0
8
8
  tqdm>=4.66.2
9
+ xgboost>=1.6.1
10
+
11
+ [feature-store]
12
+ snowflake-snowpark-python
13
+ snowflake-ml-python
@@ -0,0 +1,48 @@
1
+ [build-system]
2
+ requires = ["setuptools>=45", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "gitlabds"
7
+ description = "GitLab Data Science Tools"
8
+ dynamic = ["version"]
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ authors = [
13
+ {name = "Kevin Dietz", email = "kdietz@gitlab.com"}
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 5 - Production/Stable",
17
+ "Intended Audience :: Developers",
18
+ "Intended Audience :: Science/Research",
19
+ "Programming Language :: Python :: 3",
20
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
21
+ "Topic :: Scientific/Engineering :: Information Analysis",
22
+ "Topic :: Software Development :: Libraries",
23
+ "Topic :: Utilities",
24
+ ]
25
+ dependencies = [
26
+ "pandas>=1.5.3",
27
+ "numpy>=1.23.5",
28
+ "scipy>=1.13.1",
29
+ "scikit-learn>=1.1.1",
30
+ "imbalanced-learn>=0.9.1",
31
+ "seaborn>=0.13.2",
32
+ "shap>=0.50.0",
33
+ "tqdm>=4.66.2",
34
+ "xgboost>=1.6.1",
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ feature-store = [
39
+ "snowflake-snowpark-python",
40
+ "snowflake-ml-python",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://gitlab.com/gitlab-data/gitlabds"
45
+
46
+ [tool.setuptools]
47
+ packages = ["gitlabds"]
48
+
@@ -0,0 +1,11 @@
1
+ import setuptools, os
2
+
3
+ if os.environ.get('CI_COMMIT_TAG'):
4
+ version = os.environ['CI_COMMIT_TAG']
5
+ elif os.environ.get('CI_JOB_ID'):
6
+ version = os.environ['CI_JOB_ID']
7
+ else:
8
+ version = "0.0.0-dev"
9
+
10
+ setuptools.setup(version=version)
11
+
gitlabds-2.1.7/setup.py DELETED
@@ -1,41 +0,0 @@
1
- import setuptools, os
2
- from pathlib import Path
3
-
4
- if os.environ.get('CI_COMMIT_TAG'):
5
- version = os.environ['CI_COMMIT_TAG']
6
- elif os.environ.get('CI_JOB_ID'):
7
- version = os.environ['CI_JOB_ID']
8
- else:
9
- version = "0.0.0-dev"
10
-
11
- requires = ["pandas>=1.5.3", "numpy>=1.23.5", "scipy>=1.13.1", "scikit-learn>=1.1.1", "imbalanced-learn>=0.9.1", "seaborn>=0.13.2", "shap>=0.41.0", "tqdm>=4.66.2"]
12
-
13
- # read the contents of README file
14
- this_directory = Path(__file__).parent
15
- long_description = (this_directory / "README.md").read_text()
16
-
17
- setuptools.setup(
18
- name='gitlabds',
19
- version=version,
20
- description='Gitlab Data Science and Modeling Tools',
21
- long_description = long_description,
22
- long_description_content_type ='text/markdown',
23
- author='Kevin Dietz',
24
- author_email='kdietz@gitlab.com',
25
- packages=setuptools.find_packages(),
26
- url='https://gitlab.com/gitlab-data/gitlabds',
27
- classifiers=[
28
- 'Development Status :: 5 - Production/Stable',
29
- 'Intended Audience :: Developers',
30
- 'Intended Audience :: Science/Research',
31
- 'License :: OSI Approved :: MIT License',
32
- 'Programming Language :: Python :: 3',
33
- 'Topic :: Scientific/Engineering :: Artificial Intelligence',
34
- 'Topic :: Scientific/Engineering :: Information Analysis',
35
- 'Topic :: Software Development :: Libraries',
36
- 'Topic :: Utilities',
37
- ],
38
- python_requires= '>=3.10',
39
- install_requires=requires,
40
- )
41
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes