Skip to content

Commit ee4bb8f

Browse files
ziesemerdpgeorge
authored andcommitted
aiorepl: Optimize sys.stdout.write calls.
- aiorepl.mpy: 3,152 -> 2,955 bytes (-197 bytes, -6.3%) - Bump patch version to 0.2.4. Signed-off-by: Mark A. Ziesemer <online@mark.ziesemer.com>
1 parent 585e82e commit ee4bb8f

2 files changed

Lines changed: 50 additions & 49 deletions

File tree

micropython/aiorepl/aiorepl.py

Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,10 @@ async def task(g=None, prompt="--> "):
106106
hist_n = 0 # Number of history entries.
107107
c = 0 # ord of most recent character.
108108
t = 0 # timestamp of most recent character.
109+
write = sys.stdout.write
109110
while True:
110111
hist_b = 0 # How far back in the history are we currently.
111-
sys.stdout.write(prompt)
112+
write(prompt)
112113
cmd: str = ""
113114
paste = False
114115
curs = 0 # cursor offset from end of cmd buffer
@@ -125,7 +126,7 @@ async def task(g=None, prompt="--> "):
125126
# LF or CR (handle both for raw terminal mode compatibility)
126127
if paste:
127128
# In paste mode, preserve the actual character
128-
sys.stdout.write(b)
129+
write(b)
129130
cmd += b
130131
continue
131132
# Handle various newline sequences to avoid double-execution:
@@ -140,9 +141,9 @@ async def task(g=None, prompt="--> "):
140141
continue
141142
if curs:
142143
# move cursor to end of the line
143-
sys.stdout.write("\x1b[{}C".format(curs))
144+
write("\x1b[{}C".format(curs))
144145
curs = 0
145-
sys.stdout.write("\n")
146+
write("\n")
146147
if cmd:
147148
# Push current command.
148149
hist[hist_i] = cmd
@@ -152,22 +153,20 @@ async def task(g=None, prompt="--> "):
152153

153154
result = await execute(cmd, g, s)
154155
if result is not None:
155-
sys.stdout.write(repr(result))
156-
sys.stdout.write("\n")
156+
write(repr(result))
157+
write("\n")
157158
break
158159
elif c == 0x08 or c == 0x7F:
159160
# Backspace.
160161
if cmd:
161162
if curs:
162163
cmd = "".join((cmd[: -curs - 1], cmd[-curs:]))
163-
sys.stdout.write(
164-
"\x08\x1b[K"
165-
) # move cursor back, erase to end of line
166-
sys.stdout.write(cmd[-curs:]) # redraw line
167-
sys.stdout.write("\x1b[{}D".format(curs)) # reset cursor location
164+
write("\x08\x1b[K") # move cursor back, erase to end of line
165+
write(cmd[-curs:]) # redraw line
166+
write("\x1b[{}D".format(curs)) # reset cursor location
168167
else:
169168
cmd = cmd[:-1]
170-
sys.stdout.write("\x08 \x08")
169+
write("\x08 \x08")
171170
elif c == CHAR_CTRL_A:
172171
raw_repl(sys.stdin, g)
173172
break
@@ -176,22 +175,22 @@ async def task(g=None, prompt="--> "):
176175
elif c == CHAR_CTRL_C:
177176
if paste:
178177
break
179-
sys.stdout.write("\n")
178+
write("\n")
180179
break
181180
elif c == CHAR_CTRL_D:
182181
if paste:
183182
result = await execute(cmd, g, s)
184183
if result is not None:
185-
sys.stdout.write(repr(result))
186-
sys.stdout.write("\n")
184+
write(repr(result))
185+
write("\n")
187186
break
188187

189-
sys.stdout.write("\n")
188+
write("\n")
190189
# Shutdown asyncio.
191190
asyncio.new_event_loop()
192191
return
193192
elif c == CHAR_CTRL_E:
194-
sys.stdout.write("paste mode; Ctrl-C to cancel, Ctrl-D to finish\n===\n")
193+
write("paste mode; Ctrl-C to cancel, Ctrl-D to finish\n===\n")
195194
paste = True
196195
elif c == 0x1B:
197196
# Start of escape sequence.
@@ -201,55 +200,56 @@ async def task(g=None, prompt="--> "):
201200
hist[(hist_i - hist_b) % _HISTORY_LIMIT] = cmd
202201
# Clear current command.
203202
b = "\x08" * len(cmd)
204-
sys.stdout.write(b)
205-
sys.stdout.write(" " * len(cmd))
206-
sys.stdout.write(b)
203+
write(b)
204+
write(" " * len(cmd))
205+
write(b)
207206
# Go backwards or forwards in the history.
208207
if key == "[A":
209208
hist_b = min(hist_n, hist_b + 1)
210209
else:
211210
hist_b = max(0, hist_b - 1)
212211
# Update current command.
213212
cmd = hist[(hist_i - hist_b) % _HISTORY_LIMIT]
214-
sys.stdout.write(cmd)
213+
write(cmd)
215214
elif key == "[D": # left
216215
if curs < len(cmd) - 1:
217216
curs += 1
218-
sys.stdout.write("\x1b")
219-
sys.stdout.write(key)
217+
write("\x1b")
218+
write(key)
220219
elif key == "[C": # right
221220
if curs:
222221
curs -= 1
223-
sys.stdout.write("\x1b")
224-
sys.stdout.write(key)
222+
write("\x1b")
223+
write(key)
225224
elif key == "[H": # home
226225
pcurs = curs
227226
curs = len(cmd)
228-
sys.stdout.write("\x1b[{}D".format(curs - pcurs)) # move cursor left
227+
write("\x1b[{}D".format(curs - pcurs)) # move cursor left
229228
elif key == "[F": # end
230229
pcurs = curs
231230
curs = 0
232-
sys.stdout.write("\x1b[{}C".format(pcurs)) # move cursor right
231+
write("\x1b[{}C".format(pcurs)) # move cursor right
233232
else:
234-
# sys.stdout.write("\\x")
235-
# sys.stdout.write(hex(c))
233+
# write("\\x")
234+
# write(hex(c))
236235
pass
237236
else:
238237
if curs:
239238
# inserting into middle of line
240239
cmd = "".join((cmd[:-curs], b, cmd[-curs:]))
241-
sys.stdout.write(cmd[-curs - 1 :]) # redraw line to end
242-
sys.stdout.write("\x1b[{}D".format(curs)) # reset cursor location
240+
write(cmd[-curs - 1 :]) # redraw line to end
241+
write("\x1b[{}D".format(curs)) # reset cursor location
243242
else:
244-
sys.stdout.write(b)
243+
write(b)
245244
cmd += b
246245
finally:
247246
micropython.kbd_intr(3)
248247

