Skip to content

Commit af7cdaa

Browse files
committed
docs and fixes
1 parent f069b4e commit af7cdaa

9 files changed

Lines changed: 220 additions & 170 deletions

File tree

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ install-dev:
77
pip install -e .[dev]
88

99
test:
10-
pytest --cov=chizhik_api --cov-report=xml --cov-report=html --cov-report=term-missing
10+
pytest --cov=pyaterochka_api --cov-report=xml --cov-report=html --cov-report=term-missing
1111

1212
test-quick:
1313
pytest --tb=short
1414

1515
format:
16-
black chizhik_api/ tests/
17-
isort chizhik_api/ tests/
16+
black pyaterochka_api/ tests/
17+
isort pyaterochka_api/ tests/
1818

1919
clean:
2020
rm -rf build/ dist/ *.egg-info/

pyaterochka_api/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from .manager import PyaterochkaAPI
21
from .enums import PurchaseMode, Sorting
2+
from .manager import PyaterochkaAPI
33

44
__version__ = "0.2.0.1"
5-
__all__ = ['PyaterochkaAPI', 'PurchaseMode', 'Sorting']
5+
__all__ = ["PyaterochkaAPI", "PurchaseMode", "Sorting"]
Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Реклама"""
22

3-
from typing import TYPE_CHECKING, Literal
3+
from typing import TYPE_CHECKING, Literal, Optional
44

55
from human_requests.abstraction import FetchResponse, HttpMethod
66

@@ -17,18 +17,36 @@ class ClassAdvertising:
1717
def __init__(self, parent: "PyaterochkaAPI"):
1818
self._parent: "PyaterochkaAPI" = parent
1919

20-
async def news(self,
21-
limit: int = 12,
22-
offset: int = 0):
20+
async def news(self, limit: int = 12, offset: int = 0):
21+
"""Список новостей. Сортировка: сначала новые"""
2322
request_url = f"{self._parent.SECOND_API_URL}/public/v1/news/?limit={limit}&offset={offset}"
24-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=False, credentials=False)
25-
26-
async def promo_offers(self,
27-
limit: int = 20,
28-
web_version: bool = True,
29-
type_offers: Literal["mainpage_promotion",
30-
"zooclub_promotion",
31-
"childrenclub_promotion",
32-
"barclub_promotion"] = "mainpage_promotion") -> FetchResponse:
33-
request_url = f"{self._parent.SECOND_API_URL}/public/v1/promo-offers/?limit={limit}&web_version={str(web_version).lower()}&type={type_offers}"
34-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=False, credentials=False)
23+
return await self._parent._request(
24+
method=HttpMethod.GET,
25+
url=request_url,
26+
add_unstandard_headers=False,
27+
credentials=False,
28+
)
29+
30+
async def promo_offers(
31+
self,
32+
limit: int = 20,
33+
web_version: bool = True,
34+
type_offers: Optional[
35+
Literal[
36+
"mainpage_promotion",
37+
"zooclub_promotion",
38+
"childrenclub_promotion",
39+
"barclub_promotion",
40+
]
41+
] = None,
42+
) -> FetchResponse:
43+
"""Промо-реклама с необязательным фильтром по топику."""
44+
request_url = f"{self._parent.SECOND_API_URL}/public/v1/promo-offers/?limit={limit}&web_version={str(web_version).lower()}"
45+
if type_offers:
46+
request_url += f"&type={type_offers}"
47+
return await self._parent._request(
48+
method=HttpMethod.GET,
49+
url=request_url,
50+
add_unstandard_headers=False,
51+
credentials=False,
52+
)
Lines changed: 72 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
"""Работа с каталогом"""
22

3-
from typing import TYPE_CHECKING, Optional
43
import urllib.parse
4+
from typing import TYPE_CHECKING, Optional
5+
56
from human_requests.abstraction import FetchResponse, HttpMethod
67

78
from ..enums import PurchaseMode, Sorting
9+
810
if TYPE_CHECKING:
911
from ..manager import PyaterochkaAPI
1012

@@ -18,108 +20,101 @@ class ClassCatalog:
1820

1921
def __init__(self, parent: "PyaterochkaAPI"):
2022
self._parent: "PyaterochkaAPI" = parent
21-
self.Product: ProductService = ProductService(
22-
parent=self._parent
23-
)
23+
self.Product: ProductService = ProductService(parent=self._parent)
2424
"""Сервис для работы с товарами в каталоге."""
2525

26-
async def tree(self,
27-
sap_code_store_id: str,
28-
subcategories: bool = False,
29-
include_restrict: bool = True,
30-
mode: PurchaseMode = PurchaseMode.STORE) -> FetchResponse:
26+
async def tree(
27+
self,
28+
sap_code_store_id: str,
29+
subcategories: bool = False,
30+
include_restrict: bool = True,
31+
mode: PurchaseMode = PurchaseMode.STORE,
32+
) -> FetchResponse:
3133
"""
32-
Asynchronously retrieves a list of categories from the Pyaterochka API.
34+
Список категорий (глобальный).
3335
34-
Args:
35-
subcategories (bool, optional): Whether to include subcategories in the response. Defaults to False.
36-
include_restrict (bool, optional): I DO NOT KNOW WHAT IS IT
37-
mode (PurchaseMode, optional): The purchase mode to use. Defaults to PurchaseMode.STORE.
38-
sap_code_store_id (str, optional): The store ID (official name in API is "sap_code") to use. Defaults to "{self.DEFAULT_STORE_ID}". This lib not support search ID stores.
39-
40-
Returns:
41-
list[dict]: A dictionary representing the categories list if the request is successful, error otherwise.
42-
43-
Raises:
44-
Exception: If the response status is not 200 (OK) or 403 (Forbidden / Anti-bot).
36+
include_restrict - включать ли в выдачу закончившиеся в магазине товары.
4537
"""
4638

4739
request_url = f"{self._parent.CATALOG_URL}/catalog/v2/stores/{sap_code_store_id}/categories?mode={mode.value}&include_restrict={include_restrict}&include_subcategories={1 if subcategories else 0}"
48-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
40+
return await self._parent._request(
41+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
42+
)
4943

50-
async def tree_extended(self,
51-
sap_code_store_id: str,
52-
category_id: str,
53-
include_restrict: bool = True,
54-
mode: PurchaseMode = PurchaseMode.STORE) -> FetchResponse:
44+
async def tree_extended(
45+
self,
46+
sap_code_store_id: str,
47+
category_id: str,
48+
include_restrict: bool = True,
49+
mode: PurchaseMode = PurchaseMode.STORE,
50+
) -> FetchResponse:
5551
"""Расширенное представление категории и её подкатегорий."""
5652
request_url = f"{self._parent.CATALOG_URL}/catalog/v2/stores/{sap_code_store_id}/categories/{category_id}/extended?mode={mode.value}&include_restrict={str(include_restrict).lower()}"
57-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
58-
59-
async def search(self,
60-
sap_code_store_id: str,
61-
query: str,
62-
include_restrict: bool = True,
63-
mode: PurchaseMode = PurchaseMode.STORE,
64-
limit: int = 12) -> FetchResponse:
53+
return await self._parent._request(
54+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
55+
)
56+
57+
async def search(
58+
self,
59+
sap_code_store_id: str,
60+
query: str,
61+
include_restrict: bool = True,
62+
mode: PurchaseMode = PurchaseMode.STORE,
63+
limit: int = 12,
64+
) -> FetchResponse:
6565
"""Поиск по товарам И категориям."""
6666
q = urllib.parse.quote(query)
6767
request_url = f"{self._parent.CATALOG_URL}/catalog/v3/stores/{sap_code_store_id}/search?mode={mode.value}&include_restrict={str(include_restrict).lower()}&q={q}&limit={limit}"
68-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
68+
return await self._parent._request(
69+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
70+
)
6971

7072
async def products_list(
71-
self,
72-
category_id: str,
73-
sap_code_store_id: str,
74-
price_min: Optional[int] = None,
75-
price_max: Optional[int] = None,
76-
brands: list[str] = [],
77-
include_restrict: bool = True,
78-
mode: PurchaseMode = PurchaseMode.STORE,
79-
limit: int = 30
73+
self,
74+
category_id: str,
75+
sap_code_store_id: str,
76+
price_min: Optional[int] = None,
77+
price_max: Optional[int] = None,
78+
brands: list[str] = [],
79+
include_restrict: bool = True,
80+
mode: PurchaseMode = PurchaseMode.STORE,
81+
limit: int = 30,
8082
) -> FetchResponse:
81-
f"""
82-
Asynchronously retrieves a list of products from the Pyaterochka API for a given category.
83-
84-
Args:
85-
category_id (str): The ID of the (sub)category.
86-
mode (PurchaseMode, optional): The purchase mode to use. Defaults to PurchaseMode.STORE.
87-
sap_code_store_id (str, optional): The store ID (official name in API is "sap_code") to use. This lib not support search ID stores.
88-
limit (int, optional): The maximum number of products to retrieve. Defaults to 30. Must be between 1 and 499.
89-
90-
Returns:
91-
dict: A dictionary representing the products list if the request is successful, error otherwise.
83+
"""
84+
Список категорий (основная лента каталога).
9285
93-
Raises:
94-
ValueError: If the limit is not between 1 and 499.
95-
Exception: If the response status is not 200 (OK) or 403 (Forbidden / Anti-bot).
86+
brands - должно быть полное совпадение, другие едпоинты предоставляют их.
9687
"""
9788

