Skip to content

Commit

Permalink
[8.0] Use 'ApiResponse.body' instead of 'raw'
Browse files Browse the repository at this point in the history
  • Loading branch information
sethmlarson committed Dec 28, 2021
1 parent b7c6dfe commit 038fb32
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 133 deletions.
2 changes: 1 addition & 1 deletion elastic_transport/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def warn_stacklevel() -> int:
try:
# Grab the root module from the current module '__name__'
module_name = __name__.partition(".")[0]
module_path = Path(sys.modules[module_name].__file__)
module_path = Path(sys.modules[module_name].__file__) # type: ignore[arg-type]

# If the module is a folder we're looking at
# subdirectories, otherwise we're looking for
Expand Down
4 changes: 2 additions & 2 deletions elastic_transport/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
from dataclasses import dataclass, field
from typing import (
TYPE_CHECKING,
AbstractSet,
Any,
Collection,
Dict,
Iterator,
KeysView,
Mapping,
MutableMapping,
Optional,
Expand Down Expand Up @@ -135,7 +135,7 @@ def __hash__(self) -> int:
def get(self, key: str, default: Optional[str] = None) -> Optional[str]: # type: ignore[override]
return self._internal.get(self._normalize_key(key), (None, default))[1]

def keys(self) -> AbstractSet[str]:
def keys(self) -> KeysView[str]:
return self._internal.keys()

def values(self) -> ValuesView[str]:
Expand Down
2 changes: 1 addition & 1 deletion elastic_transport/_node/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def ssl_context_from_node_config(node_config: NodeConfig) -> ssl.SSLContext:
if hasattr(ctx, "keylog_filename"):
sslkeylogfile = os.environ.get("SSLKEYLOGFILE", "")
if sslkeylogfile:
ctx.keylog_filename = sslkeylogfile # type: ignore[attr-defined]
ctx.keylog_filename = sslkeylogfile

# Apply the 'ssl_version' if given, otherwise default to TLSv1.2+
ssl_version = node_config.ssl_version
Expand Down
2 changes: 1 addition & 1 deletion elastic_transport/_node_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def __init__(self, node_configs: List[NodeConfig]):

def select(self, nodes: Sequence[BaseNode]) -> BaseNode:
self._thread_local.rr = (getattr(self._thread_local, "rr", -1) + 1) % len(nodes)
return nodes[self._thread_local.rr] # type: ignore[no-any-return]
return nodes[self._thread_local.rr]


_SELECTOR_CLASS_NAMES: Dict[str, Type[NodeSelector]] = {
Expand Down
172 changes: 75 additions & 97 deletions elastic_transport/_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,121 +22,127 @@
Iterable,
Iterator,
List,
Optional,
Type,
NoReturn,
TypeVar,
Union,
overload,
)

from ._models import ApiResponseMeta

_RawType = TypeVar("_RawType")
_BodyType = TypeVar("_BodyType")
_ObjectBodyType = TypeVar("_ObjectBodyType")
_ListItemRawType = TypeVar("_ListItemRawType")
_ListItemBodyType = TypeVar("_ListItemBodyType")


class ApiResponse(Generic[_RawType, _BodyType]):
class ApiResponse(Generic[_BodyType]):
"""Base class for all API response classes"""

__slots__ = ("_raw", "_meta", "_body_cls")
__slots__ = ("_body", "_meta")

def __init__(
self,
raw: _RawType,
meta: ApiResponseMeta,
body_cls: Optional[Type[_BodyType]] = None,
*args: Any,
**kwargs: Any,
):
self._raw = raw
def _raise_typeerror() -> NoReturn:
raise TypeError("Must pass 'meta' and 'body' to ApiResponse") from None

# Working around pre-releases of elasticsearch-python
# that would use raw=... instead of body=...
try:
if bool(args) == bool(kwargs):
_raise_typeerror()
elif args and len(args) == 2:
body, meta = args
elif kwargs and "raw" in kwargs:
body = kwargs.pop("raw")
meta = kwargs.pop("meta")
kwargs.pop("body_cls", None)
elif kwargs and "body" in kwargs:
body = kwargs.pop("body")
meta = kwargs.pop("meta")
kwargs.pop("body_cls", None)
else:
_raise_typeerror()
except KeyError:
_raise_typeerror()
# If there are still kwargs left over
# and we're not in positional mode...
if not args and kwargs:
_raise_typeerror()

self._body = body
self._meta = meta
self._body_cls = body_cls

def __repr__(self) -> str:
body_repr: Any = self._raw
try:
body_repr = self.body
except NotImplementedError:
pass
return f"{type(self).__name__}({body_repr!r})"
return f"{type(self).__name__}({self.body!r})"

def __contains__(self, item: Any) -> bool:
return item in self._raw # type: ignore[operator]
return item in self._body

def __eq__(self, other: object) -> bool:
if isinstance(other, ApiResponse):
other = other._raw
return self._raw == other
other = other.body
return self._body == other # type: ignore[no-any-return]

def __ne__(self, other: object) -> bool:
if isinstance(other, ApiResponse):
other = other.raw
return self._raw != other
other = other.body
return self._body != other # type: ignore[no-any-return]

def __getitem__(self, item: Any) -> Any:
return self._raw[item] # type: ignore[index]
return self._body[item]

def __getattr__(self, attr: str) -> Any:
return getattr(self._raw, attr)
return getattr(self._body, attr)

def __len__(self) -> int:
return len(self._raw) # type: ignore[arg-type]
return len(self._body)

def __iter__(self) -> Iterable[Any]:
return iter(self._raw) # type: ignore[no-any-return,call-overload]
return iter(self._body)

def __str__(self) -> str:
return str(self._raw)
return str(self._body)

def __bool__(self) -> bool:
return bool(self._raw)
return bool(self._body)

@property
def meta(self) -> ApiResponseMeta:
"""Response metadata"""
return self._meta

@property
def raw(self) -> _RawType:
"""Raw deserialized response"""
return self._raw
return self._meta # type: ignore[no-any-return]

@property
def body(self) -> _BodyType:
"""User-friendly view into the raw response with type hints if applicable"""
raise NotImplementedError()
return self._body # type: ignore[no-any-return]

@property
def raw(self) -> _BodyType:
return self.body


class TextApiResponse(ApiResponse[str, str]):
class TextApiResponse(ApiResponse[str]):
"""API responses which are text such as 'text/plain' or 'text/csv'"""

def __init__(self, raw: str, meta: ApiResponseMeta):
super().__init__(raw=raw, meta=meta)

def __iter__(self) -> Iterable[str]:
return iter(self._raw)
return iter(self.body)

def __getitem__(self, item: Union[int, slice]) -> str:
return self._raw[item]

@property
def raw(self) -> str:
return self._raw
return self.body[item]

@property
def body(self) -> str:
return self.raw
return self._body # type: ignore[no-any-return]


class BinaryApiResponse(ApiResponse[bytes, bytes]):
class BinaryApiResponse(ApiResponse[bytes]):
"""API responses which are a binary response such as Mapbox vector tiles"""

def __init__(self, raw: bytes, meta: ApiResponseMeta):
super().__init__(raw=raw, meta=meta)

def __iter__(self) -> Iterable[int]:
return iter(self.raw)
return iter(self.body)

@overload
def __getitem__(self, item: slice) -> bytes:
Expand All @@ -147,91 +153,63 @@ def __getitem__(self, item: int) -> int:
...

def __getitem__(self, item: Union[int, slice]) -> Union[int, bytes]:
return self.raw[item]

@property
def raw(self) -> bytes:
return self._raw
return self.body[item]

@property
def body(self) -> bytes:
return self.raw
return self._body # type: ignore[no-any-return]


class HeadApiResponse(ApiResponse[bool, bool]):
class HeadApiResponse(ApiResponse[bool]):
"""API responses which are for an 'exists' / HEAD API request"""

def __init__(self, meta: ApiResponseMeta):
super().__init__(raw=200 <= meta.status < 300, meta=meta)
super().__init__(body=200 <= meta.status < 300, meta=meta)

def __bool__(self) -> bool:
return 200 <= self.meta.status < 300

@property
def raw(self) -> bool:
return bool(self)

@property
def body(self) -> bool:
return bool(self)


class ObjectApiResponse(
Generic[_ObjectBodyType], ApiResponse[Dict[str, Any], _ObjectBodyType]
):
class ObjectApiResponse(Generic[_ObjectBodyType], ApiResponse[Dict[str, Any]]):
"""API responses which are for a JSON object"""

def __init__(self, raw: Dict[str, Any], meta: ApiResponseMeta):
super().__init__(raw=raw, meta=meta)

def __getitem__(self, item: str) -> Any:
return self.raw[item]
return self.body[item] # type: ignore[index]

def __iter__(self) -> Iterator[str]:
return iter(self.raw)
return iter(self._body)

@property
def raw(self) -> Dict[str, Any]:
return self._raw

@property
def body(self) -> _ObjectBodyType:
if self._body_cls is None:
raise NotImplementedError
return self._body_cls(self.raw) # type: ignore[call-arg]
def body(self) -> _ObjectBodyType: # type: ignore[override]
return self._body # type: ignore[no-any-return]


class ListApiResponse(
Generic[_ListItemRawType, _ListItemBodyType],
ApiResponse[List[_ListItemRawType], List[_ListItemBodyType]],
Generic[_ListItemBodyType],
ApiResponse[List[Any]],
):
"""API responses which are a list of items. Can be NDJSON or a JSON list"""

def __init__(self, raw: List[Any], meta: ApiResponseMeta):
super().__init__(raw=raw, meta=meta)

@overload
def __getitem__(self, item: slice) -> List[_ListItemRawType]:
def __getitem__(self, item: slice) -> List[_ListItemBodyType]:
...

@overload
def __getitem__(self, item: int) -> _ListItemRawType:
def __getitem__(self, item: int) -> _ListItemBodyType:
...

def __getitem__(
self, item: Union[int, slice]
) -> Union[_ListItemRawType, List[_ListItemRawType]]:
return self.raw[item]
) -> Union[_ListItemBodyType, List[_ListItemBodyType]]:
return self.body[item]

def __iter__(self) -> Iterable[_ListItemRawType]:
return iter(self.raw)

@property
def raw(self) -> List[_ListItemRawType]:
return self._raw
def __iter__(self) -> Iterable[_ListItemBodyType]:
return iter(self.body)

@property
def body(self) -> List[_ListItemBodyType]:
if self._body_cls is None:
raise NotImplementedError
return [self._body_cls(item) for item in self._raw] # type: ignore[call-overload]
return self._body # type: ignore[no-any-return]
2 changes: 1 addition & 1 deletion elastic_transport/_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ def __init__(
if sniff_on_start:
self.sniff(True)

def perform_request( # type: ignore[override,return]
def perform_request( # type: ignore[return]
self,
method: str,
target: str,
Expand Down
Loading

0 comments on commit 038fb32

Please sign in to comment.