Skip to content

Commit 31e4b73

Browse files
authored
chore: add mypy support (#1257)
1 parent ba3e787 commit 31e4b73

28 files changed

Lines changed: 613 additions & 326 deletions

.github/workflows/ci.yml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,37 @@ jobs:
2323
with:
2424
args: check --config ci.ruff.toml
2525

26+
type-checking:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- uses: actions/checkout@v3
30+
- name: Set up Python
31+
uses: actions/setup-python@v4
32+
with:
33+
python-version: "3.12"
34+
- name: Install poetry
35+
uses: abatilo/actions-poetry@v2
36+
- name: Setup a local virtual environment
37+
run: |
38+
poetry config virtualenvs.create true --local
39+
poetry config virtualenvs.in-project true --local
40+
- uses: actions/cache@v3
41+
name: Define a cache for the virtual environment based on the dependencies lock file
42+
with:
43+
path: ./.venv
44+
key: venv-type-check-${{ hashFiles('poetry.lock') }}
45+
- uses: actions/cache@v3
46+
name: Cache mypy cache
47+
with:
48+
path: ./.mypy_cache
49+
key: mypy-${{ hashFiles('**/*.py', 'pyproject.toml') }}
50+
restore-keys: |
51+
mypy-
52+
- name: Install dependencies
53+
run: poetry install --only=main,dev
54+
- name: Run mypy type checking
55+
run: poetry run mypy langfuse --no-error-summary
56+
2657
ci:
2758
runs-on: ubuntu-latest
2859
timeout-minutes: 30
@@ -160,7 +191,7 @@ jobs:
160191
all-tests-passed:
161192
# This allows us to have a branch protection rule for tests and deploys with matrix
162193
runs-on: ubuntu-latest
163-
needs: [ci, linting]
194+
needs: [ci, linting, type-checking]
164195
if: always()
165196
steps:
166197
- name: Successful deploy

.pre-commit-config.yaml

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,34 @@ repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
33
rev: v0.3.2
44
hooks:
5-
# Run the linter and fix
5+
# Run the linter and fix
66
- id: ruff
7-
types_or: [ python, pyi, jupyter ]
8-
args: [ --fix, --config=ci.ruff.toml ]
7+
types_or: [python, pyi, jupyter]
8+
args: [--fix, --config=ci.ruff.toml]
99

1010
# Run the formatter.
1111
- id: ruff-format
12-
types_or: [ python, pyi, jupyter ]
12+
types_or: [python, pyi, jupyter]
1313

14+
- repo: https://github.com/pre-commit/mirrors-mypy
15+
rev: v1.8.0
16+
hooks:
17+
- id: mypy
18+
additional_dependencies:
19+
- types-requests
20+
- types-setuptools
21+
- httpx
22+
- pydantic>=1.10.7
23+
- backoff>=1.10.0
24+
- openai>=0.27.8
25+
- wrapt
26+
- packaging>=23.2
27+
- opentelemetry-api
28+
- opentelemetry-sdk
29+
- opentelemetry-exporter-otlp
30+
- numpy
31+
- langchain>=0.0.309
32+
- langchain-core
33+
- langgraph
34+
args: [--no-error-summary]
35+
files: ^langfuse/

langfuse/_client/attributes.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import json
1414
from datetime import datetime
15-
from typing import Any, Dict, List, Literal, Optional
15+
from typing import Any, Dict, List, Literal, Optional, Union
1616

1717
from langfuse._utils.serializer import EventSerializer
1818
from langfuse.model import PromptClient
@@ -68,7 +68,7 @@ def create_trace_attributes(
6868
metadata: Optional[Any] = None,
6969
tags: Optional[List[str]] = None,
7070
public: Optional[bool] = None,
71-
):
71+
) -> dict:
7272
attributes = {
7373
LangfuseOtelSpanAttributes.TRACE_NAME: name,
7474
LangfuseOtelSpanAttributes.TRACE_USER_ID: user_id,
@@ -93,7 +93,7 @@ def create_span_attributes(
9393
level: Optional[SpanLevel] = None,
9494
status_message: Optional[str] = None,
9595
version: Optional[str] = None,
96-
):
96+
) -> dict:
9797
attributes = {
9898
LangfuseOtelSpanAttributes.OBSERVATION_TYPE: "span",
9999
LangfuseOtelSpanAttributes.OBSERVATION_LEVEL: level,
@@ -122,7 +122,7 @@ def create_generation_attributes(
122122
usage_details: Optional[Dict[str, int]] = None,
123123
cost_details: Optional[Dict[str, float]] = None,
124124
prompt: Optional[PromptClient] = None,
125-
):
125+
) -> dict:
126126
attributes = {
127127
LangfuseOtelSpanAttributes.OBSERVATION_TYPE: "generation",
128128
LangfuseOtelSpanAttributes.OBSERVATION_LEVEL: level,
@@ -151,20 +151,20 @@ def create_generation_attributes(
151151
return {k: v for k, v in attributes.items() if v is not None}
152152

153153

154-
def _serialize(obj):
154+
def _serialize(obj: Any) -> Optional[str]:
155155
return json.dumps(obj, cls=EventSerializer) if obj is not None else None
156156

157157

158158
def _flatten_and_serialize_metadata(
159159
metadata: Any, type: Literal["observation", "trace"]
160-
):
160+
) -> dict:
161161
prefix = (
162162
LangfuseOtelSpanAttributes.OBSERVATION_METADATA
163163
if type == "observation"
164164
else LangfuseOtelSpanAttributes.TRACE_METADATA
165165
)
166166

167-
metadata_attributes = {}
167+
metadata_attributes: Dict[str, Union[str, int, None]] = {}
168168

169169
if not isinstance(metadata, dict):
170170
metadata_attributes[prefix] = _serialize(metadata)

0 commit comments

Comments
 (0)