File: makefile.py

package info (click to toggle)
python-cheroot 6.5.4%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 504 kB
  • sloc: python: 4,648; makefile: 14; sh: 2
file content (418 lines) | stat: -rw-r--r-- 15,426 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
"""Socket file object."""

from __future__ import absolute_import, division, print_function
__metaclass__ = type

import socket

try:
    # prefer slower Python-based io module
    import _pyio as io
except ImportError:
    # Python 2.6
    import io

import six

from . import errors
from ._compat import extract_bytes, memoryview


# Write only 16K at a time to sockets
SOCK_WRITE_BLOCKSIZE = 16384


class BufferedWriter(io.BufferedWriter):
    """Faux file object attached to a socket object."""

    def write(self, b):
        """Write bytes to buffer."""
        self._checkClosed()
        if isinstance(b, str):
            raise TypeError("can't write str to binary stream")

        with self._write_lock:
            self._write_buf.extend(b)
            self._flush_unlocked()
            return len(b)

    def _flush_unlocked(self):
        self._checkClosed('flush of closed file')
        while self._write_buf:
            try:
                # ssl sockets only except 'bytes', not bytearrays
                # so perhaps we should conditionally wrap this for perf?
                n = self.raw.write(bytes(self._write_buf))
            except io.BlockingIOError as e:
                n = e.characters_written
            del self._write_buf[:n]


