From 9668b43c25f5d6be1f4ceb18a3e8fc2bcf557e84 Mon Sep 17 00:00:00 2001 From: "Gabriele N. Tornetta" Date: Thu, 30 Apr 2026 13:08:55 +0100 Subject: [PATCH] chore: fix all checks --- .flake8 | 3 +- austin/base.py | 1 - austin/events.py | 1 - austin/format/collapsed_stack.py | 9 +++--- austin/format/compress.py | 8 +++-- austin/format/mojo.py | 51 +++++++++++++++++++------------- austin/format/pprof/__init__.py | 1 - austin/format/speedscope.py | 2 -- austin/stats.py | 18 ++++++----- austin/tools/diff.py | 10 ++++--- austin/tools/mojodbg.py | 1 - austin/tools/resolve.py | 13 ++++---- pyproject.toml | 36 ++++++++++++++++------ test/conftest.py | 1 - test/format/test_mojo.py | 3 -- test/format/test_speedscope.py | 1 - test/stats/test_austin_stats.py | 3 +- test/test_aio.py | 1 - test/tools/test_diff.py | 8 +++-- test/tools/test_resolve.py | 1 - 20 files changed, 97 insertions(+), 75 deletions(-) diff --git a/.flake8 b/.flake8 index a51b095..be08ea3 100644 --- a/.flake8 +++ b/.flake8 @@ -1,12 +1,11 @@ [flake8] select = ANN,B,B9,C,D,E,F,W,I -ignore = ANN101,ANN102,ANN401,B950,D100,D102,D103,D104,D107,E203,E501,I001,I005,W503,W606 +ignore = ANN101,ANN102,ANN401,B905,B950,D100,D102,D103,D104,D107,E203,E501,I001,I005,W503,W606 exclude = austin/format/pprof/profile_pb2.py test/data/column.py max-line-length = 88 docstring-convention = google -import-order-style = pep8 application-import-names = austin per-file-ignores = test/*:ANN,D diff --git a/austin/base.py b/austin/base.py index d40c0c8..0901c51 100644 --- a/austin/base.py +++ b/austin/base.py @@ -43,7 +43,6 @@ from austin.events import AustinMetadata from austin.events import AustinSample - SemVer = Tuple[int, int, int] diff --git a/austin/events.py b/austin/events.py index 6303356..8444769 100644 --- a/austin/events.py +++ b/austin/events.py @@ -1,7 +1,6 @@ import typing as t from dataclasses import dataclass - ProcessId = int ThreadName = str InterpreterId = int diff --git a/austin/format/collapsed_stack.py b/austin/format/collapsed_stack.py index fc870ac..681d7a5 100644 --- a/austin/format/collapsed_stack.py +++ b/austin/format/collapsed_stack.py @@ -1,6 +1,6 @@ +import typing as t from functools import singledispatchmethod from pathlib import Path -import typing as t from austin.events import AustinEvent from austin.events import AustinEventIterator @@ -10,7 +10,6 @@ from austin.events import AustinSample from austin.format.mojo import MojoStreamReader - __version__ = "0.1.0" @@ -66,17 +65,17 @@ def parse_collapsed_stack(sample: str) -> AustinSample: raise InvalidSample(sample) if sample[0] != "P": - raise InvalidSample(f"No process ID in sample '{sample}'") + raise InvalidSample(f"No process ID in sample {sample!r}") head, _, metrics = sample.rpartition(" ") process, _, rest = head.partition(";") try: pid = int(process[1:]) except ValueError: - raise InvalidSample(f"Invalid process ID in sample '{sample}'") from None + raise InvalidSample(f"Invalid process ID in sample {sample!r}") from None if rest[0] != "T": - raise InvalidSample(f"No thread ID in sample '{sample}'") + raise InvalidSample(f"No thread ID in sample {sample!r}") thread, _, frames_data = rest.partition(";") thread = thread[1:] diff --git a/austin/format/compress.py b/austin/format/compress.py index 0398208..8e2e77e 100644 --- a/austin/format/compress.py +++ b/austin/format/compress.py @@ -62,9 +62,11 @@ def compress(source: AustinFileReader, dest: TextIO, counts: bool = False) -> No formatter.format( AustinSample.from_key_and_metrics( key, - AustinMetrics(memory=metrics) - if is_memory - else AustinMetrics(time=metrics), + ( + AustinMetrics(memory=metrics) + if is_memory + else AustinMetrics(time=metrics) + ), ) ) + "\n" diff --git a/austin/format/mojo.py b/austin/format/mojo.py index f574d1e..4cad82f 100644 --- a/austin/format/mojo.py +++ b/austin/format/mojo.py @@ -84,6 +84,7 @@ class MojoEvent: """MOJO event.""" EVENT_ID: t.ClassVar = None + raw: t.ClassVar[bytes] = b"" def ref(self) -> int: return getattr(self, fields(self)[0].name) @@ -93,9 +94,7 @@ def to_bytes(self) -> bytes: for f in fields(self): value = getattr(self, f.name) field_type = ( - f.type.__args__[0] - if isinstance(f.type, t._UnionGenericAlias) - else f.type + t.get_args(f.type)[0] if t.get_origin(f.type) is t.Union else f.type ) if field_type is str: buffer += value.encode() @@ -127,9 +126,11 @@ class MojoMetric(MojoEvent): def to_bytes(self) -> bytes: buffer = bytearray( [ - MojoEvents.METRIC_TIME - if self.metric_type is MojoMetricType.TIME - else MojoEvents.METRIC_MEMORY + ( + MojoEvents.METRIC_TIME + if self.metric_type is MojoMetricType.TIME + else MojoEvents.METRIC_MEMORY + ) ] ) buffer += to_varint(self.value) @@ -381,19 +382,21 @@ def _finalize_sample(self) -> AustinSample: for metric_type, metric in self._running_sample.metrics.items() } ), - frames=tuple( - AustinFrame( - filename=mf.filename.value, - function=mf.scope.value, - line=mf.line, - line_end=mf.line_end, - column=mf.column, - column_end=mf.column_end, + frames=( + tuple( + AustinFrame( + filename=mf.filename.value, + function=mf.scope.value, + line=mf.line, + line_end=mf.line_end, + column=mf.column, + column_end=mf.column_end, + ) + for mf in self._running_sample.frames ) - for mf in self._running_sample.frames - ) - if self._running_sample.frames - else None, + if self._running_sample.frames + else None + ), gc=self._running_sample.gc, idle=self._running_sample.idle, ) @@ -670,7 +673,9 @@ def __iter__(self) -> t.Iterator[AustinEvent]: if self._running_sample is not None: yield self._finalize_sample() - def hexdump(self, start: int, end: int, highlight: t.Set[int] = set()) -> None: # noqa: B006 + def hexdump( + self, start: int, end: int, highlight: t.Set[int] = set() # noqa: B006 + ) -> None: """Print a hexdump of the MOJO file.""" self.mojo.seek(start) data = self.mojo.read(end - start) @@ -855,6 +860,8 @@ async def __aiter__(self) -> t.AsyncIterator[AustinEvent]: class BaseMojoStreamWriter(abc.ABC): + """Base class for MOJO stream writers.""" + HEADER = b"MOJ\x03" def __init__(self, mojo: t.Any) -> None: @@ -904,11 +911,13 @@ def resolve_frame(self, frame: AustinFrame) -> MojoFrame: return mojo_frame @abc.abstractmethod - def write(self, event: AustinEvent) -> int: ... + def write(self, event: AustinEvent) -> int: ... # noqa: E704 class MojoStreamWriter(BaseMojoStreamWriter): - def __init__(self, mojo: io.BytesIO): + """MOJO stream writer.""" + + def __init__(self, mojo: io.BytesIO) -> None: super().__init__(mojo) mojo.write(self.HEADER) diff --git a/austin/format/pprof/__init__.py b/austin/format/pprof/__init__.py index ea7c6da..e242bbe 100644 --- a/austin/format/pprof/__init__.py +++ b/austin/format/pprof/__init__.py @@ -33,7 +33,6 @@ from austin.format.pprof.profile_pb2 import Profile from austin.format.pprof.profile_pb2 import Sample - PROCESS_ID_LABEL = "Process ID" THREAD_ID_LABEL = "Thread ID" INTERPRETER_ID_LABEL = "Interpreter ID" diff --git a/austin/format/speedscope.py b/austin/format/speedscope.py index 926e504..5d62bc9 100644 --- a/austin/format/speedscope.py +++ b/austin/format/speedscope.py @@ -38,8 +38,6 @@ from austin.events import AustinSample from austin.format import Mode from austin.format.collapsed_stack import AustinFileReader -from austin.format.collapsed_stack import InvalidSample - __version__ = "0.3.1" diff --git a/austin/stats.py b/austin/stats.py index 4a7c09e..f1d64cc 100644 --- a/austin/stats.py +++ b/austin/stats.py @@ -42,7 +42,6 @@ from austin.events import ProcessId from austin.format.collapsed_stack import AustinEventCollapsedStackFormatter - ThreadInfo = namedtuple("ThreadInfo", ["thread", "iid"]) @@ -123,9 +122,11 @@ def collapse( if self.own: yield ( [frame], - AustinMetrics(time=self.own) - if stats_type in {AustinStatsType.CPU, AustinStatsType.WALL} - else AustinMetrics(memory=self.own), + ( + AustinMetrics(time=self.own) + if stats_type in {AustinStatsType.CPU, AustinStatsType.WALL} + else AustinMetrics(memory=self.own) + ), ) if self.children: @@ -146,14 +147,15 @@ def collapse( self, stats_type: AustinStatsType ) -> Generator[Tuple[ThreadInfo, List[AustinFrame], AustinMetrics], None, None]: """Collapse the hierarchical statistics.""" - if self.own: yield ( self.label, [], - AustinMetrics(time=self.own) - if stats_type in {AustinStatsType.CPU, AustinStatsType.WALL} - else AustinMetrics(memory=self.own), + ( + AustinMetrics(time=self.own) + if stats_type in {AustinStatsType.CPU, AustinStatsType.WALL} + else AustinMetrics(memory=self.own) + ), ) if self.children: diff --git a/austin/tools/diff.py b/austin/tools/diff.py index ff6bfb4..3e7aea7 100644 --- a/austin/tools/diff.py +++ b/austin/tools/diff.py @@ -30,9 +30,11 @@ from typing import Tuple from austin.events import AustinFrame +from austin.events import AustinMetrics +from austin.format.collapsed_stack import InvalidSample +from austin.format.collapsed_stack import parse_collapsed_stack from austin.format.compress import compress - FoldedStack = List[AustinFrame] @@ -41,7 +43,7 @@ def _similarities( ) -> List[Tuple[Tuple[int, int], float]]: """O(n * log(n)), n = len(x) * len(y).""" - def score(a: List[Frame], b: List[Frame]) -> float: + def score(a: List[AustinFrame], b: List[AustinFrame]) -> float: """Score two folded stacks.""" if not len(a) and not len(b): return 1 @@ -90,12 +92,12 @@ def compressed(source: TextIO) -> str: compress(source, _) return _.getvalue() - def get_frames(text: str) -> List[Tuple[FoldedStack, Metric]]: + def get_frames(text: str) -> List[Tuple[FoldedStack, AustinMetrics]]: """Get the folded stacks and metrics from a string of samples.""" x = [] for _ in text.splitlines(keepends=False): try: - sample = Sample.parse(_) + sample = parse_collapsed_stack(_) x.append((sample.frames, sample.metrics)) except InvalidSample: continue diff --git a/austin/tools/mojodbg.py b/austin/tools/mojodbg.py index 95b0649..fd31788 100644 --- a/austin/tools/mojodbg.py +++ b/austin/tools/mojodbg.py @@ -29,7 +29,6 @@ from austin.format.mojo import MojoEvent from austin.format.mojo import MojoStreamReader - __version__ = "0.1.0" diff --git a/austin/tools/resolve.py b/austin/tools/resolve.py index f3045dd..147c4a3 100644 --- a/austin/tools/resolve.py +++ b/austin/tools/resolve.py @@ -30,7 +30,6 @@ from austin.format.mojo import MojoString from austin.format.mojo import to_varint - __version__ = "0.2.0" @@ -176,8 +175,10 @@ def resolve_mojo(input: str, output: str) -> None: filename, scope, line = resolved new_value = filename or scope - event.raw = event.raw.replace( - event.value.encode(), new_value.encode() + object.__setattr__( + event, + "raw", + event.raw.replace(event.value.encode(), new_value.encode()), ) if filename is not None: @@ -185,9 +186,11 @@ def resolve_mojo(input: str, output: str) -> None: elif isinstance(event, MojoFrame): if event.filename.key in maps.lines: - event.raw = ( + object.__setattr__( + event, + "raw", event.raw[: -len(to_varint(event.line))] - + maps.lines[event.filename.key] + + maps.lines[event.filename.key], ) fout.write(event.raw) diff --git a/pyproject.toml b/pyproject.toml index 8d27ebc..76feb05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,17 +80,18 @@ tests = "pytest --cov=austin --cov-report=term-missing --cov-report=xml {args}" python = ["3.10", "3.11", "3.12", "3.13", "3.14"] [tool.hatch.envs.checks] -python = "3.10" +python = "3.13" template = "checks" dependencies = [ - "mypy~=0.770", - "flake8~=5.0.4", - "flake8-annotations~=2.9.1", - "flake8-black", - "flake8-bugbear~=22.9.23", - "flake8-docstrings~=1.6.0", - "flake8-import-order~=0.18.1", - "flake8-isort~=5.0.0", + "black~=26.3", + "mypy~=0.990", + "flake8~=7.3", + "flake8-annotations~=3.2", + "flake8-black~=0.4", + "flake8-bugbear~=25.11", + "flake8-docstrings~=1.7", + "flake8-isort~=7.0", + "isort~=5.13", ] [tool.hatch.envs.checks.scripts] @@ -145,6 +146,23 @@ module = [ ] ignore_errors = true +[tool.black] +target-version = ["py310", "py311", "py312", "py313", "py314"] +extend-exclude = ''' +( + /profile_pb2\.py + | /test/data/column\.py +) +''' + +[tool.isort] +force_single_line = true +lines_after_imports = -1 +skip = [ + "austin/format/pprof/profile_pb2.py", + "test/data/column.py", +] + [build-system] requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" diff --git a/test/conftest.py b/test/conftest.py index 70c20b8..b221fa6 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -2,7 +2,6 @@ import pytest - DATAPATH = pathlib.Path(__file__).parent / "data" diff --git a/test/format/test_mojo.py b/test/format/test_mojo.py index e3a0049..8443b30 100644 --- a/test/format/test_mojo.py +++ b/test/format/test_mojo.py @@ -35,13 +35,10 @@ from austin.events import AustinSample from austin.format.collapsed_stack import main from austin.format.mojo import MojoFrame -from austin.format.mojo import MojoMetadata from austin.format.mojo import MojoStreamReader from austin.format.mojo import MojoStreamWriter from austin.format.mojo import MojoString from austin.format.mojo import to_varint -from austin.tools.mojodbg import mojodbg - HERE = Path(__file__).parent DATA = HERE.parent / "data" diff --git a/test/format/test_speedscope.py b/test/format/test_speedscope.py index 7add4f7..433e84a 100644 --- a/test/format/test_speedscope.py +++ b/test/format/test_speedscope.py @@ -32,7 +32,6 @@ from austin.format.speedscope import SpeedscopeFrame from austin.format.speedscope import SpeedscopeProfile - _SPEEDSCOPE_FILE_FIELDS = ("$schema", "shared", "profiles", "name", "exporter") _SPEEDSCOPE_SCHEMA_URL = "https://www.speedscope.app/file-format-schema.json" _SPEEDSCOPE_FRAME_FIELDS = tuple([field.name for field in fields(SpeedscopeFrame)]) diff --git a/test/stats/test_austin_stats.py b/test/stats/test_austin_stats.py index 92374be..3f18deb 100644 --- a/test/stats/test_austin_stats.py +++ b/test/stats/test_austin_stats.py @@ -21,8 +21,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from copy import deepcopy import io +from copy import deepcopy from austin.events import AustinFrame from austin.events import AustinMetrics @@ -36,7 +36,6 @@ from austin.stats import ThreadInfo from austin.stats import ThreadStats - DUMP_LOAD_SAMPLES = """# mode: wall {}P42;T0x7f45645646;foo_module.py:foo:10 300 diff --git a/test/test_aio.py b/test/test_aio.py index a55ed51..3e40ad7 100644 --- a/test/test_aio.py +++ b/test/test_aio.py @@ -33,7 +33,6 @@ from austin.events import AustinMetadata from austin.events import AustinSample - if sys.platform == "win32": loop = asyncio.ProactorEventLoop() asyncio.set_event_loop(loop) diff --git a/test/tools/test_diff.py b/test/tools/test_diff.py index 77ed4e3..31888aa 100644 --- a/test/tools/test_diff.py +++ b/test/tools/test_diff.py @@ -5,7 +5,9 @@ @pytest.mark.skip("Needs fixing") def test_diff(): - with open("test/data/diff_a.austin") as a, open( - "test/data/diff_b.austin" - ) as b, open("test/data/diff_a-b.austin") as d: + with ( + open("test/data/diff_a.austin") as a, + open("test/data/diff_b.austin") as b, + open("test/data/diff_a-b.austin") as d, + ): assert diff(a, b).strip() == d.read().strip() diff --git a/test/tools/test_resolve.py b/test/tools/test_resolve.py index 71e9bb9..cd84cc5 100644 --- a/test/tools/test_resolve.py +++ b/test/tools/test_resolve.py @@ -29,7 +29,6 @@ from austin.tools.resolve import main - HERE = Path(__file__).parent DATA = HERE.parent / "data"