Compare commits

..

3 Commits
v0.2.2 ... main

Author SHA1 Message Date
62e79c03b6 allow early stop calls to CLI spinner 2025-11-11 10:07:02 +01:00
d14448293b bump version to v0.2.3 2025-11-11 09:54:16 +01:00
332162775f do not suppress KeyboardInterrupts in CLI loader 2025-11-11 09:53:28 +01:00
2 changed files with 10 additions and 7 deletions

View File

@ -1,6 +1,6 @@
[project] [project]
name = "dopt-basics" name = "dopt-basics"
version = "0.2.2" version = "0.2.4"
description = "basic cross-project tools for Python-based d-opt projects" description = "basic cross-project tools for Python-based d-opt projects"
authors = [ authors = [
{name = "Florian Förster", email = "f.foerster@d-opt.com"}, {name = "Florian Förster", email = "f.foerster@d-opt.com"},
@ -69,7 +69,7 @@ directory = "reports/coverage"
[tool.bumpversion] [tool.bumpversion]
current_version = "0.2.2" current_version = "0.2.4"
parse = """(?x) parse = """(?x)
(?P<major>0|[1-9]\\d*)\\. (?P<major>0|[1-9]\\d*)\\.
(?P<minor>0|[1-9]\\d*)\\. (?P<minor>0|[1-9]\\d*)\\.

View File

@ -24,6 +24,7 @@ class LoadingAnimation:
self.ending_text = ending_text self.ending_text = ending_text
self.timeout = timeout self.timeout = timeout
self.done: bool = False self.done: bool = False
self.keyboard_interrupt: bool = False
self._isatty = sys.stdout.isatty() self._isatty = sys.stdout.isatty()
self._do_animation = bool(sys.stdout.isatty()) self._do_animation = bool(sys.stdout.isatty())
@ -53,16 +54,15 @@ class LoadingAnimation:
exc_type: type[Exception], exc_type: type[Exception],
exc_value, exc_value,
tb, tb,
) -> bool: ) -> None:
if exc_type is not None: if exc_type is not None:
self.stop(interrupt=True) self.stop(interrupt=True)
if exc_type is KeyboardInterrupt: if exc_type is KeyboardInterrupt:
self.keyboard_interrupt = True
print("Operation cancelled by user. (KeyboardInterrupt)", flush=True) print("Operation cancelled by user. (KeyboardInterrupt)", flush=True)
return True return
return False
self.stop() self.stop()
return False
def _animation(self) -> None: def _animation(self) -> None:
for frame in cycle(self.frames): for frame in cycle(self.frames):
@ -81,6 +81,9 @@ class LoadingAnimation:
self, self,
interrupt: bool = False, interrupt: bool = False,
) -> None: ) -> None:
if self.done:
return
self.done = True self.done = True
if self._do_animation: if self._do_animation:
self._thread.join() self._thread.join()
@ -100,6 +103,6 @@ def default_loading(func: Callable[P, T]) -> Callable[P, T]:
with LoadingAnimation(loading_txt, ending_text): with LoadingAnimation(loading_txt, ending_text):
res = func(*args, **kwargs) res = func(*args, **kwargs)
return res # type: ignore return res
return wrapper return wrapper