[docs]classBrowserMaster:""" Family aggregator. Holds the currently selected backend and delegates launch/close. Always returns a Browser. No persistent context. """def__init__(self,*,engine:Engine="chromium",stealth:bool=False,launch_opts:Dict[str,Any]|None=None,)->None:self._engine:Engine=engineself._stealth_flag:bool=stealthself.launch_opts=launch_optsor{}# через сеттер нижеself._family:BrowserFamily|None=None# активное семействоself._validate_compat()# ─────────── свойства (сеттеры не запускают, только меняют «desired») ───────────@property
@launch_opts.setterdeflaunch_opts(self,value:Dict[str,Any]|None)->None:opts=dict(valueor{})self._launch_opts=opts# ─────────────────────────── публичные методы ───────────────────────────
[docs]asyncdefstart(self)->None:"""Idempotent launch of the current family. Switches family if necessary."""fam=self._select_family(self._engine)ifself._familyisNoneor(self._family.name!=fam.name):# переключаемся на другое семейство — закрываем прежнееawaitself.close(camoufox=True,playwright=True)self._family=fameng:PlaywrightEngine|None=(cast(PlaywrightEngine,self._engine)iffam.name=="playwright"elseNone)cfg=DesiredConfig(family=fam.name,engine=eng,stealth=self._stealth_flag,launch_opts=self._launch_opts,)awaitself._family.start(cfg)