1111from Algorithmia .util import getParentAndBase
1212from Algorithmia .data import DataObject , DataObjectType
1313from Algorithmia .errors import DataApiError , raiseDataApiError
14+ from io import RawIOBase
1415
1516
1617class DataFile (DataObject ):
@@ -24,7 +25,7 @@ def __init__(self, client, dataUrl):
2425 self .size = None
2526
2627 def set_attributes (self , attributes ):
27- self .last_modified = datetime .strptime (attributes ['last_modified' ],'%Y-%m-%dT%H:%M:%S.%fZ' )
28+ self .last_modified = datetime .strptime (attributes ['last_modified' ], '%Y-%m-%dT%H:%M:%S.%fZ' )
2829 self .size = attributes ['size' ]
2930
3031 # Deprecated:
@@ -38,13 +39,13 @@ def getFile(self):
3839 raise DataApiError ('unable to get file {} - {}' .format (self .path , error ))
3940 # Make HTTP get request
4041 response = self .client .getHelper (self .url )
41- with tempfile .NamedTemporaryFile (delete = False ) as f :
42+ with tempfile .NamedTemporaryFile (delete = False ) as f :
4243 for block in response .iter_content (1024 ):
4344 if not block :
44- break ;
45+ break
4546 f .write (block )
4647 f .flush ()
47- return open (f .name )
48+ return open (f .name )
4849
4950 def getName (self ):
5051 _ , name = getParentAndBase (self .path )
@@ -129,6 +130,7 @@ def putFile(self, path):
129130 raise raiseDataApiError (result )
130131 else :
131132 return self
133+
132134 def putNumpy (self , array ):
133135 # Post numpy array as json payload
134136 np_loader = pkgutil .find_loader ('numpy' )
@@ -148,6 +150,7 @@ def delete(self):
148150 else :
149151 return True
150152
153+
151154class LocalDataFile ():
152155 def __init__ (self , client , filePath ):
153156 self .client = client
@@ -158,7 +161,7 @@ def __init__(self, client, filePath):
158161 self .size = None
159162
160163 def set_attributes (self , attributes ):
161- self .last_modified = datetime .strptime (attributes ['last_modified' ],'%Y-%m-%dT%H:%M:%S.%fZ' )
164+ self .last_modified = datetime .strptime (attributes ['last_modified' ], '%Y-%m-%dT%H:%M:%S.%fZ' )
162165 self .size = attributes ['size' ]
163166
164167 # Get file from the data api
@@ -229,9 +232,76 @@ def delete(self):
229232 except :
230233 raise DataApiError ('Failed to delete local file ' + self .path )
231234
235+
232236def localPutHelper (path , contents ):
233237 try :
234238 with open (path , 'wb' ) as f :
235239 f .write (contents )
236240 return dict (status = 'success' )
237- except Exception as e : return dict (error = str (e ))
241+ except Exception as e :
242+ return dict (error = str (e ))
243+
244+
245+ class AdvancedDataFile (DataFile , RawIOBase ):
246+ def __init__ (self , client , dataUrl , cleanup = True ):
247+ super (AdvancedDataFile , self ).__init__ (client , dataUrl )
248+ self .cleanup = cleanup
249+ self .local_file = None
250+
251+ def __del__ (self ):
252+ if self .local_file :
253+ self .local_file .close ()
254+ if self .cleanup :
255+ os .remove (self .local_file )
256+
257+ def readable (self ):
258+ return True
259+
260+ def seekable (self ):
261+ return True
262+
263+ def writable (self ):
264+ return False
265+
266+ def read (self , __size = None ):
267+ if not self .local_file :
268+ self .local_file = self .getFile ()
269+ if __size :
270+ output = self .local_file .read (__size )
271+ else :
272+ output = self .local_file .read ()
273+ return output
274+
275+ def readline (self , __size = None ):
276+ if not self .local_file :
277+ self .local_file = self .getFile ()
278+ with self .local_file as f :
279+ if __size :
280+ output = f .readline (__size )
281+ else :
282+ output = f .readline ()
283+ return output
284+
285+ def readlines (self , __hint = None ):
286+ if not self .local_file :
287+ self .local_file = self .getFile ()
288+ if __hint :
289+ output = self .local_file .readlines (__hint )
290+ else :
291+ output = self .local_file .readlines ()
292+ return output
293+
294+ def tell (self ):
295+ if not self .local_file :
296+ self .local_file = self .getFile ()
297+ output = self .local_file .tell ()
298+ return output
299+
300+ def seek (self , __offset , __whence = None ):
301+ if not self .local_file :
302+ self .local_file = self .getFile ()
303+ if __whence :
304+ output = self .local_file .seek (__offset , __whence )
305+ else :
306+ output = self .local_file .seek (__offset )
307+ return output
0 commit comments