meta.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. """Build metadata for a project using PEP 517 hooks.
  2. """
  3. import argparse
  4. import logging
  5. import os
  6. import shutil
  7. import functools
  8. try:
  9. import importlib.metadata as imp_meta
  10. except ImportError:
  11. import importlib_metadata as imp_meta
  12. try:
  13. from zipfile import Path
  14. except ImportError:
  15. from zipp import Path
  16. from .envbuild import BuildEnvironment
  17. from .wrappers import Pep517HookCaller, quiet_subprocess_runner
  18. from .dirtools import tempdir, mkdir_p, dir_to_zipfile
  19. from .build import validate_system, load_system, compat_system
  20. log = logging.getLogger(__name__)
  21. def _prep_meta(hooks, env, dest):
  22. reqs = hooks.get_requires_for_build_wheel({})
  23. log.info('Got build requires: %s', reqs)
  24. env.pip_install(reqs)
  25. log.info('Installed dynamic build dependencies')
  26. with tempdir() as td:
  27. log.info('Trying to build metadata in %s', td)
  28. filename = hooks.prepare_metadata_for_build_wheel(td, {})
  29. source = os.path.join(td, filename)
  30. shutil.move(source, os.path.join(dest, os.path.basename(filename)))
  31. def build(source_dir='.', dest=None, system=None):
  32. system = system or load_system(source_dir)
  33. dest = os.path.join(source_dir, dest or 'dist')
  34. mkdir_p(dest)
  35. validate_system(system)
  36. hooks = Pep517HookCaller(
  37. source_dir, system['build-backend'], system.get('backend-path')
  38. )
  39. with hooks.subprocess_runner(quiet_subprocess_runner):
  40. with BuildEnvironment() as env:
  41. env.pip_install(system['requires'])
  42. _prep_meta(hooks, env, dest)
  43. def build_as_zip(builder=build):
  44. with tempdir() as out_dir:
  45. builder(dest=out_dir)
  46. return dir_to_zipfile(out_dir)
  47. def load(root):
  48. """
  49. Given a source directory (root) of a package,
  50. return an importlib.metadata.Distribution object
  51. with metadata build from that package.
  52. """
  53. root = os.path.expanduser(root)
  54. system = compat_system(root)
  55. builder = functools.partial(build, source_dir=root, system=system)
  56. path = Path(build_as_zip(builder))
  57. return imp_meta.PathDistribution(path)
  58. parser = argparse.ArgumentParser()
  59. parser.add_argument(
  60. 'source_dir',
  61. help="A directory containing pyproject.toml",
  62. )
  63. parser.add_argument(
  64. '--out-dir', '-o',
  65. help="Destination in which to save the builds relative to source dir",
  66. )
  67. def main():
  68. args = parser.parse_args()
  69. build(args.source_dir, args.out_dir)
  70. if __name__ == '__main__':
  71. main()