From d452e396e3b811b9a50dab25e29367a38b1ee143 Mon Sep 17 00:00:00 2001 From: Seungwoo Hong Date: Sun, 4 Feb 2024 22:57:51 +0900 Subject: [PATCH 1/3] modify `State` to use `SimpleNamespace` --- starlette/datastructures.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/starlette/datastructures.py b/starlette/datastructures.py index e430d09b6..a3fa4bb26 100644 --- a/starlette/datastructures.py +++ b/starlette/datastructures.py @@ -2,6 +2,7 @@ import typing from shlex import shlex +from types import SimpleNamespace from urllib.parse import SplitResult, parse_qsl, urlencode, urlsplit from starlette.concurrency import run_in_threadpool @@ -677,7 +678,7 @@ def add_vary_header(self, vary: str) -> None: self["vary"] = vary -class State: +class State(SimpleNamespace): """ An object that can be used to store arbitrary state. @@ -690,16 +691,8 @@ def __init__(self, state: dict[str, typing.Any] | None = None): if state is None: state = {} super().__setattr__("_state", state) + super().__init__(**state) def __setattr__(self, key: typing.Any, value: typing.Any) -> None: + super().__setattr__(key, value) self._state[key] = value - - def __getattr__(self, key: typing.Any) -> typing.Any: - try: - return self._state[key] - except KeyError: - message = "'{}' object has no attribute '{}'" - raise AttributeError(message.format(self.__class__.__name__, key)) - - def __delattr__(self, key: typing.Any) -> None: - del self._state[key] From e04302d670eb89eff4f9219124535b44b638a0f5 Mon Sep 17 00:00:00 2001 From: Seungwoo Hong Date: Thu, 8 Feb 2024 18:03:44 +0900 Subject: [PATCH 2/3] . --- starlette/datastructures.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/starlette/datastructures.py b/starlette/datastructures.py index a3fa4bb26..3f41b247a 100644 --- a/starlette/datastructures.py +++ b/starlette/datastructures.py @@ -2,7 +2,6 @@ import typing from shlex import shlex -from types import SimpleNamespace from urllib.parse import SplitResult, parse_qsl, urlencode, urlsplit from starlette.concurrency import run_in_threadpool @@ -678,7 +677,7 @@ def add_vary_header(self, vary: str) -> None: self["vary"] = vary -class State(SimpleNamespace): +class State: """ An object that can be used to store arbitrary state. @@ -691,8 +690,17 @@ def __init__(self, state: dict[str, typing.Any] | None = None): if state is None: state = {} super().__setattr__("_state", state) - super().__init__(**state) def __setattr__(self, key: typing.Any, value: typing.Any) -> None: - super().__setattr__(key, value) self._state[key] = value + + def __getattribute__(self, key: typing.Any) -> typing.Any: + state = object.__getattribute__(self, "_state") + + if key in state: + return state[key] + + return object.__getattribute__(self, key) + + def __delattr__(self, key: typing.Any) -> None: + del self._state[key] From 50bbcafce6dfc53b178782a5fbc48ed4b76d9c6f Mon Sep 17 00:00:00 2001 From: Seungwoo Hong Date: Thu, 8 Feb 2024 18:09:14 +0900 Subject: [PATCH 3/3] . --- starlette/datastructures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starlette/datastructures.py b/starlette/datastructures.py index 3f41b247a..b93570e91 100644 --- a/starlette/datastructures.py +++ b/starlette/datastructures.py @@ -692,7 +692,7 @@ def __init__(self, state: dict[str, typing.Any] | None = None): super().__setattr__("_state", state) def __setattr__(self, key: typing.Any, value: typing.Any) -> None: - self._state[key] = value + object.__getattribute__(self, "_state")[key] = value def __getattribute__(self, key: typing.Any) -> typing.Any: state = object.__getattribute__(self, "_state")