bookalimo 0.1.5__py3-none-any.whl → 1.0.0__py3-none-any.whl
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/__init__.py +17 -24
- bookalimo/_version.py +9 -0
- bookalimo/client.py +310 -0
- bookalimo/config.py +16 -0
- bookalimo/exceptions.py +115 -5
- bookalimo/integrations/__init__.py +1 -0
- bookalimo/integrations/google_places/__init__.py +31 -0
- bookalimo/integrations/google_places/client_async.py +258 -0
- bookalimo/integrations/google_places/client_sync.py +257 -0
- bookalimo/integrations/google_places/common.py +245 -0
- bookalimo/integrations/google_places/proto_adapter.py +224 -0
- bookalimo/{_logging.py → logging.py} +45 -42
- bookalimo/schemas/__init__.py +97 -0
- bookalimo/schemas/base.py +56 -0
- bookalimo/{models.py → schemas/booking.py} +88 -100
- bookalimo/schemas/places/__init__.py +37 -0
- bookalimo/schemas/places/common.py +198 -0
- bookalimo/schemas/places/google.py +596 -0
- bookalimo/schemas/places/place.py +337 -0
- bookalimo/services/__init__.py +11 -0
- bookalimo/services/pricing.py +191 -0
- bookalimo/services/reservations.py +227 -0
- bookalimo/transport/__init__.py +7 -0
- bookalimo/transport/auth.py +41 -0
- bookalimo/transport/base.py +44 -0
- bookalimo/transport/httpx_async.py +230 -0
- bookalimo/transport/httpx_sync.py +230 -0
- bookalimo/transport/retry.py +102 -0
- bookalimo/transport/utils.py +59 -0
- bookalimo-1.0.0.dist-info/METADATA +307 -0
- bookalimo-1.0.0.dist-info/RECORD +35 -0
- bookalimo/_client.py +0 -420
- bookalimo/wrapper.py +0 -444
- bookalimo-0.1.5.dist-info/METADATA +0 -392
- bookalimo-0.1.5.dist-info/RECORD +0 -12
- {bookalimo-0.1.5.dist-info → bookalimo-1.0.0.dist-info}/WHEEL +0 -0
- {bookalimo-0.1.5.dist-info → bookalimo-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {bookalimo-0.1.5.dist-info → bookalimo-1.0.0.dist-info}/top_level.txt +0 -0
bookalimo/__init__.py
CHANGED
@@ -1,31 +1,24 @@
|
|
1
1
|
"""
|
2
|
-
Book-A-Limo API
|
3
|
-
Provides a clean, typed interface to the Book-A-Limo API.
|
4
|
-
"""
|
2
|
+
Bookalimo SDK - Python client for the Book-A-Limo API.
|
5
3
|
|
6
|
-
|
4
|
+
Provides clean, typed interfaces for booking transportation services.
|
5
|
+
"""
|
7
6
|
|
8
|
-
from .
|
9
|
-
from .
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
create_passenger,
|
16
|
-
create_stop,
|
7
|
+
from ._version import __version__
|
8
|
+
from .client import AsyncBookalimo, Bookalimo
|
9
|
+
from .exceptions import (
|
10
|
+
BookalimoError,
|
11
|
+
BookalimoHTTPError,
|
12
|
+
BookalimoTimeout,
|
13
|
+
BookalimoValidationError,
|
17
14
|
)
|
18
15
|
|
19
16
|
__all__ = [
|
20
|
-
"
|
21
|
-
"
|
22
|
-
"
|
23
|
-
"
|
24
|
-
"
|
25
|
-
"
|
26
|
-
"
|
27
|
-
"enable_debug_logging",
|
28
|
-
"disable_debug_logging",
|
17
|
+
"Bookalimo",
|
18
|
+
"AsyncBookalimo",
|
19
|
+
"BookalimoError",
|
20
|
+
"BookalimoHTTPError",
|
21
|
+
"BookalimoTimeout",
|
22
|
+
"BookalimoValidationError",
|
23
|
+
"__version__",
|
29
24
|
]
|
30
|
-
|
31
|
-
__version__ = importlib.metadata.version(__package__ or __name__)
|
bookalimo/_version.py
ADDED
bookalimo/client.py
ADDED
@@ -0,0 +1,310 @@
|
|
1
|
+
"""Main client classes for the Bookalimo SDK."""
|
2
|
+
|
3
|
+
import warnings
|
4
|
+
from typing import TYPE_CHECKING, Any, Optional
|
5
|
+
|
6
|
+
if TYPE_CHECKING:
|
7
|
+
from .integrations.google_places import AsyncGooglePlaces, GooglePlaces
|
8
|
+
|
9
|
+
from .config import DEFAULT_BASE_URL, DEFAULT_TIMEOUTS, DEFAULT_USER_AGENT
|
10
|
+
from .exceptions import DuplicateCredentialsWarning, MissingCredentialsWarning
|
11
|
+
from .services import (
|
12
|
+
AsyncPricingService,
|
13
|
+
AsyncReservationsService,
|
14
|
+
PricingService,
|
15
|
+
ReservationsService,
|
16
|
+
)
|
17
|
+
from .transport import AsyncTransport, SyncTransport
|
18
|
+
from .transport.auth import Credentials
|
19
|
+
|
20
|
+
# Optional integrations
|
21
|
+
try:
|
22
|
+
from .integrations.google_places import (
|
23
|
+
AsyncGooglePlaces as _AsyncGooglePlaces,
|
24
|
+
)
|
25
|
+
from .integrations.google_places import (
|
26
|
+
GooglePlaces as _GooglePlaces,
|
27
|
+
)
|
28
|
+
|
29
|
+
_GOOGLE_PLACES_AVAILABLE = True
|
30
|
+
except ImportError:
|
31
|
+
_GOOGLE_PLACES_AVAILABLE = False
|
32
|
+
_AsyncGooglePlaces = None # type: ignore
|
33
|
+
_GooglePlaces = None # type: ignore
|
34
|
+
|
35
|
+
|
36
|
+
class AsyncBookalimo:
|
37
|
+
"""
|
38
|
+
Async client for the Book-A-Limo API.
|
39
|
+
|
40
|
+
Provides access to reservations and pricing services through a clean,
|
41
|
+
resource-style interface. Optionally includes Google Places integration
|
42
|
+
for location services.
|
43
|
+
|
44
|
+
Examples:
|
45
|
+
# Basic usage
|
46
|
+
async with AsyncBookalimo(credentials=creds) as client:
|
47
|
+
quote = await client.pricing.quote(
|
48
|
+
rate_type=RateType.P2P,
|
49
|
+
date_time="09/10/2025 03:00 PM",
|
50
|
+
pickup=pickup_location,
|
51
|
+
dropoff=dropoff_location,
|
52
|
+
passengers=2,
|
53
|
+
luggage=2,
|
54
|
+
)
|
55
|
+
|
56
|
+
# With Google Places integration
|
57
|
+
async with AsyncBookalimo(
|
58
|
+
credentials=creds,
|
59
|
+
google_places_api_key="your-google-api-key"
|
60
|
+
) as client:
|
61
|
+
# Find locations using Google Places
|
62
|
+
places = await client.places.search_text("Empire State Building")
|
63
|
+
|
64
|
+
# Use in booking
|
65
|
+
quote = await client.pricing.quote(
|
66
|
+
rate_type=RateType.P2P,
|
67
|
+
date_time="09/10/2025 03:00 PM",
|
68
|
+
pickup=pickup_location,
|
69
|
+
dropoff=dropoff_location,
|
70
|
+
passengers=2,
|
71
|
+
luggage=2,
|
72
|
+
)
|
73
|
+
"""
|
74
|
+
|
75
|
+
def __init__(
|
76
|
+
self,
|
77
|
+
*,
|
78
|
+
credentials: Optional[Credentials] = None,
|
79
|
+
base_url: str = DEFAULT_BASE_URL,
|
80
|
+
timeouts: Any = DEFAULT_TIMEOUTS,
|
81
|
+
user_agent: str = DEFAULT_USER_AGENT,
|
82
|
+
transport: Optional[AsyncTransport] = None,
|
83
|
+
google_places_api_key: Optional[str] = None,
|
84
|
+
):
|
85
|
+
"""
|
86
|
+
Initialize the async Bookalimo client.
|
87
|
+
|
88
|
+
Args:
|
89
|
+
credentials: Authentication credentials (required for API calls)
|
90
|
+
base_url: API base URL
|
91
|
+
timeouts: Request timeout configuration
|
92
|
+
user_agent: User agent string
|
93
|
+
transport: Custom transport instance (optional)
|
94
|
+
google_places_api_key: Google Places API key for location services (optional)
|
95
|
+
"""
|
96
|
+
|
97
|
+
transport_credentials = transport.credentials if transport else None
|
98
|
+
|
99
|
+
both_provided = all([transport_credentials, credentials])
|
100
|
+
both_missing = not any([transport_credentials, credentials])
|
101
|
+
|
102
|
+
if both_provided:
|
103
|
+
warnings.warn(
|
104
|
+
"Credentials provided in both transport and constructor. "
|
105
|
+
"The transport credentials will be used.",
|
106
|
+
DuplicateCredentialsWarning,
|
107
|
+
stacklevel=2,
|
108
|
+
)
|
109
|
+
elif both_missing:
|
110
|
+
warnings.warn(
|
111
|
+
"No credentials provided in transport or constructor; proceeding unauthenticated.",
|
112
|
+
MissingCredentialsWarning,
|
113
|
+
stacklevel=2,
|
114
|
+
)
|
115
|
+
|
116
|
+
# Use whichever exists when we need to build a transport ourselves
|
117
|
+
effective_credentials = (
|
118
|
+
credentials if credentials is not None else transport_credentials
|
119
|
+
)
|
120
|
+
if transport:
|
121
|
+
transport.credentials = effective_credentials
|
122
|
+
self._transport = transport or AsyncTransport(
|
123
|
+
base_url=base_url,
|
124
|
+
timeouts=timeouts,
|
125
|
+
user_agent=user_agent,
|
126
|
+
credentials=effective_credentials,
|
127
|
+
)
|
128
|
+
|
129
|
+
# Initialize service instances
|
130
|
+
self.reservations = AsyncReservationsService(self._transport)
|
131
|
+
self.pricing = AsyncPricingService(self._transport)
|
132
|
+
|
133
|
+
# Initialize Google Places integration if available
|
134
|
+
self._google_places_api_key = google_places_api_key
|
135
|
+
self._google_places_client: Optional[AsyncGooglePlaces] = None
|
136
|
+
|
137
|
+
@property
|
138
|
+
def places(self) -> "AsyncGooglePlaces":
|
139
|
+
"""
|
140
|
+
Access Google Places integration for location services.
|
141
|
+
|
142
|
+
Returns:
|
143
|
+
AsyncGooglePlaces client instance
|
144
|
+
|
145
|
+
Raises:
|
146
|
+
ImportError: If Google Places dependencies are not installed
|
147
|
+
|
148
|
+
Note:
|
149
|
+
Auth priority is as follows:
|
150
|
+
- provided api key in constructor
|
151
|
+
- GOOGLE_PLACES_API_KEY environment variable
|
152
|
+
- Google ADC - Except for Geocoding API.
|
153
|
+
"""
|
154
|
+
if not _GOOGLE_PLACES_AVAILABLE:
|
155
|
+
raise ImportError(
|
156
|
+
"Google Places integration requires the 'places' extra. "
|
157
|
+
"Install with: pip install bookalimo[places]"
|
158
|
+
)
|
159
|
+
|
160
|
+
if self._google_places_client is None:
|
161
|
+
if _AsyncGooglePlaces is None:
|
162
|
+
raise ImportError("Google Places integration not available")
|
163
|
+
self._google_places_client = _AsyncGooglePlaces(
|
164
|
+
api_key=self._google_places_api_key
|
165
|
+
)
|
166
|
+
|
167
|
+
return self._google_places_client
|
168
|
+
|
169
|
+
async def aclose(self) -> None:
|
170
|
+
"""Close the client and clean up resources."""
|
171
|
+
await self._transport.aclose()
|
172
|
+
if self._google_places_client is not None:
|
173
|
+
await self._google_places_client.aclose()
|
174
|
+
|
175
|
+
async def __aenter__(self) -> "AsyncBookalimo":
|
176
|
+
"""Async context manager entry."""
|
177
|
+
return self
|
178
|
+
|
179
|
+
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
180
|
+
"""Async context manager exit."""
|
181
|
+
await self.aclose()
|
182
|
+
|
183
|
+
|
184
|
+
class Bookalimo:
|
185
|
+
"""
|
186
|
+
Sync client for the Book-A-Limo API.
|
187
|
+
|
188
|
+
Provides access to reservations and pricing services through a clean,
|
189
|
+
resource-style interface. Optionally includes Google Places integration
|
190
|
+
for location services.
|
191
|
+
|
192
|
+
Examples:
|
193
|
+
# Basic usage
|
194
|
+
with Bookalimo(credentials=creds) as client:
|
195
|
+
quote = client.pricing.quote(
|
196
|
+
rate_type=RateType.P2P,
|
197
|
+
date_time="09/10/2025 03:00 PM",
|
198
|
+
pickup=pickup_location,
|
199
|
+
dropoff=dropoff_location,
|
200
|
+
passengers=2,
|
201
|
+
luggage=2,
|
202
|
+
)
|
203
|
+
|
204
|
+
# With Google Places integration
|
205
|
+
with Bookalimo(
|
206
|
+
credentials=creds,
|
207
|
+
google_places_api_key="your-google-api-key"
|
208
|
+
) as client:
|
209
|
+
# Find locations using Google Places
|
210
|
+
places = client.places.search_text("Empire State Building")
|
211
|
+
|
212
|
+
# Use in booking
|
213
|
+
quote = client.pricing.quote(
|
214
|
+
rate_type=RateType.P2P,
|
215
|
+
date_time="09/10/2025 03:00 PM",
|
216
|
+
pickup=pickup_location,
|
217
|
+
dropoff=dropoff_location,
|
218
|
+
passengers=2,
|
219
|
+
luggage=2,
|
220
|
+
)
|
221
|
+
"""
|
222
|
+
|
223
|
+
def __init__(
|
224
|
+
self,
|
225
|
+
*,
|
226
|
+
credentials: Optional[Credentials] = None,
|
227
|
+
base_url: str = DEFAULT_BASE_URL,
|
228
|
+
timeouts: Any = DEFAULT_TIMEOUTS,
|
229
|
+
user_agent: str = DEFAULT_USER_AGENT,
|
230
|
+
transport: Optional[SyncTransport] = None,
|
231
|
+
google_places_api_key: Optional[str] = None,
|
232
|
+
):
|
233
|
+
"""
|
234
|
+
Initialize the sync Bookalimo client.
|
235
|
+
|
236
|
+
Args:
|
237
|
+
credentials: Authentication credentials (required for API calls)
|
238
|
+
base_url: API base URL
|
239
|
+
timeouts: Request timeout configuration
|
240
|
+
user_agent: User agent string
|
241
|
+
transport: Custom transport instance (optional)
|
242
|
+
google_places_api_key: Google Places API key for location services (optional)
|
243
|
+
"""
|
244
|
+
if transport and transport.credentials is not None and credentials is not None:
|
245
|
+
warnings.warn(
|
246
|
+
"Credentials provided in both transport and constructor. "
|
247
|
+
"The transport credentials will be used.",
|
248
|
+
UserWarning,
|
249
|
+
stacklevel=2,
|
250
|
+
)
|
251
|
+
self._transport = transport or SyncTransport(
|
252
|
+
base_url=base_url,
|
253
|
+
timeouts=timeouts,
|
254
|
+
user_agent=user_agent,
|
255
|
+
credentials=credentials,
|
256
|
+
)
|
257
|
+
|
258
|
+
# Initialize service instances
|
259
|
+
self.reservations = ReservationsService(self._transport)
|
260
|
+
self.pricing = PricingService(self._transport)
|
261
|
+
|
262
|
+
# Initialize Google Places integration if available
|
263
|
+
self._google_places_api_key = google_places_api_key
|
264
|
+
self._google_places_client: Optional[GooglePlaces] = None
|
265
|
+
|
266
|
+
@property
|
267
|
+
def places(self) -> "GooglePlaces":
|
268
|
+
"""
|
269
|
+
Access Google Places integration for location services.
|
270
|
+
|
271
|
+
Returns:
|
272
|
+
GooglePlaces client instance
|
273
|
+
|
274
|
+
Raises:
|
275
|
+
ImportError: If Google Places dependencies are not installed
|
276
|
+
|
277
|
+
Note:
|
278
|
+
Auth priority is as follows:
|
279
|
+
- provided api key in constructor
|
280
|
+
- GOOGLE_PLACES_API_KEY environment variable
|
281
|
+
- Google ADC - Except for Geocoding API.
|
282
|
+
"""
|
283
|
+
if not _GOOGLE_PLACES_AVAILABLE:
|
284
|
+
raise ImportError(
|
285
|
+
"Google Places integration requires the 'places' extra. "
|
286
|
+
"Install with: pip install bookalimo[places]"
|
287
|
+
)
|
288
|
+
|
289
|
+
if self._google_places_client is None:
|
290
|
+
if _GooglePlaces is None:
|
291
|
+
raise ImportError("Google Places integration not available")
|
292
|
+
self._google_places_client = _GooglePlaces(
|
293
|
+
api_key=self._google_places_api_key
|
294
|
+
)
|
295
|
+
|
296
|
+
return self._google_places_client
|
297
|
+
|
298
|
+
def close(self) -> None:
|
299
|
+
"""Close the client and clean up resources."""
|
300
|
+
self._transport.close()
|
301
|
+
if self._google_places_client is not None:
|
302
|
+
self._google_places_client.close()
|
303
|
+
|
304
|
+
def __enter__(self) -> "Bookalimo":
|
305
|
+
"""Context manager entry."""
|
306
|
+
return self
|
307
|
+
|
308
|
+
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
309
|
+
"""Context manager exit."""
|
310
|
+
self.close()
|
bookalimo/config.py
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
"""Configuration defaults for the Bookalimo SDK."""
|
2
|
+
|
3
|
+
from ._version import __version__
|
4
|
+
|
5
|
+
# Default API configuration
|
6
|
+
DEFAULT_BASE_URL = "https://www.bookalimo.com/web/api"
|
7
|
+
DEFAULT_TIMEOUT = 5.0
|
8
|
+
DEFAULT_USER_AGENT = f"bookalimo-python/{__version__} (+https://github.com/asparagusbeef/bookalimo-python)"
|
9
|
+
|
10
|
+
# Default retry configuration
|
11
|
+
DEFAULT_RETRIES = 2
|
12
|
+
DEFAULT_BACKOFF = 0.3
|
13
|
+
DEFAULT_STATUS_FORCELIST = (500, 502, 503, 504)
|
14
|
+
|
15
|
+
# Default timeouts (can be dict for httpx.Timeout)
|
16
|
+
DEFAULT_TIMEOUTS = DEFAULT_TIMEOUT
|
bookalimo/exceptions.py
CHANGED
@@ -1,15 +1,125 @@
|
|
1
|
-
|
1
|
+
"""Exception classes for the Bookalimo SDK."""
|
2
2
|
|
3
|
+
from typing import Any, Literal, Optional
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
from pydantic import ValidationError
|
6
|
+
from pydantic_core import ErrorDetails, InitErrorDetails
|
7
|
+
|
8
|
+
|
9
|
+
class BookalimoError(Exception): ...
|
10
|
+
|
11
|
+
|
12
|
+
class BookalimoValidationError(BookalimoError):
|
13
|
+
"""Validation error for input data that wraps Pydantic ValidationError."""
|
14
|
+
|
15
|
+
def __init__(
|
16
|
+
self, message: str, validation_error: Optional[ValidationError] = None
|
17
|
+
):
|
18
|
+
"""Initialize validation error with message and optional Pydantic ValidationError."""
|
19
|
+
super().__init__(message)
|
20
|
+
self._validation_error = validation_error
|
21
|
+
self._message = message
|
22
|
+
|
23
|
+
@property
|
24
|
+
def message(self) -> str:
|
25
|
+
"""Get the error message."""
|
26
|
+
return self._message
|
27
|
+
|
28
|
+
def errors(self, **kwargs: Any) -> list[ErrorDetails]:
|
29
|
+
"""Get validation errors if available."""
|
30
|
+
if self._validation_error:
|
31
|
+
return self._validation_error.errors(**kwargs)
|
32
|
+
return []
|
33
|
+
|
34
|
+
def error_count(self) -> int:
|
35
|
+
"""Get error count."""
|
36
|
+
if self._validation_error:
|
37
|
+
return self._validation_error.error_count()
|
38
|
+
return 1
|
39
|
+
|
40
|
+
@property
|
41
|
+
def title(self) -> str:
|
42
|
+
"""Get validation error title."""
|
43
|
+
if self._validation_error:
|
44
|
+
return self._validation_error.title
|
45
|
+
return "BookalimoValidationError"
|
46
|
+
|
47
|
+
def json(self, **kwargs: Any) -> str:
|
48
|
+
"""Get errors as JSON string."""
|
49
|
+
if self._validation_error:
|
50
|
+
return self._validation_error.json(**kwargs)
|
51
|
+
import json
|
52
|
+
|
53
|
+
return json.dumps([{"type": "error", "msg": self._message, "loc": []}])
|
54
|
+
|
55
|
+
@classmethod
|
56
|
+
def from_exception_data(
|
57
|
+
cls,
|
58
|
+
title: str,
|
59
|
+
line_errors: list[InitErrorDetails],
|
60
|
+
input_type: Literal["python", "json"] = "python",
|
61
|
+
hide_input: bool = False,
|
62
|
+
) -> "BookalimoValidationError":
|
63
|
+
"""Create validation error from Pydantic error details."""
|
64
|
+
# Create a proper ValidationError
|
65
|
+
validation_error = ValidationError.from_exception_data(
|
66
|
+
title, line_errors, input_type, hide_input
|
67
|
+
)
|
68
|
+
return cls(f"Validation error in {title}", validation_error)
|
69
|
+
|
70
|
+
@classmethod
|
71
|
+
def from_validation_error(
|
72
|
+
cls, validation_error: ValidationError, message: Optional[str] = None
|
73
|
+
) -> "BookalimoValidationError":
|
74
|
+
"""Create BookalimoValidationError from an existing ValidationError."""
|
75
|
+
if message is None:
|
76
|
+
message = f"Validation error: {validation_error}"
|
77
|
+
return cls(message, validation_error)
|
78
|
+
|
79
|
+
|
80
|
+
class BookalimoRequestError(BookalimoError): ...
|
81
|
+
|
82
|
+
|
83
|
+
class BookalimoConnectionError(BookalimoError): ...
|
84
|
+
|
85
|
+
|
86
|
+
class BookalimoHTTPError(BookalimoError):
|
87
|
+
"""HTTP-related errors (4xx, 5xx responses)."""
|
6
88
|
|
7
89
|
def __init__(
|
8
90
|
self,
|
9
91
|
message: str,
|
92
|
+
*,
|
10
93
|
status_code: Optional[int] = None,
|
11
|
-
|
94
|
+
payload: Optional[dict[str, Any]] = None,
|
12
95
|
):
|
13
96
|
super().__init__(message)
|
97
|
+
self.message = message
|
14
98
|
self.status_code = status_code
|
15
|
-
self.
|
99
|
+
self.payload = payload
|
100
|
+
|
101
|
+
def __str__(self) -> str:
|
102
|
+
base = super().__str__()
|
103
|
+
if self.payload and isinstance(self.payload, dict) and "error" in self.payload:
|
104
|
+
error_msg = self.payload["error"]
|
105
|
+
if self.status_code:
|
106
|
+
return f"{base}: {error_msg} (status_code={self.status_code})"
|
107
|
+
else:
|
108
|
+
return f"{base}: {error_msg}"
|
109
|
+
return f"{base} (status_code={self.status_code})" if self.status_code else base
|
110
|
+
|
111
|
+
|
112
|
+
class BookalimoTimeout(BookalimoHTTPError):
|
113
|
+
"""Request timeout errors."""
|
114
|
+
|
115
|
+
def __init__(self, message: str = "Request timeout", **kwargs: Any):
|
116
|
+
super().__init__(message, status_code=408, **kwargs)
|
117
|
+
self.message = message
|
118
|
+
self.status_code = 408
|
119
|
+
self.payload = kwargs.get("payload", None)
|
120
|
+
|
121
|
+
|
122
|
+
class DuplicateCredentialsWarning(UserWarning): ...
|
123
|
+
|
124
|
+
|
125
|
+
class MissingCredentialsWarning(UserWarning): ...
|
@@ -0,0 +1 @@
|
|
1
|
+
"""Optional integrations for the Bookalimo SDK."""
|
@@ -0,0 +1,31 @@
|
|
1
|
+
"""
|
2
|
+
Google Places API integration for Bookalimo.
|
3
|
+
|
4
|
+
This integration requires the 'places' extra:
|
5
|
+
pip install bookalimo[places]
|
6
|
+
|
7
|
+
Examples:
|
8
|
+
# Async client
|
9
|
+
from bookalimo.integrations.google_places import AsyncGooglePlaces
|
10
|
+
|
11
|
+
async with AsyncGooglePlaces() as places:
|
12
|
+
results = await places.autocomplete("Empire State Building")
|
13
|
+
|
14
|
+
# Sync client
|
15
|
+
from bookalimo.integrations.google_places import GooglePlaces
|
16
|
+
|
17
|
+
with GooglePlaces() as places:
|
18
|
+
results = places.autocomplete("Empire State Building")
|
19
|
+
"""
|
20
|
+
|
21
|
+
try:
|
22
|
+
from .client_async import AsyncGooglePlaces
|
23
|
+
from .client_sync import GooglePlaces
|
24
|
+
|
25
|
+
__all__ = ["AsyncGooglePlaces", "GooglePlaces"]
|
26
|
+
|
27
|
+
except ImportError as e:
|
28
|
+
raise ImportError(
|
29
|
+
"Google Places integration requires the 'places' extra. "
|
30
|
+
"Install with: pip install bookalimo[places]"
|
31
|
+
) from e
|