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