Stopwatch

Summary

Package:

pyTooling

Doc-string:

documented

File

Expected

Covered

Uncovered

Coverage

__init__.py

93

93

0

100.0%

Overall (1 files)

93

93

0

100.0%

Source

pyTooling/Stopwatch/__init__.pydocumentedundocumentedignoredexcludednot counted
31"""
32A stopwatch to measure execution times.
33
34.. hint::
35
36   See :ref:`high-level help <COMMON/Stopwatch>` for explanations and usage examples.
37
38.. seealso::
39
40   :mod:`pyTooling.Tracing`
41      |rarr| Nested timespans instead of a single measurement, for tracing an execution.
42   :mod:`pyTooling.Process`
43      |rarr| The process' memory usage, next to its runtime.
44"""
...
56
58@export
59class StopwatchError(ToolingException):
60	"""This exception is caused by wrong usage of the stopwatch."""
61
63@export
64class Duration(timedelta):
65	"""
66	A :class:`~datetime.timedelta` resolving nanoseconds, which can be formatted by a format specification.
67
68	The constructor takes the parameters of :class:`~datetime.timedelta` (``days``, ``seconds``, ``microseconds``,
69	``milliseconds``, ``minutes``, ``hours``, ``weeks``) and ``nanoseconds``; all of them are added up. Like
70	:class:`~datetime.timedelta`, a duration is normalized into components: :attr:`~datetime.timedelta.days` (the only
71	one with a sign), :attr:`~datetime.timedelta.seconds` (``0`` to ``86399``) and :attr:`nanoseconds` (``0`` to
72	``999999999``). The inherited :attr:`~datetime.timedelta.microseconds` is ``nanoseconds // 1000``, so code written
73	for :class:`~datetime.timedelta` sees the duration truncated to microseconds. An existing
74	:class:`~datetime.timedelta` is converted by :meth:`FromTimedelta`.
75
76	Arithmetic and comparisons involving a duration calculate in nanoseconds and return a duration (or a number, where
77	:class:`~datetime.timedelta` returns one). A :class:`~datetime.timedelta` operand is converted.
78	``datetime + duration`` stays the arithmetic of :class:`~datetime.datetime`, which resolves microseconds.
79
80	.. note::
81
82	   :class:`~datetime.timedelta` is a C type, so this is a plain class with ``__slots__``, not an
83	   :class:`~pyTooling.MetaClasses.ExtendedType` class.
84	"""
85
86	__slots__ = ("_nanoseconds",)
87
88	_nanoseconds: int  #: Sub-second component in nanoseconds, ``0`` to ``999999999``.
89
90	_FIELDS: ClassVar[dict[str, Callable[[int], str]]] = {
91		"H": lambda nanoseconds: f"{nanoseconds // 3_600_000_000_000:02}",
92		"M": lambda nanoseconds: f"{nanoseconds // 60_000_000_000 % 60:02}",
93		"S": lambda nanoseconds: f"{nanoseconds // 1_000_000_000 % 60:02}",
94		"L": lambda nanoseconds: f"{nanoseconds // 1_000_000 % 1_000:03}",
95		"U": lambda nanoseconds: f"{nanoseconds // 1_000 % 1_000_000:06}",
96		"N": lambda nanoseconds: f"{nanoseconds % 1_000_000_000:09}",
97		"s": lambda nanoseconds: f"{nanoseconds // 1_000_000_000}",
98		"m": lambda nanoseconds: f"{nanoseconds // 1_000_000}",
99		"u": lambda nanoseconds: f"{nanoseconds // 1_000}",
100		"n": lambda nanoseconds: f"{nanoseconds}",
101	}  #: Functions rendering a format specifier from a non-negative duration in nanoseconds.
102
103	def __new__(
104		cls,
105		days:         float = 0,
106		seconds:      float = 0,
107		microseconds: float = 0,
108		milliseconds: float = 0,
109		minutes:      float = 0,
110		hours:        float = 0,
111		weeks:        float = 0,
112		nanoseconds:  float = 0
113	) -> Self:
114		"""
115		Initializes a duration from the sum of all given units.
116
117		The units of :class:`~datetime.timedelta` are converted by :class:`~datetime.timedelta`, so they resolve
118		microseconds; ``nanoseconds`` resolves nanoseconds. A float number of nanoseconds is rounded to the nearest
119		integer.
120
121		:param days:         Optional, number of days. Default: ``0``.
122		:param seconds:      Optional, number of seconds. Default: ``0``.
123		:param microseconds: Optional, number of microseconds. Default: ``0``.
124		:param milliseconds: Optional, number of milliseconds. Default: ``0``.
125		:param minutes:      Optional, number of minutes. Default: ``0``.
126		:param hours:        Optional, number of hours. Default: ``0``.
127		:param weeks:        Optional, number of weeks. Default: ``0``.
128		:param nanoseconds:  Optional, number of nanoseconds. Default: ``0``.
129		:returns:            The duration.
130		:raises TypeError:   If one of the parameters 'days' to 'weeks' is not a number (raised by
131		                     :class:`~datetime.timedelta`).
132		:raises ValueError:  If parameter 'nanoseconds' is None.
133		:raises TypeError:   If parameter 'nanoseconds' is not of type :class:`int` or :class:`float`.
134		"""
		...
