limitreader.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. # ============================================================================
  2. class LimitReader(object):
  3. """
  4. A reader which will not read more than specified limit
  5. """
  6. def __init__(self, stream, limit):
  7. self.stream = stream
  8. self.limit = limit
  9. self._orig_limit = limit
  10. def _update(self, buff):
  11. length = len(buff)
  12. self.limit -= length
  13. return buff
  14. def read(self, length=None):
  15. if length is not None:
  16. length = min(length, self.limit)
  17. else:
  18. length = self.limit
  19. if length == 0:
  20. return b''
  21. buff = self.stream.read(length)
  22. return self._update(buff)
  23. def readline(self, length=None):
  24. if length is not None:
  25. length = min(length, self.limit)
  26. else:
  27. length = self.limit
  28. if length == 0:
  29. return b''
  30. buff = self.stream.readline(length)
  31. return self._update(buff)
  32. def close(self):
  33. self.stream.close()
  34. def tell(self):
  35. # implement our own tell
  36. return self._orig_limit - self.limit
  37. @staticmethod
  38. def wrap_stream(stream, content_length):
  39. """
  40. If given content_length is an int > 0, wrap the stream
  41. in a LimitReader. Otherwise, return the stream unaltered
  42. """
  43. try:
  44. content_length = int(content_length)
  45. if content_length >= 0:
  46. # optimize: if already a LimitStream, set limit to
  47. # the smaller of the two limits
  48. if isinstance(stream, LimitReader):
  49. stream.limit = min(stream.limit, content_length)
  50. else:
  51. stream = LimitReader(stream, content_length)
  52. except (ValueError, TypeError):
  53. pass
  54. return stream