Это действительно большая тема, но не общая.У меня лично есть частный проект WebDAV, который реализует и версию синхронизации, и асинхронную версию.
Во-первых, мой клиент WebDAV принимает один аргумент с именем client
, который может быть requests.Session
или aiohttp.ClientSession
для выполнения синхронизации.запросы или асинхронные запросы.
Во-вторых, у меня есть базовый класс для реализации всей общей логики, такой как:
def _perform_dav_request(self, method, auth_tuple=None, client=None, **kwargs):
auth_tuple = self._get_auth_tuple(auth_tuple)
client = self._get_client(client)
data = kwargs.get("data")
headers = None
url = None
path = kwargs.get("path")
if path:
root_url = urljoin(self._base_url, self._dav_url)
url = root_url + path
from_path = kwargs.get("from_path")
to_path = kwargs.get("to_path")
if from_path and to_path:
root_url = urljoin(self._base_url, self._dav_url)
url = root_url + from_path
destination = root_url + quote(to_path)
headers = {
"Destination": destination
}
return client.request(method, url, data=data, headers=headers, auth=auth_tuple)
Дело в том, что и requests.Session
, и aiohttp.ClientSession
поддерживают почти одинаковоAPI, поэтому здесь я мог бы использовать неоднозначный вызов client.request(...)
.
В-третьих, я должен экспортировать различные API:
# In async client
async def ls(self, path, auth_tuple=None, client=None):
response = await self._perform_dav_request("PROPFIND", auth_tuple, client, path=path)
if response.status == 207:
return parse_ls(await response.read())
raise WebDavHTTPError(response.status, await response.read())
# In sync client
def ls(self, path, auth_tuple=None, client=None):
response = self._perform_dav_request("PROPFIND", auth_tuple, client, path=path)
if response.status_code == 207:
return parse_ls(response.content)
raise WebDavHTTPError(response.status_code, response.content)
Так, наконец, мои пользователи могут использовать его как dav = DAV(...)
илиdav = AsyncDAV(...)
.
Так я работаю с двумя разными версиями.Я думаю, что идея заключается в том, что вы можете передавать эти сопрограммы через вызовы функций и оценивать их только на самом высоком уровне.Таким образом, вам нужно только написать другой код на последнем уровне, но иметь ту же логику на всех других уровнях.