Data tool can now export project trees not starting from the root

This commit is contained in:
clearml 2024-12-05 19:06:56 +02:00
parent 7b5679fd70
commit 8f942f0da2

View File

@ -28,6 +28,7 @@ from urllib.parse import unquote, urlparse
from uuid import uuid4, UUID, uuid5
from zipfile import ZipFile, ZIP_BZIP2
import attr
import mongoengine
from boltons.iterutils import chunked_iter, first
from furl import furl
@ -84,6 +85,11 @@ class PrePopulate:
user_cls: Type[User]
auth_user_cls: Type[AuthUser]
@attr.s(auto_attribs=True)
class ParentPrefix:
prefix: str
path: Sequence[str]
# noinspection PyTypeChecker
@classmethod
def _init_entity_types(cls):
@ -469,20 +475,35 @@ class PrePopulate:
@classmethod
def _check_projects_hierarchy(cls, projects: Set[Project]):
"""
For any exported project all its parents up to the root should be present
For the projects that are exported not from the root
fix their parents tree to exclude the not exported parents
"""
if not projects:
return
project_ids = {p.id for p in projects}
orphans = [p.id for p in projects if p.parent and p.parent not in project_ids]
orphans = [p for p in projects if p.parent and p.parent not in project_ids]
if not orphans:
return
print(
f"ERROR: the following projects are exported without their parents: {orphans}"
)
exit(1)
prefixes = [
cls.ParentPrefix(prefix=f"{project.name.rpartition('/')[0]}/", path=project.path)
for project in orphans
]
prefixes.sort(key=lambda p: len(p.path), reverse=True)
for project in projects:
prefix = first(pref for pref in prefixes if project.path[:len(pref.path)] == pref.path)
if not prefix:
continue
project.path = project.path[len(prefix.path):]
if not project.path:
project.parent = None
project.name = project.name.removeprefix(prefix.prefix)
# print(
# f"ERROR: the following projects are exported without their parents: {orphans}"
# )
# exit(1)
@classmethod
def _resolve_entities(
@ -491,6 +512,7 @@ class PrePopulate:
projects: Sequence[str] = None,
task_statuses: Sequence[str] = None,
) -> Dict[Type[mongoengine.Document], Set[mongoengine.Document]]:
# noinspection PyTypeChecker
entities: Dict[Any] = defaultdict(set)
if projects:
@ -539,6 +561,7 @@ class PrePopulate:
print("Reading models...")
entities[cls.model_cls] = set(cls.model_cls.objects(id__in=list(model_ids)))
# noinspection PyTypeChecker
return entities
@classmethod
@ -1133,7 +1156,7 @@ class PrePopulate:
if isinstance(doc, cls.task_cls):
tasks.append(doc)
cls.event_bll.delete_task_events(company_id, doc.id, allow_locked=True)
cls.event_bll.delete_task_events(company_id, doc.id)
if tasks:
return tasks