unreader.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. # -*- coding: utf-8 -
  2. #
  3. # This file is part of gunicorn released under the MIT license.
  4. # See the NOTICE for more information.
  5. import io
  6. import os
  7. # Classes that can undo reading data from
  8. # a given type of data source.
  9. class Unreader(object):
  10. def __init__(self):
  11. self.buf = io.BytesIO()
  12. def chunk(self):
  13. raise NotImplementedError()
  14. def read(self, size=None):
  15. if size is not None and not isinstance(size, int):
  16. raise TypeError("size parameter must be an int or long.")
  17. if size is not None:
  18. if size == 0:
  19. return b""
  20. if size < 0:
  21. size = None
  22. self.buf.seek(0, os.SEEK_END)
  23. if size is None and self.buf.tell():
  24. ret = self.buf.getvalue()
  25. self.buf = io.BytesIO()
  26. return ret
  27. if size is None:
  28. d = self.chunk()
  29. return d
  30. while self.buf.tell() < size:
  31. chunk = self.chunk()
  32. if not chunk:
  33. ret = self.buf.getvalue()
  34. self.buf = io.BytesIO()
  35. return ret
  36. self.buf.write(chunk)
  37. data = self.buf.getvalue()
  38. self.buf = io.BytesIO()
  39. self.buf.write(data[size:])
  40. return data[:size]
  41. def unread(self, data):
  42. self.buf.seek(0, os.SEEK_END)
  43. self.buf.write(data)
  44. class SocketUnreader(Unreader):
  45. def __init__(self, sock, max_chunk=8192):
  46. super().__init__()
  47. self.sock = sock
  48. self.mxchunk = max_chunk
  49. def chunk(self):
  50. return self.sock.recv(self.mxchunk)
  51. class IterUnreader(Unreader):
  52. def __init__(self, iterable):
  53. super().__init__()
  54. self.iter = iter(iterable)
  55. def chunk(self):
  56. if not self.iter:
  57. return b""
  58. try:
  59. return next(self.iter)
  60. except StopIteration:
  61. self.iter = None
  62. return b""