156
157	@classmethod
158	def FromTimedelta(cls, value: timedelta) -> Self:
159		"""
160		Convert a :class:`~datetime.timedelta` into a duration.
161
162		A duration given as ``value`` keeps its nanoseconds.
163
164		:param value:       The time delta to convert.
165		:returns:           A duration of the same length.
166		:raises ValueError: If parameter 'value' is None.
167		:raises TypeError:  If parameter 'value' is not of type :class:`~datetime.timedelta`.
168		"""
		...
179
180	@readonly
181	def nanoseconds(self) -> int:
182		"""
183		Read-only property to access the sub-second component in nanoseconds (:attr:`_nanoseconds`).
184
185		It is the counterpart of :attr:`~datetime.timedelta.microseconds` at nanosecond resolution.
186
187		:returns: The nanoseconds of the duration's last second, ``0`` to ``999999999``.
188		"""
		...
190
191	def total_nanoseconds(self) -> int:
192		"""
193		Return the whole duration in nanoseconds.
194
195		It is the counterpart of :meth:`total_seconds` at nanosecond resolution.
196
197		:returns: The duration in nanoseconds.
198		"""
		...
200
201	def total_seconds(self) -> float:
202		"""
203		Return the whole duration in seconds.
204
205		:returns: The duration in seconds, including the nanoseconds.
206		"""
		...
208
209	@staticmethod
210	def _TotalNanoseconds(value: timedelta) -> int:
211		"""
212		Return a time delta in nanoseconds.
213
214		:param value: A :class:`~datetime.timedelta` or a duration.
215		:returns:     The time delta in nanoseconds.
216		"""
		...
221
222	@staticmethod
223	def _DivideRounded(numerator: int, denominator: int) -> int:
224		"""
225		Divide two integers, rounding half to even like :class:`~datetime.timedelta` does.
226
227		:param numerator:   The dividend.
228		:param denominator: The divisor.
229		:returns:           The quotient, rounded to the nearest integer; on a tie to the even one.
230		"""
		...
241
242	def __bool__(self) -> bool:
243		"""
244		Check if the duration is not zero.
245
246		:returns: ``True``, if the duration is not zero.
247		"""
		...
249
250	def __eq__(self, other: Any) -> bool:
251		"""
252		Compare two durations for equality, in nanoseconds.
253
254		:param other:      A duration or a :class:`~datetime.timedelta` to compare with.
255		:returns:          ``True``, if both durations are equal.
256		:raises TypeError: If parameter 'other' is not of type :class:`~datetime.timedelta`.
257		"""
		...
267
268	def __ne__(self, other: Any) -> bool:
269		"""
270		Compare two durations for inequality, in nanoseconds.
271
272		:param other:      A duration or a :class:`~datetime.timedelta` to compare with.
273		:returns:          ``True``, if both durations are not equal.
274		:raises TypeError: If parameter 'other' is not of type :class:`~datetime.timedelta`.
275		"""
		...
283
284	def __lt__(self, other: Any) -> bool:
285		"""
286		Compare two durations for less-than, in nanoseconds.
287
288		:param other:      A duration or a :class:`~datetime.timedelta` to compare with.
289		:returns:          ``True``, if this duration is shorter.
290		:raises TypeError: If parameter 'other' is not of type :class:`~datetime.timedelta`.
291		"""
		...
299
300	def __le__(self, other: Any) -> bool:
301		"""
302		Compare two durations for less-than-or-equal, in nanoseconds.
303
304		:param other:      A duration or a :class:`~datetime.timedelta` to compare with.
305		:returns:          ``True``, if this duration is shorter or equal.
306		:raises TypeError: If parameter 'other' is not of type :class:`~datetime.timedelta`.
307		"""
		...
315
316	def __gt__(self, other: Any) -> bool:
317		"""
318		Compare two durations for greater-than, in nanoseconds.
319
320		:param other:      A duration or a :class:`~datetime.timedelta` to compare with.
321		:returns:          ``True``, if this duration is longer.
322		:raises TypeError: If parameter 'other' is not of type :class:`~datetime.timedelta`.
323		"""
		...
