Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .github/workflows/cibuildwheel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ jobs:
CIBW_ARCHS_LINUX: auto aarch64
# cp3*t-*: free-threaded CPython is built by default since
# cibuildwheel 4, but vmprof does not support it
CIBW_SKIP: "pp* cp3*t-* *-win32 *-manylinux_i686 *musllinux*"
CIBW_SKIP: "cp3*t-* *-win32 *-manylinux_i686 *musllinux*"
CIBW_BEFORE_BUILD_LINUX: dnf install -y libunwind-devel
CIBW_BEFORE_TEST: pip install -r test_requirements.txt
CIBW_TEST_GROUPS: test
CIBW_TEST_COMMAND: cd {package} && pytest vmprof jitlog -vv
CIBW_TEST_COMMAND_WINDOWS: cd /d {package} && pytest vmprof jitlog -vv
CIBW_TEST_SKIP: "*-*linux_{aarch64,ppc64le,s390x}"
Expand Down Expand Up @@ -78,7 +78,8 @@ jobs:
- name: Test wheel
run: |
FAILED=false
pypy -m pip install -r test_requirements.txt build
pypy -m pip install --upgrade pip
pypy -m pip install --group test build
pypy -m pytest vmprof -v || FAILED=true
pypy -m pytest jitlog -v || FAILED=true
if [ "$FAILED" == true ]; then exit 1; fi
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install .
python -m pip install -r test_requirements.txt
python -m pip install --group test
- name: Display Python version
run: python -c "import sys; print(sys.version)"
- name: Run Tests
Expand Down
4 changes: 0 additions & 4 deletions dev_requirements.txt

This file was deleted.

2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
project('vmprof', 'c',
version: '0.5.0',
version: '0.5.1',
license: 'MIT',
meson_version: '>=1.1.0',
)
Expand Down
8 changes: 7 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ authors = [
requires-python = ">=3.9,<3.16"
dependencies = [
"requests",
"six",
"colorama",
]
classifiers = [
Expand All @@ -32,5 +31,12 @@ Documentation = "https://vmprof.readthedocs.org/"
[project.scripts]
vmprofshow = "vmprof.show:main"

[dependency-groups]
test = [
"pytest",
"cffi",
"setuptools>=77",
]

[tool.meson-python.args]
setup = ["--vsenv"]
11 changes: 0 additions & 11 deletions test_requirements.txt

This file was deleted.

2 changes: 1 addition & 1 deletion vmprof/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import argparse
import sys
from six.moves import configparser
import configparser


def build_argparser():
Expand Down
5 changes: 2 additions & 3 deletions vmprof/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os
import struct
import sys
from six.moves import xrange
import io
import gzip
import datetime
Expand Down Expand Up @@ -209,12 +208,12 @@ def read_trace(self, depth):
kinds_and_pcs = self.read_addresses(depth * 2)
# kinds_and_pcs is a list of [kind1, pc1, kind2, pc2, ...]
return [wrap_kind(kinds_and_pcs[i], kinds_and_pcs[i+1])
for i in xrange(0, len(kinds_and_pcs), 2)]
for i in range(0,len(kinds_and_pcs), 2)]
else:
trace = self.read_addresses(depth)

if self.state.profile_lines:
for i in xrange(0, len(trace), 2):
for i in range(0,len(trace), 2):
# In the line profiling mode even items in the trace are line numbers.
# Every line number corresponds to the following frame, represented by an address.
trace[i] = -trace[i]
Expand Down
25 changes: 12 additions & 13 deletions vmprof/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import inspect
import linecache
import os
import six
import sys
import tokenize
import vmprof
Expand All @@ -13,15 +12,15 @@
from vmprof.stats import EmptyProfileFile


class color(six.text_type):
class color(str):
RED = '\033[31m'
WHITE = '\033[37m'
BLUE = '\033[94m'
BOLD = '\033[1m'
END = '\033[0m'

def __new__(cls, content, color, bold=False):
return six.text_type.__new__(
return str.__new__(
cls, "%s%s%s%s" % (color, cls.BOLD if bold else "", content, cls.END))

class AbstractPrinter(object):
Expand Down Expand Up @@ -81,7 +80,7 @@ def _walk_tree(self, parent, node, level, callback):
level += 1
if level > self._prune_level:
return
for c in six.itervalues(node.children):
for c in node.children.values():
self._walk_tree(node, c, level, callback)

color = color
Expand Down Expand Up @@ -140,7 +139,7 @@ def _print_tree(self, tree):
partial(self._print_node, total=float(tree.count)))


class html_color(six.text_type):
class html_color(str):
RED = 'red'
WHITE = 'black'
BLUE = 'blue'
Expand Down Expand Up @@ -172,7 +171,7 @@ def _walk_tree(self, parent, node, level, callback):
level += 1
if level > self._prune_level:
return
for c in six.itervalues(node.children):
for c in node.children.values():
self._walk_tree(node, c, level, callback)
print("</details>")

Expand Down Expand Up @@ -218,7 +217,7 @@ def _show(self, tree):

def _walk_tree(self, parent, node, callback):
callback(parent, node)
for c in six.itervalues(node.children):
for c in node.children.values():
self._walk_tree(node, c, callback)

def _print_tree(self, tree):
Expand All @@ -235,7 +234,7 @@ def collect_node(parent, node):
0 if parse_block_name(ch.name)[0] == 'n' and self.no_native
else ch.count

for ch in six.itervalues(node.children))
for ch in node.children.values())

