exeplot 0.5.2__tar.gz → 0.5.4__tar.gz
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.
- {exeplot-0.5.2 → exeplot-0.5.4}/PKG-INFO +1 -1
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/coverage.svg +1 -1
- exeplot-0.5.4/src/exeplot/VERSION.txt +1 -0
- exeplot-0.5.4/src/exeplot/__init__.py +9 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/utils.py +12 -9
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot.egg-info/PKG-INFO +1 -1
- {exeplot-0.5.2 → exeplot-0.5.4}/tests/test_others.py +3 -4
- exeplot-0.5.2/src/exeplot/VERSION.txt +0 -1
- exeplot-0.5.2/src/exeplot/__init__.py +0 -5
- {exeplot-0.5.2 → exeplot-0.5.4}/.coveragerc +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/.github/workflows/python-package.yml +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/.gitignore +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/.readthedocs.yml +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/LICENSE +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/README.md +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/_config.yml +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/mkdocs.yml +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/css/extra.css +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/calc_orig_entropy.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/calc_packed_byte.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/calc_packed_byte2.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/calc_packed_entropy.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/calc_packed_nested_pie.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/calc_packed_pie.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/icon.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/logo.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/upx_calc_byte.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/img/upx_calc_entropy.png +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/pages/index.md +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/docs/requirements.txt +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/pyproject.toml +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/pytest.ini +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/requirements.txt +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/setup.cfg +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/__conf__.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/__info__.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/__main__.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/plots/__common__.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/plots/__init__.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/plots/byte.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/plots/diff.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/plots/entropy.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/plots/graph.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/plots/nested_pie.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot/plots/pie.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot.egg-info/SOURCES.txt +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot.egg-info/dependency_links.txt +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot.egg-info/entry_points.txt +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot.egg-info/requires.txt +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/src/exeplot.egg-info/top_level.txt +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/tests/__init__.py +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/tests/hello.elf +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/tests/hello.exe +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/tests/hello.macho +0 -0
- {exeplot-0.5.2 → exeplot-0.5.4}/tests/test_plots.py +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage: 96.
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage: 96.62%"><title>coverage: 96.62%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="114" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="53" height="20" fill="#4c1"/><rect width="114" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="865" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">96.62%</text><text x="865" y="140" transform="scale(.1)" fill="#fff" textLength="430">96.62%</text></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.5.4
|
|
@@ -30,19 +30,22 @@ def human_readable_size(size: int, precision: int = 0) -> str:
|
|
|
30
30
|
return "%.*f%s" % (precision, size, units[i])
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
def ngrams_counts(byte_obj: bytes | object, n: int = 1, step: int = 1) ->
|
|
34
|
-
""" Output
|
|
35
|
-
If the input is a byte object,
|
|
33
|
+
def ngrams_counts(byte_obj: bytes | object, n: int = 1, step: int = 1) -> list[tuple[bytes, int]]:
|
|
34
|
+
""" Output a sorted list of tuples (n-gram, counts) for an input byte sequence or byte object.
|
|
35
|
+
If the input is a byte object, the result is cached.
|
|
36
36
|
|
|
37
|
-
:param byte_obj:
|
|
38
|
-
:param n:
|
|
39
|
-
:param step:
|
|
40
|
-
:param start: number of bytes to start from
|
|
37
|
+
:param byte_obj: byte sequence ('bytes') or byte object with "bytes" and "size" attributes (i.e. pathlib2.Path)
|
|
38
|
+
:param n: n determining the size of n-grams, defaults to 1
|
|
39
|
+
:param step: step for sliding the n-grams
|
|
41
40
|
"""
|
|
42
41
|
if n not in (1, 2, 3):
|
|
43
42
|
raise ValueError("n must be 1, 2, or 3")
|
|
44
43
|
if step <= 0:
|
|
45
44
|
raise ValueError("step must be positive")
|
|
45
|
+
try:
|
|
46
|
+
return byte_obj._ngram_counts_cache[n]
|
|
47
|
+
except (AttributeError, KeyError):
|
|
48
|
+
pass
|
|
46
49
|
if isinstance(byte_obj, bytes) or hasattr(byte_obj, "bytes"):
|
|
47
50
|
a = np.frombuffer(data := byte_obj if isinstance(byte_obj, bytes) else byte_obj.bytes, dtype=np.uint8)
|
|
48
51
|
l = a.size
|
|
@@ -56,6 +59,7 @@ def ngrams_counts(byte_obj: bytes | object, n: int = 1, step: int = 1) -> dict[b
|
|
|
56
59
|
grams = np.stack((a[0:end:step], a[1:1+end:step]), axis=1) if n == 2 else \
|
|
57
60
|
np.stack((a[0:end:step], a[1:1+end:step], a[2:2+end:step]), axis=1)
|
|
58
61
|
counts = {bytes(row): int(c) for row, c in zip(*np.unique(grams, axis=0, return_counts=True))}
|
|
62
|
+
counts = sorted(counts.items(), key=lambda p: p[1], reverse=True)
|
|
59
63
|
if isinstance(byte_obj, bytes):
|
|
60
64
|
return counts
|
|
61
65
|
elif hasattr(byte_obj, "bytes"):
|
|
@@ -80,8 +84,7 @@ def ngrams_distribution(byte_obj: bytes | object, n: int = 1, step: int = 1, n_m
|
|
|
80
84
|
:return: list of n_most_common (n-gram, count) pairs
|
|
81
85
|
"""
|
|
82
86
|
c = ngrams_counts(byte_obj, n, step)
|
|
83
|
-
|
|
84
|
-
r = sorted(c.items(), key=lambda p: p[1], reverse=True)[:n]
|
|
87
|
+
r = c[:len(c) if n_most_common is None else n_most_common + n_exclude_top + len(exclude or [])]
|
|
85
88
|
if exclude is not None:
|
|
86
89
|
r = [(ngram, count) for ngram, count in r if ngram not in exclude]
|
|
87
90
|
return r[n_exclude_top:n_exclude_top+(n_most_common or len(c))]
|
|
@@ -24,12 +24,11 @@ class TestUtils(TestCase):
|
|
|
24
24
|
self.assertRaises(ValueError, ngrams_counts, b"abc", n=n)
|
|
25
25
|
self.assertRaises(ValueError, ngrams_counts, b"abc", step=-1)
|
|
26
26
|
self.assertEqual(ngrams_counts(b"a", n=2), {})
|
|
27
|
-
self.assertTrue(isinstance(ngrams_counts(seq := b"\x00" * 4 + os.urandom(120) + b"\xff" * 4),
|
|
28
|
-
self.assertTrue(isinstance(ngrams_counts(seq := b"\x00" * 4 + os.urandom(120) + b"\xff" * 4, n=2),
|
|
27
|
+
self.assertTrue(isinstance(ngrams_counts(seq := b"\x00" * 4 + os.urandom(120) + b"\xff" * 4), list))
|
|
28
|
+
self.assertTrue(isinstance(ngrams_counts(seq := b"\x00" * 4 + os.urandom(120) + b"\xff" * 4, n=2), list))
|
|
29
29
|
class Test:
|
|
30
30
|
bytes = seq
|
|
31
|
-
histogram
|
|
32
|
-
self.assertTrue(isinstance(histogram, list))
|
|
31
|
+
self.assertTrue(isinstance(histogram := ngrams_distribution(t := Test(), exclude=(b"\x00", b"\xff")), list))
|
|
33
32
|
self.assertNotIn(b"\x00", [b for b, c in histogram])
|
|
34
33
|
self.assertNotIn(b"\xff", [b for b, c in histogram])
|
|
35
34
|
histogram2 = ngrams_distribution(t, n_most_common=300)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
0.5.2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|