Skip to content

Commit 8e2dde1

Browse files
authored
Make upip installable (#56)
add setup.py to build upip installable distribution package for pypi setup.py (setuptools) uses the sdist_upip module (included in this commit) to generate packages in the correct format for use with upip. To generate a distribution package, make sure the VERSION is set as desired in setup.py and then run `python3 setup.py sdist`. The result will be a tar.gz file in the dist/ subdirectory. also: add additional supported platforms It appears the "platforms" fields it not actually used by any tools but can be used to communicate to users what platforms the package is meant to work on. (https://stackoverflow.com/a/34994245) Including linux and darwin here, because the code runs well on the unix port of MicroPython, which itself runs well on Linux and macOS (darwin). In fact most of the testing had been done using the unix port.
1 parent 9217573 commit 8e2dde1

File tree

2 files changed

+181
-0
lines changed

2 files changed

+181
-0
lines changed

Diff for: sdist_upip.py

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# This module is part of Pycopy https://github.com/pfalcon/pycopy
2+
# and pycopy-lib https://github.com/pfalcon/pycopy-lib, projects to
3+
# create a (very) lightweight full-stack Python distribution.
4+
#
5+
# Copyright (c) 2016-2019 Paul Sokolovsky
6+
# Licence: MIT
7+
#
8+
# This module overrides distutils (also compatible with setuptools) "sdist"
9+
# command to perform pre- and post-processing as required for Pycopy's
10+
# upip package manager.
11+
#
12+
# Preprocessing steps:
13+
# * Creation of Python resource module (R.py) from each top-level package's
14+
# resources.
15+
# Postprocessing steps:
16+
# * Removing metadata files not used by upip (this includes setup.py)
17+
# * Recompressing gzip archive with 4K dictionary size so it can be
18+
# installed even on low-heap targets.
19+
#
20+
import sys
21+
import os
22+
import zlib
23+
from subprocess import Popen, PIPE
24+
import glob
25+
import tarfile
26+
import re
27+
import io
28+
29+
from distutils.filelist import FileList
30+
from setuptools.command.sdist import sdist as _sdist
31+
32+
33+
def gzip_4k(inf, fname):
34+
comp = zlib.compressobj(level=9, wbits=16 + 12)
35+
with open(fname + ".out", "wb") as outf:
36+
while 1:
37+
data = inf.read(1024)
38+
if not data:
39+
break
40+
outf.write(comp.compress(data))
41+
outf.write(comp.flush())
42+
os.rename(fname, fname + ".orig")
43+
os.rename(fname + ".out", fname)
44+
45+
46+
FILTERS = [
47+
# include, exclude, repeat
48+
(r".+\.egg-info/(PKG-INFO|requires\.txt)", r"setup.py$"),
49+
(r".+\.py$", r"[^/]+$"),
50+
(None, r".+\.egg-info/.+"),
51+
]
52+
53+
54+
outbuf = io.BytesIO()
55+
56+
def filter_tar(name):
57+
fin = tarfile.open(name, "r:gz")
58+
fout = tarfile.open(fileobj=outbuf, mode="w")
59+
for info in fin:
60+
# print(info)
61+
if not "/" in info.name:
62+
continue
63+
fname = info.name.split("/", 1)[1]
64+
include = None
65+
66+
for inc_re, exc_re in FILTERS:
67+
if include is None and inc_re:
68+
if re.match(inc_re, fname):
69+
include = True
70+
71+
if include is None and exc_re:
72+
if re.match(exc_re, fname):
73+
include = False
74+
75+
if include is None:
76+
include = True
77+
78+
if include:
79+
print("including:", fname)
80+
else:
81+
print("excluding:", fname)
82+
continue
83+
84+
farch = fin.extractfile(info)
85+
fout.addfile(info, farch)
86+
fout.close()
87+
fin.close()
88+
89+
90+
def make_resource_module(manifest_files):
91+
resources = []
92+
# Any non-python file included in manifest is resource
93+
for fname in manifest_files:
94+
ext = fname.rsplit(".", 1)
95+
if len(ext) > 1:
96+
ext = ext[1]
97+
else:
98+
ext = ""
99+
if ext != "py":
100+
resources.append(fname)
101+
102+
if resources:
103+
print("creating resource module R.py")
104+
resources.sort()
105+
last_pkg = None
106+
r_file = None
107+
for fname in resources:
108+
try:
109+
pkg, res_name = fname.split("/", 1)
110+
except ValueError:
111+
print("not treating %s as a resource" % fname)
112+
continue
113+
if last_pkg != pkg:
114+
last_pkg = pkg
115+
if r_file:
116+
r_file.write("}\n")
117+
r_file.close()
118+
r_file = open(pkg + "/R.py", "w")
119+
r_file.write("R = {\n")
120+
121+
with open(fname, "rb") as f:
122+
r_file.write("%r: %r,\n" % (res_name, f.read()))
123+
124+
if r_file:
125+
r_file.write("}\n")
126+
r_file.close()
127+
128+
129+
class sdist(_sdist):
130+
131+
def run(self):
132+
self.filelist = FileList()
133+
self.get_file_list()
134+
make_resource_module(self.filelist.files)
135+
136+
r = super().run()
137+
138+
assert len(self.archive_files) == 1
139+
print("filtering files and recompressing with 4K dictionary")
140+
filter_tar(self.archive_files[0])
141+
outbuf.seek(0)
142+
gzip_4k(outbuf, self.archive_files[0])
143+
144+
return r
145+
146+
147+
# For testing only
148+
if __name__ == "__main__":
149+
filter_tar(sys.argv[1])
150+
outbuf.seek(0)
151+
gzip_4k(outbuf, sys.argv[1])

Diff for: setup.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from pathlib import Path
2+
from setuptools import setup
3+
import sdist_upip
4+
5+
6+
HERE = Path(__file__).parent
7+
README = (HERE / 'README.rst').read_text()
8+
9+
VERSION = "1.0.0"
10+
11+
setup(
12+
name="micropython-py-esp32-ulp",
13+
version=VERSION,
14+
description="Assembler toolchain for the ESP32 ULP co-processor, written in MicroPython",
15+
long_description=README,
16+
long_description_content_type='text/x-rst',
17+
url="https://github.com/ThomasWaldmann/py-esp32-ulp",
18+
license="MIT",
19+
author="py-esp32-ulp authors",
20+
author_email="[email protected]",
21+
maintainer="py-esp32-ulp authors",
22+
maintainer_email="[email protected]",
23+
classifiers=[
24+
'License :: OSI Approved :: MIT License',
25+
'Programming Language :: Python :: Implementation :: MicroPython',
26+
],
27+
platforms=["esp32", "linux", "darwin"],
28+
cmdclass={"sdist": sdist_upip.sdist},
29+
packages=["esp32_ulp"],
30+
)

0 commit comments

Comments
 (0)