austin-python 2.0.0__py3-none-any.whl → 2.1.1__py3-none-any.whl

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.
austin/events.py CHANGED
@@ -1,8 +1,9 @@
1
1
  import typing as t
2
+ from collections import namedtuple
2
3
  from dataclasses import dataclass
3
4
 
4
5
 
5
- ThreadName = str
6
+ ThreadName = namedtuple("ThreadName", ["thread", "iid"])
6
7
  ProcessId = int
7
8
  InterpreterId = int
8
9
  MicroSeconds = int
@@ -48,7 +48,7 @@ def parse_frame(frame: str) -> AustinFrame:
48
48
  filename, function, line = frame.rsplit(":", maxsplit=2)
49
49
  except ValueError:
50
50
  raise InvalidFrame(frame) from None
51
- return AustinFrame(filename=filename, function=function, line=int(line))
51
+ return AustinFrame(filename=filename, function=function, line=int(line or 0))
52
52
 
53
53
 
54
54
  def parse_collapsed_stack(sample: str) -> AustinSample:
austin/format/mojo.py CHANGED
@@ -1,7 +1,10 @@
1
+ import abc
1
2
  import asyncio
3
+ import io
2
4
  import typing as t
3
5
  from dataclasses import dataclass
4
6
  from dataclasses import field
7
+ from dataclasses import fields
5
8
  from enum import Enum
6
9
 
7
10
  from austin.events import AustinEvent
@@ -76,12 +79,35 @@ class MojoEventHandler:
76
79
  ...
77
80
 
78
81
 
82
+ @dataclass(frozen=True, eq=True)
79
83
  class MojoEvent:
80
84
  """MOJO event."""
81
85
 
82
- def __init__(self) -> None:
83
- """Initialize the event."""
84
- self.raw = bytes([])
86
+ EVENT_ID: t.ClassVar = None
87
+
88
+ def ref(self) -> int:
89
+ return getattr(self, fields(self)[0].name)
90
+
91
+ def to_bytes(self) -> bytes:
92
+ buffer = bytearray([self.EVENT_ID])
93
+ for f in fields(self):
94
+ value = getattr(self, f.name)
95
+ field_type = (
96
+ f.type.__args__[0]
97
+ if isinstance(f.type, t._UnionGenericAlias)
98
+ else f.type
99
+ )
100
+ if field_type is str:
101
+ buffer += value.encode()
102
+ buffer += b"\x00"
103
+ elif field_type is int:
104
+ buffer += to_varint(value)
105
+ elif issubclass(field_type, MojoEvent):
106
+ buffer += to_varint(value.ref())
107
+ else:
108
+ msg = f"Invalid MOJO event field type {f.type}"
109
+ raise TypeError(msg)
110
+ return bytes(buffer)
85
111
 
86
112
 
87
113
  class MojoMetricType(str, Enum):
@@ -98,11 +124,24 @@ class MojoMetric(MojoEvent):
98
124
  metric_type: MojoMetricType
99
125
  value: int
100
126
 
127
+ def to_bytes(self) -> bytes:
128
+ buffer = bytearray(
129
+ [
130
+ MojoEvents.METRIC_TIME
131
+ if self.metric_type is MojoMetricType.TIME
132
+ else MojoEvents.METRIC_MEMORY
133
+ ]
134
+ )
135
+ buffer += to_varint(self.value)
136
+ return bytes(buffer)
137
+
101
138
 
102
139
  @dataclass(frozen=True, eq=True)
103
140
  class MojoString(MojoEvent):
104
141
  """MOJO string."""
105
142
 
143
+ EVENT_ID = MojoEvents.STRING
144
+
106
145
  key: int
107
146
  value: str
108
147
 
@@ -111,12 +150,16 @@ class MojoString(MojoEvent):
111
150
  class MojoStringReference(MojoEvent):
112
151
  """MOJO string reference."""
113
152
 
153
+ EVENT_ID = MojoEvents.STRING_REF
154
+
114
155
  string: MojoString
115
156
 
116
157
 
