woltapi 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {woltapi-0.2.0/src/woltapi.egg-info → woltapi-0.3.0}/PKG-INFO +64 -18
- {woltapi-0.2.0 → woltapi-0.3.0}/README.md +63 -17
- {woltapi-0.2.0 → woltapi-0.3.0}/examples/order.py +45 -85
- {woltapi-0.2.0 → woltapi-0.3.0}/pyproject.toml +1 -1
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/__init__.py +2 -0
- woltapi-0.3.0/src/woltapi/basket.py +297 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/client.py +51 -2
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/selection.py +23 -14
- {woltapi-0.2.0 → woltapi-0.3.0/src/woltapi.egg-info}/PKG-INFO +64 -18
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi.egg-info/SOURCES.txt +2 -0
- woltapi-0.3.0/tests/test_basket.py +229 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/tests/test_client.py +65 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/tests/test_order_example.py +79 -95
- {woltapi-0.2.0 → woltapi-0.3.0}/tests/test_selection.py +93 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/LICENSE +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/MANIFEST.in +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/RELEASING.md +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/examples/browse.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/examples/check_session.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/setup.cfg +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/auth.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/credentials.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/errors.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/models.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/purchase.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/services.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi/transport.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi.egg-info/dependency_links.txt +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi.egg-info/requires.txt +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/src/woltapi.egg-info/top_level.txt +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/tests/__init__.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/tests/test_auth.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/tests/test_browse.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/tests/test_check_session.py +0 -0
- {woltapi-0.2.0 → woltapi-0.3.0}/tests/test_purchase.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: woltapi
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A small synchronous client for observed Wolt ordering flows.
|
|
5
5
|
License-Expression: AGPL-3.0-only
|
|
6
6
|
Project-URL: Repository, https://github.com/skorokithakis/woltapi
|
|
@@ -261,6 +261,53 @@ Responses can contain personal information. Avoid printing entire responses or
|
|
|
261
261
|
sending them to shared logs. The examples print saved addresses and card labels
|
|
262
262
|
to the local terminal only. The browsing example prints only selected fields.
|
|
263
263
|
|
|
264
|
+
### Baskets
|
|
265
|
+
|
|
266
|
+
A basket is your list of chosen items at one restaurant. The `Basket` class
|
|
267
|
+
builds that list locally, with no network requests. It reads names, option
|
|
268
|
+
prices, and totals from the restaurant's menu, so you do not type any prices:
|
|
269
|
+
|
|
270
|
+
```python
|
|
271
|
+
from woltapi import Basket, OptionSelection, OptionValueSelection
|
|
272
|
+
|
|
273
|
+
menu = client.get_assortment(restaurant.slug)
|
|
274
|
+
basket = Basket(menu, "en")
|
|
275
|
+
|
|
276
|
+
basket.add_item("<item id>", count=2)
|
|
277
|
+
basket.add_item(
|
|
278
|
+
"<other item id>",
|
|
279
|
+
options=[
|
|
280
|
+
OptionSelection(
|
|
281
|
+
"<item option configuration id>", [OptionValueSelection("<value id>", 1)]
|
|
282
|
+
),
|
|
283
|
+
],
|
|
284
|
+
)
|
|
285
|
+
basket.set_count("<item id>", 1)
|
|
286
|
+
basket.set_options("<item id>", [])
|
|
287
|
+
basket.remove_item("<other item id>")
|
|
288
|
+
|
|
289
|
+
items = basket.item_selections()
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Item, option, and value IDs come from the assortment dictionary. For
|
|
293
|
+
`OptionSelection`, use the configuration ID from the catalog item's own
|
|
294
|
+
`options` list, not the root option ID from the assortment's top-level
|
|
295
|
+
`options`. Pass the result of `item_selections()` to
|
|
296
|
+
`client.create_selection(...)`, which validates the whole selection against the
|
|
297
|
+
current menu.
|
|
298
|
+
|
|
299
|
+
Wolt also stores one basket per restaurant on its servers. These are the
|
|
300
|
+
baskets you see in the Wolt app. The library can read and replace them:
|
|
301
|
+
|
|
302
|
+
| Call | What it does |
|
|
303
|
+
| --- | --- |
|
|
304
|
+
| `client.save_basket(selection)` | Replaces the server basket for that restaurant with your selection. This does not place an order. |
|
|
305
|
+
| `client.get_basket_count()` | The number of baskets stored on the server. |
|
|
306
|
+
| `client.get_venue_basket(venue_id)` | The server basket for one restaurant, or `None` if there is none. |
|
|
307
|
+
| `client.get_baskets_page(latitude, longitude)` | The full baskets page as a dictionary. It can contain personal data; do not log it raw. |
|
|
308
|
+
|
|
309
|
+
Deleting a server basket is not supported.
|
|
310
|
+
|
|
264
311
|
## Can it order food?
|
|
265
312
|
|
|
266
313
|
Not as a simple, ready-to-use feature yet. There is no `order("pizza")` method.
|
|
@@ -274,23 +321,22 @@ python examples/order.py --latitude 60.17 --longitude 24.94 --query pizza \
|
|
|
274
321
|
```
|
|
275
322
|
|
|
276
323
|
Use your own coordinates. It reads and saves your refresh token as described in
|
|
277
|
-
[Get a token](#get-a-token), guides you through selecting
|
|
278
|
-
delivery target/card, then asks before requesting a
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
rather than guessing for zero or multiple categories.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
own code, including browser/device information and detailed item data.
|
|
324
|
+
[Get a token](#get-a-token), guides you through selecting one or more items with
|
|
325
|
+
their options and a saved delivery target/card, then asks before requesting a
|
|
326
|
+
price. Line totals come from the menu through the local basket builder; you do
|
|
327
|
+
not type any amounts. It never submits a purchase. Basket saving is off by
|
|
328
|
+
default and needs a separate confirmation if enabled.
|
|
329
|
+
|
|
330
|
+
The basket builder derives `category_id`, `category_ids`, and the three checkout
|
|
331
|
+
exclusion flags from the assortment. It only supports items in exactly one
|
|
332
|
+
category and stops rather than guessing for zero or multiple categories. It may
|
|
333
|
+
also stop if required catalog data is missing. Run
|
|
334
|
+
`python examples/order.py --help` for available options.
|
|
335
|
+
|
|
336
|
+
The library has methods to build and manage a basket, save it, ask Wolt for a
|
|
337
|
+
price, and submit a purchase. But some purchase inputs still need to come from
|
|
338
|
+
your own code, including browser/device information and a few purchase-only
|
|
339
|
+
item fields.
|
|
294
340
|
|
|
295
341
|
Order-history and saved-address reads have worked in live checks. **Payment and
|
|
296
342
|
purchase handling have not been verified with a real order.** The purchase code
|
|
@@ -243,6 +243,53 @@ Responses can contain personal information. Avoid printing entire responses or
|
|
|
243
243
|
sending them to shared logs. The examples print saved addresses and card labels
|
|
244
244
|
to the local terminal only. The browsing example prints only selected fields.
|
|
245
245
|
|
|
246
|
+
### Baskets
|
|
247
|
+
|
|
248
|
+
A basket is your list of chosen items at one restaurant. The `Basket` class
|
|
249
|
+
builds that list locally, with no network requests. It reads names, option
|
|
250
|
+
prices, and totals from the restaurant's menu, so you do not type any prices:
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
from woltapi import Basket, OptionSelection, OptionValueSelection
|
|
254
|
+
|
|
255
|
+
menu = client.get_assortment(restaurant.slug)
|
|
256
|
+
basket = Basket(menu, "en")
|
|
257
|
+
|
|
258
|
+
basket.add_item("<item id>", count=2)
|
|
259
|
+
basket.add_item(
|
|
260
|
+
"<other item id>",
|
|
261
|
+
options=[
|
|
262
|
+
OptionSelection(
|
|
263
|
+
"<item option configuration id>", [OptionValueSelection("<value id>", 1)]
|
|
264
|
+
),
|
|
265
|
+
],
|
|
266
|
+
)
|
|
267
|
+
basket.set_count("<item id>", 1)
|
|
268
|
+
basket.set_options("<item id>", [])
|
|
269
|
+
basket.remove_item("<other item id>")
|
|
270
|
+
|
|
271
|
+
items = basket.item_selections()
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Item, option, and value IDs come from the assortment dictionary. For
|
|
275
|
+
`OptionSelection`, use the configuration ID from the catalog item's own
|
|
276
|
+
`options` list, not the root option ID from the assortment's top-level
|
|
277
|
+
`options`. Pass the result of `item_selections()` to
|
|
278
|
+
`client.create_selection(...)`, which validates the whole selection against the
|
|
279
|
+
current menu.
|
|
280
|
+
|
|
281
|
+
Wolt also stores one basket per restaurant on its servers. These are the
|
|
282
|
+
baskets you see in the Wolt app. The library can read and replace them:
|
|
283
|
+
|
|
284
|
+
| Call | What it does |
|
|
285
|
+
| --- | --- |
|
|
286
|
+
| `client.save_basket(selection)` | Replaces the server basket for that restaurant with your selection. This does not place an order. |
|
|
287
|
+
| `client.get_basket_count()` | The number of baskets stored on the server. |
|
|
288
|
+
| `client.get_venue_basket(venue_id)` | The server basket for one restaurant, or `None` if there is none. |
|
|
289
|
+
| `client.get_baskets_page(latitude, longitude)` | The full baskets page as a dictionary. It can contain personal data; do not log it raw. |
|
|
290
|
+
|
|
291
|
+
Deleting a server basket is not supported.
|
|
292
|
+
|
|
246
293
|
## Can it order food?
|
|
247
294
|
|
|
248
295
|
Not as a simple, ready-to-use feature yet. There is no `order("pizza")` method.
|
|
@@ -256,23 +303,22 @@ python examples/order.py --latitude 60.17 --longitude 24.94 --query pizza \
|
|
|
256
303
|
```
|
|
257
304
|
|
|
258
305
|
Use your own coordinates. It reads and saves your refresh token as described in
|
|
259
|
-
[Get a token](#get-a-token), guides you through selecting
|
|
260
|
-
delivery target/card, then asks before requesting a
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
rather than guessing for zero or multiple categories.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
own code, including browser/device information and detailed item data.
|
|
306
|
+
[Get a token](#get-a-token), guides you through selecting one or more items with
|
|
307
|
+
their options and a saved delivery target/card, then asks before requesting a
|
|
308
|
+
price. Line totals come from the menu through the local basket builder; you do
|
|
309
|
+
not type any amounts. It never submits a purchase. Basket saving is off by
|
|
310
|
+
default and needs a separate confirmation if enabled.
|
|
311
|
+
|
|
312
|
+
The basket builder derives `category_id`, `category_ids`, and the three checkout
|
|
313
|
+
exclusion flags from the assortment. It only supports items in exactly one
|
|
314
|
+
category and stops rather than guessing for zero or multiple categories. It may
|
|
315
|
+
also stop if required catalog data is missing. Run
|
|
316
|
+
`python examples/order.py --help` for available options.
|
|
317
|
+
|
|
318
|
+
The library has methods to build and manage a basket, save it, ask Wolt for a
|
|
319
|
+
price, and submit a purchase. But some purchase inputs still need to come from
|
|
320
|
+
your own code, including browser/device information and a few purchase-only
|
|
321
|
+
item fields.
|
|
276
322
|
|
|
277
323
|
Order-history and saved-address reads have worked in live checks. **Payment and
|
|
278
324
|
purchase handling have not been verified with a real order.** The purchase code
|
|
@@ -9,15 +9,14 @@ from pathlib import Path
|
|
|
9
9
|
from browse import TokenFileError, check_token_file, refresh_credentials, text
|
|
10
10
|
|
|
11
11
|
from woltapi import (
|
|
12
|
+
Basket,
|
|
12
13
|
DeliverySelection,
|
|
13
14
|
HTTPStatusError,
|
|
14
|
-
ItemSelection,
|
|
15
15
|
OptionSelection,
|
|
16
16
|
OptionValueSelection,
|
|
17
17
|
VenueCheckoutContext,
|
|
18
18
|
WoltApiError,
|
|
19
19
|
WoltClient,
|
|
20
|
-
derive_checkout_fields,
|
|
21
20
|
)
|
|
22
21
|
|
|
23
22
|
|
|
@@ -101,7 +100,6 @@ def select_options(item, assortment, language):
|
|
|
101
100
|
raise CheckoutInputError("Missing catalog option lists.")
|
|
102
101
|
selected = []
|
|
103
102
|
descriptions = []
|
|
104
|
-
option_amount = 0
|
|
105
103
|
for config in configurations:
|
|
106
104
|
if not isinstance(config, dict) or config.get("prerequisite_values") != []:
|
|
107
105
|
raise CheckoutInputError(
|
|
@@ -145,19 +143,13 @@ def select_options(item, assortment, language):
|
|
|
145
143
|
f"Count for {name} (0 to {single}): ", 0, single, empty_value=0
|
|
146
144
|
)
|
|
147
145
|
if count:
|
|
148
|
-
price = value.get("price")
|
|
149
|
-
if type(price) is not int:
|
|
150
|
-
raise CheckoutInputError(
|
|
151
|
-
"Missing or invalid catalog option value price."
|
|
152
|
-
)
|
|
153
146
|
selections.append(OptionValueSelection(value["id"], count))
|
|
154
147
|
descriptions.append(f"{count} x {name}")
|
|
155
|
-
option_amount += price * count
|
|
156
148
|
if not low <= sum(v.count for v in selections) <= high:
|
|
157
149
|
raise CheckoutInputError("Selected options do not meet the catalog limits.")
|
|
158
150
|
if selections:
|
|
159
151
|
selected.append(OptionSelection(config["id"], selections))
|
|
160
|
-
return selected, descriptions
|
|
152
|
+
return selected, descriptions
|
|
161
153
|
|
|
162
154
|
|
|
163
155
|
def checkout(client, args, context):
|
|
@@ -168,6 +160,8 @@ def checkout(client, args, context):
|
|
|
168
160
|
raise CheckoutInputError(
|
|
169
161
|
"Static venue response does not match the selected restaurant."
|
|
170
162
|
)
|
|
163
|
+
if context and context.get("venue_id") != venue.id:
|
|
164
|
+
raise CheckoutInputError("Context venue_id must match the selected restaurant.")
|
|
171
165
|
venue_fields = fields(
|
|
172
166
|
static,
|
|
173
167
|
context.get("venue", {}),
|
|
@@ -185,60 +179,32 @@ def checkout(client, args, context):
|
|
|
185
179
|
isinstance(i, dict) for i in catalog_items
|
|
186
180
|
):
|
|
187
181
|
raise CheckoutInputError("Missing assortment items.")
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
):
|
|
196
|
-
raise CheckoutInputError(
|
|
197
|
-
"Context venue_id and item_id must match the selected restaurant and item."
|
|
182
|
+
basket = Basket(assortment, args.language)
|
|
183
|
+
selected_items = []
|
|
184
|
+
while True:
|
|
185
|
+
item = choose(
|
|
186
|
+
"menu item",
|
|
187
|
+
catalog_items,
|
|
188
|
+
lambda i: f"{text(i.get('name'), args.language)} | {money(i.get('price'), currency)}",
|
|
198
189
|
)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
"exclude_from_credits",
|
|
218
|
-
"exclude_from_discounts",
|
|
219
|
-
"exclude_from_discounts_min_basket",
|
|
220
|
-
"alcohol_permille",
|
|
221
|
-
"restrictions",
|
|
222
|
-
),
|
|
223
|
-
"checkout_fields",
|
|
224
|
-
)
|
|
225
|
-
if checkout_fields["alcohol_permille"] != 0:
|
|
226
|
-
raise CheckoutInputError("Age-restricted items are unsupported.")
|
|
227
|
-
payment_fields = fields(
|
|
228
|
-
item,
|
|
229
|
-
context.get("payment_fields", {}),
|
|
230
|
-
(
|
|
231
|
-
"product_hierarchy_tags",
|
|
232
|
-
"vat_percentage",
|
|
233
|
-
"vat_percentage_decimal",
|
|
234
|
-
),
|
|
235
|
-
"payment_fields",
|
|
236
|
-
)
|
|
237
|
-
unit_amount = item_price + option_amount
|
|
238
|
-
print(f"Computed configured unit price: {money(unit_amount, currency)}")
|
|
239
|
-
if input("Does this match the Wolt UI? Type YES: ").strip() != "YES":
|
|
240
|
-
print("Cancelled before card lookup or quote.")
|
|
241
|
-
return
|
|
190
|
+
if item.get("restrictions") != []:
|
|
191
|
+
raise CheckoutInputError("Restricted items are unsupported.")
|
|
192
|
+
methods = item.get("allowed_delivery_methods")
|
|
193
|
+
if not isinstance(methods, list) or "homedelivery" not in methods:
|
|
194
|
+
raise CheckoutInputError(
|
|
195
|
+
"This item does not explicitly support home delivery."
|
|
196
|
+
)
|
|
197
|
+
count = number("Item quantity: ", 1)
|
|
198
|
+
options, option_names = select_options(item, assortment, args.language)
|
|
199
|
+
basket.add_item(item["id"], count, options)
|
|
200
|
+
selected_item = basket.contents[item["id"]]
|
|
201
|
+
if selected_item.checkout_fields["alcohol_permille"] != 0:
|
|
202
|
+
raise CheckoutInputError("Age-restricted items are unsupported.")
|
|
203
|
+
selected_items.append((selected_item, option_names))
|
|
204
|
+
if input("Add another menu item? Type YES: ").strip() != "YES":
|
|
205
|
+
break
|
|
206
|
+
|
|
207
|
+
item_selections = basket.item_selections()
|
|
242
208
|
tip = number("Courier tip in cents (0 for none): ")
|
|
243
209
|
delivery = choose(
|
|
244
210
|
"saved delivery target", client.list_delivery_targets(), delivery_description
|
|
@@ -257,10 +223,11 @@ def checkout(client, args, context):
|
|
|
257
223
|
"available_methods": ["card"],
|
|
258
224
|
"items": [
|
|
259
225
|
{
|
|
260
|
-
"id": item
|
|
261
|
-
"alcohol_permille": checkout_fields["alcohol_permille"],
|
|
262
|
-
**payment_fields,
|
|
226
|
+
"id": item.id,
|
|
227
|
+
"alcohol_permille": item.checkout_fields["alcohol_permille"],
|
|
228
|
+
**item.payment_fields,
|
|
263
229
|
}
|
|
230
|
+
for item in item_selections
|
|
264
231
|
],
|
|
265
232
|
}
|
|
266
233
|
card = choose(
|
|
@@ -268,31 +235,24 @@ def checkout(client, args, context):
|
|
|
268
235
|
client.get_payment_methods(card_context),
|
|
269
236
|
card_description,
|
|
270
237
|
)
|
|
271
|
-
selected_item = ItemSelection(
|
|
272
|
-
id=item["id"],
|
|
273
|
-
count=count,
|
|
274
|
-
basket_name=text(item.get("name"), args.language),
|
|
275
|
-
basket_price=unit_amount,
|
|
276
|
-
end_amount=unit_amount,
|
|
277
|
-
substitution_allowed=False,
|
|
278
|
-
checkout_fields=checkout_fields,
|
|
279
|
-
options=options,
|
|
280
|
-
payment_fields=payment_fields,
|
|
281
|
-
)
|
|
282
238
|
selection = client.create_selection(
|
|
283
239
|
assortment,
|
|
284
240
|
venue=VenueCheckoutContext(id=venue.id, preorder_config=None, **venue_fields),
|
|
285
241
|
delivery=DeliverySelection(delivery.id, args.latitude, args.longitude),
|
|
286
242
|
payment_method={"id": card.id, "type": card.type},
|
|
287
243
|
courier_tip=tip,
|
|
288
|
-
items=
|
|
289
|
-
)
|
|
290
|
-
print(
|
|
291
|
-
f"\n{count} x {selected_item.basket_name} at {text(venue.title or venue.slug)}"
|
|
244
|
+
items=item_selections,
|
|
292
245
|
)
|
|
293
|
-
for
|
|
294
|
-
print(
|
|
295
|
-
|
|
246
|
+
for selected_item, option_names in selected_items:
|
|
247
|
+
print(
|
|
248
|
+
f"\n{selected_item.count} x {selected_item.basket_name} "
|
|
249
|
+
f"at {text(venue.title or venue.slug)}"
|
|
250
|
+
)
|
|
251
|
+
for name in option_names:
|
|
252
|
+
print(f" Option: {name}")
|
|
253
|
+
print(
|
|
254
|
+
f"Catalog-derived line total: {money(selected_item.basket_price, currency)}"
|
|
255
|
+
)
|
|
296
256
|
print(
|
|
297
257
|
f"Delivery: {delivery_description(delivery)} | Card: {card_description(card)}"
|
|
298
258
|
)
|
|
@@ -360,7 +320,7 @@ def main():
|
|
|
360
320
|
parser.add_argument(
|
|
361
321
|
"--context-file",
|
|
362
322
|
type=Path,
|
|
363
|
-
help="Optional current browser metadata for fields missing from
|
|
323
|
+
help="Optional current browser metadata for venue fields missing from static data",
|
|
364
324
|
)
|
|
365
325
|
parser.add_argument(
|
|
366
326
|
"--save-basket",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Synchronous selection and explicit purchase client for observed Wolt hosts."""
|
|
2
2
|
|
|
3
3
|
from .auth import RefreshTokenCredentials
|
|
4
|
+
from .basket import Basket
|
|
4
5
|
from .client import WoltClient
|
|
5
6
|
from .credentials import SessionCredentials
|
|
6
7
|
from .errors import (
|
|
@@ -50,6 +51,7 @@ from .transport import WoltTransport
|
|
|
50
51
|
__all__ = [
|
|
51
52
|
"DeliveryTarget",
|
|
52
53
|
"DeliverySelection",
|
|
54
|
+
"Basket",
|
|
53
55
|
"DuplicatePurchaseAttempt",
|
|
54
56
|
"HTTPStatusError",
|
|
55
57
|
"ItemSelection",
|