9889
if limit < 1 or limit >= 500:
9990
raise ValueError("Limit must be between 1 and 499")
10091

10192
request_url = f"{self._parent.CATALOG_URL}/catalog/v2/stores/{sap_code_store_id}/categories/{category_id}/products?mode={mode.value}&limit={limit}&include_restrict={str(include_restrict).lower()}"
10293
if price_min:
103-
request_url += "&price_min="+str(price_min)
94+
request_url += "&price_min=" + str(price_min)
10495
if price_max:
105-
request_url += "&price_max="+str(price_max)
96+
request_url += "&price_max=" + str(price_max)
10697
if len(brands) > 0:
107-
encoded_brands = [f'brands={urllib.parse.quote(brand)}' for brand in brands]
108-
request_url += "&" + '&&'.join(encoded_brands)
98+
encoded_brands = [f"brands={urllib.parse.quote(brand)}" for brand in brands]
99+
request_url += "&" + "&&".join(encoded_brands)
109100

110-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
101+
return await self._parent._request(
102+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
103+
)
111104

112105
async def products_line(
113-
self,
114-
category_id: str,
115-
sap_code_store_id: str,
116-
include_restrict: bool = True,
117-
mode: PurchaseMode = PurchaseMode.STORE,
118-
order_by: Sorting = Sorting.POPULARITY
119-
) -> FetchResponse:
106+
self,
107+
category_id: str,
108+
sap_code_store_id: str,
109+
include_restrict: bool = True,
110+
mode: PurchaseMode = PurchaseMode.STORE,
111+
order_by: Sorting = Sorting.POPULARITY,
112+
) -> FetchResponse:
120113
"""Рекомендованные товары \"что интересного?\"."""
121114
request_url = f"{self._parent.CATALOG_URL}/catalog/v1/stores/{sap_code_store_id}/categories/{category_id}/products_line?mode={mode.value}&include_restrict={str(include_restrict).lower()}&order_by={order_by.value}"
122-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
115+
return await self._parent._request(
116+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
117+
)
123118

