import abc
import json
import requests
from typing import Dict, Any
class Base(abc.ABC)
@abc.abstractmethod
def call(self, *args, **kwargs) -> requests.Response:
raise NotImplementedError
def safe_call(self, *args, **kwargs) -> Dict[str, Any]:
try:
response = self.call(*args, **kwargs)
response.raise_for_status()
return response.json()
except json.JSONDecodeError as je: ...
except requests.exceptions.ConnectionError as ce: ...
except requests.exceptions.Timeout as te: ...
except requests.exceptions.HTTPError as he: ...
except Exception as e: ...
return {"success": False}
class Derived(Base):
def call(self, url: str, json: Dict[str, Any], timeout: int, retries: int) -> requests.Response:
# actual logic for making the http call
response = requests.post(url, json=json, timeout=timeout, ...)
return response
который будет использоваться как
executor = Derived()
response = executor.safe_call(url='https://example.com', json={"key": "value"}, ...)
Есть ли способ прикрепить подпись Derived.call к Derived.safe_call, чтобы современные автозаполнение IDE и средства проверки типов работали?
Поскольку это ужасно похоже на шаблон декоратора, я попробовал использовать functools.update_wrapper в __init__, но это не помогло
AttributeError: 'method' object has no attribute '__module__'
У меня есть несколько вариантов, но я не могу найти никаких рекомендаций по этой проблеме.
- Я может пойти по пути метакласса, чтобы изменить атрибуты подписи и строки документации до того, как класс будет полностью создан. Однако это может не работать с IDE.
- Я могу определить файл-заглушку .pyi и поддерживать его вместе с основным кодом.
def safe_call(self, url: str, json: Dict[str, Any], timeout: int, retries: int) -> Dict[str, Any]: ...
- Полностью измените дизайн на другой
< li>(Изменить: добавлен первый ответ) (Ab) используйте @typing.overload
@typing.overload
def safe_call(self, url: str, json: Dict[str, Any], timeout: int, retries: int) -> Dict[str, Any]:
...
def call(self, url: str, json: Dict[str, Any], timeout: int, retries: int) -> requests.Response:
# actual logic for making the http call
response = requests.post(url, json=json, timeout=timeout, ...)
return response
Подробнее здесь: https://stackoverflow.com/questions/687 ... ethod-from