gluetool 3.3__tar.gz → 3.4__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 (59) hide show
  1. {gluetool-3.3 → gluetool-3.4}/PKG-INFO +1 -1
  2. {gluetool-3.3 → gluetool-3.4}/gluetool/glue.py +10 -0
  3. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_tool.py +66 -0
  4. {gluetool-3.3 → gluetool-3.4}/gluetool/tool.py +31 -1
  5. {gluetool-3.3 → gluetool-3.4}/pyproject.toml +2 -2
  6. {gluetool-3.3 → gluetool-3.4}/README.rst +0 -0
  7. {gluetool-3.3 → gluetool-3.4}/assets/html-log/prism.css +0 -0
  8. {gluetool-3.3 → gluetool-3.4}/assets/html-log/prism.js +0 -0
  9. {gluetool-3.3 → gluetool-3.4}/assets/html-log/semantic.min.css +0 -0
  10. {gluetool-3.3 → gluetool-3.4}/assets/html-log/semantic.min.js +0 -0
  11. {gluetool-3.3 → gluetool-3.4}/gluetool/__init__.py +0 -0
  12. {gluetool-3.3 → gluetool-3.4}/gluetool/action.py +0 -0
  13. {gluetool-3.3 → gluetool-3.4}/gluetool/color.py +0 -0
  14. {gluetool-3.3 → gluetool-3.4}/gluetool/help.py +0 -0
  15. {gluetool-3.3 → gluetool-3.4}/gluetool/html_log.py +0 -0
  16. {gluetool-3.3 → gluetool-3.4}/gluetool/log.py +0 -0
  17. {gluetool-3.3 → gluetool-3.4}/gluetool/proxy.py +0 -0
  18. {gluetool-3.3 → gluetool-3.4}/gluetool/py.typed +0 -0
  19. {gluetool-3.3 → gluetool-3.4}/gluetool/pylint/__init__.py +0 -0
  20. {gluetool-3.3 → gluetool-3.4}/gluetool/pylint/option_default.py +0 -0
  21. {gluetool-3.3 → gluetool-3.4}/gluetool/pylint/shared_defined.py +0 -0
  22. {gluetool-3.3 → gluetool-3.4}/gluetool/pylint/unknown_option.py +0 -0
  23. {gluetool-3.3 → gluetool-3.4}/gluetool/result.py +0 -0
  24. {gluetool-3.3 → gluetool-3.4}/gluetool/sentry.py +0 -0
  25. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/__init__.py +0 -0
  26. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroot/config/data_config_root_a +0 -0
  27. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroot/config/data_config_root_b +0 -0
  28. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroot/config/data_not_unicode +0 -0
  29. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configroota/config/data_config_root_a +0 -0
  30. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/assets/parse_config/configrootb/config/data_config_root_b +0 -0
  31. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/conftest.py +0 -0
  32. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_action.py +0 -0
  33. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_core.py +0 -0
  34. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_error.py +0 -0
  35. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_eval_context.py +0 -0
  36. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_help.py +0 -0
  37. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_json.py +0 -0
  38. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_load_yaml.py +0 -0
  39. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_log_exception.py +0 -0
  40. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_logging.py +0 -0
  41. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_module_discovery.py +0 -0
  42. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_new_xml_element.py +0 -0
  43. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_normalize_option.py +0 -0
  44. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_option.py +0 -0
  45. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_parse_config.py +0 -0
  46. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_pipeline_step.py +0 -0
  47. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_render_template.py +0 -0
  48. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_requests.py +0 -0
  49. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_result.py +0 -0
  50. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_run_command.py +0 -0
  51. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_run_modules.py +0 -0
  52. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_treat_url.py +0 -0
  53. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_utils.py +0 -0
  54. {gluetool-3.3 → gluetool-3.4}/gluetool/tests/test_wait.py +0 -0
  55. {gluetool-3.3 → gluetool-3.4}/gluetool/utils.py +0 -0
  56. {gluetool-3.3 → gluetool-3.4}/gluetool/version.py +0 -0
  57. {gluetool-3.3 → gluetool-3.4}/gluetool_modules/__init__.py +0 -0
  58. {gluetool-3.3 → gluetool-3.4}/gluetool_modules/bash_completion.py +0 -0
  59. {gluetool-3.3 → gluetool-3.4}/gluetool_modules/yaml_pipeline.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: gluetool