249248

250249
def raw_paste(s, window=512):
251-
sys.stdout.write("R\x01") # supported
252-
sys.stdout.write(bytearray([window & 0xFF, window >> 8, 0x01]).decode())
250+
write = sys.stdout.write
251+
write("R\x01") # supported
252+
write(bytearray([window & 0xFF, window >> 8, 0x01]).decode())
253253
eof = False
254254
idx = 0
255255
buff = bytearray(window)
@@ -260,7 +260,7 @@ def raw_paste(s, window=512):
260260
c = ord(b)
261261
if c == CHAR_CTRL_C or c == CHAR_CTRL_D:
262262
# end of file
263-
sys.stdout.write(chr(CHAR_CTRL_D))
263+
write(chr(CHAR_CTRL_D))
264264
if c == CHAR_CTRL_C:
265265
raise KeyboardInterrupt
266266
file += buff[:idx]
@@ -270,7 +270,7 @@ def raw_paste(s, window=512):
270270

271271
if not eof:
272272
file += buff
273-
sys.stdout.write("\x01") # indicate window available to host
273+
write("\x01") # indicate window available to host
274274

275275
return file
276276

@@ -283,11 +283,12 @@ def raw_repl(s, g: dict):
283283
"""
284284
heading = "raw REPL; CTRL-B to exit\n"
285285
line = ""
286-
sys.stdout.write(heading)
286+
write = sys.stdout.write
287+
write(heading)
287288

288289
while True:
289290
line = ""
290-
sys.stdout.write(">")
291+
write(">")
291292
while True:
292293
b = s.read(1)
293294
c = ord(b)
@@ -301,20 +302,20 @@ def raw_repl(s, g: dict):
301302
break
302303
else:
303304
# reset raw REPL
304-
sys.stdout.write(heading)
305-
sys.stdout.write(">")
305+
write(heading)
306+
write(">")
306307
continue
307308
elif c == CHAR_CTRL_B:
308309
# exit raw REPL
309-
sys.stdout.write("\n")
310+
write("\n")
310311
return 0
311312
elif c == CHAR_CTRL_C:
312313
# clear line
313314
line = ""
314315
elif c == CHAR_CTRL_D:
315316
# entry finished
316317
# indicate reception of command
317-
sys.stdout.write("OK")
318+
write("OK")
318319
break
319320
else:
320321
# let through any other raw 8-bit value
@@ -323,16 +324,16 @@ def raw_repl(s, g: dict):
323324
if len(line) == 0:
324325
# Normally used to trigger soft-reset but stay in raw mode.
325326
# Fake it for aiorepl / mpremote.
326-
sys.stdout.write("Ignored: soft reboot\n")
327-
sys.stdout.write(heading)
327+
write("Ignored: soft reboot\n")
328+
write(heading)
328329

329330
try:
330331
result = exec(line, g)
331332
if result is not None:
332-
sys.stdout.write(repr(result))
333-
sys.stdout.write(chr(CHAR_CTRL_D))
333+
write(repr(result))
334+
write(chr(CHAR_CTRL_D))
334335
except Exception as ex:
335336
print(line)
336-
sys.stdout.write(chr(CHAR_CTRL_D))
337+
write(chr(CHAR_CTRL_D))
337338
sys.print_exception(ex, sys.stdout)
338-
sys.stdout.write(chr(CHAR_CTRL_D))
339+
write(chr(CHAR_CTRL_D))

micropython/aiorepl/manifest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
metadata(
2-
version="0.2.3",
2+
version="0.2.4",
33
description="Provides an asynchronous REPL that can run concurrently with an asyncio, also allowing await expressions.",
44
)
55

0 commit comments

Comments
 (0)