diff --git a/.travis.yml b/.travis.yml index fdec0b8..05d69f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,16 +5,10 @@ python: - "3.9" - "3.8" - "3.7" - - "3.6" - - "3.5" matrix: include: - - python: 3.4 + - python: 3.8 dist: xenial - - python: 2.7 - before_install: - - pip install -U mock - - pip install -U pytest # command to install dependencies install: - pip install -r requirements.txt && pip install -e . diff --git a/README.en.md b/README.en.md index ed67490..f41eb8a 100644 --- a/README.en.md +++ b/README.en.md @@ -11,7 +11,7 @@ This product is used for managing payments under [The YooKassa API](https://yook For usage by those who implemented YooKassa using the API method. ## Requirements -1. Python 2.7 or Python 3.x +1. Python >=3.7 2. pip ## Installation diff --git a/README.md b/README.md index 6d5d42d..1c7b098 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# YooKassa API Python Client Library +# YooKassa ASync API Python Client Library [![Build Status](https://travis-ci.org/yoomoney/yookassa-sdk-python.svg?branch=master)](https://travis-ci.org/yoomoney/yookassa-sdk-python) [![Latest Stable Version](https://img.shields.io/pypi/v/yookassa.svg)](https://pypi.org/project/yookassa/) @@ -10,9 +10,11 @@ Russian | [English](https://github.com/yoomoney/yookassa-sdk-python/blob/master/ Клиент для работы с платежами по [API ЮKassa](https://yookassa.ru/developers/api) Подходит тем, у кого способ подключения к ЮKassa называется API. +Асинхронная версия. + ## Требования -1. Python 2.7 or Python 3.x +1. Python >=3.7 2. pip ## Установка @@ -113,4 +115,4 @@ Configuration.configure_user_agent( * [Запрос на создание чека](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Запрос-на-создание-чека) * [Запрос на создание чека через билдер](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Запрос-на-создание-чека-через-билдер) * [Получить информацию о чеке](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Получить-информацию-о-чеке) -* [Получить список чеков с фильтрацией](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Получить-список-чеков-с-фильтрацией) \ No newline at end of file +* [Получить список чеков с фильтрацией](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Получить-список-чеков-с-фильтрацией) diff --git a/docs/examples/01-configuration.md b/docs/examples/01-configuration.md index 4e2ab9c..f2a2331 100644 --- a/docs/examples/01-configuration.md +++ b/docs/examples/01-configuration.md @@ -87,8 +87,7 @@ var_dump.var_dump(me) ```python import var_dump as var_dump -from yookassa import Webhook -from yookassa.domain.notification import WebhookNotificationEventType +from yookassa.domain.notification import WebhookNotification, WebhookNotificationEventType whUrl = 'https://merchant-site.ru/payment-notification' needWebhookList = [ diff --git a/requirements.txt b/requirements.txt index 0e808d3..c0f9091 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +httpx requests setuptools urllib3 diff --git a/setup.py b/setup.py index 252f22d..10d8c65 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ For usage by those who implemented YooKassa using the API method. ## Requirements -1. Python 2.7 or Python 3.x +1. Python >=3.7 2. pip ## Installation @@ -102,7 +102,7 @@ version = re.search(r"__version__\s*=\s*'(.*)'", fp.read()).group(1) setup( - name="yookassa", + name="yookassa-async", author="YooMoney", author_email="cms@yoomoney.ru", version=version, @@ -113,17 +113,14 @@ url="https://github.com/yoomoney/yookassa-sdk-python", package_dir={"": "src"}, packages=find_packages('src'), - install_requires=["requests", "urllib3", "netaddr", "distro", "deprecated"], + install_requires=["httpx", "requests", "urllib3", "netaddr", "distro", "deprecated"], zip_safe=False, license="MIT", classifiers=[ "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9" + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10" ] ) diff --git a/src/yookassa/client.py b/src/yookassa/client.py index 358c939..3036c6d 100644 --- a/src/yookassa/client.py +++ b/src/yookassa/client.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -import requests -from requests.adapters import HTTPAdapter +import typing +import httpx +import time from requests.auth import _basic_auth_str -from urllib3 import Retry from yookassa import Configuration from yookassa.domain.common import RequestObject, UserAgent @@ -10,6 +10,41 @@ ResponseProcessingError, TooManyRequestsError, UnauthorizedError +class RetryTransport(httpx.HTTPTransport): + """ Адаптация urllib3.Retry для HTTPX """ + + def __init__(self, *args, total: int = 3, backoff_factor: float = 1, method_whitelist: typing.Optional[list] = None, status_forcelist: typing.Optional[list] = None, **kwargs): + super(RetryTransport, self).__init__(*args, **kwargs) + self.total = total + self.backoff_factor = backoff_factor + self.method_whitelist = method_whitelist + self.status_forcelist = status_forcelist + + def handle_request( + self, + request: httpx.Request, + ) -> httpx.Response: + retry = 0 + resp = None + retry_active = not self.method_whitelist or request.method in self.method_whitelist + while retry < self.total: + retry += 1 + if retry > 2: + time.sleep(self.backoff_factor) + try: + if resp is not None: + resp.close() + resp = super().handle_request(request) + except Exception: + if not retry_active: + raise + continue + if self.status_forcelist and resp.status_code in self.status_forcelist: + continue + break + return resp + + class ApiClient: endpoint = Configuration.api_endpoint() @@ -29,35 +64,34 @@ def __init__(self): if self.configuration.agent_module: self.user_agent.module = self.configuration.agent_module - def request(self, method="", path="", query_params=None, headers=None, body=None): + async def request(self, method="", path="", query_params=None, headers=None, body=None): if isinstance(body, RequestObject): body.validate() body = dict(body) request_headers = self.prepare_request_headers(headers) - raw_response = self.execute(body, method, path, query_params, request_headers) + raw_response = await self.execute(body, method, path, query_params, request_headers) if raw_response.status_code != 200: self.__handle_error(raw_response) return raw_response.json() - def execute(self, body, method, path, query_params, request_headers): + async def execute(self, body, method, path, query_params, request_headers): session = self.get_session() raw_response = session.request(method, - self.endpoint + path, + f'{self.endpoint}{path}', params=query_params, headers=request_headers, - json=body) + json=body, + timeout=None) return raw_response - def get_session(self): - session = requests.Session() - retries = Retry(total=self.max_attempts, - backoff_factor=self.timeout / 1000, - method_whitelist=['POST'], - status_forcelist=[202]) - session.mount('https://', HTTPAdapter(max_retries=retries)) + def get_session(self) -> httpx.Client: + session = httpx.Client( + timeout=httpx.Timeout(self.timeout / 1000, connect=self.timeout / 1000), + transport=RetryTransport() + ) return session def prepare_request_headers(self, headers): diff --git a/src/yookassa/deal.py b/src/yookassa/deal.py index bef433c..ac73d80 100644 --- a/src/yookassa/deal.py +++ b/src/yookassa/deal.py @@ -14,7 +14,7 @@ def __init__(self): self.client = ApiClient() @classmethod - def find_one(cls, deal_id): + async def find_one(cls, deal_id): """ Get receipt information @@ -26,11 +26,11 @@ def find_one(cls, deal_id): raise ValueError('Invalid payment_id value') path = instance.base_path + '/' + deal_id - response = instance.client.request(HttpVerb.GET, path) + response = await instance.client.request(HttpVerb.GET, path) return DealResponse(response) @classmethod - def create(cls, params, idempotency_key=None): + async def create(cls, params, idempotency_key=None): """ Create receipt @@ -55,13 +55,13 @@ def create(cls, params, idempotency_key=None): else: raise TypeError('Invalid params value type') - response = instance.client.request(HttpVerb.POST, path, None, headers, params_object) + response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object) return DealResponse(response) @classmethod - def list(cls, params): + async def list(cls, params): instance = cls() path = cls.base_path - response = instance.client.request(HttpVerb.GET, path, params) + response = await instance.client.request(HttpVerb.GET, path, params) return DealListResponse(response) diff --git a/src/yookassa/payment.py b/src/yookassa/payment.py index f81d0cb..33ba739 100644 --- a/src/yookassa/payment.py +++ b/src/yookassa/payment.py @@ -14,7 +14,7 @@ def __init__(self): self.client = ApiClient() @classmethod - def find_one(cls, payment_id): + async def find_one(cls, payment_id): """ Get information about payment @@ -26,11 +26,11 @@ def find_one(cls, payment_id): raise ValueError('Invalid payment_id value') path = instance.base_path + '/' + payment_id - response = instance.client.request(HttpVerb.GET, path) + response = await instance.client.request(HttpVerb.GET, path) return PaymentResponse(response) @classmethod - def create(cls, params, idempotency_key=None): + async def create(cls, params, idempotency_key=None): """ Create payment @@ -55,11 +55,11 @@ def create(cls, params, idempotency_key=None): else: raise TypeError('Invalid params value type') - response = instance.client.request(HttpVerb.POST, path, None, headers, params_object) + response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object) return PaymentResponse(response) @classmethod - def capture(cls, payment_id, params=None, idempotency_key=None): + async def capture(cls, payment_id, params=None, idempotency_key=None): """ Capture payment @@ -88,11 +88,11 @@ def capture(cls, payment_id, params=None, idempotency_key=None): else: params_object = None - response = instance.client.request(HttpVerb.POST, path, None, headers, params_object) + response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object) return PaymentResponse(response) @classmethod - def cancel(cls, payment_id, idempotency_key=None): + async def cancel(cls, payment_id, idempotency_key=None): """ Cancel payment @@ -111,13 +111,13 @@ def cancel(cls, payment_id, idempotency_key=None): headers = { 'Idempotence-Key': str(idempotency_key) } - response = instance.client.request(HttpVerb.POST, path, None, headers) + response = await instance.client.request(HttpVerb.POST, path, None, headers) return PaymentResponse(response) @classmethod - def list(cls, params): + async def list(cls, params): instance = cls() path = cls.base_path - response = instance.client.request(HttpVerb.GET, path, params) + response = await instance.client.request(HttpVerb.GET, path, params) return PaymentListResponse(response) diff --git a/src/yookassa/payout.py b/src/yookassa/payout.py index ce5027a..d4563f8 100644 --- a/src/yookassa/payout.py +++ b/src/yookassa/payout.py @@ -14,7 +14,7 @@ def __init__(self): self.client = ApiClient() @classmethod - def find_one(cls, payout_id): + async def find_one(cls, payout_id): """ Get receipt information @@ -26,11 +26,11 @@ def find_one(cls, payout_id): raise ValueError('Invalid payment_id value') path = instance.base_path + '/' + payout_id - response = instance.client.request(HttpVerb.GET, path) + response = await instance.client.request(HttpVerb.GET, path) return PayoutResponse(response) @classmethod - def create(cls, params, idempotency_key=None): + async def create(cls, params, idempotency_key=None): """ Create receipt @@ -55,5 +55,5 @@ def create(cls, params, idempotency_key=None): else: raise TypeError('Invalid params value type') - response = instance.client.request(HttpVerb.POST, path, None, headers, params_object) + response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object) return PayoutResponse(response) diff --git a/src/yookassa/receipt.py b/src/yookassa/receipt.py index 3cfb414..f26af4c 100644 --- a/src/yookassa/receipt.py +++ b/src/yookassa/receipt.py @@ -15,7 +15,7 @@ def __init__(self): self.client = ApiClient() @classmethod - def find_one(cls, receipt_id): + async def find_one(cls, receipt_id): """ Get receipt information @@ -27,11 +27,11 @@ def find_one(cls, receipt_id): raise ValueError('Invalid payment_id value') path = instance.base_path + '/' + receipt_id - response = instance.client.request(HttpVerb.GET, path) + response = await instance.client.request(HttpVerb.GET, path) return ReceiptResponse(response) @classmethod - def create(cls, params, idempotency_key=None): + async def create(cls, params, idempotency_key=None): """ Create receipt @@ -56,13 +56,13 @@ def create(cls, params, idempotency_key=None): else: raise TypeError('Invalid params value type') - response = instance.client.request(HttpVerb.POST, path, None, headers, params_object) + response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object) return ReceiptResponse(response) @classmethod - def list(cls, params): + async def list(cls, params): instance = cls() path = cls.base_path - response = instance.client.request(HttpVerb.GET, path, params) + response = await instance.client.request(HttpVerb.GET, path, params) return ReceiptListResponse(response) diff --git a/src/yookassa/refund.py b/src/yookassa/refund.py index 7879d0e..dcc130f 100644 --- a/src/yookassa/refund.py +++ b/src/yookassa/refund.py @@ -15,7 +15,7 @@ def __init__(self): self.client = ApiClient() @classmethod - def create(cls, params, idempotency_key=None): + async def create(cls, params, idempotency_key=None): """ Create refund @@ -38,11 +38,11 @@ def create(cls, params, idempotency_key=None): else: raise TypeError('Invalid params value type') - response = instance.client.request(HttpVerb.POST, path, None, headers, params_object) + response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object) return RefundResponse(response) @classmethod - def find_one(cls, refund_id): + async def find_one(cls, refund_id): """ Get refund information @@ -53,13 +53,13 @@ def find_one(cls, refund_id): if not isinstance(refund_id, str) or not refund_id: raise ValueError('Invalid payment_id value') path = instance.base_path + '/' + refund_id - response = instance.client.request(HttpVerb.GET, path) + response = await instance.client.request(HttpVerb.GET, path) return RefundResponse(response) @classmethod - def list(cls, params): + async def list(cls, params): instance = cls() path = cls.base_path - response = instance.client.request(HttpVerb.GET, path, params) + response = await instance.client.request(HttpVerb.GET, path, params) return RefundListResponse(response) diff --git a/src/yookassa/settings.py b/src/yookassa/settings.py index 2e86e9b..453dd68 100644 --- a/src/yookassa/settings.py +++ b/src/yookassa/settings.py @@ -10,7 +10,7 @@ def __init__(self): self.client = ApiClient() @classmethod - def get_account_settings(cls, params=None): + async def get_account_settings(cls, params=None): """ Shop Info @@ -21,5 +21,5 @@ def get_account_settings(cls, params=None): instance = cls() path = cls.base_path - response = instance.client.request(HttpVerb.GET, path, params) + response = await instance.client.request(HttpVerb.GET, path, params) return response diff --git a/src/yookassa/webhook.py b/src/yookassa/webhook.py index c99a285..ee3a883 100644 --- a/src/yookassa/webhook.py +++ b/src/yookassa/webhook.py @@ -19,11 +19,11 @@ def __init__(self): :return: WebhookList """ @classmethod - def list(cls): + async def list(cls): instance = cls() path = cls.base_path - response = instance.client.request(HttpVerb.GET, path) + response = await instance.client.request(HttpVerb.GET, path) return WebhookList(response) """ @@ -34,7 +34,7 @@ def list(cls): :return: WebhookResponse """ @classmethod - def add(cls, params, idempotency_key=None): + async def add(cls, params, idempotency_key=None): instance = cls() path = cls.base_path if not idempotency_key: @@ -50,7 +50,7 @@ def add(cls, params, idempotency_key=None): else: raise TypeError('Invalid params value type') - response = instance.client.request(HttpVerb.POST, path, None, headers, params_object) + response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object) return WebhookResponse(response) """ @@ -61,7 +61,7 @@ def add(cls, params, idempotency_key=None): :return: WebhookResponse """ @classmethod - def remove(cls, webhook_id, idempotency_key=None): + async def remove(cls, webhook_id, idempotency_key=None): instance = cls() path = cls.base_path + '/' + webhook_id if not idempotency_key: @@ -70,5 +70,5 @@ def remove(cls, webhook_id, idempotency_key=None): 'Idempotence-Key': str(idempotency_key) } - response = instance.client.request(HttpVerb.DELETE, path, None, headers) + response = await instance.client.request(HttpVerb.DELETE, path, None, headers) return WebhookResponse(response) diff --git a/test/unit/test_client.py b/test/unit/test_client.py index f7e3ffe..6bbb88e 100644 --- a/test/unit/test_client.py +++ b/test/unit/test_client.py @@ -17,7 +17,7 @@ from yookassa.domain.common.request_object import RequestObject -class TestClient(unittest.TestCase): +class TestClient(unittest.IsolatedAsyncioTestCase): def setUp(self): Configuration.configure(account_id='test_account_id', secret_key='test_secret_key') @@ -25,7 +25,7 @@ def setUp(self): Configuration.agent_cms = Version('YooMoney.Cms', '0.0.2') Configuration.agent_module = Version('YooMoney.Module', '0.0.3') - def test_request(self): + async def test_request(self): client = ApiClient() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -39,9 +39,9 @@ def test_request(self): 'status': 'canceled' } - client.request(HttpVerb.POST, '/path', RequestObject(), {'header': 'header'}) + await client.request(HttpVerb.POST, '/path', RequestObject(), {'header': 'header'}) - def test_execute(self): + async def test_execute(self): client = ApiClient() with patch('yookassa.client.ApiClient.execute') as request_mock: res = Response() @@ -49,4 +49,4 @@ def test_execute(self): res._content = b"{}" request_mock.return_value = res - client.request(HttpVerb.POST, '/path', RequestObject({"param": "param"}), {'header': 'header'}) + await client.request(HttpVerb.POST, '/path', RequestObject({"param": "param"}), {'header': 'header'}) diff --git a/test/unit/test_deal.py b/test/unit/test_deal.py index 187d9bc..888ce49 100644 --- a/test/unit/test_deal.py +++ b/test/unit/test_deal.py @@ -2,10 +2,7 @@ import sys import unittest -if sys.version_info >= (3, 3): - from unittest.mock import patch -else: - from mock import patch +from unittest.mock import patch from yookassa.configuration import Configuration from yookassa.domain.models.amount import Amount @@ -14,11 +11,11 @@ from yookassa.deal import Deal -class TestDealFacade(unittest.TestCase): +class TestDealFacade(unittest.IsolatedAsyncioTestCase): def setUp(self): Configuration.configure(account_id='test_account_id', secret_key='test_secret_key') - def test_create_deal_with_dict(self): + async def test_create_deal_with_dict(self): self.maxDiff = None deal_facade = Deal() with patch('yookassa.client.ApiClient.request') as request_mock: @@ -43,7 +40,7 @@ def test_create_deal_with_dict(self): "description": "SAFE_DEAL 123554642-2432FF344R", "test": False } - deal = deal_facade.create({ + deal = await deal_facade.create({ "type": "safe_deal", "fee_moment": "deal_closed", "metadata": { @@ -56,7 +53,7 @@ def test_create_deal_with_dict(self): self.assertIsInstance(deal.balance, Amount) self.assertIsInstance(deal.payout_balance, Amount) - def test_create_deal_with_object(self): + async def test_create_deal_with_object(self): self.maxDiff = None deal_facade = Deal() with patch('yookassa.client.ApiClient.request') as request_mock: @@ -81,7 +78,7 @@ def test_create_deal_with_object(self): "description": "SAFE_DEAL 123554642-2432FF344R", "test": False } - deal = deal_facade.create(DealRequest({ + deal = await deal_facade.create(DealRequest({ "type": "safe_deal", "fee_moment": "deal_closed", "metadata": { @@ -94,7 +91,7 @@ def test_create_deal_with_object(self): self.assertIsInstance(deal.balance, Amount) self.assertIsInstance(deal.payout_balance, Amount) - def test_deal_info(self): + async def test_deal_info(self): deal_facade = Deal() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -118,13 +115,13 @@ def test_deal_info(self): "description": "SAFE_DEAL 123554642-2432FF344R", "test": False } - deal = deal_facade.find_one('dl-285e5ee7-0022-5000-8000-01516a44b147') + deal = await deal_facade.find_one('dl-285e5ee7-0022-5000-8000-01516a44b147') self.assertIsInstance(deal, DealResponse) self.assertIsInstance(deal.balance, Amount) self.assertIsInstance(deal.payout_balance, Amount) - def test_deal_list(self): + async def test_deal_list(self): deal_facade = Deal() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -154,7 +151,7 @@ def test_deal_list(self): "type": "list", "next_cursor": "37a5c87d-3984-51e8-a7f3-8de646d39ec15" } - deal = deal_facade.list({ + deal = await deal_facade.list({ 'status': 'closed', 'limit': 1 }) @@ -162,9 +159,11 @@ def test_deal_list(self): self.assertIsInstance(deal, DealListResponse) self.assertIsInstance(deal.items, list) - def test_invalid_data(self): + async def test_invalid_data(self): with self.assertRaises(ValueError): - Deal().find_one('') + deal = Deal() + await deal.find_one('') with self.assertRaises(TypeError): - Deal().create('invalid params') + deal = Deal() + await deal.create('invalid params') diff --git a/test/unit/test_payment_facade.py b/test/unit/test_payment_facade.py index b62c9ff..1f1ef48 100644 --- a/test/unit/test_payment_facade.py +++ b/test/unit/test_payment_facade.py @@ -2,10 +2,7 @@ import sys import unittest -if sys.version_info >= (3, 3): - from unittest.mock import patch -else: - from mock import patch +from unittest.mock import patch from yookassa.configuration import Configuration from yookassa.domain.models.amount import Amount @@ -17,11 +14,11 @@ from yookassa.payment import Payment -class TestPaymentFacade(unittest.TestCase): +class TestPaymentFacade(unittest.IsolatedAsyncioTestCase): def setUp(self): Configuration.configure(account_id='test_account_id', secret_key='test_secret_key') - def test_create_payment_with_dict(self): + async def test_create_payment_with_dict(self): self.maxDiff = None payment_facade = Payment() with patch('yookassa.client.ApiClient.request') as request_mock: @@ -35,7 +32,7 @@ def test_create_payment_with_dict(self): 'recipient': {'account_id': '156833', 'gateway_id': '468284'}, 'status': 'waiting_for_capture' } - payment = payment_facade.create({ + payment = await payment_facade.create({ "amount": { "value": "1.00", "currency": "RUB" @@ -74,7 +71,7 @@ def test_create_payment_with_dict(self): self.assertIsInstance(payment.amount, Amount) self.assertIsInstance(payment.payment_method, PaymentDataBankCard) - def test_create_payment_with_object(self): + async def test_create_payment_with_object(self): self.maxDiff = None payment_facade = Payment() with patch('yookassa.client.ApiClient.request') as request_mock: @@ -88,7 +85,7 @@ def test_create_payment_with_object(self): 'recipient': {'account_id': '156833', 'gateway_id': '468284'}, 'status': 'waiting_for_capture' } - payment = payment_facade.create(PaymentRequest({ + payment = await payment_facade.create(PaymentRequest({ "amount": { "value": "1.00", "currency": "RUB" @@ -127,7 +124,7 @@ def test_create_payment_with_object(self): self.assertIsInstance(payment.amount, Amount) self.assertIsInstance(payment.payment_method, PaymentDataBankCard) - def test_create_capture_with_dict(self): + async def test_create_capture_with_dict(self): payment_facade = Payment() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -141,7 +138,7 @@ def test_create_capture_with_dict(self): 'status': 'waiting_for_capture' } - payment = payment_facade.capture('21b23b5b-000f-5061-a000-0674e49a8c10', { + payment = await payment_facade.capture('21b23b5b-000f-5061-a000-0674e49a8c10', { "amount": { "value": "1.00", "currency": "RUB" @@ -180,7 +177,7 @@ def test_create_capture_with_dict(self): self.assertIsInstance(payment.amount, Amount) self.assertIsInstance(payment.payment_method, PaymentDataBankCard) - def test_create_capture_with_object(self): + async def test_create_capture_with_object(self): payment_facade = Payment() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -194,7 +191,7 @@ def test_create_capture_with_object(self): 'status': 'waiting_for_capture' } - payment = payment_facade.capture('21b23b5b-000f-5061-a000-0674e49a8c10', CapturePaymentRequest({ + payment = await payment_facade.capture('21b23b5b-000f-5061-a000-0674e49a8c10', CapturePaymentRequest({ "amount": { "value": "1.00", "currency": "RUB" @@ -233,7 +230,7 @@ def test_create_capture_with_object(self): self.assertIsInstance(payment.amount, Amount) self.assertIsInstance(payment.payment_method, PaymentDataBankCard) - def test_create_capture(self): + async def test_create_capture(self): payment_facade = Payment() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -247,13 +244,13 @@ def test_create_capture(self): 'status': 'waiting_for_capture' } - payment = payment_facade.capture('21b23b5b-000f-5061-a000-0674e49a8c10') + payment = await payment_facade.capture('21b23b5b-000f-5061-a000-0674e49a8c10') self.assertIsInstance(payment, PaymentResponse) self.assertIsInstance(payment.amount, Amount) self.assertIsInstance(payment.payment_method, PaymentDataBankCard) - def test_payment_info(self): + async def test_payment_info(self): payment_facade = Payment() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -266,13 +263,13 @@ def test_payment_info(self): 'recipient': {'account_id': '156833', 'gateway_id': '468284'}, 'status': 'waiting_for_capture' } - payment = payment_facade.find_one('21b23b5b-000f-5061-a000-0674e49a8c10') + payment = await payment_facade.find_one('21b23b5b-000f-5061-a000-0674e49a8c10') self.assertIsInstance(payment, PaymentResponse) self.assertIsInstance(payment.amount, Amount) self.assertIsInstance(payment.payment_method, PaymentDataBankCard) - def test_payment_cancel(self): + async def test_payment_cancel(self): payment_facade = Payment() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -285,13 +282,13 @@ def test_payment_cancel(self): 'recipient': {'account_id': '156833', 'gateway_id': '468284'}, 'status': 'canceled' } - payment = payment_facade.cancel('21b23b5b-000f-5061-a000-0674e49a8c10') + payment = await payment_facade.cancel('21b23b5b-000f-5061-a000-0674e49a8c10') self.assertIsInstance(payment, PaymentResponse) self.assertIsInstance(payment.amount, Amount) self.assertIsInstance(payment.payment_method, PaymentDataBankCard) - def test_payment_list(self): + async def test_payment_list(self): payment_facade = Payment() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -322,7 +319,7 @@ def test_payment_list(self): ], 'next_page': '2018-08-02 08:24:01.180;48539871', 'type': 'list'} - payment = payment_facade.list({ + payment = await payment_facade.list({ 'status': 'succeeded', 'limit': 1 }) @@ -330,15 +327,19 @@ def test_payment_list(self): self.assertIsInstance(payment, PaymentListResponse) self.assertIsInstance(payment.items, list) - def test_invalid_data(self): + async def test_invalid_data(self): with self.assertRaises(ValueError): - Payment().find_one('') + payment = Payment() + await payment.find_one('') with self.assertRaises(TypeError): - Payment().create('invalid params') + payment = Payment() + await payment.create('invalid params') with self.assertRaises(ValueError): - Payment().capture(111) + payment = Payment() + await payment.capture(111) with self.assertRaises(ValueError): - Payment().cancel('') + payment = Payment() + await payment.cancel('') diff --git a/test/unit/test_payout.py b/test/unit/test_payout.py index 217c93e..2a77810 100644 --- a/test/unit/test_payout.py +++ b/test/unit/test_payout.py @@ -6,10 +6,7 @@ from yookassa.domain.models.payout_data.payout_destination import PayoutDestination from yookassa.domain.models.payout_data.response.payout_destination_bank_card import PayoutDestinationBankCard -if sys.version_info >= (3, 3): - from unittest.mock import patch -else: - from mock import patch +from unittest.mock import patch from yookassa.configuration import Configuration from yookassa.domain.models.amount import Amount @@ -18,11 +15,11 @@ from yookassa.payout import Payout -class TestPayoutFacade(unittest.TestCase): +class TestPayoutFacade(unittest.IsolatedAsyncioTestCase): def setUp(self): Configuration.configure(account_id='test_account_id', secret_key='test_secret_key') - def test_create_payout_with_dict(self): + async def test_create_payout_with_dict(self): self.maxDiff = None payout_facade = Payout() with patch('yookassa.client.ApiClient.request') as request_mock: @@ -53,7 +50,7 @@ def test_create_payout_with_dict(self): }, "test": False } - payout = payout_facade.create({ + payout = await payout_facade.create({ "amount": { "value": 320.0, "currency": Currency.RUB @@ -79,7 +76,7 @@ def test_create_payout_with_dict(self): self.assertIsInstance(payout.metadata, dict) self.assertIsInstance(payout.deal, PayoutDealInfo) - def test_create_payout_with_object(self): + async def test_create_payout_with_object(self): self.maxDiff = None payout_facade = Payout() with patch('yookassa.client.ApiClient.request') as request_mock: @@ -110,7 +107,7 @@ def test_create_payout_with_object(self): }, "test": False } - payout = payout_facade.create(PayoutRequest({ + payout = await payout_facade.create(PayoutRequest({ "amount": { "value": 320.0, "currency": Currency.RUB @@ -130,7 +127,7 @@ def test_create_payout_with_object(self): self.assertIsInstance(payout.metadata, dict) self.assertIsInstance(payout.deal, PayoutDealInfo) - def test_payout_info(self): + async def test_payout_info(self): payout_facade = Payout() with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -160,7 +157,7 @@ def test_payout_info(self): }, "test": False } - payout = payout_facade.find_one('po-2855a19a-0003-5000-a000-0efa9e7f4264') + payout = await payout_facade.find_one('po-2855a19a-0003-5000-a000-0efa9e7f4264') self.assertIsInstance(payout, PayoutResponse) self.assertIsInstance(payout.amount, Amount) @@ -168,9 +165,11 @@ def test_payout_info(self): self.assertIsInstance(payout.deal, PayoutDealInfo) self.assertIsInstance(payout.payout_destination, PayoutDestinationBankCard) - def test_invalid_data(self): + async def test_invalid_data(self): with self.assertRaises(ValueError): - Payout().find_one('') + payout = Payout() + await payout.find_one('') with self.assertRaises(TypeError): - Payout().create('invalid params') + payout = Payout() + await payout.create('invalid params') diff --git a/test/unit/test_receipt.py b/test/unit/test_receipt.py index 663732b..4473faa 100644 --- a/test/unit/test_receipt.py +++ b/test/unit/test_receipt.py @@ -17,12 +17,12 @@ from yookassa.configuration import Configuration -class TestReceipt(unittest.TestCase): +class TestReceipt(unittest.IsolatedAsyncioTestCase): def setUp(self): Configuration.configure(account_id='test_account_id', secret_key='test_secret_key') - def test_list(self): + async def test_list(self): self.maxDiff = None with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -55,13 +55,13 @@ def test_list(self): } params = {"refund_id": "24be8857-000f-5000-a000-1833ed1577f3"} - rec_list = Receipt.list(params) + rec_list = await Receipt.list(params) self.assertIsInstance(rec_list, ReceiptListResponse) self.assertEqual(rec_list.type, "list") self.assertIsInstance(rec_list.items[0], ReceiptResponse) - def test_create(self): + async def test_create(self): self.maxDiff = None with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -142,7 +142,7 @@ def test_create(self): 'payment_id': '215d8da0-000f-50be-b000-0003308c89be', 'on_behalf_of': 'string' } - rec = Receipt.create(params) + rec = await Receipt.create(params) self.assertIsInstance(rec, ReceiptResponse) self.assertEqual(rec.type, ReceiptType.PAYMENT) @@ -172,10 +172,10 @@ def test_create(self): })) request.tax_system_code = 1 request.payment_id = '215d8da0-000f-50be-b000-0003308c89be' - rec = Receipt.create(request) + rec = await Receipt.create(request) self.assertIsInstance(rec, ReceiptResponse) self.assertEqual(rec.type, "payment") with self.assertRaises(TypeError): - Receipt.create('invalid data') + await Receipt.create('invalid data') diff --git a/test/unit/test_refund_facade.py b/test/unit/test_refund_facade.py index b3933d8..304188d 100644 --- a/test/unit/test_refund_facade.py +++ b/test/unit/test_refund_facade.py @@ -4,10 +4,8 @@ from yookassa import Configuration -if sys.version_info >= (3, 3): - from unittest.mock import patch -else: - from mock import patch + +from unittest.mock import patch from yookassa.domain.models.amount import Amount from yookassa.domain.request.refund_request import RefundRequest @@ -15,12 +13,12 @@ from yookassa.refund import Refund -class TestRefundFacade(unittest.TestCase): +class TestRefundFacade(unittest.IsolatedAsyncioTestCase): def setUp(self): Configuration.configure(account_id='test_account_id', secret_key='test_secret_key') - def test_create_payment_with_dict(self): + async def test_create_payment_with_dict(self): self.maxDiff = None refund_facade = Refund() with patch('yookassa.client.ApiClient.request') as request_mock: @@ -34,7 +32,7 @@ def test_create_payment_with_dict(self): "created_at": "2017-10-04T19:27:51.407Z", "payment_id": "216749da-000f-50be-b000-096747fad91e" } - refund = refund_facade.create({ + refund = await refund_facade.create({ "payment_id": "21b36369-000f-500b-9000-070b97dced26", "amount": { "value": 1000.01, @@ -62,7 +60,7 @@ def test_create_payment_with_dict(self): self.assertIsInstance(refund, RefundResponse) self.assertIsInstance(refund.amount, Amount) - def test_create_payment_with_object(self): + async def test_create_payment_with_object(self): self.maxDiff = None refund_facade = Refund() @@ -77,7 +75,7 @@ def test_create_payment_with_object(self): "created_at": "2017-10-04T19:27:51.407Z", "payment_id": "216749da-000f-50be-b000-096747fad91e" } - refund = refund_facade.create(RefundRequest({ + refund = await refund_facade.create(RefundRequest({ "payment_id": "21b36369-000f-500b-9000-070b97dced26", "amount": { "value": 1000.01, @@ -105,7 +103,7 @@ def test_create_payment_with_object(self): self.assertIsInstance(refund, RefundResponse) self.assertIsInstance(refund.amount, Amount) - def test_refund_info(self): + async def test_refund_info(self): self.maxDiff = None refund_facade = Refund() with patch('yookassa.client.ApiClient.request') as request_mock: @@ -120,15 +118,16 @@ def test_refund_info(self): "payment_id": "216749da-000f-50be-b000-096747fad91e" } - refund = refund_facade.find_one("216749f7-0016-50be-b000-078d43a63ae4") + refund = await refund_facade.find_one("216749f7-0016-50be-b000-078d43a63ae4") self.assertIsInstance(refund, RefundResponse) self.assertIsInstance(refund.amount, Amount) - def test_invalid_data(self): + async def test_invalid_data(self): with self.assertRaises(TypeError): - Refund().create('') + refund = Refund() + await refund.create('') with self.assertRaises(ValueError): - Refund().find_one('') - + refund = Refund() + await refund.find_one('') diff --git a/test/unit/test_settings.py b/test/unit/test_settings.py index bd1c1e8..93f0d7a 100644 --- a/test/unit/test_settings.py +++ b/test/unit/test_settings.py @@ -2,20 +2,18 @@ import sys import unittest -if sys.version_info >= (3, 3): - from unittest.mock import patch -else: - from mock import patch + +from unittest.mock import patch from yookassa import Settings, Configuration -class TestSettings(unittest.TestCase): +class TestSettings(unittest.IsolatedAsyncioTestCase): def setUp(self): Configuration.configure(account_id='test_account_id', secret_key='test_secret_key') - def test_get_account_settings(self): + async def test_get_account_settings(self): self.maxDiff = None with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -28,7 +26,7 @@ def test_get_account_settings(self): "bank_card" ] } - settings = Settings.get_account_settings() + settings = await Settings.get_account_settings() self.assertIsInstance(settings, dict) self.assertIsInstance(settings['payment_methods'], list) diff --git a/test/unit/test_webhook.py b/test/unit/test_webhook.py index 101b1b4..dbef3f2 100644 --- a/test/unit/test_webhook.py +++ b/test/unit/test_webhook.py @@ -1,24 +1,20 @@ # -*- coding: utf-8 -*- -import sys import unittest from yookassa.domain.request import WebhookRequest from yookassa.domain.response import WebhookList, WebhookResponse -if sys.version_info >= (3, 3): - from unittest.mock import patch -else: - from mock import patch +from unittest.mock import patch from yookassa import Configuration, Webhook -class TestWebhook(unittest.TestCase): +class TestWebhook(unittest.IsolatedAsyncioTestCase): def setUp(self): Configuration.configure(account_id='test_account_id', secret_key='test_secret_key') - def test_list(self): + async def test_list(self): self.maxDiff = None with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -36,13 +32,13 @@ def test_list(self): } ] } - wh_list = Webhook.list() + wh_list = await Webhook.list() self.assertIsInstance(wh_list, WebhookList) self.assertEqual(wh_list.type, "list") self.assertIsInstance(wh_list.items[0], WebhookResponse) - def test_add(self): + async def test_add(self): self.maxDiff = None with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = { @@ -55,7 +51,7 @@ def test_add(self): "event": "payment.succeeded", "url": "https://www.merchant-website.com/notification_url", }) - wh = Webhook.add(params) + wh = await Webhook.add(params) self.assertIsInstance(wh, WebhookResponse) self.assertEqual(wh.event, "payment.succeeded") @@ -64,19 +60,19 @@ def test_add(self): "event": "payment.succeeded", "url": "https://www.merchant-website.com/notification_url", } - wh = Webhook.add(params) + wh = await Webhook.add(params) self.assertIsInstance(wh, WebhookResponse) self.assertEqual(wh.event, "payment.succeeded") with self.assertRaises(TypeError): - Webhook.add('invalid data') + await Webhook.add('invalid data') - def test_remove(self): + async def test_remove(self): self.maxDiff = None with patch('yookassa.client.ApiClient.request') as request_mock: request_mock.return_value = {} - response = Webhook.remove("wh-22d6d597-000f-5000-9000-145f6df21d6f") + response = await Webhook.remove("wh-22d6d597-000f-5000-9000-145f6df21d6f") self.assertIsInstance(response, WebhookResponse)