Repository: apify/crawlee-python
File: src/crawlee/browsers/_playwright_browser.py (Python)

Code before:
            raise RuntimeError('Persistent browser can have only one context')

        launch_options = self._browser_launch_options | context_options

        if self._user_data_dir:
            user_data_dir = self._user_data_dir
            temp_dir = False
        else:
            user_data_dir = tempfile.mkdtemp(prefix='apify-playwright-firefox-taac-')
            temp_dir = True

        self._context = await self._browser_type.launch_persistent_context(
            user_data_dir=user_data_dir, **launch_options
        )

        if temp_dir:
            self._context.on('close', partial(shutil.rmtree, user_data_dir))

        return self._context

    async def close(self) -> None:
        """Close browser by closing its context."""
        if self._context:
            await self._context.close()
            self._context = None
        self._is_connected = False


Review comment (bug):
I am not really sure how this is going to work with [Fingerprints](https://github.com/apify/crawlee-python/blob/master/src/crawlee/browsers/_playwright_browser_controller.py#L211C17-L211C39)

Since in order to have fingerprints we inject them through `browserforge` and that is already wrapping [browser.new_context](https://github.com/daijro/browserforge/blob/main/browserforge/injectors/playwright/injector.py#L29) call.

Seems to me that this wrapper replaces that wrapper and no fingerprints will be injected.

Maybe I am wrong, but I would like to see at least one test that checks that both `fingerprints` and `persistent context` works together 

Code after:

    @property
    def browser_type(self) -> BrowserType:
        return self._browser_type

    @property
    def contexts(self) -> list[BrowserContext]:
        return [self._context] if self._context else []

    def is_connected(self) -> bool:
        return self._is_connected

    async def new_context(self, **context_options: Any) -> BrowserContext:
        """Create persistent context instead of regular one. Merge launch options with context options."""
        if self._context:
            raise RuntimeError('Persistent browser can have only one context')

        launch_options = self._browser_launch_options | context_options

        if self._user_data_dir:
            user_data_dir = self._user_data_dir
        else:
            user_data_dir = tempfile.mkdtemp(prefix=self._TMP_DIR_PREFIX)
            self._temp_dir = user_data_dir

        self._context = await self._browser_type.launch_persistent_context(
            user_data_dir=user_data_dir, **launch_options
        )

        if self._temp_dir:
            self._context.on('close', self._delete_temp_dir)

        return self._context

    async def _delete_temp_dir(self, _: BrowserContext) -> None:
        if self._temp_dir:
            await asyncio.to_thread(shutil.rmtree, self._temp_dir)

    @override
    async def close(self, **kwargs: Any) -> None:
        """Close browser by closing its context."""
        if self._context:
            await self._context.close()
            self._context = None
        self._is_connected = False

    @property
    @override
    def version(self) -> str:
        raise NotImplementedError('Persistent browser does not support version.')