3
- Version: 3.3
3
+ Version: 3.4
4
4
  Summary: Python framework for constructing command-line pipelines.
5
5
  Home-page: https://gluetool.readthedocs.org/
6
6
  License: BSD
@@ -1788,6 +1788,15 @@ class Glue(Configurable):
1788
1788
  'action': 'store_true',
1789
1789
  'default': False
1790
1790
  },
1791
+ 'sigterm-timeout': {
1792
+ 'help': """
1793
+ Time, in seconds, to wait for a child process to exit after sending it ``SIGTERM``,
1794
+ before resorting to ``SIGKILL``. Takes precedence over the ``GLUETOOL_SIGTERM_TIMEOUT``
1795
+ environment variable (Default: 60).
1796
+ """,
1797
+ 'type': int,
1798
+ 'default': None
1799
+ },
1791
1800
  }),
1792
1801
  ('Output control', {
1793
1802
  ('c', 'colors'): {
@@ -2510,6 +2519,7 @@ class Glue(Configurable):
2510
2519
  * GLUETOOL_TRACING_SERVICE_NAME (string) - name of the trace produced by tool execution
2511
2520
  * GLUETOOL_TRACING_REPORTING_HOST (string) - a hostname where tracing collector listens
2512
2521
  * GLUETOOL_TRACING_REPORTING_PORT (int) - a port on which tracing collector listens
2522
+ * GLUETOOL_SIGTERM_TIMEOUT (int) - seconds to wait for a child to exit after SIGTERM before SIGKILL
2513
2523
  """).format(module_dirs, data_dirs, module_config_dirs)
2514
2524
 
2515
2525
  self._parse_args(args,
@@ -175,3 +175,69 @@ def test_signal(monkeypatch, log, tested_signal, exception, terminate_process_tr
175
175
  assert log.match(levelno=logging.WARNING, message=warnmsg)
176
176
  assert log.match(levelno=logging.DEBUG, message='Exiting with status 0')
177
177
  assert log.match(levelno=logging.INFO, message='gluetool some-version')
178
+
179
+
180
+ def test_sigterm_timeout_default(monkeypatch):
181
+ monkeypatch.delenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, raising=False)
182
+
183
+ assert gluetool.tool.sigterm_timeout() == gluetool.tool.DEFAULT_SIGTERM_TIMEOUT
184
+
185
+
186
+ @pytest.mark.parametrize('value,expected', [
187
+ ('0', 0),
188
+ ('1', 1),
189
+ ('120', 120),
190
+ ], ids=['zero', 'one', 'custom'])
191
+ def test_sigterm_timeout_envvar(monkeypatch, value, expected):
192
+ monkeypatch.setenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, value)
193
+
194
+ assert gluetool.tool.sigterm_timeout() == expected
195
+
196
+
197
+ def test_sigterm_timeout_envvar_invalid(monkeypatch):
198
+ monkeypatch.setenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, 'not-a-number')
199
+
200
+ with pytest.raises(ValueError):
201
+ gluetool.tool.sigterm_timeout()
202
+
203
+
204
+ def test_sigterm_timeout_option_overrides_envvar(monkeypatch):
205
+ # The `sigterm-timeout` option (command line or configuration file) takes precedence over the env variable.
206
+ monkeypatch.setenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, '30')
207
+
208
+ glue = MagicMock()
209
+ glue.option = MagicMock(return_value=90)
210
+
211
+ assert gluetool.tool.sigterm_timeout(glue) == 90
212
+ glue.option.assert_called_once_with('sigterm-timeout')
213
+
214
+
215
+ def test_sigterm_timeout_option_unset_falls_back_to_envvar(monkeypatch):
216
+ # When the option is not set, the env variable is used.
217
+ monkeypatch.setenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, '30')
218
+
219
+ glue = MagicMock()
220
+ glue.option = MagicMock(return_value=None)
221
+
222
+ assert gluetool.tool.sigterm_timeout(glue) == 30
223
+
224
+
225
+ def test_sigterm_timeout_option_unset_falls_back_to_default(monkeypatch):
226
+ # When neither the option nor the env variable is set, the default is used.
227
+ monkeypatch.delenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, raising=False)
228
+
229
+ glue = MagicMock()
230
+ glue.option = MagicMock(return_value=None)
231
+
232
+ assert gluetool.tool.sigterm_timeout(glue) == gluetool.tool.DEFAULT_SIGTERM_TIMEOUT
233
+
234
+
235
+ def test_sigterm_timeout_option_from_cmdline(monkeypatch):
236
+ # The `sigterm-timeout` option is wired into the command-line parser and parsed as an integer.
237
+ monkeypatch.delenv(gluetool.tool.SIGTERM_TIMEOUT_ENVVAR, raising=False)
238
+
239
+ glue = NonLoadingGlue()
240
+ glue._parse_args(['--sigterm-timeout', '120'])
241
+
242
+ assert glue.option('sigterm-timeout') == 120
243
+ assert gluetool.tool.sigterm_timeout(glue) == 120
@@ -44,6 +44,36 @@ DEFAULT_GLUETOOL_CONFIG_PATHS = [
44
44
 
45
45
  DEFAULT_SIGTERM_TIMEOUT = 60
46
46
 
47
+ # Environment variable overriding the time (in seconds) ``gluetool`` waits for a child process to exit after
48
+ # sending it ``SIGTERM`` before resorting to ``SIGKILL``.
49
+ SIGTERM_TIMEOUT_ENVVAR = 'GLUETOOL_SIGTERM_TIMEOUT'
50
+
51
+
52
+ def sigterm_timeout(glue: Optional['gluetool.glue.Glue'] = None) -> int:
53
+ """
54
+ Return the time, in seconds, ``gluetool`` waits for a child process to exit after sending it ``SIGTERM``
55
+ before resorting to ``SIGKILL``.
56
+
57
+ The value is resolved with the following precedence:
58
+
59
+ 1. the ``sigterm-timeout`` option (set on the command line or in a configuration file),
60
+ 2. the :py:data:`SIGTERM_TIMEOUT_ENVVAR` environment variable,
61
+ 3. :py:data:`DEFAULT_SIGTERM_TIMEOUT`.
62
+
63
+ :param glue: ``Glue`` instance to read the ``sigterm-timeout`` option from. When not provided, the option
64
+ is skipped and the value is resolved from the environment variable or the default.
65
+ """
66
+
67
+ if glue is not None:
68
+ option = glue.option('sigterm-timeout')
69
+ if option is not None:
70
+ return cast(int, option)
71
+
72
+ if SIGTERM_TIMEOUT_ENVVAR in os.environ:
73
+ return int(os.environ[SIGTERM_TIMEOUT_ENVVAR])
74
+
75
+ return DEFAULT_SIGTERM_TIMEOUT
76
+
47
77
 
48
78
  def handle_exc(func: Callable[..., Any]) -> Callable[..., Any]:
49
79
 
@@ -305,7 +335,7 @@ Will try to submit it to Sentry but giving up on everything else.
305
335
  child.terminate()
306
336
 
307
337
  try:
308
- child.wait(timeout=DEFAULT_SIGTERM_TIMEOUT)
338
+ child.wait(timeout=sigterm_timeout(Glue))
309
339
 
310
340
  except psutil.TimeoutExpired:
311
341
  Glue.warn("Sending SIGKILL to child process '{}' (PID {})".format(child.name(), child.pid))
@@ -4,7 +4,7 @@ dynamic = ["version"]
4
4
 
5
5
  [tool.poetry]
6
6
  name = "gluetool"
7
- version = "3.3"
7
+ version = "3.4"
8
8
  description = "Python framework for constructing command-line pipelines."
9
9
  authors = [
10
10
  "Milos Prchlik <mprchlik@redhat.com>",
@@ -108,7 +108,7 @@ opentelemetry-sdk = "^1.40.0"
108
108
  opentelemetry-exporter-otlp-proto-grpc = "^1.40.0"
109
109
 
110
110
  [tool.poetry-dynamic-versioning]
111
- enable = true
111
+ enable = false
112
112
 
113
113
  [build-system]
114
114
  requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning>=1.0.0,<2.0.0"]
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