6
6
7
7
8
8
class CompoundChildFile :
9
+ id : int
9
10
path : str
10
11
url : str
11
12
blob_path : str
@@ -24,8 +25,10 @@ class CompoundChildFile:
24
25
video_split_duration : int
25
26
local_id : str
26
27
ordinal : int
28
+ root_file : 'CompoundFile'
27
29
28
30
def __init__ (self ,
31
+ root_file : 'CompoundFile' ,
29
32
child_file_type : str ,
30
33
path : str = None ,
31
34
url : str = None ,
@@ -42,7 +45,9 @@ def __init__(self,
42
45
assume_new_instances_machine_made : bool = None ,
43
46
convert_names_to_label_files : bool = None ,
44
47
video_split_duration : int = None ,
45
- ordinal : int = 0 ):
48
+ ordinal : int = 0 ,
49
+ id : int = None ):
50
+ self .root_file = root_file
46
51
self .child_file_type = child_file_type
47
52
self .path = path
48
53
self .url = url
@@ -61,6 +66,38 @@ def __init__(self,
61
66
self .video_split_duration = video_split_duration
62
67
self .local_id = str (uuid4 ())
63
68
self .ordinal = ordinal
69
+ self .id = None
70
+
71
+ def __str__ (self ):
72
+ return f'<CompoundChildFile id={ self .id } ordinal={ self .ordinal } file_name={ self .file_name } child_file_type={ self .child_file_type } >'
73
+ def refresh_from_data_dict (self , data : dict ):
74
+ if not data :
75
+ return
76
+ for key in data :
77
+ setattr (self , key , data [key ])
78
+
79
+ def update (self ):
80
+ """
81
+ Syncs child file data with backend API
82
+ :return:
83
+ """
84
+ payload = {
85
+ 'ordinal' : self .ordinal ,
86
+ }
87
+ client = self .root_file .project
88
+ endpoint = f"/api/v1/project/{ self .root_file .project .project_string_id } /file/{ self .id } /update-metadata"
89
+
90
+ response = client .session .put (
91
+ client .host + endpoint ,
92
+ json = payload )
93
+
94
+ client .handle_errors (response )
95
+
96
+ data = response .json ()
97
+ new_file_data = data ['file' ]
98
+
99
+ self .refresh_from_data_dict (data = new_file_data )
100
+ return self
64
101
65
102
def set_ordinal (self , value : int ):
66
103
self .ordinal = value
@@ -69,23 +106,57 @@ def set_ordinal(self, value: int):
69
106
class CompoundFile :
70
107
project : Project
71
108
parent_file_data : dict
72
- child_files_to_upload : List [CompoundChildFile ]
109
+ child_files : List [CompoundChildFile ]
73
110
74
111
def __init__ (self , project : Project , name : str , directory_id : int ):
75
112
self .project = project
76
113
self .name = name
77
114
self .directory_id = directory_id
78
- self .child_files_to_upload = []
115
+ self .child_files = []
116
+
117
+ @staticmethod
118
+ def from_dict (project : Project , dir_id : int , dict_data : dict ):
119
+ result = CompoundFile (project = project , name = dict_data .get ('original_filename' ), directory_id = dir_id )
120
+ result .__refresh_compound_file_from_data_dict (data = dict_data )
121
+ child_files = result .__fetch_child_files ()
122
+ result .child_files = child_files
123
+ return result
124
+
125
+ def __fetch_child_files (self ) -> List [CompoundChildFile ]:
126
+ client = self .project
127
+ endpoint = f"/api/v1/project/{ self .project .project_string_id } /file/{ self .id } /child-files"
128
+
129
+ response = client .session .get (client .host + endpoint )
130
+
131
+ client .handle_errors (response )
132
+
133
+ data = response .json ()
134
+ child_files_data = data ['child_files' ]
135
+ result = []
136
+ for elm in child_files_data :
137
+ child_file = CompoundChildFile (root_file = self , child_file_type = elm .get ('type' ))
138
+ child_file .refresh_from_data_dict (data = elm )
139
+ result .append (child_file )
140
+ return result
141
+
142
+ def update_all (self ) -> bool :
143
+ """
144
+ Syncs parent and child metadata with backend API.
145
+ :return: True/False
146
+ """
147
+ for child in self .child_files :
148
+ child .update ()
149
+ return True
79
150
80
151
def __refresh_compound_file_from_data_dict (self , data : dict ):
81
152
if not data :
82
153
return
83
154
for key in data :
84
155
setattr (self , key , data [key ])
85
156
86
- def remove_compound_file (self , child_file : CompoundChildFile ) -> List [CompoundChildFile ]:
87
- self .child_files_to_upload .remove (child_file )
88
- return self .child_files_to_upload
157
+ def remove_child_file (self , child_file : CompoundChildFile ) -> List [CompoundChildFile ]:
158
+ self .child_files .remove (child_file )
159
+ return self .child_files
89
160
90
161
def __create_compound_parent_file (self ):
91
162
url = f'/api/v1/project/{ self .project .project_string_id } /file/new-compound'
@@ -110,7 +181,8 @@ def __create_child_file(self, child_file: CompoundChildFile):
110
181
frame_packet_map = child_file .frame_packet_map ,
111
182
assume_new_instances_machine_made = child_file .assume_new_instances_machine_made ,
112
183
convert_names_to_label_files = child_file .convert_names_to_label_files ,
113
- parent_file_id = self .parent_file_data .get ('id' )
184
+ parent_file_id = self .parent_file_data .get ('id' ),
185
+ ordinal = child_file .ordinal ,
114
186
)
115
187
elif child_file .child_file_type == 'from_url' :
116
188
return self .project .file .from_url (
@@ -121,7 +193,8 @@ def __create_child_file(self, child_file: CompoundChildFile):
121
193
video_split_duration = child_file .video_split_duration ,
122
194
instance_list = child_file .instance_list ,
123
195
frame_packet_map = child_file .frame_packet_map ,
124
- parent_file_id = self .parent_file_data .get ('id' )
196
+ parent_file_id = self .parent_file_data .get ('id' ),
197
+ ordinal = child_file .ordinal ,
125
198
)
126
199
elif child_file .child_file_type == 'from_blob_path' :
127
200
return self .project .file .from_blob_path (
@@ -132,7 +205,8 @@ def __create_child_file(self, child_file: CompoundChildFile):
132
205
instance_list = child_file .instance_list ,
133
206
file_name = child_file .file_name ,
134
207
frame_packet_map = child_file .frame_packet_map ,
135
- parent_file_id = self .parent_file_data .get ('id' )
208
+ parent_file_id = self .parent_file_data .get ('id' ),
209
+ ordinal = child_file .ordinal ,
136
210
)
137
211
138
212
def add_child_from_local (self ,
@@ -141,17 +215,21 @@ def add_child_from_local(self,
141
215
frame_packet_map : dict = None ,
142
216
assume_new_instances_machine_made : bool = True ,
143
217
convert_names_to_label_files : bool = True ,
144
- ordinal : int = 0 ):
218
+ ordinal : int = None ):
219
+ if ordinal is None :
220
+ ordinal = len (self .child_files )
145
221
new_child_file = CompoundChildFile (
222
+ root_file = self ,
146
223
child_file_type = "from_local" ,
147
224
path = path ,
148
225
directory_id = self .directory_id ,
149
226
instance_list = instance_list ,
150
227
frame_packet_map = frame_packet_map ,
151
228
assume_new_instances_machine_made = assume_new_instances_machine_made ,
152
- convert_names_to_label_files = convert_names_to_label_files
229
+ convert_names_to_label_files = convert_names_to_label_files ,
230
+ ordinal = ordinal
153
231
)
154
- self .child_files_to_upload .append (new_child_file )
232
+ self .child_files .append (new_child_file )
155
233
return new_child_file
156
234
157
235
def add_child_file_from_url (self ,
@@ -162,8 +240,11 @@ def add_child_file_from_url(self,
162
240
video_split_duration : int = None ,
163
241
instance_list : list = None ,
164
242
frame_packet_map : dict = None ,
165
- ordinal : int = 0 ):
243
+ ordinal : int = None ):
244
+ if ordinal is None :
245
+ ordinal = len (self .child_files )
166
246
new_child_file = CompoundChildFile (
247
+ root_file = self ,
167
248
child_file_type = "from_url" ,
168
249
url = url ,
169
250
media_type = media_type ,
@@ -173,8 +254,9 @@ def add_child_file_from_url(self,
173
254
video_split_duration = video_split_duration ,
174
255
instance_list = instance_list ,
175
256
frame_packet_map = frame_packet_map ,
257
+ ordinal = ordinal
176
258
)
177
- self .child_files_to_upload .append (new_child_file )
259
+ self .child_files .append (new_child_file )
178
260
return new_child_file
179
261
180
262
def add_child_from_blob_path (self ,
@@ -185,9 +267,12 @@ def add_child_from_blob_path(self,
185
267
instance_list : list = None ,
186
268
file_name : str = None ,
187
269
frame_packet_map : dict = None ,
188
- ordinal : int = 0
270
+ ordinal : int = None
189
271
):
272
+ if ordinal is None :
273
+ ordinal = len (self .child_files )
190
274
new_child_file = CompoundChildFile (
275
+ root_file = self ,
191
276
child_file_type = "from_blob_path" ,
192
277
blob_path = blob_path ,
193
278
bucket_name = bucket_name ,
@@ -197,15 +282,16 @@ def add_child_from_blob_path(self,
197
282
instance_list = instance_list ,
198
283
file_name = file_name ,
199
284
frame_packet_map = frame_packet_map ,
285
+ ordinal = ordinal
200
286
)
201
- self .child_files_to_upload .append (new_child_file )
287
+ self .child_files .append (new_child_file )
202
288
return new_child_file
203
289
204
290
def upload (self ):
205
- if len (self .child_files_to_upload ) == 0 :
291
+ if len (self .child_files ) == 0 :
206
292
raise AssertionError ('Need to add at least one child file to the compound file before calling upload()' )
207
293
parent_file_data : dict = self .__create_compound_parent_file ()
208
294
209
- for child_file in self .child_files_to_upload :
295
+ for child_file in self .child_files :
210
296
self .__create_child_file (child_file )
211
297
return parent_file_data
0 commit comments