Skip to content

Commit

Permalink
use jiter for httpx responses; remove twice deserialization on XrpcError
Browse files Browse the repository at this point in the history
  • Loading branch information
MarshalX committed Jul 26, 2024
1 parent ff32279 commit 131d951
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 16 deletions.
15 changes: 9 additions & 6 deletions packages/atproto_client/models/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,17 @@ def get_model_as_json(model: t.Union[DotDict, BlobRef, ModelBase]) -> str:


def is_json(json_data: t.Union[str, bytes]) -> bool:
if isinstance(json_data, bytes):
json_data.decode('UTF-8', errors='ignore')
return load_json(json_data, strict=False) is not None


def load_json(json_data: t.Union[str, bytes], strict: bool = True) -> t.Optional[t.Dict[str, t.Any]]:
try:
from_json(json_data)
return True
except ValueError:
return False
return from_json(json_data)
except ValueError as e:
if strict:
raise e

return None


def is_record_type(model: t.Union[ModelBase, DotDict], expected_type: t.Union[str, types.ModuleType]) -> bool:
Expand Down
10 changes: 5 additions & 5 deletions packages/atproto_client/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from atproto_client import exceptions
from atproto_client.models.common import XrpcError
from atproto_client.models.utils import get_or_create, is_json
from atproto_client.models.utils import get_or_create, load_json


@dataclass
Expand Down Expand Up @@ -35,7 +35,7 @@ def _convert_headers_to_dict(headers: httpx.Headers) -> t.Dict[str, str]:
def _parse_response(response: httpx.Response) -> Response:
content = response.content
if response.headers.get('content-type') == 'application/json; charset=utf-8':
content = response.json()
content = from_json(response.content)

return Response(
success=True,
Expand Down Expand Up @@ -65,9 +65,9 @@ def _handle_response(response: httpx.Response) -> httpx.Response:
content=response.content,
headers=_convert_headers_to_dict(response.headers),
)
if response.content and is_json(response.content):
data: t.Dict[str, t.Any] = from_json(response.content)
error_response.content = t.cast(XrpcError, get_or_create(data, XrpcError, strict=False))
error_content = load_json(response.content, strict=False)
if error_content:
error_response.content = t.cast(XrpcError, get_or_create(error_content, XrpcError, strict=False))

if response.status_code in {401, 403}:
raise exceptions.UnauthorizedError(error_response)
Expand Down
5 changes: 3 additions & 2 deletions packages/atproto_identity/did/resolvers/plc_resolver.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import typing as t

import httpx
from pydantic_core import from_json

from atproto_identity.did.resolvers.base_resolver import AsyncBaseResolver, BaseResolver
from atproto_identity.exceptions import DidPlcResolverError
Expand Down Expand Up @@ -31,7 +32,7 @@ def resolve_without_validation(self, did: str) -> t.Optional[t.Dict[str, t.Any]]
return None

response.raise_for_status()
return response.json()
return from_json(response.content)
except httpx.HTTPError as e:
raise DidPlcResolverError(f'Error resolving DID {did}') from e

Expand All @@ -58,6 +59,6 @@ async def resolve_without_validation(self, did: str) -> t.Optional[t.Dict[str, t
return None

response.raise_for_status()
return response.json()
return from_json(response.content)
except httpx.HTTPError as e:
raise DidPlcResolverError(f'Error resolving DID {did}') from e
5 changes: 3 additions & 2 deletions packages/atproto_identity/did/resolvers/web_resolver.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import typing as t

import httpx
from pydantic_core import from_json

from atproto_identity.did.resolvers.base_resolver import AsyncBaseResolver, BaseResolver
from atproto_identity.exceptions import DidWebResolverError, PoorlyFormattedDidError, UnsupportedDidWebPathError
Expand Down Expand Up @@ -45,7 +46,7 @@ def resolve_without_validation(self, did: str) -> t.Dict[str, t.Any]:
try:
response = self._client.get(url, timeout=self._timeout)
response.raise_for_status()
return response.json()
return from_json(response.content)
except httpx.HTTPError as e:
raise DidWebResolverError(f'Error resolving DID {did}') from e

Expand All @@ -68,6 +69,6 @@ async def resolve_without_validation(self, did: str) -> t.Dict[str, t.Any]:
try:
response = await self._client.get(url, timeout=self._timeout)
response.raise_for_status()
return response.json()
return from_json(response.content)
except httpx.HTTPError as e:
raise DidWebResolverError(f'Error resolving DID {did}') from e
36 changes: 36 additions & 0 deletions tests/test_atproto_client/models/tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest
from atproto_client.models.utils import is_json, load_json


def test_load_json() -> None:
assert load_json('{"key": "value"}')
assert load_json(b'{"key": "value"}')

assert load_json('{"key": "value"', strict=False) is None
with pytest.raises(ValueError):
load_json(b'{"key": "value"')

assert load_json('{"key": "value"', strict=False) is None
with pytest.raises(ValueError):
load_json(b'{"key": "value"')

assert load_json('{"key": "value"}'.encode('UTF-16'), strict=False) is None

with pytest.raises(TypeError):
load_json(None)


def test_is_json() -> None:
assert is_json('{"key": "value"}') is True
assert is_json(b'{"key": "value"}') is True

assert is_json('{"key": "value"') is False
assert is_json(b'{"key": "value"') is False

assert is_json('{"key": "value"}'.encode('UTF-16')) is False

assert is_json(b'') is False
assert is_json(b'{}') is True

with pytest.raises(TypeError):
load_json(None)
3 changes: 2 additions & 1 deletion update_lexicons.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pathlib import Path

import httpx
from pydantic_core import from_json

_GITHUB_BASE_URL = 'https://github.com'
_GITHUB_API_BASE_URL = 'https://api.github.com'
Expand Down Expand Up @@ -44,7 +45,7 @@ def _get_last_commit_info() -> t.Tuple[str, str, str]:
)
response.raise_for_status()

response_json = response.json()
response_json = from_json(response.content)
commit_info = response_json[0]

sha = commit_info['sha']
Expand Down

0 comments on commit 131d951

Please sign in to comment.