diff --git a/pkgs/development/python-modules/fastmcp/default.nix b/pkgs/development/python-modules/fastmcp/default.nix index 1048317f71a7..150744345889 100644 --- a/pkgs/development/python-modules/fastmcp/default.nix +++ b/pkgs/development/python-modules/fastmcp/default.nix @@ -14,37 +14,45 @@ cyclopts, exceptiongroup, httpx, + jsonschema-path, mcp, openai, - openapi-core, openapi-pydantic, + platformdirs, + py-key-value-aio, pydantic, + pydocket, pyperclip, python-dotenv, rich, + uvicorn, websockets, # tests + anthropic, dirty-equals, email-validator, fastapi, inline-snapshot, + lupa, psutil, pytest-asyncio, pytest-httpx, pytestCheckHook, + + pytest-timeout, }: -buildPythonPackage rec { +buildPythonPackage (finalAttrs: { pname = "fastmcp"; - version = "2.12.5"; + version = "2.14.2"; pyproject = true; src = fetchFromGitHub { owner = "jlowin"; repo = "fastmcp"; - tag = "v${version}"; - hash = "sha256-F8NCp1Ku1EeI/YjbHuHcDYytTgqOFyLp+sZGBqayv6s="; + tag = "v${finalAttrs.version}"; + hash = "sha256-JqDsHmhuRom4CPmQd0sMaBtgypHDtwVJ4I3fnOLjnd8="; }; build-system = [ @@ -57,15 +65,22 @@ buildPythonPackage rec { cyclopts exceptiongroup httpx + jsonschema-path mcp - openapi-core openapi-pydantic + platformdirs + py-key-value-aio pydantic + pydocket pyperclip python-dotenv rich + uvicorn websockets ] + ++ py-key-value-aio.optional-dependencies.disk + ++ py-key-value-aio.optional-dependencies.keyring + ++ py-key-value-aio.optional-dependencies.memory ++ pydantic.optional-dependencies.email; optional-dependencies = { @@ -74,27 +89,43 @@ buildPythonPackage rec { pythonImportsCheck = [ "fastmcp" ]; + pytestFlags = [ + "--timeout=30" + ]; + nativeCheckInputs = [ + anthropic dirty-equals email-validator fastapi inline-snapshot + lupa psutil pytest-asyncio pytest-httpx + pytest-timeout pytestCheckHook writableTmpDirAsHomeHook ] - ++ lib.concatAttrValues optional-dependencies + ++ lib.concatAttrValues finalAttrs.passthru.optional-dependencies ++ inline-snapshot.optional-dependencies.dirty-equals; disabledTests = [ + # redis.exceptions.ResponseError: unknown command `evalsha`, with args beginning with: + "test_get_prompt_as_task_returns_prompt_task" + "test_prompt_task_server_generated_id" + "test_logging_middleware_with_payloads" "test_structured_logging_middleware_produces_json" # AssertionError: assert 'INFO' == 'DEBUG' "test_temporary_settings" + # mcp.shared.exceptions.McpError: Connection closed + "test_log_file_captures_stderr_output_with_path" + "test_log_file_captures_stderr_output_with_textio" + "test_log_file_none_uses_default_behavior" + # RuntimeError: Client failed to connect: Connection closed "test_keep_alive_maintains_session_across_multiple_calls" "test_keep_alive_false_starts_new_session_across_multiple_calls" @@ -110,6 +141,9 @@ buildPythonPackage rec { "test_uv_transport_module" "test_github_api_schema_performance" + # Hang forever + "test_nested_streamable_http_server_resolves_correctly" + # RuntimeError: Client failed to connect: Timed out while waiting for response "test_timeout" "test_timeout_tool_call_overrides_client_timeout_even_if_lower" @@ -133,8 +167,6 @@ buildPythonPackage rec { disabledTestPaths = lib.optionals stdenv.hostPlatform.isDarwin [ # RuntimeError: Server failed to start after 10 attempts "tests/client/auth/test_oauth_client.py" - "tests/client/test_openapi_experimental.py" - "tests/client/test_openapi_legacy.py" "tests/client/test_sse.py" "tests/client/test_streamable_http.py" "tests/server/auth/test_jwt_provider.py" @@ -145,9 +177,9 @@ buildPythonPackage rec { meta = { description = "Fast, Pythonic way to build MCP servers and clients"; - changelog = "https://github.com/jlowin/fastmcp/releases/tag/${src.tag}"; + changelog = "https://github.com/jlowin/fastmcp/releases/tag/${finalAttrs.src.tag}"; homepage = "https://github.com/jlowin/fastmcp"; license = lib.licenses.asl20; maintainers = with lib.maintainers; [ GaetanLepage ]; }; -} +}) diff --git a/pkgs/development/python-modules/py-key-value-aio/default.nix b/pkgs/development/python-modules/py-key-value-aio/default.nix new file mode 100644 index 000000000000..fbfc67f3e665 --- /dev/null +++ b/pkgs/development/python-modules/py-key-value-aio/default.nix @@ -0,0 +1,194 @@ +{ + lib, + stdenv, + buildPythonPackage, + fetchFromGitHub, + + # build-system + uv-build, + + # dependencies + beartype, + py-key-value-shared, + + # optional-dependencies + # memory + cachetools, + # disk + diskcache, + pathvalidate, + # filetree + aiofile, + anyio, + # redis + redis, + # mongodb + pymongo, + # valkey + # valkey-glide, + # vault + hvac, + # types-hvac, + # memcached + aiomcache, + # elasticsearch + elasticsearch, + aiohttp, + # dynamodb + aioboto3, + types-aiobotocore-dynamodb, + # keyring + keyring, + # keyring-linux + dbus-python, + # pydantic + pydantic, + # rocksdb + rocksdict, + # duckdb + duckdb, + pytz, + # wrappers-encryption + cryptography, + + # tests + bson, + docker, + dirty-equals, + inline-snapshot, + py-key-value-shared-test, + pytest-asyncio, + pytest-xdist, + pytestCheckHook, +}: + +buildPythonPackage (finalAttrs: { + pname = "py-key-value-aio"; + version = "0.3.0"; + pyproject = true; + + src = fetchFromGitHub { + owner = "strawgate"; + repo = "py-key-value"; + tag = finalAttrs.version; + hash = "sha256-4ji+GzJTv1QnC5n/OaL9vR65j8BQmJsVGGnjjuulDiU="; + }; + + sourceRoot = "${finalAttrs.src.name}/key-value/key-value-aio"; + + postPatch = '' + substituteInPlace pyproject.toml \ + --replace-fail \ + "uv_build>=0.8.2,<0.9.0" \ + "uv_build" + ''; + + build-system = [ + uv-build + ]; + + dependencies = [ + beartype + py-key-value-shared + ]; + + optional-dependencies = { + memory = [ + cachetools + ]; + disk = [ + diskcache + pathvalidate + ]; + filetree = [ + aiofile + anyio + ]; + redis = [ + redis + ]; + mongodb = [ + pymongo + ]; + valkey = [ + # valkey-glide (unpackaged) + ]; + vault = [ + hvac + # types-hvac (unpackaged) + ]; + memcached = [ + aiomcache + ]; + elasticsearch = [ + elasticsearch + aiohttp + ]; + dynamodb = [ + aioboto3 + types-aiobotocore-dynamodb + ]; + keyring = [ + keyring + ]; + keyring-linux = [ + keyring + dbus-python + ]; + pydantic = [ + pydantic + ]; + rocksdb = [ + rocksdict + ]; + duckdb = [ + duckdb + pytz + ]; + wrappers-encryption = [ + cryptography + ]; + }; + + pythonImportsCheck = [ "key_value.aio" ]; + + nativeCheckInputs = [ + bson + dirty-equals + docker + duckdb + inline-snapshot + py-key-value-shared-test + pytest-asyncio + pytest-xdist + pytestCheckHook + ] + ++ finalAttrs.passthru.optional-dependencies.disk + ++ finalAttrs.passthru.optional-dependencies.dynamodb + ++ finalAttrs.passthru.optional-dependencies.elasticsearch + ++ finalAttrs.passthru.optional-dependencies.filetree + ++ finalAttrs.passthru.optional-dependencies.keyring + ++ finalAttrs.passthru.optional-dependencies.memcached + ++ finalAttrs.passthru.optional-dependencies.memory + ++ finalAttrs.passthru.optional-dependencies.mongodb + ++ finalAttrs.passthru.optional-dependencies.pydantic + ++ finalAttrs.passthru.optional-dependencies.redis + ++ finalAttrs.passthru.optional-dependencies.rocksdb + ++ finalAttrs.passthru.optional-dependencies.wrappers-encryption; + + disabledTestPaths = [ + # ModuleNotFoundError: No module named 'bson.codec_options' + "tests/stores/mongodb/test_mongodb.py" + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + # keyring.errors.PasswordSetError: Can't store password on keychain: (-61, 'Unknown Error') + "tests/stores/keyring/test_keyring.py" + ]; + + meta = { + description = "Async Key-Value"; + homepage = "https://github.com/strawgate/py-key-value/tree/main/key-value/key-value-aio"; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ GaetanLepage ]; + }; +}) diff --git a/pkgs/development/python-modules/py-key-value-shared-test/default.nix b/pkgs/development/python-modules/py-key-value-shared-test/default.nix new file mode 100644 index 000000000000..be9c862e87c3 --- /dev/null +++ b/pkgs/development/python-modules/py-key-value-shared-test/default.nix @@ -0,0 +1,46 @@ +{ + lib, + buildPythonPackage, + fetchFromGitHub, + + # build-system + uv-build, +}: + +buildPythonPackage (finalAttrs: { + pname = "py-key-value-shared-test"; + version = "0.3.0"; + pyproject = true; + + src = fetchFromGitHub { + owner = "strawgate"; + repo = "py-key-value"; + tag = finalAttrs.version; + hash = "sha256-4ji+GzJTv1QnC5n/OaL9vR65j8BQmJsVGGnjjuulDiU="; + }; + + sourceRoot = "${finalAttrs.src.name}/key-value/key-value-shared-test"; + + postPatch = '' + substituteInPlace pyproject.toml \ + --replace-fail \ + "uv_build>=0.8.2,<0.9.0" \ + "uv_build" + ''; + + build-system = [ + uv-build + ]; + + pythonImportsCheck = [ "key_value.shared_test" ]; + + # No tests + doCheck = false; + + meta = { + description = "Utils for key-value-shared"; + homepage = "https://github.com/strawgate/py-key-value/tree/main/key-value/key-value-shared-test"; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ GaetanLepage ]; + }; +}) diff --git a/pkgs/development/python-modules/py-key-value-shared/default.nix b/pkgs/development/python-modules/py-key-value-shared/default.nix new file mode 100644 index 000000000000..0b348b0d31cf --- /dev/null +++ b/pkgs/development/python-modules/py-key-value-shared/default.nix @@ -0,0 +1,65 @@ +{ + lib, + buildPythonPackage, + fetchFromGitHub, + + # build-system + uv-build, + + # dependencies + beartype, + typing-extensions, + + # tests + pytestCheckHook, + pytest-xdist, + inline-snapshot, + py-key-value-shared-test, +}: + +buildPythonPackage (finalAttrs: { + pname = "py-key-value-shared"; + version = "0.3.0"; + pyproject = true; + + src = fetchFromGitHub { + owner = "strawgate"; + repo = "py-key-value"; + tag = finalAttrs.version; + hash = "sha256-4ji+GzJTv1QnC5n/OaL9vR65j8BQmJsVGGnjjuulDiU="; + }; + + sourceRoot = "${finalAttrs.src.name}/key-value/key-value-shared"; + + postPatch = '' + substituteInPlace pyproject.toml \ + --replace-fail \ + "uv_build>=0.8.2,<0.9.0" \ + "uv_build" + ''; + + build-system = [ + uv-build + ]; + + dependencies = [ + beartype + typing-extensions + ]; + + pythonImportsCheck = [ "key_value.shared" ]; + + nativeCheckInputs = [ + inline-snapshot + py-key-value-shared-test + pytest-xdist + pytestCheckHook + ]; + + meta = { + description = "Shared code between key-value-aio and key-value-sync"; + homepage = "https://github.com/strawgate/py-key-value/tree/main/key-value/key-value-shared"; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ GaetanLepage ]; + }; +}) diff --git a/pkgs/development/python-modules/pydocket/default.nix b/pkgs/development/python-modules/pydocket/default.nix new file mode 100644 index 000000000000..ba6b1ecceceb --- /dev/null +++ b/pkgs/development/python-modules/pydocket/default.nix @@ -0,0 +1,77 @@ +{ + lib, + buildPythonPackage, + fetchFromGitHub, + + # build-system + hatch-vcs, + hatchling, + + # dependencies + cloudpickle, + exceptiongroup, + fakeredis, + opentelemetry-api, + opentelemetry-exporter-prometheus, + opentelemetry-instrumentation, + prometheus-client, + py-key-value-aio, + python-json-logger, + redis, + rich, + typer, + typing-extensions, +}: + +buildPythonPackage (finalAttrs: { + pname = "pydocket"; + version = "0.16.3"; + pyproject = true; + + src = fetchFromGitHub { + owner = "chrisguidry"; + repo = "docket"; + tag = finalAttrs.version; + hash = "sha256-DNq+PUbh6SfazxkM7tbjEOXbh1VSJPM3jEkgn64XQ5g="; + }; + + build-system = [ + hatch-vcs + hatchling + ]; + + pythonRelaxDeps = [ + "fakeredis" + "opentelemetry-exporter-prometheus" + "opentelemetry-instrumentation" + ]; + dependencies = [ + cloudpickle + exceptiongroup + fakeredis + opentelemetry-api + opentelemetry-exporter-prometheus + opentelemetry-instrumentation + prometheus-client + py-key-value-aio + python-json-logger + redis + rich + typer + typing-extensions + ] + ++ py-key-value-aio.optional-dependencies.memory; + + pythonImportsCheck = [ "docket" ]; + + # All tests require internet access + doCheck = false; + + meta = { + description = "Distributed background task system for Python"; + homepage = "https://github.com/chrisguidry/docket"; + changelog = "https://github.com/chrisguidry/docket/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ GaetanLepage ]; + }; +}) diff --git a/pkgs/development/python-modules/rocksdict/default.nix b/pkgs/development/python-modules/rocksdict/default.nix new file mode 100644 index 000000000000..01152c1c85ec --- /dev/null +++ b/pkgs/development/python-modules/rocksdict/default.nix @@ -0,0 +1,67 @@ +{ + lib, + buildPythonPackage, + fetchFromGitHub, + rustPlatform, + pkgs, + + # tests + pytestCheckHook, +}: + +buildPythonPackage (finalAttrs: { + pname = "rocksdict"; + version = "0.3.29"; + pyproject = true; + + src = fetchFromGitHub { + owner = "rocksdict"; + repo = "RocksDict"; + tag = "v${finalAttrs.version}"; + fetchSubmodules = true; + hash = "sha256-yP+OAVioKOGPvcYM8s1TTNHzzaFxw1sUQDrWxmptuJo="; + }; + + cargoDeps = rustPlatform.fetchCargoVendor { + inherit (finalAttrs) src pname version; + hash = "sha256-E7DrHMla7af7IjPxS5EV2bWorXjHCsclnONVkkLAUrk="; + }; + + nativeBuildInputs = [ + rustPlatform.cargoSetupHook + rustPlatform.maturinBuildHook + ]; + + env = { + # libclang.so + LIBCLANG_PATH = "${lib.getLib pkgs.libclang}/lib"; + }; + + maturinBuildFlags = [ + # We disable LTO because it is incompatible with gcc + # LTO is only supported with clang. Either disable the `lto` feature or set + # `CC=/usr/bin/clang CXX=/usr/bin/clang++` environment variables. + + # Disable all default features to get rid of "lto" + "--no-default-features" + # Manually re-enable bindgen-runtime + "--features bindgen-runtime" + ]; + + pythonImportsCheck = [ "rocksdict" ]; + + nativeCheckInputs = [ + pytestCheckHook + ]; + enabledTestPaths = [ + "test" + ]; + + meta = { + description = "Python fast on-disk dictionary / RocksDB & SpeeDB Python binding"; + homepage = "https://github.com/rocksdict/RocksDict"; + changelog = "https://github.com/rocksdict/RocksDict/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ GaetanLepage ]; + }; +}) diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 6ad5d8a6ad71..a2bbbc404c6b 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -12814,6 +12814,12 @@ self: super: with self; { py-improv-ble-client = callPackage ../development/python-modules/py-improv-ble-client { }; + py-key-value-aio = callPackage ../development/python-modules/py-key-value-aio { }; + + py-key-value-shared = callPackage ../development/python-modules/py-key-value-shared { }; + + py-key-value-shared-test = callPackage ../development/python-modules/py-key-value-shared-test { }; + py-libnuma = callPackage ../development/python-modules/py-libnuma { }; py-libzfs = callPackage ../development/python-modules/py-libzfs { }; @@ -13273,6 +13279,8 @@ self: super: with self; { pydo = callPackage ../development/python-modules/pydo { }; + pydocket = callPackage ../development/python-modules/pydocket { }; + pydocstyle = callPackage ../development/python-modules/pydocstyle { }; pydocumentdb = callPackage ../development/python-modules/pydocumentdb { }; @@ -16603,6 +16611,8 @@ self: super: with self; { rocketchat-api = callPackage ../development/python-modules/rocketchat-api { }; + rocksdict = callPackage ../development/python-modules/rocksdict { }; + roku = callPackage ../development/python-modules/roku { }; rokuecp = callPackage ../development/python-modules/rokuecp { };