bookalimo 1.0.1__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/PKG-INFO +245 -0
- bookalimo-1.0.2/README.md +183 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/pyproject.toml +5 -4
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/client.py +45 -22
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/integrations/google_places/client_async.py +56 -102
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/integrations/google_places/client_sync.py +56 -100
- bookalimo-1.0.2/src/bookalimo/integrations/google_places/common.py +509 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/integrations/google_places/resolve_airport.py +148 -119
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/integrations/google_places/transports.py +14 -7
- {bookalimo-1.0.1 → 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.1 → bookalimo-1.0.2}/src/bookalimo/schemas/places/__init__.py +3 -1
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/schemas/places/common.py +1 -1
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/schemas/places/field_mask.py +0 -9
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/schemas/places/google.py +165 -10
- 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.1/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.1 → 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.1 → bookalimo-1.0.2}/src/bookalimo.egg-info/SOURCES.txt +3 -1
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo.egg-info/requires.txt +3 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/tests/test_client.py +6 -6
- {bookalimo-1.0.1 → bookalimo-1.0.2}/tests/test_google_places.py +148 -85
- {bookalimo-1.0.1 → bookalimo-1.0.2}/tests/test_integration.py +117 -81
- {bookalimo-1.0.1 → bookalimo-1.0.2}/tests/test_real_api_integration.py +110 -68
- {bookalimo-1.0.1 → bookalimo-1.0.2}/tests/test_schemas.py +11 -12
- bookalimo-1.0.2/tests/test_services.py +620 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/tests/test_transport.py +5 -6
- bookalimo-1.0.1/PKG-INFO +0 -370
- bookalimo-1.0.1/README.md +0 -309
- bookalimo-1.0.1/src/bookalimo/integrations/google_places/common.py +0 -231
- bookalimo-1.0.1/src/bookalimo/schemas/__init__.py +0 -103
- bookalimo-1.0.1/src/bookalimo/schemas/base.py +0 -56
- bookalimo-1.0.1/src/bookalimo/services/pricing.py +0 -191
- bookalimo-1.0.1/src/bookalimo/services/reservations.py +0 -227
- bookalimo-1.0.1/src/bookalimo/transport/httpx_async.py +0 -230
- bookalimo-1.0.1/src/bookalimo/transport/httpx_sync.py +0 -230
- bookalimo-1.0.1/src/bookalimo/transport/utils.py +0 -59
- bookalimo-1.0.1/src/bookalimo.egg-info/PKG-INFO +0 -370
- bookalimo-1.0.1/tests/test_services.py +0 -495
- {bookalimo-1.0.1 → bookalimo-1.0.2}/LICENSE +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/setup.cfg +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/__init__.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/_version.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/config.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/exceptions.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/integrations/__init__.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/integrations/google_places/__init__.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/integrations/google_places/proto_adapter.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/py.typed +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/schemas/places/place.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/services/__init__.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/transport/__init__.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/transport/base.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo/transport/retry.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo.egg-info/dependency_links.txt +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/src/bookalimo.egg-info/top_level.txt +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/tests/test_config.py +0 -0
- {bookalimo-1.0.1 → bookalimo-1.0.2}/tests/test_exceptions.py +0 -0
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"}
|
@@ -43,7 +43,8 @@ places = [
|
|
43
43
|
"google-maps-places>=0.1.0",
|
44
44
|
"google-api-core>=2.0.0",
|
45
45
|
"numpy>=2.0.0",
|
46
|
-
"rapidfuzz>=3.0.0"
|
46
|
+
"rapidfuzz>=3.0.0",
|
47
|
+
"typing-extensions>=4.15.0; python_version < '3.11'"
|
47
48
|
]
|
48
49
|
dev = [
|
49
50
|
"pytest>=7.0.0",
|
@@ -96,7 +97,7 @@ lint.select = [
|
|
96
97
|
"UP", # pyupgrade
|
97
98
|
]
|
98
99
|
lint.ignore = [
|
99
|
-
"E501", # line too long, handled by
|
100
|
+
"E501", # line too long, handled by ruff-format
|
100
101
|
"B008", # do not perform function calls in argument defaults
|
101
102
|
"C901", # too complex
|
102
103
|
"UP045", # until I have time to Optional[] -> X | None everywhere.
|
@@ -127,7 +128,7 @@ warn_return_any = true
|
|
127
128
|
warn_unreachable = true
|
128
129
|
warn_unused_configs = true
|
129
130
|
warn_unused_ignores = true
|
130
|
-
mypy_path = "stubs"
|
131
|
+
mypy_path = "src:stubs"
|
131
132
|
disable_error_code = ["prop-decorator"]
|
132
133
|
|
133
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(
|