Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,12 @@ packages = ["valkey"]
sqlite_cache = true

[[tool.mypy.overrides]]
# The goal is to eliminate the `tool.mypy.overrides` section.
# The goal is to eliminate the `tool.mypy.overrides` sections.
# This will be accomplished by resolving type annotation issues
# in the modules listed below.
#
# Type checking may be re-enabled for specific submodules
# in a second "overrides" section, below.
ignore_errors = true
module = [
"valkey.client",
Expand All @@ -129,3 +132,15 @@ module = [
"valkey.asyncio.*",
"valkey._parsers.*",
]


[[tool.mypy.overrides]]
# This config section re-enables type-checking for submodules.
# For example, if all submodules in "valkey.x.*" are disabled above,
# this section might re-enable type-checking for "valkey.x.foo"
# as type annotations are added, corrected, and tested
# in "valkey.x.*", submodule by submodule.
ignore_errors = false
module = [
"valkey._parsers.encoders",
]
55 changes: 52 additions & 3 deletions valkey/_parsers/encoders.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,48 @@
from __future__ import annotations

import sys
from typing import Any, Literal, overload

from ..exceptions import DataError

if sys.version_info >= (3, 11):
from typing import Never
else:
from typing_extensions import Never


class Encoder:
"Encode strings to bytes-like and decode bytes-like to strings"

__slots__ = "encoding", "encoding_errors", "decode_responses"

def __init__(self, encoding, encoding_errors, decode_responses):
def __init__(
self,
encoding: str,
encoding_errors: (
Literal["ignore", "replace", "strict", "xmlcharrefreplace"] | str
),
decode_responses: bool,
) -> None:
self.encoding = encoding
self.encoding_errors = encoding_errors
self.decode_responses = decode_responses

def encode(self, value):
@overload
def encode(self, value: memoryview[bytes]) -> memoryview[bytes]: ...

@overload
def encode(self, value: bool) -> Never: ...

@overload
def encode(self, value: bytes | int | float | str) -> bytes: ...

@overload
def encode(self, value: Any) -> Never: ...

def encode(
self, value: bytes | memoryview[bytes] | int | float | str
) -> bytes | memoryview[bytes]:
"Return a bytestring or bytes-like representation of the value"
if isinstance(value, (bytes, memoryview)):
return value
Expand All @@ -34,7 +65,25 @@ def encode(self, value):
value = value.encode(self.encoding, self.encoding_errors)
return value

def decode(self, value, force=False):
@overload
def decode(
self,
value: bytes | memoryview[bytes] | str,
force: Literal[True],
) -> str: ...

@overload
def decode(
self,
value: bytes | memoryview[bytes] | str,
force: Literal[False],
) -> bytes | memoryview[bytes] | str: ...

def decode(
self,
value: bytes | memoryview[bytes] | str,
force: bool = False,
) -> Any:
"Return a unicode string from the bytes-like representation"
if self.decode_responses or force:
if isinstance(value, memoryview):
Expand Down