-
-
Save Bahus/19c9350f083678797e5bacb873ef827b to your computer and use it in GitHub Desktop.
from decimal import Decimal | |
import pydantic | |
@shared_task | |
def get_provider_api_stocks(api_key, url_constructor, deserialize_constructor): | |
# api_key в принципе нельзя передавать так | |
return True | |
from typing import Protocol | |
class BaseCodeProviderClient(Protocol): | |
@abstractmethod | |
def get_one_game_detail_stock(): | |
return True | |
@abstractmethod | |
def get_codes_from_order(): | |
return True | |
@abstractmethod | |
def get_orders_history(): | |
return True | |
@abstractmethod | |
def get_detail_of_order(self, order_id: str): | |
return True | |
def get_profitable_stocks_info(params): | |
get_provider_api_stocks(params) | |
get_one_game_detail_stock(params) | |
class HTTPClient: | |
def __init__( | |
self, | |
base_url: str, | |
retry_policy: Retry(connect=2, read=2), | |
timeout_policy: TimePolicy(5, 20), | |
auth: BasicHTTPAuth(user, password), | |
middleware = [HTTPLoggingMiddleware, HTTPMetricsMiddleware, HTTPXRequestID], | |
session: Optional[requests.Session] = None # requests.Session(), | |
): | |
pass | |
class OrderDetails(pydantic.BaseModel): | |
id: int | |
amount: Decimal | |
code: str | |
class GameEXECodesProvider(BaseCodeProviderClient): | |
slug = 'game_exe' | |
def __init__(self, provider: 'CodeProvider'): | |
self._provider = provider | |
self._http_client = HTTPClient( | |
base_url=provider.url, | |
auth=provider.get_auth(), | |
) | |
def get_detail_of_order(self, order_id: str) -> OrderDetails: | |
response = self._http_client.get(f'/orders/{order_id}') | |
return OrderDetails.parse_obj(response.json()) | |
class Codes1Provider(BaseCodeProviderClient): | |
slug = 'code_1' | |
def get_one_game_detail_stock(self): | |
"""do something""" | |
class Codes2Provider(BaseCodeProviderClient): | |
slug = 'code_2' | |
def get_orders_history(self, ...): | |
"""do something""" | |
AVAILABLE_PROVIDERS = { | |
GameEXECodesProvider.slug: GameEXECodesProvider, | |
Codes1Provider.slug: Codes1Provider, | |
Codes2Provider.slug: Codes2Provider, | |
} | |
class CodeProvider(Model): | |
slug = TextField(unique=True) | |
url = URLField() | |
# Authentication data can be different between providers | |
auth_data = JSONField() | |
@shared_task | |
def gather_new_codes_dispatcher(): | |
"""Scheduled tasks, executed every hour and gather all new available codes from providers.""" | |
for provider_id in CodeProvider.objects.values_list('id', flat=True): | |
gather_new_cored_for_provider(provider_id=provider_id).apply_async() | |
@shared_task | |
def gather_new_cored_for_provider(*, provider_id: int): | |
provider = CodeProvider.objects.get(id=provider_id) | |
provider_client: BaseCodeProviderClient = AVAILABLE_PROVIDERS[provider.slug](provider=provider) | |
codes = provider_client.gather_codes() | |
save_codes() |
GameEXECodesProvider — а что ты имел ввиду под exe? .exe расширение или что провайдер бывший? или ещё что-то?
я придумал это имя
я придумал это имя
ну это понятно. Какой ты смысл вкладывал, я имею ввиду?
а почему нельзя прямо в коде во время инициализации объекта доставать его из базы? Зачем его явно передавать?
def __init__(self):
self._provider = Provider.objects.get(slug=self.slug)
self._http_client = HTTPClient(
base_url=self._provider.url,
auth=self._provider.get_auth(),
)
в __init__
не стоит вообще никаких сложных действий делать (ходить в базу, ходить по http) и т.д. так как это считается сайд эффектом, в инициализаторе обычно идет присвоение данных, сами данные передаются из получаются из вне.
В указанном тобой случае класс бы выглядел так:
class GameEXECodesProvider(BaseCodeProviderClient):
def __init__(self, provider_slug: str):
self._provider_slug = provider_slug
@cached_property
def provider(self) -> 'Provider':
return Provider.objects.get(slug=self.slug)
в
__init__
не стоит вообще никаких сложных действий делать (ходить в базу, ходить по http) и т.д. так как это считается сайд эффектом, в инициализаторе обычно идет присвоение данных, сами данные передаются из получаются из вне.В указанном тобой случае класс бы выглядел так:
class GameEXECodesProvider(BaseCodeProviderClient): def __init__(self, provider_slug: str): self._provider_slug = provider_slug @cached_property def provider(self) -> 'Provider': return Provider.objects.get(slug=self.slug)
аа, ну да. Не вопрос. Так, что такой вариант c получением объекта из класса, тоже норм ?
это не рабочий код, это пример, все методы должны быть определены