117
158
  class MojoIdle(MojoEvent):
118
159
  """MOJO idle event."""
119
160
 
161
+ EVENT_ID = MojoEvents.IDLE
162
+
120
163
  pass
121
164
 
122
165
 
@@ -124,6 +167,8 @@ class MojoIdle(MojoEvent):
124
167
  class MojoMetadata(MojoEvent):
125
168
  """MOJO metadata."""
126
169
 
170
+ EVENT_ID = MojoEvents.METADATA
171
+
127
172
  key: str
128
173
  value: str
129
174
 
@@ -132,6 +177,8 @@ class MojoMetadata(MojoEvent):
132
177
  class MojoStack(MojoEvent):
133
178
  """MOJO stack."""
134
179
 
180
+ EVENT_ID = MojoEvents.STACK
181
+
135
182
  pid: int
136
183
  iid: int
137
184
  tid: str
@@ -141,6 +188,8 @@ class MojoStack(MojoEvent):
141
188
  class MojoFrame(MojoEvent):
142
189
  """MOJO frame."""
143
190
 
191
+ EVENT_ID = MojoEvents.FRAME
192
+
144
193
  key: int
145
194
  filename: MojoString
146
195
  scope: MojoString
@@ -154,6 +203,8 @@ class MojoFrame(MojoEvent):
154
203
  class MojoKernelFrame(MojoEvent):
155
204
  """MOJO kernel frame."""
156
205
 
206
+ EVENT_ID = MojoEvents.FRAME_KERNEL
207
+
157
208
  scope: str
158
209
 
159
210
 
@@ -161,6 +212,8 @@ class MojoKernelFrame(MojoEvent):
161
212
  class MojoSpecialFrame(MojoEvent):
162
213
  """MOJO special frame."""
163
214
 
215
+ EVENT_ID = MojoEvents.FRAME_INVALID
216
+
164
217
  label: str
165
218
 
166
219
 
@@ -168,6 +221,8 @@ class MojoSpecialFrame(MojoEvent):
168
221
  class MojoFrameReference(MojoEvent):
169
222
  """MOJO frame reference."""
170
223
 
224
+ EVENT_ID = MojoEvents.FRAME_REF
225
+
171
226
  frame: MojoFrame
172
227
 
173
228
 
@@ -778,3 +833,120 @@ class AsyncMojoStreamReader(BaseMojoStreamReader):
778
833
  yield self.samples[-1]
779
834
  if self._running_sample is not None:
780
835
  yield self._finalize_sample()
