91 lines
2.7 KiB
Python
91 lines
2.7 KiB
Python
|
import ast
|
||
|
import json
|
||
|
import textwrap
|
||
|
from pathlib import Path
|
||
|
|
||
|
|
||
|
def iter_namespace_pkgs(namespace):
|
||
|
parts = namespace.split(".")
|
||
|
for i in range(len(parts)):
|
||
|
yield ".".join(parts[: i + 1])
|
||
|
|
||
|
|
||
|
def build_namespace_package(tmpdir, name, version="1.0", impl="pkg_resources"):
|
||
|
src_dir = tmpdir / name
|
||
|
src_dir.mkdir()
|
||
|
setup_py = src_dir / 'setup.py'
|
||
|
namespace, _, rest = name.rpartition('.')
|
||
|
namespaces = list(iter_namespace_pkgs(namespace))
|
||
|
setup_args = {
|
||
|
"name": name,
|
||
|
"version": version,
|
||
|
"packages": namespaces,
|
||
|
}
|
||
|
|
||
|
if impl == "pkg_resources":
|
||
|
tmpl = '__import__("pkg_resources").declare_namespace(__name__)'
|
||
|
setup_args["namespace_packages"] = namespaces
|
||
|
elif impl == "pkgutil":
|
||
|
tmpl = '__path__ = __import__("pkgutil").extend_path(__path__, __name__)'
|
||
|
else:
|
||
|
raise ValueError(f"Cannot recognise {impl=} when creating namespaces")
|
||
|
|
||
|
args = json.dumps(setup_args, indent=4)
|
||
|
assert ast.literal_eval(args) # ensure it is valid Python
|
||
|
|
||
|
script = textwrap.dedent(
|
||
|
"""\
|
||
|
import setuptools
|
||
|
args = {args}
|
||
|
setuptools.setup(**args)
|
||
|
"""
|
||
|
).format(args=args)
|
||
|
setup_py.write_text(script, encoding='utf-8')
|
||
|
|
||
|
ns_pkg_dir = Path(src_dir, namespace.replace(".", "/"))
|
||
|
ns_pkg_dir.mkdir(parents=True)
|
||
|
|
||
|
for ns in namespaces:
|
||
|
pkg_init = src_dir / ns.replace(".", "/") / '__init__.py'
|
||
|
pkg_init.write_text(tmpl, encoding='utf-8')
|
||
|
|
||
|
pkg_mod = ns_pkg_dir / (rest + '.py')
|
||
|
some_functionality = 'name = {rest!r}'.format(**locals())
|
||
|
pkg_mod.write_text(some_functionality, encoding='utf-8')
|
||
|
return src_dir
|
||
|
|
||
|
|
||
|
def build_pep420_namespace_package(tmpdir, name):
|
||
|
src_dir = tmpdir / name
|
||
|
src_dir.mkdir()
|
||
|
pyproject = src_dir / "pyproject.toml"
|
||
|
namespace, _, rest = name.rpartition(".")
|
||
|
script = f"""\
|
||
|
[build-system]
|
||
|
requires = ["setuptools"]
|
||
|
build-backend = "setuptools.build_meta"
|
||
|
|
||
|
[project]
|
||
|
name = "{name}"
|
||
|
version = "3.14159"
|
||
|
"""
|
||
|
pyproject.write_text(textwrap.dedent(script), encoding='utf-8')
|
||
|
ns_pkg_dir = Path(src_dir, namespace.replace(".", "/"))
|
||
|
ns_pkg_dir.mkdir(parents=True)
|
||
|
pkg_mod = ns_pkg_dir / (rest + ".py")
|
||
|
some_functionality = f"name = {rest!r}"
|
||
|
pkg_mod.write_text(some_functionality, encoding='utf-8')
|
||
|
return src_dir
|
||
|
|
||
|
|
||
|
def make_site_dir(target):
|
||
|
"""
|
||
|
Add a sitecustomize.py module in target to cause
|
||
|
target to be added to site dirs such that .pth files
|
||
|
are processed there.
|
||
|
"""
|
||
|
sc = target / 'sitecustomize.py'
|
||
|
target_str = str(target)
|
||
|
tmpl = '__import__("site").addsitedir({target_str!r})'
|
||
|
sc.write_text(tmpl.format(**locals()), encoding='utf-8')
|