Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

version: 2
updates:
- package-ecosystem: "pip" # See documentation for possible values
- package-ecosystem: "uv" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "daily"
Expand Down
66 changes: 23 additions & 43 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,27 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: astral-sh/ruff-action@v3
- name: Install uv and set Python version
uses: astral-sh/setup-uv@v7
with:
version: "0.11.2"
python-version: "3.13"
enable-cache: true
- name: Install dependencies
run: uv sync --locked
- name: Run Ruff
run: uv run --frozen ruff check .

type-checking:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
- name: Install uv and set Python version
uses: astral-sh/setup-uv@v7
with:
version: "0.11.2"
python-version: "3.13"
- name: Install poetry
uses: abatilo/actions-poetry@v2
- name: Setup a local virtual environment
run: |
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local
- uses: actions/cache@v3
name: Define a cache for the virtual environment based on the dependencies lock file
with:
path: ./.venv
key: venv-type-check-${{ hashFiles('poetry.lock') }}
enable-cache: true
- uses: actions/cache@v3
name: Cache mypy cache
with:
Expand All @@ -48,9 +48,9 @@ jobs:
restore-keys: |
mypy-
- name: Install dependencies
run: poetry install --only=main,dev
run: uv sync --locked
- name: Run mypy type checking
run: poetry run mypy langfuse --no-error-summary
run: uv run --frozen mypy langfuse --no-error-summary

ci:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -154,43 +154,23 @@ jobs:
done
echo "Langfuse server is up and running!"

- name: Install Python
uses: actions/setup-python@v4
# see details (matrix, python-version, python-version-file, etc.)
# https://github.com/actions/setup-python
- name: Install uv and set Python version
uses: astral-sh/setup-uv@v7
with:
version: "0.11.2"
python-version: ${{ matrix.python-version }}
enable-cache: true

- name: Check python version
- name: Check Python version
run: python --version

- name: Install poetry
uses: abatilo/actions-poetry@v2

- name: Set poetry python version
run: |
poetry env use ${{ matrix.python-version }}
poetry env info

- name: Setup a local virtual environment (if no poetry.toml file)
run: |
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local

- uses: actions/cache@v3
name: Define a cache for the virtual environment based on the dependencies lock file
with:
path: ./.venv
key: |
venv-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}-${{ github.sha }}

- name: Install the project dependencies
run: poetry install --all-extras
run: uv sync --locked

- name: Run the automated tests
run: |
python --version
poetry run pytest -n auto --dist loadfile -s -v --log-cli-level=INFO
uv run --frozen pytest -n auto --dist loadfile -s -v --log-cli-level=INFO

all-tests-passed:
# This allows us to have a branch protection rule for tests and deploys with matrix
Expand Down
49 changes: 18 additions & 31 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,12 @@ jobs:
fetch-depth: 0
token: ${{ secrets.GH_ACCESS_TOKEN }}

- name: Setup Python
uses: actions/setup-python@v5
- name: Install uv and set Python version
uses: astral-sh/setup-uv@v7
with:
version: "0.11.2"
python-version: "3.12"

- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: "1.8.4"
virtualenvs-create: true
virtualenvs-in-project: true
enable-cache: true

- name: Configure Git
env:
Expand All @@ -92,7 +87,7 @@ jobs:
- name: Get current version
id: current-version
run: |
current_version=$(poetry version -s)
current_version=$(uv version --short)
echo "version=$current_version" >> $GITHUB_OUTPUT
echo "Current version: $current_version"

Expand Down Expand Up @@ -211,27 +206,13 @@ jobs:

- name: Update version in pyproject.toml
run: |
poetry version ${{ steps.new-version.outputs.version }}

- name: Update version in langfuse/version.py
run: |
new_version="${{ steps.new-version.outputs.version }}"
sed -i "s/__version__ = \".*\"/__version__ = \"$new_version\"/" langfuse/version.py
echo "Updated langfuse/version.py:"
cat langfuse/version.py
uv version ${{ steps.new-version.outputs.version }}

- name: Verify version consistency
run: |
pyproject_version=$(poetry version -s)
file_version=$(grep -oP '__version__ = "\K[^"]+' langfuse/version.py)
pyproject_version=$(uv version --short)

echo "pyproject.toml version: $pyproject_version"
echo "langfuse/version.py version: $file_version"

if [ "$pyproject_version" != "$file_version" ]; then
echo "❌ Error: Version mismatch between pyproject.toml and langfuse/version.py"
exit 1
fi

if [ "$pyproject_version" != "${{ steps.new-version.outputs.version }}" ]; then
echo "❌ Error: Version in files doesn't match expected version"
Expand All @@ -241,7 +222,7 @@ jobs:
echo "✅ Versions are consistent: $pyproject_version"

- name: Build package
run: poetry build
run: uv build --no-sources

- name: Verify build artifacts
run: |
Expand Down Expand Up @@ -278,9 +259,17 @@ jobs:
fi
echo "✅ Artifact version verified"

