mirror of
https://github.com/kuhyx/WUT_Computer_Science.git
synced 2026-11-10 17:47:14 +01:00
The pre-commit workflow already installs `python-version: "3.x"`, but ruff was still grading the archive against py310 -- so it kept withholding the pyupgrade and type-checking fixes that only become safe at the newer target. `pin_ci_python.py` rewrites the knob. The 17 findings that appeared are what the stale target was hiding: `datetime.timezone.utc` where `datetime.UTC` is now correct (UP017), and 14 imports used only in annotations that belong under `TYPE_CHECKING` (TC002, TC003) -- safe here precisely because 3.14's PEP 649 defers annotation evaluation, which is the same reason ruff would not offer them at py310. `ruff check` and `ruff format --check` are clean again, so the zero-findings state this repo reached earlier today holds at the new target. Still contradictory and deliberately untouched: the four `Programming/ERSMS-project/*/Dockerfile` files say `FROM python:3.10-slim`. They build an archived coursework service against its own era's pinned dependencies, and nothing in this repo runs them; bumping the base image would be a rewrite of that project, not a lint-target change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SfnJmxxsZ534AKk16rC2Gr
92 lines
2.6 KiB
Python
Executable File
92 lines
2.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Decorators that accumulate how long the measured calls take."""
|
|
|
|
import sys
|
|
import time
|
|
from typing import TYPE_CHECKING
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Callable
|
|
|
|
|
|
class TimeAccumulator:
|
|
"""Total time spent inside the decorated functions."""
|
|
|
|
def __init__(self) -> None:
|
|
"""Set up the object."""
|
|
self.total_time = 0
|
|
|
|
|
|
class ComplexTimeAcumulator:
|
|
"""Per-lap and longest times for the decorated functions."""
|
|
|
|
def __init__(self) -> None:
|
|
"""Set up the object."""
|
|
self.hard_reset()
|
|
|
|
def hard_reset(self) -> None:
|
|
"""Clear every recorded time."""
|
|
self.total_time = 0
|
|
self.reset()
|
|
|
|
def reset(self) -> None:
|
|
"""Clear the current lap."""
|
|
self.lap_time = 0
|
|
self.start = sys.float_info.max
|
|
self.end = 0
|
|
|
|
def save_lap_and_reset(self) -> None:
|
|
"""Store the current lap and start a new one."""
|
|
self.total_time += self.lap_time
|
|
self.reset()
|
|
|
|
|
|
time_accumulator = TimeAccumulator()
|
|
tests_time = TimeAccumulator()
|
|
|
|
longest_threads_time_accumulator = ComplexTimeAcumulator()
|
|
|
|
|
|
def time_measurement(accumulator: TimeAccumulator) -> Callable[..., object]:
|
|
"""Decorate a function so its runtime accumulates."""
|
|
|
|
def decorator(func: Callable[..., object]) -> Callable[..., object]:
|
|
"""Wrap the function so its runtime is recorded."""
|
|
|
|
def inner(*args: object, **kwargs: object) -> object:
|
|
"""Call the wrapped function and record how long it took."""
|
|
start = time.perf_counter()
|
|
result = func(*args, **kwargs)
|
|
end = time.perf_counter()
|
|
accumulator.total_time += end - start
|
|
return result
|
|
|
|
return inner
|
|
|
|
return decorator
|
|
|
|
|
|
def time_measurement_longest(
|
|
accumulator: ComplexTimeAcumulator,
|
|
) -> Callable[..., object]:
|
|
"""Decorate a function so its longest runtime is kept."""
|
|
|
|
def decorator(func: Callable[..., object]) -> Callable[..., object]:
|
|
"""Wrap the function so its runtime is recorded."""
|
|
|
|
def inner(*args: object, **kwargs: object) -> object:
|
|
"""Call the wrapped function and record how long it took."""
|
|
start = time.perf_counter()
|
|
result = func(*args, **kwargs)
|
|
end = time.perf_counter()
|
|
accumulator.start = min(accumulator.start, start)
|
|
accumulator.end = max(accumulator.end, end)
|
|
accumulator.lap_time = (
|
|
accumulator.end - accumulator.start
|
|
) # "=" instead of "+="
|
|
return result
|
|
|
|
return inner
|
|
|
|
return decorator
|