manza 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.
manza-1.0.0/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+ .venv/
9
+ venv/
10
+ dist/
11
+ build/
12
+ .coverage
13
+ htmlcov/
14
+ .env
15
+ tests/fixtures/cassettes/
16
+ cassettes-v*.tar.gz
17
+ .tox/
18
+ .python-version.local
@@ -0,0 +1,84 @@
1
+ # Changelog
2
+
3
+ All notable changes to `manza` (formerly `zazu-sdk`) are documented here.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - `ManzaConflictError` (409), the 10th error class. A duplicate
13
+ `client_reference` on a transfer draft raises it with `payment_id`
14
+ naming the existing draft. 400 now maps to `ManzaValidationError`
15
+ (lists return 400 for a malformed `limit`/`cursor`).
16
+ - `TransferDrafts.authorize(id, authorization_id, signature)` and
17
+ `decline(id, authorization_id, reason=None)` for machine-authorized
18
+ transfers. A blank signature raises `ManzaArgumentError` locally, because
19
+ the API would count it as a failed attempt.
20
+ - `TransferDrafts.create` documents the new optional `client_reference`;
21
+ responses carry `client_reference` and `authorization`.
22
+ - `manza.transfer_authorization` with `signature_input`, `sign` and
23
+ `payee_for`, the HMAC-SHA256 signer for authorization challenges, tested
24
+ with the fixed vector shared across SDKs.
25
+ - `Beneficiaries.create`, `list_external_accounts`, `get_external_account`
26
+ and `create_external_account`.
27
+ - `PayeeTrustRequests` (`client.payee_trust_requests`) with
28
+ `create(external_account_ids)` and `get(id)`.
29
+ - Docs for new pass-through fields: checkout session `customer_name`,
30
+ `collect_billing_address`, `billing_address`, `settled_at`, `transaction`
31
+ and the `clearing` status; payment link billing fields; customer
32
+ `registration_number` / `vat_number` (and MA-only `tax_id` / `ice_number`).
33
+
34
+ ### Changed
35
+
36
+ - **Renamed from `zazu-sdk` to `manza`** (1.0.0 under the new name; see the
37
+ migration guide below). The package, import, classes, User-Agent and
38
+ environment variables all move from Zazu to Manza.
39
+ - The version header is now `Manza-Version` (the API accepts both).
40
+ - User-Agent is `manza-python/<version>` (was `zazu-sdk/<version>`).
41
+ - Cassettes are fetched from `getmanza/manza-ruby`, pinned to `v1.0.0`.
42
+ - The replay placeholders are `<MANZA_API_KEY>` / `<MANZA_VERSION>` and the
43
+ fixture variables are `MANZA_FIXTURE_*` (no fallback, dev-only).
44
+ - Default base URL is now `https://ma.manza.finance` (Morocco production;
45
+ South Africa is `https://za.manza.finance`). Cassettes are recorded against
46
+ `https://ma.manza.dev`.
47
+ - Request bodies are serialized compactly (no spaces after `,` and `:`), the
48
+ same bytes the Ruby SDK sends.
49
+ - Replay harness: one cassette per test, with optional exact and
50
+ signature-less body matching for the new cassettes.
51
+
52
+ ### Deprecated
53
+
54
+ - `ZAZU_API_KEY`, `ZAZU_BASE_URL`, `ZAZU_API_VERSION` and `ZAZU_TIMEOUT` still
55
+ work for all of 1.x. `MANZA_*` wins when both are set; the legacy name emits
56
+ one `FutureWarning` per variable per process.
57
+
58
+ ### Migrating from `zazu-sdk` 0.x
59
+
60
+ | Before | After |
61
+ |---|---|
62
+ | `pip install zazu-sdk` | `pip install manza` |
63
+ | `from zazu_sdk import Zazu` | `from manza import Manza` |
64
+ | `ZazuError`, `ZazuValidationError`, ... (every `Zazu*` class) | `ManzaError`, `ManzaValidationError`, ... |
65
+ | `zazu_sdk.transfer_authorization` | `manza.transfer_authorization` |
66
+ | `ZAZU_API_KEY` / `ZAZU_BASE_URL` / `ZAZU_API_VERSION` / `ZAZU_TIMEOUT` | `MANZA_API_KEY` / `MANZA_BASE_URL` / `MANZA_API_VERSION` / `MANZA_TIMEOUT` |
67
+ | `Zazu-Version` header | `Manza-Version` |
68
+ | repo `getzazu/zazu-python` | `getmanza/manza-python` |
69
+
70
+ ## [0.2.1]
71
+
72
+ Version alignment: the whole SDK family now releases in lockstep with zazu-ruby. No functional changes since [0.1.0].
73
+
74
+ ## [0.1.0]
75
+
76
+ Initial release.
77
+
78
+ ### Added
79
+
80
+ - Sync `Zazu` client built on `httpx`
81
+ - Resource modules: `accounts`, `beneficiaries`, `checkout_sessions`, `customers`, `entity`, `invoices`, `payment_links`, `transfer_drafts`, `webhook_endpoints`
82
+ - Cursor-based `Page` with `auto_paging_iter()`
83
+ - Nine-class error hierarchy mirroring `zazu-ruby`
84
+ - Cassette-replay test harness driven by the Ruby SDK's release tarball
manza-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Manza
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
manza-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,190 @@
1
+ Metadata-Version: 2.5
2
+ Name: manza
3
+ Version: 1.0.0
4
+ Summary: Python SDK for the Manza API.
5
+ Project-URL: Homepage, https://github.com/getmanza/manza-python
6
+ Project-URL: Documentation, https://github.com/getmanza/manza-python#readme
7
+ Project-URL: Repository, https://github.com/getmanza/manza-python
8
+ Project-URL: Issues, https://github.com/getmanza/manza-python/issues
9
+ Project-URL: Changelog, https://github.com/getmanza/manza-python/blob/main/CHANGELOG.md
10
+ Author-email: Manza <hello@get-manza.com>
11
+ License-Expression: MIT
12
+ License-File: LICENSE
13
+ Keywords: api,fintech,manza,morocco,sdk
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: httpx>=0.27
26
+ Provides-Extra: dev
27
+ Requires-Dist: mypy>=1.11; extra == 'dev'
28
+ Requires-Dist: pytest-vcr>=1.0.2; extra == 'dev'
29
+ Requires-Dist: pytest>=8; extra == 'dev'
30
+ Requires-Dist: ruff>=0.7; extra == 'dev'
31
+ Requires-Dist: vcrpy>=6; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # manza
35
+
36
+ Python SDK for the [Manza API](https://ma.manza.finance).
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install manza
42
+ ```
43
+
44
+ Requires Python 3.11+.
45
+
46
+ ## Quick start
47
+
48
+ ```python
49
+ from manza import Manza
50
+
51
+ client = Manza(api_key="sk_live_...")
52
+
53
+ client.entity.get()
54
+ client.accounts.list(currency_code="MAD")
55
+ client.customers.list(q="Acme")
56
+ client.customers.create(
57
+ customer_type="business",
58
+ company_name="Acme Corp",
59
+ email="billing@acme.com",
60
+ )
61
+
62
+ client.invoices.list()
63
+ client.payment_links.cancel(payment_link_id)
64
+ client.webhook_endpoints.list()
65
+
66
+ client.checkout_sessions.create(
67
+ account_id=account_id,
68
+ amount="100.00",
69
+ success_url="https://example.com/ok",
70
+ cancel_url="https://example.com/cancel",
71
+ )
72
+ client.checkout_sessions.get(session_id)
73
+ ```
74
+
75
+ The client picks up `MANZA_API_KEY`, `MANZA_BASE_URL`, `MANZA_API_VERSION`, and
76
+ `MANZA_TIMEOUT` from the environment if you don't pass them. The old `ZAZU_*`
77
+ names still work for all of 1.x and emit a one-time `FutureWarning`.
78
+
79
+ ### Hosts
80
+
81
+ The default base URL is `https://ma.manza.finance` (Morocco). For South Africa:
82
+
83
+ ```python
84
+ client = Manza(api_key="sk_live_...", base_url="https://za.manza.finance")
85
+ ```
86
+
87
+ The replay tests run against the staging host `https://ma.manza.dev`.
88
+
89
+ ## Beneficiaries and trusted payees
90
+
91
+ ```python
92
+ beneficiary = client.beneficiaries.create(
93
+ beneficiary_type="business", # "individual" | "business"
94
+ company_name="Acme Corp",
95
+ email="ap@acme.com",
96
+ ).body
97
+
98
+ account = client.beneficiaries.create_external_account(
99
+ beneficiary["id"], account_number="..." # bank_identifier is required in ZA only
100
+ ).body
101
+ client.beneficiaries.list_external_accounts(beneficiary["id"]) # Page
102
+ client.beneficiaries.get_external_account(beneficiary["id"], account["id"])
103
+
104
+ # Ask for the account to be trusted; a member approves it in the app.
105
+ request = client.payee_trust_requests.create([account["id"]]).body
106
+ client.payee_trust_requests.get(request["id"])
107
+ ```
108
+
109
+ ## Transfers and machine authorization
110
+
111
+ ```python
112
+ draft = client.transfer_drafts.create(
113
+ account_id=account_id,
114
+ beneficiary_id=beneficiary_id,
115
+ amount="150.00",
116
+ client_reference="po_1", # unique per entity, at most 128 characters
117
+ ).body
118
+ ```
119
+
120
+ A duplicate `client_reference` raises `ManzaConflictError` with `payment_id`
121
+ naming the existing draft. A draft inside the entity's machine-authorization
122
+ envelope is sent to the enrolled authorizer as a
123
+ `payment.authorization_requested` webhook. Answer it with a different API key
124
+ holding `transfers:authorize`, signing with `manza.transfer_authorization`:
125
+
126
+ ```python
127
+ from manza import transfer_authorization as ta
128
+
129
+ signature_input = ta.signature_input(
130
+ payment_id=draft["id"],
131
+ nonce=nonce, # from the webhook
132
+ amount=draft["amount"], # the API's decimal string, verbatim
133
+ currency_code=draft["currency_code"],
134
+ account_id=draft["account_id"],
135
+ payee=ta.payee_for(external_account_id=draft["external_account_id"]),
136
+ client_reference=draft["client_reference"],
137
+ )
138
+ signature = ta.sign(signing_secret, signature_input) # lowercase hex HMAC-SHA256
139
+
140
+ authorizer.transfer_drafts.authorize(draft["id"], authorization_id, signature)
141
+ # or: authorizer.transfer_drafts.decline(draft["id"], authorization_id, "reason")
142
+ ```
143
+
144
+ `payee_for` takes exactly one of `external_account_id` / `destination_account_id`.
145
+ A blank signature raises `ManzaArgumentError` before any request is made.
146
+
147
+ ## Pagination
148
+
149
+ List endpoints return a `Page`. Iterate one page or chase cursors:
150
+
151
+ ```python
152
+ page = client.invoices.list(limit=25)
153
+ for invoice in page:
154
+ ...
155
+
156
+ # All items, automatic cursor chasing:
157
+ for invoice in client.invoices.list().auto_paging_iter():
158
+ ...
159
+ ```
160
+
161
+ ## Errors
162
+
163
+ Ten concrete subclasses; discriminate with `isinstance`. `ManzaValidationError`
164
+ covers 400 and 422, `ManzaConflictError` covers 409 and exposes `payment_id`:
165
+
166
+ ```python
167
+ from manza import (
168
+ ManzaValidationError,
169
+ ManzaRateLimitError,
170
+ ManzaNotFoundError,
171
+ )
172
+
173
+ try:
174
+ client.invoices.get("nope")
175
+ except ManzaNotFoundError as err:
176
+ print(err.status, err.request_id, err.body)
177
+ except ManzaRateLimitError as err:
178
+ print("retry after", err.retry_after, "seconds")
179
+ ```
180
+
181
+ ## Cross-SDK contract
182
+
183
+ `manza` is one of several Manza SDKs that all replay cassettes recorded by
184
+ the canonical [`manza-ruby`](https://github.com/getmanza/manza-ruby) SDK against
185
+ staging (`ma.manza.dev`). The wire format is snake_case JSON; request and response shapes match
186
+ across Ruby, TypeScript, Python, Go, and Rust.
187
+
188
+ ## License
189
+
190
+ MIT.
manza-1.0.0/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # manza
2
+
3
+ Python SDK for the [Manza API](https://ma.manza.finance).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install manza
9
+ ```
10
+
11
+ Requires Python 3.11+.
12
+
13
+ ## Quick start
14
+
15
+ ```python
16
+ from manza import Manza
17
+
18
+ client = Manza(api_key="sk_live_...")
19
+
20
+ client.entity.get()
21
+ client.accounts.list(currency_code="MAD")
22
+ client.customers.list(q="Acme")
23
+ client.customers.create(
24
+ customer_type="business",
25
+ company_name="Acme Corp",
26
+ email="billing@acme.com",
27
+ )
28
+
29
+ client.invoices.list()
30
+ client.payment_links.cancel(payment_link_id)
31
+ client.webhook_endpoints.list()
32
+
33
+ client.checkout_sessions.create(
34
+ account_id=account_id,
35
+ amount="100.00",
36
+ success_url="https://example.com/ok",
37
+ cancel_url="https://example.com/cancel",
38
+ )
39
+ client.checkout_sessions.get(session_id)
40
+ ```
41
+
42
+ The client picks up `MANZA_API_KEY`, `MANZA_BASE_URL`, `MANZA_API_VERSION`, and
43
+ `MANZA_TIMEOUT` from the environment if you don't pass them. The old `ZAZU_*`
44
+ names still work for all of 1.x and emit a one-time `FutureWarning`.
45
+
46
+ ### Hosts
47
+
48
+ The default base URL is `https://ma.manza.finance` (Morocco). For South Africa:
49
+
50
+ ```python
51
+ client = Manza(api_key="sk_live_...", base_url="https://za.manza.finance")
52
+ ```
53
+
54
+ The replay tests run against the staging host `https://ma.manza.dev`.
55
+
56
+ ## Beneficiaries and trusted payees
57
+
58
+ ```python
59
+ beneficiary = client.beneficiaries.create(
60
+ beneficiary_type="business", # "individual" | "business"
61
+ company_name="Acme Corp",
62
+ email="ap@acme.com",
63
+ ).body
64
+
65
+ account = client.beneficiaries.create_external_account(
66
+ beneficiary["id"], account_number="..." # bank_identifier is required in ZA only
67
+ ).body
68
+ client.beneficiaries.list_external_accounts(beneficiary["id"]) # Page
69
+ client.beneficiaries.get_external_account(beneficiary["id"], account["id"])
70
+
71
+ # Ask for the account to be trusted; a member approves it in the app.
72
+ request = client.payee_trust_requests.create([account["id"]]).body
73
+ client.payee_trust_requests.get(request["id"])
74
+ ```
75
+
76
+ ## Transfers and machine authorization
77
+
78
+ ```python
79
+ draft = client.transfer_drafts.create(
80
+ account_id=account_id,
81
+ beneficiary_id=beneficiary_id,
82
+ amount="150.00",
83
+ client_reference="po_1", # unique per entity, at most 128 characters
84
+ ).body
85
+ ```
86
+
87
+ A duplicate `client_reference` raises `ManzaConflictError` with `payment_id`
88
+ naming the existing draft. A draft inside the entity's machine-authorization
89
+ envelope is sent to the enrolled authorizer as a
90
+ `payment.authorization_requested` webhook. Answer it with a different API key
91
+ holding `transfers:authorize`, signing with `manza.transfer_authorization`:
92
+
93
+ ```python
94
+ from manza import transfer_authorization as ta
95
+
96
+ signature_input = ta.signature_input(
97
+ payment_id=draft["id"],
98
+ nonce=nonce, # from the webhook
99
+ amount=draft["amount"], # the API's decimal string, verbatim
100
+ currency_code=draft["currency_code"],
101
+ account_id=draft["account_id"],
102
+ payee=ta.payee_for(external_account_id=draft["external_account_id"]),
103
+ client_reference=draft["client_reference"],
104
+ )
105
+ signature = ta.sign(signing_secret, signature_input) # lowercase hex HMAC-SHA256
106
+
107
+ authorizer.transfer_drafts.authorize(draft["id"], authorization_id, signature)
108
+ # or: authorizer.transfer_drafts.decline(draft["id"], authorization_id, "reason")
109
+ ```
110
+
111
+ `payee_for` takes exactly one of `external_account_id` / `destination_account_id`.
112
+ A blank signature raises `ManzaArgumentError` before any request is made.
113
+
114
+ ## Pagination
115
+
116
+ List endpoints return a `Page`. Iterate one page or chase cursors:
117
+
118
+ ```python
119
+ page = client.invoices.list(limit=25)
120
+ for invoice in page:
121
+ ...
122
+
123
+ # All items, automatic cursor chasing:
124
+ for invoice in client.invoices.list().auto_paging_iter():
125
+ ...
126
+ ```
127
+
128
+ ## Errors
129
+
130
+ Ten concrete subclasses; discriminate with `isinstance`. `ManzaValidationError`
131
+ covers 400 and 422, `ManzaConflictError` covers 409 and exposes `payment_id`:
132
+
133
+ ```python
134
+ from manza import (
135
+ ManzaValidationError,
136
+ ManzaRateLimitError,
137
+ ManzaNotFoundError,
138
+ )
139
+
140
+ try:
141
+ client.invoices.get("nope")
142
+ except ManzaNotFoundError as err:
143
+ print(err.status, err.request_id, err.body)
144
+ except ManzaRateLimitError as err:
145
+ print("retry after", err.retry_after, "seconds")
146
+ ```
147
+
148
+ ## Cross-SDK contract
149
+
150
+ `manza` is one of several Manza SDKs that all replay cassettes recorded by
151
+ the canonical [`manza-ruby`](https://github.com/getmanza/manza-ruby) SDK against
152
+ staging (`ma.manza.dev`). The wire format is snake_case JSON; request and response shapes match
153
+ across Ruby, TypeScript, Python, Go, and Rust.
154
+
155
+ ## License
156
+
157
+ MIT.
@@ -0,0 +1,91 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "manza"
7
+ description = "Python SDK for the Manza API."
8
+ readme = "README.md"
9
+ license = "MIT"
10
+ license-files = ["LICENSE"]
11
+ requires-python = ">=3.11"
12
+ authors = [{ name = "Manza", email = "hello@get-manza.com" }]
13
+ keywords = ["manza", "sdk", "api", "fintech", "morocco"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Operating System :: OS Independent",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ "Typing :: Typed",
25
+ ]
26
+ dynamic = ["version"]
27
+ dependencies = ["httpx>=0.27"]
28
+
29
+ [project.optional-dependencies]
30
+ dev = [
31
+ "pytest>=8",
32
+ "pytest-vcr>=1.0.2",
33
+ "vcrpy>=6",
34
+ "ruff>=0.7",
35
+ "mypy>=1.11",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/getmanza/manza-python"
40
+ Documentation = "https://github.com/getmanza/manza-python#readme"
41
+ Repository = "https://github.com/getmanza/manza-python"
42
+ Issues = "https://github.com/getmanza/manza-python/issues"
43
+ Changelog = "https://github.com/getmanza/manza-python/blob/main/CHANGELOG.md"
44
+
45
+ [tool.hatch.version]
46
+ path = "src/manza/_version.py"
47
+
48
+ [tool.hatch.build.targets.wheel]
49
+ packages = ["src/manza"]
50
+
51
+ [tool.hatch.build.targets.sdist]
52
+ include = ["src/manza", "README.md", "CHANGELOG.md", "LICENSE"]
53
+
54
+ [tool.pytest.ini_options]
55
+ testpaths = ["tests"]
56
+ addopts = "-ra"
57
+ filterwarnings = ["error"]
58
+
59
+ [tool.ruff]
60
+ line-length = 100
61
+ target-version = "py311"
62
+ src = ["src", "tests"]
63
+
64
+ [tool.ruff.lint]
65
+ select = [
66
+ "E", "F", "W", # pycodestyle / pyflakes
67
+ "I", # isort
68
+ "B", # bugbear
69
+ "UP", # pyupgrade
70
+ "PL", # pylint subset
71
+ "RUF", # ruff-specific
72
+ "SIM", # simplify
73
+ "TCH", # type-checking imports
74
+ ]
75
+ ignore = [
76
+ "PLR0913", # too many args — SDK methods accept many kwargs by design
77
+ "PLR0911", # too many returns — error-status dispatch is naturally a switch
78
+ "PLR2004", # magic-value comparison — fine for HTTP status codes
79
+ "TC001", # move application imports under TYPE_CHECKING — many are used at runtime
80
+ "TC002", # move third-party imports under TYPE_CHECKING — same reason
81
+ "TC003", # move stdlib imports under TYPE_CHECKING — same reason
82
+ "UP037", # remove quotes from annotations — needed for `Self`-style forward refs
83
+ ]
84
+
85
+ [tool.ruff.lint.per-file-ignores]
86
+ "tests/**" = ["PLR2004"]
87
+
88
+ [tool.mypy]
89
+ python_version = "3.11"
90
+ strict = true
91
+ files = ["src/manza"]
@@ -0,0 +1,63 @@
1
+ """Manza Python SDK. Mirrors lib/manza.rb."""
2
+
3
+ from . import transfer_authorization
4
+ from ._version import __version__
5
+ from .client import Manza
6
+ from .errors import (
7
+ ManzaArgumentError,
8
+ ManzaAuthenticationError,
9
+ ManzaConfigurationError,
10
+ ManzaConflictError,
11
+ ManzaConnectionError,
12
+ ManzaError,
13
+ ManzaForbiddenError,
14
+ ManzaNotFoundError,
15
+ ManzaRateLimitError,
16
+ ManzaServerError,
17
+ ManzaValidationError,
18
+ )
19
+ from .page import MAX_PER_PAGE, Page
20
+ from .resources.accounts import Accounts
21
+ from .resources.beneficiaries import Beneficiaries
22
+ from .resources.checkout_sessions import CheckoutSessions
23
+ from .resources.customers import Customers
24
+ from .resources.entity import Entity
25
+ from .resources.invoices import Invoices
26
+ from .resources.payee_trust_requests import PayeeTrustRequests
27
+ from .resources.payment_links import PaymentLinks
28
+ from .resources.transfer_drafts import TransferDrafts
29
+ from .resources.webhook_endpoints import WebhookEndpoints
30
+ from .response import ManzaResponse
31
+
32
+ VERSION = __version__
33
+
34
+ __all__ = [
35
+ "MAX_PER_PAGE",
36
+ "VERSION",
37
+ "Accounts",
38
+ "Beneficiaries",
39
+ "CheckoutSessions",
40
+ "Customers",
41
+ "Entity",
42
+ "Invoices",
43
+ "Manza",
44
+ "ManzaArgumentError",
45
+ "ManzaAuthenticationError",
46
+ "ManzaConfigurationError",
47
+ "ManzaConflictError",
48
+ "ManzaConnectionError",
49
+ "ManzaError",
50
+ "ManzaForbiddenError",
51
+ "ManzaNotFoundError",
52
+ "ManzaRateLimitError",
53
+ "ManzaResponse",
54
+ "ManzaServerError",
55
+ "ManzaValidationError",
56
+ "Page",
57
+ "PayeeTrustRequests",
58
+ "PaymentLinks",
59
+ "TransferDrafts",
60
+ "WebhookEndpoints",
61
+ "__version__",
62
+ "transfer_authorization",
63
+ ]
@@ -0,0 +1,39 @@
1
+ """Environment lookup: `MANZA_<NAME>` first, then the legacy `ZAZU_<NAME>`.
2
+
3
+ The legacy name still works for all of 1.x and warns once per variable."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import os
8
+ import threading
9
+ import warnings
10
+
11
+ _warned: set[str] = set()
12
+ _lock = threading.Lock()
13
+
14
+
15
+ def get(name: str) -> str | None:
16
+ """Return `MANZA_<name>`, else `ZAZU_<name>` (warning once), else None."""
17
+ value = os.getenv(f"MANZA_{name}")
18
+ if value is not None:
19
+ return value
20
+ legacy = f"ZAZU_{name}"
21
+ value = os.getenv(legacy)
22
+ if value:
23
+ with _lock:
24
+ first = legacy not in _warned
25
+ _warned.add(legacy)
26
+ if first:
27
+ warnings.warn(
28
+ f"{legacy} is deprecated; set MANZA_{name} instead. "
29
+ "The ZAZU_* fallback will be removed in 2.0.",
30
+ FutureWarning,
31
+ stacklevel=3,
32
+ )
33
+ return value
34
+ return None
35
+
36
+
37
+ def reset_warnings() -> None:
38
+ """Forget which legacy variables already warned (for tests)."""
39
+ _warned.clear()
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0"