Skip to content

Commit

Permalink
Merge pull request #47 from knopki/feat-snake-case-dicts
Browse files Browse the repository at this point in the history
camel case <-> snake case autoconversion
  • Loading branch information
knopki authored Feb 5, 2024
2 parents af003bd + f15e30b commit ba7f8f9
Show file tree
Hide file tree
Showing 36 changed files with 468 additions and 379 deletions.
1 change: 1 addition & 0 deletions examples/example_async.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
"""Example of usage of asynchronous client"""
# pylint: skip-file

import asyncio
import sys
Expand Down
2 changes: 1 addition & 1 deletion examples/example_sync.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""Example of usage of synchronous client"""
# pylint: disable=no-value-for-parameter
# pylint: skip-file

import asyncio
import sys
Expand Down
30 changes: 11 additions & 19 deletions metis_client/client.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
"""Low level http and SSE client"""

import sys
import json
from asyncio import CancelledError
from asyncio import TimeoutError as AsyncioTimeoutError
from asyncio import sleep
from concurrent.futures import TimeoutError as FuturesTimeoutError
from datetime import timedelta
from json import JSONDecodeError
from typing import Any, Optional, Union

import aiohttp
Expand All @@ -25,23 +24,12 @@
from aiohttp_sse_client import client as sse_client
from yarl import URL

from .compat import Callable, Dict, Mapping, NotRequired, TypedDict, Unpack
from .const import HttpMethods
from .exc import MetisConnectionException, MetisException
from .helpers import http_to_metis_error_map
from .helpers import http_to_metis_error_map, metis_json_decoder, metis_json_encoder
from .models import BaseAuthenticator, MetisBase, MetisNoAuth

if sys.version_info < (3, 9): # pragma: no cover
from typing import Callable, Dict, Mapping
else: # pragma: no cover
from collections.abc import Callable, Mapping

Dict = dict

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import NotRequired, TypedDict, Unpack
else: # pragma: no cover
from typing import NotRequired, TypedDict, Unpack


class ClientRequestKwargs(TypedDict):
"MetisClient.create kwargs"
Expand Down Expand Up @@ -77,6 +65,8 @@ def __init__(
`auth`: Authenticator, subclass of `BaseAuthenticator`.
"""
self._session = session
if self._session.json_serialize is not metis_json_encoder:
self._session._json_serialize = metis_json_encoder
self._auth = auth or MetisNoAuth()
if not base_url.is_absolute():
raise TypeError("Base URL should be absolute")
Expand Down Expand Up @@ -153,7 +143,7 @@ async def _request(
f"Timeout of {opts.get('timeout')} reached while waiting for {str(url)}"
) from None

