diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml index 4d4b1812..e3f92a6a 100644 --- a/.github/workflows/checks.yaml +++ b/.github/workflows/checks.yaml @@ -80,6 +80,21 @@ jobs: run: | mise exec python@${{ matrix.python-version }} -- python ./py/scripts/nox-matrix.py ${{ matrix.shard }} 4 + vulture: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - name: Set up mise + uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4.0.1 + with: + cache: true + experimental: true + - name: Install dev dependencies + run: mise exec -- make -C py install-dev + - name: Run vulture dead-code check + run: mise exec -- make -C py vulture + adk-py: uses: ./.github/workflows/adk-py-test.yaml @@ -116,6 +131,7 @@ jobs: - ensure-pinned-actions - smoke - nox + - vulture - adk-py - langchain-py - upload-wheel @@ -141,6 +157,7 @@ jobs: check_result "ensure-pinned-actions" "${{ needs.ensure-pinned-actions.result }}" check_result "smoke" "${{ needs.smoke.result }}" check_result "nox" "${{ needs.nox.result }}" + check_result "vulture" "${{ needs.vulture.result }}" check_result "adk-py" "${{ needs.adk-py.result }}" check_result "langchain-py" "${{ needs.langchain-py.result }}" check_result "upload-wheel" "${{ needs.upload-wheel.result }}" diff --git a/py/Makefile b/py/Makefile index 56becdfe..5677f3a0 100644 --- a/py/Makefile +++ b/py/Makefile @@ -2,7 +2,7 @@ PYTHON ?= python UV := $(PYTHON) -m uv UV_VERSION := $(shell awk '$$1=="uv" { print $$2 }' ../.tool-versions) -.PHONY: lint pylint test test-wheel _template-version clean fixup build verify-build verify help install-build-deps install-dev install-optional test-core _check-git-clean bench bench-compare +.PHONY: lint pylint vulture test test-wheel _template-version clean fixup build verify-build verify help install-build-deps install-dev install-optional test-core _check-git-clean bench bench-compare clean: rm -rf build dist @@ -17,6 +17,9 @@ lint: fixup pylint: nox -s pylint +vulture: + $(PYTHON) -m vulture src/braintrust --min-confidence 100 --exclude "*/test_*.py,*/_test_*.py" + test: nox -x @@ -58,7 +61,7 @@ _check-git-clean: verify-build: _check-git-clean build test-wheel -verify: lint test +verify: lint vulture test install-build-deps: $(if $(UV_VERSION),,$(error Failed to read uv version from ../.tool-versions)) @@ -85,6 +88,7 @@ help: @echo " install-dev - Install package in development mode with all dependencies" @echo " lint - Run pylint checks" @echo " pylint - Run pylint without pre-commit hooks" + @echo " vulture - Detect unused/dead code" @echo " test - Run all tests" @echo " test-core - Run core tests only" @echo " test-wheel - Run tests against built wheel" diff --git a/py/requirements-dev.txt b/py/requirements-dev.txt index 14fb3c47..04799aaf 100644 --- a/py/requirements-dev.txt +++ b/py/requirements-dev.txt @@ -5,6 +5,7 @@ pre-commit==4.5.1 pydoc-markdown==4.8.2 pylint==4.0.5 pyperf==2.10.0 +vulture==2.16 pytest==9.0.2 pytest-asyncio==1.3.0 pytest-forked==1.6.0 diff --git a/py/src/braintrust/framework.py b/py/src/braintrust/framework.py index 378aa852..5aa9172a 100644 --- a/py/src/braintrust/framework.py +++ b/py/src/braintrust/framework.py @@ -203,7 +203,7 @@ def tags(self) -> Sequence[str]: """ @abc.abstractmethod - def report_progress(self, progress: TaskProgressEvent) -> None: + def report_progress(self, progress: TaskProgressEvent) -> None: # noqa: F841 """ Report progress that will show up in the playground. """ @@ -459,7 +459,7 @@ class EvalResultWithSummary(SerializableDataClass, Generic[Input, Output]): summary: ExperimentSummary results: list[EvalResult[Input, Output]] - def _repr_pretty_(self, p, cycle): + def _repr_pretty_(self, p, _cycle): p.text(f'EvalResultWithSummary(summary="...", results=[...])') diff --git a/py/src/braintrust/integrations/base.py b/py/src/braintrust/integrations/base.py index 68d2936a..21094fa7 100644 --- a/py/src/braintrust/integrations/base.py +++ b/py/src/braintrust/integrations/base.py @@ -194,7 +194,7 @@ def applies(cls, module: Any | None, version: str | None, *, target: Any | None @classmethod @abstractmethod - def patch_class(cls, target_class: type[Any]) -> bool | None: + def patch_class(cls, target_class: type[Any]) -> bool | None: # noqa: F841 """Patch one discovered class. Return ``False`` to skip marking the class as patched. Any other return diff --git a/py/src/braintrust/integrations/langchain/callbacks.py b/py/src/braintrust/integrations/langchain/callbacks.py index 50650da0..1c553742 100644 --- a/py/src/braintrust/integrations/langchain/callbacks.py +++ b/py/src/braintrust/integrations/langchain/callbacks.py @@ -552,7 +552,7 @@ def on_text( def on_retry( self, - retry_state: RetryCallState, + _retry_state: RetryCallState, *, run_id: UUID, parent_run_id: UUID | None = None, diff --git a/py/src/braintrust/logger.py b/py/src/braintrust/logger.py index f7c56d2b..ef7095ac 100644 --- a/py/src/braintrust/logger.py +++ b/py/src/braintrust/logger.py @@ -1445,7 +1445,7 @@ def _register_dropped_item_count(self, num_items): self._queue_drop_logging_state["last_logged_timestamp"] = time_now @staticmethod - def _write_payload_to_dir(payload_dir, payload, debug_logging_adjective=None): + def _write_payload_to_dir(payload_dir, payload): payload_file = os.path.join(payload_dir, f"payload_{time.time()}_{str(uuid.uuid4())[:8]}.json") try: os.makedirs(payload_dir, exist_ok=True) @@ -2839,7 +2839,7 @@ def _validate_and_sanitize_experiment_log_partial_args(event: Mapping[str, Any]) # Note that this only checks properties that are expected of a complete event. # _validate_and_sanitize_experiment_log_partial_args should still be invoked # (after handling special fields like 'id'). -def _validate_and_sanitize_experiment_log_full_args(event: Mapping[str, Any], has_dataset: bool) -> Mapping[str, Any]: +def _validate_and_sanitize_experiment_log_full_args(event: Mapping[str, Any]) -> Mapping[str, Any]: input = event.get("input") inputs = event.get("inputs") if (input is not None and inputs is not None) or (input is None and inputs is None): @@ -3868,8 +3868,7 @@ def log( metadata=metadata, metrics=metrics, id=id, - ), - self.dataset is not None, + ) ) span = self._start_span_impl(start_time=self.last_start_time, lookup_span_parent=False, **event) self.last_start_time = span.end()