bookalimo 1.0.0__tar.gz → 1.0.2__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.
- bookalimo-1.0.2/LICENSE +21 -0
- bookalimo-1.0.2/PKG-INFO +245 -0
- bookalimo-1.0.2/README.md +183 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/pyproject.toml +7 -3
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/client.py +45 -22
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/config.py +1 -1
- bookalimo-1.0.2/src/bookalimo/integrations/google_places/client_async.py +243 -0
- bookalimo-1.0.2/src/bookalimo/integrations/google_places/client_sync.py +243 -0
- bookalimo-1.0.2/src/bookalimo/integrations/google_places/common.py +509 -0
- bookalimo-1.0.2/src/bookalimo/integrations/google_places/resolve_airport.py +426 -0
- bookalimo-1.0.2/src/bookalimo/integrations/google_places/transports.py +105 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/logging.py +103 -0
- bookalimo-1.0.2/src/bookalimo/schemas/__init__.py +189 -0
- bookalimo-1.0.2/src/bookalimo/schemas/base.py +116 -0
- bookalimo-1.0.2/src/bookalimo/schemas/places/__init__.py +64 -0
- bookalimo-1.0.2/src/bookalimo/schemas/places/common.py +351 -0
- bookalimo-1.0.2/src/bookalimo/schemas/places/field_mask.py +212 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/schemas/places/google.py +458 -16
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/schemas/places/place.py +25 -28
- bookalimo-1.0.2/src/bookalimo/schemas/requests.py +214 -0
- bookalimo-1.0.2/src/bookalimo/schemas/responses.py +196 -0
- bookalimo-1.0.0/src/bookalimo/schemas/booking.py → bookalimo-1.0.2/src/bookalimo/schemas/shared.py +55 -218
- bookalimo-1.0.2/src/bookalimo/services/pricing.py +71 -0
- bookalimo-1.0.2/src/bookalimo/services/reservations.py +137 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/transport/auth.py +2 -2
- bookalimo-1.0.2/src/bookalimo/transport/httpx_async.py +146 -0
- bookalimo-1.0.2/src/bookalimo/transport/httpx_sync.py +151 -0
- bookalimo-1.0.2/src/bookalimo/transport/utils.py +260 -0
- bookalimo-1.0.2/src/bookalimo.egg-info/PKG-INFO +245 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo.egg-info/SOURCES.txt +6 -1
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo.egg-info/requires.txt +5 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/tests/test_client.py +6 -6
- {bookalimo-1.0.0 → bookalimo-1.0.2}/tests/test_google_places.py +204 -119
- {bookalimo-1.0.0 → bookalimo-1.0.2}/tests/test_integration.py +117 -81
- {bookalimo-1.0.0 → bookalimo-1.0.2}/tests/test_real_api_integration.py +110 -68
- {bookalimo-1.0.0 → bookalimo-1.0.2}/tests/test_schemas.py +11 -12
- bookalimo-1.0.2/tests/test_services.py +620 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/tests/test_transport.py +5 -6
- bookalimo-1.0.0/LICENSE +0 -0
- bookalimo-1.0.0/PKG-INFO +0 -307
- bookalimo-1.0.0/README.md +0 -249
- bookalimo-1.0.0/src/bookalimo/integrations/google_places/client_async.py +0 -258
- bookalimo-1.0.0/src/bookalimo/integrations/google_places/client_sync.py +0 -257
- bookalimo-1.0.0/src/bookalimo/integrations/google_places/common.py +0 -245
- bookalimo-1.0.0/src/bookalimo/schemas/__init__.py +0 -97
- bookalimo-1.0.0/src/bookalimo/schemas/base.py +0 -56
- bookalimo-1.0.0/src/bookalimo/schemas/places/__init__.py +0 -37
- bookalimo-1.0.0/src/bookalimo/schemas/places/common.py +0 -198
- bookalimo-1.0.0/src/bookalimo/services/pricing.py +0 -191
- bookalimo-1.0.0/src/bookalimo/services/reservations.py +0 -227
- bookalimo-1.0.0/src/bookalimo/transport/httpx_async.py +0 -230
- bookalimo-1.0.0/src/bookalimo/transport/httpx_sync.py +0 -230
- bookalimo-1.0.0/src/bookalimo/transport/utils.py +0 -59
- bookalimo-1.0.0/src/bookalimo.egg-info/PKG-INFO +0 -307
- bookalimo-1.0.0/tests/test_services.py +0 -495
- {bookalimo-1.0.0 → bookalimo-1.0.2}/setup.cfg +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/__init__.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/_version.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/exceptions.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/integrations/__init__.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/integrations/google_places/__init__.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/integrations/google_places/proto_adapter.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/py.typed +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/services/__init__.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/transport/__init__.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/transport/base.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo/transport/retry.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo.egg-info/dependency_links.txt +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/src/bookalimo.egg-info/top_level.txt +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/tests/test_config.py +0 -0
- {bookalimo-1.0.0 → bookalimo-1.0.2}/tests/test_exceptions.py +0 -0
bookalimo-1.0.2/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Jonathan Oren
|
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.
|
bookalimo-1.0.2/PKG-INFO
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: bookalimo
|
3
|
+
Version: 1.0.2
|
4
|
+
Summary: Python wrapper for the Book-A-Limo API
|
5
|
+
Author-email: Jonathan Oren <jonathan@bookalimo.com>
|
6
|
+
Maintainer-email: Jonathan Oren <jonathan@bookalimo.com>
|
7
|
+
License: MIT
|
8
|
+
Project-URL: Homepage, https://github.com/asparagusbeef/bookalimo-python
|
9
|
+
Project-URL: Documentation, https://asparagusbeef.github.io/bookalimo-python
|
10
|
+
Project-URL: Repository, https://github.com/asparagusbeef/bookalimo-python
|
11
|
+
Project-URL: Issues, https://github.com/asparagusbeef/bookalimo-python/issues
|
12
|
+
Project-URL: Changelog, https://github.com/asparagusbeef/bookalimo-python/blob/main/CHANGELOG.md
|
13
|
+
Keywords: bookalimo,api,transportation,booking
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
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.9
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
25
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
26
|
+
Requires-Python: >=3.9
|
27
|
+
Description-Content-Type: text/markdown
|
28
|
+
License-File: LICENSE
|
29
|
+
Requires-Dist: httpx>=0.25.0
|
30
|
+
Requires-Dist: pydantic>=2.11.0
|
31
|
+
Requires-Dist: pycountry>=22.0.0
|
32
|
+
Requires-Dist: us>=3.0.0
|
33
|
+
Requires-Dist: airportsdata>=20230101
|
34
|
+
Provides-Extra: places
|
35
|
+
Requires-Dist: google-maps-places>=0.1.0; extra == "places"
|
36
|
+
Requires-Dist: google-api-core>=2.0.0; extra == "places"
|
37
|
+
Requires-Dist: numpy>=2.0.0; extra == "places"
|
38
|
+
Requires-Dist: rapidfuzz>=3.0.0; extra == "places"
|
39
|
+
Requires-Dist: typing-extensions>=4.15.0; python_version < "3.11" and extra == "places"
|
40
|
+
Provides-Extra: dev
|
41
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
42
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
43
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
44
|
+
Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
|
45
|
+
Requires-Dist: httpx[mock]>=0.25.0; extra == "dev"
|
46
|
+
Requires-Dist: respx>=0.20.0; extra == "dev"
|
47
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
48
|
+
Requires-Dist: mypy>=1.5.0; extra == "dev"
|
49
|
+
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
|
50
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
51
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
52
|
+
Requires-Dist: python-dotenv>=1.0.0; extra == "dev"
|
53
|
+
Requires-Dist: types-protobuf>=6.0.0; extra == "dev"
|
54
|
+
Provides-Extra: test
|
55
|
+
Requires-Dist: pytest>=7.0.0; extra == "test"
|
56
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "test"
|
57
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
58
|
+
Requires-Dist: pytest-mock>=3.10.0; extra == "test"
|
59
|
+
Requires-Dist: httpx[mock]>=0.25.0; extra == "test"
|
60
|
+
Requires-Dist: respx>=0.20.0; extra == "test"
|
61
|
+
Dynamic: license-file
|
62
|
+
|
63
|
+
# Bookalimo Python SDK
|
64
|
+
|
65
|
+
[](https://codecov.io/gh/asparagusbeef/bookalimo-python)
|
66
|
+
[](https://asparagusbeef.github.io/bookalimo-python)
|
67
|
+
[](https://badge.fury.io/py/bookalimo)
|
68
|
+
[](https://pypi.org/project/bookalimo/)
|
69
|
+
[](https://opensource.org/licenses/MIT)
|
70
|
+
[](https://github.com/astral-sh/ruff)
|
71
|
+
|
72
|
+
Python client library for the Book-A-Limo transportation booking API with async/sync support, type safety, and Google Places integration.
|
73
|
+
|
74
|
+
## Design philosophy: IDE-first DX
|
75
|
+
|
76
|
+
The library is **comprehensively typed** and **richly documented** via docstrings. Most users can rely on IDE hints, docstrings, and autocomplete without reading the docs.
|
77
|
+
|
78
|
+
## Features
|
79
|
+
|
80
|
+
- **Async & Sync Support** – `AsyncBookalimo` and `Bookalimo` clients
|
81
|
+
- **Type Safety** – Full Pydantic models with validation
|
82
|
+
- **Google Places Integration** – Location search and geocoding
|
83
|
+
- **Automatic Retry** – Built-in exponential backoff
|
84
|
+
- **Resource Management** – Context managers for proper cleanup
|
85
|
+
|
86
|
+
## Installation
|
87
|
+
|
88
|
+
```bash
|
89
|
+
pip install bookalimo
|
90
|
+
|
91
|
+
# With Google Places integration
|
92
|
+
pip install bookalimo[places]
|
93
|
+
```
|
94
|
+
|
95
|
+
## Quick Example
|
96
|
+
|
97
|
+
```python
|
98
|
+
import asyncio
|
99
|
+
from bookalimo import (
|
100
|
+
AsyncBookalimo,
|
101
|
+
)
|
102
|
+
from bookalimo.transport.auth import (
|
103
|
+
Credentials,
|
104
|
+
)
|
105
|
+
from bookalimo.schemas import (
|
106
|
+
RateType,
|
107
|
+
Location,
|
108
|
+
LocationType,
|
109
|
+
Address,
|
110
|
+
City,
|
111
|
+
Airport,
|
112
|
+
PriceRequest,
|
113
|
+
BookRequest,
|
114
|
+
)
|
115
|
+
|
116
|
+
|
117
|
+
async def book_ride():
|
118
|
+
credentials = Credentials.create(
|
119
|
+
"your_id",
|
120
|
+
"your_password",
|
121
|
+
is_customer=False,
|
122
|
+
)
|
123
|
+
|
124
|
+
pickup = Location(
|
125
|
+
type=LocationType.ADDRESS,
|
126
|
+
address=Address(
|
127
|
+
place_name="Empire State Building",
|
128
|
+
city=City(
|
129
|
+
city_name="New York",
|
130
|
+
country_code="US",
|
131
|
+
state_code="NY",
|
132
|
+
),
|
133
|
+
),
|
134
|
+
)
|
135
|
+
dropoff = Location(
|
136
|
+
type=LocationType.AIRPORT,
|
137
|
+
airport=Airport(iata_code="JFK"),
|
138
|
+
)
|
139
|
+
|
140
|
+
async with AsyncBookalimo(credentials=credentials) as client:
|
141
|
+
# Get pricing
|
142
|
+
quote = await client.pricing.quote(
|
143
|
+
PriceRequest(
|
144
|
+
rate_type=RateType.P2P,
|
145
|
+
date_time="12/25/2024 03:00 PM",
|
146
|
+
pickup=pickup,
|
147
|
+
dropoff=dropoff,
|
148
|
+
passengers=2,
|
149
|
+
luggage=2,
|
150
|
+
)
|
151
|
+
)
|
152
|
+
|
153
|
+
# Book reservation
|
154
|
+
booking = await client.reservations.book(
|
155
|
+
BookRequest(
|
156
|
+
token=quote.token,
|
157
|
+
method="charge",
|
158
|
+
)
|
159
|
+
)
|
160
|
+
return booking.reservation_id
|
161
|
+
|
162
|
+
|
163
|
+
confirmation = asyncio.run(book_ride())
|
164
|
+
```
|
165
|
+
|
166
|
+
## Sync Usage
|
167
|
+
|
168
|
+
```python
|
169
|
+
from bookalimo import (
|
170
|
+
Bookalimo,
|
171
|
+
)
|
172
|
+
|
173
|
+
with Bookalimo(credentials=credentials) as client:
|
174
|
+
quote = client.pricing.quote(PriceRequest(...))
|
175
|
+
booking = client.reservations.book(
|
176
|
+
BookRequest(
|
177
|
+
token=quote.token,
|
178
|
+
method="charge",
|
179
|
+
)
|
180
|
+
)
|
181
|
+
```
|
182
|
+
|
183
|
+
## Google Places Integration
|
184
|
+
|
185
|
+
```python
|
186
|
+
async with AsyncBookalimo(
|
187
|
+
credentials=credentials,
|
188
|
+
google_places_api_key="your-google-places-key",
|
189
|
+
) as client:
|
190
|
+
# Search locations
|
191
|
+
results = await client.places.search("Hilton Miami Beach")
|
192
|
+
|
193
|
+
# Resolve airports near landmarks
|
194
|
+
airports = await client.places.resolve_airport(query="eiffel tower")
|
195
|
+
top_airport = airports[0] # Closest airport with confidence scoring
|
196
|
+
|
197
|
+
# Use in booking flow
|
198
|
+
quote = await client.pricing.quote(...)
|
199
|
+
```
|
200
|
+
|
201
|
+
## Error Handling
|
202
|
+
|
203
|
+
```python
|
204
|
+
from bookalimo.exceptions import (
|
205
|
+
BookalimoHTTPError,
|
206
|
+
BookalimoValidationError,
|
207
|
+
)
|
208
|
+
|
209
|
+
try:
|
210
|
+
booking = await client.reservations.book(...)
|
211
|
+
except BookalimoValidationError as e:
|
212
|
+
print(f"Invalid input: {e.message}")
|
213
|
+
except BookalimoHTTPError as e:
|
214
|
+
if e.status_code == 401:
|
215
|
+
print("Authentication failed")
|
216
|
+
```
|
217
|
+
|
218
|
+
## Environment
|
219
|
+
|
220
|
+
```bash
|
221
|
+
export GOOGLE_PLACES_API_KEY="your_google_places_key"
|
222
|
+
export BOOKALIMO_LOG_LEVEL="DEBUG"
|
223
|
+
```
|
224
|
+
|
225
|
+
## Documentation
|
226
|
+
|
227
|
+
**📖 Complete Documentation:** [https://asparagusbeef.github.io/bookalimo-python](https://asparagusbeef.github.io/bookalimo-python)
|
228
|
+
|
229
|
+
## Requirements
|
230
|
+
|
231
|
+
* Python 3.9+
|
232
|
+
* Book-A-Limo API credentials
|
233
|
+
* Dependencies: httpx, pydantic, pycountry, us, airportsdata, typing-extensions for Python 3.9-3.10
|
234
|
+
- Optional: google-maps-places, google-api-core, numpy, rapidfuzz
|
235
|
+
|
236
|
+
## Support & Resources
|
237
|
+
|
238
|
+
* GitHub: [https://github.com/asparagusbeef/bookalimo-python](https://github.com/asparagusbeef/bookalimo-python)
|
239
|
+
* PyPI: [https://pypi.org/project/bookalimo/](https://pypi.org/project/bookalimo/)
|
240
|
+
* Issues: [https://github.com/asparagusbeef/bookalimo-python/issues](https://github.com/asparagusbeef/bookalimo-python/issues)
|
241
|
+
* Changelog: [CHANGELOG.md](./CHANGELOG.md)
|
242
|
+
|
243
|
+
## License
|
244
|
+
|
245
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# Bookalimo Python SDK
|
2
|
+
|
3
|
+
[](https://codecov.io/gh/asparagusbeef/bookalimo-python)
|
4
|
+
[](https://asparagusbeef.github.io/bookalimo-python)
|
5
|
+
[](https://badge.fury.io/py/bookalimo)
|
6
|
+
[](https://pypi.org/project/bookalimo/)
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
8
|
+
[](https://github.com/astral-sh/ruff)
|
9
|
+
|
10
|
+
Python client library for the Book-A-Limo transportation booking API with async/sync support, type safety, and Google Places integration.
|
11
|
+
|
12
|
+
## Design philosophy: IDE-first DX
|
13
|
+
|
14
|
+
The library is **comprehensively typed** and **richly documented** via docstrings. Most users can rely on IDE hints, docstrings, and autocomplete without reading the docs.
|
15
|
+
|
16
|
+
## Features
|
17
|
+
|
18
|
+
- **Async & Sync Support** – `AsyncBookalimo` and `Bookalimo` clients
|
19
|
+
- **Type Safety** – Full Pydantic models with validation
|
20
|
+
- **Google Places Integration** – Location search and geocoding
|
21
|
+
- **Automatic Retry** – Built-in exponential backoff
|
22
|
+
- **Resource Management** – Context managers for proper cleanup
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
```bash
|
27
|
+
pip install bookalimo
|
28
|
+
|
29
|
+
# With Google Places integration
|
30
|
+
pip install bookalimo[places]
|
31
|
+
```
|
32
|
+
|
33
|
+
## Quick Example
|
34
|
+
|
35
|
+
```python
|
36
|
+
import asyncio
|
37
|
+
from bookalimo import (
|
38
|
+
AsyncBookalimo,
|
39
|
+
)
|
40
|
+
from bookalimo.transport.auth import (
|
41
|
+
Credentials,
|
42
|
+
)
|
43
|
+
from bookalimo.schemas import (
|
44
|
+
RateType,
|
45
|
+
Location,
|
46
|
+
LocationType,
|
47
|
+
Address,
|
48
|
+
City,
|
49
|
+
Airport,
|
50
|
+
PriceRequest,
|
51
|
+
BookRequest,
|
52
|
+
)
|
53
|
+
|
54
|
+
|
55
|
+
async def book_ride():
|
56
|
+
credentials = Credentials.create(
|
57
|
+
"your_id",
|
58
|
+
"your_password",
|
59
|
+
is_customer=False,
|
60
|
+
)
|
61
|
+
|
62
|
+
pickup = Location(
|
63
|
+
type=LocationType.ADDRESS,
|
64
|
+
address=Address(
|
65
|
+
place_name="Empire State Building",
|
66
|
+
city=City(
|
67
|
+
city_name="New York",
|
68
|
+
country_code="US",
|
69
|
+
state_code="NY",
|
70
|
+
),
|
71
|
+
),
|
72
|
+
)
|
73
|
+
dropoff = Location(
|
74
|
+
type=LocationType.AIRPORT,
|
75
|
+
airport=Airport(iata_code="JFK"),
|
76
|
+
)
|
77
|
+
|
78
|
+
async with AsyncBookalimo(credentials=credentials) as client:
|
79
|
+
# Get pricing
|
80
|
+
quote = await client.pricing.quote(
|
81
|
+
PriceRequest(
|
82
|
+
rate_type=RateType.P2P,
|
83
|
+
date_time="12/25/2024 03:00 PM",
|
84
|
+
pickup=pickup,
|
85
|
+
dropoff=dropoff,
|
86
|
+
passengers=2,
|
87
|
+
luggage=2,
|
88
|
+
)
|
89
|
+
)
|
90
|
+
|
91
|
+
# Book reservation
|
92
|
+
booking = await client.reservations.book(
|
93
|
+
BookRequest(
|
94
|
+
token=quote.token,
|
95
|
+
method="charge",
|
96
|
+
)
|
97
|
+
)
|
98
|
+
return booking.reservation_id
|
99
|
+
|
100
|
+
|
101
|
+
confirmation = asyncio.run(book_ride())
|
102
|
+
```
|
103
|
+
|
104
|
+
## Sync Usage
|
105
|
+
|
106
|
+
```python
|
107
|
+
from bookalimo import (
|
108
|
+
Bookalimo,
|
109
|
+
)
|
110
|
+
|
111
|
+
with Bookalimo(credentials=credentials) as client:
|
112
|
+
quote = client.pricing.quote(PriceRequest(...))
|
113
|
+
booking = client.reservations.book(
|
114
|
+
BookRequest(
|
115
|
+
token=quote.token,
|
116
|
+
method="charge",
|
117
|
+
)
|
118
|
+
)
|
119
|
+
```
|
120
|
+
|
121
|
+
## Google Places Integration
|
122
|
+
|
123
|
+
```python
|
124
|
+
async with AsyncBookalimo(
|
125
|
+
credentials=credentials,
|
126
|
+
google_places_api_key="your-google-places-key",
|
127
|
+
) as client:
|
128
|
+
# Search locations
|
129
|
+
results = await client.places.search("Hilton Miami Beach")
|
130
|
+
|
131
|
+
# Resolve airports near landmarks
|
132
|
+
airports = await client.places.resolve_airport(query="eiffel tower")
|
133
|
+
top_airport = airports[0] # Closest airport with confidence scoring
|
134
|
+
|
135
|
+
# Use in booking flow
|
136
|
+
quote = await client.pricing.quote(...)
|
137
|
+
```
|
138
|
+
|
139
|
+
## Error Handling
|
140
|
+
|
141
|
+
```python
|
142
|
+
from bookalimo.exceptions import (
|
143
|
+
BookalimoHTTPError,
|
144
|
+
BookalimoValidationError,
|
145
|
+
)
|
146
|
+
|
147
|
+
try:
|
148
|
+
booking = await client.reservations.book(...)
|
149
|
+
except BookalimoValidationError as e:
|
150
|
+
print(f"Invalid input: {e.message}")
|
151
|
+
except BookalimoHTTPError as e:
|
152
|
+
if e.status_code == 401:
|
153
|
+
print("Authentication failed")
|
154
|
+
```
|
155
|
+
|
156
|
+
## Environment
|
157
|
+
|
158
|
+
```bash
|
159
|
+
export GOOGLE_PLACES_API_KEY="your_google_places_key"
|
160
|
+
export BOOKALIMO_LOG_LEVEL="DEBUG"
|
161
|
+
```
|
162
|
+
|
163
|
+
## Documentation
|
164
|
+
|
165
|
+
**📖 Complete Documentation:** [https://asparagusbeef.github.io/bookalimo-python](https://asparagusbeef.github.io/bookalimo-python)
|
166
|
+
|
167
|
+
## Requirements
|
168
|
+
|
169
|
+
* Python 3.9+
|
170
|
+
* Book-A-Limo API credentials
|
171
|
+
* Dependencies: httpx, pydantic, pycountry, us, airportsdata, typing-extensions for Python 3.9-3.10
|
172
|
+
- Optional: google-maps-places, google-api-core, numpy, rapidfuzz
|
173
|
+
|
174
|
+
## Support & Resources
|
175
|
+
|
176
|
+
* GitHub: [https://github.com/asparagusbeef/bookalimo-python](https://github.com/asparagusbeef/bookalimo-python)
|
177
|
+
* PyPI: [https://pypi.org/project/bookalimo/](https://pypi.org/project/bookalimo/)
|
178
|
+
* Issues: [https://github.com/asparagusbeef/bookalimo-python/issues](https://github.com/asparagusbeef/bookalimo-python/issues)
|
179
|
+
* Changelog: [CHANGELOG.md](./CHANGELOG.md)
|
180
|
+
|
181
|
+
## License
|
182
|
+
|
183
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "bookalimo"
|
7
|
-
version = "1.0.
|
7
|
+
version = "1.0.2"
|
8
8
|
description = "Python wrapper for the Book-A-Limo API"
|
9
9
|
readme = "README.md"
|
10
10
|
license = {text = "MIT"}
|
@@ -24,6 +24,7 @@ classifiers = [
|
|
24
24
|
"Programming Language :: Python :: 3.10",
|
25
25
|
"Programming Language :: Python :: 3.11",
|
26
26
|
"Programming Language :: Python :: 3.12",
|
27
|
+
"Programming Language :: Python :: 3.13",
|
27
28
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
28
29
|
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
29
30
|
]
|
@@ -41,6 +42,9 @@ requires-python = ">=3.9"
|
|
41
42
|
places = [
|
42
43
|
"google-maps-places>=0.1.0",
|
43
44
|
"google-api-core>=2.0.0",
|
45
|
+
"numpy>=2.0.0",
|
46
|
+
"rapidfuzz>=3.0.0",
|
47
|
+
"typing-extensions>=4.15.0; python_version < '3.11'"
|
44
48
|
]
|
45
49
|
dev = [
|
46
50
|
"pytest>=7.0.0",
|
@@ -93,7 +97,7 @@ lint.select = [
|
|
93
97
|
"UP", # pyupgrade
|
94
98
|
]
|
95
99
|
lint.ignore = [
|
96
|
-
"E501", # line too long, handled by
|
100
|
+
"E501", # line too long, handled by ruff-format
|
97
101
|
"B008", # do not perform function calls in argument defaults
|
98
102
|
"C901", # too complex
|
99
103
|
"UP045", # until I have time to Optional[] -> X | None everywhere.
|
@@ -124,7 +128,7 @@ warn_return_any = true
|
|
124
128
|
warn_unreachable = true
|
125
129
|
warn_unused_configs = true
|
126
130
|
warn_unused_ignores = true
|
127
|
-
mypy_path = "stubs"
|
131
|
+
mypy_path = "src:stubs"
|
128
132
|
disable_error_code = ["prop-decorator"]
|
129
133
|
|
130
134
|
[[tool.mypy.overrides]]
|
@@ -59,7 +59,7 @@ class AsyncBookalimo:
|
|
59
59
|
google_places_api_key="your-google-api-key"
|
60
60
|
) as client:
|
61
61
|
# Find locations using Google Places
|
62
|
-
places = await client.places.
|
62
|
+
places = await client.places.search("Empire State Building")
|
63
63
|
|
64
64
|
# Use in booking
|
65
65
|
quote = await client.pricing.quote(
|
@@ -93,8 +93,7 @@ class AsyncBookalimo:
|
|
93
93
|
transport: Custom transport instance (optional)
|
94
94
|
google_places_api_key: Google Places API key for location services (optional)
|
95
95
|
"""
|
96
|
-
|
97
|
-
transport_credentials = transport.credentials if transport else None
|
96
|
+
transport_credentials = transport._credentials if transport else None
|
98
97
|
|
99
98
|
both_provided = all([transport_credentials, credentials])
|
100
99
|
both_missing = not any([transport_credentials, credentials])
|
@@ -113,18 +112,21 @@ class AsyncBookalimo:
|
|
113
112
|
stacklevel=2,
|
114
113
|
)
|
115
114
|
|
116
|
-
# Use whichever exists when we need to build a transport ourselves
|
117
115
|
effective_credentials = (
|
118
|
-
|
116
|
+
transport_credentials if transport_credentials is not None else credentials
|
119
117
|
)
|
118
|
+
|
120
119
|
if transport:
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
120
|
+
if transport_credentials is None and credentials is not None:
|
121
|
+
transport.credentials = credentials
|
122
|
+
self._transport = transport
|
123
|
+
else:
|
124
|
+
self._transport = AsyncTransport(
|
125
|
+
base_url=base_url,
|
126
|
+
timeouts=timeouts,
|
127
|
+
user_agent=user_agent,
|
128
|
+
credentials=effective_credentials,
|
129
|
+
)
|
128
130
|
|
129
131
|
# Initialize service instances
|
130
132
|
self.reservations = AsyncReservationsService(self._transport)
|
@@ -149,7 +151,7 @@ class AsyncBookalimo:
|
|
149
151
|
Auth priority is as follows:
|
150
152
|
- provided api key in constructor
|
151
153
|
- GOOGLE_PLACES_API_KEY environment variable
|
152
|
-
- Google ADC -
|
154
|
+
- Google ADC - Not yet implemented.
|
153
155
|
"""
|
154
156
|
if not _GOOGLE_PLACES_AVAILABLE:
|
155
157
|
raise ImportError(
|
@@ -207,7 +209,7 @@ class Bookalimo:
|
|
207
209
|
google_places_api_key="your-google-api-key"
|
208
210
|
) as client:
|
209
211
|
# Find locations using Google Places
|
210
|
-
places = client.places.
|
212
|
+
places = client.places.search("Empire State Building")
|
211
213
|
|
212
214
|
# Use in booking
|
213
215
|
quote = client.pricing.quote(
|
@@ -241,20 +243,41 @@ class Bookalimo:
|
|
241
243
|
transport: Custom transport instance (optional)
|
242
244
|
google_places_api_key: Google Places API key for location services (optional)
|
243
245
|
"""
|
244
|
-
|
246
|
+
transport_credentials = transport.credentials if transport else None
|
247
|
+
|
248
|
+
both_provided = all([transport_credentials, credentials])
|
249
|
+
both_missing = not any([transport_credentials, credentials])
|
250
|
+
|
251
|
+
if both_provided:
|
245
252
|
warnings.warn(
|
246
253
|
"Credentials provided in both transport and constructor. "
|
247
254
|
"The transport credentials will be used.",
|
248
|
-
|
255
|
+
DuplicateCredentialsWarning,
|
249
256
|
stacklevel=2,
|
250
257
|
)
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
258
|
+
elif both_missing:
|
259
|
+
warnings.warn(
|
260
|
+
"No credentials provided in transport or constructor; proceeding unauthenticated.",
|
261
|
+
MissingCredentialsWarning,
|
262
|
+
stacklevel=2,
|
263
|
+
)
|
264
|
+
|
265
|
+
effective_credentials = (
|
266
|
+
transport_credentials if transport_credentials is not None else credentials
|
256
267
|
)
|
257
268
|
|
269
|
+
if transport:
|
270
|
+
if transport_credentials is None and credentials is not None:
|
271
|
+
transport.credentials = credentials
|
272
|
+
self._transport = transport
|
273
|
+
else:
|
274
|
+
self._transport = SyncTransport(
|
275
|
+
base_url=base_url,
|
276
|
+
timeouts=timeouts,
|
277
|
+
user_agent=user_agent,
|
278
|
+
credentials=effective_credentials,
|
279
|
+
)
|
280
|
+
|
258
281
|
# Initialize service instances
|
259
282
|
self.reservations = ReservationsService(self._transport)
|
260
283
|
self.pricing = PricingService(self._transport)
|
@@ -278,7 +301,7 @@ class Bookalimo:
|
|
278
301
|
Auth priority is as follows:
|
279
302
|
- provided api key in constructor
|
280
303
|
- GOOGLE_PLACES_API_KEY environment variable
|
281
|
-
- Google ADC -
|
304
|
+
- Google ADC - Not yet implemented.
|
282
305
|
"""
|
283
306
|
if not _GOOGLE_PLACES_AVAILABLE:
|
284
307
|
raise ImportError(
|
@@ -5,7 +5,7 @@ from ._version import __version__
|
|
5
5
|
# Default API configuration
|
6
6
|
DEFAULT_BASE_URL = "https://www.bookalimo.com/web/api"
|
7
7
|
DEFAULT_TIMEOUT = 5.0
|
8
|
-
DEFAULT_USER_AGENT = f"bookalimo-python/{__version__}
|
8
|
+
DEFAULT_USER_AGENT = f"bookalimo-python/{__version__}"
|
9
9
|
|
10
10
|
# Default retry configuration
|
11
11
|
DEFAULT_RETRIES = 2
|