1# -*- coding: utf-8 -*- 2# Copyright 2013 Google Inc. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15"""FilePart implementation for representing part of a file.""" 16 17from __future__ import absolute_import 18 19import os 20 21 22class FilePart(file): 23 """Subclass of the file API for representing part of a file. 24 25 This class behaves as a contiguous subset of a given file (e.g., this object 26 will behave as though the desired part of the file was written to another 27 file, and the second file was opened). 28 """ 29 30 # pylint: disable=super-init-not-called 31 def __init__(self, filename, offset, length): 32 """Initializes the FilePart. 33 34 Args: 35 filename: The name of the existing file, of which this object represents 36 a part. 37 offset: The position (in bytes) in the original file that corresponds to 38 the first byte of the FilePart. 39 length: The total number of bytes in the FilePart. 40 """ 41 self._fp = open(filename, 'rb') 42 self.length = length 43 self._start = offset 44 self._end = self._start + self.length 45 self._fp.seek(self._start) 46 47 def __enter__(self): 48 pass 49 50 # pylint: disable=redefined-builtin 51 def __exit__(self, type, value, traceback): 52 self.close() 53 54 def tell(self): 55 return self._fp.tell() - self._start 56 57 def read(self, size=-1): 58 if size < 0: 59 size = self.length 60 size = min(size, self._end - self._fp.tell()) # Only read to our EOF 61 return self._fp.read(max(0, size)) 62 63 def seek(self, offset, whence=os.SEEK_SET): 64 if whence == os.SEEK_END: 65 return self._fp.seek(offset + self._end) 66 elif whence == os.SEEK_CUR: 67 return self._fp.seek(offset, whence) 68 else: 69 return self._fp.seek(self._start + offset) 70 71 def close(self): 72 self._fp.close() 73 74 def flush(self, size=None): 75 raise NotImplementedError('flush is not implemented in FilePart.') 76 77 def fileno(self, size=None): 78 raise NotImplementedError('fileno is not implemented in FilePart.') 79 80 def isatty(self, size=None): 81 raise NotImplementedError('isatty is not implemented in FilePart.') 82 83 def next(self, size=None): 84 raise NotImplementedError('next is not implemented in FilePart.') 85 86 def readline(self, size=None): 87 raise NotImplementedError('readline is not implemented in FilePart.') 88 89 def readlines(self, size=None): 90 raise NotImplementedError('readlines is not implemented in FilePart.') 91 92 def xreadlines(self, size=None): 93 raise NotImplementedError('xreadlines is not implemented in FilePart.') 94 95 def truncate(self, size=None): 96 raise NotImplementedError('truncate is not implemented in FilePart.') 97 98 def write(self, size=None): 99 raise NotImplementedError('write is not implemented in FilePart.') 100 101 def writelines(self, size=None): 102 raise NotImplementedError('writelines is not implemented in FilePart.') 103