[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/pythonnative/pythonnative/main/src/pythonnative/bootstrap.py [Back]  [Original]

"""Entry point the native app templates run right after Python starts.

Both templates execute one line of Python once the interpreter is up:

```python
import pythonnative.bootstrap; pythonnative.bootstrap.start()
```

[`start`][pythonnative.bootstrap.start] connects the two halves of the
bridge (installing the native -> Python callback on iOS), verifies the
protocol version, routes ``print()`` to the console on iOS, warms the
asyncio runtime, and, in debug builds, starts the dev client that syncs
sources from ``pn start``. From then on the native runtime drives
everything through ``callback("host", ...)``; see ``docs/concepts/bridge.md``.
"""

from __future__ import annotations

import os
import sys
import traceback
from typing import Any, Dict

__all__ = ["start", "status"]

_started: Dict[str, Any] = {}


def start(dev: bool = False, strict: bool = False) -> Dict[str, Any]:
    """Connect the bridge and prepare the runtime.

    Args:
        dev: Enable dev mode (RedBox, validation warnings, the dev
            client). Debug templates pass ``True``.
        strict: Re-raise the failure after recording it. The templates
            pass ``True`` so a broken bridge surfaces as a bootstrap
            error screen with the full traceback.

    Returns:
        A status dict (``{"protocol": 2, "platform": "ios"}``) that the
        template logs. Unless ``strict`` is set this never raises:
        failures are printed and reported in the dict under
        ``"error"``.
    """
    global _started
    if _started and "error" not in _started:
        return dict(_started)
    status_: Dict[str, Any] = {"platform": None, "protocol": None}
    try:
        from .utils import IS_ANDROID, IS_IOS

        status_["platform"] = "ios" if IS_IOS else "android" if IS_ANDROID else "off-device"
        if IS_IOS:
            try:
                from . import _ios_log

                _ios_log.install()
            except Exception:
                pass
        from .runtime import start as start_runtime

        start_runtime()
        from .sdk.schema import load_bundled_contracts

        load_bundled_contracts()
        from . import bridge

        status_["protocol"] = bridge.handshake()
        dev_mode = bool(dev or os.environ.get("PN_DEV") in ("1", "true"))
        if dev_mode:
            from . import diagnostics

            diagnostics.set_dev_mode(True)
        # Import the view backend eagerly: on a slow device the first
        # commit shouldn't also pay for importing the reconciler.
        from .native_views import get_backend

        get_backend()
        if dev_mode:
            # Debug builds are dev clients: connect to `pn start` when
            # the build (or a remembered connection) names a server.
            # Release bundles omit this module; they never pass dev=True.
            from . import devclient

            client = devclient.start_if_configured()
            status_["dev_server"] = client.server_label if client is not None else None
            # An overlay from the last session may already hold assets the
            # bundle doesn't; point the native resolver at it right away.
            from .assets import configure_native

            configure_native()
    except Exception as exc:
        status_["error"] = f"{type(exc).__name__}: {exc}"
        print(f"[pn.bootstrap] start failed: {exc!r}", file=sys.stderr)
        traceback.print_exc()
        _started = status_
        if strict:
            raise
        return dict(status_)
    _started = status_
    return dict(status_)


def status() -> Dict[str, Any]:
    """Return the result of the last [`start`][pythonnative.bootstrap.start] (empty before it ran)."""
    return dict(_started)

Web Proxy Viewer  |  New URL  |  Original Page