wizlib 3.1.2__py3-none-any.whl → 3.1.4__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.

Potentially problematic release.


This version of wizlib might be problematic. Click here for more details.

wizlib/app.py CHANGED
@@ -70,15 +70,18 @@ class WizApp:
70
70
  """Set up the parser for the app class"""
71
71
  cls.parser = WizParser(prog=cls.name)
72
72
  subparsers = cls.parser.add_subparsers(dest='command')
73
+ cls.dparser = WizParser(prog=f"{cls.name} {cls.base.default}")
73
74
  for command in cls.base.family_members('name'):
74
75
  key = command.get_member_attr('key')
75
76
  aliases = [key] if key else []
76
77
  subparser = subparsers.add_parser(command.name, aliases=aliases)
77
78
  if command.name == cls.base.default:
78
- cls.dparser = subparser
79
+ command.add_args(cls.dparser)
79
80
  command.add_args(subparser)
80
81
  for handler in cls.handlers:
81
82
  handler.add_args(cls.parser)
83
+ # Throws ArgumentError if the default command includes an optional
84
+ # argument that overlaps with one of the handlers
82
85
  handler.add_args(cls.dparser)
83
86
 
84
87
  def __init__(self, **vals):
wizlib/io.py ADDED
@@ -0,0 +1,21 @@
1
+ # Primitive i/o functions referenced elsewhere, useful for test patching (a
2
+ # sort of dependency injection
3
+
4
+ import sys
5
+
6
+ import readchar
7
+
8
+
9
+ ISATTY = sys.stdin.isatty()
10
+
11
+
12
+ def isatty():
13
+ return ISATTY
14
+
15
+
16
+ def stream():
17
+ return '' if ISATTY else sys.stdin.read()
18
+
19
+
20
+ def ttyin():
21
+ return readchar.readkey()
wizlib/stream_handler.py CHANGED
@@ -1,13 +1,17 @@
1
+ # In a non-interactive, non-testing mode, route input from stdin to the output.
2
+ # When testing, read from the object provided (probably a StreamIO)
3
+
1
4
  from pathlib import Path
2
5
  import sys
3
6
 
4
7
  from wizlib.handler import Handler
5
8
  from wizlib.parser import WizParser
6
-
7
- INTERACTIVE = sys.stdin.isatty()
9
+ import wizlib.io
8
10
 
9
11
 
10
12
  class StreamHandler(Handler):
13
+ """Handle non-interactive input, such as via a pipe in a shell. Only runs
14
+ when not in a tty."""
11
15
 
12
16
  name = 'stream'
13
17
  text: str = ''
@@ -15,8 +19,8 @@ class StreamHandler(Handler):
15
19
  def __init__(self, file=None, stdin=True):
16
20
  if file:
17
21
  self.text = Path(file).read_text()
18
- elif stdin and (not INTERACTIVE):
19
- self.text = sys.stdin.read()
22
+ elif not wizlib.io.isatty():
23
+ self.text = wizlib.io.stream()
20
24
 
21
25
  def __str__(self):
22
26
  return self.text
wizlib/test_case.py ADDED
@@ -0,0 +1,36 @@
1
+ # Patch inputs and outputs for easy testing
2
+
3
+ from io import StringIO
4
+ from unittest import TestCase
5
+ from unittest.mock import Mock, patch
6
+
7
+
8
+ class WizLibTestCase(TestCase):
9
+ """Wrap your test cases in this class to use the patches correctly"""
10
+
11
+ def setUp(self):
12
+ self.notty = patch('wizlib.io.isatty', Mock(return_value=False))
13
+ self.notty.start()
14
+
15
+ def tearDown(self):
16
+ self.notty.stop()
17
+
18
+ @staticmethod
19
+ def patch_stream(val: str):
20
+ """Patch stream input such as pipes for stream handler"""
21
+ mock = Mock(return_value=val)
22
+ return patch('wizlib.io.stream', mock)
23
+
24
+ @staticmethod
25
+ def patch_ttyin(val: str):
26
+ """Patch input typed by a user in shell ui"""
27
+ mock = Mock(side_effect=val)
28
+ return patch('wizlib.io.ttyin', mock)
29
+
30
+ @staticmethod
31
+ def patcherr(): # pragma: nocover
32
+ return patch('sys.stderr', StringIO())
33
+
34
+ @staticmethod
35
+ def patchout(): # pragma: nocover
36
+ return patch('sys.stdout', StringIO())
@@ -2,10 +2,8 @@ from enum import Enum
2
2
  import sys
3
3
  import re
4
4
 
5
- from readchar import readkey
6
-
7
5
  from wizlib.ui.shell import S
8
-
6
+ import wizlib.io
9
7
 
10
8
  if (sys.platform == "win32"):
11
9
  import ctypes
@@ -89,7 +87,7 @@ class ShellLineEditor: # pragma: nocover
89
87
  write(S.RESET)
90
88
  while True:
91
89
  self.write_fill()
92
- key = readkey()
90
+ key = wizlib.io.ttyin()
93
91
  self.clear_fill()
94
92
  if key == S.RETURN:
95
93
  break
wizlib/ui/shell_ui.py CHANGED
@@ -1,13 +1,10 @@
1
1
  from enum import StrEnum
2
2
  import sys
3
3
 
4
- from readchar import readkey
5
-
6
4
  from wizlib.ui import UI, Chooser, Emphasis
7
5
  from wizlib.ui.shell.line_editor import ShellLineEditor
8
6
  from wizlib.ui.shell import S
9
-
10
- INTERACTIVE = sys.stdin.isatty()
7
+ import wizlib.io
11
8
 
