From e1dc1cd4b23bd838d08c033b3f92dff42eca0884 Mon Sep 17 00:00:00 2001 From: YaNesyTortiK Date: Tue, 19 Nov 2024 23:27:35 +0300 Subject: [PATCH] Build 1.9.2; Moved tests from src; changed imports of errors and tools; minor fixes --- CHANGELOG.md | 12 +- README.md | 4 +- pyproject.toml | 2 +- src/anime_parsers_ru.egg-info/PKG-INFO | 6 +- src/anime_parsers_ru.egg-info/SOURCES.txt | 1 - src/anime_parsers_ru.egg-info/top_level.txt | 1 - src/anime_parsers_ru/errors.py | 6 +- src/anime_parsers_ru/internal_tools.py | 21 +- src/anime_parsers_ru/parser_aniboom.py | 6 +- src/anime_parsers_ru/parser_aniboom_async.py | 9 +- src/anime_parsers_ru/parser_jutsu.py | 5 +- src/anime_parsers_ru/parser_kodik.py | 30 ++- src/anime_parsers_ru/parser_kodik_async.py | 32 +++- src/anime_parsers_ru/parser_shikimori.py | 59 +++--- .../parser_shikimori_async.py | 60 +++--- src/tests.py => tests.py | 180 +++++++++--------- 16 files changed, 260 insertions(+), 174 deletions(-) rename src/tests.py => tests.py (89%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 78336d0..36d0fa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,4 +106,14 @@ Overall fixes and adjustments to KodikParser and KodikParserAsync - Added `strict` flag to `search` function to KodikParser (kodik will search by title more strictly, less random unrelated results) ## To 1.9.2 -- Fixed `search` function in KodikParser \ No newline at end of file +- Fixed `search` function in KodikParser + +## To 1.9.3 +- Fixed timeout bug in AniboomParser (Added `referer` header to request in `fast_search` function) +- Added additional checks to `get_link`, `get_info`, `search_by_id` functions in KodikParser (now all passed integer parameters will be autoconverted into strings) +- Change imports of `errors` module to local (from: from anime_parser_ru.errors to from . import errors) +- Fixed mismatch with `TooManyRequests` and `ServiceIsOverloaded` exceptions and their http codes + +Thx to @nichind for pointing these out + +- Moved `tests.py` from src to project root directory \ No newline at end of file diff --git a/README.md b/README.md index 31a95cb..120085a 100644 --- a/README.md +++ b/README.md @@ -847,10 +847,10 @@ pip install lxml Обозначает возрастную блокировку (требуется авторизация для доступа к этим данным) - TooManyRequests - Обозначает http статус 520. То есть сервер заблокировал запрос из-за слишком частого обращения + Обозначает http статус 429. То есть сервер заблокировал запрос из-за слишком частого обращения - ContentBlocked Обозначает что запрашиваемый контент или плеер заблокирован/недоступен - ServiceIsOverloaded - Обозначает http статус 429. То есть сервер перегружен и не может ответить на запрос \ No newline at end of file + Обозначает http статус 520. То есть сервер перегружен и не может ответить на запрос \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 9d31311..0b093db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "anime_parsers_ru" -version = "1.9.2" +version = "1.9.3" authors = [ { name="YaNesyTortiK", email="ya.nesy.tortik.email@gmail.com"}, ] diff --git a/src/anime_parsers_ru.egg-info/PKG-INFO b/src/anime_parsers_ru.egg-info/PKG-INFO index b24bcf6..2be8fbd 100644 --- a/src/anime_parsers_ru.egg-info/PKG-INFO +++ b/src/anime_parsers_ru.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: anime_parsers_ru -Version: 1.9.2 +Version: 1.9.3 Summary: Python package for parsing russian anime players Author-email: YaNesyTortiK Maintainer-email: YaNesyTortiK @@ -877,10 +877,10 @@ pip install lxml Обозначает возрастную блокировку (требуется авторизация для доступа к этим данным) - TooManyRequests - Обозначает http статус 520. То есть сервер заблокировал запрос из-за слишком частого обращения + Обозначает http статус 429. То есть сервер заблокировал запрос из-за слишком частого обращения - ContentBlocked Обозначает что запрашиваемый контент или плеер заблокирован/недоступен - ServiceIsOverloaded - Обозначает http статус 429. То есть сервер перегружен и не может ответить на запрос + Обозначает http статус 520. То есть сервер перегружен и не может ответить на запрос diff --git a/src/anime_parsers_ru.egg-info/SOURCES.txt b/src/anime_parsers_ru.egg-info/SOURCES.txt index 0abf916..1125a2b 100644 --- a/src/anime_parsers_ru.egg-info/SOURCES.txt +++ b/src/anime_parsers_ru.egg-info/SOURCES.txt @@ -1,7 +1,6 @@ LICENSE README.md pyproject.toml -src/tests.py src/anime_parsers_ru/__init__.py src/anime_parsers_ru/errors.py src/anime_parsers_ru/internal_tools.py diff --git a/src/anime_parsers_ru.egg-info/top_level.txt b/src/anime_parsers_ru.egg-info/top_level.txt index 919f726..fbf10f6 100644 --- a/src/anime_parsers_ru.egg-info/top_level.txt +++ b/src/anime_parsers_ru.egg-info/top_level.txt @@ -1,2 +1 @@ anime_parsers_ru -tests diff --git a/src/anime_parsers_ru/errors.py b/src/anime_parsers_ru/errors.py index 7068e23..11b0bba 100644 --- a/src/anime_parsers_ru/errors.py +++ b/src/anime_parsers_ru/errors.py @@ -35,8 +35,8 @@ class AgeRestricted(Exception): class TooManyRequests(Exception): """ - Ошибка для обозначения ошибки сервера из-за слишком частых запросов. - В основном для шикимориы + Ошибка для обозначения ошибки 429 из-за слишком частых запросов. + В основном для шикимори """ class ContentBlocked(Exception): @@ -46,6 +46,6 @@ class ContentBlocked(Exception): class ServiceIsOverloaded(Exception): """ - Ошибка для обозначения http кода 429 + Ошибка для обозначения http кода 520 Используется в парсере shikimori """ \ No newline at end of file diff --git a/src/anime_parsers_ru/internal_tools.py b/src/anime_parsers_ru/internal_tools.py index 2d1b95e..4e04e65 100644 --- a/src/anime_parsers_ru/internal_tools.py +++ b/src/anime_parsers_ru/internal_tools.py @@ -7,7 +7,6 @@ CAN_WORK = True import json -import anime_parsers_ru.errors as errors class Response: """ @@ -34,16 +33,20 @@ def __init__(self) -> None: async def get(self, url: str, **kwargs) -> Response: async with aiohttp.request(method='get', url=url, **kwargs) as response: - return Response( + text = await response.text() + res = Response( status=response.status, - text=await response.text(), - url= response.url.human_repr() - ) + text=text, + url=response.url.human_repr() + ) + return res async def post(self, url: str, **kwargs) -> Response: async with aiohttp.request(method='post', url=url, **kwargs) as response: - return Response( + text = await response.text() + res = Response( status=response.status, - text=await response.text(), - url= response.url.human_repr() - ) \ No newline at end of file + text=text, + url=response.url.human_repr() + ) + return res \ No newline at end of file diff --git a/src/anime_parsers_ru/parser_aniboom.py b/src/anime_parsers_ru/parser_aniboom.py index b8806ae..a36222c 100644 --- a/src/anime_parsers_ru/parser_aniboom.py +++ b/src/anime_parsers_ru/parser_aniboom.py @@ -9,7 +9,10 @@ import re import json -import anime_parsers_ru.errors as errors +try: + from . import errors # Импорт если библиотека установлена +except ImportError: + import errors # Импорт если ббилиотека не установлена и файл лежит локально class AniboomParser: """ @@ -45,6 +48,7 @@ def fast_search(self, title: str) -> list[dict]: headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'X-Requested-With': 'XMLHttpRequest', + 'Referer': 'https://animego.org/' } params = { 'type': 'small', diff --git a/src/anime_parsers_ru/parser_aniboom_async.py b/src/anime_parsers_ru/parser_aniboom_async.py index c6eb9e3..32a3b22 100644 --- a/src/anime_parsers_ru/parser_aniboom_async.py +++ b/src/anime_parsers_ru/parser_aniboom_async.py @@ -8,8 +8,12 @@ import re import json -import anime_parsers_ru.errors as errors -from anime_parsers_ru.internal_tools import AsyncSession +try: + from . import errors # Импорт если библиотека установлена + from .internal_tools import AsyncSession +except ImportError: + import errors # Импорт если ббилиотека не установлена и файл лежит локально + from internal_tools import AsyncSession class AniboomParserAsync: """ @@ -46,6 +50,7 @@ async def fast_search(self, title: str) -> list[dict]: headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'X-Requested-With': 'XMLHttpRequest', + 'Referer': 'https://animego.org/' } params = { 'type': 'small', diff --git a/src/anime_parsers_ru/parser_jutsu.py b/src/anime_parsers_ru/parser_jutsu.py index da4beb5..a9d67ce 100644 --- a/src/anime_parsers_ru/parser_jutsu.py +++ b/src/anime_parsers_ru/parser_jutsu.py @@ -7,7 +7,10 @@ LXML_WORKS = True from bs4 import BeautifulSoup as Soup -import anime_parsers_ru.errors as errors +try: + from . import errors # Импорт если библиотека установлена +except ImportError: + import errors # Импорт если ббилиотека не установлена и файл лежит локально class JutsuParser: """ diff --git a/src/anime_parsers_ru/parser_kodik.py b/src/anime_parsers_ru/parser_kodik.py index 9da7da1..06ba2a3 100644 --- a/src/anime_parsers_ru/parser_kodik.py +++ b/src/anime_parsers_ru/parser_kodik.py @@ -9,7 +9,10 @@ from bs4 import BeautifulSoup as Soup from base64 import b64decode -import anime_parsers_ru.errors as errors +try: + from . import errors # Импорт если библиотека установлена +except ImportError: + import errors # Импорт если ббилиотека не установлена и файл лежит локально class KodikParser: """ @@ -323,6 +326,11 @@ def search_by_id(self, id: str, id_type: str, limit: int|None = None) -> list: ... ] """ + if type(id) == int: + id = str(id) + elif type(id) != str: + raise ValueError(f'Для id ожидался тип str, получен "{type(id)}"') + if limit is None: search_data = self.base_search_by_id(id, id_type, include_material_data=True) else: @@ -447,6 +455,11 @@ def get_info(self, id: str, id_type: str) -> dict: ] } """ + if type(id) == int: + id = str(id) + elif type(id) != str: + raise ValueError(f'Для id ожидался тип str, получен "{type(id)}"') + link = self._link_to_info(id, id_type) data = requests.get(link).text soup = Soup(data, 'lxml') if self.USE_LXML else Soup(data, 'html.parser') @@ -513,6 +526,21 @@ def get_link(self, id: str, id_type: str, seria_num: int, translation_id: str) - И максимально возможное качество. """ + # Проверка переданных параметров на правильность типа + if type(id) == int: + id = str(id) + elif type(id) != str: + raise ValueError(f'Для id ожидался тип str, получен "{type(id)}"') + if type(seria_num) == str and seria_num.isdigit(): + seria_num = int(seria_num) + elif type(seria_num) != int: + raise ValueError(f'Для seria_num ожидался тип int, получен "{type(seria_num)}"') + if type(translation_id) == int: + translation_id = str(translation_id) + elif type(translation_id) != str: + raise ValueError(f'Для translation_id ожидался тип str, получен "{type(translation_id)}"') + + link = self._link_to_info(id, id_type) data = requests.get(link).text soup = Soup(data, 'lxml') if self.USE_LXML else Soup(data, 'html.parser') diff --git a/src/anime_parsers_ru/parser_kodik_async.py b/src/anime_parsers_ru/parser_kodik_async.py index 203a3dc..3d0a734 100644 --- a/src/anime_parsers_ru/parser_kodik_async.py +++ b/src/anime_parsers_ru/parser_kodik_async.py @@ -9,8 +9,12 @@ from bs4 import BeautifulSoup as Soup from base64 import b64decode -import anime_parsers_ru.errors as errors -from anime_parsers_ru.internal_tools import AsyncSession +try: + from . import errors # Импорт если библиотека установлена + from .internal_tools import AsyncSession +except ImportError: + import errors # Импорт если ббилиотека не установлена и файл лежит локально + from internal_tools import AsyncSession class KodikParserAsync: """ @@ -329,6 +333,11 @@ async def search_by_id(self, id: str, id_type: str, limit: int|None = None) -> l ... ] """ + if type(id) == int: + id = str(id) + elif type(id) != str: + raise ValueError(f'Для id ожидался тип str, получен "{type(id)}"') + if limit is None: search_data = await self.base_search_by_id(id, id_type, include_material_data=True) else: @@ -456,6 +465,11 @@ async def get_info(self, id: str, id_type: str) -> dict: ] } """ + if type(id) == int: + id = str(id) + elif type(id) != str: + raise ValueError(f'Для id ожидался тип str, получен "{type(id)}"') + link = await self._link_to_info(id, id_type) data = await self.requests.get(link) data = data.text @@ -523,6 +537,20 @@ async def get_link(self, id: str, id_type: str, seria_num: int, translation_id: И максимально возможное качество. """ + # Проверка переданных параметров на правильность типа + if type(id) == int: + id = str(id) + elif type(id) != str: + raise ValueError(f'Для id ожидался тип str, получен "{type(id)}"') + if type(seria_num) == str and seria_num.isdigit(): + seria_num = int(seria_num) + elif type(seria_num) != int: + raise ValueError(f'Для seria_num ожидался тип int, получен "{type(seria_num)}"') + if type(translation_id) == int: + translation_id = str(translation_id) + elif type(translation_id) != str: + raise ValueError(f'Для translation_id ожидался тип str, получен "{type(translation_id)}"') + link = await self._link_to_info(id, id_type) data = await self.requests.get(link) data = data.text diff --git a/src/anime_parsers_ru/parser_shikimori.py b/src/anime_parsers_ru/parser_shikimori.py index 8496f40..c1136f8 100644 --- a/src/anime_parsers_ru/parser_shikimori.py +++ b/src/anime_parsers_ru/parser_shikimori.py @@ -9,8 +9,11 @@ from bs4 import BeautifulSoup as Soup import json -import anime_parsers_ru.errors as errors - +try: + from . import errors # Импорт если библиотека установлена +except ImportError: + import errors # Импорт если ббилиотека не установлена и файл лежит локально + class ShikimoriParser: """ Парсер шикимори. Не использует встроенный в шикимори api. @@ -59,10 +62,10 @@ def search(self, title: str) -> list: } # Используем autocomplete эндпоинт, потому что обычный поиск тупо блокируется если находит 18+ контент response = requests.get('https://shikimori.one/animes/autocomplete/v2', params=params, headers=headers) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.json()['content'] @@ -135,10 +138,10 @@ def anime_info(self, shikimori_link: str) -> dict: 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0', } response = requests.get(shikimori_link, headers=headers) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.text @@ -254,10 +257,10 @@ def additional_anime_info(self, shikimori_link: str) -> dict: 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0', } response = requests.get(link, headers=headers) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.text @@ -481,9 +484,9 @@ def get_anime_list(self, status: list[str] = [], anime_type: list[str] = [], rat while i < start_page+page_limit and i <= total_pages: response = requests.get(f'{search_url}/page/{i}.json?order={sort_by}{f"&rating={rating}" if rating != None else ""}', headers=headers) if response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') elif response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError('Произошла непредвиденная ошибка при получении данных об онгоингах. Ожидался статус ответа 200. Получен: ', response.status_code) try: @@ -555,17 +558,17 @@ def link_by_id(self, shikimori_id: str) -> str: if actual_code == '404': raise errors.NoResults(f'Страница аниме с shikimori_id "{shikimori_id}" не найдена.') elif actual_code == '429': - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') elif actual_code == '302': return soup.find('a').get_attribute_list('href')[0] else: raise errors.UnexpectedBehaviour(f'Непредвиденная ошибка при попытке нахождения страницы по id ({shikimori_id}). Ожидались коды: "404", "429", "302", "200". Обнаружен: "{actual_code}"') elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code == 200 or response.status_code == 302: return response.url - elif response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') else: raise errors.UnexpectedBehaviour(f'Непредвиденная ошибка при попытке нахождения страницы по id ({shikimori_id}). Ожидались коды: "404", "302", "200". Обнаружен: "{response.status_code}"') @@ -632,10 +635,10 @@ def deep_search(self, title: str, search_parameters: dict = {}, return_parameter } response = requests.post('https://shikimori.one/api/graphql', headers=headers, json=json_data) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.json() @@ -685,10 +688,10 @@ def deep_anime_info(self, shikimori_id: str, return_parameters: list = ['id', 'n } response = requests.post('https://shikimori.one/api/graphql', headers=headers, json=json_data) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.json() diff --git a/src/anime_parsers_ru/parser_shikimori_async.py b/src/anime_parsers_ru/parser_shikimori_async.py index be81d2a..5c20c7f 100644 --- a/src/anime_parsers_ru/parser_shikimori_async.py +++ b/src/anime_parsers_ru/parser_shikimori_async.py @@ -8,8 +8,12 @@ from bs4 import BeautifulSoup as Soup import json -import anime_parsers_ru.errors as errors -from anime_parsers_ru.internal_tools import AsyncSession +try: + from . import errors # Импорт если библиотека установлена + from .internal_tools import AsyncSession +except ImportError: + import errors # Импорт если ббилиотека не установлена и файл лежит локально + from internal_tools import AsyncSession class ShikimoriParserAsync: """ @@ -60,10 +64,10 @@ async def search(self, title: str) -> list: } # Используем autocomplete эндпоинт, потому что обычный поиск тупо блокируется если находит 18+ контент response = await self.requests.get('https://shikimori.one/animes/autocomplete/v2', params=params, headers=headers) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.json()['content'] @@ -136,10 +140,10 @@ async def anime_info(self, shikimori_link: str) -> dict: 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0', } response = await self.requests.get(shikimori_link, headers=headers) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.text @@ -255,10 +259,10 @@ async def additional_anime_info(self, shikimori_link: str) -> dict: 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0', } response = await self.requests.get(link, headers=headers) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.text @@ -482,9 +486,9 @@ async def get_anime_list(self, status: list[str] = [], anime_type: list[str] = [ while i < start_page+page_limit and i <= total_pages: response = await self.requests.get(f'{search_url}/page/{i}.json?order={sort_by}{f"&rating={rating}" if rating != None else ""}', headers=headers) if response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') elif response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError('Произошла непредвиденная ошибка при получении данных об онгоингах. Ожидался статус ответа 200. Получен: ', response.status_code) try: @@ -556,17 +560,17 @@ async def link_by_id(self, shikimori_id: str) -> str: if actual_code == '404': raise errors.NoResults(f'Страница аниме с shikimori_id "{shikimori_id}" не найдена.') elif actual_code == '429': - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') elif actual_code == '302': return soup.find('a').get_attribute_list('href')[0] else: raise errors.UnexpectedBehaviour(f'Непредвиденная ошибка при попытке нахождения страницы по id ({shikimori_id}). Ожидались коды: "404", "302", "200". Обнаружен: "{actual_code}"') elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code == 200 or response.status_code == 302: return response.url - elif response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') else: raise errors.UnexpectedBehaviour(f'Непредвиденная ошибка при попытке нахождения страницы по id ({shikimori_id}). Ожидались коды: "404", "302", "200". Обнаружен: "{response.status_code}"') @@ -633,10 +637,10 @@ async def deep_search(self, title: str, search_parameters: dict = {}, return_par } response = await self.requests.post('https://shikimori.one/api/graphql', headers=headers, json=json_data) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.json() @@ -686,10 +690,10 @@ async def deep_anime_info(self, shikimori_id: str, return_parameters: list = ['i } response = await self.requests.post('https://shikimori.one/api/graphql', headers=headers, json=json_data) - if response.status_code == 520: - raise errors.TooManyRequests(f'Сервер вернул код 520 для обозначения что запросы выполняются слишком часто.') - elif response.status_code == 429: - raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 429, что означает что он перегружен и не может ответить сразу.") + if response.status_code == 429: + raise errors.TooManyRequests(f'Сервер вернул код 429 для обозначения что запросы выполняются слишком часто.') + elif response.status_code == 520: + raise errors.ServiceIsOverloaded("Сервер вернул статус ответа 520, что означает что он перегружен и не может ответить сразу.") elif response.status_code != 200: raise errors.ServiceError(f'Сервер не вернул ожидаемый код 200. Код: "{response.status_code}"') response = response.json() diff --git a/src/tests.py b/tests.py similarity index 89% rename from src/tests.py rename to tests.py index 0c03057..eff62b0 100644 --- a/src/tests.py +++ b/tests.py @@ -5,21 +5,21 @@ class TestKodik(unittest.TestCase): USE_LXML = GLOBAL_USE_LXML def test_import(self): - from anime_parsers_ru import KodikParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParser + import src.anime_parsers_ru.errors as errors def test_auto_token(self): - from anime_parsers_ru import KodikParser + from src.anime_parsers_ru import KodikParser goten_token = KodikParser.get_token() self.assertIsInstance(goten_token, str) def test_init(self): - from anime_parsers_ru import KodikParser + from src.anime_parsers_ru import KodikParser parser = KodikParser(use_lxml=self.USE_LXML) def test_base_search(self): - from anime_parsers_ru import KodikParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParser + import src.anime_parsers_ru.errors as errors parser = KodikParser(use_lxml=self.USE_LXML) search = parser.base_search('Наруто', 10) # Гарантированно существующий результат self.assertIsInstance(search, dict) @@ -32,8 +32,8 @@ def test_base_search(self): raise AssertionError(f'Base search with guaranteed bad search query returned error other then NoResults. Exception: {ex}') def test_base_search_by_id(self): - from anime_parsers_ru import KodikParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParser + import src.anime_parsers_ru.errors as errors parser = KodikParser(use_lxml=self.USE_LXML) search = parser.base_search_by_id('20', 'shikimori') # Гарантированно существующий результат self.assertIsInstance(search, dict) @@ -46,8 +46,8 @@ def test_base_search_by_id(self): raise AssertionError(f'Base search with guaranteed bad search query returned error other then NoResults. Exception: {ex}') def test_list(self): - from anime_parsers_ru import KodikParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParser + import src.anime_parsers_ru.errors as errors parser = KodikParser(use_lxml=self.USE_LXML) data = parser.get_list(include_material_data=False) self.assertIsInstance(data, tuple) @@ -68,8 +68,8 @@ def test_list(self): self.assertIsInstance(data[0][0], dict) def test_search(self): - from anime_parsers_ru import KodikParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParser + import src.anime_parsers_ru.errors as errors parser = KodikParser(use_lxml=self.USE_LXML) search = parser.search('Наруто') @@ -81,15 +81,15 @@ def test_search(self): self.assertNotEqual(len(search), 0) def test_search_by_id(self): - from anime_parsers_ru import KodikParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParser + import src.anime_parsers_ru.errors as errors parser = KodikParser(use_lxml=self.USE_LXML) search = parser.search_by_id('20', 'shikimori') self.assertIsInstance(search, list) self.assertNotEqual(len(search), 0) def test_get_info_serial(self): - from anime_parsers_ru import KodikParser + from src.anime_parsers_ru import KodikParser parser = KodikParser(use_lxml=self.USE_LXML) cur_search = parser.get_info('z20', 'shikimori') self.assertIsInstance(cur_search, dict) @@ -110,7 +110,7 @@ def test_get_info_serial(self): self.assertIsInstance(cur_search['translations'][0], dict) def test_get_info_video(self): - from anime_parsers_ru import KodikParser + from src.anime_parsers_ru import KodikParser parser = KodikParser(use_lxml=self.USE_LXML) cur_search = parser.get_info('2472', 'shikimori') self.assertIsInstance(cur_search, dict) @@ -131,7 +131,7 @@ def test_get_info_video(self): self.assertIsInstance(cur_search['translations'][0], dict) def test_get_link_serial(self): - from anime_parsers_ru import KodikParser + from src.anime_parsers_ru import KodikParser parser = KodikParser(use_lxml=self.USE_LXML) link = parser.get_link('z20', 'shikimori', 1, '609') self.assertIsInstance(link, tuple) @@ -139,7 +139,7 @@ def test_get_link_serial(self): self.assertIsInstance(link[1], int) def test_get_link_video(self): - from anime_parsers_ru import KodikParser + from src.anime_parsers_ru import KodikParser parser = KodikParser(use_lxml=self.USE_LXML) link = parser.get_link('2472', 'shikimori', 0, '609') self.assertIsInstance(link, tuple) @@ -149,21 +149,21 @@ def test_get_link_video(self): class TestKodikAsync(unittest.IsolatedAsyncioTestCase): USE_LXML = GLOBAL_USE_LXML def test_import(self): - from anime_parsers_ru import KodikParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParserAsync + import src.anime_parsers_ru.errors as errors async def test_auto_token(self): - from anime_parsers_ru import KodikParserAsync + from src.anime_parsers_ru import KodikParserAsync goten_token = await KodikParserAsync.get_token() self.assertIsInstance(goten_token, str) async def test_init(self): - from anime_parsers_ru import KodikParserAsync + from src.anime_parsers_ru import KodikParserAsync parser = KodikParserAsync(use_lxml=self.USE_LXML) async def test_base_search(self): - from anime_parsers_ru import KodikParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParserAsync + import src.anime_parsers_ru.errors as errors parser = KodikParserAsync(use_lxml=self.USE_LXML) search = await parser.base_search('Наруто', 10) # Гарантированно существующий результат self.assertIsInstance(search, dict) @@ -176,8 +176,8 @@ async def test_base_search(self): raise AssertionError(f'Base search with guaranteed bad search query returned error other then NoResults. Exception: {ex}') async def test_base_search_by_id(self): - from anime_parsers_ru import KodikParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParserAsync + import src.anime_parsers_ru.errors as errors parser = KodikParserAsync(use_lxml=self.USE_LXML) search = await parser.base_search_by_id('20', 'shikimori') # Гарантированно существующий результат self.assertIsInstance(search, dict) @@ -190,8 +190,8 @@ async def test_base_search_by_id(self): raise AssertionError(f'Base search with guaranteed bad search query returned error other then NoResults. Exception: {ex}') async def test_list(self): - from anime_parsers_ru import KodikParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParserAsync + import src.anime_parsers_ru.errors as errors parser = KodikParserAsync(use_lxml=self.USE_LXML) data = await parser.get_list(include_material_data=False) self.assertIsInstance(data, tuple) @@ -213,8 +213,8 @@ async def test_list(self): self.assertIsInstance(data[0][0], dict) async def test_search(self): - from anime_parsers_ru import KodikParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParserAsync + import src.anime_parsers_ru.errors as errors parser = KodikParserAsync(use_lxml=self.USE_LXML) search = await parser.search('Наруто') self.assertIsInstance(search, list) @@ -225,15 +225,15 @@ async def test_search(self): self.assertNotEqual(len(search), 0) async def test_search_by_id(self): - from anime_parsers_ru import KodikParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import KodikParserAsync + import src.anime_parsers_ru.errors as errors parser = KodikParserAsync(use_lxml=self.USE_LXML) search = await parser.search_by_id('20', 'shikimori') self.assertIsInstance(search, list) self.assertNotEqual(len(search), 0) async def test_get_info_serial(self): - from anime_parsers_ru import KodikParserAsync + from src.anime_parsers_ru import KodikParserAsync parser = KodikParserAsync(use_lxml=self.USE_LXML) cur_search = await parser.get_info('z20', 'shikimori') self.assertIsInstance(cur_search, dict) @@ -254,7 +254,7 @@ async def test_get_info_serial(self): self.assertIsInstance(cur_search['translations'][0], dict) async def test_get_info_video(self): - from anime_parsers_ru import KodikParserAsync + from src.anime_parsers_ru import KodikParserAsync parser = KodikParserAsync(use_lxml=self.USE_LXML) cur_search = await parser.get_info('2472', 'shikimori') self.assertIsInstance(cur_search, dict) @@ -275,7 +275,7 @@ async def test_get_info_video(self): self.assertIsInstance(cur_search['translations'][0], dict) async def test_get_link_serial(self): - from anime_parsers_ru import KodikParserAsync + from src.anime_parsers_ru import KodikParserAsync parser = KodikParserAsync(use_lxml=self.USE_LXML) link = await parser.get_link('z20', 'shikimori', 1, '609') self.assertIsInstance(link, tuple) @@ -283,7 +283,7 @@ async def test_get_link_serial(self): self.assertIsInstance(link[1], int) async def test_get_link_video(self): - from anime_parsers_ru import KodikParserAsync + from src.anime_parsers_ru import KodikParserAsync parser = KodikParserAsync(use_lxml=self.USE_LXML) link = await parser.get_link('2472', 'shikimori', 0, '609') self.assertIsInstance(link, tuple) @@ -293,15 +293,15 @@ async def test_get_link_video(self): class TestAniboom(unittest.TestCase): USE_LXML = GLOBAL_USE_LXML def test_import(self): - from anime_parsers_ru import AniboomParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import AniboomParser + import src.anime_parsers_ru.errors as errors def test_init(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) def test_fast_search(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) search = parser.fast_search('Наруто') self.assertGreater(len(search), 0) # Гарантированно имеются данные @@ -310,7 +310,7 @@ def test_fast_search(self): # Нельзя проверить на то что нет результатов, потому что у animego всегда есть результаты на какой угодно запрос \_(-_-)_/ def test_episodes_info(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) data = parser.episodes_info('https://animego.org/anime/volchica-i-pryanosti-torgovec-vstrechaet-mudruyu-volchicu-2546') self.assertIsInstance(data, list) @@ -325,7 +325,7 @@ def test_episodes_info(self): self.assertEqual(len(data), 0) def test_translations_info(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) data = parser.get_translations_info('2546') # Волчица и пряности 2024 self.assertIsInstance(data, list) @@ -339,7 +339,7 @@ def test_translations_info(self): self.assertEqual(len(data), 0) def test_anime_info(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) data = parser.anime_info('https://animego.org/anime/volchica-i-pryanosti-torgovec-vstrechaet-mudruyu-volchicu-2546') self.assertIsInstance(data, dict) @@ -353,7 +353,7 @@ def test_anime_info(self): self.assertTrue('translations' in data.keys()) def test_search(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) search = parser.search('Наруто') @@ -367,13 +367,13 @@ def test_search(self): self.assertIsInstance(search[0], dict) def test_get_embed_link(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) data = parser._get_embed_link('2546') self.assertIsInstance(data, str) def test_get_embed(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) link = parser._get_embed_link('2546') # Волчица и пряности 2024 data = parser._get_embed(link, 1, '2') # Озвучка от AniLibria @@ -385,7 +385,7 @@ def test_get_embed(self): self.assertIsInstance(data, str) def test_get_media_src(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) link = parser._get_embed_link('2546') # Волчица и пряности 2024 data = parser._get_media_src(link, 1, '2') # Озвучка от AniLibria @@ -397,7 +397,7 @@ def test_get_media_src(self): self.assertIsInstance(data, str) def test_get_mpd_playlist(self): - from anime_parsers_ru import AniboomParser + from src.anime_parsers_ru import AniboomParser parser = AniboomParser(use_lxml=self.USE_LXML) data = parser.get_mpd_playlist('2546', 1, '2') # Озвучка от AniLibria self.assertIsInstance(data, str) @@ -413,15 +413,15 @@ def test_get_mpd_playlist(self): class TestAniboomAsync(unittest.IsolatedAsyncioTestCase): USE_LXML = GLOBAL_USE_LXML def test_import(self): - from anime_parsers_ru import AniboomParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import AniboomParserAsync + import src.anime_parsers_ru.errors as errors def test_init(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) async def test_fast_search(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) search = await parser.fast_search('Наруто') self.assertGreater(len(search), 0) # Гарантированно имеются данные @@ -430,7 +430,7 @@ async def test_fast_search(self): # Нельзя проверить на то что нет результатов, потому что у animego всегда есть результаты на какой угодно запрос \_(-_-)_/ async def test_episodes_info(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) data = await parser.episodes_info('https://animego.org/anime/volchica-i-pryanosti-torgovec-vstrechaet-mudruyu-volchicu-2546') self.assertIsInstance(data, list) @@ -445,7 +445,7 @@ async def test_episodes_info(self): self.assertEqual(len(data), 0) async def test_translations_info(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) data = await parser.get_translations_info('2546') # Волчица и пряности 2024 self.assertIsInstance(data, list) @@ -459,7 +459,7 @@ async def test_translations_info(self): self.assertEqual(len(data), 0) async def test_anime_info(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) data = await parser.anime_info('https://animego.org/anime/volchica-i-pryanosti-torgovec-vstrechaet-mudruyu-volchicu-2546') self.assertIsInstance(data, dict) @@ -473,7 +473,7 @@ async def test_anime_info(self): self.assertTrue('translations' in data.keys()) async def test_search(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) search = await parser.search('Наруто') @@ -487,13 +487,13 @@ async def test_search(self): self.assertIsInstance(search[0], dict) async def test_get_embed_link(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) data = await parser._get_embed_link('2546') self.assertIsInstance(data, str) async def test_get_embed(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) link = await parser._get_embed_link('2546') # Волчица и пряности 2024 data = await parser._get_embed(link, 1, '2') # Озвучка от AniLibria @@ -505,7 +505,7 @@ async def test_get_embed(self): self.assertIsInstance(data, str) async def test_get_media_src(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) link = await parser._get_embed_link('2546') # Волчица и пряности 2024 data = await parser._get_media_src(link, 1, '2') # Озвучка от AniLibria @@ -517,7 +517,7 @@ async def test_get_media_src(self): self.assertIsInstance(data, str) async def test_get_mpd_playlist(self): - from anime_parsers_ru import AniboomParserAsync + from src.anime_parsers_ru import AniboomParserAsync parser = AniboomParserAsync(use_lxml=self.USE_LXML) data = await parser.get_mpd_playlist('2546', 1, '2') # Озвучка от AniLibria self.assertIsInstance(data, str) @@ -533,12 +533,12 @@ async def test_get_mpd_playlist(self): class TestJutsu(unittest.TestCase): USE_LXML = GLOBAL_USE_LXML def test_import(self): - from anime_parsers_ru import JutsuParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import JutsuParser + import src.anime_parsers_ru.errors as errors def test_get_anime_info(self): - from anime_parsers_ru import JutsuParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import JutsuParser + import src.anime_parsers_ru.errors as errors parser = JutsuParser(self.USE_LXML) # Проверка на аниме с одним сезоном @@ -571,8 +571,8 @@ def test_get_anime_info(self): self.assertIsInstance(data['films'][0], str) def test_get_mp4_link(self): - from anime_parsers_ru import JutsuParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import JutsuParser + import src.anime_parsers_ru.errors as errors parser = JutsuParser(self.USE_LXML) # Проверка без сезонов @@ -590,11 +590,11 @@ def test_get_mp4_link(self): class TestShikimori(unittest.TestCase): USE_LXML = GLOBAL_USE_LXML def test_import(self): - from anime_parsers_ru import ShikimoriParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import ShikimoriParser + import src.anime_parsers_ru.errors as errors def test_search(self): - from anime_parsers_ru import ShikimoriParser + from src.anime_parsers_ru import ShikimoriParser parser = ShikimoriParser(self.USE_LXML) data = parser.search('Кулинарные скитания') @@ -618,8 +618,8 @@ def test_search(self): self.assertIsInstance(data[0], dict) def test_anime_info(self): - from anime_parsers_ru import ShikimoriParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import ShikimoriParser + import src.anime_parsers_ru.errors as errors parser = ShikimoriParser(self.USE_LXML) data = parser.anime_info('https://shikimori.one/animes/z20-naruto') @@ -645,7 +645,7 @@ def test_anime_info(self): raise Warning('Обработка ограниченного по возрасту аниме не вернуло ошибку. Ожидалось: "AgeRestricted"') def test_additional_anime_info(self): - from anime_parsers_ru import ShikimoriParser + from src.anime_parsers_ru import ShikimoriParser parser = ShikimoriParser(self.USE_LXML) data = parser.additional_anime_info('https://shikimori.one/animes/z20-naruto') @@ -660,7 +660,7 @@ def test_additional_anime_info(self): self.assertIsInstance(data, dict) def test_link_by_id(self): - from anime_parsers_ru import ShikimoriParser + from src.anime_parsers_ru import ShikimoriParser parser = ShikimoriParser(self.USE_LXML) data = parser.link_by_id('20') # Наруто (реальный id - z20) @@ -676,7 +676,7 @@ def test_link_by_id(self): self.assertIsInstance(data, str) def test_id_by_link(self): - from anime_parsers_ru import ShikimoriParser + from src.anime_parsers_ru import ShikimoriParser parser = ShikimoriParser(self.USE_LXML) data = parser.id_by_link('https://shikimori.one/animes/z20-naruto') # Наруто (реальный id - z20 ожидаем - 20) @@ -692,7 +692,7 @@ def test_id_by_link(self): self.assertTrue(data == '58426') def test_get_anime_list(self): - from anime_parsers_ru import ShikimoriParser + from src.anime_parsers_ru import ShikimoriParser parser = ShikimoriParser(self.USE_LXML) data = parser.get_anime_list() @@ -753,7 +753,7 @@ def test_get_anime_list(self): def test_deep_search(self): - from anime_parsers_ru import ShikimoriParser + from src.anime_parsers_ru import ShikimoriParser parser = ShikimoriParser(self.USE_LXML) # Просто проверим доступность ссылки @@ -763,8 +763,8 @@ def test_deep_search(self): self.assertIsInstance(data[0], dict) def test_deep_anime_info(self): - from anime_parsers_ru import ShikimoriParser - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import ShikimoriParser + import src.anime_parsers_ru.errors as errors parser = ShikimoriParser(self.USE_LXML) # Просто проверим доступность ссылки @@ -784,11 +784,11 @@ def test_deep_anime_info(self): class TestShikimoriAsync(unittest.IsolatedAsyncioTestCase): USE_LXML = GLOBAL_USE_LXML def test_import(self): - from anime_parsers_ru import ShikimoriParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import ShikimoriParserAsync + import src.anime_parsers_ru.errors as errors async def test_search(self): - from anime_parsers_ru import ShikimoriParserAsync + from src.anime_parsers_ru import ShikimoriParserAsync parser = ShikimoriParserAsync(self.USE_LXML) data = await parser.search('Кулинарные скитания') @@ -812,8 +812,8 @@ async def test_search(self): self.assertIsInstance(data[0], dict) async def test_anime_info(self): - from anime_parsers_ru import ShikimoriParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import ShikimoriParserAsync + import src.anime_parsers_ru.errors as errors parser = ShikimoriParserAsync(self.USE_LXML) data = await parser.anime_info('https://shikimori.one/animes/z20-naruto') @@ -839,7 +839,7 @@ async def test_anime_info(self): raise Warning('Обработка ограниченного по возрасту аниме не вернуло ошибку. Ожидалось: "AgeRestricted"') async def test_additional_anime_info(self): - from anime_parsers_ru import ShikimoriParserAsync + from src.anime_parsers_ru import ShikimoriParserAsync parser = ShikimoriParserAsync(self.USE_LXML) data = await parser.additional_anime_info('https://shikimori.one/animes/z20-naruto') @@ -854,7 +854,7 @@ async def test_additional_anime_info(self): self.assertIsInstance(data, dict) async def test_link_by_id(self): - from anime_parsers_ru import ShikimoriParserAsync + from src.anime_parsers_ru import ShikimoriParserAsync parser = ShikimoriParserAsync(self.USE_LXML) data = await parser.link_by_id('20') # Наруто (реальный id - z20) @@ -870,7 +870,7 @@ async def test_link_by_id(self): self.assertIsInstance(data, str) def test_id_by_link(self): - from anime_parsers_ru import ShikimoriParserAsync + from src.anime_parsers_ru import ShikimoriParserAsync parser = ShikimoriParserAsync(self.USE_LXML) data = parser.id_by_link('https://shikimori.one/animes/z20-naruto') # Наруто (реальный id - z20 ожидаем - 20) @@ -886,7 +886,7 @@ def test_id_by_link(self): self.assertTrue(data == '58426') async def test_get_anime_list(self): - from anime_parsers_ru import ShikimoriParserAsync + from src.anime_parsers_ru import ShikimoriParserAsync parser = ShikimoriParserAsync(self.USE_LXML) data = await parser.get_anime_list() @@ -946,7 +946,7 @@ async def test_get_anime_list(self): self.assertTrue(data[0]['type'] == 'TV Сериал') async def test_deep_search(self): - from anime_parsers_ru import ShikimoriParserAsync + from src.anime_parsers_ru import ShikimoriParserAsync parser = ShikimoriParserAsync(self.USE_LXML) # Просто проверим доступность ссылки @@ -956,8 +956,8 @@ async def test_deep_search(self): self.assertIsInstance(data[0], dict) async def test_deep_anime_info(self): - from anime_parsers_ru import ShikimoriParserAsync - import anime_parsers_ru.errors as errors + from src.anime_parsers_ru import ShikimoriParserAsync + import src.anime_parsers_ru.errors as errors parser = ShikimoriParserAsync(self.USE_LXML) # Просто проверим доступность ссылки