836
+
837
+
838
+ class BaseMojoStreamWriter(abc.ABC):
839
+ HEADER = b"MOJ\x03"
840
+
841
+ def __init__(self, mojo: t.Any) -> None:
842
+ self.mojo = mojo
843
+ self._frames: t.Dict[AustinFrame, MojoFrame] = {}
844
+ self._strings: t.Dict[str, MojoString] = {
845
+ EMPTY.value: EMPTY,
846
+ UNKNOWN.value: UNKNOWN,
847
+ }
848
+
849
+ self._meta: t.Dict[str, str] = {}
850
+
851
+ self._mode: t.Optional[str] = None
852
+ self._gc = False
853
+
854
+ self._new_entries: t.List[MojoEvent] = []
855
+
856
+ def set_metadata(self, metadata: AustinMetadata) -> None:
857
+ self._meta[metadata.name] = metadata.value
858
+ if metadata.name == "gc" and metadata.value == "on":
859
+ self._gc = True
860
+ elif metadata.name == "mode":
861
+ self._mode = metadata.value
862
+
863
+ def resolve_string(self, value: str) -> MojoString:
864
+ try:
865
+ return self._strings[value]
866
+ except KeyError:
867
+ self._strings[value] = mojo_string = MojoString(len(self._strings), value)
868
+ self._new_entries.append(mojo_string)
869
+ return mojo_string
870
+
871
+ def resolve_frame(self, frame: AustinFrame) -> MojoFrame:
872
+ try:
873
+ return self._frames[frame]
874
+ except KeyError:
875
+ self._frames[frame] = mojo_frame = MojoFrame(
876
+ len(self._frames),
877
+ self.resolve_string(frame.filename),
878
+ self.resolve_string(frame.function),
879
+ frame.line,
880
+ frame.line_end or 0,
881
+ frame.column or 0,
882
+ frame.column_end or 0,
883
+ )
884
+ self._new_entries.append(mojo_frame)
885
+ return mojo_frame
886
+
887
+ @abc.abstractmethod
888
+ def write(self, event: AustinEvent) -> int: ...
889
+
890
+
891
+ class MojoStreamWriter(BaseMojoStreamWriter):
892
+ def __init__(self, mojo: io.BytesIO):
893
+ super().__init__(mojo)
894
+
895
+ mojo.write(self.HEADER)
896
+
897
+ def write(self, event: AustinEvent) -> int:
898
+ size = 0
899
+
900
+ if isinstance(event, AustinMetadata):
901
+ self.set_metadata(event)
902
+ size += self.mojo.write(
903
+ MojoMetadata(key=event.name, value=event.value).to_bytes()
904
+ )
905
+
906
+ elif isinstance(event, AustinSample):
907
+ frames = (
908
+ [self.resolve_frame(f) for f in event.frames] if event.frames else []
909
+ )
910
+
911
+ size += self.mojo.write(
912
+ MojoStack(
913
+ pid=event.pid, iid=event.iid or 0, tid=event.thread
914
+ ).to_bytes()
915
+ )
916
+
917
+ while self._new_entries:
918
+ size += self.mojo.write(self._new_entries.pop(0).to_bytes())
919
+
920
+ for frame in frames:
921
+ size += self.mojo.write(MojoFrameReference(frame).to_bytes())
922
+
923
+ if self._gc:
924
+ size += self.mojo.write(bytes([MojoEvents.GC]))
925
+
926
+ if self._mode == "full":
927
+ if event.idle:
928
+ size += self.mojo.write(bytes([MojoEvents.IDLE]))
929
+ size += self.mojo.write(
930
+ MojoMetric(MojoMetricType.TIME, event.metrics.time or 0).to_bytes()
931
+ )
932
+ size += self.mojo.write(
933
+ MojoMetric(
934
+ MojoMetricType.MEMORY, event.metrics.memory or 0
935
+ ).to_bytes()
936
+ )
937
+ elif self._mode == "memory":
938
+ size += self.mojo.write(
939
+ MojoMetric(
940
+ MojoMetricType.MEMORY, event.metrics.memory or 0
941
+ ).to_bytes()
942
+ )
943
+ else:
944
+ size += self.mojo.write(
945
+ MojoMetric(MojoMetricType.TIME, event.metrics.time or 0).to_bytes()
946
+ )
947
+
948
+ else:
949
+ msg = f"Unhandled event type {type(event)}"
950
+ raise TypeError(msg)
951
+
952
+ return size
@@ -22,6 +22,7 @@
22
22
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
23
23
 
24
24
  from argparse import ArgumentParser
25
+ from pathlib import Path
25
26
 
26
27
  from austin.events import AustinMetadata
27
28
  from austin.events import AustinSample
@@ -41,19 +42,21 @@ def main() -> None:
41
42
 
42
43
  arg_parser.add_argument(
43
44
  "input",
44
- type=str,
45
+ type=Path,
45
46
  help="The input file containing Austin samples.",
46
47
  )
47
48
  arg_parser.add_argument(
48
- "output", type=str, help="The name of the output pprof file."
49
+ "output",
50
+ type=Path,
51
+ help="The name of the output pprof file.",
49
52
  )
50
53
 
51
- arg_parser.add_argument("-V", "--version", action="version", version="0.2.0")
54
+ arg_parser.add_argument("-V", "--version", action="version", version="0.2.1")
52
55
 
53
56
  args = arg_parser.parse_args()
54
57
 
55
58
  try:
56
- with AustinFileReader(args.input) as fin:
59
+ with args.input.open() as austin, AustinFileReader(austin) as fin:
57
60
  pprof = None
