@@ -55,14 +55,36 @@ protos: compile-protos-python compile-protos-docs ## Compile protobufs for Pytho |
55 | 55 | build: protos build-docker ## Build protobufs and Docker images |
56 | 56 |
|
57 | 57 | format-python: ## Format Python code |
58 | | - cd ${ROOT_DIR}/sdk/python; python -m ruff check --fix feast/ tests/ |
59 | | - cd ${ROOT_DIR}/sdk/python; python -m ruff format feast/ tests/ |
| 58 | + uv run ruff check --fix sdk/python/feast/ sdk/python/tests/ |
| 59 | + uv run ruff format sdk/python/feast/ sdk/python/tests/ |
60 | 60 |
|
61 | 61 | lint-python: ## Lint Python code |
62 | | - cd ${ROOT_DIR}/sdk/python; python -m mypy feast |
63 | | - cd ${ROOT_DIR}/sdk/python; python -m ruff check feast/ tests/ |
64 | | - cd ${ROOT_DIR}/sdk/python; python -m ruff format --check feast/ tests |
65 | | - |
| 62 | + uv run ruff check sdk/python/feast/ sdk/python/tests/ |
| 63 | + uv run ruff format --check sdk/python/feast/ sdk/python/tests/ |
| 64 | + uv run bash -c "cd sdk/python && mypy feast" |
| 65 | + |
| 66 | +# New combined target |
| 67 | +precommit-check: format-python lint-python ## Run all precommit checks |
| 68 | + @echo "✅ All precommit checks passed" |
| 69 | + |
| 70 | +# Install precommit hooks with correct stages |
| 71 | +install-precommit: ## Install precommit hooks (runs on commit, not push) |
| 72 | + pip install pre-commit |
| 73 | + pre-commit install --hook-type pre-commit |
| 74 | + @echo "✅ Precommit hooks installed (will run on commit, not push)" |
| 75 | + |
| 76 | +# Manual full type check |
| 77 | +mypy-full: ## Full MyPy type checking with all files |
| 78 | + uv run bash -c "cd sdk/python && mypy feast tests" |
| 79 | + |
| 80 | +# Run precommit on all files |
| 81 | +precommit-all: ## Run all precommit hooks on all files |
| 82 | + pre-commit run --all-files |
| 83 | + |
| 84 | +# Make scripts executable |
| 85 | +setup-scripts: ## Make helper scripts executable |
| 86 | + chmod +x scripts/uv-run.sh scripts/check-init-py.sh scripts/mypy-daemon.sh |
| 87 | + |
66 | 88 | ##@ Python SDK - local |
67 | 89 | # formerly install-python-ci-dependencies-uv-venv |
68 | 90 | # editable install |
@@ -74,23 +96,22 @@ install-python-dependencies-minimal: ## Install minimal Python dependencies usin |
74 | 96 | uv pip sync --require-hashes sdk/python/requirements/py$(PYTHON_VERSION)-minimal-requirements.txt |
75 | 97 | uv pip install --no-deps -e .[minimal] |
76 | 98 |
|
77 | | -##@ Python SDK - system |
78 | | -# the --system flag installs dependencies in the global python context |
79 | | -# instead of a venv which is useful when working in a docker container or ci. |
| 99 | +##@ Python SDK - CI (uses uv with virtualenv) |
| 100 | +# Uses uv pip sync with virtualenv for CI environments |
80 | 101 |
|
81 | 102 | # Used in github actions/ci |
82 | | -# formerly install-python-ci-dependencies-uv |
83 | | -install-python-dependencies-ci: ## Install Python CI dependencies in system environment using uv |
84 | | - # Install CPU-only torch first to prevent CUDA dependency issues |
85 | | - pip uninstall torch torchvision -y || true |
| 103 | +install-python-dependencies-ci: ## Install Python CI dependencies using uv pip sync |
| 104 | + # Create virtualenv if it doesn't exist |
| 105 | + uv venv .venv |
| 106 | + # Install CPU-only torch first to prevent CUDA dependency issues (Linux only) |
86 | 107 | @if [ "$$(uname -s)" = "Linux" ]; then \ |
87 | 108 | echo "Installing dependencies with torch CPU index for Linux..."; \ |
88 | | - uv pip sync --system --extra-index-url https://download.pytorch.org/whl/cpu --index-strategy unsafe-best-match sdk/python/requirements/py$(PYTHON_VERSION)-ci-requirements.txt; \ |
| 109 | + uv pip sync --extra-index-url https://download.pytorch.org/whl/cpu --index-strategy unsafe-best-match sdk/python/requirements/py$(PYTHON_VERSION)-ci-requirements.txt; \ |
89 | 110 | else \ |
90 | 111 | echo "Installing dependencies from PyPI for macOS..."; \ |
91 | | - uv pip sync --system sdk/python/requirements/py$(PYTHON_VERSION)-ci-requirements.txt; \ |
| 112 | + uv pip sync sdk/python/requirements/py$(PYTHON_VERSION)-ci-requirements.txt; \ |
92 | 113 | fi |
93 | | - uv pip install --system --no-deps -e . |
| 114 | + uv pip install --no-deps -e . |
94 | 115 |
|
95 | 116 | # Used in github actions/ci |
96 | 117 | install-hadoop-dependencies-ci: ## Install Hadoop dependencies |
@@ -151,22 +172,44 @@ benchmark-python-local: ## Run integration + benchmark tests for Python (local d |
151 | 172 | ##@ Tests |
152 | 173 |
|
153 | 174 | test-python-unit: ## Run Python unit tests (use pattern=<pattern> to filter tests, e.g., pattern=milvus, pattern=test_online_retrieval.py, pattern=test_online_retrieval.py::test_get_online_features_milvus) |
154 | | - python -m pytest -n 8 --color=yes $(if $(pattern),-k "$(pattern)") sdk/python/tests |
| 175 | + uv run python -m pytest -n 8 --color=yes $(if $(pattern),-k "$(pattern)") sdk/python/tests |
| 176 | + |
| 177 | +# Fast unit tests only |
| 178 | +test-python-unit-fast: ## Run fast unit tests only (no external dependencies) |
| 179 | + uv run python -m pytest sdk/python/tests/unit -n auto -x --tb=short |
| 180 | + |
| 181 | +# Changed files only (requires pytest-testmon) |
| 182 | +test-python-changed: ## Run tests for changed files only |
| 183 | + uv run python -m pytest --testmon -n 8 --tb=short sdk/python/tests |
| 184 | + |
| 185 | +# Quick smoke test for PRs |
| 186 | +test-python-smoke: ## Quick smoke test for development |
| 187 | + uv run python -m pytest \ |
| 188 | + sdk/python/tests/unit/test_unit_feature_store.py \ |
| 189 | + sdk/python/tests/unit/test_repo_operations_validate_feast_project_name.py \ |
| 190 | + -n 4 --tb=short |
155 | 191 |
|
156 | 192 | test-python-integration: ## Run Python integration tests (CI) |
157 | | - python -m pytest --tb=short -v -n 8 --integration --color=yes --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ |
| 193 | + uv run python -m pytest --tb=short -v -n 8 --integration --color=yes --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ |
158 | 194 | -k "(not snowflake or not test_historical_features_main)" \ |
159 | 195 | -m "not rbac_remote_integration_test" \ |
160 | 196 | --log-cli-level=INFO -s \ |
161 | 197 | sdk/python/tests |
162 | 198 |
|
| 199 | +# Integration tests with better parallelization |
| 200 | +test-python-integration-parallel: ## Run integration tests with enhanced parallelization |
| 201 | + uv run python -m pytest sdk/python/tests/integration \ |
| 202 | + -n auto --dist loadscope \ |
| 203 | + --timeout=300 --tb=short -v \ |
| 204 | + --integration --color=yes --durations=20 |
| 205 | + |
163 | 206 | test-python-integration-local: ## Run Python integration tests (local dev mode) |
164 | 207 | FEAST_IS_LOCAL_TEST=True \ |
165 | 208 | FEAST_LOCAL_ONLINE_CONTAINER=True \ |
166 | 209 | HADOOP_HOME=$$HOME/hadoop \ |
167 | 210 | CLASSPATH="$$( $$HADOOP_HOME/bin/hadoop classpath --glob ):$$CLASSPATH" \ |
168 | 211 | HADOOP_USER_NAME=root \ |
169 | | - python -m pytest --tb=short -v -n 8 --color=yes --integration --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ |
| 212 | + uv run python -m pytest --tb=short -v -n 8 --color=yes --integration --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ |
170 | 213 | -k "not test_lambda_materialization and not test_snowflake_materialization" \ |
171 | 214 | -m "not rbac_remote_integration_test" \ |
172 | 215 | --log-cli-level=INFO -s \ |
@@ -175,7 +218,7 @@ test-python-integration-local: ## Run Python integration tests (local dev mode) |
175 | 218 | test-python-integration-rbac-remote: ## Run Python remote RBAC integration tests |
176 | 219 | FEAST_IS_LOCAL_TEST=True \ |
177 | 220 | FEAST_LOCAL_ONLINE_CONTAINER=True \ |
178 | | - python -m pytest --tb=short -v -n 8 --color=yes --integration --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ |
| 221 | + uv run python -m pytest --tb=short -v -n 8 --color=yes --integration --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ |
179 | 222 | -k "not test_lambda_materialization and not test_snowflake_materialization" \ |
180 | 223 | -m "rbac_remote_integration_test" \ |
181 | 224 | --log-cli-level=INFO -s \ |
@@ -184,7 +227,7 @@ test-python-integration-rbac-remote: ## Run Python remote RBAC integration tests |
184 | 227 | test-python-integration-container: ## Run Python integration tests using Docker |
185 | 228 | @(docker info > /dev/null 2>&1 && \ |
186 | 229 | FEAST_LOCAL_ONLINE_CONTAINER=True \ |
187 | | - python -m pytest -n 8 --integration sdk/python/tests \ |
| 230 | + uv run python -m pytest -n 8 --integration sdk/python/tests \ |
188 | 231 | ) || echo "This script uses Docker, and it isn't running - please start the Docker Daemon and try again!"; |
189 | 232 |
|
190 | 233 | test-python-integration-dbt: ## Run dbt integration tests |
@@ -242,7 +285,7 @@ test-python-historical-retrieval: |
242 | 285 | test_historical_features_persisting or \ |
243 | 286 | test_historical_retrieval_fails_on_validation" \ |
244 | 287 | sdk/python/tests |
245 | | - |
| 288 | + |
246 | 289 | test-python-universal-trino: ## Run Python Trino integration tests |
247 | 290 | PYTHONPATH='.' \ |
248 | 291 | FULL_REPO_CONFIGS_MODULE=sdk.python.feast.infra.offline_stores.contrib.trino_repo_configuration \ |
@@ -578,7 +621,7 @@ test-python-universal-couchbase-online: ## Run Python Couchbase online store int |
578 | 621 | sdk/python/tests |
579 | 622 |
|
580 | 623 | test-python-universal: ## Run all Python integration tests |
581 | | - python -m pytest -n 8 --integration sdk/python/tests |
| 624 | + uv run python -m pytest -n 8 --integration sdk/python/tests |
582 | 625 |
|
583 | 626 | ##@ Java |
584 | 627 |
|
@@ -644,7 +687,7 @@ build-feature-transformation-server-docker: ## Build Feature Transformation Serv |
644 | 687 | push-feature-server-java-docker: ## Push Feature Server Java Docker image |
645 | 688 | docker push $(REGISTRY)/feature-server-java:$(VERSION) |
646 | 689 |
|
647 | | -build-feature-server-java-docker: ## Build Feature Server Java Docker image |
| 690 | +build-feature-server-java-docker: ## Build Feature Server Java Docker image |
648 | 691 | docker buildx build --build-arg VERSION=$(VERSION) \ |
649 | 692 | -t $(REGISTRY)/feature-server-java:$(VERSION) \ |
650 | 693 | -f java/infra/docker/feature-server/Dockerfile --load . |
@@ -749,12 +792,12 @@ build-ui-local: ## Build Feast UI locally |
749 | 792 | cd $(ROOT_DIR)/ui && yarn install && npm run build --omit=dev |
750 | 793 | rm -rf $(ROOT_DIR)/sdk/python/feast/ui/build |
751 | 794 | cp -r $(ROOT_DIR)/ui/build $(ROOT_DIR)/sdk/python/feast/ui/ |
752 | | - |
| 795 | + |
753 | 796 | format-ui: ## Format Feast UI |
754 | 797 | cd $(ROOT_DIR)/ui && NPM_TOKEN= yarn install && NPM_TOKEN= yarn format |
755 | 798 |
|
756 | 799 |
|
757 | | -##@ Go SDK |
| 800 | +##@ Go SDK |
758 | 801 | PB_REL = https://github.com/protocolbuffers/protobuf/releases |
759 | 802 | PB_VERSION = 30.2 |
760 | 803 | PB_ARCH := $(shell uname -m) |
@@ -820,4 +863,3 @@ build-go-docker-dev: ## Build Go Docker image for development |
820 | 863 | docker buildx build --build-arg VERSION=dev \ |
821 | 864 | -t feastdev/feature-server-go:dev \ |
822 | 865 | -f go/infra/docker/feature-server/Dockerfile --load . |
823 | | - |
|