331
332	def __ge__(self, other: Any) -> bool:
333		"""
334		Compare two durations for greater-than-or-equal, in nanoseconds.
335
336		:param other:      A duration or a :class:`~datetime.timedelta` to compare with.
337		:returns:          ``True``, if this duration is longer or equal.
338		:raises TypeError: If parameter 'other' is not of type :class:`~datetime.timedelta`.
339		"""
		...
347
348	def __hash__(self) -> int:
349		"""
350		Return a hash, which equals the hash of an equal :class:`~datetime.timedelta`.
351
352		:returns: The hash value.
353		"""
		...
358
359	def __neg__(self) -> Self:
360		"""
361		Negate the duration.
362
363		:returns: The negated duration.
364		"""
		...
366
367	def __pos__(self) -> Self:
368		"""
369		Return the duration unchanged.
370
371		:returns: This duration.
372		"""
		...
374
375	def __abs__(self) -> Self:
376		"""
377		Return the absolute duration.
378
379		:returns: The duration without sign.
380		"""
		...
382
383	def __add__(self, other: Any) -> Any:
384		"""
385		Add a duration or a :class:`~datetime.timedelta`.
386
387		Other operands are left to :class:`~datetime.timedelta`: ``duration + datetime`` is a
388		:class:`~datetime.datetime`.
389
390		:param other: The second operand.
391		:returns:     The sum as a duration.
392		"""
		...
397
398	def __radd__(self, other: Any) -> Any:
399		"""
400		Add this duration to a :class:`~datetime.timedelta`.
401
402		:param other: The first operand.
403		:returns:     The sum as a duration.
404		"""
		...
409
410	def __sub__(self, other: Any) -> Any:
411		"""
412		Subtract a duration or a :class:`~datetime.timedelta`.
413
414		:param other: The second operand.
415		:returns:     The difference as a duration.
416		"""
		...
421
422	def __rsub__(self, other: Any) -> Any:
423		"""
424		Subtract this duration from a :class:`~datetime.timedelta`.
425
426		:param other: The first operand.
427		:returns:     The difference as a duration.
428		"""
		...
433
434	def __mul__(self, other: Any) -> Any:
435		"""
436		Multiply the duration by a number.
437
438		A product with a :class:`float` is rounded to the nearest nanosecond, on a tie to the even one.
439
440		:param other: An :class:`int` or :class:`float` factor.
441		:returns:     The product as a duration.
442		"""
		...
450
451	def __rmul__(self, other: Any) -> Any:
452		"""
453		Multiply a number by the duration.
454
455		:param other: An :class:`int` or :class:`float` factor.
456		:returns:     The product as a duration.
457		"""
		...
459
460	def __truediv__(self, other: Any) -> Any:
461		"""
462		Divide the duration by a duration, a :class:`~datetime.timedelta` or a number.
463
464		A quotient of a number is rounded to the nearest nanosecond, on a tie to the even one.
465
466		:param other: The divisor.
467		:returns:     The ratio as a :class:`float` for a time delta divisor, otherwise the quotient as a duration.
468		"""
		...
478
479	def __rtruediv__(self, other: Any) -> Any:
480		"""
481		Divide a :class:`~datetime.timedelta` by the duration.
482
483		:param other: The dividend.
484		:returns:     The ratio as a :class:`float`.
485		"""
		...
490
491	def __floordiv__(self, other: Any) -> Any:
492		"""
493		Divide the duration by a duration, a :class:`~datetime.timedelta` or an integer, rounding down.
494
495		:param other: The divisor.
496		:returns:     The ratio as an :class:`int` for a time delta divisor, otherwise the quotient as a duration.
497		"""
		...
504
505	def __rfloordiv__(self, other: Any) -> Any:
506		"""
507		Divide a :class:`~datetime.timedelta` by the duration, rounding down.
508
509		:param other: The dividend.
510		:returns:     The ratio as an :class:`int`.
511		"""
		...
516
517	def __mod__(self, other: Any) -> Any:
518		"""
519		Return the remainder of dividing the duration by a duration or a :class:`~datetime.timedelta`.
520
521		:param other: The divisor.
522		:returns:     The remainder as a duration.
523		"""
		...
528
529	def __rmod__(self, other: Any) -> Any:
530		"""
531		Return the remainder of dividing a :class:`~datetime.timedelta` by the duration.
532
533		:param other: The dividend.
534		:returns:     The remainder as a duration.
535		"""
		...
540
541	def __divmod__(self, other: Any) -> Any:
542		"""
543		Divide the duration by a duration or a :class:`~datetime.timedelta`, returning quotient and remainder.
544
545		:param other: The divisor.
546		:returns:     The quotient as an :class:`int` and the remainder as a duration.
547		"""
		...