58
61
  for e in fin:
59
62
  if isinstance(e, AustinMetadata) and e.name == "mode":
@@ -26,6 +26,7 @@ from dataclasses import asdict
26
26
  from dataclasses import dataclass
27
27
  from dataclasses import field
28
28
  from enum import Enum
29
+ from pathlib import Path
29
30
  from typing import Dict
30
31
  from typing import List
31
32
  from typing import Optional
@@ -33,13 +34,14 @@ from typing import TextIO
33
34
  from typing import Union
34
35
 
35
36
  from austin.events import AustinFrame
37
+ from austin.events import AustinMetadata
36
38
  from austin.events import AustinSample
37
39
  from austin.format import Mode
38
40
  from austin.format.collapsed_stack import AustinFileReader
39
41
  from austin.format.collapsed_stack import InvalidSample
40
42
 
41
43
 
42
- __version__ = "0.3.0"
44
+ __version__ = "0.3.1"
43
45
 
44
46
  SpeedscopeJson = Dict
45
47
  SpeedscopeWeight = int
@@ -208,11 +210,11 @@ def main() -> None:
208
210
 
209
211
  arg_parser.add_argument(
210
212
  "input",
211
- type=str,
213
+ type=Path,
212
214
  help="The input file containing Austin samples in normal format.",
213
215
  )
214
216
  arg_parser.add_argument(
215
- "output", type=str, help="The name of the output Speedscope JSON file."
217
+ "output", type=Path, help="The name of the output Speedscope JSON file."
216
218
  )
