Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wrappers.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. from contextlib import contextmanager
  2. import os
  3. from os.path import dirname, abspath, join as pjoin
  4. import shutil
  5. from subprocess import check_call
  6. import sys
  7. from tempfile import mkdtemp
  8. from . import compat
  9. _in_proc_script = pjoin(dirname(abspath(__file__)), '_in_process.py')
  10. @contextmanager
  11. def tempdir():
  12. td = mkdtemp()
  13. try:
  14. yield td
  15. finally:
  16. shutil.rmtree(td)
  17. class UnsupportedOperation(Exception):
  18. """May be raised by build_sdist if the backend indicates that it can't."""
  19. class Pep517HookCaller(object):
  20. """A wrapper around a source directory to be built with a PEP 517 backend.
  21. source_dir : The path to the source directory, containing pyproject.toml.
  22. backend : The build backend spec, as per PEP 517, from pyproject.toml.
  23. """
  24. def __init__(self, source_dir, build_backend):
  25. self.source_dir = abspath(source_dir)
  26. self.build_backend = build_backend
  27. def get_requires_for_build_wheel(self, config_settings=None):
  28. """Identify packages required for building a wheel
  29. Returns a list of dependency specifications, e.g.:
  30. ["wheel >= 0.25", "setuptools"]
  31. This does not include requirements specified in pyproject.toml.
  32. It returns the result of calling the equivalently named hook in a
  33. subprocess.
  34. """
  35. return self._call_hook('get_requires_for_build_wheel', {
  36. 'config_settings': config_settings
  37. })
  38. def prepare_metadata_for_build_wheel(self, metadata_directory, config_settings=None):
  39. """Prepare a *.dist-info folder with metadata for this project.
  40. Returns the name of the newly created folder.
  41. If the build backend defines a hook with this name, it will be called
  42. in a subprocess. If not, the backend will be asked to build a wheel,
  43. and the dist-info extracted from that.
  44. """
  45. return self._call_hook('prepare_metadata_for_build_wheel', {
  46. 'metadata_directory': abspath(metadata_directory),
  47. 'config_settings': config_settings,
  48. })
  49. def build_wheel(self, wheel_directory, config_settings=None, metadata_directory=None):
  50. """Build a wheel from this project.
  51. Returns the name of the newly created file.
  52. In general, this will call the 'build_wheel' hook in the backend.
  53. However, if that was previously called by
  54. 'prepare_metadata_for_build_wheel', and the same metadata_directory is
  55. used, the previously built wheel will be copied to wheel_directory.
  56. """
  57. if metadata_directory is not None:
  58. metadata_directory = abspath(metadata_directory)
  59. return self._call_hook('build_wheel', {
  60. 'wheel_directory': abspath(wheel_directory),
  61. 'config_settings': config_settings,
  62. 'metadata_directory': metadata_directory,
  63. })
  64. def get_requires_for_build_sdist(self, config_settings=None):
  65. """Identify packages required for building a wheel
  66. Returns a list of dependency specifications, e.g.:
  67. ["setuptools >= 26"]
  68. This does not include requirements specified in pyproject.toml.
  69. It returns the result of calling the equivalently named hook in a
  70. subprocess.
  71. """
  72. return self._call_hook('get_requires_for_build_sdist', {
  73. 'config_settings': config_settings
  74. })
  75. def build_sdist(self, sdist_directory, config_settings=None):
  76. """Build an sdist from this project.
  77. Returns the name of the newly created file.
  78. This calls the 'build_sdist' backend hook in a subprocess.
  79. """
  80. return self._call_hook('build_sdist', {
  81. 'sdist_directory': abspath(sdist_directory),
  82. 'config_settings': config_settings,
  83. })
  84. def _call_hook(self, hook_name, kwargs):
  85. env = os.environ.copy()
  86. # On Python 2, pytoml returns Unicode values (which is correct) but the
  87. # environment passed to check_call needs to contain string values. We
  88. # convert here by encoding using ASCII (the backend can only contain
  89. # letters, digits and _, . and : characters, and will be used as a
  90. # Python identifier, so non-ASCII content is wrong on Python 2 in
  91. # any case).
  92. if sys.version_info[0] == 2:
  93. build_backend = self.build_backend.encode('ASCII')
  94. else:
  95. build_backend = self.build_backend
  96. env['PEP517_BUILD_BACKEND'] = build_backend
  97. with tempdir() as td:
  98. compat.write_json({'kwargs': kwargs}, pjoin(td, 'input.json'),
  99. indent=2)
  100. # Run the hook in a subprocess
  101. check_call([sys.executable, _in_proc_script, hook_name, td],
  102. cwd=self.source_dir, env=env)
  103. data = compat.read_json(pjoin(td, 'output.json'))
  104. if data.get('unsupported'):
  105. raise UnsupportedOperation
  106. return data['return_val']