553
554	def __rdivmod__(self, other: Any) -> Any:
555		"""
556		Divide a :class:`~datetime.timedelta` by the duration, returning quotient and remainder.
557
558		:param other: The dividend.
559		:returns:     The quotient as an :class:`int` and the remainder as a duration.
560		"""
		...
566
567	def __reduce__(self) -> tuple[type[Self], tuple[int, ...]]:
568		"""
569		Return how to rebuild the duration, so :mod:`pickle` and :mod:`copy` keep its nanoseconds.
570
571		:returns: The class and its constructor arguments.
572		"""
		...
574
575	def __repr__(self) -> str:
576		"""
577		Return the duration as a constructor call.
578
579		Only components other than zero are named. A duration resolving more than microseconds names ``nanoseconds``
580		instead of ``microseconds``. A zero duration is ``Duration(0)``.
581
582		:returns: The constructor call, e.g. ``Duration(seconds=1, nanoseconds=5)``.
583		"""
		...
600
601	def __str__(self) -> str:
602		"""
603		Return the duration like :class:`~datetime.timedelta` does.
604
605		A duration resolving more than microseconds shows 9 fractional digits instead of 6.
606
607		:returns: The duration as ``[D day[s], ]H:MM:SS[.ffffff]``, or with 9 fractional digits.
608		"""
		...
616
617	def __format__(self, formatSpec: str) -> str:
618		"""
619		Return the duration according to the format specification.
620
621		.. topic:: Format Specifiers
622
623		   An **uppercase** specifier is a field of the duration as it would be displayed. A **lowercase** specifier is
624		   the whole duration expressed in one unit, which is what a report or a comparison wants.
625
626		   +-----------+--------------------------------------------------------+
627		   | Specifier | Meaning                                                |
628		   +===========+========================================================+
629		   | ``%H``    | hours, not capped - a 26 hour duration shows ``26``    |
630		   +-----------+--------------------------------------------------------+
631		   | ``%M``    | minutes, ``00`` to ``59``                              |
632		   +-----------+--------------------------------------------------------+
633		   | ``%S``    | seconds, ``00`` to ``59``                              |
634		   +-----------+--------------------------------------------------------+
635		   | ``%L``    | fractional seconds, 3 digits (milliseconds)            |
636		   +-----------+--------------------------------------------------------+
637		   | ``%U``    | fractional seconds, 6 digits (microseconds)            |
638		   +-----------+--------------------------------------------------------+
639		   | ``%N``    | fractional seconds, 9 digits (nanoseconds)             |
640		   +-----------+--------------------------------------------------------+
641		   | ``%s``    | the whole duration in seconds                          |
642		   +-----------+--------------------------------------------------------+
643		   | ``%m``    | the whole duration in milliseconds                     |
644		   +-----------+--------------------------------------------------------+
645		   | ``%u``    | the whole duration in microseconds                     |
646		   +-----------+--------------------------------------------------------+
647		   | ``%n``    | the whole duration in nanoseconds                      |
648		   +-----------+--------------------------------------------------------+
649
650		   The fractional specifiers are truncations of the same fraction, so ``%S.%U`` renders ``04.123456`` without
651		   having to be combined with anything. ``%H`` is not capped, so ``%H:%M:%S`` never silently drops a day.
652
653		   A negative duration renders the fields of its absolute value, with a ``-`` in front of the first placeholder:
654		   ``took %s s`` renders ``took -5 s``.
655
656		   ``%%`` renders a literal percent sign. An empty format specification returns :meth:`__str__`.
657
658		:param formatSpec:  The format specification, using ``%``-placeholders for the duration's parts.
659		:returns:           The formatted duration.
660		:raises ValueError: If the format specification contains an unknown placeholder.
661		"""
		...
687
689@export
690class ExcludeContextManager:
691	"""
692	A stopwatch context manager for excluding certain time spans from measurement.
693
694	While a normal stopwatch's embedded context manager (re)starts the stopwatch on every *enter* event and pauses the
695	stopwatch on every *exit* event, this context manager pauses on *enter* events and restarts on every *exit* event.
696	"""
697	_stopwatch: Stopwatch  #: Reference to the stopwatch.
698
699	def __init__(self, stopwatch: Stopwatch) -> None:
700		"""
701		Initializes an excluding context manager.
702
703		:param stopwatch: Reference to the stopwatch.
704		"""
		...
706
707	def __enter__(self) -> Self:
708		"""
709		Enter the context and pause the stopwatch.
710
711		:returns: Excluding stopwatch context manager instance.
712		"""
		...
