serverwatcher 6.dev56__tar.gz → 6.dev58__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. {serverwatcher-6.dev56/src/serverwatcher.egg-info → serverwatcher-6.dev58}/PKG-INFO +6 -6
  2. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/README.md +1 -1
  3. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/pyproject.toml +5 -5
  4. {serverwatcher-6.dev56 → serverwatcher-6.dev58/src/serverwatcher.egg-info}/PKG-INFO +6 -6
  5. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher.egg-info/SOURCES.txt +0 -1
  6. serverwatcher-6.dev56/src/serverwatcher/livecli.py +0 -447
  7. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/LICENSE +0 -0
  8. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/setup.cfg +0 -0
  9. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/__init__.py +0 -0
  10. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/__main__.py +0 -0
  11. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/configclasses/__init__.py +0 -0
  12. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/configclasses/config.py +0 -0
  13. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/configclasses/messages.py +0 -0
  14. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/configclasses/watcher.py +0 -0
  15. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/defaultconfigs/config.yaml +0 -0
  16. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/defaultconfigs/messages.yaml +0 -0
  17. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/defaultconfigs/watcher.yaml +0 -0
  18. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/tests/test.py +0 -0
  19. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/tests/test2.py +0 -0
  20. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/validator.py +0 -0
  21. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/watcher.py +0 -0
  22. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher/watchercli.py +0 -0
  23. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher.egg-info/dependency_links.txt +0 -0
  24. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher.egg-info/requires.txt +0 -0
  25. {serverwatcher-6.dev56 → serverwatcher-6.dev58}/src/serverwatcher.egg-info/top_level.txt +0 -0
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: serverwatcher
3
- Version: 6.dev56
3
+ Version: 6.dev58
4
4
  Summary: A HungerLib-powered Minecraft server automation engine.
5
5
  Author: iFamished
6
6
  License: GPL-3.0
7
- Project-URL: Homepage, https://github.com/iFamishedX/ServerWatcher
8
- Project-URL: Documentation, https://github.com/iFamishedX/ServerWatcher
9
- Project-URL: Source, https://github.com/iFamishedX/ServerWatcher
10
- Project-URL: Issues, https://github.com/iFamishedX/ServerWatcher/issues
7
+ Project-URL: Homepage, https://github.com/iFamished/ServerWatcher
8
+ Project-URL: Documentation, https://github.com/iFamished/ServerWatcher
9
+ Project-URL: Source, https://github.com/iFamished/ServerWatcher
10
+ Project-URL: Issues, https://github.com/iFamished/ServerWatcher/issues
11
11
  Keywords: pterodactyl,minecraft,automation,server-management,hungerlib,hungernet
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.10
@@ -51,7 +51,7 @@ A highly configurable Minecraft server monitoring and restart engine for HungerB
51
51
  - Optional. Only necessary if you want to use file logging.
52
52
 
53
53
  ## Installation
