sources refactor
This commit is contained in:
parent
20ef74f32b
commit
3131f2d0a0
@ -6,7 +6,7 @@ from httpx import AsyncHTTPTransport
|
|||||||
|
|
||||||
|
|
||||||
class IPAddreses(NamedTuple):
|
class IPAddreses(NamedTuple):
|
||||||
"""набор из названия источника и IP адресов, результат одного из источников"""
|
"""Набор из названия источника и IP адресов, результат одного из источников"""
|
||||||
|
|
||||||
source_name: str
|
source_name: str
|
||||||
ipv4: str
|
ipv4: str
|
||||||
@ -14,7 +14,7 @@ class IPAddreses(NamedTuple):
|
|||||||
|
|
||||||
|
|
||||||
class BaseSourceProvider(ABC):
|
class BaseSourceProvider(ABC):
|
||||||
"""базовый класс для провайдеров источников"""
|
"""Базовый класс для провайдеров источников"""
|
||||||
|
|
||||||
_childs = {}
|
_childs = {}
|
||||||
registred = {}
|
registred = {}
|
||||||
@ -35,14 +35,22 @@ class BaseSourceProvider(ABC):
|
|||||||
self.post_init()
|
self.post_init()
|
||||||
|
|
||||||
def post_init(self):
|
def post_init(self):
|
||||||
"""метод для переопределения пост инициализации"""
|
"""Метод для переопределения пост инициализации"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.__class__.__name__}: {self.name}"
|
return f"{self.__class__.__name__}: {self.name}"
|
||||||
|
|
||||||
|
def filter_ipv4(self, value: str) -> str:
|
||||||
|
"""Функция для проверки валидности IPv4 адреса, возвращает "" если адрес неправильный или пустой"""
|
||||||
|
return value if value and valid_ipv4(value) else ""
|
||||||
|
|
||||||
|
def filter_ipv6(self, value: str) -> str:
|
||||||
|
"""Функция для проверки валидности IPv6 адреса, возвращает "" если адрес неправильный или пустой"""
|
||||||
|
return value if value and valid_ipv6(value) else ""
|
||||||
|
|
||||||
async def fetch_all(self) -> IPAddreses:
|
async def fetch_all(self) -> IPAddreses:
|
||||||
"""метод для получения всех ip адресов сразу"""
|
"""Метод для получения всех IP адресов сразу"""
|
||||||
results = await asyncio.gather(
|
results = await asyncio.gather(
|
||||||
self.fetch_v4(), self.fetch_v6(), return_exceptions=True
|
self.fetch_v4(), self.fetch_v6(), return_exceptions=True
|
||||||
)
|
)
|
||||||
@ -51,13 +59,23 @@ class BaseSourceProvider(ABC):
|
|||||||
self.name, *("" if isinstance(i, Exception) else i for i in results)
|
self.name, *("" if isinstance(i, Exception) else i for i in results)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def fetch_v4(self) -> str:
|
||||||
|
"""Метод внешнего интерфейса для получения IPv4"""
|
||||||
|
ipv4 = await self.fetch_v4_impl()
|
||||||
|
return self.filter_ipv4(ipv4)
|
||||||
|
|
||||||
|
async def fetch_v6(self) -> str:
|
||||||
|
"""Метод внешнего интерфейса для получения IPv6"""
|
||||||
|
ipv6 = await self.fetch_v6_impl()
|
||||||
|
return self.filter_ipv6(ipv6)
|
||||||
|
|
||||||
def __init_subclass__(cls) -> None:
|
def __init_subclass__(cls) -> None:
|
||||||
BaseSourceProvider._childs[cls.__name__] = cls
|
BaseSourceProvider._childs[cls.__name__] = cls
|
||||||
return super().__init_subclass__()
|
return super().__init_subclass__()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_source_config(cls, name: str, config: dict):
|
def validate_source_config(cls, name: str, config: dict):
|
||||||
"""метод валидации конфигурации для провайдера"""
|
"""Метод валидации конфигурации для провайдера"""
|
||||||
if "provider" not in config:
|
if "provider" not in config:
|
||||||
return False
|
return False
|
||||||
prov_name = config["provider"]
|
prov_name = config["provider"]
|
||||||
@ -73,7 +91,7 @@ class BaseSourceProvider(ABC):
|
|||||||
ipv4t: AsyncHTTPTransport,
|
ipv4t: AsyncHTTPTransport,
|
||||||
ipv6t: AsyncHTTPTransport,
|
ipv6t: AsyncHTTPTransport,
|
||||||
):
|
):
|
||||||
"""метод регистрации провайдера по конфигурации"""
|
"""Метод регистрации провайдера по конфигурации"""
|
||||||
|
|
||||||
if not cls.validate_source_config(name, config):
|
if not cls.validate_source_config(name, config):
|
||||||
return
|
return
|
||||||
@ -81,18 +99,18 @@ class BaseSourceProvider(ABC):
|
|||||||
cls.registred[name] = provider(name, config, ipv4t, ipv6t)
|
cls.registred[name] = provider(name, config, ipv4t, ipv6t)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def fetch_v4(self) -> str:
|
async def fetch_v4_impl(self) -> Optional[str]:
|
||||||
"""необходимый метод для реализации получения ipv4"""
|
"""Необходимый метод для реализации получения IPv4"""
|
||||||
...
|
...
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def fetch_v6(self) -> str:
|
async def fetch_v6_impl(self) -> Optional[str]:
|
||||||
"""необходимый метод для реализации получения ipv6"""
|
"""Необходимый метод для реализации получения IPv6"""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
class BaseOutputProvider(ABC):
|
class BaseOutputProvider(ABC):
|
||||||
"""базовый класс для провайдеров вывода"""
|
"""Базовый класс для провайдеров вывода"""
|
||||||
|
|
||||||
_childs = {}
|
_childs = {}
|
||||||
registred = {}
|
registred = {}
|
||||||
@ -109,7 +127,7 @@ class BaseOutputProvider(ABC):
|
|||||||
self.post_init()
|
self.post_init()
|
||||||
|
|
||||||
def post_init(self):
|
def post_init(self):
|
||||||
"""метод для переопределения пост инициализации"""
|
"""Метод для переопределения пост инициализации"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def __init_subclass__(cls) -> None:
|
def __init_subclass__(cls) -> None:
|
||||||
@ -120,14 +138,14 @@ class BaseOutputProvider(ABC):
|
|||||||
return f"{self.__class__.__name__}: {self.name}"
|
return f"{self.__class__.__name__}: {self.name}"
|
||||||
|
|
||||||
def best_transport(self, addr_v4: str, addr_v6: str) -> AsyncHTTPTransport:
|
def best_transport(self, addr_v4: str, addr_v6: str) -> AsyncHTTPTransport:
|
||||||
"""метод выбирает лучший транспорт для отправки адресов (либо ipv4 либо ipv6)"""
|
"""Метод выбирает лучший транспорт для отправки адресов (либо ipv4 либо ipv6)"""
|
||||||
if addr_v6:
|
if addr_v6:
|
||||||
return self.ipv6t
|
return self.ipv6t
|
||||||
return self.ipv4t
|
return self.ipv4t
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_source_config(cls, name: str, config: dict):
|
def validate_source_config(cls, name: str, config: dict):
|
||||||
"""метод валидации конфигурации для провайдера"""
|
"""Метод валидации конфигурации для провайдера"""
|
||||||
|
|
||||||
if "provider" not in config:
|
if "provider" not in config:
|
||||||
return False
|
return False
|
||||||
@ -144,24 +162,24 @@ class BaseOutputProvider(ABC):
|
|||||||
ipv4t: AsyncHTTPTransport,
|
ipv4t: AsyncHTTPTransport,
|
||||||
ipv6t: AsyncHTTPTransport,
|
ipv6t: AsyncHTTPTransport,
|
||||||
):
|
):
|
||||||
"""метод регистрации провайдера по конфигурации"""
|
"""Метод регистрации провайдера по конфигурации"""
|
||||||
if not cls.validate_source_config(name, config):
|
if not cls.validate_source_config(name, config):
|
||||||
return
|
return
|
||||||
provider = cls._childs[config["provider"]]
|
provider = cls._childs[config["provider"]]
|
||||||
cls.registred[name] = provider(name, config, ipv4t, ipv6t)
|
cls.registred[name] = provider(name, config, ipv4t, ipv6t)
|
||||||
|
|
||||||
async def set_addrs(self, source_provider: str, addr_v4: str, addr_v6: str):
|
async def set_addrs(self, source_provider: str, addr_v4: str, addr_v6: str):
|
||||||
"""метод внешнего интерфейса для отправки адресов"""
|
"""Метод внешнего интерфейса для отправки адресов"""
|
||||||
return await self.set_addrs_imp(source_provider, addr_v4, addr_v6)
|
return await self.set_addrs_imp(source_provider, addr_v4, addr_v6)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def set_addrs_imp(self, source_provider: str, addr_v4: str, addr_v6: str):
|
async def set_addrs_imp(self, source_provider: str, addr_v4: str, addr_v6: str):
|
||||||
"""необходимый метод для реализации отправки/вывода IP аддресов"""
|
"""Необходимый метод для реализации отправки/вывода IP аддресов"""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
class BaseFilterProvider(ABC):
|
class BaseFilterProvider(ABC):
|
||||||
"""базовый класс для провайдеров фильтров"""
|
"""Базовый класс для провайдеров фильтров"""
|
||||||
|
|
||||||
_childs = {}
|
_childs = {}
|
||||||
registred = {}
|
registred = {}
|
||||||
@ -178,7 +196,7 @@ class BaseFilterProvider(ABC):
|
|||||||
self.post_init()
|
self.post_init()
|
||||||
|
|
||||||
def post_init(self):
|
def post_init(self):
|
||||||
"""метод для переопределения пост инициализации"""
|
"""Метод для переопределения пост инициализации"""
|
||||||
...
|
...
|
||||||
|
|
||||||
def __init_subclass__(cls) -> None:
|
def __init_subclass__(cls) -> None:
|
||||||
@ -190,7 +208,7 @@ class BaseFilterProvider(ABC):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_source_config(cls, name: str, config: dict) -> bool:
|
def validate_source_config(cls, name: str, config: dict) -> bool:
|
||||||
"""метод валидации конфигурации для провайдера"""
|
"""Метод валидации конфигурации для провайдера"""
|
||||||
|
|
||||||
if "provider" not in config:
|
if "provider" not in config:
|
||||||
return False
|
return False
|
||||||
@ -207,7 +225,7 @@ class BaseFilterProvider(ABC):
|
|||||||
ipv4t: AsyncHTTPTransport,
|
ipv4t: AsyncHTTPTransport,
|
||||||
ipv6t: AsyncHTTPTransport,
|
ipv6t: AsyncHTTPTransport,
|
||||||
):
|
):
|
||||||
"""метод регистрации провайдера по конфигурации"""
|
"""Метод регистрации провайдера по конфигурации"""
|
||||||
|
|
||||||
if not cls.validate_source_config(name, config):
|
if not cls.validate_source_config(name, config):
|
||||||
return
|
return
|
||||||
@ -215,20 +233,10 @@ class BaseFilterProvider(ABC):
|
|||||||
cls.registred[name] = provider(name, config, ipv4t, ipv6t)
|
cls.registred[name] = provider(name, config, ipv4t, ipv6t)
|
||||||
|
|
||||||
async def check(self, source_provider: str, addr_v4: str, addr_v6: str) -> bool:
|
async def check(self, source_provider: str, addr_v4: str, addr_v6: str) -> bool:
|
||||||
"""метод внешнего интерфейса для проверки адресов"""
|
"""Метод внешнего интерфейса для проверки адресов"""
|
||||||
return await self.check_imp(source_provider, addr_v4, addr_v6)
|
return await self.check_imp(source_provider, addr_v4, addr_v6)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def check_imp(self, source_provider: str, addr_v4: str, addr_v6: str) -> bool:
|
async def check_imp(self, source_provider: str, addr_v4: str, addr_v6: str) -> bool:
|
||||||
"""необходимый метод реализации проверки"""
|
"""Необходимый метод реализации проверки"""
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
def filter_ipv4(value: str) -> Optional[str]:
|
|
||||||
"""функция для проверки валидности IPv4 адреса, возвращает None если адрес неправильный или пустой"""
|
|
||||||
return value and valid_ipv4(value) and value or None
|
|
||||||
|
|
||||||
|
|
||||||
def filter_ipv6(value: str) -> Optional[str]:
|
|
||||||
"""функция для проверки валидности IPv6 адреса, возвращает None если адрес неправильный или пустой"""
|
|
||||||
return value and valid_ipv6(value) and value or None
|
|
||||||
|
@ -6,27 +6,33 @@ from pddnsc.base import BaseSourceProvider
|
|||||||
|
|
||||||
|
|
||||||
class DummySource(BaseSourceProvider):
|
class DummySource(BaseSourceProvider):
|
||||||
"""имитация получения пустых адресов"""
|
"""Имитация получения пустых адресов"""
|
||||||
|
|
||||||
async def fetch_v4(self) -> str:
|
async def fetch_v4_impl(self) -> str:
|
||||||
result = await asyncio.sleep(self.config.get("delay", 1), result="")
|
result = await asyncio.sleep(self.config.get("delay", 1), result="")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def fetch_v6(self) -> str:
|
async def fetch_v6_impl(self) -> str:
|
||||||
result = await asyncio.sleep(self.config.get("delay", 1), result="")
|
result = await asyncio.sleep(self.config.get("delay", 1), result="")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class FakeSource(BaseSourceProvider):
|
class FakeSource(BaseSourceProvider):
|
||||||
"""имитация получения заданных в конфигурации адресов"""
|
"""Имитация получения заданных в конфигурации адресов
|
||||||
|
|
||||||
async def fetch_v4(self) -> str:
|
Конфигурация:
|
||||||
|
|
||||||
|
- ipv4: строка IPv4, по умолчанию "127.0.0.1"
|
||||||
|
- ipv6: строка IPv6, по умолчанию "::1"
|
||||||
|
"""
|
||||||
|
|
||||||
|
async def fetch_v4_impl(self) -> str:
|
||||||
result = await asyncio.sleep(
|
result = await asyncio.sleep(
|
||||||
self.config.get("delay", 1), result=self.config.get("ipv4", "127.0.0.1")
|
self.config.get("delay", 1), result=self.config.get("ipv4", "127.0.0.1")
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
async def fetch_v6(self) -> str:
|
async def fetch_v6_impl(self) -> str:
|
||||||
result = await asyncio.sleep(
|
result = await asyncio.sleep(
|
||||||
self.config.get("delay", 1), result=self.config.get("ipv6", "::1")
|
self.config.get("delay", 1), result=self.config.get("ipv6", "::1")
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
from typing import Optional
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from pddnsc.base import BaseSourceProvider, filter_ipv4, filter_ipv6
|
from pddnsc.base import BaseSourceProvider
|
||||||
|
|
||||||
|
|
||||||
class GenericHttpSource(BaseSourceProvider):
|
class GenericHttpSource(BaseSourceProvider):
|
||||||
@ -18,7 +19,7 @@ class GenericHttpSource(BaseSourceProvider):
|
|||||||
self.url_v6 = self.config.get("url_v6")
|
self.url_v6 = self.config.get("url_v6")
|
||||||
self.headers = self.config.get("headers", {})
|
self.headers = self.config.get("headers", {})
|
||||||
|
|
||||||
async def fetch_v4(self) -> str:
|
async def fetch_v4_impl(self) -> Optional[str]:
|
||||||
if not self.url_v4:
|
if not self.url_v4:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -29,9 +30,9 @@ class GenericHttpSource(BaseSourceProvider):
|
|||||||
response = await client.get(self.url_v4)
|
response = await client.get(self.url_v4)
|
||||||
if response.is_success:
|
if response.is_success:
|
||||||
result = response.text.strip()
|
result = response.text.strip()
|
||||||
return filter_ipv4(result)
|
return result
|
||||||
|
|
||||||
async def fetch_v6(self) -> str:
|
async def fetch_v6_impl(self) -> Optional[str]:
|
||||||
if not self.url_v6:
|
if not self.url_v6:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -42,7 +43,7 @@ class GenericHttpSource(BaseSourceProvider):
|
|||||||
response = await client.get(self.url_v6)
|
response = await client.get(self.url_v6)
|
||||||
if response.is_success:
|
if response.is_success:
|
||||||
result = response.text.strip()
|
result = response.text.strip()
|
||||||
return filter_ipv6(result)
|
return result
|
||||||
|
|
||||||
|
|
||||||
class GenericHttpJsonSource(BaseSourceProvider):
|
class GenericHttpJsonSource(BaseSourceProvider):
|
||||||
@ -68,7 +69,7 @@ class GenericHttpJsonSource(BaseSourceProvider):
|
|||||||
headers = {}
|
headers = {}
|
||||||
self.headers = headers.update(self.config.get("headers", {}))
|
self.headers = headers.update(self.config.get("headers", {}))
|
||||||
|
|
||||||
async def fetch_v4(self) -> str:
|
async def fetch_v4_impl(self) -> Optional[str]:
|
||||||
if not self.url_v4 or self.key_v4 is None:
|
if not self.url_v4 or self.key_v4 is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -79,9 +80,9 @@ class GenericHttpJsonSource(BaseSourceProvider):
|
|||||||
response = await client.get(self.url_v4)
|
response = await client.get(self.url_v4)
|
||||||
if response.is_success:
|
if response.is_success:
|
||||||
result = response.json()[self.key_v4].strip()
|
result = response.json()[self.key_v4].strip()
|
||||||
return filter_ipv4(result)
|
return result
|
||||||
|
|
||||||
async def fetch_v6(self) -> str:
|
async def fetch_v6_impl(self) -> Optional[str]:
|
||||||
if not self.url_v6 or self.key_v6 is None:
|
if not self.url_v6 or self.key_v6 is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -92,4 +93,4 @@ class GenericHttpJsonSource(BaseSourceProvider):
|
|||||||
response = await client.get(self.url_v6)
|
response = await client.get(self.url_v6)
|
||||||
if response.is_success:
|
if response.is_success:
|
||||||
result = response.json()[self.key_v6].strip()
|
result = response.json()[self.key_v6].strip()
|
||||||
return filter_ipv6(result)
|
return result
|
||||||
|
Loading…
Reference in New Issue
Block a user