716
717	def __exit__(
718		self,
719		exc_type: Nullable[type[BaseException]] = None,
720		exc_val:  Nullable[BaseException] = None,
721		exc_tb:   Nullable[TracebackType] = None
722	) -> Nullable[bool]:
723		"""
724		Exit the context and restart stopwatch.
725
726		:param exc_type: Optional, exception type.
727		:param exc_val:  Optional, exception instance.
728		:param exc_tb:   Optional, exception's traceback.
729		:returns:        ``None``
730		"""
		...
732
734@export
735class Stopwatch(SlottedObject):
736	"""
737	The stopwatch implements a solution to measure and collect timings.
738
739	The time measurement can be started, paused, resumed and stopped. More over, split times can be taken too. The
740	measurement is based on :func:`time.perf_counter_ns`. Additionally, starting and stopping is preserved as absolute
741	time via :meth:`datetime.datetime.now`.
742
743	Every split time taken is a time delta to the previous operation. These are preserved in an internal sequence of
744	splits. This sequence includes time deltas of activity and inactivity. Thus, a running stopwatch can be split as well
745	as a paused stopwatch.
746
747	The stopwatch can also be used in a :ref:`with-statement <with>`, because it implements the :ref:`context manager protocol <context-managers>`.
748
749	A stopwatch measures one time span: it is started once and stopped once. There is no restart or reset operation; a
750	new stopwatch measures again.
751	"""
752
753	_name:         Nullable[str]  #: Optional name of the stopwatch.
754	_preferPause:  bool           #: If ``True``, the context manager pauses instead of stopping on exit.
755	_digits:       int            #: Number of fractional digits ``__str__`` renders the duration with.
756
757	_beginTime:    Nullable[datetime]        #: Absolute time when the stopwatch was started.
758	_endTime:      Nullable[datetime]        #: Absolute time when the stopwatch was stopped.
759	_startTime:    Nullable[int]             #: Performance counter in ns when the stopwatch was started.
760	_resumeTime:   Nullable[int]             #: Performance counter in ns of the latest resume operation.
761	_pauseTime:    Nullable[int]             #: Performance counter in ns of the latest pause operation.
762	_stopTime:     Nullable[int]             #: Performance counter in ns when the stopwatch was stopped.
763	_totalTime:    Nullable[int]             #: Duration in ns from starting to stopping, activity and inactivity.
764	_duration:     Nullable[Duration]        #: :attr:`Duration` of a stopped stopwatch, computed on first access.
765	_splits:       list[tuple[float, bool]]  #: Split times as (duration, is-active) pairs, in the order they were taken.
766
767	_excludeContextManager: ExcludeContextManager  #: The nested context manager excluding time spans from measurement.
768
769	def __init__(
770		self,
771		name: Nullable[str] = None,
772		started: bool = False,
773		preferPause: bool = False,
774		digits: int = 3
775	) -> None:
776		"""
777		Initializes the fields of the stopwatch.
778
779		If parameter ``started`` is set to true, the stopwatch will immediately start.
780
781		:param name:        Optional, name of the stopwatch.
782		:param started:     Optional, if ``True``, start the stopwatch immediately.
783		:param preferPause: Optional, if ``True``, ``__exit__(...)`` prefers pause over stop behavior.
784		:param digits:      Optional, number of fractional digits :meth:`__str__` renders the duration with.
785		:raises TypeError:  If parameter 'digits' is not of type :class:`int`.
786		:raises ValueError: If parameter 'digits' is negative or greater than 9.
787		"""
		...
817
818	def Start(self) -> None:
819		"""
820		Start the stopwatch.
821
822		A stopwatch can only be started once. There is no restart or reset operation provided; a new stopwatch measures
823		again.
824
825		:raises StopwatchError: If stopwatch was already started.
826		:raises StopwatchError: If stopwatch was already started and stopped. |br|
827		                        Create a new stopwatch to measure again.
828		"""
		...
838
839	def Split(self) -> float:
840		"""
841		Take a split time and return the time delta to the previous stopwatch operation.
842
843		The stopwatch needs to be running to take a split time. See property :data:`IsRunning` to check if the stopwatch
844		is running and the split operation is possible. |br|
845		Depending on the previous operation, the time delta will be:
846
847		* the duration from start operation to the first split.
848		* the duration from last resume to this split.
849
850		:returns:               Duration in seconds since last stopwatch operation
851		:raises StopwatchError: If stopwatch was not started or resumed.
852		"""
		...
