Разделить вход между вкладками#
BrowserLogin описывает способ входа и признаки живой сессии. Учётные данные и состояние
принадлежат BrowserSession, которую получают через login.session(...).
Сервис входа работает на странице того же клиента и возвращает состояние контекста:
# examples/mail/browser/session.py
@dataclass(frozen=True, slots=True)
class MailCredentials:
email: str
password: str = field(repr=False)
otp: str = field(repr=False)
@dataclass(slots=True)
class MailLoginService:
calls: int = 0
async def acquire(
self,
credentials: MailCredentials,
context: BrowserLoginContext,
) -> BrowserState:
self.calls += 1
portal = LoginPortal(context.client)
password = await portal.identify(email=credentials.email, options=OPTIONS)
otp = await password.submit(password=credentials.password)
await otp.submit(code=credentials.otp)
return await context.export_state()
Один объект сессии можно передать нескольким вкладкам одного контекста:
# examples/docs/integration_browser_login.py
logins, tabs, cookie = await one_login_for_two_tabs()
Файл целиком
"""Share one browser session between two tabs."""
from __future__ import annotations
import asyncio
from examples.mail.browser.session import one_login_for_two_tabs
async def main() -> None:
# docs:integration-browser-login:start
# examples/docs/integration_browser_login.py
logins, tabs, cookie = await one_login_for_two_tabs()
# docs:integration-browser-login:end
print(f"browser logins: {logins}")
print(f"tabs in context: {tabs}")
print(f"session cookie: {cookie}")
if __name__ == "__main__":
asyncio.run(main())
browser logins: 1
tabs in context: 2
session cookie: session-ada
Первый вызов берёт блокировку сессии и входит. Параллельный вызов ждёт ту же ревизию, поэтому две вкладки выполняют один вход. Объект сессии нельзя переносить в другой контекст; новый контекст получает новый объект и общее хранилище ревизий.
Объект |
Владеет |
|---|---|
|
сервисом входа, обязательными cookies и типами истечения |
|
учётными данными, блокировкой, хранилищем и ревизией контекста |
|
выполнением операций одной страницы |
Если отказ входит в expired=, клиент обновляет сессию и повторяет операцию в пределах
auth_retries. HTTP-клиенту та же сессия отдаётся целиком:
Identity(cookies=CookieState(state.cookies)) для SDK, объявившего Cookies(...).