webex-message-handler 0.6.10__tar.gz → 0.6.12__tar.gz
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.
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/PKG-INFO +4 -5
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/pyproject.toml +4 -5
- webex_message_handler-0.6.12/tests/conftest.py +89 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/tests/test_device_manager.py +67 -75
- webex_message_handler-0.6.10/tests/conftest.py +0 -40
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/.gitignore +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/API.md +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/LICENSE +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/README.md +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/examples/basic_bot.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/__init__.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/device_manager.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/errors.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/handler.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/id_utils.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/kms_client.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/logger.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/mention_parser.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/mercury_socket.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/message_decryptor.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/types.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/url_validation.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/test-proxy.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/tests/__init__.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/tests/test_handler.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/tests/test_id_utils.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/tests/test_integration.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/tests/test_kms_client.py +0 -0
- {webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/tests/test_message_decryptor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: webex-message-handler
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.12
|
|
4
4
|
Summary: Lightweight Webex Mercury WebSocket + KMS decryption for receiving bot messages without the full Webex SDK
|
|
5
5
|
Project-URL: Homepage, https://github.com/3rg0n/webex-message-handler
|
|
6
6
|
Project-URL: Repository, https://github.com/3rg0n/webex-message-handler
|
|
@@ -19,11 +19,10 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
20
|
Classifier: Topic :: Communications :: Chat
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
|
-
Requires-Dist: aiohttp>=3.
|
|
23
|
-
Requires-Dist: cryptography>=
|
|
24
|
-
Requires-Dist: jwcrypto>=1.5
|
|
22
|
+
Requires-Dist: aiohttp>=3.14.1
|
|
23
|
+
Requires-Dist: cryptography>=48.0.1
|
|
24
|
+
Requires-Dist: jwcrypto>=1.5.7
|
|
25
25
|
Provides-Extra: dev
|
|
26
|
-
Requires-Dist: aioresponses>=0.7; extra == 'dev'
|
|
27
26
|
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
28
27
|
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
29
28
|
Requires-Dist: pytest>=7; extra == 'dev'
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "webex-message-handler"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.12"
|
|
8
8
|
description = "Lightweight Webex Mercury WebSocket + KMS decryption for receiving bot messages without the full Webex SDK"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -26,9 +26,9 @@ classifiers = [
|
|
|
26
26
|
"Framework :: AsyncIO",
|
|
27
27
|
]
|
|
28
28
|
dependencies = [
|
|
29
|
-
"aiohttp>=3.
|
|
30
|
-
"cryptography>=
|
|
31
|
-
"jwcrypto>=1.5",
|
|
29
|
+
"aiohttp>=3.14.1",
|
|
30
|
+
"cryptography>=48.0.1",
|
|
31
|
+
"jwcrypto>=1.5.7",
|
|
32
32
|
]
|
|
33
33
|
|
|
34
34
|
[project.urls]
|
|
@@ -57,7 +57,6 @@ strict = true
|
|
|
57
57
|
dev = [
|
|
58
58
|
"pytest>=7",
|
|
59
59
|
"pytest-asyncio>=0.23",
|
|
60
|
-
"aioresponses>=0.7",
|
|
61
60
|
"ruff>=0.4",
|
|
62
61
|
"mypy>=1.10",
|
|
63
62
|
]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Pytest configuration and fixtures."""
|
|
2
|
+
|
|
3
|
+
import json as _json
|
|
4
|
+
|
|
5
|
+
import aiohttp
|
|
6
|
+
|
|
7
|
+
from webex_message_handler.types import FetchRequest, FetchResponse
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class MockHttpResponse:
|
|
11
|
+
"""A canned FetchResponse for the injected http_do adapter."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, status: int = 200, payload=None, *, exc: Exception | None = None):
|
|
14
|
+
self.status = status
|
|
15
|
+
self.ok = 200 <= status < 300
|
|
16
|
+
self._payload = payload
|
|
17
|
+
self._exc = exc
|
|
18
|
+
|
|
19
|
+
async def json(self):
|
|
20
|
+
return self._payload
|
|
21
|
+
|
|
22
|
+
async def text(self):
|
|
23
|
+
return _json.dumps(self._payload) if self._payload is not None else ""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MockHttpDo:
|
|
27
|
+
"""Mocks HTTP at the injected ``http_do`` seam instead of patching aiohttp.
|
|
28
|
+
|
|
29
|
+
Register canned responses keyed by ``(METHOD, url)``; the adapter pops them
|
|
30
|
+
in registration order so repeated calls to the same endpoint can return
|
|
31
|
+
different responses. A registered ``Exception`` is raised to simulate a
|
|
32
|
+
network failure (mirroring the handler's try/except path).
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
def __init__(self):
|
|
36
|
+
self._routes: dict[tuple[str, str], list] = {}
|
|
37
|
+
self.calls: list[FetchRequest] = []
|
|
38
|
+
|
|
39
|
+
def add(self, method: str, url: str, *, status: int = 200, payload=None, exc: Exception | None = None):
|
|
40
|
+
self._routes.setdefault((method.upper(), url), []).append(
|
|
41
|
+
MockHttpResponse(status=status, payload=payload, exc=exc)
|
|
42
|
+
)
|
|
43
|
+
return self
|
|
44
|
+
|
|
45
|
+
async def __call__(self, request: FetchRequest) -> FetchResponse:
|
|
46
|
+
self.calls.append(request)
|
|
47
|
+
key = (request.method.upper(), request.url)
|
|
48
|
+
queue = self._routes.get(key)
|
|
49
|
+
if not queue:
|
|
50
|
+
raise AssertionError(f"unexpected request: {request.method} {request.url}")
|
|
51
|
+
response = queue.pop(0) if len(queue) > 1 else queue[0]
|
|
52
|
+
if response._exc is not None:
|
|
53
|
+
raise response._exc
|
|
54
|
+
return response # type: ignore[return-value]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
async def create_test_http_do(connector: aiohttp.BaseConnector | None = None):
|
|
58
|
+
"""Create a test HTTP adapter for use in tests."""
|
|
59
|
+
async def http_do(request: FetchRequest) -> FetchResponse:
|
|
60
|
+
async with (
|
|
61
|
+
aiohttp.ClientSession(connector=connector) as session,
|
|
62
|
+
session.request(
|
|
63
|
+
request.method,
|
|
64
|
+
request.url,
|
|
65
|
+
headers=request.headers,
|
|
66
|
+
data=request.body,
|
|
67
|
+
) as response,
|
|
68
|
+
):
|
|
69
|
+
# Eagerly read the response body before the context closes
|
|
70
|
+
body_bytes = await response.read()
|
|
71
|
+
status = response.status
|
|
72
|
+
ok = 200 <= status < 300
|
|
73
|
+
|
|
74
|
+
class TestFetchResponse:
|
|
75
|
+
def __init__(self):
|
|
76
|
+
self.status = status
|
|
77
|
+
self.ok = ok
|
|
78
|
+
self._body = body_bytes
|
|
79
|
+
|
|
80
|
+
async def json(self):
|
|
81
|
+
import json
|
|
82
|
+
return json.loads(self._body.decode('utf-8'))
|
|
83
|
+
|
|
84
|
+
async def text(self):
|
|
85
|
+
return self._body.decode('utf-8')
|
|
86
|
+
|
|
87
|
+
return TestFetchResponse() # type: ignore[return-value]
|
|
88
|
+
|
|
89
|
+
return http_do
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"""Tests for DeviceManager."""
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
-
from aioresponses import aioresponses
|
|
5
4
|
|
|
6
|
-
from tests.conftest import
|
|
5
|
+
from tests.conftest import MockHttpDo
|
|
7
6
|
from webex_message_handler.device_manager import WDM_API_BASE, DeviceManager
|
|
8
7
|
from webex_message_handler.errors import AuthError, DeviceRegistrationError
|
|
9
8
|
|
|
@@ -25,11 +24,9 @@ MOCK_WDM_RESPONSE = {
|
|
|
25
24
|
|
|
26
25
|
class TestRegister:
|
|
27
26
|
async def test_successful_registration(self):
|
|
28
|
-
http_do =
|
|
27
|
+
http_do = MockHttpDo().add("POST", WDM_API_BASE, payload=MOCK_WDM_RESPONSE)
|
|
29
28
|
dm = DeviceManager(http_do=http_do)
|
|
30
|
-
|
|
31
|
-
m.post(WDM_API_BASE, payload=MOCK_WDM_RESPONSE)
|
|
32
|
-
result = await dm.register(MOCK_TOKEN)
|
|
29
|
+
result = await dm.register(MOCK_TOKEN)
|
|
33
30
|
|
|
34
31
|
assert result.web_socket_url == MOCK_WS_URL
|
|
35
32
|
assert result.device_url == MOCK_DEVICE_URL
|
|
@@ -38,127 +35,122 @@ class TestRegister:
|
|
|
38
35
|
assert result.services["messenger"] == "https://messenger.example.com"
|
|
39
36
|
|
|
40
37
|
async def test_auth_error_on_401(self):
|
|
41
|
-
http_do =
|
|
38
|
+
http_do = MockHttpDo().add("POST", WDM_API_BASE, status=401)
|
|
42
39
|
dm = DeviceManager(http_do=http_do)
|
|
43
|
-
with
|
|
44
|
-
|
|
45
|
-
with pytest.raises(AuthError):
|
|
46
|
-
await dm.register(MOCK_TOKEN)
|
|
40
|
+
with pytest.raises(AuthError):
|
|
41
|
+
await dm.register(MOCK_TOKEN)
|
|
47
42
|
|
|
48
43
|
async def test_device_registration_error_on_non_2xx(self):
|
|
49
|
-
http_do =
|
|
44
|
+
http_do = MockHttpDo().add("POST", WDM_API_BASE, status=400)
|
|
50
45
|
dm = DeviceManager(http_do=http_do)
|
|
51
|
-
with
|
|
52
|
-
|
|
53
|
-
with pytest.raises(DeviceRegistrationError, match="Failed to register device"):
|
|
54
|
-
await dm.register(MOCK_TOKEN)
|
|
46
|
+
with pytest.raises(DeviceRegistrationError, match="Failed to register device"):
|
|
47
|
+
await dm.register(MOCK_TOKEN)
|
|
55
48
|
|
|
56
49
|
async def test_device_registration_error_on_network_failure(self):
|
|
57
|
-
http_do =
|
|
50
|
+
http_do = MockHttpDo().add("POST", WDM_API_BASE, exc=ConnectionError("Network error"))
|
|
58
51
|
dm = DeviceManager(http_do=http_do)
|
|
59
|
-
with
|
|
60
|
-
|
|
61
|
-
with pytest.raises(DeviceRegistrationError):
|
|
62
|
-
await dm.register(MOCK_TOKEN)
|
|
52
|
+
with pytest.raises(DeviceRegistrationError):
|
|
53
|
+
await dm.register(MOCK_TOKEN)
|
|
63
54
|
|
|
64
55
|
|
|
65
56
|
class TestRefresh:
|
|
66
57
|
async def test_successful_refresh(self):
|
|
67
|
-
|
|
58
|
+
refreshed = {**MOCK_WDM_RESPONSE, "webSocketUrl": "wss://mercury-new.example.com/socket"}
|
|
59
|
+
http_do = (
|
|
60
|
+
MockHttpDo()
|
|
61
|
+
.add("POST", WDM_API_BASE, payload=MOCK_WDM_RESPONSE)
|
|
62
|
+
.add("PUT", MOCK_DEVICE_URL, payload=refreshed)
|
|
63
|
+
)
|
|
68
64
|
dm = DeviceManager(http_do=http_do)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
await dm.register(MOCK_TOKEN)
|
|
72
|
-
|
|
73
|
-
refreshed = {**MOCK_WDM_RESPONSE, "webSocketUrl": "wss://mercury-new.example.com/socket"}
|
|
74
|
-
m.put(MOCK_DEVICE_URL, payload=refreshed)
|
|
75
|
-
result = await dm.refresh(MOCK_TOKEN)
|
|
65
|
+
await dm.register(MOCK_TOKEN)
|
|
66
|
+
result = await dm.refresh(MOCK_TOKEN)
|
|
76
67
|
|
|
77
68
|
assert result.web_socket_url == "wss://mercury-new.example.com/socket"
|
|
78
69
|
|
|
79
70
|
async def test_error_if_not_registered(self):
|
|
80
|
-
http_do =
|
|
71
|
+
http_do = MockHttpDo()
|
|
81
72
|
dm = DeviceManager(http_do=http_do)
|
|
82
73
|
with pytest.raises(DeviceRegistrationError, match="Device not registered"):
|
|
83
74
|
await dm.refresh(MOCK_TOKEN)
|
|
84
75
|
|
|
85
76
|
async def test_auth_error_on_401_during_refresh(self):
|
|
86
|
-
http_do =
|
|
77
|
+
http_do = (
|
|
78
|
+
MockHttpDo()
|
|
79
|
+
.add("POST", WDM_API_BASE, payload=MOCK_WDM_RESPONSE)
|
|
80
|
+
.add("PUT", MOCK_DEVICE_URL, status=401)
|
|
81
|
+
)
|
|
87
82
|
dm = DeviceManager(http_do=http_do)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
await dm.
|
|
91
|
-
m.put(MOCK_DEVICE_URL, status=401)
|
|
92
|
-
with pytest.raises(AuthError):
|
|
93
|
-
await dm.refresh(MOCK_TOKEN)
|
|
83
|
+
await dm.register(MOCK_TOKEN)
|
|
84
|
+
with pytest.raises(AuthError):
|
|
85
|
+
await dm.refresh(MOCK_TOKEN)
|
|
94
86
|
|
|
95
87
|
async def test_device_registration_error_on_refresh_failure(self):
|
|
96
|
-
http_do =
|
|
88
|
+
http_do = (
|
|
89
|
+
MockHttpDo()
|
|
90
|
+
.add("POST", WDM_API_BASE, payload=MOCK_WDM_RESPONSE)
|
|
91
|
+
.add("PUT", MOCK_DEVICE_URL, status=500)
|
|
92
|
+
)
|
|
97
93
|
dm = DeviceManager(http_do=http_do)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
await dm.
|
|
101
|
-
m.put(MOCK_DEVICE_URL, status=500)
|
|
102
|
-
with pytest.raises(DeviceRegistrationError):
|
|
103
|
-
await dm.refresh(MOCK_TOKEN)
|
|
94
|
+
await dm.register(MOCK_TOKEN)
|
|
95
|
+
with pytest.raises(DeviceRegistrationError):
|
|
96
|
+
await dm.refresh(MOCK_TOKEN)
|
|
104
97
|
|
|
105
98
|
|
|
106
99
|
class TestUnregister:
|
|
107
100
|
async def test_successful_unregister(self):
|
|
108
|
-
http_do =
|
|
101
|
+
http_do = (
|
|
102
|
+
MockHttpDo()
|
|
103
|
+
.add("POST", WDM_API_BASE, payload=MOCK_WDM_RESPONSE)
|
|
104
|
+
.add("DELETE", MOCK_DEVICE_URL, status=204)
|
|
105
|
+
)
|
|
109
106
|
dm = DeviceManager(http_do=http_do)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
await dm.register(MOCK_TOKEN)
|
|
113
|
-
m.delete(MOCK_DEVICE_URL, status=204)
|
|
114
|
-
await dm.unregister(MOCK_TOKEN)
|
|
107
|
+
await dm.register(MOCK_TOKEN)
|
|
108
|
+
await dm.unregister(MOCK_TOKEN)
|
|
115
109
|
|
|
116
110
|
async def test_error_if_not_registered(self):
|
|
117
|
-
http_do =
|
|
111
|
+
http_do = MockHttpDo()
|
|
118
112
|
dm = DeviceManager(http_do=http_do)
|
|
119
113
|
with pytest.raises(DeviceRegistrationError, match="Device not registered"):
|
|
120
114
|
await dm.unregister(MOCK_TOKEN)
|
|
121
115
|
|
|
122
116
|
async def test_auth_error_on_401_during_unregister(self):
|
|
123
|
-
http_do =
|
|
117
|
+
http_do = (
|
|
118
|
+
MockHttpDo()
|
|
119
|
+
.add("POST", WDM_API_BASE, payload=MOCK_WDM_RESPONSE)
|
|
120
|
+
.add("DELETE", MOCK_DEVICE_URL, status=401)
|
|
121
|
+
)
|
|
124
122
|
dm = DeviceManager(http_do=http_do)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
await dm.
|
|
128
|
-
m.delete(MOCK_DEVICE_URL, status=401)
|
|
129
|
-
with pytest.raises(AuthError):
|
|
130
|
-
await dm.unregister(MOCK_TOKEN)
|
|
123
|
+
await dm.register(MOCK_TOKEN)
|
|
124
|
+
with pytest.raises(AuthError):
|
|
125
|
+
await dm.unregister(MOCK_TOKEN)
|
|
131
126
|
|
|
132
127
|
async def test_device_registration_error_on_unregister_failure(self):
|
|
133
|
-
http_do =
|
|
128
|
+
http_do = (
|
|
129
|
+
MockHttpDo()
|
|
130
|
+
.add("POST", WDM_API_BASE, payload=MOCK_WDM_RESPONSE)
|
|
131
|
+
.add("DELETE", MOCK_DEVICE_URL, status=500)
|
|
132
|
+
)
|
|
134
133
|
dm = DeviceManager(http_do=http_do)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
await dm.
|
|
138
|
-
m.delete(MOCK_DEVICE_URL, status=500)
|
|
139
|
-
with pytest.raises(DeviceRegistrationError):
|
|
140
|
-
await dm.unregister(MOCK_TOKEN)
|
|
134
|
+
await dm.register(MOCK_TOKEN)
|
|
135
|
+
with pytest.raises(DeviceRegistrationError):
|
|
136
|
+
await dm.unregister(MOCK_TOKEN)
|
|
141
137
|
|
|
142
138
|
|
|
143
139
|
class TestServiceParsing:
|
|
144
140
|
async def test_empty_services(self):
|
|
145
|
-
http_do = await create_test_http_do()
|
|
146
|
-
dm = DeviceManager(http_do=http_do)
|
|
147
141
|
response = {**MOCK_WDM_RESPONSE, "services": {}}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
142
|
+
http_do = MockHttpDo().add("POST", WDM_API_BASE, payload=response)
|
|
143
|
+
dm = DeviceManager(http_do=http_do)
|
|
144
|
+
result = await dm.register(MOCK_TOKEN)
|
|
151
145
|
|
|
152
146
|
assert result.services == {}
|
|
153
147
|
assert result.encryption_service_url == ""
|
|
154
148
|
|
|
155
149
|
async def test_missing_encryption_service_url(self):
|
|
156
|
-
http_do = await create_test_http_do()
|
|
157
|
-
dm = DeviceManager(http_do=http_do)
|
|
158
150
|
response = {**MOCK_WDM_RESPONSE, "services": {"messenger": "https://messenger.example.com"}}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
151
|
+
http_do = MockHttpDo().add("POST", WDM_API_BASE, payload=response)
|
|
152
|
+
dm = DeviceManager(http_do=http_do)
|
|
153
|
+
result = await dm.register(MOCK_TOKEN)
|
|
162
154
|
|
|
163
155
|
assert "messenger" in result.services
|
|
164
156
|
assert result.encryption_service_url == ""
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"""Pytest configuration and fixtures."""
|
|
2
|
-
|
|
3
|
-
import aiohttp
|
|
4
|
-
|
|
5
|
-
from webex_message_handler.types import FetchRequest, FetchResponse
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
async def create_test_http_do(connector: aiohttp.BaseConnector | None = None):
|
|
9
|
-
"""Create a test HTTP adapter for use in tests."""
|
|
10
|
-
async def http_do(request: FetchRequest) -> FetchResponse:
|
|
11
|
-
async with (
|
|
12
|
-
aiohttp.ClientSession(connector=connector) as session,
|
|
13
|
-
session.request(
|
|
14
|
-
request.method,
|
|
15
|
-
request.url,
|
|
16
|
-
headers=request.headers,
|
|
17
|
-
data=request.body,
|
|
18
|
-
) as response,
|
|
19
|
-
):
|
|
20
|
-
# Eagerly read the response body before the context closes
|
|
21
|
-
body_bytes = await response.read()
|
|
22
|
-
status = response.status
|
|
23
|
-
ok = 200 <= status < 300
|
|
24
|
-
|
|
25
|
-
class TestFetchResponse:
|
|
26
|
-
def __init__(self):
|
|
27
|
-
self.status = status
|
|
28
|
-
self.ok = ok
|
|
29
|
-
self._body = body_bytes
|
|
30
|
-
|
|
31
|
-
async def json(self):
|
|
32
|
-
import json
|
|
33
|
-
return json.loads(self._body.decode('utf-8'))
|
|
34
|
-
|
|
35
|
-
async def text(self):
|
|
36
|
-
return self._body.decode('utf-8')
|
|
37
|
-
|
|
38
|
-
return TestFetchResponse() # type: ignore[return-value]
|
|
39
|
-
|
|
40
|
-
return http_do
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/errors.py
RENAMED
|
File without changes
|
{webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/handler.py
RENAMED
|
File without changes
|
{webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/id_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
{webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/logger.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/src/webex_message_handler/types.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{webex_message_handler-0.6.10 → webex_message_handler-0.6.12}/tests/test_message_decryptor.py
RENAMED
|
File without changes
|