863
864	def Pause(self) -> float:
865		"""
866		Pause the stopwatch and return the time delta to the previous stopwatch operation.
867
868		The stopwatch needs to be running to pause it. See property :data:`IsRunning` to check if the stopwatch is running
869		and the pause operation is possible. |br|
870		Depending on the previous operation, the time delta will be:
871
872		* the duration from start operation to the first pause.
873		* the duration from last resume to this pause.
874
875		:returns:               Duration in seconds since last stopwatch operation
876		:raises StopwatchError: If stopwatch was not started or resumed.
877		"""
		...
888
889	def Resume(self) -> float:
890		"""
891		Resume the stopwatch and return the time delta to the previous pause operation.
892
893		The stopwatch needs to be paused to resume it. See property :data:`IsPaused` to check if the stopwatch is paused
894		and the resume operation is possible. |br|
895		The time delta will be the duration from last pause to this resume.
896
897		:returns:               Duration in seconds since last pause operation
898		:raises StopwatchError: If stopwatch was not paused.
899		"""
		...
910
911	def Stop(self) -> float:
912		"""
913		Stop the stopwatch and return the time delta to the previous stopwatch operation.
914
915		The stopwatch needs to be started to stop it. See property :data:`IsStarted` to check if the stopwatch was started
916		and the stop operation is possible. |br|
917		Depending on the previous operation, the time delta will be:
918
919		* the duration from start operation to the stop operation.
920		* the duration from last resume to the stop operation.
921
922		:returns:               Duration in seconds since last stopwatch operation
923		:raises StopwatchError: If stopwatch was not started.
924		:raises StopwatchError: If stopwatch was already stopped.
925		"""
		...
955
956	@property
957	def Digits(self) -> int:
958		"""
959		Property to get and set the number of fractional digits (:attr:`_digits`) used by :meth:`__str__`.
960
961		The measurement itself is unaffected - this only decides how many digits of the duration in seconds are
962		rendered. It defaults to ``3``, which is milliseconds.
963
964		:returns:           Number of fractional digits.
965		:raises TypeError:  If the assigned value is not of type :class:`int`.
966		:raises ValueError: If the assigned value is negative or greater than 9.
967		"""
		...
969
970	@Digits.setter
971	def Digits(self, digits: int) -> None:
		...
982
983	@readonly
984	def Name(self) -> Nullable[str]:
985		"""
986		Read-only property returning the name of the stopwatch.
987
988		:returns: Name of the stopwatch.
989		"""
		...
991
992	@readonly
993	def IsStarted(self) -> bool:
994		"""
995		Read-only property returning the IsStarted state of the stopwatch.
996
997		:returns: True, if stopwatch was started.
998		"""
		...
1000
1001	@readonly
1002	def IsRunning(self) -> bool:
1003		"""
1004		Read-only property returning the IsRunning state of the stopwatch.
1005
1006		:returns: True, if stopwatch was started and is currently not paused.
1007		"""
		...
1009
1010	@readonly
1011	def IsPaused(self) -> bool:
1012		"""
1013		Read-only property returning the IsPaused state of the stopwatch.
1014
1015		:returns: True, if stopwatch was started and is currently paused.
1016		"""
		...
1018
1019	@readonly
1020	def IsStopped(self) -> bool:
1021		"""
1022		Read-only property returning the IsStopped state of the stopwatch.
1023
1024		:returns: True, if stopwatch was stopped.
1025		"""
		...
1027
1028	@readonly
1029	def StartTime(self) -> Nullable[datetime]:
1030		"""
1031		Read-only property returning the absolute time when the stopwatch was started.
1032
1033		:returns: The time when the stopwatch was started, otherwise None.
1034		"""
		...
1036
1037	@readonly
1038	def StopTime(self) -> Nullable[datetime]:
1039		"""
1040		Read-only property returning the absolute time when the stopwatch was stopped.
1041
1042		:returns: The time when the stopwatch was stopped, otherwise None.
1043		"""
		...
1045
1046	@readonly
1047	def HasSplitTimes(self) -> bool:
1048		"""
1049		Read-only property checking if split times have been taken.
1050
1051		:returns: True, if at least one split time has been taken.
1052		"""
		...
1054
1055	@readonly
1056	def SplitCount(self) -> int:
1057		"""
1058		Read-only property returning the number of split times.
1059
1060		:returns: Number of split times.
1061		"""
		...
1063
1064	@readonly
1065	def ActiveCount(self) -> int:
1066		"""
1067		Read-only property returning the number of active split times.
1068
1069		A running stopwatch is inside an active span that hasn't been recorded yet, and that span is counted here -
1070		the result is what the stopwatch would report if it were stopped right now. This matches
1071		:attr:`Activity`, which includes the running span's duration.
1072
1073		:returns: Number of active split times, including the one in progress.
1074		"""
		...
