swifttrack 0.1.3.dev33__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.
- swifttrack-0.1.3.dev33/LICENSE +21 -0
- swifttrack-0.1.3.dev33/PKG-INFO +380 -0
- swifttrack-0.1.3.dev33/README.md +336 -0
- swifttrack-0.1.3.dev33/pyproject.toml +134 -0
- swifttrack-0.1.3.dev33/setup.cfg +4 -0
- swifttrack-0.1.3.dev33/src/swifttrack/__init__.py +31 -0
- swifttrack-0.1.3.dev33/src/swifttrack/account.py +186 -0
- swifttrack-0.1.3.dev33/src/swifttrack/address.py +174 -0
- swifttrack-0.1.3.dev33/src/swifttrack/auth.py +78 -0
- swifttrack-0.1.3.dev33/src/swifttrack/client.py +229 -0
- swifttrack-0.1.3.dev33/src/swifttrack/config.py +107 -0
- swifttrack-0.1.3.dev33/src/swifttrack/exceptions.py +128 -0
- swifttrack-0.1.3.dev33/src/swifttrack/models/__init__.py +33 -0
- swifttrack-0.1.3.dev33/src/swifttrack/models/account.py +101 -0
- swifttrack-0.1.3.dev33/src/swifttrack/models/address.py +68 -0
- swifttrack-0.1.3.dev33/src/swifttrack/models/auth.py +63 -0
- swifttrack-0.1.3.dev33/src/swifttrack/models/order.py +281 -0
- swifttrack-0.1.3.dev33/src/swifttrack/order.py +223 -0
- swifttrack-0.1.3.dev33/src/swifttrack/py.typed +0 -0
- swifttrack-0.1.3.dev33/src/swifttrack/utils/__init__.py +6 -0
- swifttrack-0.1.3.dev33/src/swifttrack/utils/http_client.py +223 -0
- swifttrack-0.1.3.dev33/src/swifttrack/utils/retry.py +126 -0
- swifttrack-0.1.3.dev33/src/swifttrack.egg-info/PKG-INFO +380 -0
- swifttrack-0.1.3.dev33/src/swifttrack.egg-info/SOURCES.txt +31 -0
- swifttrack-0.1.3.dev33/src/swifttrack.egg-info/dependency_links.txt +1 -0
- swifttrack-0.1.3.dev33/src/swifttrack.egg-info/requires.txt +16 -0
- swifttrack-0.1.3.dev33/src/swifttrack.egg-info/top_level.txt +1 -0
- swifttrack-0.1.3.dev33/tests/test_account.py +283 -0
- swifttrack-0.1.3.dev33/tests/test_address.py +304 -0
- swifttrack-0.1.3.dev33/tests/test_auth.py +195 -0
- swifttrack-0.1.3.dev33/tests/test_config.py +160 -0
- swifttrack-0.1.3.dev33/tests/test_exceptions.py +129 -0
- swifttrack-0.1.3.dev33/tests/test_order.py +304 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 SwiftTrack Team
|
|
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,380 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: swifttrack
|
|
3
|
+
Version: 0.1.3.dev33
|
|
4
|
+
Summary: A Python SDK for the SwiftTrack logistics platform
|
|
5
|
+
Author-email: SwiftTrack Team <support@swifttrack.io>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/swifttrack/swifttrack-python
|
|
8
|
+
Project-URL: Documentation, https://swifttrack.readthedocs.io
|
|
9
|
+
Project-URL: Repository, https://github.com/swifttrack/swifttrack-python.git
|
|
10
|
+
Project-URL: Issues, https://github.com/swifttrack/swifttrack-python/issues
|
|
11
|
+
Keywords: swifttrack,logistics,delivery,api,sdk
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
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: Topic :: Internet :: WWW/HTTP
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: httpx>=0.24.0
|
|
29
|
+
Requires-Dist: pydantic>=2.0.0
|
|
30
|
+
Requires-Dist: pydantic[email]>=2.0.0
|
|
31
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
36
|
+
Requires-Dist: respx>=0.20.0; extra == "dev"
|
|
37
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
38
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
39
|
+
Requires-Dist: mypy>=1.5.0; extra == "dev"
|
|
40
|
+
Requires-Dist: mkdocs>=1.5.0; extra == "dev"
|
|
41
|
+
Requires-Dist: mkdocs-material>=9.0.0; extra == "dev"
|
|
42
|
+
Requires-Dist: mkdocstrings[python]>=0.22.0; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# SwiftTrack Python SDK
|
|
46
|
+
|
|
47
|
+
[](https://github.com/swifttrack/swifttrack-python/actions/workflows/ci.yml)
|
|
48
|
+
[](https://pypi.org/project/swifttrack/)
|
|
49
|
+
[](https://pypi.org/project/swifttrack/)
|
|
50
|
+
[](LICENSE)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install swifttrack
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
A production-grade Python SDK for the **SwiftTrack** logistics platform. This SDK provides a clean, developer-friendly interface to interact with the SwiftTrack API for managing deliveries, addresses, orders, and accounts.
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- **Full API Coverage**: Auth, Address, Order, and Account management
|
|
61
|
+
- **Type-Safe**: Full type hints with Pydantic models
|
|
62
|
+
- **Robust Error Handling**: Structured exceptions for all error cases
|
|
63
|
+
- **Retry Logic**: Automatic retries with exponential backoff
|
|
64
|
+
- **Authentication**: Simple token-based authentication
|
|
65
|
+
- **Modern Python**: Supports Python 3.9+
|
|
66
|
+
- **Production Ready**: Industry-standard patterns and best practices
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install swifttrack
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from swifttrack import SwiftTrackClient
|
|
78
|
+
|
|
79
|
+
# Initialize client
|
|
80
|
+
client = SwiftTrackClient()
|
|
81
|
+
|
|
82
|
+
# Authenticate
|
|
83
|
+
client.login("your@email.com", "password")
|
|
84
|
+
|
|
85
|
+
# Use the API
|
|
86
|
+
addresses = client.addresses.list_addresses()
|
|
87
|
+
print(f"You have {len(addresses)} saved addresses")
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Authentication
|
|
91
|
+
|
|
92
|
+
### Login with Email/Password
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from swifttrack import SwiftTrackClient
|
|
96
|
+
|
|
97
|
+
client = SwiftTrackClient()
|
|
98
|
+
response = client.login("user@example.com", "password")
|
|
99
|
+
print(f"Logged in! Token: {response.access_token}")
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Using Existing Token
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from swifttrack import SwiftTrackClient
|
|
106
|
+
|
|
107
|
+
# If you already have a token
|
|
108
|
+
client = SwiftTrackClient(token="your-jwt-token")
|
|
109
|
+
# or
|
|
110
|
+
client = SwiftTrackClient()
|
|
111
|
+
client.set_token("your-jwt-token")
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Address Management
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
from swifttrack.models.address import AddressRequest
|
|
118
|
+
|
|
119
|
+
# List all addresses
|
|
120
|
+
addresses = client.addresses.list_addresses()
|
|
121
|
+
for addr in addresses:
|
|
122
|
+
print(f"{addr.label}: {addr.line1}, {addr.city}")
|
|
123
|
+
|
|
124
|
+
# Get default address
|
|
125
|
+
default = client.addresses.get_default_address()
|
|
126
|
+
|
|
127
|
+
# Create new address
|
|
128
|
+
new_address = AddressRequest(
|
|
129
|
+
label="Office",
|
|
130
|
+
line1="456 Business Park",
|
|
131
|
+
city="Bangalore",
|
|
132
|
+
state="Karnataka",
|
|
133
|
+
pincode="560001",
|
|
134
|
+
latitude=12.9716,
|
|
135
|
+
longitude=77.5946,
|
|
136
|
+
)
|
|
137
|
+
created = client.addresses.create_address(new_address)
|
|
138
|
+
print(f"Created address: {created.id}")
|
|
139
|
+
|
|
140
|
+
# Set as default
|
|
141
|
+
client.addresses.set_default(created.id)
|
|
142
|
+
|
|
143
|
+
# Update address
|
|
144
|
+
updated = client.addresses.update_address(created.id, AddressRequest(
|
|
145
|
+
label="Updated Office",
|
|
146
|
+
line1="789 New Business Park",
|
|
147
|
+
city="Bangalore",
|
|
148
|
+
state="Karnataka",
|
|
149
|
+
pincode="560001",
|
|
150
|
+
))
|
|
151
|
+
|
|
152
|
+
# Delete address
|
|
153
|
+
client.addresses.delete_address(created.id)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Order Management
|
|
157
|
+
|
|
158
|
+
### Get Delivery Quote
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from uuid import UUID
|
|
162
|
+
|
|
163
|
+
# Get quote for delivery
|
|
164
|
+
pickup_address_id = UUID("your-address-id")
|
|
165
|
+
quote = client.orders.get_quote(
|
|
166
|
+
pickup_address_id=pickup_address_id,
|
|
167
|
+
dropoff_lat=19.0760,
|
|
168
|
+
dropoff_lng=72.8777,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# View available options
|
|
172
|
+
for option in quote.quotes:
|
|
173
|
+
print(f"{option.provider_name}: ₹{option.price} ({option.estimated_delivery_time})")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Create Order
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
from swifttrack.models.order import CreateOrderRequest, LocationPoint
|
|
180
|
+
from uuid import UUID
|
|
181
|
+
|
|
182
|
+
# Create order request
|
|
183
|
+
order_request = CreateOrderRequest(
|
|
184
|
+
idempotency_key="unique-key-123", # Prevent duplicate orders
|
|
185
|
+
pickup_address_id=UUID("pickup-address-id"),
|
|
186
|
+
dropoff=LocationPoint(
|
|
187
|
+
latitude=19.0760,
|
|
188
|
+
longitude=72.8777,
|
|
189
|
+
address="456 Dropoff Street, Mumbai",
|
|
190
|
+
),
|
|
191
|
+
order_reference="MY-ORDER-001",
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
# Create the order
|
|
195
|
+
order = client.orders.create_order(order_request, quote.quote_session_id)
|
|
196
|
+
print(f"Order created: {order.order_number}")
|
|
197
|
+
print(f"Tracking URL: {order.tracking_url}")
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Cancel Order
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
# Cancel an order
|
|
204
|
+
result = client.orders.cancel_order(
|
|
205
|
+
order_id=UUID("order-id"),
|
|
206
|
+
reason="Customer requested cancellation"
|
|
207
|
+
)
|
|
208
|
+
print(result["message"])
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Get Order Details
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
# Get order status
|
|
215
|
+
status = client.orders.get_order_status(order_id)
|
|
216
|
+
print(f"Order status: {status}")
|
|
217
|
+
|
|
218
|
+
# Get full order details
|
|
219
|
+
order = client.orders.get_order(order_id)
|
|
220
|
+
print(f"Order: {order.order_number}")
|
|
221
|
+
print(f"Status: {order.status}")
|
|
222
|
+
print(f"Price: ₹{order.price}")
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Guest Quotes (No Auth Required)
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
# Get a quote without authentication
|
|
229
|
+
guest_quote = client.orders.get_guest_quote(
|
|
230
|
+
pickup_lat=19.0760,
|
|
231
|
+
pickup_lng=72.8777,
|
|
232
|
+
pickup_address="123 Pickup St, Mumbai",
|
|
233
|
+
dropoff_lat=19.2183,
|
|
234
|
+
dropoff_lng=72.9781,
|
|
235
|
+
dropoff_address="456 Dropoff St, Mumbai",
|
|
236
|
+
package_weight_kg=2.5,
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
for option in guest_quote.options:
|
|
240
|
+
print(f"{option.provider_name}: ₹{option.price}")
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Account Management
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
from swifttrack.models.account import AccountType
|
|
247
|
+
|
|
248
|
+
# Get your account
|
|
249
|
+
account = client.accounts.get_my_account(user_id)
|
|
250
|
+
print(f"Balance: ₹{account.balance}")
|
|
251
|
+
|
|
252
|
+
# Get transaction history
|
|
253
|
+
transactions = client.accounts.get_transactions(account.id, limit=10)
|
|
254
|
+
for txn in transactions:
|
|
255
|
+
print(f"{txn.transaction_type}: ₹{txn.amount} - {txn.description}")
|
|
256
|
+
|
|
257
|
+
# Create new account (for providers/drivers)
|
|
258
|
+
new_account = client.accounts.create_account(
|
|
259
|
+
user_id=user_id,
|
|
260
|
+
account_type=AccountType.PROVIDER,
|
|
261
|
+
)
|
|
262
|
+
|
|
263
|
+
# Reconcile account balance
|
|
264
|
+
result = client.accounts.reconcile_balance(account.id)
|
|
265
|
+
print(result)
|
|
266
|
+
|
|
267
|
+
# Admin: Top up wallet (requires admin permissions)
|
|
268
|
+
updated = client.accounts.top_up_wallet(
|
|
269
|
+
user_id=user_id,
|
|
270
|
+
amount=1000.00,
|
|
271
|
+
reference="TXN-REF-123",
|
|
272
|
+
)
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Error Handling
|
|
276
|
+
|
|
277
|
+
The SDK provides structured exceptions for different error scenarios:
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
from swifttrack import (
|
|
281
|
+
SwiftTrackClient,
|
|
282
|
+
AuthenticationError,
|
|
283
|
+
NotFoundError,
|
|
284
|
+
ValidationError,
|
|
285
|
+
RateLimitError,
|
|
286
|
+
ServerError,
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
client = SwiftTrackClient()
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
client.login("user@example.com", "wrong-password")
|
|
293
|
+
except AuthenticationError as e:
|
|
294
|
+
print(f"Login failed: {e.message}")
|
|
295
|
+
|
|
296
|
+
try:
|
|
297
|
+
client.addresses.get_address("non-existent-id")
|
|
298
|
+
except NotFoundError as e:
|
|
299
|
+
print(f"Address not found: {e.message}")
|
|
300
|
+
|
|
301
|
+
try:
|
|
302
|
+
# Invalid coordinates
|
|
303
|
+
client.orders.get_quote(address_id, 200, 72) # Invalid latitude
|
|
304
|
+
except ValidationError as e:
|
|
305
|
+
print(f"Validation error: {e.errors}")
|
|
306
|
+
|
|
307
|
+
try:
|
|
308
|
+
# API temporarily unavailable
|
|
309
|
+
client.orders.get_order(order_id)
|
|
310
|
+
except ServerError as e:
|
|
311
|
+
print(f"Server error: {e.message} (status: {e.status_code})")
|
|
312
|
+
|
|
313
|
+
try:
|
|
314
|
+
# Rate limited
|
|
315
|
+
client.addresses.list_addresses()
|
|
316
|
+
except RateLimitError as e:
|
|
317
|
+
print(f"Rate limited. Retry after: {e.retry_after} seconds")
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Configuration
|
|
321
|
+
|
|
322
|
+
### Custom Configuration
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
from swifttrack import SwiftTrackClient, SwiftTrackConfig
|
|
326
|
+
|
|
327
|
+
# Create custom config
|
|
328
|
+
config = SwiftTrackConfig(
|
|
329
|
+
base_url="https://custom-api.example.com",
|
|
330
|
+
token="your-token",
|
|
331
|
+
timeout=60.0, # Request timeout
|
|
332
|
+
max_retries=5, # Max retry attempts
|
|
333
|
+
retry_delay=2.0, # Initial retry delay
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
client = SwiftTrackClient(config=config)
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Context Manager
|
|
340
|
+
|
|
341
|
+
The client can be used as a context manager for automatic cleanup:
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
from swifttrack import SwiftTrackClient
|
|
345
|
+
|
|
346
|
+
with SwiftTrackClient() as client:
|
|
347
|
+
client.login("user@example.com", "password")
|
|
348
|
+
addresses = client.addresses.list_addresses()
|
|
349
|
+
# Client automatically closed when exiting context
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Logging
|
|
353
|
+
|
|
354
|
+
The SDK uses Python's standard logging. Enable debug logging to see request details:
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
import logging
|
|
358
|
+
|
|
359
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
360
|
+
logging.getLogger("swifttrack").setLevel(logging.DEBUG)
|
|
361
|
+
|
|
362
|
+
client = SwiftTrackClient()
|
|
363
|
+
# Now you'll see detailed request/response logs
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## API Reference
|
|
367
|
+
|
|
368
|
+
See the full [API documentation](https://swifttrack.readthedocs.io) for detailed reference.
|
|
369
|
+
|
|
370
|
+
## Contributing
|
|
371
|
+
|
|
372
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
373
|
+
|
|
374
|
+
## License
|
|
375
|
+
|
|
376
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
Made with ❤️ by the SwiftTrack Team
|