12
9
  COLOR = {
13
10
  Emphasis.INFO: S.BLUE,
@@ -38,13 +35,11 @@ class ShellUI(UI):
38
35
  sys.stderr.flush()
39
36
 
40
37
  def get_option(self, chooser: Chooser):
41
- """Get a choice from the user with a single keystroke"""
38
+ """Get a choice from the user with a single keystroke. Only works when
39
+ in a tty."""
42
40
  while True:
43
41
  self.ask(chooser.prompt_string)
44
- if INTERACTIVE:
45
- key = readkey()
46
- else:
47
- key = sys.stdin.read(1)
42
+ key = wizlib.io.ttyin()
48
43
  out = chooser.default if key == '\n' else \
49
44
  key if key.isprintable() else ''
50
45
  choice = chooser.choice_by_key(key)
@@ -59,8 +54,7 @@ class ShellUI(UI):
59
54
  """Allow the user to input an arbitrary line of text, with possible tab
60
55
  completion"""
61
56
  self.ask(prompt)
62
- if INTERACTIVE:
63
- value = ShellLineEditor(choices, default).edit()
64
- else:
65
- value = input()
57
+ value = ShellLineEditor(choices, default).edit()
58
+ # else:
59
+ # value = input()
66
60
  return value
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wizlib
3
- Version: 3.1.2
3
+ Version: 3.1.4
4
4
  Summary: Framework for flexible and powerful command-line applications
5
5
  License: MIT
6
6
  Author: Steampunk Wizard
@@ -1,19 +1,20 @@
1
1
  wizlib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- wizlib/app.py,sha256=imR_lfyQtYzKObu1tLZVGgJQGmdz43M7E9qAMMokyD4,3962
2
+ wizlib/app.py,sha256=ke0NbaYC6ArmdtLTySl6VIGIGicxTsIuzW9wag6b7rU,4180
3
3
  wizlib/class_family.py,sha256=tORSVAaPeWTQMcz2DX-MQClj1GQR3vCmkALPXxHa_pk,4506
4
4
  wizlib/command.py,sha256=NO1558EYuXxfkpSmX6ljjzae8n8g4w6yytZKTJtigvo,1708
5
5
  wizlib/config_handler.py,sha256=hoDavSMiGM_7PAHI8XIwC8nxPWOZDk302ryyjluoLGg,2588
6
6
  wizlib/error.py,sha256=ypwdMOYhtgKWd48ccfOX8idmCXmm-Skwx3gkPwqJB3c,46
7
7
  wizlib/handler.py,sha256=Oz80aPhDyeY9tdppZ1dvtN-19JU5ydEDVW6jtppVoD4,446
8
+ wizlib/io.py,sha256=KAMYTyHyKO2zY2kbymO5c8QpIWfHoTipWsDWzBJzDSw,307
8
9
  wizlib/parser.py,sha256=yLHV0fENeApFomCRWa3I6sB1x4lk1ag4vKejWVsic64,1550
9
- wizlib/stream_handler.py,sha256=i1EgcBrDiYhFK-CI8At7JtUtMCNunJmSkJLSlili-as,663
10
+ wizlib/stream_handler.py,sha256=UUPDpvXmfYOwG0Mmz2YMA8SKxeqau14_bK1z9vZHHp0,896
10
11
  wizlib/super_wrapper.py,sha256=msitlfFfEwnrskzTtQBEY975sh9TQPicdLVo67imuqU,315
12
+ wizlib/test_case.py,sha256=T5cX7yWy94hf8JuherDeBCH9Gve5tx2x_PZOte4udC0,1017
11
13
  wizlib/ui/__init__.py,sha256=ve_p_g4aBujh4jIJMgKkJ6cE5PT0aeY5AgRlneDswGg,4241
12
14
  wizlib/ui/shell/__init__.py,sha256=sPrYe4bG_Xf7Nwssx_dqXVk9jeyYBFUjh4oLdlSOeRY,943
13
- wizlib/ui/shell/line_editor.py,sha256=frpsqU5NggcvEz3XeB8YyqgmlExlyx6K1CKPzvARtPk,7419
14
- wizlib/ui/shell_ui.py,sha256=f2GErMJg09GPZDS4uK0q8Qq8WEssQFP1dqQyg4ycznI,2029
15
+ wizlib/ui/shell/line_editor.py,sha256=vXXsCS_i4ZCjP0su2X9W_yD1CS6MiazPAtxpiaXQ6Jc,7413
16
+ wizlib/ui/shell_ui.py,sha256=jre7E_5vP_SceNH7GYenfXZpFf4h9Sbh9cWZZycTYk8,1911
15
17
  wizlib/ui_handler.py,sha256=JoZadtw9DKAtGvHKP3_BJF2NaYqmcQYNdsY4PeRnOjg,634
16
- wizlib/util.py,sha256=x1SyL3iXot0ET2r8Jjb2ySTd_J-3Uu7J1b_CHvFgzew,156
17
- wizlib-3.1.2.dist-info/METADATA,sha256=4HzwBU_sp2F4ycdTb1XvCTDO5i7DeIMdOhl63JfCzNs,1780
18
- wizlib-3.1.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
19
- wizlib-3.1.2.dist-info/RECORD,,
18
+ wizlib-3.1.4.dist-info/METADATA,sha256=uCYiS39PTHiOjCjA-POguOE1SpJUby4k_hAMx_MYzrA,1780
19
+ wizlib-3.1.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
20
+ wizlib-3.1.4.dist-info/RECORD,,
wizlib/util.py DELETED
@@ -1,8 +0,0 @@
1
- from unittest.mock import Mock, patch
2
-
3
-
4
- RK = 'wizlib.ui.shell.line_editor.readkey'
5
-
6
-
7
- def mock_keys(keys: str):
8
- return patch(RK, Mock(side_effect=keys))
File without changes