Skip to content

Commit 6e07056

Browse files
authored
chore!: langfuse - drop Python 3.9 and use X|Y typing (#2709)
1 parent 6232ede commit 6e07056

4 files changed

Lines changed: 21 additions & 28 deletions

File tree

integrations/langfuse/pyproject.toml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,21 @@ name = "langfuse-haystack"
77
dynamic = ["version"]
88
description = "Langfuse integration for Haystack"
99
readme = "README.md"
10-
requires-python = ">=3.9"
10+
requires-python = ">=3.10"
1111
license = "Apache-2.0"
1212
keywords = []
1313
authors = [{ name = "deepset GmbH", email = "info@deepset.ai" }]
1414
classifiers = [
1515
"Development Status :: 4 - Beta",
1616
"Programming Language :: Python",
17-
"Programming Language :: Python :: 3.9",
1817
"Programming Language :: Python :: 3.10",
1918
"Programming Language :: Python :: 3.11",
2019
"Programming Language :: Python :: 3.12",
2120
"Programming Language :: Python :: 3.13",
2221
"Programming Language :: Python :: Implementation :: CPython",
2322
"Programming Language :: Python :: Implementation :: PyPy",
2423
]
25-
dependencies = ["haystack-ai>=2.17.1", "langfuse>=3.3.1, <4.0.0"]
24+
dependencies = ["haystack-ai>=2.22.0", "langfuse>=3.3.1, <4.0.0"]
2625

2726
[project.urls]
2827
Documentation = "https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/langfuse#readme"
@@ -82,7 +81,6 @@ allow-direct-references = true
8281

8382

8483
[tool.ruff]
85-
target-version = "py39"
8684
line-length = 120
8785

8886
[tool.ruff.lint]
@@ -128,10 +126,6 @@ ignore = [
128126
# Asserts
129127
"S101",
130128
]
131-
unfixable = [
132-
# Don't touch unused imports
133-
"F401",
134-
]
135129

136130
[tool.ruff.lint.isort]
137131
known-first-party = ["haystack_integrations"]

integrations/langfuse/src/haystack_integrations/components/connectors/langfuse/langfuse_connector.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# SPDX-License-Identifier: Apache-2.0
44

5-
from typing import Any, Optional
5+
from typing import Any
66

77
import httpx
88
from haystack import component, default_from_dict, default_to_dict, logging, tracing
@@ -118,13 +118,13 @@ def __init__(
118118
self,
119119
name: str,
120120
public: bool = False,
121-
public_key: Optional[Secret] = Secret.from_env_var("LANGFUSE_PUBLIC_KEY"), # noqa: B008
122-
secret_key: Optional[Secret] = Secret.from_env_var("LANGFUSE_SECRET_KEY"), # noqa: B008
123-
httpx_client: Optional[httpx.Client] = None,
124-
span_handler: Optional[SpanHandler] = None,
121+
public_key: Secret | None = Secret.from_env_var("LANGFUSE_PUBLIC_KEY"), # noqa: B008
122+
secret_key: Secret | None = Secret.from_env_var("LANGFUSE_SECRET_KEY"), # noqa: B008
123+
httpx_client: httpx.Client | None = None,
124+
span_handler: SpanHandler | None = None,
125125
*,
126-
host: Optional[str] = None,
127-
langfuse_client_kwargs: Optional[dict[str, Any]] = None,
126+
host: str | None = None,
127+
langfuse_client_kwargs: dict[str, Any] | None = None,
128128
) -> None:
129129
"""
130130
Initialize the LangfuseConnector component.
@@ -172,7 +172,7 @@ def __init__(
172172
tracing.enable_tracing(self.tracer)
173173

174174
@component.output_types(name=str, trace_url=str, trace_id=str)
175-
def run(self, invocation_context: Optional[dict[str, Any]] = None) -> dict[str, str]:
175+
def run(self, invocation_context: dict[str, Any] | None = None) -> dict[str, str]:
176176
"""
177177
Runs the LangfuseConnector component.
178178

integrations/langfuse/src/haystack_integrations/tracing/langfuse/tracer.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from contextvars import ContextVar
1313
from dataclasses import dataclass
1414
from datetime import datetime
15-
from typing import Any, Literal, Optional, cast
15+
from typing import Any, Literal, cast
1616

1717
from haystack import default_from_dict, default_to_dict, logging
1818
from haystack.dataclasses import ChatMessage
@@ -48,7 +48,7 @@
4848

4949
# Internal span execution hierarchy for our tracer
5050
# Manages parent-child relationships and prevents cross-request span interleaving
51-
span_stack_var: ContextVar[Optional[list["LangfuseSpan"]]] = ContextVar("span_stack", default=None)
51+
span_stack_var: ContextVar[list["LangfuseSpan"] | None] = ContextVar("span_stack", default=None)
5252

5353

5454
class LangfuseSpan(Span):
@@ -150,9 +150,9 @@ class SpanContext:
150150

151151
name: str
152152
operation_name: str
153-
component_type: Optional[str]
153+
component_type: str | None
154154
tags: dict[str, Any]
155-
parent_span: Optional[Span]
155+
parent_span: Span | None
156156
trace_name: str = "Haystack"
157157
public: bool = False
158158

@@ -189,7 +189,7 @@ class SpanHandler(ABC):
189189
"""
190190

191191
def __init__(self) -> None:
192-
self.tracer: Optional[langfuse.Langfuse] = None
192+
self.tracer: langfuse.Langfuse | None = None
193193

194194
def init_tracer(self, tracer: langfuse.Langfuse) -> None:
195195
"""
@@ -215,7 +215,7 @@ def create_span(self, context: SpanContext) -> LangfuseSpan:
215215
pass
216216

217217
@abstractmethod
218-
def handle(self, span: LangfuseSpan, component_type: Optional[str]) -> None:
218+
def handle(self, span: LangfuseSpan, component_type: str | None) -> None:
219219
"""
220220
Process a span after component execution by attaching metadata and metrics.
221221
@@ -338,7 +338,7 @@ def create_span(self, context: SpanContext) -> LangfuseSpan:
338338
else:
339339
return LangfuseSpan(self.tracer.start_as_current_span(name=context.name))
340340

341-
def handle(self, span: LangfuseSpan, component_type: Optional[str]) -> None:
341+
def handle(self, span: LangfuseSpan, component_type: str | None) -> None:
342342
# If the span is at the pipeline level, we add input and output keys to the span
343343
at_pipeline_level = span.get_data().get(_PIPELINE_INPUT_KEY) is not None
344344
if at_pipeline_level:
@@ -420,7 +420,7 @@ def __init__(
420420
tracer: langfuse.Langfuse,
421421
name: str = "Haystack",
422422
public: bool = False,
423-
span_handler: Optional[SpanHandler] = None,
423+
span_handler: SpanHandler | None = None,
424424
) -> None:
425425
"""
426426
Initialize a LangfuseTracer instance.
@@ -450,7 +450,7 @@ def __init__(
450450

451451
@contextlib.contextmanager
452452
def trace(
453-
self, operation_name: str, tags: Optional[dict[str, Any]] = None, parent_span: Optional[Span] = None
453+
self, operation_name: str, tags: dict[str, Any] | None = None, parent_span: Span | None = None
454454
) -> Iterator[Span]:
455455
tags = tags or {}
456456
span_name = tags.get(_COMPONENT_NAME_KEY, operation_name)
@@ -541,7 +541,7 @@ def trace(
541541
def flush(self) -> None:
542542
self._tracer.flush()
543543

544-
def current_span(self) -> Optional[Span]:
544+
def current_span(self) -> Span | None:
545545
"""
546546
Return the current active span.
547547

integrations/langfuse/tests/test_tracer.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import datetime
77
import logging
88
import sys
9-
from typing import Optional
109
from unittest.mock import MagicMock, Mock, patch
1110

1211
import pytest
@@ -107,7 +106,7 @@ def flush(self):
107106

108107

109108
class CustomSpanHandler(DefaultSpanHandler):
110-
def handle(self, span: LangfuseSpan, component_type: Optional[str]) -> None:
109+
def handle(self, span: LangfuseSpan, component_type: str | None) -> None:
111110
if component_type == "OpenAIChatGenerator":
112111
output = span.get_data().get(_COMPONENT_OUTPUT_KEY, {})
113112
replies = output.get("replies", [])

0 commit comments

Comments
 (0)