Skip to content

Commit 74eeef3

Browse files
authored
feat: add compound file ordinal endpoints update (#56)
1 parent facca7b commit 74eeef3

File tree

2 files changed

+131
-28
lines changed

2 files changed

+131
-28
lines changed

sdk/diffgram/file/compound_file.py

+104-18
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77

88
class CompoundChildFile:
9+
id: int
910
path: str
1011
url: str
1112
blob_path: str
@@ -24,8 +25,10 @@ class CompoundChildFile:
2425
video_split_duration: int
2526
local_id: str
2627
ordinal: int
28+
root_file: 'CompoundFile'
2729

2830
def __init__(self,
31+
root_file: 'CompoundFile',
2932
child_file_type: str,
3033
path: str = None,
3134
url: str = None,
@@ -42,7 +45,9 @@ def __init__(self,
4245
assume_new_instances_machine_made: bool = None,
4346
convert_names_to_label_files: bool = None,
4447
video_split_duration: int = None,
45-
ordinal: int = 0):
48+
ordinal: int = 0,
49+
id: int = None):
50+
self.root_file = root_file
4651
self.child_file_type = child_file_type
4752
self.path = path
4853
self.url = url
@@ -61,6 +66,38 @@ def __init__(self,
6166
self.video_split_duration = video_split_duration
6267
self.local_id = str(uuid4())
6368
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
64101

65102
def set_ordinal(self, value: int):
66103
self.ordinal = value
@@ -69,23 +106,57 @@ def set_ordinal(self, value: int):
69106
class CompoundFile:
70107
project: Project
71108
parent_file_data: dict
72-
child_files_to_upload: List[CompoundChildFile]
109+
child_files: List[CompoundChildFile]
73110

74111
def __init__(self, project: Project, name: str, directory_id: int):
75112
self.project = project
76113
self.name = name
77114
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
79150

80151
def __refresh_compound_file_from_data_dict(self, data: dict):
81152
if not data:
82153
return
83154
for key in data:
84155
setattr(self, key, data[key])
85156

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
89160

90161
def __create_compound_parent_file(self):
91162
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):
110181
frame_packet_map = child_file.frame_packet_map,
111182
assume_new_instances_machine_made = child_file.assume_new_instances_machine_made,
112183
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,
114186
)
115187
elif child_file.child_file_type == 'from_url':
116188
return self.project.file.from_url(
@@ -121,7 +193,8 @@ def __create_child_file(self, child_file: CompoundChildFile):
121193
video_split_duration = child_file.video_split_duration,
122194
instance_list = child_file.instance_list,
123195
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,
125198
)
126199
elif child_file.child_file_type == 'from_blob_path':
127200
return self.project.file.from_blob_path(
@@ -132,7 +205,8 @@ def __create_child_file(self, child_file: CompoundChildFile):
132205
instance_list = child_file.instance_list,
133206
file_name = child_file.file_name,
134207
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,
136210
)
137211

