soia-client 1.0.10__py3-none-any.whl → 1.0.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of soia-client might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: soia-client
3
- Version: 1.0.10
3
+ Version: 1.0.11
4
4
  Author-email: Tyler Fibonacci <gepheum@gmail.com>
5
5
  License: MIT License
6
6
 
@@ -1,11 +1,13 @@
1
- soia_client-1.0.10.dist-info/licenses/LICENSE,sha256=SaAftKkX6hfSOiPdENQPS70tifH3PDHgazq8eK2Pwfw,1064
2
- soialib/__init__.py,sha256=h_ENkLJEdrh1mGhCoKgIadDasSulW3zK9_qhEsTviXY,429
1
+ soia_client-1.0.11.dist-info/licenses/LICENSE,sha256=SaAftKkX6hfSOiPdENQPS70tifH3PDHgazq8eK2Pwfw,1064
2
+ soialib/_.py,sha256=I4SxBM3brmE9D6hyrDrdkbfVnDLVRWaGwnj0C9Zxh54,52
3
+ soialib/__init__.py,sha256=UyNrMaKEwCmYecsEwgsglMJvjKzIbDp7idbIxLdBz_k,499
3
4
  soialib/keyed_items.py,sha256=q7MCn82obf-0jh7FcAhuw4eh9-wtuHIpkEFcSfc8EaY,338
4
5
  soialib/method.py,sha256=2qWG4jMqYhS3hA8y8YDu3iqzhXA_AKebpB38RWNmsYQ,452
5
6
  soialib/module_initializer.py,sha256=Riq6B6cS9HUG1W8tyaa0GkiG3F4fGX70bKU0UOCnrRw,4205
6
7
  soialib/never.py,sha256=bYU63XyNX4e2wOUXQHhHWGO-an4IFr9_ur1ut6GmGN0,47
7
8
  soialib/serializer.py,sha256=jSDanuJ4TEPWEO0ssYSKy2CDLUPV0zwCUzNGHk6uFRQ,3122
8
9
  soialib/serializers.py,sha256=vNLNsfuu6dF0ivJF6v7wQj5Yr6uo2kZHXG5tMrYiVTA,2564
10
+ soialib/service_client.py,sha256=DvBu5-w64FKvuu8Ew9v3Ph6FYGTMcfCwz4eEwKRE2Dc,2284
9
11
  soialib/spec.py,sha256=w-eMMUqOchOlCJaXppyAa2JpSBrMo9lrMvqz8VaEX4I,3699
10
12
  soialib/timestamp.py,sha256=lXBNH8mPmzflkNjSKZSBl2XS-ot9N8N92B_zGO2SMtU,4078
11
13
  soialib/impl/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -17,7 +19,7 @@ soialib/impl/primitives.py,sha256=AHMVvs3BWvPfggsdFnY5dwwqAwiNVFYJa_rJ-WjMJfk,74
17
19
  soialib/impl/repr.py,sha256=7WX0bEAVENTjlyZIcbT8TcJylS7IRIyafGCmqaIMxFM,1413
18
20
  soialib/impl/structs.py,sha256=g__J0w6FAteHW2ZF69yuhZGNfm5-XCorBQW_T1r3PCg,25621
19
21
  soialib/impl/type_adapter.py,sha256=e72nBDqOP0uWNY10EtG7qOvRTzujA-LUVA30Ff7eeac,1935
20
- soia_client-1.0.10.dist-info/METADATA,sha256=R762Xlk_IeNnEQaVy2Ib1ZNFJTrt34vnP-loB5sBq0Y,1667
21
- soia_client-1.0.10.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
22
- soia_client-1.0.10.dist-info/top_level.txt,sha256=2vPmAo5G0SrCxYrNdJKJJVdpalYppgjO2mmz2PtsFUI,8
23
- soia_client-1.0.10.dist-info/RECORD,,
22
+ soia_client-1.0.11.dist-info/METADATA,sha256=c0HD3ulDxxyRoi2V-r6tOxlq0oI-hwm16X_ejUExWO0,1667
23
+ soia_client-1.0.11.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
24
+ soia_client-1.0.11.dist-info/top_level.txt,sha256=2vPmAo5G0SrCxYrNdJKJJVdpalYppgjO2mmz2PtsFUI,8
25
+ soia_client-1.0.11.dist-info/RECORD,,
soialib/_.py ADDED
@@ -0,0 +1,3 @@
1
+ from typing import Any, Final
2
+
3
+ _: Final[Any] = None
soialib/__init__.py CHANGED
@@ -6,12 +6,14 @@ from soialib.serializers import (
6
6
  optional_serializer,
7
7
  primitive_serializer,
8
8
  )
9
+ from soialib.service_client import ServiceClient
9
10
  from soialib.timestamp import Timestamp
10
11
 
11
12
  __all__ = [
12
13
  "KeyedItems",
13
14
  "Method",
14
15
  "Serializer",
16
+ "ServiceClient",
15
17
  "Timestamp",
16
18
  "array_serializer",
17
19
  "optional_serializer",
@@ -0,0 +1,70 @@
1
+ import http.client
2
+ from typing import Final, Mapping, TypeVar
3
+ from urllib.parse import urlparse
4
+
5
+ from soialib import Method
6
+
7
+ Request = TypeVar("Request")
8
+ Response = TypeVar("Response")
9
+
10
+
11
+ class ServiceClient:
12
+ _scheme: Final[str]
13
+ _host: Final[str] # May include the port
14
+ _path: Final[str]
15
+
16
+ def __init__(self, service_url: str, use_https: bool = False):
17
+ parsed_url = urlparse(service_url)
18
+ if parsed_url.query:
19
+ raise ValueError("Service URL must not contain a query string")
20
+ scheme = parsed_url.scheme
21
+ if scheme not in ["http", "https"]:
22
+ raise ValueError("Service URL must start with http:// or https://")
23
+ self._scheme = scheme
24
+ self._host = parsed_url.netloc
25
+ self._path = parsed_url.path
26
+
27
+ def invoke_remote(
28
+ self,
29
+ method: Method[Request, Response],
30
+ request: Request,
31
+ headers: Mapping[str, str] = {},
32
+ ) -> Response:
33
+ request_json = method.request_serializer.to_json_code(request)
34
+ body = ":".join(
35
+ [
36
+ method.name,
37
+ str(method.number),
38
+ "",
39
+ request_json,
40
+ ]
41
+ )
42
+ headers = {
43
+ **headers,
44
+ "Content-Type": "text/plain; charset=utf-8",
45
+ "Content-Length": str(len(body)),
46
+ }
47
+ if self._scheme == "https":
48
+ conn = http.client.HTTPSConnection(self._host)
49
+ else:
50
+ conn = http.client.HTTPConnection(self._host)
51
+ try:
52
+ conn.request(
53
+ "POST",
54
+ self._path,
55
+ body=body,
56
+ headers=headers,
57
+ )
58
+ response = conn.getresponse()
59
+ status_code = response.status
60
+ content_type = response.getheader("Content-Type")
61
+ response_data = response.read().decode("utf-8", errors="ignore")
62
+ finally:
63
+ conn.close()
64
+ if status_code in range(200, 300):
65
+ return method.response_serializer.from_json_code(response_data)
66
+ else:
67
+ message = f"HTTP response status {status_code}"
68
+ if content_type == "text/plain":
69
+ message = f"{message}: {response_data}"
70
+ raise RuntimeError(message)