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

Lines changed: 106 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy