-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathobject.py
More file actions
132 lines (111 loc) · 4.19 KB
/
object.py
File metadata and controls
132 lines (111 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
from .base import ArtifactBase
from simvue.models import NAME_REGEX
from simvue.serialization import serialize_object
from simvue.utilities import calculate_sha256
import pydantic
import typing
import sys
import io
try:
from typing import Self
except ImportError:
from typing_extensions import Self
class ObjectArtifact(ArtifactBase):
"""Object based artifact modification and creation class."""
def __init__(
self, identifier: str | None = None, _read_only: bool = True, **kwargs
) -> None:
"""Initialise a new object artifact connection.
Parameters
----------
identifier : str, optional
the identifier of this object on the server.
"""
kwargs.pop("original_path", None)
super().__init__(identifier, _read_only, original_path="", **kwargs)
@classmethod
@pydantic.validate_call
def new(
cls,
*,
name: typing.Annotated[str, pydantic.Field(pattern=NAME_REGEX)],
storage: str | None,
obj: typing.Any,
metadata: dict[str, typing.Any] | None,
upload_timeout: int | None = None,
allow_pickling: bool = True,
offline: bool = False,
**kwargs,
) -> Self:
"""Create a new artifact either locally or on the server
Note all arguments are keyword arguments
Parameters
----------
name : str
the name for this artifact
storage : str | None
the identifier for the storage location for this object
obj : Any
object to serialize and upload
metadata : dict[str, Any] | None
supply metadata information for this artifact
upload_timeout : int | None, optional
specify the timeout in seconds for upload
allow_pickling : bool, optional
whether to allow the object to be pickled if no other
serialization found. Default is True
offline : bool, optional
whether to define this artifact locally, default is False
"""
# If the object has been saved as a bytes file, obj will be None
if obj is None:
try:
_data_type = kwargs.pop("mime_type")
_serialized = kwargs.pop("serialized")
_checksum = kwargs.pop("checksum")
kwargs.pop("size")
kwargs.pop("original_path")
except KeyError:
raise ValueError("Must provide an object to be saved, not None.")
else:
_serialization = serialize_object(obj, allow_pickling)
if not _serialization or not (_serialized := _serialization[0]):
raise ValueError(f"Could not serialize object of type '{type(obj)}'")
if not (_data_type := _serialization[1]) and not allow_pickling:
raise ValueError(
f"Could not serialize object of type '{type(obj)}' without pickling"
)
_checksum = calculate_sha256(_serialized, is_file=False)
_artifact = ObjectArtifact(
name=name,
storage=storage,
size=sys.getsizeof(_serialized),
mime_type=_data_type,
checksum=_checksum,
metadata=metadata,
_offline=offline,
_read_only=False,
**kwargs,
)
if offline:
_artifact._init_data = {}
_artifact._staging["obj"] = None
_artifact._local_staging_file.parent.mkdir(parents=True, exist_ok=True)
with open(
_artifact._local_staging_file.parent.joinpath(f"{_artifact.id}.object"),
"wb",
) as file:
file.write(_serialized)
else:
_artifact._init_data = _artifact._post(**_artifact._staging)
_artifact._staging["url"] = _artifact._init_data["url"]
_artifact._init_data["runs"] = kwargs.get("runs") or {}
if offline:
return _artifact
_file_data = io.BytesIO(_serialized)
_artifact._upload(
file=_file_data,
timeout=upload_timeout,
file_size=len(_file_data.getbuffer()),
)
return _artifact