1079
1080	@readonly
1081	def InactiveCount(self) -> int:
1082		"""
1083		Read-only property returning the number of inactive split times.
1084
1085		A paused stopwatch is inside an inactive span that hasn't been recorded yet, and that span is counted here -
1086		the result is what the stopwatch would report if it were stopped right now. This matches
1087		:attr:`Inactivity`, which includes the paused span's duration.
1088
1089		:returns: Number of inactive split times, including the one in progress.
1090		"""
		...
1095
1096	@readonly
1097	def Activity(self) -> Duration:
1098		"""
1099		Read-only property returning the duration of all active split times.
1100
1101		If the stopwatch is currently running, the duration since start or last resume operation will be included. It is
1102		built from :attr:`ActivityInSeconds`, the same value as a float, so it resolves microseconds.
1103
1104		:returns: Duration of all active split times. If the stopwatch was never started, the return value is a zero
1105		          duration.
1106		"""
		...
1108
1109	@readonly
1110	def ActivityInSeconds(self) -> float:
1111		"""
1112		Read-only property returning the same duration as :attr:`Activity`, but in seconds.
1113
1114		:returns: Duration of all active split times in seconds. If the stopwatch was never started, the return value will
1115		          be 0.0.
1116		"""
		...
1122
1123	@readonly
1124	def Inactivity(self) -> Duration:
1125		"""
1126		Read-only property returning the duration of all inactive split times.
1127
1128		If the stopwatch is currently paused, the duration since last pause operation will be included. It is built from
1129		:attr:`InactivityInSeconds`, the same value as a float, so it resolves microseconds.
1130
1131		:returns: Duration of all inactive split times. If the stopwatch was never started, the return value is a zero
1132		          duration.
1133		"""
		...
1135
1136	@readonly
1137	def InactivityInSeconds(self) -> float:
1138		"""
1139		Read-only property returning the same duration as :attr:`Inactivity`, but in seconds.
1140
1141		:returns: Duration of all inactive split times in seconds. If the stopwatch was never started, the return value will
1142		          be 0.0.
1143		"""
		...
1149
1150	@readonly
1151	def Duration(self) -> Duration:
1152		"""
1153		Read-only property returning the duration from start operation to stop operation.
1154
1155		If the stopwatch is not yet stopped, the duration from start to now is returned. A
1156		:class:`~pyTooling.Stopwatch.Duration` prints as hours, minutes and seconds, accepts a format specification and
1157		resolves nanoseconds; :attr:`DurationInSeconds` and :attr:`DurationInNanoseconds` are the same measurement as
1158		numbers. The duration of a stopped stopwatch is computed once (:attr:`_duration`).
1159
1160		:returns: Duration since the stopwatch was started. If the stopwatch was never started, the return value is a zero
1161		          duration.
1162		"""
		...
1171
1172	@readonly
1173	def DurationInSeconds(self) -> float:
1174		"""
1175		Read-only property returning the same duration as :attr:`Duration`, but in seconds.
1176
1177		:returns: Duration since stopwatch was started in seconds. If the stopwatch was never started, the return value will
1178		          be 0.0.
1179		"""
		...
1181
1182	@readonly
1183	def DurationInNanoseconds(self) -> int:
1184		"""
1185		Read-only property returning the same duration as :attr:`Duration`, but in whole nanoseconds.
1186
1187		This is the measurement as the underlying :func:`time.perf_counter_ns` took it, so anything that divides a
1188		duration into parts - :meth:`__format__` does - works from an integer instead of converting a float back.
1189
1190		Precision is not the reason to prefer it. A float holds a duration in seconds exactly, to the nanosecond, up
1191		to :math:`2^{53}` ns - a little over 104 days - which no stopwatch will reach.
1192
1193		:returns: Duration since the stopwatch was started in nanoseconds. If the stopwatch was never started, the
1194		          return value will be 0.
1195		"""
		...
1202
1203	@readonly
1204	def Exclude(self) -> ExcludeContextManager:
1205		"""
1206		Return an *exclude* context manager for the stopwatch instance.
1207
1208		:returns: An excluding context manager.
1209		"""
		...
1214
1215	def __enter__(self) -> Self:
1216		"""
1217		Enter the context and start or resume the stopwatch.
1218
1219		An unstarted stopwatch is started, a paused one is resumed.
1220
1221		:returns:               The stopwatch itself.
1222		:raises StopwatchError: If the stopwatch is running.
1223		:raises StopwatchError: If the stopwatch was already stopped. |br|
1224		                        Create a new stopwatch to measure again, or create it with ``preferPause=True`` to
1225		                        measure several ``with``-blocks.
1226		"""
		...
