def serve_stream(self, stream: FileLike): buffer = io.BytesIO() self.send_header('Content-Length', str(copy_stream(stream, buffer))) self.end_headers() buffer.seek(0) try: copy_stream(buffer, self.wfile) except ConnectionResetError: pass
def read(self, size: int = None) -> bytes: """ Read from the underlying file. :param size: Amount of bytes ro read. """ if size is None: buffer = io.BytesIO() copy_stream(self, buffer) return buffer.getvalue() else: return self._read_chunked(size)
def put(self, filename: str, stream: FileLike): physical_path = self._get_physical_path(filename) physical_directory = dirname(physical_path) if not exists(physical_directory): makedirs(physical_directory, exist_ok=True) with open(physical_path, mode='wb') as target_file: return copy_stream(stream, target_file, chunk_size=self.chunk_size)
def test_localfs(self): descriptor = AttachableDescriptor(self.cat_jpeg, width=100, height=80) self.assertIsInstance(descriptor, LocalFileSystemDescriptor) self.assertEqual(descriptor.filename, self.cat_jpeg) # Must be determined from the given file's extension: .jpg self.assertEqual(descriptor.content_type, 'image/jpeg') self.assertEqual(descriptor.original_filename, self.cat_jpeg) self.assertEqual(descriptor.width, 100) self.assertEqual(descriptor.height, 80) self.assertEqual(len(descriptor.get_header_buffer()), 1024) buffer = io.BytesIO() copy_stream(descriptor, buffer) buffer.seek(0) self.assertEqual(md5sum(buffer), md5sum(self.cat_jpeg))
def test_cgi_field_storage(self): # encode a multipart form content_type, body, content_length = encode_multipart_data(files=dict(cat=self.cat_jpeg)) environ = { 'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': content_type, 'CONTENT_LENGTH': content_length } storage = cgi.FieldStorage(body, environ=environ) descriptor = AttachableDescriptor(storage['cat']) self.assertIsInstance(descriptor, CgiFieldStorageDescriptor) self.assertEqual(descriptor.content_type, 'image/jpeg') self.assertEqual(descriptor.original_filename, split(self.cat_jpeg)[1]) buffer = io.BytesIO() copy_stream(descriptor, buffer) buffer.seek(0) self.assertEqual(md5sum(buffer), md5sum(self.cat_jpeg))
def do_GET(self): try: bucket, _ = self._validate_host() except TypeError: return if self.path == '/': return self.send_error('400', 'BadObjectError') filename = join(temp_path, bucket, self.path[1:]) if not exists(filename): return self.send_error(404, 'NotFound') self.send_response(HTTPStatus.OK) with open(filename, 'rb') as f: data = f.read() self.send_header('Content-Length', len(data)) self.end_headers() f.seek(0) try: copy_stream(f, self.wfile) except ConnectionResetError: pass
def prepare_to_read(self, backend: str = 'temp') -> None: """ .. versionadded:: 0.5 If the underlying file-object is not seekable, tries to store the underlying non-seekable file-like object as an instance of :class:`io.BytesIO`, :obj:`tempfile.NamedTemporaryFile` and :obj:`tempfile.TemporaryFile`. .. warning:: Anyway, this method will seeks the descriptor to ``0``. .. warning:: If any physical file is created during this operation, This will be deleted after the :meth:`.close` has been called. .. warning:: :exc:`.DescriptorOperationError` may be raised, if the current position is greater than zero ``0``, and also if called on a seekable instance. .. note:: The ``file`` option is also a temp file but file is guaranteed to have a visible name in the file system (on Unix, the directory entry is not unlinked). filename will be retrieved by the :attr:`.filename`. :param backend: Available choices are: ``memory``, ``file`` and ``temp``. """ if self.seekable(): self.seek(0) return if backend == 'memory': buffer = io.BytesIO() elif backend == 'temp': buffer = TemporaryFile() elif backend == 'file': buffer = NamedTemporaryFile() else: raise DescriptorOperationError( 'Invalid backend for descriptor: %r' % backend) length = copy_stream(self, buffer) buffer.seek(0) self.replace( buffer, position=0, content_length=length, extension=self.extension, original_filename=self.original_filename, )