138212
def add_child_from_local(self,
@@ -141,17 +215,21 @@ def add_child_from_local(self,
141215
frame_packet_map: dict = None,
142216
assume_new_instances_machine_made: bool = True,
143217
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)
145221
new_child_file = CompoundChildFile(
222+
root_file = self,
146223
child_file_type = "from_local",
147224
path = path,
148225
directory_id = self.directory_id,
149226
instance_list = instance_list,
150227
frame_packet_map = frame_packet_map,
151228
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
153231
)
154-
self.child_files_to_upload.append(new_child_file)
232+
self.child_files.append(new_child_file)
155233
return new_child_file
156234

157235
def add_child_file_from_url(self,
@@ -162,8 +240,11 @@ def add_child_file_from_url(self,
162240
video_split_duration: int = None,
163241
instance_list: list = None,
164242
frame_packet_map: dict = None,
165-
ordinal: int = 0):
243+
ordinal: int = None):
244+
if ordinal is None:
245+
ordinal = len(self.child_files)
166246
new_child_file = CompoundChildFile(
247+
root_file = self,
167248
child_file_type = "from_url",
168249
url = url,
169250
media_type = media_type,
@@ -173,8 +254,9 @@ def add_child_file_from_url(self,
173254
video_split_duration = video_split_duration,
174255
instance_list = instance_list,
175256
frame_packet_map = frame_packet_map,
257+
ordinal = ordinal
176258
)
177-
self.child_files_to_upload.append(new_child_file)
259+
self.child_files.append(new_child_file)
178260
return new_child_file
179261

180262
def add_child_from_blob_path(self,
@@ -185,9 +267,12 @@ def add_child_from_blob_path(self,
185267
instance_list: list = None,
186268
file_name: str = None,
187269
frame_packet_map: dict = None,
188-
ordinal: int = 0
270+
ordinal: int = None
189271
):
272+
if ordinal is None:
273+
ordinal = len(self.child_files)
190274
new_child_file = CompoundChildFile(
275+
root_file = self,
191276
child_file_type = "from_blob_path",
192277
blob_path = blob_path,
193278
bucket_name = bucket_name,
@@ -197,15 +282,16 @@ def add_child_from_blob_path(self,
197282
instance_list = instance_list,
198283
file_name = file_name,
199284
frame_packet_map = frame_packet_map,
285+
ordinal = ordinal
200286
)
201-
self.child_files_to_upload.append(new_child_file)
287+
self.child_files.append(new_child_file)
202288
return new_child_file
203289

204290
def upload(self):
205-
if len(self.child_files_to_upload) == 0:
291+
if len(self.child_files) == 0:
206292
raise AssertionError('Need to add at least one child file to the compound file before calling upload()')
207293
parent_file_data: dict = self.__create_compound_parent_file()
208294

209-
for child_file in self.child_files_to_upload:
295+
for child_file in self.child_files:
210296
self.__create_child_file(child_file)
211297
return parent_file_data

sdk/diffgram/file/file_constructor.py

+27-10
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ def from_local(
4444
frame_packet_map: dict = None,
4545
assume_new_instances_machine_made: bool = True,
4646
convert_names_to_label_files: bool = True,
47-
parent_file_id: int = None
47+
parent_file_id: int = None,
48+
ordinal: int = 0
4849
):
4950
"""
5051
Create a Project file from local path
@@ -56,7 +57,9 @@ def from_local(
5657

5758
files = {'file': (os.path.basename(path), open(path, 'rb'), 'application/octet-stream')}
5859

59-
json_payload = {}
60+
json_payload = {
61+
'ordinal': ordinal
62+
}
6063

6164
if directory_id is None:
6265
directory_id = self.client.directory_id
@@ -107,13 +110,15 @@ def __build_packet_payload(self,
107110
bucket_name: str = None,
108111
file_name: str = None,
109112
blob_path: str = None,
110-
parent_file_id: int = None):
113+
parent_file_id: int = None,
114+
ordinal: int = 0):
111115
packet = {'media': {}}
112116
packet['media']['url'] = url
113117
packet['media']['type'] = media_type
114118

115119
# Existing Instances
116120
packet['frame_packet_map'] = frame_packet_map
121+
packet['ordinal'] = ordinal
117122
packet['type'] = type
118123
packet['connection_id'] = connection_id
119124
packet['parent_file_id'] = parent_file_id
@@ -140,7 +145,8 @@ def from_blob_path(self,
140145
instance_list: list = None,
141146
file_name: str = None,
142147
frame_packet_map: dict = None,
143-
parent_file_id: int = None):
148+
parent_file_id: int = None,
149+
ordinal: int = 0):
144150
"""
145151
Bind a blob path in the given connection ID into Diffgram
146152
:param blob_path:
@@ -167,7 +173,8 @@ def from_blob_path(self,
167173
file_name = name,
168174
directory_id = directory_id,
169175
type = "from_blob_path",
170-
parent_file_id=parent_file_id
176+
parent_file_id=parent_file_id,
177+
ordinal = ordinal
171178
)
172179
self.from_packet(packet = packet)
173180
return True
@@ -181,7 +188,8 @@ def from_url(
181188
video_split_duration: int = None,
182189
instance_list: list = None, # for Images
183190
frame_packet_map: dict = None, # for Video
184-
parent_file_id: int = None
191+
parent_file_id: int = None,
192+
ordinal: int = 0
185193
):
186194
"""
187195
@@ -214,7 +222,8 @@ def from_url(
214222
video_split_duration = video_split_duration,
215223
instance_list = instance_list,
216224
frame_packet_map = frame_packet_map,
217-
parent_file_id = parent_file_id
225+
parent_file_id = parent_file_id,
226+
ordinal = ordinal
218227
)
219228
self.from_packet(packet = packet)
220229

@@ -554,7 +563,15 @@ def get_by_id(self,
554563

555564
response_json = response.json()
556565
file_data = response_json.get(file_response_key)
566+
if file_data.get('type') == 'compound':
567+
from diffgram.file.compound_file import CompoundFile
568+
return CompoundFile.from_dict(
569+
project = self.client,
570+
dir_id = self.client.directory_id,
571+
dict_data = file_data
572+
)
557573

558-
return File.new(
559-
client = self.client,
560-
file_json = file_data)
574+
else:
575+
return File.new(
576+
client = self.client,
577+
file_json = file_data)

0 commit comments

Comments
 (0)