func_id_to_count[ndescr] = func_id_to_count.get(ndescr, 0) + mycount

Expand Down Expand Up @@ -284,15 +283,15 @@ def walk(node, d):
# only python supported for line profiling
if block_type == 'py':
lines = d.setdefault((filename, int(funline), funname), {})
for l, cnt in six.iteritems(node.lines):
for l, cnt in node.lines.items():
lines[l] = lines.get(l, 0) + cnt

for c in six.itervalues(node.children):
for c in node.children.values():
walk(c, d)

walk(tree, funcs)

return six.iteritems(funcs)
return funcs.items()

def show_func(self, filename, start_lineno, func_name, timings, stream=None, stripzeros=False):
""" Show results for a single function.
Expand All @@ -305,7 +304,7 @@ def show_func(self, filename, start_lineno, func_name, timings, stream=None, str
total_hits = 0.0

linenos = []
for lineno, nhits in six.iteritems(timings):
for lineno, nhits in timings.items():
total_hits += nhits
linenos.append(lineno)

Expand Down Expand Up @@ -338,7 +337,7 @@ def show_func(self, filename, start_lineno, func_name, timings, stream=None, str
# Fake empty lines so we can see the timings, if not the code.
nlines = max(linenos) - min(min(linenos), start_lineno) + 1
sublines = [''] * nlines
for lineno, nhits in six.iteritems(timings):
for lineno, nhits in timings.items():
d[lineno] = (nhits, '%5.1f' % (100* nhits / total_hits))
linenos = range(start_lineno, start_lineno + len(sublines))
empty = ('', '')
Expand Down
15 changes: 7 additions & 8 deletions vmprof/stats.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import six
from vmprof.reader import AssemblerCode, JittedCode, NativeCode

class EmptyProfileFile(Exception):
Expand Down Expand Up @@ -77,7 +76,7 @@ def generate_top(self):
current_iter[addr] = None

def top_profile(self):
return [(self._get_name(k), v) for (k, v) in six.iteritems(self.functions)]
return [(self._get_name(k), v) for (k, v) in self.functions.items()]

def _get_name(self, addr):
if self.adr_dict is not None:
Expand Down Expand Up @@ -203,29 +202,29 @@ def as_json(self):
return json.dumps(self._serialize())

def _serialize(self):
chld = [ch._serialize() for ch in six.itervalues(self.children)]
chld = [ch._serialize() for ch in self.children.values()]
# if we don't make str() of addr here, JS does its
# int -> float -> int losy convertion without
# any warning
return [self.name, str(self.addr), self.count, self.meta, chld]

def _rec_count(self):
c = 1
for x in six.itervalues(self.children):
for x in self.children.values():
c += x._rec_count()
return c

def walk(self, callback):
callback(self)
for c in six.itervalues(self.children):
for c in self.children.values():
c.walk(callback)

def cumulative_meta(self, d=None):
if d is None:
d = {}
for c in six.itervalues(self.children):
for c in self.children.values():
c.cumulative_meta(d)
for k, v in six.iteritems(self.meta):
for k, v in self.meta.items():
d[k] = d.get(k, 0) + v
return d

Expand All @@ -241,7 +240,7 @@ def get_self_count(self):
if self._self_count is not None:
return self._self_count
self._self_count = self.count
for elem in six.itervalues(self.children):
for elem in self.children.values():
self._self_count -= elem.count
return self._self_count

Expand Down
30 changes: 9 additions & 21 deletions vmprof/test/test_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import gzip
import time
import vmprof
import six
from cffi import FFI
from datetime import datetime
import requests
Expand Down Expand Up @@ -52,11 +51,6 @@ def read(self, count):
return s


if sys.version_info.major == 3:
xrange = range
PY3K = True
else:
PY3K = False
if hasattr(os, 'uname') and os.uname()[4] == 'ppc64le':
PPC64LE = True
else:
Expand All @@ -69,7 +63,7 @@ def read(self, count):

def function_foo():
for k in range(1000):
l = [a for a in xrange(COUNT)]
l = [a for a in range(COUNT)]
return l

def function_bar():
Expand Down Expand Up @@ -197,16 +191,11 @@ def test_nested_call():
t = t['']
assert len(t.children) == 1
assert 'function_foo' in t[''].name
if PY3K:
# In Python 3.12+, list comprehensions are inlined and don't create
# a separate stack frame (PEP 709), so <listcomp> won't appear
if sys.version_info >= (3, 12):
assert len(t[''].children) == 0
else:
assert len(t[''].children) == 1
assert '<listcomp>' in t[''][''].name
else:
if sys.version_info >= (3, 12):
assert len(t[''].children) == 0
else:
assert len(t[''].children) == 1
assert '<listcomp>' in t[''][''].name

def test_multithreaded():
if '__pypy__' in sys.builtin_module_names:
Expand All @@ -218,7 +207,7 @@ def test_multithreaded():

def f():
for k in range(1000):
l = [a for a in xrange(COUNT)]
l = [a for a in range(COUNT)]
finished.append("foo")

threads = [threading.Thread(target=f), threading.Thread(target=f)]
Expand Down Expand Up @@ -255,7 +244,7 @@ def test_memory_measurment():
def function_foo():
all = []
for k in range(1000):
all.append([a for a in xrange(COUNT)])
all.append([a for a in range(COUNT)])
return all

def function_bar():
Expand Down Expand Up @@ -419,8 +408,7 @@ def read_one_marker(fileobj, status, buffer_so_far=None):
elif marker == MARKER_VIRTUAL_IP or marker == MARKER_NATIVE_SYMBOLS:
unique_id = read_addr(fileobj)
name = read_string(fileobj)
if PY3K:
name = name.decode()
name = name.decode()
status.virtual_ips[unique_id] = name
elif marker == MARKER_META:
read_string(fileobj)
Expand Down Expand Up @@ -457,7 +445,7 @@ def test_line_profiling():
def walk(tree):
assert len(tree.lines) >= len(tree.children)

for v in six.itervalues(tree.children):
for v in tree.children.values():
walk(v)

stats = read_profile(tmpfile.name)
Expand Down
4 changes: 2 additions & 2 deletions vmprof/test/test_stats.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import json
import os
import zlib

import pytest
import six

import vmprof
from vmprof.stats import Node, Stats, JittedCode, AssemblerCode
Expand Down Expand Up @@ -34,7 +34,7 @@ def test_tree_jit():
def test_read_simple():
pytest.skip("think later")
lib_cache = get_or_write_libcache('simple_nested.pypy.prof')
path = py.path.local(__file__).join('..', 'simple_nested.pypy.prof')
path = os.path.join(os.path.dirname(__file__), 'simple_nested.pypy.prof')
stats = vmprof.read_profile(path, virtual_only=True,
include_extra_info=True, lib_cache=lib_cache)
tree = stats.get_tree()
Expand Down