3 Commits

+47 -14
View File
@@ -77,7 +77,7 @@ class AyonClient:
parent_id: str,
folder_type: str = "Asset",
) -> dict:
"""Create a new folder under a parent."""
"""Create a new folder under a parent. Returns full folder dict."""
r = self._client.post(
f"/api/projects/{project}/folders",
json={
@@ -87,32 +87,53 @@ class AyonClient:
},
)
r.raise_for_status()
return r.json()
folder_id = r.json()["id"]
# Re-fetch to get full folder details (including name/path)
return self._get_folder(project, folder_id)
def _get_folder(self, project: str, folder_id: str) -> dict:
"""Get a single folder by ID via GraphQL."""
query = (
'{project(name:"' + project + '")'
'{folder(id:"' + folder_id + '")'
"{id name path parentId folderType}}}"
)
data = self._graphql(query)
return data["project"]["folder"]
def find_or_create_folder(
self, project: str, path: str, folder_type: str = "Asset"
) -> dict:
"""Find existing folder or create it (including parents)."""
"""Find existing folder or create it (including parents).
Walks the path component by component — each component must match
the exact folder name under the current parent, not just endswith.
"""
f = self.find_folder(project, path)
if f:
return f
parts = path.strip("/").split("/")
current_parent = None
# Find root parent
# Resolve root-level folders (no parentId)
folders = self.list_folders(project)
current_parent = None
for part in parts:
found = None
for f in folders:
fp = f.get("path", "").lstrip("/")
pid = f.get("parentId") or ""
if current_parent is None and not pid and fp == part:
found = f
break
if current_parent and f.get("parentId") == current_parent["id"] and fp.endswith(part):
found = f
break
if current_parent is None:
# Root level: name matches and no parent
if f.get("name") == part and not pid:
found = f
break
else:
# Child level: name matches AND parentId matches
if f.get("name") == part and pid == current_parent["id"]:
found = f
break
if found:
current_parent = found
@@ -239,13 +260,25 @@ class AyonClient:
name: str,
files: list[dict],
) -> dict:
"""files: [{"name": "BaseColor.png", "size": 12345}, ...]"""
"""files: [{"name": "BaseColor.png", "size": 12345}, ...]
Files are enriched with required 'id' (UUID) and 'path' fields.
"""
import uuid
enriched = []
for f in files:
enriched.append({
"id": uuid.uuid4().hex,
"name": f.get("name", f.get("path", "file")),
"path": f.get("path", f"/tmp/{f.get('name', 'file')}"),
"size": f.get("size", 0),
})
r = self._client.post(
f"/api/projects/{project}/representations",
json={
"name": name,
"versionId": version_id,
"files": files,
"files": enriched,
},
)
r.raise_for_status()