-
-
Save dholth/b9673950b20843afc91c26982788b1e4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import wheel.metadata | |
def convert_requirements(requirements, extras): | |
""" | |
Convert requirements from a setup()-style dictionary to Requires-Dist | |
and Provides-Extra. | |
""" | |
extras[''] = requirements | |
for extra, depends in extras.items(): | |
condition = '' | |
if extra and ':' in extra: # setuptools extra:condition syntax | |
extra, condition = extra.split(':', 1) | |
if extra: | |
yield ('Provides-Extra', extra) | |
if condition: | |
condition += " and " | |
condition += 'extra == %s' % repr(extra) | |
if condition: | |
condition = '; ' + condition | |
for new_req in sorted(wheel.metadata.convert_requirements(depends)): | |
yield ('Requires-Dist', new_req + condition) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example build requirements folling build-deps-pep | |
[build-system] | |
requires = ["cffi", "SCons>=2.5.0", "toml"] | |
[metadata] | |
name="pysdl2-cffi" | |
version="0.11.0" | |
packages=['sdl', '_sdl', '_sdl_image', '_sdl_mixer', '_sdl_ttf'] | |
setup_requires=["cffi>=1.6.0"] | |
install_requires=["cffi>=1.6.0"] | |
cffi_modules=[ | |
"_sdl/cdefs.py:ffi", | |
"_sdl_image/cdefs.py:ffi", | |
"_sdl_mixer/cdefs.py:ffi", | |
"_sdl_ttf/cdefs.py:ffi", | |
] | |
description="SDL2 wrapper with cffi" | |
# long_description=README + CHANGES | |
license="GPLv2+" | |
classifiers=[ | |
"Programming Language :: Python :: 2.7", | |
"Programming Language :: Python :: 3", | |
"Programming Language :: Python :: 3.4", | |
"License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)" | |
] | |
keywords=["sdl", "cffi"] | |
author="Daniel Holth" | |
author_email="dholth@fastmail.fm" | |
url="https://bitbucket.org/dholth/pysdl2-cffi" | |
[metadata.extras_require] | |
build = ['pycparser', 'astor', 'cffi>=1.6.0'] | |
doc = ['sphinx'] | |
":sys_platform=='win32'" = ["sdl2_lib"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Generate automatic wrapper helpers. | |
# Shell version: | |
# | |
# (cd builder ; python dox.py ~/prog/SDL2-2.0.3/include/xml/) | |
# Build the API wrappers | |
# python -m builder.build_sdl | |
# python -m builder.build_ttf | |
# python -m builder.build_mixer | |
# python -m builder.build_image | |
# # Sphinx and doc extraction don't work in Python 3 yet. | |
# # echo "Sphinx" | |
# (cd docs; make clean; make html) | |
# sdist notes | |
# unversioned dist_name.egg-info (hyphen to underscore) | |
# PKG-INFO in root | |
import sys | |
from distutils import sysconfig, ccompiler | |
import bdist | |
# compiler = distutils.ccompiler.new_compiler() | |
# distutils.sysconfig.customize_compiler(compiler) | |
# (parse arguments into scons environment) | |
compiler = sysconfig.customize_compiler(ccompiler.new_compiler()) | |
# the include dirs only come from build_ext's finalize_options | |
# (sysconfig.get_python_inc()) maybe also in cpython | |
# Python environment? | |
env = Environment(tools=['default', 'packaging']) | |
conf = Configure(env) | |
conf.env.Append(CPPPATH=[sysconfig.get_python_inc()]) | |
conf.env.Append(LIBPATH=[sysconfig.get_config_var('LIBDIR')]) | |
# LIBS = ['python' + sysconfig.get_config_var('VERSION')] # only on CPython; ask distutils | |
env = conf.Finish() | |
import contoml as toml | |
metadata = dict(toml.loads(open('pyproject.toml').read()).primitive)['metadata'] | |
# actually it should be the dictionary interface | |
env.PACKAGE_METADATA = metadata | |
env['PACKAGE_METADATA'] = metadata | |
env['PACKAGE_NAME'] = metadata['name'] | |
env['PACKAGE_VERSION'] = metadata['version'] | |
from SCons.Script import Execute, Mkdir # for Execute and Mkdir | |
def normalize_package(name): | |
return name.replace('-', '_') | |
env['PACKAGE_NAME_SAFE'] = normalize_package(env['PACKAGE_NAME']) | |
# Development .egg-info has no version number | |
env.EGG_INFO_PATH = env['PACKAGE_NAME_SAFE'] + '.egg-info' | |
def egg_info_targets(): | |
""" | |
Write the minimum .egg-info for pip. Full metadata will go into wheel's .dist-info | |
""" | |
return [env.fs.Dir(env.EGG_INFO_PATH).File(name) | |
for name in ['PKG-INFO', 'requires.txt']] | |
import setuptools.command.egg_info | |
class Command(object): | |
"""Mock object to allow setuptools to write files for us""" | |
def __init__(self, distribution): | |
self.distribution = distribution | |
def write_or_delete_file(self, basename, filename, data): | |
self.data = data | |
class Distribution(object): | |
def __init__(self, metadata): | |
self.__dict__ = metadata | |
command = Command(Distribution(env.PACKAGE_METADATA)) | |
def egg_info_builder(target, source, env): | |
""" | |
Minimum egg_info. To be used only by pip to get dependencies. | |
""" | |
for dnode in target: | |
with open(dnode.get_path(), 'w') as f: | |
if dnode.name == 'PKG-INFO': | |
f.write("Metadata-Version: 1.1\n") | |
f.write("Name: %s\n" % env['PACKAGE_NAME']) | |
f.write("Version: %s\n" % env['PACKAGE_VERSION']) | |
elif dnode.name == "requires.txt": | |
setuptools.command.egg_info.write_requirements(command, dnode.name, 'spamalot') | |
f.write(command.data) | |
egg_info = env.Command(egg_info_targets(), 'pyproject.toml', | |
egg_info_builder) | |
env.Alias('egg_info', egg_info) | |
def metadata_builder(target, source, env): | |
metadata = env['PACKAGE_METADATA'] | |
with open(target[0].get_path(), 'w') as f: | |
f.write("Metadata-Version: 2.0\n") | |
f.write("Name: %s\n" % metadata['name']) | |
f.write("Version: %s\n" % metadata['version']) | |
f.write("Sumary: %s\n" % metadata['description']) | |
f.write("Home-Page: %s\n" % metadata['url']) | |
f.write("Author: %s\n" % metadata['author']) | |
f.write("Author-email: %s\n" % metadata['author_email']) | |
f.write("License: %s\n" % metadata['license']) | |
f.write("Keywords: %s" % " ".join(metadata['keywords'])) | |
f.write("Platform: %s\n" % metadata.get('platform', 'UNKNOWN')) | |
for classifier in metadata.get('classifiers', []): | |
f.write("Classifier: %s\n" % classifier) | |
for requirement in bdist.convert_requirements(metadata.get('install_requires', []), | |
metadata.get('extras_require', {})): | |
f.write("%s: %s\n" % requirement) | |
# XXX long description | |
metadata = env.Command('METADATA', 'pyproject.toml', metadata_builder) | |
pkg_info = env.Command('PKG-INFO', egg_info_targets()[0].get_path(), | |
Copy('$TARGET', '$SOURCE')) | |
# env.NoClean('important-file') | |
# env.Precious('foobar') | |
# egg_info = env.Command(Dir(env.EGG_INFO_PATH), 'pyproject.toml', build_egg_info) | |
# distutils.command.build_ext._get_c_extension_suffix() | |
# get_ext_filename() | |
# get_export_symbols() | |
def get_build_command(name): | |
return sys.executable + " -m builder.build_" + name | |
src_files = Glob('sdl/*.py') + Glob('_sdl*/*.py') | |
parts_targets = {'sdl': 'sdl/__init__.py', | |
'image': 'sdl/image.py', | |
'sdl_image': 'sdl/image.py', | |
'mixer': 'sdl/mixer.py', | |
'sdl_mixer': 'sdl/mixer.py', | |
'ttf': 'sdl/ttf.py', | |
'sdl_ttf': 'sdl/ttf.py', | |
} | |
sdl = env.Command('sdl/__init__.py', | |
Glob("builder/*.py") + Glob("_sdl/*.py") + Glob("_sdl/*.h"), | |
get_build_command("sdl")) | |
for part in ('image', 'mixer', 'ttf'): | |
env.Command(parts_targets[part], | |
sdl + Glob("builder/*.py") + Glob("_sdl_%s/*.py" % part) + Glob("_sdl_%s/*.h" % part), | |
get_build_command(part)) | |
from distutils import dist | |
from distutils.command.build_ext import build_ext | |
from _sdl.cdefs import _extension_args | |
modules = [] | |
for part in ('sdl', 'sdl_image', 'sdl_mixer', 'sdl_ttf'): | |
# XXX currently this also compiles the extension | |
env.Command('__%s.c' % part, | |
parts_targets[part], | |
sys.executable + " -m _%s.cdefs" % part) | |
ext = build_ext(dist.Distribution(dict(name='__%s' % part))) | |
FRAMEWORKS = [] | |
LIBS = [] | |
if sys.platform == 'darwin': | |
FRAMEWORKS = Split("SDL2 SDL2_image SDL2_mixer SDL2_ttf") # OSX | |
else: | |
LIBS = _extension_args(part.rsplit('_')[-1])['libraries'] | |
modules.append(env.LoadableModule( | |
ext.get_ext_filename('__%s' % part), | |
['__%s.c' % part], | |
LIBPREFIX = '', | |
FRAMEWORKS = FRAMEWORKS, | |
LIBS = LIBS | |
)) | |
# noop pythonbuilder? | |
package = env.Package( | |
NAME=env['PACKAGE_NAME'], | |
VERSION=env['PACKAGE_VERSION'], | |
PACKAGETYPE='src_zip', | |
LICENSE='gpl', | |
source=FindSourceFiles() + [pkg_info] | |
) | |
def wheelmeta_builder(target, source, env): | |
with open(target[0].get_path(), 'w') as f: | |
f.write("""Wheel-Version: 1.0 | |
Generator: SConstruct (0.0.1) | |
Root-Is-Purelib: false | |
Tag: cp27-none-linux_x86_64.whl | |
""") | |
env.Command('WHEEL', 'pyproject.toml', wheelmeta_builder) | |
env['WHEEL_PATH'] = 'build/wheel' | |
# avoid escaping problems with variable name followed by . : | |
env['WHEEL_DATA'] = '$WHEEL_PATH/$PACKAGE_NAME_SAFE-' + env['PACKAGE_VERSION'] + '.data' | |
env['DIST_INFO'] = '$WHEEL_PATH/$PACKAGE_NAME_SAFE-' + env['PACKAGE_VERSION'] + '.dist-info' | |
env.InstallAs('$DIST_INFO/METADATA', 'METADATA') | |
env.InstallAs('$DIST_INFO/WHEEL', 'WHEEL') | |
for module in modules: | |
# assume there's only one file per module... | |
env.InstallAs('$WHEEL_PATH/' + module[0].get_path(), [module]) | |
py_source = Glob('_sdl*/*.py') + Glob('sdl/*.py') | |
py_dest = ['$WHEEL_PATH/' + s.get_path() for s in py_source] | |
env.InstallAs(py_dest, py_source) | |
whl = env.Zip(target = '$PACKAGE_NAME_SAFE-' + env['PACKAGE_VERSION'] + '-cp27-none-linux_x86_64.whl', | |
source = 'build/wheel/', ZIPROOT='build/wheel/') | |
import base64 | |
def urlsafe_b64encode(data): | |
"""urlsafe_b64encode without padding""" | |
return base64.urlsafe_b64encode(data).rstrip(b'=') | |
def add_manifest(target, source, env): | |
""" | |
Add the wheel manifest. | |
""" | |
# os.path.relpath | |
import hashlib | |
import zipfile | |
archive = zipfile.ZipFile(source[0].get_path(), 'a') | |
lines = [] | |
for f in archive.namelist(): | |
print("File: %s" % f) | |
data = archive.read(f) | |
size = len(data) | |
digest = hashlib.sha256(data).digest() | |
digest = "sha256="+(urlsafe_b64encode(digest).decode('ascii')) | |
lines.append("%s,%s,%s" % (f.replace(',', ',,'), digest, size)) | |
record_path = '%s-%s.dist-info/RECORD' % (env['PACKAGE_NAME_SAFE'], env['PACKAGE_VERSION']) | |
lines.append(record_path+',,') | |
RECORD = '\n'.join(lines) | |
archive.writestr(record_path, RECORD) | |
env.Command('dummy', whl, add_manifest) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment