diff --git a/README.rst b/README.rst index eb6810e..d0a43aa 100644 --- a/README.rst +++ b/README.rst @@ -73,11 +73,13 @@ Example enscons projects Right now, the best way to learn how enscons works is by example. -* `rsalette `_ Simple package with just two modules. -* `cryptacular `_ Has a C extension. -* `pysdl2-cffi `_ Generates Python and C source code as part of the build, then compiles the generated source. +* `rsalette `_ Simple package with just two modules. +* `cryptacular `_ Has a C extension. +* `pysdl2-cffi `_ Generates Python and C source code as part of the build, then compiles the generated source. * `hello-pyrust `_ An extension using `Rust `_ and `cffi `_ instead of C. -* `enscons `_ Enscons builds itself. +* `enscons `_ Enscons builds itself. +* `nonstdlib `_ Experimental repackaging of the Python standard library into many wheels. + More about SCons ================ diff --git a/enscons/__init__.py b/enscons/__init__.py index cec9d59..978b61b 100644 --- a/enscons/__init__.py +++ b/enscons/__init__.py @@ -231,6 +231,25 @@ def urlsafe_b64encode(data): return base64.urlsafe_b64encode(data).rstrip(b"=") +def add_editable(target, source, env): + """ + Add the editable stub modules to a zip file. + """ + import zipfile + import editables + import os.path + + src_root = os.path.abspath(env["PACKAGE_METADATA"].get("src_root", "")) + + archive = zipfile.ZipFile( + target[0].get_path(), "a", compression=zipfile.ZIP_DEFLATED + ) + lines = [] + for f, data in editables.build_editable(src_root): + archive.writestr(zipfile.ZipInfo(f, time.gmtime(SOURCE_EPOCH_ZIP)[:6]), data) + archive.close() + + def add_manifest(target, source, env): """ Add the wheel manifest. @@ -320,6 +339,24 @@ def init_wheel(env): targets = wheelmeta + wheel_entry_points + # experimental PEP517-style editable + # with filename that won't collide with our real wheel (SCons wouldn't like that) + editable_filename = ( + "-".join( + (env["PACKAGE_NAME_SAFE"], env["PACKAGE_VERSION"], "ed." + env["WHEEL_TAG"]) + ) + + ".whl" + ) + editable = env.Zip( + target=env.Dir(env["WHEEL_DIR"]).File(editable_filename), + source=env["DIST_INFO_PATH"], + ZIPROOT=env["WHEEL_PATH"], + ) + env.Alias("editable", editable) + env.NoClean(editable) + env.AddPostAction(editable, Action(add_editable)) + env.AddPostAction(editable, Action(add_manifest)) + return targets diff --git a/enscons/api.py b/enscons/api.py index e97d43b..df66537 100644 --- a/enscons/api.py +++ b/enscons/api.py @@ -49,3 +49,11 @@ def build_sdist(sdist_directory, settings): target_name = str(target) if target_name.endswith(".tar.gz"): return os.path.basename(target_name) + + +# experimental PEP517-style editable installation +def build_wheel_for_editable( + wheel_directory, scheme, settings, metadata_directory=None +): + sys.argv[1:] = ["--wheel-dir=" + wheel_directory, "editable"] + return _run("editable") diff --git a/pyproject.toml b/pyproject.toml index b9e0557..6b88bdf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ [build-system] -requires = ["pytoml>=0.1", "scons", "enscons>=0.23"] +requires = ["pytoml>=0.1", "scons", "enscons>=0.23", "editables"] build-backend = "enscons.api" [tool.enscons] name="enscons" -version="0.23.0" +version="0.24.0" packages=["enscons"] -install_requires=["scons>=3.0.5", "pytoml>=0.1", "setuptools", "wheel", "attrs", "packaging"] +install_requires=["scons>=3.0.5", "pytoml>=0.1", "setuptools", "wheel", "attrs", "packaging", "editables"] description="Tools for building Python packages with SCons" description_file="README.rst" license="MIT" @@ -22,6 +22,7 @@ keywords=["packaging", "wheel"] author="Daniel Holth" author_email="dholth@fastmail.fm" url="https://bitbucket.org/dholth/enscons" +src_root="." [tool.enscons.entry_points] console_scripts = ["setup2toml = enscons.setup2toml:main"]