class MakeFile_PY2(getattr(socket, '_fileobject', object)):
    """Faux file object attached to a socket object."""

    def __init__(self, *args, **kwargs):
        """Initialize faux file object."""
        self.bytes_read = 0
        self.bytes_written = 0
        socket._fileobject.__init__(self, *args, **kwargs)
        self._refcount = 0

    def _reuse(self):
        self._refcount += 1

    def _drop(self):
        if self._refcount < 0:
            self.close()
        else:
            self._refcount -= 1

    def write(self, data):
        """Sendall for non-blocking sockets."""
        bytes_sent = 0
        data_mv = memoryview(data)
        payload_size = len(data_mv)
        while bytes_sent < payload_size:
            try:
                bytes_sent += self.send(
                    data_mv[bytes_sent:bytes_sent + SOCK_WRITE_BLOCKSIZE]
                )
            except socket.error as e:
                if e.args[0] not in errors.socket_errors_nonblocking:
                    raise

    def send(self, data):
        """Send some part of message to the socket."""
        bytes_sent = self._sock.send(extract_bytes(data))
        self.bytes_written += bytes_sent
        return bytes_sent

    def flush(self):
        """Write all data from buffer to socket and reset write buffer."""
        if self._wbuf:
            buffer = ''.join(self._wbuf)
            self._wbuf = []
            self.write(buffer)

    def recv(self, size):
        """Receive message of a size from the socket."""
        while True:
            try:
                data = self._sock.recv(size)
                self.bytes_read += len(data)
                return data
            except socket.error as e:
                what = (
                    e.args[0] not in errors.socket_errors_nonblocking
                    and e.args[0] not in errors.socket_error_eintr
                )
                if what:
                    raise

    class FauxSocket:
        """Faux socket with the minimal interface required by pypy."""

        def _reuse(self):
            pass

    _fileobject_uses_str_type = six.PY2 and isinstance(
        socket._fileobject(FauxSocket())._rbuf, six.string_types)

    # FauxSocket is no longer needed
    del FauxSocket

    if not _fileobject_uses_str_type:
        def read(self, size=-1):
            """Read data from the socket to buffer."""
            # Use max, disallow tiny reads in a loop as they are very
            # inefficient.
            # We never leave read() with any leftover data from a new recv()
            # call in our internal buffer.
            rbufsize = max(self._rbufsize, self.default_bufsize)
            # Our use of StringIO rather than lists of string objects returned
            # by recv() minimizes memory usage and fragmentation that occurs
            # when rbufsize is large compared to the typical return value of
            # recv().
            buf = self._rbuf
            buf.seek(0, 2)  # seek end
            if size < 0:
                # Read until EOF
                # reset _rbuf.  we consume it via buf.
                self._rbuf = io.BytesIO()
                while True:
                    data = self.recv(rbufsize)
                    if not data:
                        break
                    buf.write(data)
                return buf.getvalue()
            else:
                # Read until size bytes or EOF seen, whichever comes first
                buf_len = buf.tell()
                if buf_len >= size:
                    # Already have size bytes in our buffer?  Extract and
                    # return.
                    buf.seek(0)
                    rv = buf.read(size)
                    self._rbuf = io.BytesIO()
                    self._rbuf.write(buf.read())
                    return rv

                # reset _rbuf.  we consume it via buf.
                self._rbuf = io.BytesIO()
                while True:
                    left = size - buf_len
                    # recv() will malloc the amount of memory given as its
                    # parameter even though it often returns much less data
                    # than that.  The returned data string is short lived
                    # as we copy it into a StringIO and free it.  This avoids
                    # fragmentation issues on many platforms.
                    data = self.recv(left)
                    if not data:
                        break
                    n = len(data)
                    if n == size and not buf_len:
                        # Shortcut.  Avoid buffer data copies when:
                        # - We have no data in our buffer.
                        # AND
                        # - Our call to recv returned exactly the
                        #   number of bytes we were asked to read.
                        return data
                    if n == left:
                        buf.write(data)
                        del data  # explicit free
                        break
                    assert n <= left, 'recv(%d) returned %d bytes' % (left, n)
                    buf.write(data)
                    buf_len += n
                    del data  # explicit free
                    # assert buf_len == buf.tell()
                return buf.getvalue()

        def readline(self, size=-1):
            """Read line from the socket to buffer."""
            buf = self._rbuf
            buf.seek(0, 2)  # seek end
            if buf.tell() > 0:
                # check if we already have it in our buffer
                buf.seek(0)
                bline = buf.readline(size)
                if bline.endswith('\n') or len(bline) == size:
                    self._rbuf = io.BytesIO()
                    self._rbuf.write(buf.read())
                    return bline
                del bline
            if size < 0:
                # Read until \n or EOF, whichever comes first
                if self._rbufsize <= 1:
                    # Speed up unbuffered case
                    buf.seek(0)
                    buffers = [buf.read()]
                    # reset _rbuf.  we consume it via buf.
                    self._rbuf = io.BytesIO()
                    data = None
                    recv = self.recv
                    while data != '\n':
                        data = recv(1)
                        if not data:
                            break
                        buffers.append(data)
                    return ''.join(buffers)

                buf.seek(0, 2)  # seek end
                # reset _rbuf.  we consume it via buf.
                self._rbuf = io.BytesIO()
                while True:
                    data = self.recv(self._rbufsize)
                    if not data:
                        break
                    nl = data.find('\n')
                    if nl >= 0:
                        nl += 1
                        buf.write(data[:nl])
                        self._rbuf.write(data[nl:])
                        del data
                        break
                    buf.write(data)
                return buf.getvalue()
            else:
                # Read until size bytes or \n or EOF seen, whichever comes
                # first
                buf.seek(0, 2)  # seek end
                buf_len = buf.tell()
                if buf_len >= size:
                    buf.seek(0)
                    rv = buf.read(size)
                    self._rbuf = io.BytesIO()
                    self._rbuf.write(buf.read())
                    return rv
                # reset _rbuf.  we consume it via buf.
                self._rbuf = io.BytesIO()
                while True:
                    data = self.recv(self._rbufsize)
                    if not data:
                        break
                    left = size - buf_len
                    # did we just receive a newline?
                    nl = data.find('\n', 0, left)
                    if nl >= 0:
                        nl += 1
                        # save the excess data to _rbuf
                        self._rbuf.write(data[nl:])
                        if buf_len:
                            buf.write(data[:nl])
                            break
                        else:
                            # Shortcut.  Avoid data copy through buf when
                            # returning a substring of our first recv().
                            return data[:nl]
                    n = len(data)
                    if n == size and not buf_len:
                        # Shortcut.  Avoid data copy through buf when
                        # returning exactly all of our first recv().
                        return data
                    if n >= left:
                        buf.write(data[:left])
                        self._rbuf.write(data[left:])
                        break
                    buf.write(data)
                    buf_len += n
                    # assert buf_len == buf.tell()
                return buf.getvalue()
    else:
        def read(self, size=-1):
            """Read data from the socket to buffer."""
            if size < 0:
                # Read until EOF
                buffers = [self._rbuf]
                self._rbuf = ''
                if self._rbufsize <= 1:
                    recv_size = self.default_bufsize
                else:
                    recv_size = self._rbufsize

                while True:
                    data = self.recv(recv_size)
                    if not data:
                        break
                    buffers.append(data)
                return ''.join(buffers)
            else:
                # Read until size bytes or EOF seen, whichever comes first
                data = self._rbuf
                buf_len = len(data)
                if buf_len >= size:
                    self._rbuf = data[size:]
                    return data[:size]
                buffers = []
                if data:
                    buffers.append(data)
                self._rbuf = ''
                while True:
                    left = size - buf_len
                    recv_size = max(self._rbufsize, left)
                    data = self.recv(recv_size)
                    if not data:
                        break
                    buffers.append(data)
                    n = len(data)
                    if n >= left:
                        self._rbuf = data[left:]
                        buffers[-1] = data[:left]
                        break
                    buf_len += n
                return ''.join(buffers)

        def readline(self, size=-1):
            """Read line from the socket to buffer."""
            data = self._rbuf
            if size < 0:
                # Read until \n or EOF, whichever comes first
                if self._rbufsize <= 1:
                    # Speed up unbuffered case
                    assert data == ''
                    buffers = []
                    while data != '\n':
                        data = self.recv(1)
                        if not data:
                            break
                        buffers.append(data)
                    return ''.join(buffers)
                nl = data.find('\n')
                if nl >= 0:
                    nl += 1
                    self._rbuf = data[nl:]
                    return data[:nl]
                buffers = []
                if data:
                    buffers.append(data)
                self._rbuf = ''
                while True:
                    data = self.recv(self._rbufsize)
                    if not data:
                        break
                    buffers.append(data)
                    nl = data.find('\n')
                    if nl >= 0:
                        nl += 1
                        self._rbuf = data[nl:]
                        buffers[-1] = data[:nl]
                        break
                return ''.join(buffers)
            else:
                # Read until size bytes or \n or EOF seen, whichever comes
                # first
                nl = data.find('\n', 0, size)
                if nl >= 0:
                    nl += 1
                    self._rbuf = data[nl:]
                    return data[:nl]
                buf_len = len(data)
                if buf_len >= size:
                    self._rbuf = data[size:]
                    return data[:size]
                buffers = []
                if data:
                    buffers.append(data)
                self._rbuf = ''
                while True:
                    data = self.recv(self._rbufsize)
                    if not data:
                        break
                    buffers.append(data)
                    left = size - buf_len
                    nl = data.find('\n', 0, left)
                    if nl >= 0:
                        nl += 1
                        self._rbuf = data[nl:]
                        buffers[-1] = data[:nl]
                        break
                    n = len(data)
                    if n >= left:
                        self._rbuf = data[left:]
                        buffers[-1] = data[:left]
                        break
                    buf_len += n
                return ''.join(buffers)


if six.PY3:
    class StreamReader(io.BufferedReader):
        """Socket stream reader."""

        def __init__(self, sock, mode='r', bufsize=io.DEFAULT_BUFFER_SIZE):
            """Initialize socket stream reader."""
            super().__init__(socket.SocketIO(sock, mode), bufsize)

    class StreamWriter(BufferedWriter):
        """Socket stream writer."""

        def __init__(self, sock, mode='w', bufsize=io.DEFAULT_BUFFER_SIZE):
            """Initialize socket stream writer."""
            super().__init__(socket.SocketIO(sock, mode), bufsize)

    def MakeFile(sock, mode='r', bufsize=io.DEFAULT_BUFFER_SIZE):
        """File object attached to a socket object."""
        cls = StreamReader if 'r' in mode else StreamWriter
        return cls(sock, mode, bufsize)
else:
    StreamReader = StreamWriter = MakeFile = MakeFile_PY2