From c676e056f6a9ce33a68b688a9f27b0c8a9ebd360 Mon Sep 17 00:00:00 2001 From: Benjamin Riviere Date: Sun, 8 Sep 2024 19:51:19 +0200 Subject: [PATCH 1/7] Prepare some type aliases to ease readability. --- src/trackotron/types_/__init__.py | 31 +++++++++++++++++++++++++++++-- src/trackotron/types_/aliases.py | 26 ++++++++++++++++++++++++++ src/trackotron/types_/generics.py | 3 ++- 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 src/trackotron/types_/aliases.py diff --git a/src/trackotron/types_/__init__.py b/src/trackotron/types_/__init__.py index 41d0a70..8e4334a 100644 --- a/src/trackotron/types_/__init__.py +++ b/src/trackotron/types_/__init__.py @@ -2,6 +2,20 @@ from __future__ import annotations +from .aliases import ( + AsyncClassMethod, + AsyncFunction, + AsyncInjectedClassMethod, + AsyncInjectedFunction, + AsyncInjectedMethod, + AsyncMethod, + ClassMethod, + Function, + InjectedClassMethod, + InjectedFunction, + InjectedMethod, + Method, +) from .compatibility import ( Langfuse, ModelUsage, @@ -13,12 +27,26 @@ StatefulSpanClient, StatefulTraceClient, ) -from .generics import P, R_co, T_contra +from .generics import C, I, P, R_co from .misc import Arguments, ObservationParameters, ObservationType, TraceParameters __all__ = [ "Arguments", + "AsyncClassMethod", + "AsyncFunction", + "AsyncInjectedClassMethod", + "AsyncInjectedFunction", + "AsyncInjectedMethod", + "AsyncMethod", + "C", + "ClassMethod", + "Function", + "I", + "InjectedClassMethod", + "InjectedFunction", + "InjectedMethod", "Langfuse", + "Method", "ModelUsage", "ObservationParameters", "ObservationType", @@ -31,6 +59,5 @@ "StatefulGenerationClient", "StatefulSpanClient", "StatefulTraceClient", - "T_contra", "TraceParameters", ] diff --git a/src/trackotron/types_/aliases.py b/src/trackotron/types_/aliases.py new file mode 100644 index 0000000..aac3787 --- /dev/null +++ b/src/trackotron/types_/aliases.py @@ -0,0 +1,26 @@ +"""Copyright (c) 2024 Bendabir.""" + +from __future__ import annotations + +from typing import Any, Callable, Coroutine + +from typing_extensions import Concatenate + +from trackotron.types_.generics import C, I, P, R_co + +Function = Callable[P, R_co] +InjectedFunction = Callable[Concatenate[I, P], R_co] +Method = Callable[Concatenate[C, P], R_co] +InjectedMethod = Callable[Concatenate[C, I, P], R_co] +ClassMethod = Callable[Concatenate[type[C], P], R_co] +InjectedClassMethod = Callable[Concatenate[type[C], I, P], R_co] + +AsyncFunction = Callable[P, Coroutine[Any, Any, R_co]] +AsyncInjectedFunction = Callable[Concatenate[I, P], Coroutine[Any, Any, R_co]] +AsyncMethod = Callable[Concatenate[C, P], Coroutine[Any, Any, R_co]] +AsyncInjectedMethod = Callable[Concatenate[C, I, P], Coroutine[Any, Any, R_co]] +AsyncClassMethod = Callable[Concatenate[type[C], P], Coroutine[Any, Any, R_co]] +AsyncInjectedClassMethod = Callable[ + Concatenate[type[C], I, P], + Coroutine[Any, Any, R_co], +] diff --git a/src/trackotron/types_/generics.py b/src/trackotron/types_/generics.py index 5a6e2bc..4a4d2a8 100644 --- a/src/trackotron/types_/generics.py +++ b/src/trackotron/types_/generics.py @@ -8,4 +8,5 @@ P = ParamSpec("P") R_co = TypeVar("R_co", covariant=True) -T_contra = TypeVar("T_contra", contravariant=True) +C = TypeVar("C") +I = TypeVar("I") From f4a868d2c1c5b5e7115366a9aec6d27ccd37c898 Mon Sep 17 00:00:00 2001 From: Benjamin Riviere Date: Sun, 8 Sep 2024 19:56:19 +0200 Subject: [PATCH 2/7] Use new typing. --- src/trackotron/contexts/context.py | 49 +++++++++++++----------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/src/trackotron/contexts/context.py b/src/trackotron/contexts/context.py index 89d591e..2c362e6 100644 --- a/src/trackotron/contexts/context.py +++ b/src/trackotron/contexts/context.py @@ -12,7 +12,6 @@ TYPE_CHECKING, Any, Callable, - Coroutine, Generic, TypeVar, final, @@ -28,9 +27,18 @@ from contextvars import ContextVar from types import TracebackType - from trackotron.types_ import Arguments, P, R_co + from trackotron.types_ import ( + Arguments, + AsyncFunction, + AsyncInjectedFunction, + Function, + InjectedFunction, + ObservationParameters, + P, + R_co, + TraceParameters, + ) from trackotron.types_.compatibility import Langfuse, StatefulClient - from trackotron.types_.misc import ObservationParameters, TraceParameters U_co = TypeVar("U_co", bound=ObservationUpdate, covariant=True) @@ -238,12 +246,9 @@ def _is_method(f: Callable[P, R_co], /) -> bool: @final def _wrap_sync( self, - f: Callable[ - Concatenate[ObservationProxy[O_co, U_co], P], - R_co, - ], + f: InjectedFunction[ObservationProxy[O_co, U_co], P, R_co], /, - ) -> Callable[P, R_co]: + ) -> Function[P, R_co]: @ft.wraps(f) def wrap(*args: Any, **kwargs: Any) -> R_co: with self._context() as proxy: @@ -288,43 +293,31 @@ def wrap(*args: Any, **kwargs: Any) -> R_co: @final def _wrap_async( self, - f: Callable[ - Concatenate[ObservationProxy[O_co, U_co], P], - Coroutine[Any, Any, R_co], - ], + f: AsyncInjectedFunction[ObservationProxy[O_co, U_co], P, R_co], /, - ) -> Callable[P, Coroutine[Any, Any, R_co]]: + ) -> AsyncFunction[P, R_co]: raise NotImplementedError @overload def __call__( self, - f: Callable[ - Concatenate[ObservationProxy[O_co, U_co], P], - R_co, - ], + f: InjectedFunction[ObservationProxy[O_co, U_co], P, R_co], /, - ) -> Callable[P, R_co]: ... + ) -> Function[P, R_co]: ... @overload def __call__( self, - f: Callable[ - Concatenate[ObservationProxy[O_co, U_co], P], - Coroutine[Any, Any, R_co], - ], + f: AsyncInjectedFunction[ObservationProxy[O_co, U_co], P, R_co], /, - ) -> Callable[P, Coroutine[Any, Any, R_co]]: ... + ) -> AsyncFunction[P, R_co]: ... @final def __call__( self, - f: Callable[ - Concatenate[ObservationProxy[O_co, U_co], P], - R_co, - ], + f: InjectedFunction[ObservationProxy[O_co, U_co], P, R_co], /, - ) -> Callable[P, R_co] | Callable[P, Coroutine[Any, Any, R_co]]: + ) -> Function[P, R_co] | AsyncFunction[P, R_co]: """Decorate a function to observe it in Langfuse. If the name was not provided, it will infer it from the function/method. From c5b9656004a710fbcdf814dae6a458ec13daa64b Mon Sep 17 00:00:00 2001 From: Benjamin Riviere Date: Sun, 8 Sep 2024 19:56:43 +0200 Subject: [PATCH 3/7] Bump version. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2220f0c..2c540b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ # --- poetry --- [tool.poetry] name = "trackotron" -version = "0.1.0" +version = "0.2.0" description = "Improved decorator for Langfuse." license = "GPL-3.0-or-later" authors = ["Bendabir"] From d76bd8db3eec6f27f575e688e75b30562fa2d6a5 Mon Sep 17 00:00:00 2001 From: Benjamin Riviere Date: Sun, 8 Sep 2024 19:58:28 +0200 Subject: [PATCH 4/7] Fix changelog. --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84263ef..ee79bf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Typing has been improved. + +## [0.1.0] + ### Added - Various observations contexts to track code. -[Unreleased]: https://github.com/bendabir/trackotron/tree/develop +[Unreleased]: https://github.com/bendabir/trackotron/compare/0.1.0...main +[0.1.0]: https://github.com/bendabir/trackotron/tree/0.1.0 From 9a91aef6651f6b2106b8548e67b0d295e6528062 Mon Sep 17 00:00:00 2001 From: Benjamin Riviere Date: Sun, 8 Sep 2024 20:00:12 +0200 Subject: [PATCH 5/7] Add PR template. --- .github/pull_request_template.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..2034556 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +## Description + + + +## TODO + +- [ ] Update version. +- [ ] Update [changelog](../CHANGELOG.md). +- [ ] Quality passed. +- [ ] Tests passed. +- [ ] Readme is up-to-date. From 91cb2fdae30d4d56d8029cf14364a7e4190859ee Mon Sep 17 00:00:00 2001 From: Benjamin Riviere Date: Sat, 21 Sep 2024 09:07:59 +0200 Subject: [PATCH 6/7] Fix configuration. --- pyproject.toml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2c540b3..9618ecc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,13 +37,13 @@ build-backend = "poetry.core.masonry.api" # --- black --- [tool.black] line-length = 88 -target-version = ["py38"] +target-version = ["py39"] preview = false # --- mypy --- [tool.mypy] local_partial_types = true -python_version = "3.8" +python_version = "3.9" mypy_path = "src/,tests/" files = "**/src/**/*.py,**/tests/**/*.py" scripts_are_modules = true @@ -79,15 +79,10 @@ enable_error_code = [ "unused-awaitable", ] -[tool.pydantic-mypy] -init_typed = false -init_forbid_extra = true -warn_required_dynamic_aliases = true - # --- ruff --- [tool.ruff] line-length = 88 -target-version = "py38" +target-version = "py39" indent-width = 4 preview = true namespace-packages = ["src/trackotron"] From 7eeef327624801824c69e1eabf4b3d884e7d0ceb Mon Sep 17 00:00:00 2001 From: Benjamin Riviere Date: Sat, 21 Sep 2024 09:08:13 +0200 Subject: [PATCH 7/7] Fix configuration. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e2158c6..ec9e6fd 100644 --- a/README.md +++ b/README.md @@ -117,3 +117,4 @@ Here are some ideas to improve the current decorator : - [ ] Add more tests to ensure behaviors and consistency - [ ] Support context reuse if that makes sense - [ ] Handle data obfuscation when needed so we don't expose secrets. +- [ ] Make parenthesis usage optional (see [#918](https://github.com/langfuse/langfuse-python/pull/918))