except BaseException as exc: # pragma: no cover
except BaseException as exc: # pragma: no cover # noqa: B036
raise MetisException(
f"Unexpected exception for {str(url)!r} with - {exc}"
) from exc
Expand All @@ -163,19 +153,21 @@ async def _request(
body = None
if result.content_type.startswith("application/json"):
body = await result.json(
encoding="utf-8", content_type=result.content_type
encoding="utf-8",
content_type=result.content_type,
loads=metis_json_decoder,
)
if isinstance(body, dict) and body.get("error", None):
msg = str(body.get("error"))
elif result.content_type.startswith("text/"):
msg = await result.text("utf-8")
else:
msg = str(await result.read())
except (ClientPayloadError, JSONDecodeError) as exc:
except (ClientPayloadError, json.JSONDecodeError) as exc:
raise MetisException(
f"Broken payload data from {str(url)!r}: {exc}"
) from exc
except BaseException as exc: # pragma: no cover
except BaseException as exc: # pragma: no cover # noqa: B036
raise MetisException(
f"Could not handle response data from {str(url)!r} with - {exc}"
) from exc
Expand Down
38 changes: 38 additions & 0 deletions metis_client/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Compatibility layer"""

import sys

if sys.version_info < (3, 9): # pragma: no cover
from typing import Awaitable, Callable, Dict, List, Mapping, Sequence
else: # pragma: no cover
from collections.abc import Awaitable, Callable, Mapping, Sequence

Dict = dict
List = list


if sys.version_info < (3, 10): # pragma: no cover
from typing_extensions import TypeGuard
else: # pragma: no cover
from typing import TypeGuard

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import Concatenate, NotRequired, ParamSpec, TypedDict, Unpack
else: # pragma: no cover
from typing import Concatenate, NotRequired, ParamSpec, TypedDict, Unpack


__all__ = [
"Awaitable",
"Callable",
"Concatenate",
"Dict",
"List",
"Mapping",
"NotRequired",
"ParamSpec",
"Sequence",
"TypeGuard",
"TypedDict",
"Unpack",
]
7 changes: 1 addition & 6 deletions metis_client/dtos/auth.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
"""Authentication DTOs"""

import sys

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import TypedDict
else: # pragma: no cover
from typing import TypedDict
from ..compat import TypedDict


class MetisAuthCredentialsRequestDTO(TypedDict):
Expand Down
10 changes: 3 additions & 7 deletions metis_client/dtos/base.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
"""Base of DTOs"""

import sys
from datetime import datetime

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import NotRequired, TypedDict
else: # pragma: no cover
from typing import NotRequired, TypedDict
from ..compat import NotRequired, TypedDict


class MetisTimestampsDTO(TypedDict):
"Response with timestamps"
createdAt: NotRequired[datetime]
updatedAt: NotRequired[datetime]
created_at: NotRequired[datetime]
updated_at: NotRequired[datetime]
14 changes: 2 additions & 12 deletions metis_client/dtos/calculation.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
"""Calculation DTOs"""
import sys

from ..compat import NotRequired, Sequence
from .base import MetisTimestampsDTO
from .datasource import MetisDataSourceDTO

if sys.version_info < (3, 9): # pragma: no cover
from typing import Sequence
else: # pragma: no cover
from collections.abc import Sequence

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import NotRequired
else: # pragma: no cover
from typing import NotRequired


class MetisCalculationDTO(MetisTimestampsDTO):
"Calculation DTO"
id: int
name: str
userId: int
user_id: int
progress: int
parent: int
result: NotRequired[Sequence[MetisDataSourceDTO]]
31 changes: 11 additions & 20 deletions metis_client/dtos/collection.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
"""Collections DTOs"""

import sys
# pylint: disable=too-many-ancestors

from typing import Literal, Union

from ..compat import NotRequired, Sequence, TypedDict
from .base import MetisTimestampsDTO

if sys.version_info < (3, 9): # pragma: no cover
from typing import Sequence
else: # pragma: no cover
from collections.abc import Sequence

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import NotRequired, TypedDict
else: # pragma: no cover
from typing import NotRequired, TypedDict


MetisCollectionVisibility = Union[
Literal["private"], Literal["shared"], Literal["community"]
]
Expand All @@ -35,8 +26,8 @@ class MetisCollectionCommonDTO(TypedDict):

id: NotRequired[int]
title: str
typeId: int
dataSources: NotRequired[Sequence[int]]
type_id: int
data_sources: NotRequired[Sequence[int]]
users: NotRequired[Sequence[int]]


Expand All @@ -54,9 +45,9 @@ class MetisCollectionDTO(MetisCollectionCommonDTO, MetisTimestampsDTO):
description: str
visibility: MetisCollectionVisibility

userId: int
userFirstName: NotRequired[str]
userLastName: NotRequired[str]
typeSlug: NotRequired[str]
typeLabel: NotRequired[str]
typeFlavor: NotRequired[str]
user_id: int
user_first_name: NotRequired[str]
user_last_name: NotRequired[str]
type_slug: NotRequired[str]
type_label: NotRequired[str]
type_flavor: NotRequired[str]
22 changes: 7 additions & 15 deletions metis_client/dtos/datasource.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
"""Data sources DTOs"""

import sys
# pylint: disable=too-many-ancestors

from enum import Enum

from ..compat import Sequence, TypedDict
from .base import MetisTimestampsDTO
from .collection import MetisCollectionDTO

if sys.version_info < (3, 9): # pragma: no cover
from typing import Sequence
else: # pragma: no cover
from collections.abc import Sequence

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import TypedDict
else: # pragma: no cover
from typing import TypedDict


class DataSourceType(int, Enum):
"""The basic data types supported"""
Expand All @@ -34,10 +26,10 @@ class MetisDataSourceDTO(MetisTimestampsDTO):
id: int
parents: Sequence[int]
children: Sequence[int]
userId: int
userFirstName: str
userLastName: str
userEmail: str
user_id: int
user_first_name: str
user_last_name: str
user_email: str
name: str
content: str
type: int
Expand Down
8 changes: 3 additions & 5 deletions metis_client/dtos/error.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
"""Error DTOs"""

import sys
# pylint: disable=too-many-ancestors

from typing import Union

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import TypedDict
else: # pragma: no cover
from typing import TypedDict
from ..compat import TypedDict


class MetisErrorMessageDTO(TypedDict):
Expand Down
21 changes: 5 additions & 16 deletions metis_client/dtos/event.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,19 @@
"""SSE DTOs"""

import sys
from typing import Literal, Union

from ..compat import Sequence, TypedDict
from .calculation import MetisCalculationDTO
from .collection import MetisCollectionDTO, MetisCollectionTypeDTO
from .datasource import MetisDataSourceDTO
from .error import MetisErrorDTO

if sys.version_info < (3, 9): # pragma: no cover
from typing import Sequence
else: # pragma: no cover
from collections.abc import Sequence

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import TypedDict
else: # pragma: no cover
from typing import TypedDict


MetisEventType = Literal["calculations", "collections", "datasources", "errors", "pong"]


class MetisErrorEventDataDTO(TypedDict):
"Errors event data DTO"
reqId: str
req_id: str
data: Sequence[MetisErrorDTO]


Expand All @@ -42,7 +31,7 @@ class MetisPongEventDTO(TypedDict):

class MetisDataSourcesEventDataDTO(TypedDict):
"Data sources event data DTO"
reqId: str
req_id: str
data: Sequence[MetisDataSourceDTO]
total: int
types: Sequence[MetisCollectionTypeDTO]
Expand All @@ -56,7 +45,7 @@ class MetisDataSourcesEventDTO(TypedDict):

class MetisCalculationsEventDataDTO(TypedDict):
"Calculations event data DTO"
reqId: str
req_id: str
data: Sequence[MetisCalculationDTO]
total: int
types: Sequence[MetisCollectionTypeDTO]
Expand All @@ -70,7 +59,7 @@ class MetisCalculationsEventDTO(TypedDict):

class MetisCollectionsEventDataDTO(TypedDict):
"Collections event data DTO"
reqId: str
req_id: str
data: Sequence[MetisCollectionDTO]
total: int
types: Sequence[MetisCollectionTypeDTO]
Expand Down
9 changes: 2 additions & 7 deletions metis_client/dtos/resp.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
"Base response DTO"

import sys

if sys.version_info < (3, 11): # pragma: no cover
from typing_extensions import TypedDict
else: # pragma: no cover
from typing import TypedDict
from ..compat import TypedDict


class MetisRequestIdDTO(TypedDict):
"Response with request id dictionary"
reqId: str
req_id: str
Loading

0 comments on commit ba7f8f9

Please sign in to comment.