217
219
  arg_parser.add_argument(
218
220
  "--indent", type=int, help="Give a non-null value to prettify the JSON output."
@@ -223,24 +225,30 @@ def main() -> None:
223
225
  args = arg_parser.parse_args()
224
226
 
225
227
  try:
226
- with AustinFileReader(args.input) as fin:
227
- mode = fin.metadata["mode"]
228
- speedscope = Speedscope(os.path.basename(args.input), mode, args.indent)
228
+ with args.input.open() as austin, AustinFileReader(austin) as fin:
229
+ speedscope = None
229
230
  for event in fin:
230
- if not isinstance(event, AustinSample):
231
- continue
232
- try:
233
- speedscope.add_sample(event)
234
- except InvalidSample:
235
- continue
231
+ if isinstance(event, AustinMetadata):
232
+ if event.name == "mode":
233
+ speedscope = Speedscope(
234
+ os.path.basename(args.input), event.value, args.indent
235
+ )
236
+ elif isinstance(event, AustinSample):
237
+ if speedscope is not None:
238
+ speedscope.add_sample(event)
239
+ else:
240
+ raise ValueError("Invalid sample found in input file")
241
+
242
+ if speedscope is None:
243
+ raise RuntimeError("Invalid input file: no mode metadata found")
244
+
245
+ with args.output.open("w") as fout:
246
+ speedscope.dump(fout)
236
247
 
237
248
  except FileNotFoundError:
238
249
  print(f"No such input file: {args.input}")
239
250
  exit(1)
240
251
 
241
- with open(args.output, "w") as fout:
242
- speedscope.dump(fout)
243
-
244
252
 
245
253
  if __name__ == "__main__":
246
254
  main()
austin/stats.py CHANGED
@@ -28,13 +28,15 @@ from enum import Enum
28
28
  from threading import Lock
29
29
  from typing import Any
30
30
  from typing import Dict
31
+ from typing import Generator
31
32
  from typing import List
32
33
  from typing import Optional
33
- from typing import TextIO
34
+ from typing import Tuple
34
35
 
35
36
  from austin.events import AustinEventIterator
36
37
  from austin.events import AustinFrame
37
38
  from austin.events import AustinMetadata
39
+ from austin.events import AustinMetrics
38
40
  from austin.events import AustinSample
39
41
  from austin.events import ProcessId
40
42
  from austin.events import ThreadName
@@ -44,6 +46,15 @@ from austin.format.collapsed_stack import AustinEventCollapsedStackFormatter
44
46
  COLLAPSED_STACK_FORMATTER = AustinEventCollapsedStackFormatter()
45
47
 
46
48
 
49
+ class AustinStatsType(Enum):
50
+ """Austin stats type."""
51
+
52
+ WALL = "wall"
53
+ CPU = "cpu"
54
+ MEMORY_ALLOC = "memory_alloc"
55
+ MEMORY_DEALLOC = "memory_dealloc"
56
+
57
+
47
58
  @dataclass
48
59
  class HierarchicalStats:
49
60
  """Base dataclass for representing hierarchical statistics.
@@ -87,7 +98,7 @@ class HierarchicalStats:
87
98
  """Get a child from the children collection."""
88
99
  return self.children[label]
89
100
 
90
- def collapse(self, prefix: str = "") -> List[str]:
101
+ def collapse(self, stats_type: AustinStatsType) -> Generator[Any, None, None]:
91
102
  """Collapse the hierarchical statistics."""
92
103
  raise NotImplementedError()
93
104
 
@@ -100,19 +111,26 @@ class FrameStats(HierarchicalStats):
100
111
  height: int = 0
101
112
  children: Dict[AustinFrame, "FrameStats"] = field(default_factory=dict) # type: ignore[assignment]
102
113
 
103
- def collapse(self, prefix: str = "") -> List[str]:
114
+ def collapse(
115
+ self, stats_type: AustinStatsType
116
+ ) -> Generator[Tuple[List[AustinFrame], AustinMetrics], None, None]:
104
117
  """Collapse the hierarchical statistics."""
105
- frame = COLLAPSED_STACK_FORMATTER.format(self.label)
118
+ frame = self.label
106
119
 
107
- if not self.children:
108
- return [f";{prefix}{frame} {self.own}"]
120
+ if self.own:
121
+ yield (
122
+ [frame],
123
+ AustinMetrics(time=self.own)
124
+ if stats_type in {AustinStatsType.CPU, AustinStatsType.WALL}
125
+ else AustinMetrics(memory=self.own),
126
+ )
109
127
 
110
- own = [] if self.own == 0 else [f";{prefix}{frame} {self.own}"]
111
- return own + [
112
- f";{prefix}{frame}{rest}"
113
- for _, child in self.children.items()
114
- for rest in child.collapse()
115
- ]
128
+ if self.children:
129
+ yield from (
130
+ ([frame, *rest], metric)
131
+ for child in self.children.values()
132
+ for rest, metric in child.collapse(stats_type)
133
+ )
116
134
 
117
135
 
118
136
  class ThreadStats(HierarchicalStats):
@@ -121,16 +139,26 @@ class ThreadStats(HierarchicalStats):
121
139
  label: ThreadName
122
140
  children: Dict[AustinFrame, FrameStats] = field(default_factory=dict) # type: ignore[assignment]
123
141
 
124
- def collapse(self, prefix: str = "") -> List[str]:
142
+ def collapse(
143
+ self, stats_type: AustinStatsType
144
+ ) -> Generator[Tuple[ThreadName, List[AustinFrame], AustinMetrics], None, None]:
125
145
  """Collapse the hierarchical statistics."""
126
- if not self.children:
127
- return [f";T{self.label} {self.own}"]
128
- own = [] if self.own == 0 else [f";T{self.label} {self.own}"]
129
- return own + [
130
- f";T{self.label}{rest}"
131
- for stats in self.children.values()
132
- for rest in stats.collapse()
133
- ]
146
+
147
+ if self.own:
148
+ yield (
149
+ self.label,
150
+ [],
151
+ AustinMetrics(time=self.own)
152
+ if stats_type in {AustinStatsType.CPU, AustinStatsType.WALL}
153
+ else AustinMetrics(memory=self.own),
154
+ )
155
+
156
+ if self.children:
157
+ yield from (
158
+ (self.label, frames, metric)
159
+ for stats in self.children.values()
160
+ for frames, metric in stats.collapse(stats_type)
161
+ )
134
162
 
135
163
 
136
164
  @dataclass
@@ -140,13 +168,21 @@ class ProcessStats:
140
168
  pid: ProcessId
141
169
  threads: Dict[ThreadName, ThreadStats] = field(default_factory=dict)
142
170
 
143
- def collapse(self) -> List[str]:
171
+ def collapse(
172
+ self, stats_type: AustinStatsType
173
+ ) -> Generator[AustinSample, None, None]:
144
174
  """Collapse the hierarchical statistics."""
145
- return [
146
- f"P{self.pid}{rest}"
147
- for _, thread in self.threads.items()
148
- for rest in thread.collapse()
149
- ]
175
+ yield from (
176
+ AustinSample(
177
+ pid=self.pid,
178
+ iid=thread_name.iid,
179
+ thread=thread_name.thread,
180
+ frames=tuple(frames),
181
+ metrics=metric,
182
+ )
183
+ for thread in self.threads.values()
184
+ for thread_name, frames, metric in thread.collapse(stats_type)
185
+ )
150
186
 
151
187
  def get_thread(self, thread_name: ThreadName) -> Optional[ThreadStats]:
152
188
  """Get thread statistics from this process by name.
@@ -157,15 +193,6 @@ class ProcessStats:
157
193
  return self.threads.get(thread_name)
158
194
 
159
195
 
160
- class AustinStatsType(Enum):
161
- """Austin stats type."""
162
-
163
- WALL = "wall"
164
- CPU = "cpu"
165
- MEMORY_ALLOC = "memory_alloc"
166
- MEMORY_DEALLOC = "memory_dealloc"
167
-
168
-
169
196
  @dataclass
170
197
  class AustinStats:
171
198
  """Austin statistics.
@@ -190,19 +217,6 @@ class AustinStats:
190
217
 
191
218
  return copy
192
219
 
193
- def dump(self, stream: TextIO) -> None:
194
- """Dump the statistics to the given text stream."""
195
- with self._lock:
196
- stream.write(f"# mode: {self.stats_type.value.partition('_')[0]}\n\n")
197
- for _, process in self.processes.items():
198
- samples = process.collapse()
199
-
200
- if all(sample.endswith(" 0 0") for sample in samples):
201
- samples = [sample[:-4] for sample in samples]
202
-
203
- for sample in samples:
204
- stream.write(sample + "\n")
205
-
206
220
  def get_process(self, pid: ProcessId) -> ProcessStats:
207
221
  """Get process statistics for the given PID."""
208
222
  return self.processes[pid]
@@ -272,7 +286,8 @@ class AustinStats:
272
286
  return
273
287
 
274
288
  pid = sample.pid
275
- thread_stats = ThreadStats(sample.thread, own=0, total=metric)
289
+ thread_name = ThreadName(sample.thread, sample.iid or 0)
290
+ thread_stats = ThreadStats(thread_name, own=0, total=metric)
276
291
 
277
292
  # Convert the list of frames into a nested FrameStats instance
278
293
  stats: HierarchicalStats = thread_stats
@@ -285,12 +300,16 @@ class AustinStats:
285
300
 
286
301
  with self._lock:
287
302
  if pid not in self.processes:
288
- self.processes[pid] = ProcessStats(pid, {sample.thread: thread_stats})
303
+ self.processes[pid] = ProcessStats(pid, {thread_name: thread_stats})
289
304
  return
290
305
 
291
306
  process = self.processes[pid]
292
- if sample.thread not in process.threads:
293
- process.threads[sample.thread] = thread_stats
307
+ if thread_name not in process.threads:
308
+ process.threads[thread_name] = thread_stats
294
309
  return
295
310
 
296
- process.threads[sample.thread] << thread_stats
311
+ process.threads[thread_name] << thread_stats
312
+
313
+ def flatten(self) -> Generator[AustinSample, None, None]:
314
+ for process in self.processes.values():
315
+ yield from process.collapse(self.stats_type)
austin/tools/mojodbg.py CHANGED
@@ -33,12 +33,13 @@ from austin.format.mojo import MojoStreamReader
33
33
  __version__ = "0.1.0"
34
34
 
35
35
 
36
- def mojodbg(args: t.Any) -> None:
37
- mojo = MojoStreamReader(args.input.expanduser().open("rb"))
36
+ def mojodbg(mojo: MojoStreamReader, echo: bool = False) -> None:
38
37
  offset = 4
39
38
  last_event_data: t.Tuple[t.Optional[MojoEvent], int] = (None, 0)
40
39
  try:
41
40
  for e in mojo.parse():
41
+ if echo:
42
+ print(e)
42
43
  last_event_data = (e, offset)
43
44
  offset = mojo._offset + 1
44
45
  except Exception as exc:
@@ -63,10 +64,15 @@ def main() -> None:
63
64
  argp = ArgumentParser(prog="mojodbg", description="Debug MOJO files.")
64
65
 
65
66
  argp.add_argument("input", type=Path, help="The MOJO file to debug.")
67
+ argp.add_argument(
68
+ "-e", "echo", action="store_true", help="Echo all the MOJO events"
69
+ )
66
70
  argp.add_argument("-V", "--version", action="version", version=__version__)
67
71
 
72
+ args = argp.parse_args()
73
+
68
74
  try:
69
- mojodbg(args := argp.parse_args())
75
+ mojodbg(MojoStreamReader(args.input.expanduser().open("rb")), args.echo)
70
76
  except FileNotFoundError:
71
77
  print(f"No such input file: {args.input}")
72
78
  exit(2)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: austin-python
3
- Version: 2.0.0
3
+ Version: 2.1.1
4
4
  Summary: Python wrapper for Austin, the CPython frame stack sampler.
5
5
  Project-URL: homepage, https://github.com/P403n1x87/austin-python
6
6
  Project-URL: documentation, https://austin-python.readthedocs.io
@@ -4,26 +4,26 @@ austin/base.py,sha256=wAYVZQi3hcgJA9cVg3mfc3f3E0qwFXmeX7UX6qgn2Pk,7554
4
4
  austin/cli.py,sha256=--PKm2I4NBBSSSBV5l-YC0mcmLjrvb1FHzxgY4dkby4,7826
5
5
  austin/config.py,sha256=PEwdG2Cy8ay1SrFr2N6YfQSZwseYBA1BA5dMfocKR3A,2091
6
6
  austin/errors.py,sha256=lCDSTANW_95Az_eDXbn__JRBllB9yw7tGnFo1-tw09Q,1046
7
- austin/events.py,sha256=yk1FZVNfQJxxUDjUmXb5Q_ajhgVCJS_CS3aObCYQv_M,2160
7
+ austin/events.py,sha256=39BHP-pUHotZZxJ-MbECFu5_QOAnRJP-_hFEdYPYwKY,2235
8
8
  austin/simple.py,sha256=iTmJGAjSBeUv82SgdMTwdNlAQwuK33RyU8FkBCE8rRg,5579
9
- austin/stats.py,sha256=ef3_vOI4xIACDo3l6wl0fwuz2k3qvRI57R2ZSuUEGFs,10368
9
+ austin/stats.py,sha256=8cpuq3cyZUpGkm2VZS3j1Zpz-Yhr3i9Wg6bR-sGwWJM,10933
10
10
  austin/threads.py,sha256=AvcoOkr3FeFAGBcqgXukNIt9xOZUipv7pXMqPIL_Qts,3649
11
11
  austin/format/__init__.py,sha256=ZtBJCLpTiZaLFwCN1UbMXLQvYjOSpwmtyGwqgK8yruQ,405
12
- austin/format/collapsed_stack.py,sha256=D1JaB3vREouVW_CcO_yY3IuuIRP3lhi2WXHr2AXxYZM,7241
12
+ austin/format/collapsed_stack.py,sha256=61iEu3oFl9e3vUNHvhpAQzgJndxtE7WcbRwvRLO03S4,7246
13
13
  austin/format/compress.py,sha256=YEceebWzVB7eSCntnJ89_rIcbzBskvZGy86D5QgZli0,3741
14
- austin/format/mojo.py,sha256=fGY_6o-7_XMQvb1lt2T1-RzxLywmn0x0OAnkQklt04U,22983
15
- austin/format/speedscope.py,sha256=Ydfi02f90F9BZftA-tb5qSZO-zzbE-lKXPz3f6_YRUc,7981
14
+ austin/format/mojo.py,sha256=IlnFsH9gGofENWBMdbpAc0BrutNGvetk5JLLJeCHKuo,28294
15
+ austin/format/speedscope.py,sha256=RvlFugm0S3ATMf9lmzH8jrX4oBt8PJ0j9EsuXWayOQc,8381
16
16
  austin/format/pprof/__init__.py,sha256=DvY1CDnPqBc-GUv9fidtMplshIIXj_HWZ3SlWOJoLxc,6805
17
- austin/format/pprof/__main__.py,sha256=4O4gmVvw807A1Wmxajj7dGly0M9kd-NYhEq9m47Bjas,2583
17
+ austin/format/pprof/__main__.py,sha256=pzWoSmlFrjfmAAq5I4SIIDmxavdLStCnlw3NlBxgyDo,2652
18
18
  austin/format/pprof/profile.proto,sha256=fPfBgzXIEmFdrrwgTQWs-9GwKjt-TShRmJq-eaxDx88,8840
19
19
  austin/format/pprof/profile_pb2.py,sha256=i_uM8lDExR95yz7qnEVikhpkpNvetKaYzoiH7AbMAt8,28214
20
20
  austin/tools/diff.py,sha256=KnY9kD5mmSKALCNxnSe-dSObC4LgkoxLGnoTiklKa5M,4821
21
- austin/tools/mojodbg.py,sha256=gpNhPJf1qrIEruBgAQ4wZk7cte0gE29vL3ZDi6HES4U,2632
21
+ austin/tools/mojodbg.py,sha256=BGdngj-r1c-GAQDrs_oJ_x4QZxuL4t_OQ194fvJJm7A,2817
22
22
  austin/tools/resolve.py,sha256=pEOBiP8FNkaJqDTj3fOK8dx5-EocroqZDXLL3CzCWLY,7677
23
- austin_python-2.0.0.dist-info/METADATA,sha256=OKQj3tS0abH3Eox2TNORgeohIaIs5JiH1K2pz6LLjcw,7535
24
- austin_python-2.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
- austin_python-2.0.0.dist-info/entry_points.txt,sha256=YatHOUQsHQ3WABcrNKPf4RWatQ0CzbR-1ClXjMjZys8,329
26
- austin_python-2.0.0.dist-info/licenses/AUTHORS,sha256=pARRmpJQYH8iWy_0SonXsxOiV02AFitowle4AtURxUI,45
27
- austin_python-2.0.0.dist-info/licenses/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
28
- austin_python-2.0.0.dist-info/licenses/LICENSE.md,sha256=edVDhmEiPf2W5lWzqLkrj6EYLSrCeYg9MJy28YsiMFU,34937
29
- austin_python-2.0.0.dist-info/RECORD,,
23
+ austin_python-2.1.1.dist-info/METADATA,sha256=t22jsfhB6Ssk8vR8LIwD0l9bcw0LnUb0eEXKx-uJEp0,7535
24
+ austin_python-2.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
25
+ austin_python-2.1.1.dist-info/entry_points.txt,sha256=YatHOUQsHQ3WABcrNKPf4RWatQ0CzbR-1ClXjMjZys8,329
26
+ austin_python-2.1.1.dist-info/licenses/AUTHORS,sha256=pARRmpJQYH8iWy_0SonXsxOiV02AFitowle4AtURxUI,45
27
+ austin_python-2.1.1.dist-info/licenses/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
28
+ austin_python-2.1.1.dist-info/licenses/LICENSE.md,sha256=edVDhmEiPf2W5lWzqLkrj6EYLSrCeYg9MJy28YsiMFU,34937
29
+ austin_python-2.1.1.dist-info/RECORD,,