plesty.server.services.updates
Updating the application from inside it: Help ▸ Check for updates… (#29).
Two installs can update themselves, the two the installers make:
Windows — a virtual environment of its own,
%LOCALAPPDATA%\PLESTY Bench\app, updated withpip installinto it.macOS and Linux — a
uv toolenvironment (it carries uv’suv-receipt.toml), updated withuv tool install --force.
Neither update runs inside the console. On Windows it cannot: the console is
that environment’s interpreter, Windows will not replace a file a running
process holds, and pip fails on the first one it meets. Elsewhere it could,
but the console would go on running the old code until restarted. So the
console hands the update to a helper outside the environment —
assets/update.ps1 or assets/update.sh, copied out first — which waits
for the console to exit and installs. Beside it the console starts the update
window, assets/update_window.py, on the interpreter the environment was
made from: it shows the install as it runs and, when it has finished, offers
to open the new console. Where no window can be shown, the helper starts the
console again itself.
The result is left in two files the console reads on its next start, so a failure is reported even if the window was closed early, and is kept as the last update, which Help ▸ About shows.
A console run from a source checkout is not an install, and is told so.
Attributes
Exceptions
The newest version could not be read, or the update could not be started. |
Classes
An install this console can update. |
|
What the helper left of the last update, read once on the next start. |
|
The last update that finished, as Help ▸ About shows it. |
Functions
|
The version of the console that is running; |
|
The newest release of the console on PyPI. |
|
|
|
Whether release candidate is later than current. |
|
|
|
|
|
The Windows installer's directory, |
|
Where the update helper and its log go on this platform. |
|
The install this console runs from, when it is one that can update itself. |
|
How this console was installed, and where, in a line for Help ▸ About. |
|
|
|
Whether platform — this one when |
|
Where the helper writes its log; its |
|
The console's launcher once the update is in: what Open PLESTY Bench starts. |
|
The interpreter to show the update window with, or |
|
Hand the update to the helper, which runs once this console has exited. |
|
|
|
|
|
What the last update left, once: its marker files are removed as they are read. |
|
Keep result, with what was asked for, as the last update. |
|
The last update that finished, or |
|
The release newer than installed to tell of when the console starts, or |
Module Contents
- plesty.server.services.updates.PACKAGE = 'plesty-server'
- plesty.server.services.updates.REQUIREMENT = 'plesty-server[gui]'
- plesty.server.services.updates.PYPI_URL = 'https://pypi.org/pypi/plesty-server/json'
- plesty.server.services.updates.INSTALL_DIR = 'PLESTY Bench'
- plesty.server.services.updates.UV_RECEIPT = 'uv-receipt.toml'
- plesty.server.services.updates.PENDING = 'update.json'
- plesty.server.services.updates.RECORD = 'last-update.json'
- plesty.server.services.updates.CHECKOUT_NOTE = 'This copy runs from a source checkout, not from an install, so it cannot update itself. Update...
- exception plesty.server.services.updates.UpdateError
Bases:
RuntimeErrorThe newest version could not be read, or the update could not be started.
Initialize self. See help(type(self)) for accurate signature.
- class plesty.server.services.updates.Install
An install this console can update.
- Variables:
kind –
windows(the installer’s environment) oruv-tool.env – Its environment.
state – Where the helper and its log go — outside env.
- kind: str
- env: pathlib.Path
- state: pathlib.Path
- class plesty.server.services.updates.LastUpdate
What the helper left of the last update, read once on the next start.
- Variables:
ok – Whether the install succeeded.
reason – Why it failed, in one line; empty on success.
log – The helper’s log, for the details.
shown – Whether the update window already showed the operator how it went.
- ok: bool
- reason: str
- log: pathlib.Path
- shown: bool = False
- class plesty.server.services.updates.UpdateRecord
The last update that finished, as Help ▸ About shows it.
- Variables:
from_version – The version that was installed before it;
""if unknown.to_version – The version it installed, or tried to.
asked – When it was asked for, ISO 8601;
""if unknown.finished – When the helper finished, ISO 8601.
ok – Whether the install succeeded.
reason – Why it failed; empty on success.
log – The helper’s log.
- from_version: str
- to_version: str
- asked: str
- finished: str
- ok: bool
- reason: str
- log: str
- plesty.server.services.updates.installed_version() str
The version of the console that is running;
"dev"for a checkout never installed.- Return type:
str
- plesty.server.services.updates.latest_version(fetch: collections.abc.Callable[[str], bytes] | None = None) str
The newest release of the console on PyPI.
- Parameters:
fetch (collections.abc.Callable[[str], bytes] | None) – Reads a URL; a 10-second request by default.
- Returns:
Its version.
- Raises:
UpdateError – When PyPI cannot be reached or does not answer as expected.
- Return type:
str
- plesty.server.services.updates._fetch(url: str) bytes
- Parameters:
url (str)
- Return type:
bytes
- plesty.server.services.updates.is_newer(candidate: str, current: str) bool
Whether release candidate is later than current.
Compared by their release numbers, which is all a PyPI release carries. A current that is not a plain release —
dev, or a checkout’s0.5.0.dev3+abc— is older than the release it leads to.- Parameters:
candidate (str)
current (str)
- Return type:
bool
- plesty.server.services.updates._release(version: str) tuple[int, Ellipsis] | None
- Parameters:
version (str)
- Return type:
tuple[int, Ellipsis] | None
- plesty.server.services.updates._is_prerelease(version: str) bool
- Parameters:
version (str)
- Return type:
bool
- plesty.server.services.updates.install_dir(environ: collections.abc.Mapping[str, str] | None = None) pathlib.Path | None
The Windows installer’s directory,
%LOCALAPPDATA%\PLESTY Bench, if any.- Parameters:
environ (collections.abc.Mapping[str, str] | None)
- Return type:
pathlib.Path | None
- plesty.server.services.updates.state_dir(environ: collections.abc.Mapping[str, str] | None = None, platform: str | None = None) pathlib.Path | None
Where the update helper and its log go on this platform.
Windows: beside the install log (
install_dir()). Elsewhere: the user’s state directory,$XDG_STATE_HOME/plesty-benchor~/.local/state/plesty-bench— never inside the environment being replaced.- Parameters:
environ (collections.abc.Mapping[str, str] | None)
platform (str | None)
- Return type:
pathlib.Path | None
- plesty.server.services.updates.current_install(prefix: str | None = None, environ: collections.abc.Mapping[str, str] | None = None, platform: str | None = None) Install | None
The install this console runs from, when it is one that can update itself.
- Parameters:
prefix (str | None) – The running interpreter’s environment;
sys.prefixby default.environ (collections.abc.Mapping[str, str] | None) – The environment variables; this process’s by default.
platform (str | None) – The platform; this one by default.
- Returns:
The Windows installer’s environment,
%LOCALAPPDATA%\PLESTY Bench\app; auv toolenvironment (one holdingUV_RECEIPT); orNonefor anything else — a source checkout, above all.- Return type:
Install | None
- plesty.server.services.updates.describe_install(install: Install | None, prefix: str | None = None) str
How this console was installed, and where, in a line for Help ▸ About.
- Parameters:
install (Install | None)
prefix (str | None)
- Return type:
str
- plesty.server.services.updates._same_path(one: pathlib.Path, other: pathlib.Path) bool
- Parameters:
one (pathlib.Path)
other (pathlib.Path)
- Return type:
bool
- plesty.server.services.updates._on_windows(platform: str | None) bool
Whether platform — this one when
None— is Windows, ashostdecides.- Parameters:
platform (str | None)
- Return type:
bool
- plesty.server.services.updates.update_log(base: pathlib.Path) pathlib.Path
Where the helper writes its log; its
.exitand.reasonlie beside it.- Parameters:
base (pathlib.Path)
- Return type:
pathlib.Path
- plesty.server.services.updates.launcher(install: Install) pathlib.Path
The console’s launcher once the update is in: what Open PLESTY Bench starts.
Windows: the copy the installer put in
~\.local\bin, which the shortcuts start, else the environment’s own. Auv tool: the environment’s, whichuv tool install --forceputs back in place.- Parameters:
install (Install)
- Return type:
pathlib.Path
- plesty.server.services.updates.window_python() pathlib.Path | None
The interpreter to show the update window with, or
Nonewhen it has no Tk.The one the environment was made from: it lies outside the environment the update replaces. Asked whether it can import
tkinterfirst, so an interpreter without it leaves the helper to start the console again.- Return type:
pathlib.Path | None
- plesty.server.services.updates.start_update(version: str, install: Install, pid: int | None = None, spawn: collections.abc.Callable[Ellipsis, Any] | None = None, uv: collections.abc.Callable[[], str] | None = None, python: collections.abc.Callable[[], pathlib.Path | None] | None = None, installed: str | None = None, theme: collections.abc.Mapping[str, Any] | None = None) pathlib.Path
Hand the update to the helper, which runs once this console has exited.
- Parameters:
version (str) – The release to install.
install (Install) – The install to update (
current_install()).pid (int | None) – The console’s process, which the helper waits out; this one by default.
spawn (collections.abc.Callable[Ellipsis, Any] | None) – Starts the helper and the window;
subprocess.Popenby default.uv (collections.abc.Callable[[], str] | None) – Finds
uvfor auv toolinstall; the bench’s own search by default.python (collections.abc.Callable[[], pathlib.Path | None] | None) – Finds the interpreter for the update window,
Nonefor none;window_python()by default.installed (str | None) – The version being replaced, for the record; this one by default.
theme (collections.abc.Mapping[str, Any] | None) – The console’s palette and fonts, for the window to be drawn in (
tokens,ui_font,mono_font,mark); its own copy of the palette whenNone.
- Returns:
The helper’s log.
- Raises:
UpdateError – When the helper cannot be prepared or started.
- Return type:
pathlib.Path
- plesty.server.services.updates._find_uv() str
- Return type:
str
- plesty.server.services.updates._beside(log: pathlib.Path, suffix: str) pathlib.Path
- Parameters:
log (pathlib.Path)
suffix (str)
- Return type:
pathlib.Path
- plesty.server.services.updates.last_update(base: pathlib.Path | None) LastUpdate | None
What the last update left, once: its marker files are removed as they are read.
What it left is kept as the last update (
update_record()) for Help ▸ About, which shows it for as long as no newer update finishes.- Parameters:
base (pathlib.Path | None) – The helper’s directory (
state_dir()).- Returns:
The result, or
Nonewhen no update has finished since the last start.- Return type:
LastUpdate | None
- plesty.server.services.updates._keep(base: pathlib.Path, result: LastUpdate, finished: datetime.datetime) None
Keep result, with what was asked for, as the last update.
- Parameters:
base (pathlib.Path)
result (LastUpdate)
finished (datetime.datetime)
- Return type:
None
- plesty.server.services.updates.update_record(base: pathlib.Path | None) UpdateRecord | None
The last update that finished, or
Nonewhen there has been none to tell of.- Parameters:
base (pathlib.Path | None) – The helper’s directory (
state_dir()).- Return type:
UpdateRecord | None
- plesty.server.services.updates.STARTUP_CHECK = 'update-check.json'
- plesty.server.services.updates.CHECK_EVERY
- plesty.server.services.updates.startup_update(home: pathlib.Path, installed: str, now: datetime.datetime | None = None, fetch: collections.abc.Callable[[str], bytes] | None = None) str | None
The release newer than installed to tell of when the console starts, or
None.PyPI is asked at most once per
CHECK_EVERY; within it, the release the last check heard of is used again, so the line stays on every start until the bench is updated. Only a check that answered is written down: one with no network is tried again on the next start. Never raises — a bench with no network says nothing.- Parameters:
home (pathlib.Path) – The bench home, where
STARTUP_CHECKis kept.installed (str) – The version running.
now (datetime.datetime | None) – The time; injected by tests.
fetch (collections.abc.Callable[[str], bytes] | None) – Reads a URL; injected by tests.
- Return type:
str | None