124119

125120
class ProductService:
@@ -133,18 +128,12 @@ async def info(
133128
sap_code_store_id: str,
134129
plu_id: int,
135130
mode: PurchaseMode = PurchaseMode.STORE,
136-
include_restrict: bool = True
131+
include_restrict: bool = True,
137132
) -> FetchResponse:
138133
"""
139-
Asynchronously retrieves product information from the Pyaterochka API for a given PLU ID. Average time processing 2 seconds (first start 6 seconds).
140-
141-
Args:
142-
plu_id (int): The PLU ID of the product.
143-
Returns:
144-
dict: A dictionary representing the product information.
145-
Raises:
146-
ValueError: If the response does not contain the expected JSON data.
134+
Подробная информация о конкретном товаре.
147135
"""
148-
149136
request_url = f"{self._parent.CATALOG_URL}/catalog/v2/stores/{sap_code_store_id}/products/{plu_id}?mode={mode.value}&include_restrict={str(include_restrict).lower()}"
150-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
137+
return await self._parent._request(
138+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
139+
)

pyaterochka_api/endpoints/general.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
from io import BytesIO
44
from typing import TYPE_CHECKING
5-
from aiohttp_retry import RetryClient, ExponentialRetry
65

6+
from aiohttp_retry import ExponentialRetry, RetryClient
77