1246
1247	def __exit__(
1248		self,
1249		exc_type: Nullable[type[BaseException]] = None,
1250		exc_val:  Nullable[BaseException] = None,
1251		exc_tb:   Nullable[TracebackType] = None
1252	) -> Nullable[bool]:
1253		"""
1254		Exit the context and pause or stop the stopwatch.
1255
1256		A running stopwatch is paused, if ``preferPause`` was set, otherwise it's stopped.
1257
1258		:param exc_type:        Optional, exception type, otherwise None.
1259		:param exc_val:         Optional, exception object, otherwise None.
1260		:param exc_tb:          Optional, exception's traceback, otherwise None.
1261		:returns:               ``None``
1262		:raises StopwatchError: If the stopwatch was never started.
1263		:raises StopwatchError: If the stopwatch was already stopped.
1264		:raises StopwatchError: If the stopwatch is paused, because it wasn't resumed.
1265		"""
		...
1288
1289	def __len__(self) -> int:
1290		"""
1291		Implementation of ``len(...)`` to return the number of split times.
1292
1293		:returns: Number of split times.
1294		"""
		...
1296
1297	def __getitem__(self, index: int) -> tuple[float, bool]:
1298		"""
1299		Implementation of ``split = object[i]`` to return the i-th split time.
1300
1301		:param index:       Index to access the i-th split time.
1302		:returns:           i-th split time as a tuple of: |br|
1303		                    (1) delta time to the previous stopwatch operation and |br|
1304		                    (2) a boolean indicating if the split was an activity (true) or inactivity (false).
1305		:raises IndexError: If index *i* doesn't exist.
1306		"""
		...
1308
1309	def __iter__(self) -> Iterator[tuple[float, bool]]:
1310		"""
1311		Return an iterator of tuples to iterate all split times.
1312
1313		If the stopwatch is not stopped yet, the last split won't be included.
1314
1315		:returns: Iterator of split time tuples of: |br|
1316		          (1) delta time to the previous stopwatch operation and |br|
1317		          (2) a boolean indicating if the split was an activity (true) or inactivity (false).
1318		"""
		...
1320
1321	def __format__(self, formatSpec: str) -> str:
1322		"""
1323		Return the measured duration according to the format specification.
1324
1325		.. topic:: Format Specifiers
1326
1327		   An **uppercase** specifier is a field of the duration as it would be displayed. A **lowercase** specifier is
1328		   the whole duration expressed in one unit, which is what a report or a comparison wants.
1329
1330		   +-----------+--------------------------------------------------------+
1331		   | Specifier | Meaning                                                |
1332		   +===========+========================================================+
1333		   | ``%H``    | hours, not capped - a 26 hour measurement shows ``26`` |
1334		   +-----------+--------------------------------------------------------+
1335		   | ``%M``    | minutes, ``00`` to ``59``                              |
1336		   +-----------+--------------------------------------------------------+
1337		   | ``%S``    | seconds, ``00`` to ``59``                              |
1338		   +-----------+--------------------------------------------------------+
1339		   | ``%L``    | fractional seconds, 3 digits (milliseconds)            |
1340		   +-----------+--------------------------------------------------------+
1341		   | ``%U``    | fractional seconds, 6 digits (microseconds)            |
1342		   +-----------+--------------------------------------------------------+
1343		   | ``%N``    | fractional seconds, 9 digits (nanoseconds)             |
1344		   +-----------+--------------------------------------------------------+
1345		   | ``%s``    | the whole duration in seconds                          |
1346		   +-----------+--------------------------------------------------------+
1347		   | ``%m``    | the whole duration in milliseconds                     |
1348		   +-----------+--------------------------------------------------------+
1349		   | ``%u``    | the whole duration in microseconds                     |
1350		   +-----------+--------------------------------------------------------+
1351		   | ``%n``    | the whole duration in nanoseconds                      |
1352		   +-----------+--------------------------------------------------------+
1353
1354		   The fractional specifiers are truncations of the same fraction, so ``%S.%U`` renders ``04.123456`` without
1355		   having to be combined with anything. ``%H`` is not capped, so ``%H:%M:%S`` never silently drops a day.
1356
1357		   ``%%`` renders a literal percent sign. An empty format specification returns :meth:`__str__`.
1358
1359		:param formatSpec:  The format specification, using ``%``-placeholders for the duration's parts.
1360		:returns:           The formatted duration.
1361		:raises ValueError: If the format specification contains an unknown placeholder.
1362		"""
		...
1367
1368	def __str__(self) -> str:
1369		"""
1370		Returns the stopwatch's state and its measured time span.
1371
1372		The duration is rendered in seconds with :attr:`Digits` fractional digits, in every state - a running and a
1373		stopped stopwatch report the same unit at the same resolution.
1374
1375		:returns: The string equivalent of the stopwatch.
1376		"""
		...