epostix 1.0.0__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.
- epostix-1.0.0/.codegen.json +31 -0
- epostix-1.0.0/.github/workflows/ci.yml +105 -0
- epostix-1.0.0/.github/workflows/release.yml +85 -0
- epostix-1.0.0/.gitignore +7 -0
- epostix-1.0.0/PKG-INFO +6 -0
- epostix-1.0.0/conftest.py +131 -0
- epostix-1.0.0/epostix/__init__.py +223 -0
- epostix-1.0.0/epostix/_client.py +253 -0
- epostix-1.0.0/epostix/_codec.py +248 -0
- epostix-1.0.0/epostix/_errors.py +335 -0
- epostix-1.0.0/epostix/_generated/__init__.py +19 -0
- epostix-1.0.0/epostix/_generated/codecs.py +1027 -0
- epostix-1.0.0/epostix/_generated/models.py +1268 -0
- epostix-1.0.0/epostix/_generated/operations.py +879 -0
- epostix-1.0.0/epostix/_generated/resources/__init__.py +90 -0
- epostix-1.0.0/epostix/_generated/resources/analytics.py +83 -0
- epostix-1.0.0/epostix/_generated/resources/api_keys.py +231 -0
- epostix-1.0.0/epostix/_generated/resources/attachments.py +15 -0
- epostix-1.0.0/epostix/_generated/resources/broadcasts.py +239 -0
- epostix-1.0.0/epostix/_generated/resources/contacts.py +296 -0
- epostix-1.0.0/epostix/_generated/resources/domains.py +193 -0
- epostix-1.0.0/epostix/_generated/resources/emails.py +346 -0
- epostix-1.0.0/epostix/_generated/resources/events.py +136 -0
- epostix-1.0.0/epostix/_generated/resources/inbound.py +169 -0
- epostix-1.0.0/epostix/_generated/resources/suppressions.py +186 -0
- epostix-1.0.0/epostix/_generated/resources/tags.py +119 -0
- epostix-1.0.0/epostix/_generated/resources/templates.py +202 -0
- epostix-1.0.0/epostix/_generated/resources/templates_versions.py +157 -0
- epostix-1.0.0/epostix/_generated/resources/webhooks.py +236 -0
- epostix-1.0.0/epostix/_generated/resources/webhooks_logs.py +150 -0
- epostix-1.0.0/epostix/_mailbox.py +23 -0
- epostix-1.0.0/epostix/_model.py +24 -0
- epostix-1.0.0/epostix/_pagination.py +293 -0
- epostix-1.0.0/epostix/_response.py +109 -0
- epostix-1.0.0/epostix/_retry.py +193 -0
- epostix-1.0.0/epostix/_transport.py +716 -0
- epostix-1.0.0/epostix/_types.py +20 -0
- epostix-1.0.0/epostix/attachments.py +152 -0
- epostix-1.0.0/epostix/batch.py +119 -0
- epostix-1.0.0/epostix/models.py +291 -0
- epostix-1.0.0/epostix/overrides.py +216 -0
- epostix-1.0.0/epostix/py.typed +0 -0
- epostix-1.0.0/epostix/webhooks.py +322 -0
- epostix-1.0.0/openapi/developer-v1.yaml +5774 -0
- epostix-1.0.0/pyproject.toml +21 -0
- epostix-1.0.0/tests/fixtures/decoding.json +126 -0
- epostix-1.0.0/tests/fixtures/pagination.json +62 -0
- epostix-1.0.0/tests/fixtures/serialization.json +389 -0
- epostix-1.0.0/tests/fixtures/webhook.json +186 -0
- epostix-1.0.0/tests/test_attachments.py +118 -0
- epostix-1.0.0/tests/test_batch.py +138 -0
- epostix-1.0.0/tests/test_decoding.py +203 -0
- epostix-1.0.0/tests/test_exports.py +52 -0
- epostix-1.0.0/tests/test_operations.py +123 -0
- epostix-1.0.0/tests/test_overrides.py +213 -0
- epostix-1.0.0/tests/test_pagination.py +209 -0
- epostix-1.0.0/tests/test_parity.py +148 -0
- epostix-1.0.0/tests/test_retry.py +374 -0
- epostix-1.0.0/tests/test_serialization.py +168 -0
- epostix-1.0.0/tests/test_transport.py +285 -0
- epostix-1.0.0/tests/test_webhook.py +182 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"generator": "epostix-codegen",
|
|
3
|
+
"spec": {
|
|
4
|
+
"raw_sha256": "bb71a54ab7ec8025ecc7f833f8a9c260ee0a9040fcfb39608c5cde1ba952c6f2",
|
|
5
|
+
"contract_sha256": "8f5de3df7a3ac063c6f0110ffc007cea51db26cb9f2826b0d72e6e27d235b4f3"
|
|
6
|
+
},
|
|
7
|
+
"ir_sha256": "182bab5a6f40f8c424518090112332f014d04098e0969687b0f3321738d93b07",
|
|
8
|
+
"files": {
|
|
9
|
+
"epostix/_generated/models.py": "ad1cb5fed77e365c193fe31f9d17bb7b84dab9700a3824b6f5955251be01a0fe",
|
|
10
|
+
"epostix/models.py": "2f647a6f861262349357aa6bab61e9403af76c9fde9d6e68f5c5c9e25ae4fab2",
|
|
11
|
+
"epostix/_generated/codecs.py": "94d7e413d040b0592efe1cd3baf97698d0bec68ac5307dc135f0da4e09a19ad0",
|
|
12
|
+
"epostix/_generated/operations.py": "547b7896baea9dafd21f6ce4e7794f07e7e0cb8e93833a168f463245356ea963",
|
|
13
|
+
"epostix/_generated/resources/analytics.py": "3bb7c5464b1f8dbc83eaa408db8b2da660599545a9b0b88cc6e327ef44e910e1",
|
|
14
|
+
"epostix/_generated/resources/api_keys.py": "514a460940e59e8bc91af1554e08c9cc9c827b40630e5014c302969f3183dfba",
|
|
15
|
+
"epostix/_generated/resources/attachments.py": "e87758a7f2957a7093f173d6d701a692e7915117ed029fd2276a7bd7815f7ae8",
|
|
16
|
+
"epostix/_generated/resources/broadcasts.py": "e756cfb53034d502cc767f167ee5c872816231ba86a4901ac992a8bc408b4534",
|
|
17
|
+
"epostix/_generated/resources/contacts.py": "757ed6ca3e5140954b675d324c8d4f8c1ca9d592205cae2b62ab1ab5af22b9e2",
|
|
18
|
+
"epostix/_generated/resources/domains.py": "eb961f7a3c46c9ac6f0a2a81ec38163ddb24816344083aa1cb6697fed33011bf",
|
|
19
|
+
"epostix/_generated/resources/emails.py": "1a9dfe9c838d6eb31dc5f505b14c9a4f5fbdba128a4c476688cd597944dea330",
|
|
20
|
+
"epostix/_generated/resources/events.py": "0fc1e45b2c6ed11e846d9e6413cd4184e7852a2299b1460717e62536c9738a14",
|
|
21
|
+
"epostix/_generated/resources/inbound.py": "75e8a5b18195051d60cea5fd972c48a5580921c7b3511d2c90e25f048df09b83",
|
|
22
|
+
"epostix/_generated/resources/suppressions.py": "38d60c29befe9259ad5bb160f6959e2140ac696b31d6e58b1d132372c9672dc7",
|
|
23
|
+
"epostix/_generated/resources/tags.py": "9fd18587e35a1b09949808210bb91812c859b9e28e7f7cc5794adadcec29ca4d",
|
|
24
|
+
"epostix/_generated/resources/templates.py": "47d6e3be9377ae9f42dcacdcc414895588d9b2c502a99be2cf878fed5efa72d0",
|
|
25
|
+
"epostix/_generated/resources/templates_versions.py": "a9ccd5054204147eb35cb0fb107fd038cdc2658afc80ce725efe0ca3ed6dcca1",
|
|
26
|
+
"epostix/_generated/resources/webhooks.py": "4a44e89fceaf0e7687c214815b3939d532be835c955a92001945b259081b9d28",
|
|
27
|
+
"epostix/_generated/resources/webhooks_logs.py": "bd09bf857b311d080cdf09533a85b098512d09681c3401f96c89ff9b285f8d84",
|
|
28
|
+
"epostix/_generated/resources/__init__.py": "8242f142db2e5367c72f73f140e25b5c2eff97ac7af2c54c97d594c2232d68f4",
|
|
29
|
+
"epostix/_generated/__init__.py": "64747d64d6dc44e816b417cd4dd4f9d50643c3ef1f2931d6dc1fa2d6396e87ef"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: ["**"]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
contract:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v5
|
|
20
|
+
- name: the vendored spec must match the codegen manifest
|
|
21
|
+
run: |
|
|
22
|
+
expected=$(python3 -c "import json;print(json.load(open('.codegen.json'))['spec']['raw_sha256'])")
|
|
23
|
+
actual=$(sha256sum openapi/developer-v1.yaml | cut -d' ' -f1)
|
|
24
|
+
if [ "$expected" != "$actual" ]; then
|
|
25
|
+
echo "the vendored spec does not match .codegen.json"
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
- name: generated files must not be hand-edited
|
|
29
|
+
run: |
|
|
30
|
+
python3 - <<'PY'
|
|
31
|
+
import hashlib, json, sys
|
|
32
|
+
manifest = json.load(open('.codegen.json'))
|
|
33
|
+
failures = 0
|
|
34
|
+
for path, expected in manifest['files'].items():
|
|
35
|
+
try:
|
|
36
|
+
actual = hashlib.sha256(open(path, 'rb').read()).hexdigest()
|
|
37
|
+
except FileNotFoundError:
|
|
38
|
+
print(f'missing generated file: {path}')
|
|
39
|
+
failures += 1
|
|
40
|
+
continue
|
|
41
|
+
if actual != expected:
|
|
42
|
+
print(f'generated file was edited by hand: {path}')
|
|
43
|
+
failures += 1
|
|
44
|
+
if failures:
|
|
45
|
+
sys.exit(1)
|
|
46
|
+
print(f"contract ok: {len(manifest['files'])} generated files")
|
|
47
|
+
PY
|
|
48
|
+
|
|
49
|
+
test:
|
|
50
|
+
needs: contract
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
strategy:
|
|
53
|
+
fail-fast: false
|
|
54
|
+
matrix:
|
|
55
|
+
python: ["3.11", "3.12", "3.13", "3.14"]
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v5
|
|
58
|
+
- uses: actions/setup-python@v6
|
|
59
|
+
with:
|
|
60
|
+
python-version: ${{ matrix.python }}
|
|
61
|
+
- run: pip install httpx pytest pytest-asyncio mypy
|
|
62
|
+
- run: python -m pytest -q
|
|
63
|
+
- run: python -m mypy --strict epostix
|
|
64
|
+
|
|
65
|
+
prerelease:
|
|
66
|
+
needs: contract
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
continue-on-error: true
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v5
|
|
71
|
+
- uses: actions/setup-python@v6
|
|
72
|
+
with:
|
|
73
|
+
python-version: "3.15"
|
|
74
|
+
allow-prereleases: true
|
|
75
|
+
- run: pip install httpx pytest pytest-asyncio
|
|
76
|
+
- run: python -m pytest -q
|
|
77
|
+
|
|
78
|
+
package:
|
|
79
|
+
needs: test
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v5
|
|
83
|
+
- uses: actions/setup-python@v6
|
|
84
|
+
with:
|
|
85
|
+
python-version: "3.13"
|
|
86
|
+
- run: pip install build
|
|
87
|
+
- run: python -m build
|
|
88
|
+
- name: install the built wheel into a clean environment
|
|
89
|
+
run: |
|
|
90
|
+
python -m venv /tmp/smoke
|
|
91
|
+
/tmp/smoke/bin/pip install --quiet dist/*.whl
|
|
92
|
+
/tmp/smoke/bin/python -c "
|
|
93
|
+
import epostix
|
|
94
|
+
client = epostix.Epostix(api_key='tix_test_smoke')
|
|
95
|
+
assert callable(client.emails.send_email)
|
|
96
|
+
assert callable(client.templates.versions.list_template_versions)
|
|
97
|
+
assert callable(client.attachments.upload_attachment)
|
|
98
|
+
from epostix.webhooks import EpostixWebhookVerifier
|
|
99
|
+
assert EpostixWebhookVerifier is not None
|
|
100
|
+
print('install smoke ok')
|
|
101
|
+
"
|
|
102
|
+
- uses: actions/upload-artifact@v4
|
|
103
|
+
with:
|
|
104
|
+
name: distributions
|
|
105
|
+
path: dist/
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
verify:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v5
|
|
15
|
+
with:
|
|
16
|
+
ref: ${{ github.event.release.tag_name }}
|
|
17
|
+
- uses: actions/setup-python@v6
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.13"
|
|
20
|
+
- run: pip install httpx pytest pytest-asyncio mypy
|
|
21
|
+
- run: python -m pytest -q
|
|
22
|
+
- run: python -m mypy --strict epostix
|
|
23
|
+
- name: the tag must match the project version
|
|
24
|
+
run: |
|
|
25
|
+
version=$(python3 -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
26
|
+
tag="${{ github.event.release.tag_name }}"
|
|
27
|
+
if [ "v$version" != "$tag" ]; then
|
|
28
|
+
echo "pyproject.toml is $version but the tag is $tag"
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
- name: the tag must be a signed annotated tag
|
|
32
|
+
env:
|
|
33
|
+
GH_TOKEN: ${{ github.token }}
|
|
34
|
+
run: |
|
|
35
|
+
tag="${{ github.event.release.tag_name }}"
|
|
36
|
+
ref=$(gh api "repos/${{ github.repository }}/git/ref/tags/$tag")
|
|
37
|
+
kind=$(echo "$ref" | jq -r .object.type)
|
|
38
|
+
sha=$(echo "$ref" | jq -r .object.sha)
|
|
39
|
+
|
|
40
|
+
if [ "$kind" != "tag" ]; then
|
|
41
|
+
echo "$tag is a lightweight tag; a release must use a signed annotated tag"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
object=$(gh api "repos/${{ github.repository }}/git/tags/$sha")
|
|
46
|
+
verified=$(echo "$object" | jq -r .verification.verified)
|
|
47
|
+
reason=$(echo "$object" | jq -r .verification.reason)
|
|
48
|
+
|
|
49
|
+
if [ "$verified" != "true" ]; then
|
|
50
|
+
echo "$tag is not a verified signed tag: $reason"
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
echo "$tag is signed and verified by GitHub ($reason)"
|
|
55
|
+
|
|
56
|
+
build:
|
|
57
|
+
needs: verify
|
|
58
|
+
runs-on: ubuntu-latest
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v5
|
|
61
|
+
with:
|
|
62
|
+
ref: ${{ github.event.release.tag_name }}
|
|
63
|
+
- uses: actions/setup-python@v6
|
|
64
|
+
with:
|
|
65
|
+
python-version: "3.13"
|
|
66
|
+
- run: pip install build
|
|
67
|
+
- run: python -m build
|
|
68
|
+
- uses: actions/upload-artifact@v4
|
|
69
|
+
with:
|
|
70
|
+
name: distributions
|
|
71
|
+
path: dist/
|
|
72
|
+
|
|
73
|
+
publish:
|
|
74
|
+
needs: build
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
environment: pypi
|
|
77
|
+
permissions:
|
|
78
|
+
contents: read
|
|
79
|
+
id-token: write
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/download-artifact@v5
|
|
82
|
+
with:
|
|
83
|
+
name: distributions
|
|
84
|
+
path: dist/
|
|
85
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
epostix-1.0.0/.gitignore
ADDED
epostix-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any, Callable, Iterator, Sequence, cast
|
|
8
|
+
|
|
9
|
+
import httpx
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from epostix import AsyncEpostix, Epostix
|
|
13
|
+
from epostix._codec import Codec
|
|
14
|
+
from epostix._generated import codecs
|
|
15
|
+
from epostix._retry import DISABLED_RETRY_POLICY, RetryPolicy
|
|
16
|
+
|
|
17
|
+
FIXTURES = Path(__file__).parent / "tests" / "fixtures"
|
|
18
|
+
|
|
19
|
+
BASE_URL = "https://api.epostix.test/v1"
|
|
20
|
+
API_KEY = "tix_test_abcdef"
|
|
21
|
+
|
|
22
|
+
def load_fixture(name: str) -> Any:
|
|
23
|
+
return json.loads((FIXTURES / f"{name}.json").read_text())
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def screaming(name: str) -> str:
|
|
27
|
+
name = re.sub(r"([a-z0-9])([A-Z])", r"\1_\2", name)
|
|
28
|
+
name = re.sub(r"([A-Z]+)([A-Z][a-z])", r"\1_\2", name)
|
|
29
|
+
|
|
30
|
+
return name.upper()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def codec_for(type_name: str) -> Codec:
|
|
34
|
+
codec = getattr(codecs, "CODEC_" + screaming(type_name), None)
|
|
35
|
+
|
|
36
|
+
if codec is None:
|
|
37
|
+
raise AssertionError(f"no codec for fixture type {type_name}")
|
|
38
|
+
|
|
39
|
+
return cast(Codec, codec)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class Reply:
|
|
44
|
+
status: int = 200
|
|
45
|
+
body: Any = None
|
|
46
|
+
text: str | None = None
|
|
47
|
+
headers: dict[str, str] = field(default_factory=dict)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class Recorder:
|
|
52
|
+
replies: list[Reply]
|
|
53
|
+
requests: list[httpx.Request] = field(default_factory=list)
|
|
54
|
+
|
|
55
|
+
def __call__(self, request: httpx.Request) -> httpx.Response:
|
|
56
|
+
index = min(len(self.requests), len(self.replies) - 1)
|
|
57
|
+
self.requests.append(request)
|
|
58
|
+
reply = self.replies[index]
|
|
59
|
+
|
|
60
|
+
if reply.text is not None:
|
|
61
|
+
return httpx.Response(reply.status, text=reply.text, headers=reply.headers)
|
|
62
|
+
|
|
63
|
+
return httpx.Response(reply.status, json=reply.body, headers=reply.headers)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def count(self) -> int:
|
|
67
|
+
return len(self.requests)
|
|
68
|
+
|
|
69
|
+
def query_of(self, index: int) -> dict[str, list[str]]:
|
|
70
|
+
params = self.requests[index].url.params
|
|
71
|
+
|
|
72
|
+
return {key: params.get_list(key) for key in params.keys()}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass
|
|
76
|
+
class Clients:
|
|
77
|
+
_closers: list[Callable[[], None]] = field(default_factory=list)
|
|
78
|
+
|
|
79
|
+
def sync(
|
|
80
|
+
self,
|
|
81
|
+
recorder: Recorder,
|
|
82
|
+
*,
|
|
83
|
+
retry_policy: RetryPolicy = DISABLED_RETRY_POLICY,
|
|
84
|
+
automatic_idempotency_keys: bool = True,
|
|
85
|
+
) -> Epostix:
|
|
86
|
+
http = httpx.Client(transport=httpx.MockTransport(recorder))
|
|
87
|
+
self._closers.append(http.close)
|
|
88
|
+
|
|
89
|
+
return Epostix(
|
|
90
|
+
API_KEY,
|
|
91
|
+
base_url=BASE_URL,
|
|
92
|
+
http_client=http,
|
|
93
|
+
retry_policy=retry_policy,
|
|
94
|
+
automatic_idempotency_keys=automatic_idempotency_keys,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def asynchronous(
|
|
98
|
+
self,
|
|
99
|
+
recorder: Recorder,
|
|
100
|
+
*,
|
|
101
|
+
retry_policy: RetryPolicy = DISABLED_RETRY_POLICY,
|
|
102
|
+
automatic_idempotency_keys: bool = True,
|
|
103
|
+
) -> AsyncEpostix:
|
|
104
|
+
http = httpx.AsyncClient(transport=httpx.MockTransport(recorder))
|
|
105
|
+
|
|
106
|
+
return AsyncEpostix(
|
|
107
|
+
API_KEY,
|
|
108
|
+
base_url=BASE_URL,
|
|
109
|
+
http_client=http,
|
|
110
|
+
retry_policy=retry_policy,
|
|
111
|
+
automatic_idempotency_keys=automatic_idempotency_keys,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def close(self) -> None:
|
|
115
|
+
for closer in self._closers:
|
|
116
|
+
closer()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@pytest.fixture
|
|
120
|
+
def clients() -> Iterator[Clients]:
|
|
121
|
+
built = Clients()
|
|
122
|
+
yield built
|
|
123
|
+
built.close()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def replies(*items: Reply) -> list[Reply]:
|
|
127
|
+
return list(items)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def pages(bodies: Sequence[Any]) -> list[Reply]:
|
|
131
|
+
return [Reply(status=200, body=body) for body in bodies]
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from . import attachments as attachments
|
|
4
|
+
from . import batch as batch
|
|
5
|
+
from . import models as models
|
|
6
|
+
from . import overrides as overrides
|
|
7
|
+
from . import webhooks as webhooks
|
|
8
|
+
from ._client import (
|
|
9
|
+
DEDUPLICATION_SCOPE as DEDUPLICATION_SCOPE,
|
|
10
|
+
)
|
|
11
|
+
from ._client import (
|
|
12
|
+
PRODUCTION_BASE_URL as PRODUCTION_BASE_URL,
|
|
13
|
+
)
|
|
14
|
+
from ._client import (
|
|
15
|
+
SANDBOX_DOMAIN as SANDBOX_DOMAIN,
|
|
16
|
+
)
|
|
17
|
+
from ._client import (
|
|
18
|
+
STAGING_BASE_URL as STAGING_BASE_URL,
|
|
19
|
+
)
|
|
20
|
+
from ._client import (
|
|
21
|
+
AsyncEpostix as AsyncEpostix,
|
|
22
|
+
)
|
|
23
|
+
from ._client import (
|
|
24
|
+
Epostix as Epostix,
|
|
25
|
+
)
|
|
26
|
+
from ._client import (
|
|
27
|
+
KeyEnvironment as KeyEnvironment,
|
|
28
|
+
)
|
|
29
|
+
from ._client import (
|
|
30
|
+
key_environment_of as key_environment_of,
|
|
31
|
+
)
|
|
32
|
+
from ._codec import (
|
|
33
|
+
EpostixDecodeError as EpostixDecodeError,
|
|
34
|
+
)
|
|
35
|
+
from ._codec import (
|
|
36
|
+
is_known_enum_value as is_known_enum_value,
|
|
37
|
+
)
|
|
38
|
+
from ._errors import (
|
|
39
|
+
EpostixAccountSuspendedError as EpostixAccountSuspendedError,
|
|
40
|
+
)
|
|
41
|
+
from ._errors import (
|
|
42
|
+
EpostixAPIError as EpostixAPIError,
|
|
43
|
+
)
|
|
44
|
+
from ._errors import (
|
|
45
|
+
EpostixAuthenticationError as EpostixAuthenticationError,
|
|
46
|
+
)
|
|
47
|
+
from ._errors import (
|
|
48
|
+
EpostixConfigurationError as EpostixConfigurationError,
|
|
49
|
+
)
|
|
50
|
+
from ._errors import (
|
|
51
|
+
EpostixConflictError as EpostixConflictError,
|
|
52
|
+
)
|
|
53
|
+
from ._errors import (
|
|
54
|
+
EpostixContentError as EpostixContentError,
|
|
55
|
+
)
|
|
56
|
+
from ._errors import (
|
|
57
|
+
EpostixError as EpostixError,
|
|
58
|
+
)
|
|
59
|
+
from ._errors import (
|
|
60
|
+
EpostixErrorType as EpostixErrorType,
|
|
61
|
+
)
|
|
62
|
+
from ._errors import (
|
|
63
|
+
EpostixIdempotencyConflictError as EpostixIdempotencyConflictError,
|
|
64
|
+
)
|
|
65
|
+
from ._errors import (
|
|
66
|
+
EpostixIdempotencyInProgressError as EpostixIdempotencyInProgressError,
|
|
67
|
+
)
|
|
68
|
+
from ._errors import (
|
|
69
|
+
EpostixInvalidRequestError as EpostixInvalidRequestError,
|
|
70
|
+
)
|
|
71
|
+
from ._errors import (
|
|
72
|
+
EpostixNotFoundError as EpostixNotFoundError,
|
|
73
|
+
)
|
|
74
|
+
from ._errors import (
|
|
75
|
+
EpostixOutcomeUnknownError as EpostixOutcomeUnknownError,
|
|
76
|
+
)
|
|
77
|
+
from ._errors import (
|
|
78
|
+
EpostixPaginationError as EpostixPaginationError,
|
|
79
|
+
)
|
|
80
|
+
from ._errors import (
|
|
81
|
+
EpostixPermissionError as EpostixPermissionError,
|
|
82
|
+
)
|
|
83
|
+
from ._errors import (
|
|
84
|
+
EpostixQuotaExceededError as EpostixQuotaExceededError,
|
|
85
|
+
)
|
|
86
|
+
from ._errors import (
|
|
87
|
+
EpostixRateLimitError as EpostixRateLimitError,
|
|
88
|
+
)
|
|
89
|
+
from ._errors import (
|
|
90
|
+
EpostixServerError as EpostixServerError,
|
|
91
|
+
)
|
|
92
|
+
from ._errors import (
|
|
93
|
+
EpostixTimeoutError as EpostixTimeoutError,
|
|
94
|
+
)
|
|
95
|
+
from ._errors import (
|
|
96
|
+
EpostixTransportError as EpostixTransportError,
|
|
97
|
+
)
|
|
98
|
+
from ._errors import (
|
|
99
|
+
EpostixValidationError as EpostixValidationError,
|
|
100
|
+
)
|
|
101
|
+
from ._errors import (
|
|
102
|
+
EpostixWebhookVerificationError as EpostixWebhookVerificationError,
|
|
103
|
+
)
|
|
104
|
+
from ._errors import (
|
|
105
|
+
FieldError as FieldError,
|
|
106
|
+
)
|
|
107
|
+
from ._errors import (
|
|
108
|
+
PaginationFailureReason as PaginationFailureReason,
|
|
109
|
+
)
|
|
110
|
+
from ._errors import (
|
|
111
|
+
QuotaPeriod as QuotaPeriod,
|
|
112
|
+
)
|
|
113
|
+
from ._errors import (
|
|
114
|
+
TimeoutPhase as TimeoutPhase,
|
|
115
|
+
)
|
|
116
|
+
from ._errors import (
|
|
117
|
+
WebhookFailureReason as WebhookFailureReason,
|
|
118
|
+
)
|
|
119
|
+
from ._mailbox import (
|
|
120
|
+
Mailbox as Mailbox,
|
|
121
|
+
)
|
|
122
|
+
from ._mailbox import (
|
|
123
|
+
addr as addr,
|
|
124
|
+
)
|
|
125
|
+
from ._mailbox import (
|
|
126
|
+
named as named,
|
|
127
|
+
)
|
|
128
|
+
from ._model import (
|
|
129
|
+
Model as Model,
|
|
130
|
+
)
|
|
131
|
+
from ._model import (
|
|
132
|
+
response_metadata_of as response_metadata_of,
|
|
133
|
+
)
|
|
134
|
+
from ._model import (
|
|
135
|
+
unknown_fields_of as unknown_fields_of,
|
|
136
|
+
)
|
|
137
|
+
from ._pagination import (
|
|
138
|
+
AsyncPaginator as AsyncPaginator,
|
|
139
|
+
)
|
|
140
|
+
from ._pagination import (
|
|
141
|
+
Collection as Collection,
|
|
142
|
+
)
|
|
143
|
+
from ._pagination import (
|
|
144
|
+
Page as Page,
|
|
145
|
+
)
|
|
146
|
+
from ._pagination import (
|
|
147
|
+
Paginator as Paginator,
|
|
148
|
+
)
|
|
149
|
+
from ._response import (
|
|
150
|
+
AttemptRecord as AttemptRecord,
|
|
151
|
+
)
|
|
152
|
+
from ._response import (
|
|
153
|
+
RateLimitSnapshot as RateLimitSnapshot,
|
|
154
|
+
)
|
|
155
|
+
from ._response import (
|
|
156
|
+
ResponseMetadata as ResponseMetadata,
|
|
157
|
+
)
|
|
158
|
+
from ._response import (
|
|
159
|
+
RetriesExhaustedReason as RetriesExhaustedReason,
|
|
160
|
+
)
|
|
161
|
+
from ._retry import (
|
|
162
|
+
BATCH_RETRY_POLICY as BATCH_RETRY_POLICY,
|
|
163
|
+
)
|
|
164
|
+
from ._retry import (
|
|
165
|
+
DEFAULT_RETRY_POLICY as DEFAULT_RETRY_POLICY,
|
|
166
|
+
)
|
|
167
|
+
from ._retry import (
|
|
168
|
+
DISABLED_RETRY_POLICY as DISABLED_RETRY_POLICY,
|
|
169
|
+
)
|
|
170
|
+
from ._retry import (
|
|
171
|
+
UPLOAD_RETRY_POLICY as UPLOAD_RETRY_POLICY,
|
|
172
|
+
)
|
|
173
|
+
from ._retry import (
|
|
174
|
+
MutationRetryMode as MutationRetryMode,
|
|
175
|
+
)
|
|
176
|
+
from ._retry import (
|
|
177
|
+
RetryClass as RetryClass,
|
|
178
|
+
)
|
|
179
|
+
from ._retry import (
|
|
180
|
+
RetryPolicy as RetryPolicy,
|
|
181
|
+
)
|
|
182
|
+
from ._transport import (
|
|
183
|
+
IDEMPOTENCY_KEY_MAXIMUM_LENGTH as IDEMPOTENCY_KEY_MAXIMUM_LENGTH,
|
|
184
|
+
)
|
|
185
|
+
from ._transport import (
|
|
186
|
+
IDEMPOTENCY_RETENTION_HOURS as IDEMPOTENCY_RETENTION_HOURS,
|
|
187
|
+
)
|
|
188
|
+
from ._transport import (
|
|
189
|
+
OperationSpec as OperationSpec,
|
|
190
|
+
)
|
|
191
|
+
from ._transport import (
|
|
192
|
+
RequestOptions as RequestOptions,
|
|
193
|
+
)
|
|
194
|
+
from .attachments import (
|
|
195
|
+
ATTACHMENT_DECODED_LIMIT_BYTES as ATTACHMENT_DECODED_LIMIT_BYTES,
|
|
196
|
+
)
|
|
197
|
+
from .attachments import (
|
|
198
|
+
REQUEST_BODY_LIMIT_BYTES as REQUEST_BODY_LIMIT_BYTES,
|
|
199
|
+
)
|
|
200
|
+
from .attachments import (
|
|
201
|
+
EpostixAttachmentTooLargeError as EpostixAttachmentTooLargeError,
|
|
202
|
+
)
|
|
203
|
+
from .attachments import (
|
|
204
|
+
EpostixRequestTooLargeError as EpostixRequestTooLargeError,
|
|
205
|
+
)
|
|
206
|
+
from ._types import (
|
|
207
|
+
NOT_GIVEN as NOT_GIVEN,
|
|
208
|
+
)
|
|
209
|
+
from ._types import (
|
|
210
|
+
JsonValue as JsonValue,
|
|
211
|
+
)
|
|
212
|
+
from ._types import (
|
|
213
|
+
NotGiven as NotGiven,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
from .overrides import (
|
|
217
|
+
AsyncRawContent as AsyncRawContent,
|
|
218
|
+
)
|
|
219
|
+
from .overrides import (
|
|
220
|
+
RawContent as RawContent,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
__version__ = "1.0.0"
|