Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions test/test_backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,29 @@ def test_list_return_defaults_incremental_base_backup_id_to_none(entry: Dict[str
# The server omits the field for non-incremental backups, and only populates
# it for callers it has confirmed as root, so absent must not be an error.
assert BackupListReturn(**entry).incremental_base_backup_id is None


def test_running_backup_and_export_zero_completed_at_is_none() -> None:
from weaviate.export.export import ExportStatusReturn

backup = BackupListReturn(
**_list_entry(status="STARTED", completedAt="0001-01-01T00:00:00.000Z")
)
assert backup.completed_at is None

completed = BackupListReturn(
**_list_entry(status="SUCCESS", completedAt="2026-08-01T10:05:00.000Z")
)
assert completed.completed_at is not None
assert completed.completed_at.year == 2026

export_status = ExportStatusReturn(
id="exp1",
backend="filesystem",
path="/tmp/exports/exp1",
status="TRANSFERRING",
startedAt="2026-10-21T06:50:47.995Z",
completedAt="0001-01-01T00:00:00.000Z",
classes=["Article"],
)
assert export_status.completed_at is None
9 changes: 8 additions & 1 deletion weaviate/backup/backup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from enum import Enum
from typing import Any, Dict, List, Optional, cast

from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, field_validator

from weaviate.backup.backup_location import _BackupLocationConfig

Expand Down Expand Up @@ -107,3 +107,10 @@ class BackupListReturn(BaseModel):
# None when the backup is not incremental, and also when the server omits the
# field: it is only returned to callers Weaviate has confirmed as root.
incremental_base_backup_id: Optional[str] = Field(default=None)

@field_validator("completed_at", mode="after")
@classmethod
def _normalize_zero_completed_at(cls, v: Optional[datetime]) -> Optional[datetime]:
if v is not None and v.year <= 1:
return None
return v
9 changes: 8 additions & 1 deletion weaviate/export/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from enum import Enum
from typing import Dict, List, Optional

from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, field_validator

from weaviate.backup.backup import BackupStorage

Expand Down Expand Up @@ -69,3 +69,10 @@ class ExportStatusReturn(ExportCreateReturn):
)
error: Optional[str] = None
took_in_ms: Optional[int] = Field(alias="tookInMs", default=None)

@field_validator("completed_at", mode="after")
@classmethod
def _normalize_zero_completed_at(cls, v: Optional[datetime]) -> Optional[datetime]:
if v is not None and v.year <= 1:
return None
return v
Loading