smartbroker-plus-sdk 0.3.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.
Files changed (130) hide show
  1. smartbroker_plus_sdk-0.3.0/LICENSE +21 -0
  2. smartbroker_plus_sdk-0.3.0/PKG-INFO +250 -0
  3. smartbroker_plus_sdk-0.3.0/README.md +195 -0
  4. smartbroker_plus_sdk-0.3.0/pyproject.toml +75 -0
  5. smartbroker_plus_sdk-0.3.0/setup.cfg +148 -0
  6. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/__init__.py +242 -0
  7. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/__main__.py +9 -0
  8. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/__init__.py +0 -0
  9. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_account_prefs/__init__.py +8 -0
  10. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_account_prefs/_account_preferences.py +68 -0
  11. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_account_prefs/_account_prefs_store.py +133 -0
  12. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_active_account/__init__.py +0 -0
  13. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_active_account/_active_account.py +22 -0
  14. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_active_account/_active_account_store.py +68 -0
  15. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_environments.py +91 -0
  16. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_oauth.py +505 -0
  17. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_token_cache/__init__.py +0 -0
  18. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_token_cache/_cached_token.py +103 -0
  19. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_token_cache/_file_token_cache.py +155 -0
  20. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_token_cache/_null_token_cache.py +49 -0
  21. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_token_cache/_path_resolver.py +32 -0
  22. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_token_cache/_token_cache.py +48 -0
  23. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_two_factor.py +494 -0
  24. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_two_factor_poll.py +99 -0
  25. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_two_factor_provider.py +52 -0
  26. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_auth/_two_factor_requests.py +119 -0
  27. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/__init__.py +0 -0
  28. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_account_resolver.py +65 -0
  29. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_account_transactions_cmd.py +53 -0
  30. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_app.py +153 -0
  31. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_auth_cmd.py +325 -0
  32. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_client_factory.py +181 -0
  33. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_context.py +23 -0
  34. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_cost_report_cmd.py +89 -0
  35. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_entrypoint.py +42 -0
  36. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_environments.py +10 -0
  37. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_error_handler.py +184 -0
  38. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_health_cmd.py +20 -0
  39. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_logging_setup.py +61 -0
  40. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_marketstate_cmd.py +44 -0
  41. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_modifications_cmd.py +194 -0
  42. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_oauth_browser.py +96 -0
  43. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_orders_cmd.py +167 -0
  44. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_output.py +166 -0
  45. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_output_format.py +12 -0
  46. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_payload_loader.py +59 -0
  47. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_portfolios_cmd.py +77 -0
  48. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_positions_cmd.py +127 -0
  49. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_profile_cmd.py +40 -0
  50. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_prompts.py +32 -0
  51. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_tradeability_cmd.py +71 -0
  52. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_cli/_transactions_cmd.py +77 -0
  53. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_client.py +505 -0
  54. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_error_mapping.py +112 -0
  55. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_exceptions.py +124 -0
  56. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/__init__.py +0 -0
  57. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_account_transactions.py +42 -0
  58. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_auth.py +65 -0
  59. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_common.py +366 -0
  60. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_cost_report.py +49 -0
  61. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_marketstate.py +46 -0
  62. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_modifications.py +162 -0
  63. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_orders.py +318 -0
  64. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_portfolios.py +87 -0
  65. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_positions.py +50 -0
  66. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_profile.py +13 -0
  67. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_tradeability.py +79 -0
  68. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_models/_transactions.py +63 -0
  69. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/__init__.py +0 -0
  70. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_account_transactions.py +96 -0
  71. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_account_transactions_requests.py +71 -0
  72. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_b2b_base.py +2 -0
  73. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_cost_report.py +86 -0
  74. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_cost_report_requests.py +31 -0
  75. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_health.py +47 -0
  76. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_health_requests.py +15 -0
  77. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_marketstate.py +70 -0
  78. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_marketstate_requests.py +33 -0
  79. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_order_modifications.py +260 -0
  80. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_order_modifications_requests.py +128 -0
  81. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_orders.py +545 -0
  82. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_orders_requests.py +272 -0
  83. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_portfolios.py +50 -0
  84. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_portfolios_requests.py +27 -0
  85. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_positions.py +289 -0
  86. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_positions_requests.py +89 -0
  87. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_profile.py +56 -0
  88. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_profile_requests.py +17 -0
  89. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_request.py +35 -0
  90. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_tradeability.py +122 -0
  91. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_tradeability_requests.py +91 -0
  92. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_transactions.py +95 -0
  93. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_transactions_requests.py +34 -0
  94. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_resources/_validation.py +57 -0
  95. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/__init__.py +0 -0
  96. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_auth_policy.py +182 -0
  97. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_http_transport.py +530 -0
  98. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_log_formatting.py +345 -0
  99. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_logging_transport.py +83 -0
  100. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_logging_transport_async.py +83 -0
  101. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_response.py +25 -0
  102. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_retry.py +18 -0
  103. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_two_factor_guard.py +204 -0
  104. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/_transport/_urls.py +22 -0
  105. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/account/__init__.py +46 -0
  106. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/exceptions.py +43 -0
  107. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/market/__init__.py +29 -0
  108. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/py.typed +0 -0
  109. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk/trading/__init__.py +87 -0
  110. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk.egg-info/PKG-INFO +250 -0
  111. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk.egg-info/SOURCES.txt +129 -0
  112. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk.egg-info/dependency_links.txt +1 -0
  113. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk.egg-info/entry_points.txt +2 -0
  114. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk.egg-info/requires.txt +6 -0
  115. smartbroker_plus_sdk-0.3.0/src/smartbroker_plus_sdk.egg-info/top_level.txt +1 -0
  116. smartbroker_plus_sdk-0.3.0/tests/test_build_script.py +23 -0
  117. smartbroker_plus_sdk-0.3.0/tests/test_client.py +426 -0
  118. smartbroker_plus_sdk-0.3.0/tests/test_error_mapping.py +237 -0
  119. smartbroker_plus_sdk-0.3.0/tests/test_exceptions.py +153 -0
  120. smartbroker_plus_sdk-0.3.0/tests/test_internal_paths_hidden.py +26 -0
  121. smartbroker_plus_sdk-0.3.0/tests/test_main.py +19 -0
  122. smartbroker_plus_sdk-0.3.0/tests/test_placeholder.py +7 -0
  123. smartbroker_plus_sdk-0.3.0/tests/test_public_api.py +221 -0
  124. smartbroker_plus_sdk-0.3.0/tests/test_public_api_behavior.py +264 -0
  125. smartbroker_plus_sdk-0.3.0/tests/test_public_subnamespace_account.py +42 -0
  126. smartbroker_plus_sdk-0.3.0/tests/test_public_subnamespace_market.py +37 -0
  127. smartbroker_plus_sdk-0.3.0/tests/test_public_subnamespace_trading.py +67 -0
  128. smartbroker_plus_sdk-0.3.0/tests/test_sandbox_conftest_behavior.py +165 -0
  129. smartbroker_plus_sdk-0.3.0/tests/test_tools_tests_runner.py +235 -0
  130. smartbroker_plus_sdk-0.3.0/version.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Steven England
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.
@@ -0,0 +1,250 @@
1
+ Metadata-Version: 2.4
2
+ Name: smartbroker-plus-sdk
3
+ Version: 0.3.0
4
+ Summary: Python SDK for the Smartbroker+ B2B API
5
+ Author-email: Steven England <github@steven-england.info>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Steven England
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/stevenengland/smartbroker-plus-sdk
29
+ Project-URL: Issues, https://github.com/stevenengland/smartbroker-plus-sdk/issues
30
+ Project-URL: Documentation, https://github.com/stevenengland/smartbroker-plus-sdk#readme
31
+ Project-URL: Changelog, https://github.com/stevenengland/smartbroker-plus-sdk/blob/main/CHANGELOG.md
32
+ Keywords: smartbroker,smartbroker-plus,trading,brokerage
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: Intended Audience :: Financial and Insurance Industry
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.11
40
+ Classifier: Programming Language :: Python :: 3.12
41
+ Classifier: Programming Language :: Python :: 3.13
42
+ Classifier: Programming Language :: Python :: Implementation :: CPython
43
+ Classifier: Topic :: Office/Business :: Financial :: Investment
44
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
45
+ Classifier: Typing :: Typed
46
+ Requires-Python: >=3.11
47
+ Description-Content-Type: text/markdown
48
+ License-File: LICENSE
49
+ Requires-Dist: httpx
50
+ Requires-Dist: pydantic>=2.0
51
+ Provides-Extra: cli
52
+ Requires-Dist: typer>=0.12; extra == "cli"
53
+ Requires-Dist: rich>=13; extra == "cli"
54
+ Dynamic: license-file
55
+
56
+ # smartbroker-plus-sdk
57
+
58
+ [![Build](https://github.com/stevenengland/smartbroker-plus-sdk/actions/workflows/code_testing.yml/badge.svg)](https://github.com/stevenengland/smartbroker-plus-sdk/actions/workflows/code_testing.yml)
59
+ [![Python Versions](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org)
60
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
61
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/stevenengland/smartbroker-plus-sdk/pulls)
62
+
63
+ > *Typed Python SDK and CLI for the for the Smartbroker+ B2B API.*
64
+
65
+ > [!WARNING]
66
+ > **Alpha** — the public surface may still change. Unofficial project, not
67
+ > affiliated with Smartbroker+.
68
+
69
+ ## Features
70
+
71
+ - **OAuth2 Authorization Code + PKCE helpers** — full RFC 7636 implementation; the SDK handles token exchange, refresh, and revocation.
72
+ - **Sync and async parity** — `SmartbrokerClient` and `AsyncSmartbrokerClient` expose identical resource surfaces.
73
+ - **Full B2B resource coverage** — orders, order modifications, portfolios, positions, account transactions, market state, tradeability, cost report, and profile.
74
+ - **2FA token header support** — automatic `X-2fa-Token` injection for order-modifying endpoints.
75
+ - **Typed end-to-end** — Pydantic v2 models throughout, ships `py.typed`.
76
+ - **RFC 9457 error mapping** — HTTP problem details mapped to a typed exception hierarchy.
77
+ - **Python 3.11+**
78
+
79
+ ## Quick Start (sync)
80
+
81
+ ```python
82
+ from smartbroker_plus_sdk import SmartbrokerClient, generate_code_verifier, generate_code_challenge
83
+
84
+ # 1. Generate PKCE pair before starting the authorization flow
85
+ verifier = generate_code_verifier()
86
+ challenge = generate_code_challenge(verifier)
87
+ # → Send `challenge` as `code_challenge` in the authorization URL
88
+
89
+ # 2. Create a client — it handles token exchange and refresh internally
90
+ client = SmartbrokerClient(
91
+ base_url="https://api.smartbroker.de",
92
+ token_url="https://auth.smartbroker.de/.../token",
93
+ api_key="your_api_key",
94
+ client_id="your_client_id",
95
+ client_secret="your_client_secret",
96
+ )
97
+
98
+ # 3. Exchange the authorization code for tokens
99
+ tokens = client.exchange_authorization_code(
100
+ code="authorization_code_from_callback",
101
+ redirect_uri="https://your-app.com/callback",
102
+ code_verifier=verifier,
103
+ )
104
+
105
+ # 4. Use resources
106
+ profile = client.profile.get_account_numbers()
107
+ print(profile.account_number)
108
+ ```
109
+
110
+ ## Quick Start (async)
111
+
112
+ ```python
113
+ import asyncio
114
+ from smartbroker_plus_sdk import AsyncSmartbrokerClient, generate_code_verifier, generate_code_challenge
115
+
116
+ async def main() -> None:
117
+ verifier = generate_code_verifier()
118
+ challenge = generate_code_challenge(verifier)
119
+
120
+ client = AsyncSmartbrokerClient(
121
+ base_url="https://api.smartbroker.de",
122
+ token_url="https://auth.smartbroker.de/.../token",
123
+ api_key="your_api_key",
124
+ client_id="your_client_id",
125
+ client_secret="your_client_secret",
126
+ )
127
+
128
+ await client.exchange_authorization_code(
129
+ code="authorization_code_from_callback",
130
+ redirect_uri="https://your-app.com/callback",
131
+ code_verifier=verifier,
132
+ )
133
+
134
+ profile = await client.profile.get_account_numbers()
135
+ print(profile.account_number)
136
+
137
+ asyncio.run(main())
138
+ ```
139
+
140
+ ## Error Handling
141
+
142
+ All SDK errors extend `SmartbrokerApiError`:
143
+
144
+ ```
145
+ SmartbrokerApiError
146
+ ├── AuthenticationError # HTTP 401 — invalid/expired credentials
147
+ ├── AuthorizationError # HTTP 403 — insufficient permissions
148
+ ├── NotFoundError # HTTP 404 — resource does not exist
149
+ ├── ValidationError # HTTP 400/412 — request validation failed
150
+ │ ├── OrderRejectedError # messageKey: ORDER_REJECTED
151
+ │ ├── InsufficientBalanceError # messageKey: INSUFFICIENT_BALANCE
152
+ │ └── BuyingPowerExceededError # messageKey: BUYINGPOWER_EXCEEDED
153
+ ├── ServerError # HTTP 5xx — vendor server-side failure
154
+ ├── TwoFactorError # 2FA token flow failed (timeout, rejection)
155
+ └── RetryExhaustedError # all retry attempts exhausted
156
+ ```
157
+
158
+ ```python
159
+ from smartbroker_plus_sdk.exceptions import SmartbrokerApiError, ValidationError
160
+
161
+ try:
162
+ client.orders.create(...)
163
+ except ValidationError as e:
164
+ print(f"Validation failed: {e}")
165
+ except SmartbrokerApiError as e:
166
+ print(f"API error: {e}")
167
+ ```
168
+
169
+ ## CLI Quick Start
170
+
171
+ Install the package and run the CLI with `sbplus`:
172
+
173
+ ```bash
174
+ # 1. Set credentials (or use env vars — see table below)
175
+ export SMARTBROKER_CLIENT_ID=my-client-id
176
+ export SMARTBROKER_CLIENT_SECRET=my-client-secret # or enter at the prompt
177
+
178
+ # 2. Log in — prompts for environment (sand/prod), then opens browser for PKCE flow
179
+ sbplus auth login
180
+ # > Environment [sand/prod] (prod): prod
181
+ # > Credentials will be stored at ~/.cache/smartbroker-plus-sdk/tokens.json. Continue? [Y/n]:
182
+
183
+ # 3. Check status and browse data
184
+ sbplus auth status
185
+ sbplus portfolios list
186
+ sbplus orders list --portfolio <portfolioId>
187
+
188
+ # 4. Log out
189
+ sbplus auth logout
190
+ ```
191
+
192
+ Use `--output` (or `-o`) to change the format: `table` (default), `wide`, `detail`, `json`.
193
+
194
+ For terminal demo recordings see [docs/cast/](docs/cast/).
195
+
196
+ ### Environment Variables
197
+
198
+ | Variable | Flag | Description |
199
+ |---|---|---|
200
+ | `SMARTBROKER_BASE_URL` | `--base-url` | API base URL |
201
+ | `SMARTBROKER_ENV` | `--env` | Deployment environment (`sand` or `prod`) |
202
+ | `SMARTBROKER_AUTH_BASE_URL` | `--auth-base-url` | Auth/IdP base URL (defaults to `--base-url`) |
203
+ | `SMARTBROKER_API_KEY` | `--api-key` | API key |
204
+ | `SMARTBROKER_CLIENT_ID` | `--client-id` | OAuth2 client ID |
205
+ | `SMARTBROKER_CLIENT_SECRET` | `--client-secret` | OAuth2 client secret |
206
+ | `SMARTBROKER_REDIRECT_URI` | `--redirect-uri` | OAuth2 redirect URI (default: `http://127.0.0.1:8765/callback`) |
207
+ | `SMARTBROKER_CACHE_DIR` | `--cache-dir` | Token cache directory |
208
+ | `SMARTBROKER_OUTPUT` | `--output` / `-o` | Default output format (`table`, `wide`, `detail`, `json`) |
209
+ | `SMARTBROKER_TIMEOUT` | `--timeout` | HTTP request timeout in seconds (default: 30) |
210
+
211
+ ### Exit Codes
212
+
213
+ | Code | Meaning |
214
+ |------|---------|
215
+ | `0` | Success |
216
+ | `1` | General error / unexpected exception |
217
+ | `2` | Authentication or authorization failure |
218
+ | `3` | Resource not found |
219
+ | `4` | Validation error |
220
+ | `5` | Server error |
221
+ | `6` | 2FA required |
222
+ | `7` | Retry limit exhausted |
223
+ | `130` | Interrupted (Ctrl-C) |
224
+
225
+ ## Migration from pre-0.2 (`#41` rename)
226
+
227
+ The `smartbroker_plus_sdk.auth` sub-package was removed in 0.2.0. Update your imports:
228
+
229
+ ```python
230
+ # Before (≤0.1.x)
231
+ from smartbroker_plus_sdk.auth import generate_code_verifier, generate_code_challenge
232
+ from smartbroker_plus_sdk.auth.exceptions import AuthenticationError
233
+
234
+ # After (≥0.2.0)
235
+ from smartbroker_plus_sdk import generate_code_verifier, generate_code_challenge
236
+ from smartbroker_plus_sdk.exceptions import AuthenticationError
237
+ ```
238
+
239
+ ## Troubleshooting
240
+
241
+ See [docs/troubleshooting.md](docs/troubleshooting.md) for common gotchas.
242
+
243
+ ## Changelog
244
+
245
+ See [CHANGELOG.md](CHANGELOG.md).
246
+
247
+ ## Development
248
+
249
+ See [docs/development.md](docs/development.md) for the full development guide.
250
+
@@ -0,0 +1,195 @@
1
+ # smartbroker-plus-sdk
2
+
3
+ [![Build](https://github.com/stevenengland/smartbroker-plus-sdk/actions/workflows/code_testing.yml/badge.svg)](https://github.com/stevenengland/smartbroker-plus-sdk/actions/workflows/code_testing.yml)
4
+ [![Python Versions](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/stevenengland/smartbroker-plus-sdk/pulls)
7
+
8
+ > *Typed Python SDK and CLI for the for the Smartbroker+ B2B API.*
9
+
10
+ > [!WARNING]
11
+ > **Alpha** — the public surface may still change. Unofficial project, not
12
+ > affiliated with Smartbroker+.
13
+
14
+ ## Features
15
+
16
+ - **OAuth2 Authorization Code + PKCE helpers** — full RFC 7636 implementation; the SDK handles token exchange, refresh, and revocation.
17
+ - **Sync and async parity** — `SmartbrokerClient` and `AsyncSmartbrokerClient` expose identical resource surfaces.
18
+ - **Full B2B resource coverage** — orders, order modifications, portfolios, positions, account transactions, market state, tradeability, cost report, and profile.
19
+ - **2FA token header support** — automatic `X-2fa-Token` injection for order-modifying endpoints.
20
+ - **Typed end-to-end** — Pydantic v2 models throughout, ships `py.typed`.
21
+ - **RFC 9457 error mapping** — HTTP problem details mapped to a typed exception hierarchy.
22
+ - **Python 3.11+**
23
+
24
+ ## Quick Start (sync)
25
+
26
+ ```python
27
+ from smartbroker_plus_sdk import SmartbrokerClient, generate_code_verifier, generate_code_challenge
28
+
29
+ # 1. Generate PKCE pair before starting the authorization flow
30
+ verifier = generate_code_verifier()
31
+ challenge = generate_code_challenge(verifier)
32
+ # → Send `challenge` as `code_challenge` in the authorization URL
33
+
34
+ # 2. Create a client — it handles token exchange and refresh internally
35
+ client = SmartbrokerClient(
36
+ base_url="https://api.smartbroker.de",
37
+ token_url="https://auth.smartbroker.de/.../token",
38
+ api_key="your_api_key",
39
+ client_id="your_client_id",
40
+ client_secret="your_client_secret",
41
+ )
42
+
43
+ # 3. Exchange the authorization code for tokens
44
+ tokens = client.exchange_authorization_code(
45
+ code="authorization_code_from_callback",
46
+ redirect_uri="https://your-app.com/callback",
47
+ code_verifier=verifier,
48
+ )
49
+
50
+ # 4. Use resources
51
+ profile = client.profile.get_account_numbers()
52
+ print(profile.account_number)
53
+ ```
54
+
55
+ ## Quick Start (async)
56
+
57
+ ```python
58
+ import asyncio
59
+ from smartbroker_plus_sdk import AsyncSmartbrokerClient, generate_code_verifier, generate_code_challenge
60
+
61
+ async def main() -> None:
62
+ verifier = generate_code_verifier()
63
+ challenge = generate_code_challenge(verifier)
64
+
65
+ client = AsyncSmartbrokerClient(
66
+ base_url="https://api.smartbroker.de",
67
+ token_url="https://auth.smartbroker.de/.../token",
68
+ api_key="your_api_key",
69
+ client_id="your_client_id",
70
+ client_secret="your_client_secret",
71
+ )
72
+
73
+ await client.exchange_authorization_code(
74
+ code="authorization_code_from_callback",
75
+ redirect_uri="https://your-app.com/callback",
76
+ code_verifier=verifier,
77
+ )
78
+
79
+ profile = await client.profile.get_account_numbers()
80
+ print(profile.account_number)
81
+
82
+ asyncio.run(main())
83
+ ```
84
+
85
+ ## Error Handling
86
+
87
+ All SDK errors extend `SmartbrokerApiError`:
88
+
89
+ ```
90
+ SmartbrokerApiError
91
+ ├── AuthenticationError # HTTP 401 — invalid/expired credentials
92
+ ├── AuthorizationError # HTTP 403 — insufficient permissions
93
+ ├── NotFoundError # HTTP 404 — resource does not exist
94
+ ├── ValidationError # HTTP 400/412 — request validation failed
95
+ │ ├── OrderRejectedError # messageKey: ORDER_REJECTED
96
+ │ ├── InsufficientBalanceError # messageKey: INSUFFICIENT_BALANCE
97
+ │ └── BuyingPowerExceededError # messageKey: BUYINGPOWER_EXCEEDED
98
+ ├── ServerError # HTTP 5xx — vendor server-side failure
99
+ ├── TwoFactorError # 2FA token flow failed (timeout, rejection)
100
+ └── RetryExhaustedError # all retry attempts exhausted
101
+ ```
102
+
103
+ ```python
104
+ from smartbroker_plus_sdk.exceptions import SmartbrokerApiError, ValidationError
105
+
106
+ try:
107
+ client.orders.create(...)
108
+ except ValidationError as e:
109
+ print(f"Validation failed: {e}")
110
+ except SmartbrokerApiError as e:
111
+ print(f"API error: {e}")
112
+ ```
113
+
114
+ ## CLI Quick Start
115
+
116
+ Install the package and run the CLI with `sbplus`:
117
+
118
+ ```bash
119
+ # 1. Set credentials (or use env vars — see table below)
120
+ export SMARTBROKER_CLIENT_ID=my-client-id
121
+ export SMARTBROKER_CLIENT_SECRET=my-client-secret # or enter at the prompt
122
+
123
+ # 2. Log in — prompts for environment (sand/prod), then opens browser for PKCE flow
124
+ sbplus auth login
125
+ # > Environment [sand/prod] (prod): prod
126
+ # > Credentials will be stored at ~/.cache/smartbroker-plus-sdk/tokens.json. Continue? [Y/n]:
127
+
128
+ # 3. Check status and browse data
129
+ sbplus auth status
130
+ sbplus portfolios list
131
+ sbplus orders list --portfolio <portfolioId>
132
+
133
+ # 4. Log out
134
+ sbplus auth logout
135
+ ```
136
+
137
+ Use `--output` (or `-o`) to change the format: `table` (default), `wide`, `detail`, `json`.
138
+
139
+ For terminal demo recordings see [docs/cast/](docs/cast/).
140
+
141
+ ### Environment Variables
142
+
143
+ | Variable | Flag | Description |
144
+ |---|---|---|
145
+ | `SMARTBROKER_BASE_URL` | `--base-url` | API base URL |
146
+ | `SMARTBROKER_ENV` | `--env` | Deployment environment (`sand` or `prod`) |
147
+ | `SMARTBROKER_AUTH_BASE_URL` | `--auth-base-url` | Auth/IdP base URL (defaults to `--base-url`) |
148
+ | `SMARTBROKER_API_KEY` | `--api-key` | API key |
149
+ | `SMARTBROKER_CLIENT_ID` | `--client-id` | OAuth2 client ID |
150
+ | `SMARTBROKER_CLIENT_SECRET` | `--client-secret` | OAuth2 client secret |
151
+ | `SMARTBROKER_REDIRECT_URI` | `--redirect-uri` | OAuth2 redirect URI (default: `http://127.0.0.1:8765/callback`) |
152
+ | `SMARTBROKER_CACHE_DIR` | `--cache-dir` | Token cache directory |
153
+ | `SMARTBROKER_OUTPUT` | `--output` / `-o` | Default output format (`table`, `wide`, `detail`, `json`) |
154
+ | `SMARTBROKER_TIMEOUT` | `--timeout` | HTTP request timeout in seconds (default: 30) |
155
+
156
+ ### Exit Codes
157
+
158
+ | Code | Meaning |
159
+ |------|---------|
160
+ | `0` | Success |
161
+ | `1` | General error / unexpected exception |
162
+ | `2` | Authentication or authorization failure |
163
+ | `3` | Resource not found |
164
+ | `4` | Validation error |
165
+ | `5` | Server error |
166
+ | `6` | 2FA required |
167
+ | `7` | Retry limit exhausted |
168
+ | `130` | Interrupted (Ctrl-C) |
169
+
170
+ ## Migration from pre-0.2 (`#41` rename)
171
+
172
+ The `smartbroker_plus_sdk.auth` sub-package was removed in 0.2.0. Update your imports:
173
+
174
+ ```python
175
+ # Before (≤0.1.x)
176
+ from smartbroker_plus_sdk.auth import generate_code_verifier, generate_code_challenge
177
+ from smartbroker_plus_sdk.auth.exceptions import AuthenticationError
178
+
179
+ # After (≥0.2.0)
180
+ from smartbroker_plus_sdk import generate_code_verifier, generate_code_challenge
181
+ from smartbroker_plus_sdk.exceptions import AuthenticationError
182
+ ```
183
+
184
+ ## Troubleshooting
185
+
186
+ See [docs/troubleshooting.md](docs/troubleshooting.md) for common gotchas.
187
+
188
+ ## Changelog
189
+
190
+ See [CHANGELOG.md](CHANGELOG.md).
191
+
192
+ ## Development
193
+
194
+ See [docs/development.md](docs/development.md) for the full development guide.
195
+
@@ -0,0 +1,75 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "smartbroker-plus-sdk"
7
+ dynamic = ["version"]
8
+ description = "Python SDK for the Smartbroker+ B2B API"
9
+ readme = "README.md"
10
+ license = {file = "LICENSE"}
11
+ authors = [
12
+ {name = "Steven England", email = "github@steven-england.info"},
13
+ ]
14
+ keywords = ["smartbroker", "smartbroker-plus", "trading", "brokerage"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "Intended Audience :: Financial and Insurance Industry",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python :: 3",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: Implementation :: CPython",
26
+ "Topic :: Office/Business :: Financial :: Investment",
27
+ "Topic :: Software Development :: Libraries :: Python Modules",
28
+ "Typing :: Typed",
29
+ ]
30
+ requires-python = ">=3.11"
31
+ dependencies = [
32
+ "httpx",
33
+ "pydantic>=2.0",
34
+ ]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/stevenengland/smartbroker-plus-sdk"
38
+ Issues = "https://github.com/stevenengland/smartbroker-plus-sdk/issues"
39
+ Documentation = "https://github.com/stevenengland/smartbroker-plus-sdk#readme"
40
+ Changelog = "https://github.com/stevenengland/smartbroker-plus-sdk/blob/main/CHANGELOG.md"
41
+
42
+ [project.optional-dependencies]
43
+ cli = ["typer>=0.12", "rich>=13"]
44
+
45
+ [project.scripts]
46
+ sbplus = "smartbroker_plus_sdk._cli._entrypoint:main"
47
+
48
+ [tool.setuptools.packages.find]
49
+ where = ["src"]
50
+
51
+ [tool.setuptools.package-data]
52
+ smartbroker_plus_sdk = ["py.typed"]
53
+
54
+ [tool.setuptools.dynamic]
55
+ version = {file = "version.txt"}
56
+
57
+ # solely for Pyright (Pylance is built on top)
58
+ # extraPath and pythonPath settings are necessary to avoid building a complete package
59
+ # - like with setup.py -> package_dir
60
+ # - like with pyproject.toml -> setuptools
61
+ # -> Otherwise the imports are not resolved at least from the tests dir
62
+ [tool.pyright]
63
+ include = ["src", "tests"]
64
+ reportRedeclaration = "none"
65
+ reportUnusedVariable = "warning"
66
+ reportUnusedImport = "warning"
67
+ reportUnusedFunction = "warning"
68
+ reportUnusedClass = "warning"
69
+ reportUnusedExpression = "warning"
70
+ extraPaths = ["."]
71
+ pythonPath = "."
72
+ executionEnvironments = [
73
+ { root = "tests", pythonPath = ".", reportUnknownMemberType = "none", reportArgumentType = "none" },
74
+ { root = ".", pythonPath = "." }
75
+ ]
@@ -0,0 +1,148 @@
1
+ [black]
2
+
3
+ [flake8]
4
+ select = WPS
5
+ format = wemake
6
+ show-source = true
7
+ statistics = false
8
+ doctests = true
9
+ enable-extensions = G
10
+ exclude =
11
+ .git,
12
+ __pycache__,
13
+ .venv,
14
+ tools,
15
+ .mypy_cache,
16
+ .eggs,
17
+ *.egg,
18
+ tests/assets,
19
+ .claude,
20
+ .agents
21
+ max-complexity = 10
22
+ max-cognitive-complexity = 12
23
+ max-line-length = 120
24
+ extend-ignore = E203
25
+ max-module-expressions = 7
26
+ max-methods = 10
27
+ max-imports = 20
28
+ ignore = D401, X100, W504, RST303, RST304, DAR103, DAR203,
29
+ D100, D101, D102, D103, D104, D105, D106, D107
30
+ Q000,
31
+ WPS305, WPS237
32
+ WPS421
33
+ WPS202
34
+ WPS210
35
+ W503
36
+ WPS337
37
+ WPS348
38
+ per-file-ignores =
39
+ tests/*.py: S101, S105, WPS432, WPS114, WPS202, WPS210, WPS118, WPS226, WPS204, WPS218, WPS213, WPS221, WPS201, WPS229, WPS501, WPS232, WPS214, WPS230, WPS430, WPS402, WPS441, WPS437, WPS236, WPS110, WPS211, WPS111, WPS219, WPS520, WPS338, WPS407, WPS527, WPS300, WPS301, WPS458
40
+
41
+ src/smartbroker_plus_sdk/__init__.py: WPS203, WPS235, WPS410, WPS412, WPS300, WPS201
42
+
43
+ src/smartbroker_plus_sdk/exceptions.py: WPS300, WPS410
44
+
45
+ src/smartbroker_plus_sdk/_resources/_orders.py: WPS214
46
+
47
+ src/smartbroker_plus_sdk/_auth/_oauth.py: WPS214
48
+
49
+ src/smartbroker_plus_sdk/trading/__init__.py: WPS201, WPS300, WPS410, WPS412
50
+ src/smartbroker_plus_sdk/market/__init__.py: WPS300, WPS410, WPS412
51
+ src/smartbroker_plus_sdk/account/__init__.py: WPS300, WPS410, WPS412
52
+
53
+ src/smartbroker_plus_sdk/_cli/*.py: WPS211, WPS213, WPS231, WPS404, WPS407, WPS432, WPS441
54
+ src/smartbroker_plus_sdk/_cli/_oauth_browser.py: WPS211, WPS213, WPS226, WPS231, WPS338, WPS404, WPS407, WPS420, WPS431, WPS432, WPS441
55
+ src/smartbroker_plus_sdk/_cli/_auth_cmd.py: WPS211, WPS213, WPS231, WPS404, WPS407, WPS420, WPS432, WPS441
56
+ src/smartbroker_plus_sdk/_cli/_error_handler.py: WPS211, WPS213, WPS231, WPS404, WPS407, WPS420, WPS432, WPS441
57
+ src/smartbroker_plus_sdk/_cli/_payload_loader.py: WPS211, WPS213, WPS231, WPS238, WPS404, WPS407, WPS432, WPS441
58
+ strictness = long
59
+ docstring-style = google
60
+
61
+ [isort]
62
+ profile = black
63
+ include_trailing_comma = true
64
+ use_parentheses = true
65
+ multi_line_output = 3
66
+ line_length = 80
67
+
68
+ [mypy]
69
+ exclude = tests/assets
70
+ mypy_path = src
71
+ enable_error_code =
72
+ truthy-bool,
73
+ redundant-expr,
74
+ unused-awaitable,
75
+ ignore-without-code
76
+ allow_redefinition = false
77
+ check_untyped_defs = true
78
+ disallow_untyped_decorators = true
79
+ disallow_any_explicit = true
80
+ disallow_any_generics = true
81
+ disallow_untyped_calls = true
82
+ explicit_package_bases = true
83
+ ignore_errors = false
84
+ ignore_missing_imports = true
85
+ implicit_reexport = false
86
+ local_partial_types = true
87
+ strict_optional = true
88
+ strict_equality = true
89
+ show_error_codes = true
90
+ no_implicit_optional = true
91
+ warn_unused_ignores = true
92
+ warn_redundant_casts = true
93
+ warn_unused_configs = true
94
+ warn_unreachable = true
95
+ warn_no_return = true
96
+ plugins = pydantic.mypy
97
+
98
+ [pydantic-mypy]
99
+ init_typed = True
100
+
101
+ [mypy-tests.*]
102
+ disallow_any_explicit = false
103
+
104
+ [mypy-smartbroker_plus_sdk._models.*]
105
+ disallow_any_explicit = false
106
+
107
+ [mypy-smartbroker_plus_sdk._cli._detail_renderers]
108
+ disallow_any_explicit = false
109
+
110
+ [mypy-smartbroker_plus_sdk._cli._output]
111
+ disallow_any_explicit = false
112
+
113
+ [mypy-smartbroker_plus_sdk._cli._error_handler]
114
+ disallow_any_explicit = false
115
+
116
+ [mypy-smartbroker_plus_sdk._cli._cost_report_cmd]
117
+ disallow_any_explicit = false
118
+
119
+ [tool:pytest]
120
+ timeout = 5
121
+ xfail_strict = true
122
+ norecursedirs = *.egg .eggs dist build docs .tox .git __pycache__ tools tests/assets
123
+ markers =
124
+ e2e: end-to-end tests requiring Docker (deselect by default)
125
+ sandbox_reachability: sandbox reachability tests (require .env.sandbox)
126
+ sandbox_readonly: sandbox read-only tests (require .env.sandbox)
127
+ sandbox_mutating: sandbox mutating tests (require .env.sandbox)
128
+ sandbox_pkce_roundtrip: sandbox PKCE round-trip test (interactive browser flow, opt-in only)
129
+ addopts =
130
+ --strict-markers
131
+ --strict-config
132
+ --doctest-modules
133
+ -m "not e2e"
134
+ --tb=short
135
+ --cov=src
136
+ --cov-branch
137
+ --cov-report=term-missing:skip-covered
138
+ --cov-report=html
139
+ --cov-report=xml
140
+ --cov-fail-under=90
141
+ --basetemp=./tests/test_temp
142
+
143
+ [coverage:run]
144
+
145
+ [egg_info]
146
+ tag_build =
147
+ tag_date = 0
148
+