resolved RESOLVED PASS · 9 tool calls · 64 s · fastapi/fastapi
♻️ Make the result of `Depends()` and `Security()` hashable, as a workaround for other tools interacting with these internal parts ♻️ Make the result of `Depends()` and `Security()` hashable, as a workaround for other tools interacting with these internal parts --- This comes from https://github.com/fastapi/fastapi/pull/14320 As a note, FastAPI doesn't really have official support for extending its internals in ways that are not documented in the docs. So this is not a long-term commitment to keep some specific behavior, but a quick workaround to make things easier for current tools that interact with FastAPI internals in some way. --- At some point in the future, I'll refactor the internals of FastAPI to make them more explicitly private, and then also figure out the right ways to expose any points of connection with external components that currently need to interact with the internals in some way, and formalize that better. --- Before that, I need to handle a few issues, bugs, features, refactors, deprecations, etc. And then I'll be able to come back to this idea of figuring out how and what to expose. :nerd_face:
| # | Tool | Arguments | Result |
|---|---|---|---|
| 1 | run_command | {
"command": "grep -rn \"class Depends\" ."
} | {"status": "ok", "stdout": "./fastapi/params.py:766:class Depends:\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "./fastapi/params.py:766:class Depends:\n", "stderr": "", "exit_code": 0} |
| 2 | run_command | {
"command": "grep -rn \"class Security\" ."
} | {"status": "ok", "stdout": "./fastapi/params.py:773:class Security(Depends):\n./fastapi/security/oauth2.py:614:class SecurityScopes:\n./fastapi/security/base.pyfull{"status": "ok", "stdout": "./fastapi/params.py:773:class Security(Depends):\n./fastapi/security/oauth2.py:614:class SecurityScopes:\n./fastapi/security/base.py:4:class SecurityBase:\n./fastapi/dependencies/models.py:19:class SecurityRequirement:\n./fastapi/openapi/models.py:337:class SecuritySchemeType(Enum):\n./fastapi/openapi/models.py:344:class SecurityBase(BaseModelWithConfig):\n", "stderr": "", "exit_code": 0} |
| 3 | run_command | {
"command": "sed -n '760,780p' fastapi/params.py"
} | {"status": "ok", "stdout": " json_schema_extra=json_schema_extra,\n **extra,\n )\n\n\n@dataclass\nclass Depends:\n dependency: Optional[Callable[..., Any]] = Nofull{"status": "ok", "stdout": " json_schema_extra=json_schema_extra,\n **extra,\n )\n\n\n@dataclass\nclass Depends:\n dependency: Optional[Callable[..., Any]] = None\n use_cache: bool = True\n scope: Union[Literal[\"function\", \"request\"], None] = None\n\n\n@dataclass\nclass Security(Depends):\n scopes: Optional[Sequence[str]] = None\n", "stderr": "", "exit_code": 0} |
| 4 | run_command | {
"command": "python3 - <<'PY'\nfrom fastapi.params import Depends, Security\nfrom typing import Callable\n\ndef mock_dep():\n return \"ok\"\n\nd1 = Depends(mock_dep)\nd2 = Depends(mock_dep)\ns1 = Security(mock_dep)\ns2 = Security(mock_dep)\n\nprint(f\"Depends hashable: {hash(d1) == hash(d2)}\")\ntry:\n hash(d1)\n print(\"Depends is hashable\")\nexcept TypeError as e:\n print(f\"Depends is not hashable: {e}\")\n\ntry:\n hash(s1)\n print(\"Security is hashable\")\nexcept TypeError as e:\n print(f\"Security is not hashable: {e}\")\nPY\n"
} | {"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"<stdin>\", line 12, in <module>\nTypeError: unhafull{"status": "error", "error_type": "CommandError", "error_message": "Traceback (most recent call last):\n File \"<stdin>\", line 12, in <module>\nTypeError: unhashable type: 'Depends'\n", "details": {"stdout": "", "stderr": "Traceback (most recent call last):\n File \"<stdin>\", line 12, in <module>\nTypeError: unhashable type: 'Depends'\n", "exit_code": 1}} |
| 5 | run_command | {
"command": "python3 - <<'PY'\nfrom dataclasses import dataclass\nfrom typing import Optional, Any, Callable\n\n@dataclass\nclass Depends:\n dependency: Optional[Callable[..., Any]] = None\n\nd1 = Depends()\ntry:\n hash(d1)\n print(\"Hashable\")\nexcept TypeError as e:\n print(f\"Not hashable: {e}\")\nPY\n"
} | {"status": "ok", "stdout": "Not hashable: unhashable type: 'Depends'\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "Not hashable: unhashable type: 'Depends'\n", "stderr": "", "exit_code": 0} |
| 6 | run_command | {
"command": "python3 - <<'PY'\nfrom dataclasses import dataclass\nfrom typing import Optional, Any, Callable\n\n@dataclass(frozen=True)\nclass Depends:\n dependency: Optional[Callable[..., Any]] = None\n\nd1 = Depends()\ntry:\n hash(d1)\n print(\"Hashable\")\nexcept TypeError as e:\n print(f\"Not hashable: {e}\")\nPY\n"
} | {"status": "ok", "stdout": "Hashable\n", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "Hashable\n", "stderr": "", "exit_code": 0} |
| 7 | run_command | {
"command": "cd /workspace && python3 - <<'PY'\nfrom pathlib import Path\np = Path(\"fastapi/params.py\")\ns = p.read_text()\nold = \"\"\"@dataclass\nclass Depends:\n dependency: Optional[Callable[..., Any]] = None\n use_cache: bool = True\n scope: Union[Literal[\"function\", \"request\"], None] = None\n\n\n@dataclass\nclass Security(Depends):\n scopes: Optional[Sequence[str]] = None\"\"\"\nnew = \"\"\"@dataclass(frozen=True)\nclass Depends:\n dependency: Optional[Callable[..., Any]] = None\n use_cache: bool = True\n scope: Union[Literal[\"function\", \"request\"], None] = None\n\n\n@dataclass(frozen=True)\nclass Security(Depends):\n scopes: Optional[Sequence[str]] = None\"\"\"\nassert s.count(old) == 1, (\"old text found this many times:\", s.count(old))\nt = s.replace(old, new)\np.write_text(t)\nPY\n"
} | {"status": "ok", "stdout": "", "stderr": "", "exit_code": 0}full{"status": "ok", "stdout": "", "stderr": "", "exit_code": 0} |
| 8 | run_command | {
"command": "python3 - <<'PY'\nfrom fastapi.params import Depends, Security\nfrom typing import Callable\n\ndef mock_dep():\n return \"ok\"\n\nd1 = Depends(mock_dep)\nd2 = Depends(mock_dep)\ns1 = Security(mock_dep)\ns2 = Security(mock_dep)\n\nprint(f\"Depends hashable: {hash(d1) == hash(d2)}\")\nprint(f\"Security hashable: {hash(s1) == hash(s2)}\")\n\ntry:\n hash(d1)\n print(\"Depends is hashable\")\nexcept TypeError as e:\n print(f\"Depends is not hashable: {e}\")\n\ntry:\n hash(s1)\n print(\"Security is hashable\")\nexcept TypeError as e:\n print(f\"Security is not hashable: {e}\")\n\n# Verify that they are actually frozen (cannot be modified)\ntry:\n d1.use_cache = False\nexcept Exception as e:\n print(f\"Depends is frozen: {e}\")\n\ntry:\n s1.scopes = [\"admin\"]\nexcept Exception as e:\n print(f\"Security is frozen: {e}\")\nPY\n"
} | {"status": "ok", "stdout": "Depends hashable: True\nSecurity hashable: True\nDepends is hashable\nSecurity is hashable\nDepends is frozen: cannot assign to fielfull{"status": "ok", "stdout": "Depends hashable: True\nSecurity hashable: True\nDepends is hashable\nSecurity is hashable\nDepends is frozen: cannot assign to field 'use_cache'\nSecurity is frozen: cannot assign to field 'scopes'\n", "stderr": "", "exit_code": 0} |
| 9 | run_command | {
"command": "git diff"
} | {"status": "ok", "stdout": "diff --git a/fastapi/params.py b/fastapi/params.py\nindex 6a58d580..6d07df35 100644\n--- a/fastapi/params.py\n+++ b/fastapi/params.pfull{"status": "ok", "stdout": "diff --git a/fastapi/params.py b/fastapi/params.py\nindex 6a58d580..6d07df35 100644\n--- a/fastapi/params.py\n+++ b/fastapi/params.py\n@@ -762,13 +762,13 @@ class File(Form): # type: ignore[misc]\n )\n \n \n-@dataclass\n+@dataclass(frozen=True)\n class Depends:\n dependency: Optional[Callable[..., Any]] = None\n use_cache: bool = True\n scope: Union[Literal[\"function\", \"request\"], None] = None\n \n \n-@dataclass\n+@dataclass(frozen=True)\n class Security(Depends):\n scopes: Optional[Sequence[str]] = None\n", "stderr": "", "exit_code": 0} |
| 10 | submit_patch | {} | {"status": "ok", "patch_size": 516, "files_changed": 1}full{"status": "ok", "patch_size": 516, "files_changed": 1} |
diff --git a/fastapi/params.py b/fastapi/params.py
index 6a58d580..6d07df35 100644
--- a/fastapi/params.py
+++ b/fastapi/params.py
@@ -762,13 +762,13 @@ class File(Form): # type: ignore[misc]
)
-@dataclass
+@dataclass(frozen=True)
class Depends:
dependency: Optional[Callable[..., Any]] = None
use_cache: bool = True
scope: Union[Literal["function", "request"], None] = None
-@dataclass
+@dataclass(frozen=True)
class Security(Depends):
scopes: Optional[Sequence[str]] = None
. [100%] 1 passed in 0.28s