88
if TYPE_CHECKING:
99
from ..manager import PyaterochkaAPI
@@ -19,13 +19,14 @@ class ClassGeneral:
1919
def __init__(self, parent: "PyaterochkaAPI"):
2020
self._parent: "PyaterochkaAPI" = parent
2121

22-
async def download_image(self,
23-
url: str,
24-
retry_attempts: int = 3,
25-
timeout: float = 10) -> BytesIO:
22+
async def download_image(
23+
self, url: str, retry_attempts: int = 3, timeout: float = 10
24+
) -> BytesIO:
2625
"""Скачать изображение по URL."""
27-
retry_options = ExponentialRetry(attempts=retry_attempts, start_timeout=3.0, max_timeout=timeout)
28-
26+
retry_options = ExponentialRetry(
27+
attempts=retry_attempts, start_timeout=3.0, max_timeout=timeout
28+
)
29+
2930
async with RetryClient(retry_options=retry_options) as retry_client:
3031
async with retry_client.get(url, raise_for_status=True) as resp:
3132
body = await resp.read()
Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""Геолокация"""
22

3-
from typing import TYPE_CHECKING, Optional
43
import urllib
4+
from typing import TYPE_CHECKING, Optional
55

66
from human_requests.abstraction import FetchResponse, HttpMethod
77

@@ -21,34 +21,35 @@ def __init__(self, parent: "PyaterochkaAPI"):
2121

2222
async def find_store(self, longitude: float, latitude: float) -> FetchResponse:
2323
"""
24-
Asynchronously finds the store associated with the given coordinates.
25-
26-
Args:
27-
longitude (float): The longitude of the location.
28-
latitude (float): The latitude of the location.
29-
30-
Returns:
31-
dict: A dictionary representing the store information if the request is successful, error otherwise.
24+
Найти магазин ближайший (закрепленный) за этой местностью.
3225
"""
3326

3427
request_url = f"{self._parent.CATALOG_URL}/orders/v1/orders/stores/?lon={longitude}&lat={latitude}"
35-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
28+
return await self._parent._request(
29+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
30+
)
3631

3732
async def suggest(self, query: str) -> FetchResponse:
38-
"""Начинайте вводить адрес, он предложит точные варианты"""
33+
"""Начинайте вводить адрес, он предложит точные варианты."""
3934
request_url = f"{self._parent.MAIN_SITE_URL}/api/maps/suggest/?text={urllib.parse.quote(query)}"
40-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
41-
42-
async def geocode(self,
43-
country: str = "Россия",
44-
city: str = "Москва",
45-
street: str = "проспект Мира",
46-
house: Optional[str] = None) -> FetchResponse:
35+
return await self._parent._request(
36+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
37+
)
38+
39+
async def geocode(
40+
self,
41+
country: str = "Россия",
42+
city: str = "Москва",
43+
street: str = "проспект Мира",
44+
house: Optional[str] = None,
45+
) -> FetchResponse:
4746
"""Возвращает геокод (геопозицию) на четкий запрос (используй suggest)"""
4847
tup = [country, city, street]
4948
if house:
5049
tup.append(house)
5150
string = urllib.parse.quote(", ".join(tup))
52-
51+
5352
request_url = f"{self._parent.MAIN_SITE_URL}/api/maps/geocode/?geocode={string}"
54-
return await self._parent._request(method=HttpMethod.GET, url=request_url, add_unstandard_headers=True)
53+
return await self._parent._request(
54+
method=HttpMethod.GET, url=request_url, add_unstandard_headers=True
55+
)

0 commit comments

Comments
 (0)