Over-the-air (OTA) updates¶
Nyora delivers its JavaScript parser bundle and source catalog over the air,
so you get new sources and parser fixes without upgrading the nyora package.
nyora.ota.OtaManager fetches a signed manifest from the public OTA feed,
verifies each artifact by SHA-256, and caches the bundle, catalog, and manifest
atomically in a per-user directory. When nothing is cached, reads transparently
fall back to the assets shipped inside the package, so the SDK works fully
offline on first run.
The feed and artifacts¶
The OTA feed lives at:
https://Hasan72341.github.io/nyora-ota-parsers
The manager works with three artifacts:
Artifact |
Filename |
Purpose |
|---|---|---|
Manifest |
|
Version number plus per-artifact |
Parser bundle |
|
The JavaScript parser bundle run by the runtime. |
Source catalog |
|
The catalog of available sources. |
The manifest contains an integer version and bundle/sources entries, each
with a url and an optional sha256 checksum.
Cache location¶
Cached artifacts live under the per-user cache directory (resolved by
platformdirs):
<user cache dir>/nyora/ota/
manifest.json
parsers.bundle.js
sources.json
Read OtaManager().cache_dir to get the exact path on your platform. You can
override it by constructing OtaManager(cache_dir=Path(...)).
Offline fallback¶
If a cached artifact is missing, the manager reads the copy bundled inside the
package (nyora.assets). This is why a fresh install works with no network:
the shipped bundle and catalog are used until you pull an update.
From the default client¶
The simplest path is through nyora.Nyora, which owns an OtaManager as
client.ota and adds two convenience methods.
Check without applying¶
from nyora import Nyora
with Nyora() as client:
available, installed, latest = client.check_update()
print(available, installed, latest)
check_update() returns (available, installed_version, latest_version).
Versions are None when unknown (nothing installed yet, or the manifest could
not be reached). Network and manifest errors are treated as “no update
available” rather than raising, so it is safe to call opportunistically.
Apply an update¶
from nyora import Nyora
with Nyora() as client:
result = client.update() # or client.update(force=True)
print("updated:", result.updated)
print("version:", result.version)
client.update(*, force=False) downloads and verifies the latest artifacts,
writes them to the cache, and reloads the embedded runtime so the new
parsers are live in the same process. With force=True it re-downloads even when
already current. It returns an OtaUpdateResult.
Using OtaManager directly¶
from nyora.ota import OtaManager
ota = OtaManager(timeout=30.0)
print("cache dir:", ota.cache_dir)
available, installed, latest = ota.is_update_available()
if available:
result = ota.update()
print("updated to", result.version, "at", result.bundle_path)
Note
OtaManager.update() only writes the cache — it does not reload any running
runtime. If you call it on a bare manager while a Nyora client is live, call
client._runtime.reload() or just use client.update() instead, which does
both.
OtaManager methods¶
cache_dir(property) — the directory where artifacts are cached.fetch_manifest() -> dict— download and parse the remote manifest. Raisesnyora.NyoraErrorif it cannot be fetched or is not a JSON object.installed_version() -> int | None— the version currently cached, orNone.is_update_available() -> tuple[bool, int | None, int | None]— returns(available, installed, latest); never raises on network/manifest errors.update(*, force=False) -> OtaUpdateResult— download, SHA-256-verify, and atomically write the artifacts. Raisesnyora.NyoraErroron fetch failure or a checksum mismatch.read_bundle_text() -> str— the parser bundle text (cached, else bundled fallback).read_sources_text() -> str— the source-catalog JSON (cached, else bundled fallback).
OtaUpdateResult¶
The dataclass returned by update():
Field |
Type |
Meaning |
|---|---|---|
|
|
|
|
|
The manifest version now installed in the cache. |
|
|
Path to the cached parser bundle. |
|
|
Path to the cached source catalog. |
Integrity and atomicity¶
SHA-256 verification. When the manifest entry includes a
sha256, the downloaded bytes are hashed and compared; a mismatch raisesnyora.NyoraErrorand nothing is written.Atomic writes. Each artifact is written to a temp file in the cache directory and then
os.replaced into place, so a cache file is never left half-written.No-op when current. Without
force, if the installed version is at least the latest and both cached files exist,update()returnsOtaUpdateResult(updated=False, ...)without downloading.
From the CLI¶
The nyora-cli update command runs the same flow as Nyora().update(). See the
CLI docs for its flags and output. The helper client also exposes the helper’s
own OTA status via client.system.ota_status() and client.system.ota_check()
(see the library guide); those query the helper’s feed, not
this in-process manager.