urwid 3.0.3__py3-none-any.whl → 3.0.5__py3-none-any.whl
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.
- urwid/__init__.py +29 -16
- urwid/display/__init__.py +53 -48
- urwid/display/_raw_display_base.py +2 -2
- urwid/display/common.py +17 -17
- urwid/display/curses.py +1 -3
- urwid/display/web.py +1 -1
- urwid/event_loop/asyncio_loop.py +3 -1
- urwid/event_loop/main_loop.py +5 -5
- urwid/font.py +6 -4
- urwid/numedit.py +65 -65
- urwid/signals.py +17 -26
- urwid/split_repr.py +9 -3
- urwid/str_util.py +90 -42
- urwid/text_layout.py +8 -6
- urwid/util.py +1 -1
- urwid/version.py +2 -2
- urwid/vterm.py +2 -2
- urwid/widget/attr_map.py +10 -10
- urwid/widget/attr_wrap.py +3 -3
- urwid/widget/big_text.py +0 -3
- urwid/widget/box_adapter.py +2 -2
- urwid/widget/divider.py +6 -6
- urwid/widget/edit.py +42 -42
- urwid/widget/filler.py +8 -8
- urwid/widget/frame.py +3 -3
- urwid/widget/line_box.py +19 -19
- urwid/widget/listbox.py +1 -1
- urwid/widget/monitored_list.py +69 -45
- urwid/widget/padding.py +20 -20
- urwid/widget/progress_bar.py +7 -7
- urwid/widget/solid_fill.py +3 -3
- urwid/widget/text.py +44 -30
- urwid/widget/widget.py +6 -6
- urwid/widget/widget_decoration.py +2 -2
- urwid/widget/wimp.py +61 -61
- {urwid-3.0.3.dist-info → urwid-3.0.5.dist-info}/METADATA +6 -5
- urwid-3.0.5.dist-info/RECORD +74 -0
- {urwid-3.0.3.dist-info → urwid-3.0.5.dist-info}/WHEEL +1 -1
- urwid-3.0.3.dist-info/RECORD +0 -74
- {urwid-3.0.3.dist-info → urwid-3.0.5.dist-info}/licenses/COPYING +0 -0
- {urwid-3.0.3.dist-info → urwid-3.0.5.dist-info}/top_level.txt +0 -0
urwid/__init__.py
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
from __future__ import annotations
|
|
23
23
|
|
|
24
|
-
import importlib
|
|
24
|
+
import importlib.util
|
|
25
25
|
import sys
|
|
26
26
|
import types
|
|
27
27
|
import typing
|
|
@@ -265,12 +265,28 @@ _moved_warn: dict[str, str] = {
|
|
|
265
265
|
}
|
|
266
266
|
# Backward compatible lazy load without any warnings
|
|
267
267
|
# Before DeprecationWarning need to start PendingDeprecationWarning process.
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
"
|
|
272
|
-
|
|
273
|
-
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def lazy_import(name: str, package: str | None = None) -> types.ModuleType:
|
|
271
|
+
"""Lazy import implementation from Python documentation.
|
|
272
|
+
|
|
273
|
+
Useful for cases where no warnings expected for moved modules.
|
|
274
|
+
"""
|
|
275
|
+
spec = importlib.util.find_spec(name, package)
|
|
276
|
+
if not spec:
|
|
277
|
+
raise ImportError(f"No module named {name!r}")
|
|
278
|
+
if not spec.loader:
|
|
279
|
+
raise ImportError(f"Module named {name!r} is invalid")
|
|
280
|
+
|
|
281
|
+
loader = importlib.util.LazyLoader(spec.loader)
|
|
282
|
+
spec.loader = loader
|
|
283
|
+
module = importlib.util.module_from_spec(spec)
|
|
284
|
+
if not package:
|
|
285
|
+
sys.modules[name] = module
|
|
286
|
+
else:
|
|
287
|
+
sys.modules[f"{package.rstrip('.')}.{name.lstrip('.')}"] = module
|
|
288
|
+
loader.exec_module(module)
|
|
289
|
+
return module
|
|
274
290
|
|
|
275
291
|
|
|
276
292
|
class _MovedModule(types.ModuleType):
|
|
@@ -293,6 +309,12 @@ class _MovedModule(types.ModuleType):
|
|
|
293
309
|
return getattr(real_module, name)
|
|
294
310
|
|
|
295
311
|
|
|
312
|
+
display_common = lazy_import("urwid.display.common")
|
|
313
|
+
raw_display = lazy_import("urwid.display.raw")
|
|
314
|
+
curses_display = lazy_import("urwid.display.curses")
|
|
315
|
+
escape = lazy_import("urwid.display.escape")
|
|
316
|
+
|
|
317
|
+
|
|
296
318
|
class _MovedModuleWarn(_MovedModule):
|
|
297
319
|
"""Special class to handle moved modules.
|
|
298
320
|
|
|
@@ -310,10 +332,6 @@ class _MovedModuleWarn(_MovedModule):
|
|
|
310
332
|
return super().__getattr__(name)
|
|
311
333
|
|
|
312
334
|
|
|
313
|
-
for _name, _module in _moved_no_warn.items():
|
|
314
|
-
_module_path = f"{__name__}.{_name}"
|
|
315
|
-
sys.modules[_module_path] = _MovedModule(_module_path, _module)
|
|
316
|
-
|
|
317
335
|
for _name, _module in _moved_warn.items():
|
|
318
336
|
_module_path = f"{__name__}.{_name}"
|
|
319
337
|
sys.modules[_module_path] = _MovedModuleWarn(_module_path, _module)
|
|
@@ -325,11 +343,6 @@ def __getattr__(name: str) -> typing.Any:
|
|
|
325
343
|
:return: attribute by name
|
|
326
344
|
:raises AttributeError: attribute is not defined for lazy load
|
|
327
345
|
"""
|
|
328
|
-
if name in _moved_no_warn:
|
|
329
|
-
mod = importlib.import_module(_moved_no_warn[name])
|
|
330
|
-
__locals[name] = mod
|
|
331
|
-
return mod
|
|
332
|
-
|
|
333
346
|
if name in _moved_warn:
|
|
334
347
|
warnings.warn(
|
|
335
348
|
f"{name} is moved to {_moved_warn[name]}",
|
urwid/display/__init__.py
CHANGED
|
@@ -2,9 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
import importlib
|
|
5
|
+
import importlib.util
|
|
6
|
+
import sys
|
|
6
7
|
import typing
|
|
7
8
|
|
|
9
|
+
from . import raw
|
|
10
|
+
from .common import (
|
|
11
|
+
BLACK,
|
|
12
|
+
BROWN,
|
|
13
|
+
DARK_BLUE,
|
|
14
|
+
DARK_CYAN,
|
|
15
|
+
DARK_GRAY,
|
|
16
|
+
DARK_GREEN,
|
|
17
|
+
DARK_MAGENTA,
|
|
18
|
+
DARK_RED,
|
|
19
|
+
DEFAULT,
|
|
20
|
+
LIGHT_BLUE,
|
|
21
|
+
LIGHT_CYAN,
|
|
22
|
+
LIGHT_GRAY,
|
|
23
|
+
LIGHT_GREEN,
|
|
24
|
+
LIGHT_MAGENTA,
|
|
25
|
+
LIGHT_RED,
|
|
26
|
+
UPDATE_PALETTE_ENTRY,
|
|
27
|
+
WHITE,
|
|
28
|
+
YELLOW,
|
|
29
|
+
AttrSpec,
|
|
30
|
+
AttrSpecError,
|
|
31
|
+
BaseScreen,
|
|
32
|
+
RealTerminal,
|
|
33
|
+
ScreenError,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if typing.TYPE_CHECKING:
|
|
37
|
+
import types
|
|
38
|
+
|
|
8
39
|
__all__ = (
|
|
9
40
|
"BLACK",
|
|
10
41
|
"BROWN",
|
|
@@ -36,33 +67,6 @@ __all__ = (
|
|
|
36
67
|
"web",
|
|
37
68
|
)
|
|
38
69
|
|
|
39
|
-
from . import raw
|
|
40
|
-
from .common import (
|
|
41
|
-
BLACK,
|
|
42
|
-
BROWN,
|
|
43
|
-
DARK_BLUE,
|
|
44
|
-
DARK_CYAN,
|
|
45
|
-
DARK_GRAY,
|
|
46
|
-
DARK_GREEN,
|
|
47
|
-
DARK_MAGENTA,
|
|
48
|
-
DARK_RED,
|
|
49
|
-
DEFAULT,
|
|
50
|
-
LIGHT_BLUE,
|
|
51
|
-
LIGHT_CYAN,
|
|
52
|
-
LIGHT_GRAY,
|
|
53
|
-
LIGHT_GREEN,
|
|
54
|
-
LIGHT_MAGENTA,
|
|
55
|
-
LIGHT_RED,
|
|
56
|
-
UPDATE_PALETTE_ENTRY,
|
|
57
|
-
WHITE,
|
|
58
|
-
YELLOW,
|
|
59
|
-
AttrSpec,
|
|
60
|
-
AttrSpecError,
|
|
61
|
-
BaseScreen,
|
|
62
|
-
RealTerminal,
|
|
63
|
-
ScreenError,
|
|
64
|
-
)
|
|
65
|
-
|
|
66
70
|
try:
|
|
67
71
|
from . import curses
|
|
68
72
|
|
|
@@ -70,28 +74,29 @@ try:
|
|
|
70
74
|
except ImportError:
|
|
71
75
|
pass
|
|
72
76
|
|
|
73
|
-
# Moved modules handling
|
|
74
|
-
__locals: dict[str, typing.Any] = locals() # use mutable access for pure lazy loading
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
(
|
|
79
|
-
"html_fragment",
|
|
80
|
-
"lcd",
|
|
81
|
-
"web",
|
|
82
|
-
)
|
|
83
|
-
)
|
|
78
|
+
def lazy_import(name: str, package: str | None = None) -> types.ModuleType:
|
|
79
|
+
"""Lazy import implementation from Python documentation.
|
|
84
80
|
|
|
81
|
+
Useful for cases where no warnings expected for moved modules.
|
|
82
|
+
"""
|
|
83
|
+
spec = importlib.util.find_spec(name, package)
|
|
84
|
+
if not spec:
|
|
85
|
+
raise ImportError(f"No module named {name!r}")
|
|
86
|
+
if not spec.loader:
|
|
87
|
+
raise ImportError(f"Module named {name!r} is invalid")
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
|
|
89
|
+
loader = importlib.util.LazyLoader(spec.loader)
|
|
90
|
+
spec.loader = loader
|
|
91
|
+
module = importlib.util.module_from_spec(spec)
|
|
92
|
+
if not package:
|
|
93
|
+
sys.modules[name] = module
|
|
94
|
+
else:
|
|
95
|
+
sys.modules[f"{package.rstrip('.')}.{name.lstrip('.')}"] = module
|
|
96
|
+
loader.exec_module(module)
|
|
97
|
+
return module
|
|
88
98
|
|
|
89
|
-
:return: attribute by name
|
|
90
|
-
:raises AttributeError: attribute is not defined for lazy load
|
|
91
|
-
"""
|
|
92
|
-
if name in _lazy_load:
|
|
93
|
-
mod = importlib.import_module(f"{__package__}.{name}")
|
|
94
|
-
__locals[name] = mod
|
|
95
|
-
return mod
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
html_fragment = lazy_import(".html_fragment", __package__)
|
|
101
|
+
lcd = lazy_import(".lcd", __package__)
|
|
102
|
+
web = lazy_import(".web", __package__)
|
|
@@ -790,9 +790,9 @@ class Screen(BaseScreen, RealTerminal):
|
|
|
790
790
|
>>> s = Screen()
|
|
791
791
|
>>> s.set_terminal_properties(colors=256)
|
|
792
792
|
>>> a2e = s._attrspec_to_escape
|
|
793
|
-
>>> a2e(s.AttrSpec(
|
|
793
|
+
>>> a2e(s.AttrSpec("brown", "dark green"))
|
|
794
794
|
'\\x1b[0;33;42m'
|
|
795
|
-
>>> a2e(s.AttrSpec(
|
|
795
|
+
>>> a2e(s.AttrSpec("#fea,underline", "#d0d"))
|
|
796
796
|
'\\x1b[0;38;5;229;4;48;5;164m'
|
|
797
797
|
"""
|
|
798
798
|
if self.term == "fbterm":
|
urwid/display/common.py
CHANGED
|
@@ -389,13 +389,13 @@ def _parse_color_256(desc: str) -> int | None:
|
|
|
389
389
|
|
|
390
390
|
Returns None if desc is invalid.
|
|
391
391
|
|
|
392
|
-
>>> _parse_color_256(
|
|
392
|
+
>>> _parse_color_256("h142")
|
|
393
393
|
142
|
|
394
|
-
>>> _parse_color_256(
|
|
394
|
+
>>> _parse_color_256("#f00")
|
|
395
395
|
196
|
|
396
|
-
>>> _parse_color_256(
|
|
396
|
+
>>> _parse_color_256("g100")
|
|
397
397
|
231
|
|
398
|
-
>>> _parse_color_256(
|
|
398
|
+
>>> _parse_color_256("g#80")
|
|
399
399
|
244
|
|
400
400
|
"""
|
|
401
401
|
if len(desc) > 4:
|
|
@@ -425,7 +425,7 @@ def _parse_color_256(desc: str) -> int | None:
|
|
|
425
425
|
# Only remaining possibility is gray value
|
|
426
426
|
if desc.startswith("g#"):
|
|
427
427
|
# hex value 00..ff
|
|
428
|
-
gray = int(desc[2:], 16)
|
|
428
|
+
gray = int(desc[2:], 16) # noqa: FURB166
|
|
429
429
|
if gray < 0 or gray > 255:
|
|
430
430
|
return None
|
|
431
431
|
gray = _GRAY_256_LOOKUP[gray]
|
|
@@ -466,14 +466,14 @@ def _parse_color_88(desc: str) -> int | None:
|
|
|
466
466
|
|
|
467
467
|
Returns None if desc is invalid.
|
|
468
468
|
|
|
469
|
-
>>> _parse_color_88(
|
|
470
|
-
>>> _parse_color_88(
|
|
469
|
+
>>> _parse_color_88("h142")
|
|
470
|
+
>>> _parse_color_88("h42")
|
|
471
471
|
42
|
|
472
|
-
>>> _parse_color_88(
|
|
472
|
+
>>> _parse_color_88("#f00")
|
|
473
473
|
64
|
|
474
|
-
>>> _parse_color_88(
|
|
474
|
+
>>> _parse_color_88("g100")
|
|
475
475
|
79
|
|
476
|
-
>>> _parse_color_88(
|
|
476
|
+
>>> _parse_color_88("g#80")
|
|
477
477
|
83
|
|
478
478
|
"""
|
|
479
479
|
if len(desc) == 7:
|
|
@@ -505,7 +505,7 @@ def _parse_color_88(desc: str) -> int | None:
|
|
|
505
505
|
# Only remaining possibility is gray value
|
|
506
506
|
if desc.startswith("g#"):
|
|
507
507
|
# hex value 00..ff
|
|
508
|
-
gray = int(desc[2:], 16)
|
|
508
|
+
gray = int(desc[2:], 16) # noqa: FURB166
|
|
509
509
|
if gray < 0 or gray > 255:
|
|
510
510
|
return None
|
|
511
511
|
gray = _GRAY_88_LOOKUP[gray]
|
|
@@ -582,13 +582,13 @@ class AttrSpec:
|
|
|
582
582
|
values are only usable with 88, 256, or 2**24 colors. With
|
|
583
583
|
1 color only the foreground settings may be used.
|
|
584
584
|
|
|
585
|
-
>>> AttrSpec(
|
|
585
|
+
>>> AttrSpec("dark red", "light gray", 16)
|
|
586
586
|
AttrSpec('dark red', 'light gray')
|
|
587
|
-
>>> AttrSpec(
|
|
587
|
+
>>> AttrSpec("yellow, underline, bold", "dark blue")
|
|
588
588
|
AttrSpec('yellow,bold,underline', 'dark blue')
|
|
589
|
-
>>> AttrSpec(
|
|
589
|
+
>>> AttrSpec("#ddb", "#004", 256) # closest colors will be found
|
|
590
590
|
AttrSpec('#dda', '#006')
|
|
591
|
-
>>> AttrSpec(
|
|
591
|
+
>>> AttrSpec("#ddb", "#004", 88)
|
|
592
592
|
AttrSpec('#ccc', '#000', colors=88)
|
|
593
593
|
"""
|
|
594
594
|
if colors not in {1, 16, 88, 256, 2**24}:
|
|
@@ -820,9 +820,9 @@ class AttrSpec:
|
|
|
820
820
|
If the foreground or background is 'default' then all their compenents
|
|
821
821
|
will be returned as None.
|
|
822
822
|
|
|
823
|
-
>>> AttrSpec(
|
|
823
|
+
>>> AttrSpec("yellow", "#ccf", colors=88).get_rgb_values()
|
|
824
824
|
(255, 255, 0, 205, 205, 255)
|
|
825
|
-
>>> AttrSpec(
|
|
825
|
+
>>> AttrSpec("default", "g92").get_rgb_values()
|
|
826
826
|
(None, None, None, 238, 238, 238)
|
|
827
827
|
"""
|
|
828
828
|
if not (self.foreground_basic or self.foreground_high or self.foreground_true):
|
urwid/display/curses.py
CHANGED
|
@@ -563,9 +563,7 @@ class Screen(BaseScreen, RealTerminal):
|
|
|
563
563
|
|
|
564
564
|
logger.debug(f"Drawing screen with size {size!r}")
|
|
565
565
|
|
|
566
|
-
y
|
|
567
|
-
for row in canvas.content():
|
|
568
|
-
y += 1
|
|
566
|
+
for y, row in enumerate(canvas.content()):
|
|
569
567
|
try:
|
|
570
568
|
self.s.move(y, 0)
|
|
571
569
|
except curses.error:
|
urwid/display/web.py
CHANGED
urwid/event_loop/asyncio_loop.py
CHANGED
|
@@ -79,7 +79,9 @@ class AsyncioEventLoop(EventLoop):
|
|
|
79
79
|
self._original_event_loop_policy, asyncio.WindowsSelectorEventLoopPolicy
|
|
80
80
|
):
|
|
81
81
|
self.logger.debug("Set WindowsSelectorEventLoopPolicy as asyncio event loop policy")
|
|
82
|
-
asyncio.set_event_loop_policy(
|
|
82
|
+
asyncio.set_event_loop_policy(
|
|
83
|
+
asyncio.WindowsSelectorEventLoopPolicy() # pylint: disable=deprecated-class
|
|
84
|
+
)
|
|
83
85
|
self._event_loop_policy_altered = True
|
|
84
86
|
else:
|
|
85
87
|
self._event_loop_policy_altered = False
|
urwid/event_loop/main_loop.py
CHANGED
|
@@ -340,7 +340,7 @@ class MainLoop:
|
|
|
340
340
|
|
|
341
341
|
def _test_run(self):
|
|
342
342
|
"""
|
|
343
|
-
>>> w = _refl("widget")
|
|
343
|
+
>>> w = _refl("widget") # _refl prints out function calls
|
|
344
344
|
>>> w.render_rval = "fake canvas" # *_rval is used for return values
|
|
345
345
|
>>> scr = _refl("screen")
|
|
346
346
|
>>> scr.get_input_descriptors_rval = [42]
|
|
@@ -351,7 +351,7 @@ class MainLoop:
|
|
|
351
351
|
>>> evl.enter_idle_rval = 1
|
|
352
352
|
>>> evl.watch_file_rval = 2
|
|
353
353
|
>>> ml = MainLoop(w, [], scr, event_loop=evl)
|
|
354
|
-
>>> ml.run()
|
|
354
|
+
>>> ml.run() # doctest:+ELLIPSIS
|
|
355
355
|
screen.start()
|
|
356
356
|
screen.set_mouse_tracking()
|
|
357
357
|
screen.unhook_event_loop(...)
|
|
@@ -361,7 +361,7 @@ class MainLoop:
|
|
|
361
361
|
event_loop.remove_enter_idle(1)
|
|
362
362
|
screen.unhook_event_loop(...)
|
|
363
363
|
screen.stop()
|
|
364
|
-
>>> ml.draw_screen()
|
|
364
|
+
>>> ml.draw_screen() # doctest:+ELLIPSIS
|
|
365
365
|
screen.get_cols_rows()
|
|
366
366
|
widget.render((20, 10), focus=True)
|
|
367
367
|
screen.draw_screen((20, 10), 'fake canvas')
|
|
@@ -454,7 +454,7 @@ class MainLoop:
|
|
|
454
454
|
>>> evl = _refl("event_loop")
|
|
455
455
|
>>> ml = MainLoop(w, [], scr, event_loop=evl)
|
|
456
456
|
>>> ml._input_timeout = "old timeout"
|
|
457
|
-
>>> ml._update([
|
|
457
|
+
>>> ml._update(["y"], [121]) # doctest:+ELLIPSIS
|
|
458
458
|
screen.get_cols_rows()
|
|
459
459
|
widget.selectable()
|
|
460
460
|
widget.keypress((15, 5), 'y')
|
|
@@ -599,7 +599,7 @@ class MainLoop:
|
|
|
599
599
|
>>> scr = _refl("screen")
|
|
600
600
|
>>> scr.get_cols_rows_rval = (10, 5)
|
|
601
601
|
>>> ml = MainLoop(w, [], scr)
|
|
602
|
-
>>> ml.process_input([
|
|
602
|
+
>>> ml.process_input(["enter", ("mouse drag", 1, 14, 20)])
|
|
603
603
|
screen.get_cols_rows()
|
|
604
604
|
widget.selectable()
|
|
605
605
|
widget.keypress((10, 5), 'enter')
|
urwid/font.py
CHANGED
|
@@ -24,9 +24,11 @@ import typing
|
|
|
24
24
|
import warnings
|
|
25
25
|
from pprint import pformat
|
|
26
26
|
|
|
27
|
+
import wcwidth
|
|
28
|
+
|
|
27
29
|
from urwid.canvas import CanvasError, TextCanvas
|
|
28
30
|
from urwid.display.escape import SAFE_ASCII_DEC_SPECIAL_RE
|
|
29
|
-
from urwid.util import apply_target_encoding
|
|
31
|
+
from urwid.util import apply_target_encoding
|
|
30
32
|
|
|
31
33
|
if typing.TYPE_CHECKING:
|
|
32
34
|
from collections.abc import Iterator, Sequence
|
|
@@ -60,7 +62,7 @@ def separate_glyphs(gdata: str, height: int) -> tuple[dict[str, tuple[int, list[
|
|
|
60
62
|
character = key_line[key_index]
|
|
61
63
|
|
|
62
64
|
if key_index < len(key_line) and key_line[key_index] == character:
|
|
63
|
-
end_col +=
|
|
65
|
+
end_col += wcwidth.width(character, control_codes="ignore")
|
|
64
66
|
key_index += 1
|
|
65
67
|
continue
|
|
66
68
|
|
|
@@ -76,7 +78,7 @@ def separate_glyphs(gdata: str, height: int) -> tuple[dict[str, tuple[int, list[
|
|
|
76
78
|
if j >= len(line):
|
|
77
79
|
fill = end_col - start_col - y
|
|
78
80
|
break
|
|
79
|
-
y +=
|
|
81
|
+
y += wcwidth.width(line[j], control_codes="ignore")
|
|
80
82
|
j += 1
|
|
81
83
|
if y + fill != end_col - start_col:
|
|
82
84
|
raise ValueError(repr((y, fill, end_col)))
|
|
@@ -139,7 +141,7 @@ class FontRegistry(type):
|
|
|
139
141
|
3
|
|
140
142
|
>>> with set_temporary_encoding("utf-8"):
|
|
141
143
|
... canvas: TextCanvas = font.render("+")
|
|
142
|
-
>>> b
|
|
144
|
+
>>> b"\\n".join(canvas.text).decode("utf-8")
|
|
143
145
|
' \\n ┼\\n '
|
|
144
146
|
"""
|
|
145
147
|
return mcs.__registered.get(item)
|
urwid/numedit.py
CHANGED
|
@@ -88,28 +88,28 @@ class NumEdit(Edit):
|
|
|
88
88
|
Handle editing keystrokes. Remove leading zeros.
|
|
89
89
|
|
|
90
90
|
>>> e, size = NumEdit("0123456789", "", "5002"), (10,)
|
|
91
|
-
>>> e.keypress(size,
|
|
92
|
-
>>> e.keypress(size,
|
|
91
|
+
>>> e.keypress(size, "home")
|
|
92
|
+
>>> e.keypress(size, "delete")
|
|
93
93
|
>>> assert e.edit_text == "002"
|
|
94
|
-
>>> e.keypress(size,
|
|
94
|
+
>>> e.keypress(size, "end")
|
|
95
95
|
>>> assert e.edit_text == "2"
|
|
96
96
|
>>> # binary only
|
|
97
97
|
>>> e, size = NumEdit("01", "", ""), (10,)
|
|
98
98
|
>>> assert e.edit_text == ""
|
|
99
|
-
>>> e.keypress(size,
|
|
100
|
-
>>> e.keypress(size,
|
|
101
|
-
>>> e.keypress(size,
|
|
99
|
+
>>> e.keypress(size, "1")
|
|
100
|
+
>>> e.keypress(size, "0")
|
|
101
|
+
>>> e.keypress(size, "1")
|
|
102
102
|
>>> assert e.edit_text == "101"
|
|
103
103
|
>>> e, size = NumEdit("0123456789", "", "", allow_negative=True), (10,)
|
|
104
104
|
>>> e.keypress(size, "-")
|
|
105
|
-
>>> e.keypress(size,
|
|
105
|
+
>>> e.keypress(size, "1")
|
|
106
106
|
>>> e.edit_text
|
|
107
107
|
'-1'
|
|
108
|
-
>>> e.keypress(size,
|
|
109
|
-
>>> e.keypress(size,
|
|
108
|
+
>>> e.keypress(size, "home")
|
|
109
|
+
>>> e.keypress(size, "delete")
|
|
110
110
|
>>> e.edit_text
|
|
111
111
|
'1'
|
|
112
|
-
>>> e.keypress(size,
|
|
112
|
+
>>> e.keypress(size, "end")
|
|
113
113
|
>>> e.keypress(size, "-")
|
|
114
114
|
'-'
|
|
115
115
|
>>> e.edit_text
|
|
@@ -141,52 +141,52 @@ class IntegerEdit(NumEdit):
|
|
|
141
141
|
caption -- caption markup
|
|
142
142
|
default -- default edit value
|
|
143
143
|
|
|
144
|
-
>>> IntegerEdit(
|
|
144
|
+
>>> IntegerEdit("", 42)
|
|
145
145
|
<IntegerEdit selectable flow widget '42' edit_pos=2>
|
|
146
|
-
>>> e, size = IntegerEdit(
|
|
147
|
-
>>> e.keypress(size,
|
|
148
|
-
>>> e.keypress(size,
|
|
146
|
+
>>> e, size = IntegerEdit("", "5002"), (10,)
|
|
147
|
+
>>> e.keypress(size, "home")
|
|
148
|
+
>>> e.keypress(size, "delete")
|
|
149
149
|
>>> assert e.edit_text == "002"
|
|
150
|
-
>>> e.keypress(size,
|
|
150
|
+
>>> e.keypress(size, "end")
|
|
151
151
|
>>> assert e.edit_text == "2"
|
|
152
|
-
>>> e.keypress(size,
|
|
153
|
-
>>> e.keypress(size,
|
|
152
|
+
>>> e.keypress(size, "9")
|
|
153
|
+
>>> e.keypress(size, "0")
|
|
154
154
|
>>> assert e.edit_text == "290"
|
|
155
155
|
>>> e, size = IntegerEdit("", ""), (10,)
|
|
156
156
|
>>> assert e.value() is None
|
|
157
157
|
>>> # binary
|
|
158
|
-
>>> e, size = IntegerEdit(
|
|
159
|
-
>>> e.keypress(size,
|
|
160
|
-
>>> e.keypress(size,
|
|
158
|
+
>>> e, size = IntegerEdit("", "1010", base=2), (10,)
|
|
159
|
+
>>> e.keypress(size, "end")
|
|
160
|
+
>>> e.keypress(size, "1")
|
|
161
161
|
>>> assert e.edit_text == "10101"
|
|
162
162
|
>>> assert e.value() == Decimal("21")
|
|
163
163
|
>>> # HEX
|
|
164
|
-
>>> e, size = IntegerEdit(
|
|
165
|
-
>>> e.keypress(size,
|
|
166
|
-
>>> e.keypress(size,
|
|
167
|
-
>>> e.keypress(size,
|
|
164
|
+
>>> e, size = IntegerEdit("", "10", base=16), (10,)
|
|
165
|
+
>>> e.keypress(size, "end")
|
|
166
|
+
>>> e.keypress(size, "F")
|
|
167
|
+
>>> e.keypress(size, "f")
|
|
168
168
|
>>> assert e.edit_text == "10Ff"
|
|
169
|
-
>>> assert e.keypress(size,
|
|
169
|
+
>>> assert e.keypress(size, "G") == "G" # unhandled key
|
|
170
170
|
>>> assert e.edit_text == "10Ff"
|
|
171
171
|
>>> # keep leading 0's when not base 10
|
|
172
|
-
>>> e, size = IntegerEdit(
|
|
172
|
+
>>> e, size = IntegerEdit("", "10FF", base=16), (10,)
|
|
173
173
|
>>> assert e.edit_text == "10FF"
|
|
174
174
|
>>> assert e.value() == Decimal("4351")
|
|
175
|
-
>>> e.keypress(size,
|
|
176
|
-
>>> e.keypress(size,
|
|
177
|
-
>>> e.keypress(size,
|
|
175
|
+
>>> e.keypress(size, "home")
|
|
176
|
+
>>> e.keypress(size, "delete")
|
|
177
|
+
>>> e.keypress(size, "0")
|
|
178
178
|
>>> assert e.edit_text == "00FF"
|
|
179
179
|
>>> # test exception on incompatible value for base
|
|
180
|
-
>>> e, size = IntegerEdit(
|
|
180
|
+
>>> e, size = IntegerEdit("", "10FG", base=16), (10,)
|
|
181
181
|
Traceback (most recent call last):
|
|
182
182
|
...
|
|
183
183
|
ValueError: invalid value: 10FG for base 16
|
|
184
184
|
>>> # test exception on float init value
|
|
185
|
-
>>> e, size = IntegerEdit(
|
|
185
|
+
>>> e, size = IntegerEdit("", 10.0), (10,)
|
|
186
186
|
Traceback (most recent call last):
|
|
187
187
|
...
|
|
188
188
|
ValueError: default: Only 'str', 'int', 'long' or Decimal input allowed
|
|
189
|
-
>>> e, size = IntegerEdit(
|
|
189
|
+
>>> e, size = IntegerEdit("", Decimal("10.0")), (10,)
|
|
190
190
|
Traceback (most recent call last):
|
|
191
191
|
...
|
|
192
192
|
ValueError: not an 'integer Decimal' instance
|
|
@@ -226,8 +226,8 @@ class IntegerEdit(NumEdit):
|
|
|
226
226
|
Return the numeric value of self.edit_text.
|
|
227
227
|
|
|
228
228
|
>>> e, size = IntegerEdit(), (10,)
|
|
229
|
-
>>> e.keypress(size,
|
|
230
|
-
>>> e.keypress(size,
|
|
229
|
+
>>> e.keypress(size, "5")
|
|
230
|
+
>>> e.keypress(size, "1")
|
|
231
231
|
>>> assert e.value() == 51
|
|
232
232
|
"""
|
|
233
233
|
if self.edit_text:
|
|
@@ -240,9 +240,9 @@ class IntegerEdit(NumEdit):
|
|
|
240
240
|
|
|
241
241
|
>>> e, size = IntegerEdit(allow_negative=True), (10,)
|
|
242
242
|
>>> assert int(e) == 0
|
|
243
|
-
>>> e.keypress(size,
|
|
244
|
-
>>> e.keypress(size,
|
|
245
|
-
>>> e.keypress(size,
|
|
243
|
+
>>> e.keypress(size, "-")
|
|
244
|
+
>>> e.keypress(size, "4")
|
|
245
|
+
>>> e.keypress(size, "2")
|
|
246
246
|
>>> assert int(e) == -42
|
|
247
247
|
"""
|
|
248
248
|
if self.edit_text:
|
|
@@ -270,46 +270,46 @@ class FloatEdit(NumEdit):
|
|
|
270
270
|
preserve_significance -- return value has the same signif. as default
|
|
271
271
|
decimal_separator -- use '.' as separator by default, optionally a ','
|
|
272
272
|
|
|
273
|
-
>>> FloatEdit(
|
|
273
|
+
>>> FloatEdit("", "1.065434")
|
|
274
274
|
<FloatEdit selectable flow widget '1.065434' edit_pos=8>
|
|
275
|
-
>>> e, size = FloatEdit(
|
|
276
|
-
>>> e.keypress(size,
|
|
277
|
-
>>> e.keypress(size,
|
|
275
|
+
>>> e, size = FloatEdit("", "1.065434"), (10,)
|
|
276
|
+
>>> e.keypress(size, "home")
|
|
277
|
+
>>> e.keypress(size, "delete")
|
|
278
278
|
>>> assert e.edit_text == ".065434"
|
|
279
|
-
>>> e.keypress(size,
|
|
280
|
-
>>> e.keypress(size,
|
|
279
|
+
>>> e.keypress(size, "end")
|
|
280
|
+
>>> e.keypress(size, "backspace")
|
|
281
281
|
>>> assert e.edit_text == ".06543"
|
|
282
282
|
>>> e, size = FloatEdit(), (10,)
|
|
283
|
-
>>> e.keypress(size,
|
|
284
|
-
>>> e.keypress(size,
|
|
285
|
-
>>> e.keypress(size,
|
|
286
|
-
>>> e.keypress(size,
|
|
287
|
-
>>> e.keypress(size,
|
|
283
|
+
>>> e.keypress(size, "5")
|
|
284
|
+
>>> e.keypress(size, "1")
|
|
285
|
+
>>> e.keypress(size, ".")
|
|
286
|
+
>>> e.keypress(size, "5")
|
|
287
|
+
>>> e.keypress(size, "1")
|
|
288
288
|
>>> assert e.value() == Decimal("51.51"), e.value()
|
|
289
289
|
>>> e, size = FloatEdit(decimal_separator=":"), (10,)
|
|
290
290
|
Traceback (most recent call last):
|
|
291
291
|
...
|
|
292
292
|
ValueError: invalid decimal separator: :
|
|
293
293
|
>>> e, size = FloatEdit(decimal_separator=","), (10,)
|
|
294
|
-
>>> e.keypress(size,
|
|
295
|
-
>>> e.keypress(size,
|
|
296
|
-
>>> e.keypress(size,
|
|
297
|
-
>>> e.keypress(size,
|
|
298
|
-
>>> e.keypress(size,
|
|
294
|
+
>>> e.keypress(size, "5")
|
|
295
|
+
>>> e.keypress(size, "1")
|
|
296
|
+
>>> e.keypress(size, ",")
|
|
297
|
+
>>> e.keypress(size, "5")
|
|
298
|
+
>>> e.keypress(size, "1")
|
|
299
299
|
>>> assert e.edit_text == "51,51"
|
|
300
300
|
>>> e, size = FloatEdit("", "3.1415", preserve_significance=True), (10,)
|
|
301
|
-
>>> e.keypress(size,
|
|
302
|
-
>>> e.keypress(size,
|
|
303
|
-
>>> e.keypress(size,
|
|
301
|
+
>>> e.keypress(size, "end")
|
|
302
|
+
>>> e.keypress(size, "backspace")
|
|
303
|
+
>>> e.keypress(size, "backspace")
|
|
304
304
|
>>> assert e.edit_text == "3.14"
|
|
305
305
|
>>> assert e.value() == Decimal("3.1400")
|
|
306
|
-
>>> e.keypress(size,
|
|
307
|
-
>>> e.keypress(size,
|
|
308
|
-
>>> e.keypress(size,
|
|
306
|
+
>>> e.keypress(size, "1")
|
|
307
|
+
>>> e.keypress(size, "5")
|
|
308
|
+
>>> e.keypress(size, "9")
|
|
309
309
|
>>> assert e.value() == Decimal("3.1416"), e.value()
|
|
310
310
|
>>> e, size = FloatEdit("", ""), (10,)
|
|
311
311
|
>>> assert e.value() is None
|
|
312
|
-
>>> e, size = FloatEdit(
|
|
312
|
+
>>> e, size = FloatEdit("", 10.0), (10,)
|
|
313
313
|
Traceback (most recent call last):
|
|
314
314
|
...
|
|
315
315
|
ValueError: default: Only 'str', 'int', 'long' or Decimal input allowed
|
|
@@ -368,11 +368,11 @@ class FloatEdit(NumEdit):
|
|
|
368
368
|
"""Enforced float value return.
|
|
369
369
|
|
|
370
370
|
>>> e, size = FloatEdit(allow_negative=True), (10,)
|
|
371
|
-
>>> assert float(e) == 0.
|
|
372
|
-
>>> e.keypress(size,
|
|
373
|
-
>>> e.keypress(size,
|
|
374
|
-
>>> e.keypress(size,
|
|
375
|
-
>>> e.keypress(size,
|
|
371
|
+
>>> assert float(e) == 0.0
|
|
372
|
+
>>> e.keypress(size, "-")
|
|
373
|
+
>>> e.keypress(size, "4")
|
|
374
|
+
>>> e.keypress(size, ".")
|
|
375
|
+
>>> e.keypress(size, "2")
|
|
376
376
|
>>> assert float(e) == -4.2
|
|
377
377
|
"""
|
|
378
378
|
if self.edit_text:
|