Loading pkgs/development/python-modules/fastmcp/default.nix +43 −11 Original line number Diff line number Diff line Loading @@ -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 = [ Loading @@ -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 = { Loading @@ -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" Loading @@ -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" Loading @@ -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" Loading @@ -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 ]; }; } }) pkgs/development/python-modules/py-key-value-aio/default.nix 0 → 100644 +194 −0 Original line number Diff line number Diff line { 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 ]; }; }) pkgs/development/python-modules/py-key-value-shared-test/default.nix 0 → 100644 +46 −0 Original line number Diff line number Diff line { 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 ]; }; }) pkgs/development/python-modules/py-key-value-shared/default.nix 0 → 100644 +65 −0 Original line number Diff line number Diff line { 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 ]; }; }) pkgs/development/python-modules/pydocket/default.nix 0 → 100644 +77 −0 Original line number Diff line number Diff line { 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 ]; }; }) Loading
pkgs/development/python-modules/fastmcp/default.nix +43 −11 Original line number Diff line number Diff line Loading @@ -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 = [ Loading @@ -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 = { Loading @@ -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" Loading @@ -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" Loading @@ -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" Loading @@ -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 ]; }; } })
pkgs/development/python-modules/py-key-value-aio/default.nix 0 → 100644 +194 −0 Original line number Diff line number Diff line { 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 ]; }; })
pkgs/development/python-modules/py-key-value-shared-test/default.nix 0 → 100644 +46 −0 Original line number Diff line number Diff line { 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 ]; }; })
pkgs/development/python-modules/py-key-value-shared/default.nix 0 → 100644 +65 −0 Original line number Diff line number Diff line { 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 ]; }; })
pkgs/development/python-modules/pydocket/default.nix 0 → 100644 +77 −0 Original line number Diff line number Diff line { 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 ]; }; })