- name: Smoke test wheel
run: |
uv run --isolated --no-project --with dist/*.whl python -c "from importlib.metadata import version; import langfuse; assert langfuse.__version__ == version('langfuse')"

- name: Smoke test source distribution
run: |
uv run --isolated --no-project --with dist/*.tar.gz python -c "from importlib.metadata import version; import langfuse; assert langfuse.__version__ == version('langfuse')"

- name: Commit version changes
run: |
git add pyproject.toml langfuse/version.py
git add pyproject.toml uv.lock
git commit -m "chore: release v${{ steps.new-version.outputs.version }}"

- name: Create and push tag
Expand All @@ -292,9 +281,7 @@ jobs:

- name: Publish to PyPI
id: publish-pypi
uses: pypa/gh-action-pypi-publish@release/v1
with:
print-hash: true
run: uv publish --trusted-publishing always

- name: Create GitHub Release
id: create-release
Expand Down
47 changes: 21 additions & 26 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.2
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.11.2
hooks:
- id: uv-lock

- repo: local
hooks:
# Run the linter and fix
- id: ruff-check
- id: uv-ruff-check
name: ruff-check
entry: uv run --frozen ruff check --fix
language: system
types_or: [python, pyi, jupyter]
args: [--fix]
exclude: ^langfuse/api/

# Run the formatter.
- id: ruff-format
- id: uv-ruff-format
name: ruff-format
entry: uv run --frozen ruff format
language: system
types_or: [python, pyi, jupyter]
exclude: ^langfuse/api/

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.18.2
hooks:
- id: mypy
additional_dependencies:
- types-requests
- types-setuptools
- httpx
- pydantic>=1.10.7
- backoff>=1.10.0
- openai>=0.27.8
- wrapt
- packaging>=23.2
- opentelemetry-api
- opentelemetry-sdk
- opentelemetry-exporter-otlp
- numpy
- langchain>=0.0.309
- langchain-core
- langgraph
args: [--no-error-summary]
- id: uv-mypy
name: mypy
entry: uv run --frozen mypy langfuse --no-error-summary
language: system
files: ^langfuse/
pass_filenames: false
35 changes: 16 additions & 19 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,60 +11,57 @@ This is the Langfuse Python SDK, a client library for accessing the Langfuse obs
### Setup

```bash
# Install Poetry plugins (one-time setup)
poetry self add poetry-dotenv-plugin

# Install all dependencies including optional extras
poetry install --all-extras
# Install the project and development dependencies
uv sync

# Setup pre-commit hooks
poetry run pre-commit install
uv run pre-commit install
```

### Testing

```bash
# Run all tests with verbose output
poetry run pytest -s -v --log-cli-level=INFO
uv run --env-file .env pytest -s -v --log-cli-level=INFO

# Run a specific test
poetry run pytest -s -v --log-cli-level=INFO tests/test_core_sdk.py::test_flush
uv run --env-file .env pytest -s -v --log-cli-level=INFO tests/test_core_sdk.py::test_flush

# Run tests in parallel (faster)
poetry run pytest -s -v --log-cli-level=INFO -n auto
uv run --env-file .env pytest -s -v --log-cli-level=INFO -n auto
```

### Code Quality

```bash
# Format code with Ruff
poetry run ruff format .
uv run ruff format .

# Run linting (development config)
poetry run ruff check .
uv run ruff check .

# Run type checking
poetry run mypy .
uv run mypy .

# Run pre-commit hooks manually
poetry run pre-commit run --all-files
uv run pre-commit run --all-files
```

### Building and Releasing

```bash
# Build the package locally (for testing)
poetry build
uv build --no-sources

# Generate documentation
poetry run pdoc -o docs/ --docformat google --logo "https://langfuse.com/langfuse_logo.svg" langfuse
uv run --group docs pdoc -o docs/ --docformat google --logo "https://langfuse.com/langfuse_logo.svg" langfuse
```

Releases are automated via GitHub Actions. To release:

1. Go to Actions > "Release Python SDK" workflow
2. Click "Run workflow"
3. Select version bump type (patch/minor/major/prerelease)
3. Select version bump type (patch/minor/major/prepatch/preminor/premajor)
4. For prereleases, select the type (alpha/beta/rc)

The workflow handles versioning, building, PyPI publishing (via OIDC), and GitHub release creation.
Expand Down Expand Up @@ -120,16 +117,16 @@ Environment variables (defined in `_client/environment_variables.py`):

## Important Files

- `pyproject.toml`: Poetry configuration, dependencies, and tool settings
- `langfuse/version.py`: Version string (updated by CI release workflow)
- `pyproject.toml`: uv project metadata, dependencies, and tool settings
- `uv.lock`: Locked dependency graph for local development and CI

## API Generation

The `langfuse/api/` directory is auto-generated from the Langfuse OpenAPI specification using Fern. To update:

1. Generate new SDK in main Langfuse repo
2. Copy generated files from `generated/python` to `langfuse/api/`
3. Run `poetry run ruff format .` to format the generated code
3. Run `uv run ruff format .` to format the generated code

## Testing Guidelines

Expand Down
Loading
Loading