Skip to content

Commit

Permalink
Merge branch 'ahivert:master' into max-cookie
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxWinterstein authored Aug 7, 2024
2 parents e726861 + b4b4a2b commit f8d4d4f
Show file tree
Hide file tree
Showing 12 changed files with 713 additions and 430 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
custom: [buymeacoffee.com/ahivert, paypal.me/ahivert]
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
Expand Down
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
repos:
- repo: https://github.com/psf/black
rev: 22.10.0
rev: 24.1.1
hooks:
- id: black
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
rev: 7.0.0
hooks:
- id: flake8
106 changes: 100 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@

Python client that help you to talk with [TooGoodToGo](https://toogoodtogo.com) API.

Python version: 3.7+
Python version: 3.8+

Handle:

- create an account (`auth/vX/signUpByEmail`)
- create an account (`/api/auth/vX/signUpByEmail`)
- login (`/api/auth/vX/authByEmail`)
- refresh token (`/api/auth/vX/token/refresh`)
- list stores (`/api/item/`)
- get a store (`/api/item/:id`)
- set favorite (`/api/item/:id/setFavorite`)
- list stores (`/api/item/vX`)
- get a store (`/api/item/vX/:id`)
- get favorites (`/api/discover/vX/bucket`)
- set favorite (`/api/user/favorite/vX/:id/update`)
- create an order (`/api/order/vX/create/:id`)
- abort an order (`/api/order/vX/:id/abort`)
- get the status of an order (`/api/order/vX/:id/status`)
- get active orders (`/api/order/vX/active`)
- get inactive orders (`/api/order/vX/inactive`)

Expand Down Expand Up @@ -87,7 +91,7 @@ print(items)
{
"item": {
"item_id": "64346",
"price": {"code": "EUR", "minor_units": 499, "decimals": 2},
"item_price": {"code": "EUR", "minor_units": 499, "decimals": 2},
"sales_taxes": [],
"tax_amount": {"code": "EUR", "minor_units": 0, "decimals": 2},
"price_excluding_taxes": {"code": "EUR", "minor_units": 499, "decimals": 2},
Expand Down Expand Up @@ -416,6 +420,85 @@ print(item)

</details>

## Create an order

```python
order = client.create_order(item_id, number_of_items_to_order)
print(order)
```

<details>
<summary>Example response</summary>

```python
{
"id": "<order_id>",
"item_id": "<item_id_that_was_ordered>",
"user_id": "<your_user_id>",
"state": "RESERVED",
"order_line": {
"quantity": 1,
"item_price_including_taxes": {
"code": "EUR",
"minor_units": 600,
"decimals": 2
},
"item_price_excluding_taxes": {
"code": "EUR",
"minor_units": 550,
"decimals": 2
},
"total_price_including_taxes": {
"code": "EUR",
"minor_units": 600,
"decimals": 2
},
"total_price_excluding_taxes": {
"code": "EUR",
"minor_units": 550,
"decimals": 2
}
},
"reserved_at": "2023-01-01T10:30:32.331280392",
"order_type": "MAGICBAG"
}
```

</details>

Please note that payment of an order is currently not implemented.
In other words: you can create an order via this client, but you can not pay for it.

### Get the status of an order

```python
order_status = client.get_order_status(order_id)
print(order_status)
```

<details>
<summary>Example response</summary>

```python
{
"id": "<order_id>",
"item_id": "<item_id_that_was_ordered>",
"user_id": "<your_user_id>",
"state": "RESERVED"
}
```

</details>

### Abort an order
```python
client.abort_order(order_id)
```

When successful, this call will not return a value.

The app uses this call when the user aborts an order before paying for it. When the order has been payed, the app uses a different call.

### Get active orders

```python
Expand Down Expand Up @@ -461,6 +544,17 @@ To e.g. sum up all orders you have ever made:
)
```

### Get favorites

This will list all the currently set favorite stores.

```python
favorites = client.get_favorites()
print(favorites)
```

The behavior of `get_favorites` is more or less the same as `get_items()`, but better mimics the official application.

### Set favorite

_(Using item_id from get_items response)_
Expand Down
737 changes: 367 additions & 370 deletions poetry.lock

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
[tool.poetry]
name = "tgtg"
version = "0.13.2"
version = "0.17.0"
description = "Unoffical python client for TooGoodToGo API"
readme = "README.md"
authors = ["Anthony Hivert <[email protected]>"]
repository = "https://github.com/ahivert/tgtg-python"

[tool.poetry.dependencies]
python = "^3.7"
python = "^3.8"
requests = "^2.27.1"

[tool.isort]
profile = "black"

[tool.poetry.dev-dependencies]
freezegun = "^1.2.2"
pre-commit = "^2.21.0"
pytest = "^7.2.1"
pytest-cov = "^4.0.0"
freezegun = "^1.4.0"
pre-commit = "^3.5.0"
pytest = "^8.0.0"
pytest-cov = "^4.1.0"
pytest-responses = "^0.5.1"
responses = "^0.22.0"
typed-ast = "^1.5.4"
responses = "^0.24.1"
typed-ast = "^1.5.5"

[build-system]
requires = ["poetry>=0.12"]
requires = ["poetry-core>=1.5.0"]
build-backend = "poetry.masonry.api"
8 changes: 8 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
AUTH_POLLING_ENDPOINT,
BASE_URL,
REFRESH_ENDPOINT,
TgtgClient,
)

from .constants import tgtg_client_fake_tokens


@pytest.fixture(scope="function")
def auth_by_email_response():
Expand Down Expand Up @@ -47,3 +50,8 @@ def refresh_tokens_response():
status=200,
adding_headers={"set-cookie": "sweet sweet cookie"},
)


@pytest.fixture(scope="function")
def client(refresh_tokens_response):
yield TgtgClient(**tgtg_client_fake_tokens)
16 changes: 5 additions & 11 deletions tests/test_active.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,18 @@
import pytest
import responses

from tgtg import ACTIVE_ORDER_ENDPOINT, BASE_URL, INACTIVE_ORDER_ENDPOINT, TgtgClient
from tgtg import ACTIVE_ORDER_ENDPOINT, BASE_URL, INACTIVE_ORDER_ENDPOINT
from tgtg.exceptions import TgtgAPIError

from .constants import tgtg_client_fake_tokens


def test_get_active_success(refresh_tokens_response):
def test_get_active_success(client):
responses.add(
responses.POST,
urljoin(BASE_URL, ACTIVE_ORDER_ENDPOINT),
json={"orders": []},
status=200,
headers={"set-cookie": "session_id=12345; a=b; c=d"},
)
client = TgtgClient(**tgtg_client_fake_tokens)
assert client.get_active()["orders"] == []
assert (
len(
Expand All @@ -31,23 +28,21 @@ def test_get_active_success(refresh_tokens_response):
)


def test_get_active_fail(refresh_tokens_response):
def test_get_active_fail(client):
responses.add(
responses.POST, urljoin(BASE_URL, ACTIVE_ORDER_ENDPOINT), json={}, status=400
)
client = TgtgClient(**tgtg_client_fake_tokens)
with pytest.raises(TgtgAPIError):
client.get_active()


def test_get_inactive_success(refresh_tokens_response):
def test_get_inactive_success(client):
responses.add(
responses.POST,
urljoin(BASE_URL, INACTIVE_ORDER_ENDPOINT),
json={"orders": []},
status=200,
)
client = TgtgClient(**tgtg_client_fake_tokens)
assert client.get_inactive()["orders"] == []
assert (
len(
Expand All @@ -61,10 +56,9 @@ def test_get_inactive_success(refresh_tokens_response):
)


def test_get_inactive_fail(refresh_tokens_response):
def test_get_inactive_fail(client):
responses.add(
responses.POST, urljoin(BASE_URL, INACTIVE_ORDER_ENDPOINT), json={}, status=400
)
client = TgtgClient(**tgtg_client_fake_tokens)
with pytest.raises(TgtgAPIError):
client.get_inactive()
Loading

0 comments on commit f8d4d4f

Please sign in to comment.