Assets¶
Files under app/assets/ are bundled into the iOS app, the Android APK,
and the browser preview, and are addressed from Python by relative path:
import pythonnative as pn
logo = pn.asset("images/logo.png") # Asset("images/logo.png")
pn.Image(source=logo, style=pn.style(width=120, height=40))
config = pn.asset("data/config.json").read_text()
The Assets guide covers density variants, fonts, icons, and how the folder is bundled and synced.
Bundled assets: images, fonts, and other files shipped inside the app.
Everything under app/assets/ is copied into the native application
by pn build and synced to connected devices by pn start. Code
refers to those files with asset:
import pythonnative as pn
logo = pn.asset("images/logo.png")
pn.Image(source=logo, style=pn.style(width=120, height=40))
An Asset is a small frozen value. On the wire it
becomes the URI asset://images/logo.png; the native runtimes resolve
that against the dev overlay (when connected to pn start) and then
the bundle, and pick the density variant (logo@2x.png, logo@3x.png)
closest to the device scale. Python never needs to know the device's
pixel ratio or where the bundle lives.
Fonts work the same way: drop .ttf or .otf files into
app/assets/fonts/ and reference them by family name with
font_family. The family, weight, and style are read from the font
files themselves (see read_font_face),
so no mapping file is needed.
The build tool and the dev server describe an asset directory with an
AssetManifest
(see scan), which lists every file, groups
density variants by base name, and carries the parsed font faces. The
native runtimes read the manifest that ships in the bundle and receive a
fresh one over the bridge whenever the dev overlay changes.
Modules:
| Name | Description |
|---|---|
fonts |
Read the identifying tables of TrueType and OpenType font files. |
Classes:
| Name | Description |
|---|---|
FontFace |
One face (a family at one weight and style) provided by a font file. |
FontParseError |
The file isn't a TrueType or OpenType font this reader understands. |
Asset |
A file under |
AssetManifest |
Everything a runtime needs to know about one assets directory. |
Functions:
| Name | Description |
|---|---|
read_font_face |
Return the |
weight_from_name |
Infer a CSS weight from a style name like |
normalize_path |
Return |
is_asset_uri |
Whether |
split_variant |
Split |
choose_variant |
Pick the variant path best suited to a device |
asset |
Reference a file bundled under |
scan |
Describe the assets directory at |
write_manifest |
Scan |
assets_roots |
Directories that may hold |
font_faces |
The font faces bundled with the app. |
generation |
A counter bumped whenever synced assets change (for caches). |
bump_generation |
Invalidate asset caches after a sync; returns the new generation. |
configure_native |
Tell the native runtime about the dev overlay's assets. |
Attributes:
| Name | Type | Description |
|---|---|---|
ASSETS_DIR |
Directory under |
|
ASSET_SCHEME |
URI scheme the native runtimes resolve against the bundled assets. |
|
MANIFEST_NAME |
File name of the manifest the builder writes next to staged assets. |
ASSET_SCHEME
module-attribute
¶
URI scheme the native runtimes resolve against the bundled assets.
MANIFEST_NAME
module-attribute
¶
File name of the manifest the builder writes next to staged assets.
FONT_SUFFIXES
module-attribute
¶
File suffixes scanned for font faces.
FontFace
dataclass
¶
One face (a family at one weight and style) provided by a font file.
Attributes:
| Name | Type | Description |
|---|---|---|
family |
str
|
The family name apps pass as |
weight |
int
|
CSS-style weight from 100 to 900. |
italic |
bool
|
Whether the face is italic or oblique. |
postscript_name |
str
|
The PostScript name, which is what |
path |
str
|
The file path relative to |
FontParseError
¶
Bases: ValueError
The file isn't a TrueType or OpenType font this reader understands.
Asset
dataclass
¶
Asset(path: str)
A file under app/assets/, addressed by its relative path.
Build one with asset. Assets compare and hash
by path, so they're safe as dict keys, in StyleSheet values, and
as use_effect dependencies.
Attributes:
| Name | Type | Description |
|---|---|---|
path |
str
|
The normalized path relative to |
Methods:
| Name | Description |
|---|---|
read_bytes |
Return the file's contents. |
read_text |
Return the file's contents decoded as text. |
exists |
Whether some copy of the asset (overlay, bundle, or APK) exists. |
read_bytes
¶
read_bytes() -> bytes
Return the file's contents.
Looks in the dev overlay and the bundled app/assets/ directory
first; on Android, where bundled assets live inside the APK, the
native Assets module reads them.
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If no copy of the asset can be found. |
AssetManifest
dataclass
¶
AssetManifest(
files: Tuple[str, ...] = (),
variants: Dict[str, Dict[str, str]] = dict(),
fonts: Tuple[FontFace, ...] = (),
)
Everything a runtime needs to know about one assets directory.
Attributes:
| Name | Type | Description |
|---|---|---|
files |
Tuple[str, ...]
|
Every asset path, sorted. |
variants |
Dict[str, Dict[str, str]]
|
|
fonts |
Tuple[FontFace, ...]
|
The font faces found under |
Methods:
| Name | Description |
|---|---|
resolve |
Return the variant of |
faces |
Every face of |
to_dict |
A JSON-ready form (what the builder writes and the bridge sends). |
from_dict |
Rebuild a manifest written by |
dumps |
The manifest as pretty JSON. |
resolve
¶
Return the variant of path that best matches scale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
An asset path or |
required |
scale
|
float
|
The device pixel ratio. |
1.0
|
Returns:
| Type | Description |
|---|---|
Optional[str]
|
The path to load, or |
to_dict
¶
A JSON-ready form (what the builder writes and the bridge sends).
read_font_face
¶
Return the FontFace described by a font file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Union[str, Path, bytes]
|
A file path or the file's bytes. |
required |
path
|
str
|
The asset-relative path recorded on the result. Defaults to
the file name when |
''
|
Raises:
| Type | Description |
|---|---|
FontParseError
|
If the data isn't a supported font. |
weight_from_name
¶
Infer a CSS weight from a style name like "Semi Bold Italic".
Longer words are checked first so "extrabold" doesn't match
"bold". Returns None when nothing matches.
normalize_path
¶
Return path as a clean, asset-relative POSIX path.
Accepts "images/logo.png", "./images/logo.png", an
asset:// URI, or Windows separators; rejects absolute paths,
.. segments, and empty input.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the path can't name a file under |
split_variant
¶
Split "images/logo@2x.png" into ("images/logo.png", 2.0).
Paths without a density suffix return scale 1.0 and themselves.
choose_variant
¶
Pick the variant path best suited to a device scale.
Preference order: an exact match, the nearest variant above scale
(so images are downsampled rather than upsampled), then the largest
available. Returns None when variants is empty.
asset
¶
Reference a file bundled under app/assets/.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
Path relative to |
required |
Returns:
| Type | Description |
|---|---|
Asset
|
An |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
scan
¶
scan(
root: Union[str, Path], *, log: Any = None
) -> AssetManifest
Describe the assets directory at root.
Hidden files, editor swap files, and __pycache__ are skipped. Font
files that can't be parsed are reported through log (when given)
and omitted, so one broken font never breaks a build.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Union[str, Path]
|
The |
required |
log
|
Any
|
Optional callable that receives warning strings. |
None
|
write_manifest
¶
write_manifest(
root: Union[str, Path], *, log: Any = None
) -> AssetManifest
Scan root and write pn_assets.json inside it.
The build tool calls this on the staged copy of app/assets/ so
the native runtimes can resolve variants and register fonts without
listing the bundle at startup. Returns the manifest that was written.
A missing root is created so the bundle always carries a manifest.
assets_roots
¶
Directories that may hold app/assets/ files, most specific first.
The dev overlay (when pn start is connected) comes before the
bundled or checked-out app/ package. On Android the bundled copy
isn't a directory at all (it lives in the APK), so only the overlay is
listed there; Asset.read_bytes falls
back to the native Assets module.
font_faces
¶
The font faces bundled with the app.
Readable roots (the dev overlay, a checkout, the iOS bundle) are
scanned directly. On Android the bundled app/assets/ lives inside
the APK rather than on disk, so its faces come from the manifest the
build wrote, read through the native Assets module.
bump_generation
¶
bump_generation() -> int
Invalidate asset caches after a sync; returns the new generation.
configure_native
¶
Tell the native runtime about the dev overlay's assets.
Called by the dev client after a sync and by bootstrap.start in
debug builds. It scans <overlay>/app/assets/ and sends the
resulting manifest to the native Assets module, which then
resolves asset:// URIs against the overlay before the bundle and
registers any overlay fonts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
paths
|
Optional[Iterable[str]]
|
The synced paths ( |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
|
Fonts¶
Bundled .ttf and .otf files are parsed at build time so font_family
can refer to them by family name.
Read the identifying tables of TrueType and OpenType font files.
The build tool and the dev server need to know, for every file under
app/assets/fonts/, which family it belongs to and which weight and
style it provides, so font_family="Poppins", font_weight=700 can be
matched to Poppins-Bold.ttf on every platform without a hand-written
mapping. That information lives inside the font: the name table
carries the family and PostScript names and the OS/2 table carries
the weight class and the italic flag.
This module reads exactly those tables (plus head as a fallback for
the style bits) with :mod:struct; it never parses glyph data. It
handles .ttf, .otf (CFF outlines), and the first face of a
.ttc collection.
Classes:
| Name | Description |
|---|---|
FontParseError |
The file isn't a TrueType or OpenType font this reader understands. |
FontFace |
One face (a family at one weight and style) provided by a font file. |
Functions:
| Name | Description |
|---|---|
weight_from_name |
Infer a CSS weight from a style name like |
read_font_face |
Return the |
FontParseError
¶
Bases: ValueError
The file isn't a TrueType or OpenType font this reader understands.
FontFace
dataclass
¶
One face (a family at one weight and style) provided by a font file.
Attributes:
| Name | Type | Description |
|---|---|---|
family |
str
|
The family name apps pass as |
weight |
int
|
CSS-style weight from 100 to 900. |
italic |
bool
|
Whether the face is italic or oblique. |
postscript_name |
str
|
The PostScript name, which is what |
path |
str
|
The file path relative to |
weight_from_name
¶
Infer a CSS weight from a style name like "Semi Bold Italic".
Longer words are checked first so "extrabold" doesn't match
"bold". Returns None when nothing matches.
read_font_face
¶
Return the FontFace described by a font file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Union[str, Path, bytes]
|
A file path or the file's bytes. |
required |
path
|
str
|
The asset-relative path recorded on the result. Defaults to
the file name when |
''
|
Raises:
| Type | Description |
|---|---|
FontParseError
|
If the data isn't a supported font. |