iripau 1.1.0__tar.gz → 1.1.2__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.
- {iripau-1.1.0 → iripau-1.1.2}/PKG-INFO +1 -1
- iripau-1.1.2/iripau/executable.py +176 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau/logging.py +2 -2
- {iripau-1.1.0 → iripau-1.1.2}/iripau/requests.py +29 -1
- {iripau-1.1.0 → iripau-1.1.2}/iripau/subprocess.py +3 -3
- {iripau-1.1.0 → iripau-1.1.2}/iripau.egg-info/PKG-INFO +1 -1
- {iripau-1.1.0 → iripau-1.1.2}/pyproject.toml +1 -1
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_requests.py +56 -0
- iripau-1.1.0/iripau/executable.py +0 -108
- {iripau-1.1.0 → iripau-1.1.2}/LICENSE +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/README.md +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau/__init__.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau/functools.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau/random.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau/shutil.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau/threading.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau.egg-info/SOURCES.txt +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau.egg-info/dependency_links.txt +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau.egg-info/requires.txt +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/iripau.egg-info/top_level.txt +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/setup.cfg +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_command.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_executable.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_functools.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_logging.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_random.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_shutil.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_subprocess.py +0 -0
- {iripau-1.1.0 → iripau-1.1.2}/tests/test_threading.py +0 -0
@@ -0,0 +1,176 @@
|
|
1
|
+
"""
|
2
|
+
Execute commands as Python functions
|
3
|
+
"""
|
4
|
+
|
5
|
+
from shlex import split
|
6
|
+
from random import choice
|
7
|
+
from itertools import chain
|
8
|
+
|
9
|
+
from iripau.command import host_run
|
10
|
+
|
11
|
+
|
12
|
+
class Command:
|
13
|
+
""" Run an executable command as a Python callable
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
"""
|
18
|
+
|
19
|
+
def __init__(self, parent, command):
|
20
|
+
self._parent = parent
|
21
|
+
self._command = parent._mk_command(command)
|
22
|
+
self._mk_command = parent._mk_command
|
23
|
+
|
24
|
+
def __getattr__(self, command):
|
25
|
+
child = Command(self, command)
|
26
|
+
setattr(self, command, child)
|
27
|
+
return child
|
28
|
+
|
29
|
+
def __call__(self, *args, **kwargs):
|
30
|
+
return self._parent(self._command, *args, **kwargs)
|
31
|
+
|
32
|
+
|
33
|
+
def make_command(command):
|
34
|
+
""" Replace underscore with dash.
|
35
|
+
|
36
|
+
Suitable for a CLI that uses dashes as word-separator in their
|
37
|
+
positional arguments.
|
38
|
+
|
39
|
+
Args:
|
40
|
+
command (str): Python identifier referring to a CLI command or
|
41
|
+
sub-command.
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
str: Final token to be used as a CLI positional argument.
|
45
|
+
"""
|
46
|
+
return command.replace("_", "-")
|
47
|
+
|
48
|
+
|
49
|
+
def make_option(option):
|
50
|
+
""" Replace underscore with dash and prepend two more dashes.
|
51
|
+
|
52
|
+
Suitable for a CLI that uses dashes as word-separator in their
|
53
|
+
positional arguments.
|
54
|
+
|
55
|
+
Args:
|
56
|
+
option (str): Python identifier referring to a CLI optional
|
57
|
+
argument.
|
58
|
+
|
59
|
+
Returns:
|
60
|
+
Tuple[str]: The tokens that could be used as a CLI positional argument.
|
61
|
+
"""
|
62
|
+
return "--" + option.replace("_", "-"),
|
63
|
+
|
64
|
+
|
65
|
+
class Executable:
|
66
|
+
""" Run an executable as a Python callable.
|
67
|
+
|
68
|
+
Args:
|
69
|
+
executable (str): Path to an executable file or just the name if it
|
70
|
+
exists in the ``PATH``.
|
71
|
+
make_command (Callable[[str], str]): Function to convert a Python
|
72
|
+
identifier to the corresponding command positional argument for
|
73
|
+
the CLI.
|
74
|
+
make_option (Callable[str], Tuple[str]): Function to convert a Python
|
75
|
+
identifier into the corresponding optional argument for the CLI.
|
76
|
+
randomly, and
|
77
|
+
alias (str, list(str)): Alias for ``executable``. See ``alias`` in
|
78
|
+
`iripau.subprocess.Popen`_.
|
79
|
+
run_args_prefix (str): When calling an instance of this class, all
|
80
|
+
of the ``**kwargs`` starting with this prefix will be passed to
|
81
|
+
the ``run_function`` after removing the prefix.
|
82
|
+
run_function (Callable[List[str] *Any], subprocess.CompletedProcess):
|
83
|
+
The function that will actually run the process, wait for it and
|
84
|
+
return a ``CompletedProcess``.
|
85
|
+
|
86
|
+
If ``None``, the default function is `iripau.command.host_run`_.
|
87
|
+
**kwargs: Keyword arguments to be passed to ``run_function`` every
|
88
|
+
time an instance of this object is called.
|
89
|
+
The ``run_args_prefix`` is not needed here.
|
90
|
+
"""
|
91
|
+
def __init__(
|
92
|
+
self, executable, make_command=make_command, make_option=make_option,
|
93
|
+
alias=None, run_args_prefix="_", run_function=None, **kwargs
|
94
|
+
):
|
95
|
+
self._run = run_function or host_run
|
96
|
+
self._exe = split(executable) if isinstance(executable, str) else executable
|
97
|
+
self._alias = split(alias) if isinstance(alias, str) else alias
|
98
|
+
self._kwargs = kwargs
|
99
|
+
|
100
|
+
self._prefix = run_args_prefix
|
101
|
+
self._mk_option = make_option
|
102
|
+
self._mk_command = make_command
|
103
|
+
|
104
|
+
def __getattr__(self, command):
|
105
|
+
child = Command(self, command)
|
106
|
+
setattr(self, command, child)
|
107
|
+
return child
|
108
|
+
|
109
|
+
def __call__(self, *args, **kwargs):
|
110
|
+
optionals = chain.from_iterable(
|
111
|
+
self._make_arg(self._mk_option(key), value)
|
112
|
+
for key, value in kwargs.items()
|
113
|
+
if not key.startswith(self._prefix)
|
114
|
+
)
|
115
|
+
|
116
|
+
positionals = list(map(str, args))
|
117
|
+
optionals = list(optionals)
|
118
|
+
|
119
|
+
kwargs = {
|
120
|
+
key[len(self._prefix):]: value
|
121
|
+
for key, value in kwargs.items()
|
122
|
+
if key.startswith(self._prefix)
|
123
|
+
}
|
124
|
+
|
125
|
+
if self._alias:
|
126
|
+
kwargs.setdefault("alias", self._alias + positionals + optionals)
|
127
|
+
|
128
|
+
cmd = self._exe + positionals + optionals
|
129
|
+
return self._run(cmd, **self._kwargs, **kwargs)
|
130
|
+
|
131
|
+
@staticmethod
|
132
|
+
def _is_iterable(value):
|
133
|
+
if isinstance(value, (str, bytes)):
|
134
|
+
return False
|
135
|
+
return hasattr(value, "__iter__")
|
136
|
+
|
137
|
+
@classmethod
|
138
|
+
def _make_arg(cls, options, value):
|
139
|
+
""" Return a list of tokens.
|
140
|
+
|
141
|
+
Args:
|
142
|
+
options (Tuple[str]): One of this strings will be randomly chosen.
|
143
|
+
|
144
|
+
If the chosen option starts with ``--``, there will be a
|
145
|
+
single token with the option and the value: ``["--option=value"]``
|
146
|
+
|
147
|
+
If not, there will be two tokens: ``["-o", "value"]``.
|
148
|
+
value: The value of the optional argument for the CLI.
|
149
|
+
|
150
|
+
If ``True``, the option will be treated as a flag, with no
|
151
|
+
value: ``["--option"]``.
|
152
|
+
|
153
|
+
If ``False`` or ``None``, the option will be ignored: ``[]``.
|
154
|
+
|
155
|
+
If an iterable and not a string, the option will be repeated
|
156
|
+
for each item: ``["--option=value1", "--option=value2"]
|
157
|
+
|
158
|
+
Otherwise, it will be converted to a string before using it.
|
159
|
+
"""
|
160
|
+
if cls._is_iterable(value):
|
161
|
+
return chain.from_iterable(
|
162
|
+
cls._make_arg(options, item)
|
163
|
+
for item in value
|
164
|
+
)
|
165
|
+
|
166
|
+
if value in {None, False}:
|
167
|
+
return []
|
168
|
+
|
169
|
+
option = choice(options)
|
170
|
+
if value is True:
|
171
|
+
return [option]
|
172
|
+
|
173
|
+
value = str(value)
|
174
|
+
if option.startswith("--"):
|
175
|
+
return [option + "=" + value]
|
176
|
+
return [option, value]
|
@@ -50,8 +50,8 @@ class LoggerFile:
|
|
50
50
|
|
51
51
|
|
52
52
|
class SimpleThreadNameFormatter(logging.Formatter):
|
53
|
-
""" The same logging.Formatter but threadName is just the first token
|
54
|
-
splitting it: record.threadName.split(maxsplit=1)[0]
|
53
|
+
""" The same ``logging.Formatter`` but threadName is just the first token
|
54
|
+
after splitting it: ``record.threadName.split(maxsplit=1)[0]``.
|
55
55
|
"""
|
56
56
|
|
57
57
|
def format(self, record):
|
@@ -1,5 +1,5 @@
|
|
1
1
|
"""
|
2
|
-
|
2
|
+
A wrapper of the requests module
|
3
3
|
"""
|
4
4
|
|
5
5
|
import requests
|
@@ -79,3 +79,31 @@ class Session(requests.Session):
|
|
79
79
|
echo
|
80
80
|
)
|
81
81
|
return response
|
82
|
+
|
83
|
+
|
84
|
+
def delete(*args, **kwargs):
|
85
|
+
return Session().delete(*args, **kwargs)
|
86
|
+
|
87
|
+
|
88
|
+
def get(*args, **kwargs):
|
89
|
+
return Session().get(*args, **kwargs)
|
90
|
+
|
91
|
+
|
92
|
+
def head(*args, **kwargs):
|
93
|
+
return Session().head(*args, **kwargs)
|
94
|
+
|
95
|
+
|
96
|
+
def options(*args, **kwargs):
|
97
|
+
return Session().options(*args, **kwargs)
|
98
|
+
|
99
|
+
|
100
|
+
def patch(*args, **kwargs):
|
101
|
+
return Session().patch(*args, **kwargs)
|
102
|
+
|
103
|
+
|
104
|
+
def post(*args, **kwargs):
|
105
|
+
return Session().post(*args, **kwargs)
|
106
|
+
|
107
|
+
|
108
|
+
def put(*args, **kwargs):
|
109
|
+
return Session().put(*args, **kwargs)
|
@@ -459,17 +459,17 @@ def set_global_echo(value):
|
|
459
459
|
|
460
460
|
def set_global_stdout_files(*files: TeeStream):
|
461
461
|
global GLOBAL_STDOUTS
|
462
|
-
GLOBAL_STDOUTS = set(
|
462
|
+
GLOBAL_STDOUTS = set(files)
|
463
463
|
|
464
464
|
|
465
465
|
def set_global_stderr_files(*files: TeeStream):
|
466
466
|
global GLOBAL_STDERRS
|
467
|
-
GLOBAL_STDERRS = set(
|
467
|
+
GLOBAL_STDERRS = set(files)
|
468
468
|
|
469
469
|
|
470
470
|
def set_global_prompt_files(*files: TeeStream):
|
471
471
|
global GLOBAL_PROMPTS
|
472
|
-
GLOBAL_PROMPTS = set(
|
472
|
+
GLOBAL_PROMPTS = set(files)
|
473
473
|
|
474
474
|
|
475
475
|
def _output_context(kwargs, key, encoding, errors, text):
|
@@ -3,8 +3,22 @@ Tests to validate iripau.requests module
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import pytest
|
6
|
+
import mock
|
6
7
|
|
7
8
|
from iripau.requests import Session
|
9
|
+
from iripau.requests import delete
|
10
|
+
from iripau.requests import get
|
11
|
+
from iripau.requests import head
|
12
|
+
from iripau.requests import options
|
13
|
+
from iripau.requests import patch
|
14
|
+
from iripau.requests import post
|
15
|
+
from iripau.requests import put
|
16
|
+
|
17
|
+
URL = "https://some.url.com:8080/api"
|
18
|
+
KWARGS = {
|
19
|
+
"kwarg1": "Value-1",
|
20
|
+
"kwarg2": "Value-2"
|
21
|
+
}
|
8
22
|
|
9
23
|
|
10
24
|
class TestRequests:
|
@@ -70,3 +84,45 @@ class TestRequests:
|
|
70
84
|
|
71
85
|
assert response.request.headers["API-Key"] != "***"
|
72
86
|
assert response.request.headers["Authorization"] != "***"
|
87
|
+
|
88
|
+
@mock.patch("iripau.requests.Session")
|
89
|
+
def test_delete(self, mock_session):
|
90
|
+
response = delete(URL, **KWARGS)
|
91
|
+
mock_session.return_value.delete.assert_called_once_with(URL, **KWARGS)
|
92
|
+
assert mock_session.return_value.delete.return_value == response
|
93
|
+
|
94
|
+
@mock.patch("iripau.requests.Session")
|
95
|
+
def test_get(self, mock_session):
|
96
|
+
response = get(URL, **KWARGS)
|
97
|
+
mock_session.return_value.get.assert_called_once_with(URL, **KWARGS)
|
98
|
+
assert mock_session.return_value.get.return_value == response
|
99
|
+
|
100
|
+
@mock.patch("iripau.requests.Session")
|
101
|
+
def test_head(self, mock_session):
|
102
|
+
response = head(URL, **KWARGS)
|
103
|
+
mock_session.return_value.head.assert_called_once_with(URL, **KWARGS)
|
104
|
+
assert mock_session.return_value.head.return_value == response
|
105
|
+
|
106
|
+
@mock.patch("iripau.requests.Session")
|
107
|
+
def test_options(self, mock_session):
|
108
|
+
response = options(URL, **KWARGS)
|
109
|
+
mock_session.return_value.options.assert_called_once_with(URL, **KWARGS)
|
110
|
+
assert mock_session.return_value.options.return_value == response
|
111
|
+
|
112
|
+
@mock.patch("iripau.requests.Session")
|
113
|
+
def test_patch(self, mock_session):
|
114
|
+
response = patch(URL, **KWARGS)
|
115
|
+
mock_session.return_value.patch.assert_called_once_with(URL, **KWARGS)
|
116
|
+
assert mock_session.return_value.patch.return_value == response
|
117
|
+
|
118
|
+
@mock.patch("iripau.requests.Session")
|
119
|
+
def test_post(self, mock_session):
|
120
|
+
response = post(URL, **KWARGS)
|
121
|
+
mock_session.return_value.post.assert_called_once_with(URL, **KWARGS)
|
122
|
+
assert mock_session.return_value.post.return_value == response
|
123
|
+
|
124
|
+
@mock.patch("iripau.requests.Session")
|
125
|
+
def test_put(self, mock_session):
|
126
|
+
response = put(URL, **KWARGS)
|
127
|
+
mock_session.return_value.put.assert_called_once_with(URL, **KWARGS)
|
128
|
+
assert mock_session.return_value.put.return_value == response
|
@@ -1,108 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Execute commands as Python functions
|
3
|
-
"""
|
4
|
-
|
5
|
-
from shlex import split
|
6
|
-
from random import choice
|
7
|
-
from itertools import chain
|
8
|
-
|
9
|
-
from iripau.command import host_run
|
10
|
-
|
11
|
-
|
12
|
-
class Command:
|
13
|
-
""" Run an executable command as a Python callable """
|
14
|
-
|
15
|
-
def __init__(self, parent, command):
|
16
|
-
self._parent = parent
|
17
|
-
self._command = parent._mk_command(command)
|
18
|
-
self._mk_command = parent._mk_command
|
19
|
-
|
20
|
-
def __getattr__(self, command):
|
21
|
-
child = Command(self, command)
|
22
|
-
setattr(self, command, child)
|
23
|
-
return child
|
24
|
-
|
25
|
-
def __call__(self, *args, **kwargs):
|
26
|
-
return self._parent(self._command, *args, **kwargs)
|
27
|
-
|
28
|
-
|
29
|
-
def make_command(command):
|
30
|
-
return command.replace("_", "-")
|
31
|
-
|
32
|
-
|
33
|
-
def make_option(option):
|
34
|
-
return "--" + option.replace("_", "-"),
|
35
|
-
|
36
|
-
|
37
|
-
class Executable:
|
38
|
-
""" Run an executable as a Python callable """
|
39
|
-
|
40
|
-
def __init__(
|
41
|
-
self, executable, make_command=make_command, make_option=make_option,
|
42
|
-
alias=None, run_args_prefix="_", run_function=None, **kwargs
|
43
|
-
):
|
44
|
-
self._run = run_function or host_run
|
45
|
-
self._exe = split(executable) if isinstance(executable, str) else executable
|
46
|
-
self._alias = split(alias) if isinstance(alias, str) else alias
|
47
|
-
self._kwargs = kwargs
|
48
|
-
|
49
|
-
self._prefix = run_args_prefix
|
50
|
-
self._mk_option = make_option
|
51
|
-
self._mk_command = make_command
|
52
|
-
|
53
|
-
def __getattr__(self, command):
|
54
|
-
child = Command(self, command)
|
55
|
-
setattr(self, command, child)
|
56
|
-
return child
|
57
|
-
|
58
|
-
def __call__(self, *args, **kwargs):
|
59
|
-
optionals = chain.from_iterable(
|
60
|
-
self._make_arg(self._mk_option(key), value)
|
61
|
-
for key, value in kwargs.items()
|
62
|
-
if not key.startswith(self._prefix)
|
63
|
-
)
|
64
|
-
|
65
|
-
positionals = list(map(str, args))
|
66
|
-
optionals = list(optionals)
|
67
|
-
|
68
|
-
kwargs = {
|
69
|
-
key[len(self._prefix):]: value
|
70
|
-
for key, value in kwargs.items()
|
71
|
-
if key.startswith(self._prefix)
|
72
|
-
}
|
73
|
-
|
74
|
-
if self._alias:
|
75
|
-
kwargs.setdefault("alias", self._alias + positionals + optionals)
|
76
|
-
|
77
|
-
cmd = self._exe + positionals + optionals
|
78
|
-
return self._run(cmd, **self._kwargs, **kwargs)
|
79
|
-
|
80
|
-
@staticmethod
|
81
|
-
def _is_iterable(value):
|
82
|
-
if isinstance(value, (str, bytes)):
|
83
|
-
return False
|
84
|
-
return hasattr(value, "__iter__")
|
85
|
-
|
86
|
-
@classmethod
|
87
|
-
def _make_arg(cls, options, value=None):
|
88
|
-
""" Return a list of tokens. Randomly choose a short or long option.
|
89
|
-
If a 'value' is given it's appended appropriately.
|
90
|
-
If 'value' is iterable, the option will be repeated for each item.
|
91
|
-
"""
|
92
|
-
if cls._is_iterable(value):
|
93
|
-
return chain.from_iterable(
|
94
|
-
cls._make_arg(options, item)
|
95
|
-
for item in value
|
96
|
-
)
|
97
|
-
|
98
|
-
if value in {None, False}:
|
99
|
-
return []
|
100
|
-
|
101
|
-
option = choice(options)
|
102
|
-
if value is True:
|
103
|
-
return [option]
|
104
|
-
|
105
|
-
value = str(value)
|
106
|
-
if option.startswith("--"):
|
107
|
-
return [option + "=" + value]
|
108
|
-
return [option, value]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|