54
- - Download the [**ServerWatcher Pterodactyl egg**](https://github.com/iFamishedX/ServerWatcher/blob/main/eggs/serverwatcher.json)
54
+ - Download the [**ServerWatcher Pterodactyl egg**](https://github.com/iFamished/ServerWatcher/blob/main/eggs/serverwatcher.json)
55
55
  - Import it into your desired nest in your panel
56
56
  - Create a server with the egg selected
57
57
  - Start the server and wait for instalation and file generation to finish
@@ -22,7 +22,7 @@ A highly configurable Minecraft server monitoring and restart engine for HungerB
22
22
  - Optional. Only necessary if you want to use file logging.
23
23
 
24
24
  ## Installation
25
- - Download the [**ServerWatcher Pterodactyl egg**](https://github.com/iFamishedX/ServerWatcher/blob/main/eggs/serverwatcher.json)
25
+ - Download the [**ServerWatcher Pterodactyl egg**](https://github.com/iFamished/ServerWatcher/blob/main/eggs/serverwatcher.json)
26
26
  - Import it into your desired nest in your panel
27
27
  - Create a server with the egg selected
28
28
  - Start the server and wait for instalation and file generation to finish
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "serverwatcher"
10
- version = "6-dev.56"
10
+ version = "6-dev.58"
11
11
  description = "A HungerLib-powered Minecraft server automation engine."
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.14"
@@ -44,10 +44,10 @@ classifiers = [
44
44
  text = "GPL-3.0"
45
45
 
46
46
  [project.urls]
47
- Homepage = "https://github.com/iFamishedX/ServerWatcher"
48
- Documentation = "https://github.com/iFamishedX/ServerWatcher"
49
- Source = "https://github.com/iFamishedX/ServerWatcher"
50
- Issues = "https://github.com/iFamishedX/ServerWatcher/issues"
47
+ Homepage = "https://github.com/iFamished/ServerWatcher"
48
+ Documentation = "https://github.com/iFamished/ServerWatcher"
49
+ Source = "https://github.com/iFamished/ServerWatcher"
50
+ Issues = "https://github.com/iFamished/ServerWatcher/issues"
51
51
 
52
52
  [tool.setuptools.packages.find]
53
53
  where = [
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: serverwatcher
3
- Version: 6.dev56
3
+ Version: 6.dev58
4
4
  Summary: A HungerLib-powered Minecraft server automation engine.
5
5
  Author: iFamished
6
6
  License: GPL-3.0
7
- Project-URL: Homepage, https://github.com/iFamishedX/ServerWatcher
8
- Project-URL: Documentation, https://github.com/iFamishedX/ServerWatcher
9
- Project-URL: Source, https://github.com/iFamishedX/ServerWatcher
10
- Project-URL: Issues, https://github.com/iFamishedX/ServerWatcher/issues
7
+ Project-URL: Homepage, https://github.com/iFamished/ServerWatcher
8
+ Project-URL: Documentation, https://github.com/iFamished/ServerWatcher
9
+ Project-URL: Source, https://github.com/iFamished/ServerWatcher
10
+ Project-URL: Issues, https://github.com/iFamished/ServerWatcher/issues
11
11
  Keywords: pterodactyl,minecraft,automation,server-management,hungerlib,hungernet
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.10
@@ -51,7 +51,7 @@ A highly configurable Minecraft server monitoring and restart engine for HungerB
51
51
  - Optional. Only necessary if you want to use file logging.
52
52
 
53
53
  ## Installation
54
- - Download the [**ServerWatcher Pterodactyl egg**](https://github.com/iFamishedX/ServerWatcher/blob/main/eggs/serverwatcher.json)
54
+ - Download the [**ServerWatcher Pterodactyl egg**](https://github.com/iFamished/ServerWatcher/blob/main/eggs/serverwatcher.json)
55
55
  - Import it into your desired nest in your panel
56
56
  - Create a server with the egg selected
57
57
  - Start the server and wait for instalation and file generation to finish
@@ -3,7 +3,6 @@ README.md
3
3
  pyproject.toml
4
4
  src/serverwatcher/__init__.py
5
5
  src/serverwatcher/__main__.py
6
- src/serverwatcher/livecli.py
7
6
  src/serverwatcher/validator.py
8
7
  src/serverwatcher/watcher.py
9
8
  src/serverwatcher/watchercli.py
@@ -1,447 +0,0 @@
1
- from dataclasses import dataclass
2
- import cmd
3
- import sys
4
- import termios
5
- import tty
6
- import asyncio
7
- import inspect
8
-
9
- from mapres import res, ascii_colors, setGlobalMaps
10
-
11
- setGlobalMaps(ascii_colors)
12
-
13
-
14
- COMMANDS = {}
15
-
16
- @dataclass
17
- class ParamSpec:
18
- name: str
19
- type_: type
20
- default: object
21
- func: callable
22
- desc: str | None
23
-
24
- @dataclass
25
- class FlagSpec:
26
- name: str
27
- func: callable
28
- desc: str | None
29
-
30
- @dataclass
31
- class ArgMeta:
32
- name: str
33
- params: list[str]
34
- flags: list[str]
35
- required_params: set[str]
36
- required_flags: set[str]
37
-
38
- class ChildSpec:
39
- def __init__(self, parent, name, func):
40
- self.parent = parent
41
- self.name = name
42
- self.func = func
43
- self.params = {}
44
- self.flags = {}
45
- self.args_meta = {}
46
- self.desc = self._doc(func)
47
- self._extract_args_block()
48
- self._parse_args_meta()
49
- self._infer_arg_requirement()
50
-
51
- def _doc(self, f):
52
- d = f.__doc__
53
- return d.strip().splitlines()[0].strip() if d else None
54
-
55
- def _extract_args_block(self):
56
- src = inspect.getsource(self.func)
57
- lines = src.splitlines()
58
- block = []
59
- in_block = False
60
- for line in lines:
61
- s = line.strip()
62
- if s.startswith('__args__'):
63
- in_block = True
64
- continue
65
- if in_block:
66
- if s.startswith(("'''", '"""')):
67
- if not block:
68
- continue
69
- else:
70
- break
71
- block.append(line)
72
- if block:
73
- raw = '\n'.join(l.strip() for l in block)
74
- setattr(self.func, '__args__', raw)
75
-
76
- def _parse_args_meta(self):
77
- raw = getattr(self.func, '__args__', None)
78
- if not raw:
79
- return
80
- for line in raw.splitlines():
81
- s = line.strip()
82
- if not s:
83
- continue
84
- if ':' in s:
85
- arg, rest = s.split(':', 1)
86
- arg = arg.strip()
87
- tokens = [t.strip() for t in rest.split(',') if t.strip()]
88
- else:
89
- arg = s
90
- tokens = []
91
- params = []
92
- flags = []
93
- req_p = set()
94
- req_f = set()
95
- for t in tokens:
96
- required = True
97
- if t.startswith('[') and t.endswith(']'):
98
- required = False
99
- t = t[1:-1].strip()
100
- if t.startswith('--'):
101
- f = t[2:]
102
- flags.append(f)
103
- if required:
104
- req_f.add(f)
105
- else:
106
- params.append(t)
107
- if required:
108
- req_p.add(t)
109
- self.args_meta[arg] = ArgMeta(arg, params, flags, req_p, req_f)
110
-
111
- def _infer_arg_requirement(self):
112
- sig = inspect.signature(self.func)
113
- ps = list(sig.parameters.values())
114
- if len(ps) == 1:
115
- self.requires_arg = False
116
- self.optional_arg = False
117
- elif len(ps) == 2:
118
- p = ps[1]
119
- if p.default is inspect._empty:
120
- self.requires_arg = True
121
- self.optional_arg = False
122
- else:
123
- self.requires_arg = False
124
- self.optional_arg = True
125
- else:
126
- self.requires_arg = False
127
- self.optional_arg = False
128
-
129
- def param(self, name, type=str, default=None):
130
- def deco(f):
131
- py = name.replace('-', '_')
132
- d = f.__doc__.strip().splitlines()[0].strip() if f.__doc__ else None
133
- self.params[py] = ParamSpec(name, type, default, f, d)
134
- return f
135
- return deco
136
-
137
- def flag(self, name):
138
- def deco(f):
139
- py = name.replace('-', '_')
140
- d = f.__doc__.strip().splitlines()[0].strip() if f.__doc__ else None
141
- self.flags[py] = FlagSpec(name, f, d)
142
- return f
143
- return deco
144
-
145
- class CommandSpec:
146
- def __init__(self, name, func, namespace=False):
147
- self.name = name
148
- self.func = func
149
- self.children = {}
150
- self.params = {}
151
- self.flags = {}
152
- self.desc = self._doc(func)
153
-
154
- self.is_namespace = namespace
155
-
156
- def _doc(self, f):
157
- d = f.__doc__
158
- return d.strip().splitlines()[0].strip() if d else None
159
-
160
- def param(self, name, type=str, default=None):
161
- def deco(f):
162
- py = name.replace('-', '_')
163
- d = f.__doc__.strip().splitlines()[0].strip() if f.__doc__ else None
164
- self.params[py] = ParamSpec(name, type, default, f, d)
165
- return f
166
- return deco
167
-
168
- def flag(self, name):
169
- def deco(f):
170
- py = name.replace('-', '_')
171
- d = f.__doc__.strip().splitlines()[0].strip() if f.__doc__ else None
172
- self.flags[py] = FlagSpec(name, f, d)
173
- return f
174
- return deco
175
-
176
- def child(self, name):
177
- def deco(f):
178
- c = ChildSpec(self, name, f)
179
- self.children[name] = c
180
- setattr(self, name, c)
181
- return c
182
- return deco
183
-
184
- class CommandDSL:
185
- def __call__(self, name, namespace=False):
186
- def deco(f):
187
- spec = CommandSpec(name, f, namespace=namespace)
188
- COMMANDS[name] = spec
189
- return spec
190
- return deco
191
-
192
- command = CommandDSL()
193
-
194
- @dataclass
195
- class ParsedArgs:
196
- sub: str | None
197
- pos: list[str]
198
- flags: dict[str, bool]
199
- params: dict[str, str]
200
-
201
- def parse_line(raw):
202
- raw = raw.strip()
203
- if not raw:
204
- return ParsedArgs(None, [], {}, {})
205
- parts = raw.split()
206
- sub = parts[0]
207
- pos = []
208
- flags = {}
209
- params = {}
210
- for t in parts[1:]:
211
- if t.startswith('--'):
212
- flags[t[2:]] = True
213
- elif ':' in t:
214
- k, v = t.split(':', 1)
215
- params[k.lower()] = v
216
- else:
217
- pos.append(t)
218
- return ParsedArgs(sub, pos, flags, params)
219
-
220
- def help_command(cmd):
221
- lines = []
222
- d = cmd.desc or 'No description'
223
- lines.append(res(f'<bold><yellow>{cmd.name}<reset>: <gray>{d}<reset>'))
224
-
225
- if cmd.children:
226
- if cmd.is_namespace:
227
- u = res(f'<aqua>Usage:<reset> <gold>{cmd.name}<reset> <dark_gray>\\<<reset>child<dark_gray>\\><reset>')
228
- else:
229
- u = res(f'<aqua>Usage:<reset> <gold>{cmd.name}<reset> <dark_gray>[<reset>child<dark_gray>]<reset>')
230
- else:
231
- u = res(f'<aqua>Usage:<reset> <gold>{cmd.name}<reset>')
232
-
233
- if cmd.flags:
234
- u += res(' <dark_gray>[<reset>--flags<dark_gray>]<reset>')
235
-
236
- lines.append(u)
237
-
238
- if cmd.flags:
239
- lines.append('')
240
- lines.append(res('\0 <light_purple>Flags:<reset>'))
241
- for n, fs in cmd.flags.items():
242
- d = fs.desc or 'No description'
243
- lines.append(res(f'\0 <blue>--{fs.name}<reset>: <gray>{d}<reset>'))
244
-
245
- if cmd.children:
246
- lines.append('')
247
- lines.append(res('\0 <light_purple>Children:<reset>'))
248
- for n, c in cmd.children.items():
249
- cd = c.desc or 'No description'
250
- lines.append(res(f'\0 <green>{n}<reset>: <gray>{cd}<reset>'))
251
-
252
- return '\n'.join(lines)
253
-
254
- def help_child(child):
255
- lines = []
256
- d = child.desc or 'No description'
257
- p = child.parent.name
258
- lines.append(res(f'<bold><green>{child.name}<reset>: <gray>{d}<reset>'))
259
-
260
- u = res(f'<aqua>Usage:<reset> <gold>{p}<reset> <green>{child.name}<reset>')
261
- if child.requires_arg:
262
- u += res(' <dark_gray>\\<<reset>arg<dark_gray>\\><reset>')
263
- elif child.optional_arg:
264
- u += res(' <dark_gray>[<reset>arg<dark_gray>]<reset>')
265
- if child.params:
266
- u += res(' <dark_gray>[<reset>params<dark_gray>]<reset>')
267
- if child.flags:
268
- u += res(' <dark_gray>[<reset>--flags<dark_gray>]<reset>')
269
- lines.append(u)
270
-
271
- if child.args_meta:
272
- lines.append('')
273
- lines.append(res('\0 <light_purple>Args:<reset>'))
274
- for a, m in child.args_meta.items():
275
- parts = [res(f'<green>{a}<reset>')]
276
- for pn in m.params:
277
- parts.append(res(f'<dark_gray>[<reset>{pn}<dark_gray>]<reset>'))
278
- for fn in m.flags:
279
- parts.append(res(f'<dark_gray>[<reset>--{fn}<dark_gray>]<reset>'))
280
- lines.append('\0 ' + ' '.join(parts))
281
-
282
- if child.params:
283
- lines.append('')
284
- lines.append(res('\0 <light_purple>Params:<reset>'))
285
- for n, ps in child.params.items():
286
- t = ps.type_.__name__
287
- d = ps.desc or 'No description'
288
- lines.append(res(f'\0 <blue>{n}<reset> (type=<gold>{t}<reset>, default=<gray>{ps.default}<reset>): <gray>{d}<reset>'))
289
-
290
- if child.flags:
291
- lines.append('')
292
- lines.append(res('\0 <light_purple>Flags:<reset>'))
293
- for n, fs in child.flags.items():
294
- d = fs.desc or 'No description'
295
- lines.append(res(f'\0 <blue>--{fs.name}<reset>: <gray>{d}<reset>'))
296
-
297
- return '\n'.join(lines)
298
-
299
- def help_arg(child, meta):
300
- lines = []
301
- p = child.parent.name
302
- a = meta.name
303
- lines.append(res(f'<bold><aqua>{a}<reset>: <gray>Retrieve and print the {a} of the server<reset>'))
304
-
305
- u = res(f'<aqua>Usage:<reset> <gold>{p}<reset> <green>{child.name}<reset> <aqua>{a}<reset>')
306
- req = []
307
- opt = []
308
- for pn in meta.params:
309
- ps = child.params.get(pn)
310
- t = ps.type_.__name__ if ps else 'str'
311
- if pn in meta.required_params:
312
- req.append(res(f'<dark_gray>\\<<reset>{pn}:{t}<dark_gray>\\><reset>'))
313
- else:
314
- opt.append(res(f'<dark_gray>[<reset>{pn}:{t}<dark_gray>]<reset>'))
315
- if req:
316
- u += ' ' + ' '.join(req)
317
- if opt:
318
- u += ' ' + ' '.join(opt)
319
- if meta.flags:
320
- u += res(' <dark_gray>[<reset>--flags<dark_gray>]<reset>')
321
- lines.append(u)
322
-
323
- if meta.params:
324
- lines.append('')
325
- lines.append(res('\0 <light_purple>Params:<reset>'))
326
- for pn in meta.params:
327
- ps = child.params.get(pn)
328
- if not ps:
329
- continue
330
- t = ps.type_.__name__
331
- d = ps.desc or 'No description'
332
- lines.append(res(f'\0 <blue>{pn}<reset> (type=<gold>{t}<reset>, default=<gray>{ps.default}<reset>): <gray>{d}<reset>'))
333
-
334
- if meta.flags:
335
- lines.append('')
336
- lines.append(res('\0 <light_purple>Flags:<reset>'))
337
- for fn in meta.flags:
338
- fs = child.flags.get(fn)
339
- if not fs:
340
- continue
341
- d = fs.desc or 'No description'
342
- lines.append(res(f'\0 <blue>--{fn}<reset>: <gray>{d}<reset>'))
343
-
344
- return '\n'.join(lines)
345
-
346
- def dispatch(cli, line):
347
- p = parse_line(line)
348
- if not p.sub:
349
- return
350
- cmd = COMMANDS.get(p.sub)
351
- if not cmd:
352
- return cli.safePrint(res(f'<red>Error:<reset> <gray>Unknown command {p.sub}<reset>'))
353
- if 'help' in p.flags and not p.pos:
354
- return cli.safePrint(help_command(cmd))
355
- if cmd.children:
356
- if not p.pos:
357
- return cli.safePrint(res('<red>Error:<reset> <gray>Missing subcommand<reset>'))
358
- else:
359
- return cmd.func(cli)
360
- cname = p.pos[0]
361
- child = cmd.children.get(cname)
362
- if not child:
363
- return cli.safePrint(res(f'<red>Error:<reset> <gray>Unknown subcommand {cname}<reset>'))
364
- if 'help' in p.flags and len(p.pos) == 1:
365
- return cli.safePrint(help_child(child))
366
- if 'help' in p.flags and len(p.pos) >= 2:
367
- an = p.pos[1]
368
- meta = child.args_meta.get(an)
369
- if not meta:
370
- return cli.safePrint(res(f'<red>Error:<reset> <gray>Unknown argument {an}<reset>'))
371
- return cli.safePrint(help_arg(child, meta))
372
- arg = p.pos[1] if len(p.pos) > 1 else None
373
- if child.requires_arg and arg is None:
374
- return cli.safePrint(res(f'<red>Error:<reset> <gray>Subcommand {child.name} requires an argument<reset>'))
375
- g = child.func.__globals__
376
- for n, ps in child.params.items():
377
- if n in p.params:
378
- try:
379
- v = ps.type_(p.params[n])
380
- except:
381
- v = ps.default
382
- else:
383
- v = ps.default
384
- def wrap(f=ps.func, val=v):
385
- def w():
386
- return f(val)
387
- return w
388
- g[n] = wrap()
389
- for n, fs in child.flags.items():
390
- present = n in p.flags
391
- def wrap(f=fs.func, pr=present):
392
- def w():
393
- return pr
394
- return w
395
- g[n] = wrap()
396
- f = child.func
397
- if f.__code__.co_argcount >= 2:
398
- return f(cli, arg)
399
- return f(cli)
400
-
401
- class LiveCLI(cmd.Cmd):
402
- prompt = ''
403
-
404
- def safePrint(self, msg='', end='\n', write_buffer=True):
405
- text = str(msg)
406
- if write_buffer and hasattr(self, 'buffer'):
407
- buf = self.buffer
408
- if getattr(buf, 'enabled', False) and text.strip():
409
- buf.captured.append(text.rstrip('\n'))
410
- print(text, end=end)
411
-
412
- def read_line_raw(self):
413
- fd = sys.stdin.fileno()
414
- old = termios.tcgetattr(fd)
415
- try:
416
- tty.setraw(fd)
417
- chars = []
418
- while True:
419
- ch = sys.stdin.read(1)
420
- if ch in ('\r', '\n'):
421
- break
422
- chars.append(ch)
423
- return ''.join(chars)
424
- finally:
425
- termios.tcsetattr(fd, termios.TCSADRAIN, old)
426
-
427
- async def run(self):
428
- while True:
429
- line = await asyncio.to_thread(self.read_line_raw)
430
- line = line.strip()
431
- if not line:
432
- continue
433
-
434
- # buffer the command (but not view commands)
435
- buf = getattr(self, 'buffer', None)
436
- if buf is not None and getattr(buf, 'enabled', False):
437
- if not line.startswith(("view", "clear")):
438
- buf.captured.append(line)
439
-
440
- # execute command
441
- stop = await asyncio.to_thread(self.onecmd, line)
442
- self.safePrint("", write_buffer=False)
443
- if stop:
444
- break
445
-
446
- def onecmd(self, line):
447
- return dispatch(self, line)
File without changes