micropython-lib/optimize_upip.py

122 wiersze
2.8 KiB
Python

#
# This script optimizes a Python source distribution tarball as produced by
# "python3 setup.py sdist" command for MicroPython's native package manager,
# upip. Optimization includes:
# * Removing metadata files not used by upip (this includes setup.py)
# * Recompressing gzip archive with 4K dictionary size so it can be
# installed even on low-heap targets.
#
import sys
import os
import zlib
from subprocess import Popen, PIPE
import glob
import tarfile
import re
import io
def gzip_4k(inf, fname):
comp = zlib.compressobj(level=9, wbits=16 + 12)
with open(fname + ".out", "wb") as outf:
while 1:
data = inf.read(1024)
if not data:
break
outf.write(comp.compress(data))
outf.write(comp.flush())
os.rename(fname, fname + ".orig")
os.rename(fname + ".out", fname)
def recompress(fname):
with Popen(["gzip", "-d", "-c", fname], stdout=PIPE).stdout as inf:
gzip_4k(inf, fname)
def find_latest(dir):
res = []
for fname in glob.glob(dir + "/*.gz"):
st = os.stat(fname)
res.append((st.st_mtime, fname))
res.sort()
latest = res[-1][1]
return latest
def recompress_latest(dir):
latest = find_latest(dir)
print(latest)
recompress(latest)
FILTERS = [
# include, exclude, repeat
(r".+\.egg-info/(PKG-INFO|requires\.txt)", r"setup.py$"),
(r".+\.py$", r"[^/]+$"),
(None, r".+\.egg-info/.+"),
]
outbuf = io.BytesIO()
def filter_tar(name):
fin = tarfile.open(name, "r:gz")
fout = tarfile.open(fileobj=outbuf, mode="w")
for info in fin:
# print(info)
if not "/" in info.name:
continue
fname = info.name.split("/", 1)[1]
include = None
for inc_re, exc_re in FILTERS:
if include is None and inc_re:
if re.match(inc_re, fname):
include = True
if include is None and exc_re:
if re.match(exc_re, fname):
include = False
if include is None:
include = True
if include:
print("Including:", fname)
else:
print("Excluding:", fname)
continue
farch = fin.extractfile(info)
fout.addfile(info, farch)
fout.close()
fin.close()
from setuptools import Command
class OptimizeUpip(Command):
user_options = []
def run(self):
latest = find_latest("dist")
filter_tar(latest)
outbuf.seek(0)
gzip_4k(outbuf, latest)
def initialize_options(self):
pass
def finalize_options(self):
pass
# For testing only
if __name__ == "__main__":
# recompress_latest(sys.argv[1])
filter_tar(sys.argv[1])
outbuf.seek(0)
gzip_4k(outbuf, sys.argv[1])