kumiho.revision
Revision module for Kumiho asset management.
This module provides the Revision class, which represents a specific
iteration of an item. Revisions contain artifacts (file references), tags,
and metadata, and can be linked to other revisions to track dependencies.
Example
Working with revisions:
import kumiho
# Get a revision
revision = kumiho.get_revision("kref://project/models/hero.model?r=1")
# Add artifacts
revision.create_artifact("mesh", "/assets/hero.fbx")
revision.create_artifact("textures", "/assets/hero_tex.zip")
# Tag the revision
revision.tag("approved")
revision.tag("ready-for-lighting")
# Create edges to dependencies
texture_revision = kumiho.get_revision("kref://project/textures/skin.texture?r=3")
revision.create_edge(texture_revision, kumiho.DEPENDS_ON)
- class kumiho.revision.Revision[source]
Bases:
KumihoObjectA specific iteration of an item in the Kumiho system.
Revisions are immutable snapshots of an item at a point in time. Each revision can have multiple artifacts (file references), tags for categorization, and edges to other revisions for dependency tracking.
The revision’s kref includes the revision number:
kref://project/space/item.kind?r=1Revisions support dynamic tag checking—the
tagsproperty automatically refreshes from the server if the local data might be stale (older than 5 seconds). This ensures tags like “latest” are always current.- kref
The unique reference URI for this revision.
- Type:
- item_kref
Reference to the parent item.
- Type:
- number
The revision number (1-based).
- Type:
- latest
Whether this is currently the latest revision.
- Type:
- tags
Tags applied to this revision (auto-refreshes).
- Type:
List[str]
- created_at
ISO timestamp when the revision was created.
- Type:
Optional[str]
- author
The user ID who created the revision.
- Type:
- deprecated
Whether the revision is deprecated.
- Type:
- published
Whether the revision is published.
- Type:
- username
Display name of the creator.
- Type:
- default_artifact
Name of the default artifact.
- Type:
Optional[str]
Example
Creating and managing revisions:
import kumiho item = kumiho.get_item("kref://project/models/hero.model") # Create a revision with metadata v1 = item.create_revision(metadata={ "artist": "jane.doe", "software": "maya-2024", "notes": "Initial model" }) # Add artifacts mesh = v1.create_artifact("mesh", "/assets/hero.fbx") rig = v1.create_artifact("rig", "/assets/hero_rig.fbx") # Set default artifact (for resolve) v1.set_default_artifact("mesh") # Tag the revision v1.tag("approved") # Check tags if v1.has_tag("approved"): print("Revision is approved!") # Get all artifacts for r in v1.get_artifacts(): print(f" {r.name}: {r.location}") # Edge to dependencies texture = kumiho.get_revision("kref://project/tex/skin.texture?r=2") v1.create_edge(texture, kumiho.DEPENDS_ON)
- __init__(pb_revision, client)[source]
Initialize a Revision from a protobuf response.
- Parameters:
pb_revision (
RevisionResponse) – The protobuf RevisionResponse message.client (
_Client) – The client instance for making API calls.
- Return type:
None
- property tags: List[str]
Get the current tags for this revision.
This property automatically refreshes from the server if the data might be stale (older than 5 seconds), ensuring dynamic tags like “latest” are always current.
- Returns:
The list of tags on this revision.
- Return type:
List[str]
Example
>>> revision = item.get_revision(1) >>> print(revision.tags) # ['latest', 'approved']
- create_artifact(name, location)[source]
Create a new artifact for this revision.
Artifacts are file references that point to actual assets on disk or network storage. Kumiho tracks the path and metadata but does not upload or copy the files.
- Parameters:
- Returns:
The newly created Artifact object.
- Return type:
Example
>>> mesh = revision.create_artifact("mesh", "/assets/hero.fbx") >>> textures = revision.create_artifact("textures", "smb://server/tex/hero.zip")
- set_metadata(metadata)[source]
Set or update metadata for this revision.
Metadata is merged with existing metadata—existing keys are overwritten and new keys are added.
- Parameters:
metadata (
Dict[str,str]) – Dictionary of metadata key-value pairs.- Returns:
The updated Revision object.
- Return type:
Example
>>> revision.set_metadata({ ... "render_engine": "arnold", ... "frame_range": "1-100", ... "resolution": "4K" ... })
- set_attribute(key, value)[source]
Set a single metadata attribute.
This allows granular updates to metadata without replacing the entire metadata map.
- Parameters:
- Returns:
True if the attribute was set successfully.
- Return type:
Example
>>> revision.set_attribute("render_engine", "cycles") True
- get_attribute(key)[source]
Get a single metadata attribute.
- Parameters:
key (
str) – The attribute key to retrieve.- Return type:
- Returns:
The attribute value if it exists, None otherwise.
Example
>>> revision.get_attribute("render_engine") "cycles"
- delete_attribute(key)[source]
Delete a single metadata attribute.
- Parameters:
key (
str) – The attribute key to delete.- Returns:
True if the attribute was deleted successfully.
- Return type:
Example
>>> revision.delete_attribute("old_field") True
- has_tag(tag)[source]
Check if this revision currently has a specific tag.
This makes a server call to ensure the tag status is current.
- Parameters:
tag (
str) – The tag to check for.- Returns:
True if the revision has the tag, False otherwise.
- Return type:
Example
>>> if revision.has_tag("approved"): ... print("Ready for production!")
- tag(tag)[source]
Apply a tag to this revision.
Tags are used to categorize revisions and mark their status. Common tags include “latest”, “published”, “approved”, etc.
Note
The “latest” tag is automatically managed—it always points to the newest revision.
Example
>>> revision.tag("approved") >>> revision.tag("ready-for-lighting")
- untag(tag)[source]
Remove a tag from this revision.
Example
>>> revision.untag("work-in-progress")
- was_tagged(tag)[source]
Check if this revision was ever tagged with a specific tag.
This checks the historical record, not just current tags.
- Parameters:
tag (
str) – The tag to check for.- Returns:
True if the revision was ever tagged with this tag.
- Return type:
Example
>>> if revision.was_tagged("approved"): ... print("Was approved at some point")
- get_artifact(name)[source]
Get a specific artifact by name from this revision.
- Parameters:
name (
str) – The name of the artifact.- Returns:
The Artifact object.
- Return type:
- Raises:
grpc.RpcError – If the artifact is not found.
Example
>>> mesh = revision.get_artifact("mesh") >>> print(mesh.location)
- get_artifacts()[source]
Get all artifacts associated with this revision.
- Returns:
A list of Artifact objects.
- Return type:
List[Artifact]
Example
>>> for artifact in revision.get_artifacts(): ... print(f"{artifact.name}: {artifact.location}")
- get_locations()[source]
Get the file locations of all artifacts in this revision.
This is a convenience method to quickly get all file paths.
- Returns:
A list of file location strings.
- Return type:
List[str]
Example
>>> locations = revision.get_locations() >>> for loc in locations: ... print(loc)
- get_item()[source]
Get the parent item of this revision.
- Returns:
The Item object that contains this revision.
- Return type:
Example
>>> item = revision.get_item() >>> print(item.item_name)
- get_space()[source]
Get the space that contains this revision’s item.
- Returns:
The Space object.
- Return type:
Example
>>> space = revision.get_space() >>> print(space.path)
- get_project()[source]
Get the project that contains this revision.
- Returns:
The Project object.
- Return type:
Example
>>> project = revision.get_project() >>> print(project.name)
- refresh()[source]
Refresh this revision’s data from the server.
This updates all properties to reflect the current state in the database, including tags that may have changed (like “latest”).
Example
>>> revision.refresh() >>> print(revision.tags) # Now shows current tags
- Return type:
- set_default_artifact(artifact_name)[source]
Set the default artifact for this revision.
The default artifact is used when resolving the revision’s kref without specifying an artifact name.
Example
>>> revision.set_default_artifact("mesh") >>> # Now kref://project/model.kind?r=1 resolves to the mesh
- delete(force=False)[source]
Delete this revision.
- Parameters:
force (
bool) – If True, force deletion even if the revision has artifacts. If False (default), deletion may fail.- Raises:
grpc.RpcError – If deletion fails.
- Return type:
Example
>>> revision.delete() # Fails if has artifacts >>> revision.delete(force=True) # Force delete
- set_deprecated(status)[source]
Set the deprecated status of this revision.
Deprecated revisions are hidden from default queries but remain accessible for historical reference.
Example
>>> revision.set_deprecated(True) # Hide from queries
- create_edge(target_revision, edge_type, metadata=None)[source]
Create an edge from this revision to another revision.
Edges represent relationships between revisions, such as dependencies, references, or derivations. This is useful for tracking asset lineage.
- Parameters:
target_revision (
Revision) – The target revision to link to.edge_type (
str) – The type of edge. Use constants fromkumiho.EdgeType: -kumiho.DEPENDS_ON: This revision depends on target. -kumiho.DERIVED_FROM: This revision was derived from target. -kumiho.REFERENCED: This revision references target. -kumiho.CONTAINS: This revision contains target.metadata (
Optional[Dict[str,str]]) – Optional metadata for the edge.
- Returns:
The created Edge object.
- Return type:
Example
>>> import kumiho
>>> # Edge to a texture dependency >>> texture = kumiho.get_revision("kref://project/tex/skin.texture?r=2") >>> revision.create_edge(texture, kumiho.DEPENDS_ON)
>>> # Edge with metadata >>> base = kumiho.get_revision("kref://project/models/base.model?r=1") >>> revision.create_edge(base, kumiho.DERIVED_FROM, { ... "modification": "Added details" ... })
- get_edges(edge_type_filter=None, direction=0)[source]
Get edges involving this revision.
- Parameters:
- Returns:
A list of Edge objects.
- Return type:
List[Edge]
Example
>>> import kumiho
>>> # Get all dependencies >>> deps = revision.get_edges(kumiho.DEPENDS_ON, kumiho.OUTGOING)
>>> # Get all revisions that depend on this one >>> dependents = revision.get_edges(kumiho.DEPENDS_ON, kumiho.INCOMING)
- delete_edge(target_revision, edge_type)[source]
Delete an edge from this revision.
- Parameters:
- Return type:
Example
>>> revision.delete_edge(texture_revision, kumiho.DEPENDS_ON)
- get_all_dependencies(edge_type_filter=None, max_depth=10, limit=100)[source]
Get all transitive dependencies of this revision.
Traverses outgoing edges to find all revisions this revision depends on, directly or indirectly.
- Parameters:
- Returns:
Contains all discovered revisions and paths.
- Return type:
TraversalResult
Example
>>> import kumiho
>>> # Get all dependencies up to 5 hops >>> deps = revision.get_all_dependencies( ... edge_type_filter=[kumiho.DEPENDS_ON], ... max_depth=5 ... ) >>> for kref in deps.revision_krefs: ... print(f"Depends on: {kref}")
- get_all_dependents(edge_type_filter=None, max_depth=10, limit=100)[source]
Get all revisions that transitively depend on this revision.
Traverses incoming edges to find all revisions that depend on this revision, directly or indirectly. Useful for impact analysis.
- Parameters:
- Returns:
Contains all dependent revisions.
- Return type:
TraversalResult
Example
>>> # Find everything that would be affected by changing this texture >>> dependents = texture_v1.get_all_dependents([kumiho.DEPENDS_ON]) >>> print(f"{len(dependents.revision_krefs)} revisions would be affected")
- find_path_to(target, edge_type_filter=None, max_depth=10, all_paths=False)[source]
Find the shortest path from this revision to another.
Uses graph traversal to find how two revisions are connected.
- Parameters:
- Return type:
Optional[RevisionPath]- Returns:
RevisionPath if a path exists, None otherwise. Use all_paths=True and access result.paths for multiple paths.
Example
>>> path = model_v1.find_path_to(texture_v3) >>> if path: ... print(f"Path length: {path.total_depth}") ... for step in path.steps: ... print(f" -> {step.revision_kref} via {step.edge_type}")
- analyze_impact(edge_type_filter=None, max_depth=10, limit=100)[source]
Analyze the impact of changes to this revision.
Returns all revisions that directly or indirectly depend on this revision, sorted by impact depth (closest dependencies first).
- Parameters:
- Returns:
Revisions that would be impacted.
- Return type:
List[ImpactedRevision]
Example
>>> # Before modifying a shared texture >>> impact = texture_v1.analyze_impact() >>> print(f"{len(impact)} revisions would need review") >>> for iv in impact[:5]: ... print(f" {iv.revision_kref} (depth {iv.impact_depth})")