"Fossies" - the Fresh Open Source Software Archive 
Member "polysh-polysh-0.13/polysh/buffered_dispatcher.py" (11 May 2020, 3160 Bytes) of package /linux/privat/polysh-polysh-0.13.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style:
standard) with prefixed line numbers.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "buffered_dispatcher.py" see the
Fossies "Dox" file reference documentation.
1 """Polysh - Buffered Dispatcher Class
2
3 Copyright (c) 2006 Guillaume Chazarain <guichaz@gmail.com>
4 Copyright (c) 2018 InnoGames GmbH
5 """
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 import asyncore
20 import errno
21
22 from polysh.console import console_output
23
24
25 class BufferedDispatcher(asyncore.file_dispatcher):
26 """A dispatcher with a write buffer to allow asynchronous writers, and a
27 read buffer to permit line oriented manipulations"""
28
29 # 1 MiB should be enough for everybody
30 MAX_BUFFER_SIZE = 1 * 1024 * 1024
31
32 def __init__(self, fd: int) -> None:
33 asyncore.file_dispatcher.__init__(self, fd)
34 self.fd = fd
35 self.read_buffer = b''
36 self.write_buffer = b''
37
38 def handle_read(self) -> None:
39 self._handle_read_chunk()
40
41 def _handle_read_chunk(self) -> bytes:
42 """Some data can be read"""
43 new_data = b''
44 buffer_length = len(self.read_buffer)
45 try:
46 while buffer_length < self.MAX_BUFFER_SIZE:
47 try:
48 piece = self.recv(4096)
49 except OSError as e:
50 if e.errno == errno.EAGAIN:
51 # End of the available data
52 break
53 elif e.errno == errno.EIO and new_data:
54 # Hopefully we could read an error message before the
55 # actual termination
56 break
57 else:
58 raise
59
60 if not piece:
61 # A closed connection is indicated by signaling a read
62 # condition, and having recv() return 0.
63 break
64
65 new_data += piece
66 buffer_length += len(piece)
67
68 finally:
69 new_data = new_data.replace(b'\r', b'\n')
70 self.read_buffer += new_data
71 return new_data
72
73 def readable(self) -> bool:
74 """No need to ask data if our buffer is already full"""
75 return len(self.read_buffer) < self.MAX_BUFFER_SIZE
76
77 def writable(self) -> bool:
78 """Do we have something to write?"""
79 return self.write_buffer != b''
80
81 def dispatch_write(self, buf: bytes) -> bool:
82 """Augment the buffer with stuff to write when possible"""
83 self.write_buffer += buf
84 if len(self.write_buffer) > self.MAX_BUFFER_SIZE:
85 console_output('Buffer too big ({:d}) for {}\n'.format(
86 len(self.write_buffer), str(self)).encode())
87 raise asyncore.ExitNow(1)
88 return True