Move an integration from 0.8 to 0.9¶
The 0.9 development SDK uses C ABI 57, schema 27 and exchange protocol 1. Update the binding and native library together. Python 0.8 bindings reject an ABI 57 library. Existing production identities and stored knowledge retain their meaning; opening older files follows the existing migration rules.
Old form |
Use in 0.9 |
|---|---|
C additive/revision-only transaction constructors |
|
C++ |
|
Python edit context setter |
Pass |
Python |
|
Python revision-ID-only transaction base |
|
Python |
The path itself |
Asset-only Python/C++ import result |
|
C import’s asset-only outputs |
Add nullable |
Python |
|
C++ |
|
Python |
|
Python |
|
Manual asset/revision page loops in Python or Rust |
The retained view’s |
C file-source creation, staging and release |
|
C resolution factory plus setters |
One |
C++ resolution factory plus setters |
|
C++ |
|
Rust |
|
C status-only commit / |
|
CLI |
|
Python metadata accepts (vocabulary, property) keys and native str,
bool, signed int, bytes, exact Fraction and list/tuple values. Reads
return scalars and immutable tuples. Keep explicit unsigned, URI, localized
text and other ambiguous variants. Floats, None and dictionaries do not
acquire an inferred metadata meaning. See Metadata vocabularies.
Python edit(), edit(base) and view.edit() accept origin= and
message=. Uncommitted context exit rolls back. Commit returns this edit’s
own receipt, including an absent revision for no change. A failed commit is
terminal; Base revisions and semantic conflicts explains explicit retry.
Five Python tasks¶
These excerpts run together in docs/examples/python/ergonomics.py. Its
fixture supplies rushes/A001.mov, an empty moved/ directory and an output
directory. The host produces the output bytes before recording them.
The historical comparison
runs the same workflow against the published 0.8 platform wheel.
The qualified ABI-53 comparison
preserves the initial 0.9 program; the current excerpts use ABI 57.
Import a file and ordinary metadata with one edit:
with Production.create(work / "tasks.pproj", "Documentary") as production:
with production.edit(origin="example:editor", message="Import take") as edit:
imported = edit.import_media(original, display_name="Camera A")
asset_id = imported.asset_id
edit.add_metadata(
AssetRef(asset_id), ("example:editorial", "title"), "Interview"
)
receipt = edit.commit()
assert receipt.revision is not None # This edit's own revision.
Reuse an existing identity after an explicit adoption decision:
with production.read_session() as view:
matches = view.find_known_media(original, limit=2)
if matches.next_cursor is not None or len(matches.items) != 1:
raise ValueError("Adoption needs an explicit, unique choice")
known = matches.items[0]
adopted_asset = known.asset_id # Store this ID in the host project.
assert adopted_asset == asset_id # No new identity or revision.
assert known.representation_id == imported.representation_id
After the fixture moves the file, resolve and explicitly confirm its location. The detached base lets the caller close the view before host/UI work:
with production.read_session() as view:
resolutions = view.resolve(
asset_id,
search_directories=[moved.parent],
verification=VerificationMode.CONTENT,
)
selected = next(
item
for item in resolutions
if item.representation_id == known.representation_id
)
selection = selected.select_verified()
# The copied decision survives the view; host/UI work can happen here.
with production.edit(base=selection.base, message="Confirm moved take") as edit:
edit.confirm_selection(selection)
relink_receipt = edit.commit()
assert relink_receipt.revision is not None
Record a produced representation with its actual activity and parameters:
with production.read_session() as view:
input_id = known.representation_id # Retained from explicit adoption.
with view.edit(message="Record host output") as edit:
registered = edit.register_outputs(
((asset_id, RepresentationKind.DERIVED, output),),
ActivitySpec(
"example:preview",
inputs=(input_id,),
tool=ToolIdentity("Example file copy", "1.0"),
parameters={("example:preview", "mode"): "copy"},
),
)
output_id = registered.outputs[0].representation_id
output_receipt = edit.commit() # Output and knowledge are atomic.
assert output_receipt.revision is not None
Activity inputs describe provenance. They do not imply authored references inside the output; record dependency observations only when the host has inspected such references.
Scan a pinned asset set and finite history with bounded pages:
with production.read_session() as view:
assets = list(view.assets(page_size=100))
revisions = list(view.revisions(after=0, page_size=100))
assert len(assets) == 1
assert [revision.sequence for revision in revisions] == [1, 2, 3]
For the equivalent C, C++17, Rust and CLI paths, use Create a production and import media, Adopt media already known to a production, Media roots and resolution, Provenance integration and Consuming the revision feed. The CLI JSON format remains 1; command-line decisions now use the scoped token. See CLI output.
Produced outputs¶
Use Edit.register_outputs, C++ Transaction::registerOutputs, native
pp_transaction_register_outputs or CLI artifact register for an
already-produced file or compound source and its actual activity/parameters.
Rust uses prepare_outputs followed by owned stage; failed staging rolls
back the owned edit. Commit remains explicit.
ActivitySpec writes accept representation IDs or (ID, role) pairs. Copied
read edges retain snapshots and no longer serve as write builders. Python
parameters accept a mapping or repeated key/value pairs; C++ accepts typed
parameter tuples. Native activity creation now takes pp_activity_recipe_t
and a separate output-edge array. Update headers, library and bindings together.
Verified relinking (development ABI 57)¶
Retain the import’s representation ID and select it explicitly from resolution
results. Python select_verified, C++ selectVerified and native
pp_resolution_set_select_verified copy/lend complete verified locations with
the original decision base. Confirm them together using a read-bound edit;
Rust uses stage_relink. CLI media relink REPRESENTATION --confirm captures
its own coherent decision and requires explicit confirmation.
A single candidate is insufficient when verification is partial or search is
incomplete. Unverified optional members remain in diagnostics. Existing
locations are guarded no-ops. Explicit locator confirmation remains available
for independent human/host decisions. Deferred intent uses
locator.confirm.v1; older protocol decoders reject that command as unsupported.
Native Python metadata values¶
Read and write strings, signed integers, booleans, binary values and exact
rationals as str, int, bool, bytes and Fraction. Lists and tuples write
one list value; reads return immutable tuples. The corresponding
MetadataString, MetadataI64, MetadataBool, MetadataBytes,
MetadataRational and MetadataList classes are removed.
Unsigned values keep MetadataU64; URI, language, timestamp, decimal, reference
and ordered structure values remain explicit. Inspect Python types when reading:
ordinary Python equality equates True and 1, while metadata assertion/field
equality preserves their distinct stored kinds. Repeated assertions and ordered
fields retain their meaning. Cycles and unsupported dictionaries are rejected.
Advanced Python imports¶
Import job requests, states, leases and job events from postproject.jobs.
Import proposal commands/builders, request IDs, durable outcomes and replication
positions from postproject.exchange. Their package-root exports are removed;
ordinary production/media/metadata recipes keep the root imports.
Edit.prepare_proposal captures an already prepared native edit. The command
builder expresses deferred intent. Both remain available. Notification progress
and replication positions retain their distinct scopes.