Skip to content

Commit 6d2c001

Browse files
committed
optimize_upip.py: Script to optimize archives for low-heap upip usage.
1 parent 89e7f26 commit 6d2c001

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

optimize_upip.py

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#
2+
# This script optimizes a Python source distribution tarball as produced by
3+
# "python3 setup.py sdist" command for MicroPython's native package manager,
4+
# upip. Optimization includes:
5+
# * Removing metadata files not used by upip (this includes setup.py)
6+
# * Recompressing gzip archive with 4K dictionary size so it can be
7+
# installed even on low-heap targets.
8+
#
9+
import sys
10+
import os
11+
import zlib
12+
from subprocess import Popen, PIPE
13+
import glob
14+
import tarfile
15+
import re
16+
import io
17+
18+
19+
def gzip_4k(inf, fname):
20+
comp = zlib.compressobj(level=9, wbits=16 + 12)
21+
with open(fname + ".out", "wb") as outf:
22+
while 1:
23+
data = inf.read(1024)
24+
if not data:
25+
break
26+
outf.write(comp.compress(data))
27+
outf.write(comp.flush())
28+
os.rename(fname, fname + ".orig")
29+
os.rename(fname + ".out", fname)
30+
31+
32+
def recompress(fname):
33+
with Popen(["gzip", "-d", "-c", fname], stdout=PIPE).stdout as inf:
34+
gzip_4k(inf, fname)
35+
36+
def find_latest(dir):
37+
res = []
38+
for fname in glob.glob(dir + "/*.gz"):
39+
st = os.stat(fname)
40+
res.append((st.st_mtime, fname))
41+
res.sort()
42+
latest = res[-1][1]
43+
return latest
44+
45+
46+
def recompress_latest(dir):
47+
latest = find_latest(dir)
48+
print(latest)
49+
recompress(latest)
50+
51+
52+
EXCLUDE = [r".+/setup.py"]
53+
INCLUDE = [r".+\.py", r".+\.egg-info/(PKG-INFO|requires\.txt)"]
54+
55+
56+
outbuf = io.BytesIO()
57+
58+
def filter_tar(name):
59+
fin = tarfile.open(name, "r:gz")
60+
fout = tarfile.open(fileobj=outbuf, mode="w")
61+
for info in fin:
62+
# print(info)
63+
include = None
64+
for p in EXCLUDE:
65+
if re.match(p, info.name):
66+
include = False
67+
break
68+
if include is None:
69+
for p in INCLUDE:
70+
if re.match(p, info.name):
71+
include = True
72+
print("Including:", info.name)
73+
if not include:
74+
continue
75+
farch = fin.extractfile(info)
76+
fout.addfile(info, farch)
77+
fout.close()
78+
fin.close()
79+
80+
81+
82+
from setuptools import Command
83+
84+
class OptimizeUpip(Command):
85+
86+
user_options = []
87+
88+
def run(self):
89+
latest = find_latest("dist")
90+
filter_tar(latest)
91+
outbuf.seek(0)
92+
gzip_4k(outbuf, latest)
93+
94+
def initialize_options(self):
95+
pass
96+
97+
def finalize_options(self):
98+
pass
99+
100+
101+
# For testing only
102+
if __name__ == "__main__":
103+
# recompress_latest(sys.argv[1])
104+
filter_tar(sys.argv[1])
105+
outbuf.seek(0)
106+
gzip_4k(outbuf, sys.argv[1])

0 commit comments

Comments
 (0)