diff --git a/src/meta_memcache/connection/memcache_socket.py b/src/meta_memcache/connection/memcache_socket.py index b396961..7bf14cf 100644 --- a/src/meta_memcache/connection/memcache_socket.py +++ b/src/meta_memcache/connection/memcache_socket.py @@ -21,6 +21,9 @@ ) _log: logging.Logger = logging.getLogger(__name__) +NOT_STORED = NotStored() +MISS = Miss() +CONFLICT = Conflict() class MemcacheSocket: @@ -224,15 +227,15 @@ def get_response( self._add_flags(result, chunks) elif response_code == b"NS": # Value response, parse size and flags - result = NotStored() + result = NOT_STORED assert len(chunks) == 0 # noqa: S101 elif response_code == b"EX": # Already exists, not changed, CAS conflict - result = Conflict() + result = CONFLICT assert len(chunks) == 0 # noqa: S101 elif response_code == b"EN" or response_code == b"NF": # Not Found, Miss. - result = Miss() + result = MISS assert len(chunks) == 0 # noqa: S101 else: raise MemcacheError(f"Unknown response: {bytes(response_code)!r}") diff --git a/src/meta_memcache/protocol.py b/src/meta_memcache/protocol.py index 2bdf826..831c7a6 100644 --- a/src/meta_memcache/protocol.py +++ b/src/meta_memcache/protocol.py @@ -1,6 +1,6 @@ from dataclasses import dataclass from enum import Enum, IntEnum -from typing import Any, Dict, List, NamedTuple, Optional, Set, Union +from typing import Any, Dict, List, Optional, Set, Union ENDL = b"\r\n" NOOP: bytes = b"mn" + ENDL @@ -8,10 +8,25 @@ SPACE: int = ord(" ") -class Key(NamedTuple): +@dataclass +class Key: + __slots__ = ("key", "routing_key", "is_unicode") key: str - routing_key: Optional[str] = None - is_unicode: bool = False + routing_key: Optional[str] + is_unicode: bool + + def __init__( + self, + key: str, + routing_key: Optional[str] = None, + is_unicode: bool = False, + ) -> None: + self.key = key + self.routing_key = routing_key + self.is_unicode = is_unicode + + def __hash__(self) -> int: + return hash((self.key, self.routing_key)) class MetaCommand(Enum): @@ -84,16 +99,19 @@ class TokenFlag(Enum): token_flags_values: Dict[int, TokenFlag] = {f.value[0]: f for f in TokenFlag} +@dataclass class MemcacheResponse: - pass + __slots__ = () +@dataclass class Miss(MemcacheResponse): - pass + __slots__ = () @dataclass class Success(MemcacheResponse): + __slots__ = ("flags", "int_flags", "token_flags") flags: Set[Flag] int_flags: Dict[IntFlag, int] token_flags: Dict[TokenFlag, bytes] @@ -111,6 +129,7 @@ def __init__( @dataclass class Value(Success): + __slots__ = ("flags", "int_flags", "token_flags", "size", "value") size: int value: Optional[Any] @@ -127,7 +146,9 @@ def __init__( self.value = value -class ValueContainer(NamedTuple): +@dataclass +class ValueContainer: + __slots__ = ("value",) value: Any @@ -137,12 +158,12 @@ class ValueContainer(NamedTuple): @dataclass class NotStored(MemcacheResponse): - pass + __slots__ = () @dataclass class Conflict(MemcacheResponse): - pass + __slots__ = () ReadResponse = Union[Miss, Value, Success]