bacommon.workspace package

Functionality related to ballistica.net workspaces.

Submodules

bacommon.workspace.assetsv1 module

Public types for assets-v1 workspaces.

While this module is currently only used server-side, its source code can be useful as reference when setting workspace config data by hand or for use in client-side workspace modification tools. There may be advanced settings that are not accessible through the UI/etc.

class bacommon.workspace.assetsv1.AssetsV1AprefFile[source]

Bases: IOMultiType[AssetsV1AprefFileTypeID]

Top level class for our multitype.

An <name>.apref source in an assets_v1 workspace is an asset-package reference: a pin to a published asset-package version. String briefs can then reference the pinned package’s translations via cross-package term refs ({@<apref-logical-path>:<entry-path>}).

classmethod get_type(type_id: AssetsV1AprefFileTypeID) type[AssetsV1AprefFile][source]

Return the subclass for each of our type-ids.

classmethod get_type_id() AssetsV1AprefFileTypeID[source]

Return the type-id for this subclass.

classmethod get_type_id_storage_name() str[source]

Return the key used to store type id in serialized data.

The default is a short obscure value so that it is unlikely to conflict with members of individual type attrs, but in some cases one might prefer to serialize it to something simpler like ‘type’ by overriding this call. One just needs to make sure that no encompassed types serialize anything to that same name themself (dataclassio will error if they do).

class bacommon.workspace.assetsv1.AssetsV1AprefFileTypeID(*values)[source]

Bases: Enum

Type ID for each of our subclasses.

V1 = 'v1'
class bacommon.workspace.assetsv1.AssetsV1AprefFileV1(apverid: str)[source]

Bases: AssetsV1AprefFile

Our initial version of asset-package-ref file data.

apverid: str

The pinned asset-package-version id (<account>.<package>.<version-segment>). Always a concrete version — including on the dev track (a specific devN segment, never the bare dev pseudo-id); pins only move via the explicit update/switch-track actions in the workspace UI.

classmethod get_type_id() AssetsV1AprefFileTypeID[source]

Return the type-id for this subclass.

class bacommon.workspace.assetsv1.AssetsV1GlobalVals(base_assets: str | None = None, base_assets_filter: str = '', docs: str = '', dev_team: str | None = None, asset_package_name: str | None = None, conventions: ConventionsMode = ConventionsMode.RELAXED)[source]

Bases: object

Global values for an assets_v1 workspace.

asset_package_name: str | None = None

The asset-package name this workspace publishes under. None means it is derived from the workspace’s display name (see derive_asset_package_name()); set explicitly to decouple the published name from the display name (e.g. to keep a package lineage across a workspace rename, or to have a new workspace take over publishing an existing package name).

base_assets: str | None = None
base_assets_filter: str = ''
conventions: ConventionsMode = 'relaxed'

Conventions-check enforcement level (see ConventionsMode). First-party workspaces set strict (see the asset-packages design doc). Set by hand in workspace.json – deliberately not exposed in the UI. Unknown stored values fall back to relaxed so older servers never over-enforce.

dev_team: str | None = None

Dev-team id granting resolve access to this workspace’s dev/test asset-package versions. None (unset) means owner-only access — matching the semantics of the asset-package doc’s dev_team_id (see AssetPackage.account_has_access).

docs: str = ''

Optional free-form workspace documentation, appended to the generated wrapper module’s docstring (after the auto-generated summary line). Empty string means none.

class bacommon.workspace.assetsv1.AssetsV1PathVals[source]

Bases: IOMultiType[AssetsV1PathValsTypeID]

Top level class for path vals classes.

classmethod get_type(type_id: AssetsV1PathValsTypeID) type[AssetsV1PathVals][source]

Return a specific subclass given a type-id.

Should be overridden by child classes. Generally, users of the class should call get_type_cached() instead of this, as it is more efficient.

classmethod get_type_id() AssetsV1PathValsTypeID[source]

Return the type-id for this subclass.

classmethod get_type_id_storage_name() str[source]

Return the key used to store type id in serialized data.

The default is a short obscure value so that it is unlikely to conflict with members of individual type attrs, but in some cases one might prefer to serialize it to something simpler like ‘type’ by overriding this call. One just needs to make sure that no encompassed types serialize anything to that same name themself (dataclassio will error if they do).

class bacommon.workspace.assetsv1.AssetsV1PathValsAudioV1(audio_role: AudioRole = AudioRole.DEFAULT, audio_quality: AudioQuality = AudioQuality.DEFAULT, docs: str = '')[source]

