Implement stream_read_file for the Swift storage engine
				
					
				
			Note that Swift doesn't seem to have a file-like interface, so we need to wrap the generator we get back from it. Fixes #210
This commit is contained in:
		
							parent
							
								
									cb238f8764
								
							
						
					
					
						commit
						4333bb9e14
					
				
					 3 changed files with 127 additions and 1 deletions
				
			
		
							
								
								
									
										76
									
								
								util/generatorfile.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								util/generatorfile.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,76 @@ | |||
| def _complain_ifclosed(closed): | ||||
|   if closed: | ||||
|     raise ValueError, "I/O operation on closed file" | ||||
| 
 | ||||
| class GeneratorFile(object): | ||||
|   """ File-like object which wraps a Python generator to produce the file contents. | ||||
|       Modeled on StringIO and comments on the file-like interface copied from there. | ||||
|   """ | ||||
|   def __init__(self, generator): | ||||
|     self._generator = generator | ||||
|     self._closed = False | ||||
|     self._buf = '' | ||||
| 
 | ||||
|   def __iter__(self): | ||||
|     return self | ||||
| 
 | ||||
|   def next(self): | ||||
|     """A file object is its own iterator, for example iter(f) returns f | ||||
|     (unless f is closed). When a file is used as an iterator, typically | ||||
|     in a for loop (for example, for line in f: print line), the next() | ||||
|     method is called repeatedly. This method returns the next input line, | ||||
|     or raises StopIteration when EOF is hit. | ||||
|     """ | ||||
|     _complain_ifclosed(self._closed) | ||||
|     r = self.read() | ||||
|     if not r: | ||||
|       raise StopIteration | ||||
|     return r | ||||
| 
 | ||||
|   def readline(self): | ||||
|     buf = [] | ||||
|     while True: | ||||
|       c = self.read(size=1) | ||||
|       buf.append(c) | ||||
|       if c == '\n' or c == '': | ||||
|         return ''.join(buf) | ||||
| 
 | ||||
|   def flush(self): | ||||
|     _complain_ifclosed(self._closed) | ||||
| 
 | ||||
|   def read(self, size=-1): | ||||
|     """Read at most size bytes from the file | ||||
|     (less if the read hits EOF before obtaining size bytes). | ||||
| 
 | ||||
|     If the size argument is negative or omitted, read all data until EOF | ||||
|     is reached. The bytes are returned as a string object. An empty | ||||
|     string is returned when EOF is encountered immediately. | ||||
|     """ | ||||
|     _complain_ifclosed(self._closed) | ||||
|     buf = self._buf | ||||
|     while size < 0 or len(buf) < size: | ||||
|       try: | ||||
|         buf = buf + self._generator.next() | ||||
|       except StopIteration: | ||||
|         break | ||||
| 
 | ||||
|     returned = '' | ||||
|     if size >= 1: | ||||
|       self._buf = buf[size:] | ||||
|       returned = buf[:size] | ||||
|     else: | ||||
|       self._buf = '' | ||||
|       returned = buf | ||||
| 
 | ||||
|     return returned | ||||
| 
 | ||||
| 
 | ||||
|   def close(self): | ||||
|     self._closed = True | ||||
|     del self._buf | ||||
| 
 | ||||
|   def __enter__(self): | ||||
|     return self | ||||
| 
 | ||||
|   def __exit__(self, type, value, traceback): | ||||
|     self._closed = True | ||||
		Reference in a new issue