Bases: AssetsV1PathVals

Path-specific values for an audio source in an assets_v1 workspace.

The per-sound authoring knobs (AudioRole, AudioQuality) are module-level types in this module.

audio_quality: AudioQuality = 'default'
audio_role: AudioRole = 'default'
docs: str = ''

Optional free-form documentation for this asset, surfaced as a comment above the asset in generated wrapper modules (and in the Sphinx docs). Empty string means no docs.

classmethod get_type_id() AssetsV1PathValsTypeID[source]

Return the type-id for this subclass.

class bacommon.workspace.assetsv1.AssetsV1PathValsCubeMapV1(docs: str = '')[source]

Bases: AssetsV1PathVals

Path-specific values for a cube map (.cubemap dir) in a workspace.

Cube maps are reflection textures with no Python API (decision #24), so they aren’t wrapper-visible. This currently carries only optional docs – stored for completeness/consistency with other asset kinds, but not yet consumed by anything (it’ll have a home if/when cube maps gain a Python surface). Keyed in workspace.json’s path dict by the .cubemap directory path.

docs: str = ''

Optional free-form documentation for this cube map. Stored but not yet surfaced anywhere (cube maps have no wrapper entry). Empty string means no docs.

classmethod get_type_id() AssetsV1PathValsTypeID[source]

Return the type-id for this subclass.

class bacommon.workspace.assetsv1.AssetsV1PathValsGroupV1(docs: str = '')[source]

Bases: AssetsV1PathVals

Path-specific values for a group (directory) in a workspace.

A group builds no asset of its own; this exists purely to carry optional docs (decision #28) that become the generated wrapper group class’s docstring. Keyed in workspace.json’s path dict by the directory path (e.g. textures or mydir/subdir).

docs: str = ''

Optional free-form documentation for this group, used as the generated wrapper group class’s docstring (a trailing “See source for the full asset list.” is always appended). Empty string means fall back to the auto-generated docstring.

classmethod get_type_id() AssetsV1PathValsTypeID[source]

Return the type-id for this subclass.

class bacommon.workspace.assetsv1.AssetsV1PathValsMeshV1(mesh_role: MeshRole = MeshRole.DEFAULT, docs: str = '')[source]

Bases: AssetsV1PathVals

Path-specific values for a mesh source in an assets_v1 workspace.

The per-mesh authoring knob (MeshRole) is a module-level type in this module.

docs: str = ''

Optional free-form documentation for this asset, surfaced as a comment above the asset in generated wrapper modules (and in the Sphinx docs). Empty string means no docs.

classmethod get_type_id() AssetsV1PathValsTypeID[source]

Return the type-id for this subclass.

mesh_role: MeshRole = 'default'
class bacommon.workspace.assetsv1.AssetsV1PathValsStrV1(up_to_date_state: str | None = None, wrap: WrapParams | None = None, deps: AssetsV1StrTermDeps | None = None, conv: AssetsV1StrConvCache | None = None)[source]

Bases: AssetsV1PathVals

Path-specific values for an assets_v1 workspace path.

conv: AssetsV1StrConvCache | None = None

Cached conventions findings (see AssetsV1StrConvCache). Absent until first computed; ignored (and lazily recomputed from the file) whenever its state no longer matches the entry’s current inputs – so write paths that don’t maintain it merely cost a read, never a wrong answer.

deps: AssetsV1StrTermDeps | None = None

Cached term-ref info (see AssetsV1StrTermDeps). Absent until first extracted; ignored (and lazily recomputed from the file) whenever its file_id no longer matches the entry’s current content – so write paths that don’t maintain it merely cost a read, never a wrong answer.

classmethod get_type_id() AssetsV1PathValsTypeID[source]

Return the type-id for this subclass.

up_to_date_state: str | None = None

Hash generated when all translations for this entry are complete. Used as a fast-out for checking whether updates are needed.

(Historical note: string author docs briefly lived here as a docs path-val to avoid restaling translations; they moved into the .bstr itself once docs began feeding the translation prompt, with the UI’s mark-translations-clean action as the no-regeneration-needed escape hatch.)

wrap: WrapParams | None = None

Optional definition-time line-wrapping hints (decision D-t in the language-string-context initiative): applied automatically at evaluation everywhere this string displays. Locale-invariant. Lives HERE (not in the .bstr) deliberately: the .bstr is by definition the translation input, so its content hash is the translation-staleness key, and display-side metadata like this must not restale translations (the same reasoning as the docs history above, in reverse – wrap does not feed the translation prompt).

class bacommon.workspace.assetsv1.AssetsV1PathValsTexV1(texture_quality: TextureQuality = TextureQuality.DEFAULT, texture_role: Role = Role.DEFAULT, astc_settings: AstcSettings = <factory>, bc7_settings: Bc7Settings = <factory>, docs: str = '', fallback_high_res: bool = False)[source]

Bases: AssetsV1PathVals

Path-specific values for an assets_v1 workspace path.

The per-texture quality knobs (TextureQuality, Role, AstcSettings, Bc7Settings) are module-level types in this module.

astc_settings: AstcSettings

Per-format encode settings, consulted only when texture_quality is CUSTOM. Fully defaulted so a texture never has to store them explicitly.

bc7_settings: Bc7Settings
docs: str = ''

Optional free-form documentation for this asset, surfaced as a comment above the asset in generated wrapper modules (and in the Sphinx docs). Empty string means no docs.

fallback_high_res: bool = False

Halve the fallback flavor’s level0 downsize divisor (2 instead of 4) so this asset’s fallback carries a higher-res top mip. For the rare asset whose fallback bytes get consumed directly rather than just serving as a universal render fallback – e.g. the engine cursor texture feeding OS hardware cursors, which wants a retina-res mip. Deliberately not exposed in the workspace web UI (it would be noise there); edit workspace.json directly for the odd asset that needs it.

classmethod get_type_id() AssetsV1PathValsTypeID[source]

Return the type-id for this subclass.

normalize() None[source]

Reset redundant/unused settings to defaults, in place.

A pure tidiness pass to run before storing: it never changes the resolved result, only drops dead data so store_default=False can strip it from workspace.json. Resolution consults the per-format settings only when the top-level texture_quality is CUSTOM, and a format’s explicit block_size/rdo only when that format’s own texture_quality is CUSTOM – so anything outside those paths is unused and gets cleared here.

texture_quality: TextureQuality = 'default'
texture_role: Role = 'default'
class bacommon.workspace.assetsv1.AssetsV1PathValsTypeID(*values)[source]

Bases: Enum

Types of vals we can store for paths.

AUDIO_V1 = 'audio_v1'
CUBE_MAP_V1 = 'cube_map_v1'
GROUP_V1 = 'group_v1'
MESH_V1 = 'mesh_v1'
STR_V1 = 'str_v1'
TEX_V1 = 'tex_v1'
class bacommon.workspace.assetsv1.AssetsV1StrConvCache(state: str, findings: list[str] = <factory>)[source]

Bases: object

Cached conventions findings for a .bstr, keyed to its inputs.

Per-entry conventions findings are a pure function of the .bstr file’s content plus the workspace’s cross-package term environment (its .apref files’ content-ids) plus the checks’ own version – all folded into state. Consumers (the conventions lint) use it to skip reading the file; on mismatch they fall back to reading and re-checking that one entry. Maintained automatically by the string save/translate paths; do not hand-edit (wrong findings with a matching state would be trusted).

findings: list[str]

The entry’s findings (human-readable one-liners), empty if clean.

state: str

Token pinning the inputs these findings were computed from (see class docs). Opaque; produced by the conventions module.

class bacommon.workspace.assetsv1.AssetsV1StrTermDeps(file_id: str, local: list[str] = <factory>, cross: list[str] = <factory>)[source]

Bases: object

Cached term-ref info for a .bstr, keyed to its content.

Term refs ({@term} / {@pkg:term} in the brief) are a pure function of the .bstr file’s content, which is pinned by its content-addressed file_id – so this record stays valid exactly as long as file_id matches the entry’s current file. Consumers (dep-aware staleness calcs) use it to skip reading the file; on mismatch they fall back to reading that one file. Maintained automatically by the string save/translate paths; do not hand-edit (a wrong local/cross list with a matching file_id would be trusted).

cross: list[str]

Cross-package ref targets (.apref paths, no extension).

file_id: str

Content-id of the .bstr file these refs were extracted from.

local: list[str]

Local term-ref targets (logical .bstr paths, no extension).

class bacommon.workspace.assetsv1.AssetsV1StringFile[source]

Bases: IOMultiType[AssetsV1StringFileTypeID]

Top level class for our multitype.

classmethod get_type(type_id: AssetsV1StringFileTypeID) type[AssetsV1StringFile][source]

Return the subclass for each of our type-ids.

classmethod get_type_id() AssetsV1StringFileTypeID[source]

Return the type-id for this subclass.

classmethod get_type_id_storage_name() str[source]

Return the key used to store type id in serialized data.

The default is a short obscure value so that it is unlikely to conflict with members of individual type attrs, but in some cases one might prefer to serialize it to something simpler like ‘type’ by overriding this call. One just needs to make sure that no encompassed types serialize anything to that same name themself (dataclassio will error if they do).

class bacommon.workspace.assetsv1.AssetsV1StringFileTypeID(*values)[source]

Bases: Enum

Type ID for each of our subclasses.

V1 = 'v1'
class bacommon.workspace.assetsv1.AssetsV1StringFileV1(input: str, input_modtime: datetime.datetime, style_preset: StylePreset = StylePreset.NONE, docs: str = '', fit_preset: FitPreset = FitPreset.NONE, outputs: dict[Locale, Output]=<factory>)[source]

Bases: AssetsV1StringFile

Our initial version of string file data.

class FitPreset(*values)[source]

Bases: Enum

Preset bounding translated-output size for UI space.

Mirrors StylePreset: a rough size budget passed to the translator (with UI context) so localized output respects the space available. Budgets are display-width in Latin characters – wide-glyph scripts (CJK) target roughly half the character count – and are aims, not hard caps (soft enforcement with generous slack; see char_budget).

CHARS_20 = 'chars_20'

Aim for ~20 characters - narrow buttons, tabs, column headings.

CHARS_40 = 'chars_40'

Aim for ~40 characters - standard buttons and labels.

CHARS_80 = 'chars_80'

Aim for ~80 characters / one concise line - transient messages, status lines, and the like.

NONE = 'none'

No size constraint (the default).

property char_budget: int | None

The preset’s rough character budget (None for NONE).

class Output(modtime: datetime, value: str | StringSelector = '')[source]

Bases: object

Represents a single localized output.

modtime: datetime

When this output was last changed.

value: str | StringSelector = ''

The localized output – a plain string, or a render-time StringSelector (plural/select) whose final form is chosen at display time. (A type-disjoint dataclassio union; selectors ride the wire as dicts.)

class StylePreset(*values)[source]

Bases: Enum

Preset for general styling in translated strings.

LOUD = 'loud'
NONE = 'none'
SOFT = 'soft'
TITLE = 'title'
docs: str = ''

Optional free-form usage docs describing where this string appears and how it is used. Feeds both the generated wrapper accessor’s docstring and the translation prompt (as usage context). Lives in the .bstr itself so edits restale translations via the file’s content-id; when an edit doesn’t warrant regeneration, use the UI’s mark-translations-clean action.

fit_preset: FitPreset = 'none'

Optional size/fit constraint (see FitPreset). Passed to the translator so localized output respects the UI space available.

classmethod get_type_id() AssetsV1StringFileTypeID[source]

Return the type-id for this subclass.

input: str
input_modtime: datetime.datetime
outputs: dict[Locale, Output]
style_preset: StylePreset = 'none'
class bacommon.workspace.assetsv1.AstcBlockSize(*values)[source]

Bases: Enum

ASTC square block size — the mobile bitrate lever.

Smaller block = more bits per texel = higher quality + larger output. Consulted only when an AstcSettings has its texture_quality set to CUSTOM; otherwise the blanket LOW/DEFAULT/HIGH map to a value in this range (LOW = TWELVE_BY_TWELVE, HIGH = FOUR_BY_FOUR).

EIGHT_BY_EIGHT = '8x8'
FIVE_BY_FIVE = '5x5'
FOUR_BY_FOUR = '4x4'
SIX_BY_SIX = '6x6'
TEN_BY_TEN = '10x10'
TWELVE_BY_TWELVE = '12x12'
class bacommon.workspace.assetsv1.AstcSettings(texture_quality: TextureQuality = TextureQuality.DEFAULT, block_size: AstcBlockSize = AstcBlockSize.SIX_BY_SIX)[source]

Bases: object

Per-texture ASTC (mobile) encode settings.

Consulted only when the texture’s top-level texture_quality is CUSTOM. Its own texture_quality may in turn be CUSTOM to use the explicit block_size; otherwise LOW/DEFAULT/ HIGH map to the encoder’s block-size range. Fully defaulted so a texture never has to store it explicitly.

block_size: AstcBlockSize = '6x6'
texture_quality: TextureQuality = 'default'
class bacommon.workspace.assetsv1.AudioQuality(*values)[source]

Bases: Enum

Per-sound authoring quality knob (asset-packages decision #25).

Mirrors the texture knob’s LOW/DEFAULT/HIGH pattern. Defined from day one as the escape hatch for content whose default encode budget doesn’t fit (e.g. a short pre-mixed UI sound sharing music’s bitrate), but nothing consumes it yet — the recipe carries it in its cache key only, so wiring it up later rebuilds correctly.

DEFAULT = 'default'
HIGH = 'high'
LOW = 'low'
class bacommon.workspace.assetsv1.AudioRole(*values)[source]

Bases: Enum

A sound’s channel/encode contract (asset-packages decision #25).

Names the technical contract, not a content category — “music” deliberately does not exist as a build-time concept (volume routing stays a runtime play-flag; streaming is a length-derived engine policy).

  • DEFAULT — spatialization-ready: downmixed to mono at encode (OpenAL only spatializes mono; a hard requirement, not a size optimization). The vast majority of sounds.

  • PRE_MIXED — an authored mix: channels preserved (≤2) and the sound always plays listener-space. The recipe stamps a BA_ROLE=pre_mixed vorbis comment tag so the engine knows at load time (channel count alone can’t carry the bit — a mono pre-mixed source stays mono). Music, plus any intentionally stereo (or otherwise authored-mix) sound.

DEFAULT = 'default'
PRE_MIXED = 'pre_mixed'
class bacommon.workspace.assetsv1.Bc7Rdo(*values)[source]

Bases: Enum

BC7 RDO (rate-distortion optimization) lambda — the desktop lever.

BC7 is a fixed 8bpp block format, so its size lever is RDO: higher lambda steers the encoder toward more zlib/LZ-compressible output (smaller on-disk) at the cost of quality. OFF disables RDO (best quality, largest). Consulted only when a Bc7Settings has its texture_quality set to CUSTOM; otherwise the blanket LOW/DEFAULT/HIGH map to a value in this range (LOW = FOUR, HIGH = OFF).

FOUR = '4'
OFF = 'off'
ONE = '1'
TWO = '2'
ZERO_POINT_FIVE = '0.5'
ZERO_POINT_ONE_TWO_FIVE = '0.125'
ZERO_POINT_TWO_FIVE = '0.25'
class bacommon.workspace.assetsv1.Bc7Settings(texture_quality: TextureQuality = TextureQuality.DEFAULT, rdo: Bc7Rdo = Bc7Rdo.ONE)[source]

Bases: object

Per-texture BC7 (desktop) encode settings.

Consulted only when the texture’s top-level texture_quality is CUSTOM. Its own texture_quality may in turn be CUSTOM to use the explicit rdo lambda; otherwise LOW/DEFAULT/ HIGH map to the encoder’s RDO range. Fully defaulted so a texture never has to store it explicitly.

rdo: Bc7Rdo = '1'
texture_quality: TextureQuality = 'default'
class bacommon.workspace.assetsv1.ConventionsMode(*values)[source]

Bases: Enum

Conventions-check enforcement level for an assets_v1 workspace.

STRICT blocks test/prod publishes while conventions findings exist (dev-track resolves are never gated); RELAXED (the default) surfaces findings as informational hints only.

RELAXED = 'relaxed'
STRICT = 'strict'
class bacommon.workspace.assetsv1.MeshRole(*values)[source]

Bases: Enum

What a mesh .obj source builds (asset-packages decision #26).

  • DEFAULT — a display mesh: compiled to the engine’s binary .bob format (welded/quantized verts, vertex-cache-optimized index order) and served from the flavor-varying meshes bucket (headless builds get none).

  • COLLISION — a collision mesh: compiled to the engine’s binary .cob format (positions + indices for the physics trimesh) and served from the flavor-invariant constant bucket — every build including headless gets it, and the bytes are identical across all flavors (networked sims/replays must agree on collision geometry).

COLLISION = 'collision'
DEFAULT = 'default'
class bacommon.workspace.assetsv1.Role(*values)[source]

Bases: Enum

What a texture is for (its authoring intent).

Drives mip-filtering math and encoder flags (asset-packages initiative decisions #19/#23). Intent-based rather than a bundle of low-level mechanical flags — the recipe maps each role to a concrete filtering/encoding behavior. normal_map / data are reserved slots for when such content (and the compressed- profile recipes) land.

DEFAULT = 'default'

sRGB color with straight opacity alpha. The pipeline premultiplies it by its alpha for storage (decision #23): premult-weighted, halo-free mip filtering in the requested render_space, premult output bytes, ALPHA_PREMULTIPLIED DFD flag set. The common case for color sprites. Renders correctly only with premult-blend (the renderer wiring lands in a later step; until then DEFAULT output shows darkened edges under the legacy straight-blend path).

SOURCE_PREMULTIPLIED = 'source_premultiplied'

sRGB color whose SOURCE RGB is already premultiplied by its alpha (e.g. glow sprites — they carry additive RGB > alpha values that straight alpha cannot represent). The pipeline does NOT re-multiply; mips filter the premultiplied RGB directly (in the requested render_space) and the flag is set. Renders identically to DEFAULT (both premult-blend); they differ only in whether the pipeline applies the multiply.

STRAIGHT_ALPHA = 'straight_alpha'

sRGB color with straight alpha whose RGB channels carry meaningful color even in transparent regions, so they must be preserved (decision #23). The pipeline does NOT premultiply: mips filter RGB and alpha INDEPENDENTLY (color still filtered in the requested render_space, but with no premult round-trip, which would zero — and fail to recover — the transparent-region color). Straight output bytes; ALPHA_PREMULTIPLIED flag clear. Renders with ordinary straight-alpha blending.

bacommon.workspace.assetsv1.STRING_NOT_TRANSLATED = '<NOT-TRANSLATED>'

Placeholder value for a string with no generated output in its own locale or in English. We deliberately do NOT fall back to the brief input here: that’s the author’s description of what the string should say (a translator prompt), often a long-winded sentence – not display text – so rendering it is worse than an obvious “untranslated” marker.

class bacommon.workspace.assetsv1.TextureQuality(*values)[source]

Bases: Enum

Per-texture authoring quality knob (decision #19).

DEFAULT is the normal case (the vast majority of textures); LOW and HIGH are deliberate per-texture overrides for special cases (e.g. HIGH for a hero texture that must stay crisp, LOW for one that can afford to be cheap). Named DEFAULT rather than MEDIUM to communicate that — it’s the baseline, not a middle setting you’d routinely reach past.

LOW/DEFAULT/HIGH are blanket settings that map to a sensible value for whichever encoder a profile uses (ASTC block size on mobile, BC7 RDO lambda on desktop). CUSTOM instead defers to the per-format AstcSettings / Bc7Settings so a texture can be tuned independently per encoder (e.g. ASTC HIGH while BC7 DEFAULT). Distinct from the bucket-level TextureTier.

CUSTOM = 'custom'
DEFAULT = 'default'
HIGH = 'high'
LOW = 'low'
class bacommon.workspace.assetsv1.WrapperType(*values)[source]

Bases: Enum

Python wrapper-module flavor for an asset-package version.

Selects which feature-set’s loader API the generated wrapper delegates to. Members today correspond 1:1 with feature-sets, but the type is deliberately named WrapperType (not WrapperFeatureset) to leave room for non-featureset-shaped variants (e.g. tooling-only or future loader APIs) without a rename.

BABASE = 'babase'

Strings-only wrapper for the babase layer (no classic asset loader APIs exist there); string leaves emit the same native babase.LangStr accessors as the featureset forms. Exists so pre-featureset machinery (e.g. construct-mode’s bring-up UI) can consume package strings.

BASCENEV1 = 'bascenev1'
BAUIV1 = 'bauiv1'
bacommon.workspace.assetsv1.complete_locale_values(string_files: dict[str, AssetsV1StringFileV1], locale: Locale) dict[str, str | StringSelector][source]

English-completed per-locale values for a set of string files.

Maps each string’s logical name to its value for locale: the locale’s own output, else the English output, else the STRING_NOT_TRANSLATED placeholder. So every locale’s map carries the complete key set with graceful English fallback – an untranslated string still renders (in English where available, else an obvious <NOT-TRANSLATED> marker) rather than failing, and every locale’s key set is identical. The brief input is intentionally never used as a value: it’s the author’s prompt/description, not display text.

The shared value-selection both the asset-build string recipe and the langstr vendor command route through (paired with serialize_language_blob()) so the built and vendored blobs can’t drift.

bacommon.workspace.assetsv1.derive_asset_package_name(workspace_name: str) str[source]

Derive a default asset-package name from a workspace name.

Lowercases and strips spaces (‘My Awesome Assets’ -> ‘myawesomeassets’). The single source for this rule — publish paths, collision checks, and UI previews must all route through it. Note the result is not guaranteed to be a valid asset-package name (the workspace name may contain characters with no valid mapping); consumers validate at point of use.