test_wheel.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #!/usr/bin/env python
  2. """
  3. Tests a .whl file by installing it and pytest into a virtual environment and
  4. running the test suite.
  5. Requires pip to be installed, as well as 'virtualenv' on Python 2.
  6. """
  7. import os
  8. import sys
  9. import shutil
  10. import subprocess
  11. import tempfile
  12. from optparse import OptionParser
  13. def test_wheel(wheel, verbose=False, ignores=[]):
  14. envdir = tempfile.mkdtemp(prefix="venv-")
  15. print("Setting up virtual environment in {0}".format(envdir))
  16. sys.stdout.flush()
  17. # Create a virtualenv.
  18. if sys.version_info >= (3, 0):
  19. subprocess.call([sys.executable, "-B", "-m", "venv", "--clear", envdir])
  20. else:
  21. subprocess.call([sys.executable, "-B", "-m", "virtualenv", "--clear", envdir])
  22. # Determine the path to the Python interpreter.
  23. if sys.platform == "win32":
  24. python = os.path.join(envdir, "Scripts", "python.exe")
  25. else:
  26. python = os.path.join(envdir, "bin", "python")
  27. # Upgrade pip inside the environment too.
  28. pip_pkg = "pip"
  29. if sys.version_info[0:2] == (3, 4):
  30. pip_pkg = "pip<19.2"
  31. if subprocess.call([python, "-m", "pip", "install", "-U", pip_pkg]) != 0:
  32. shutil.rmtree(envdir)
  33. sys.exit(1)
  34. # Temp hack to patch issue pypa/pip#6885 in pip 19.2.2 and Python 3.8.
  35. if sys.platform == "win32" and "-cp38-cp38-" in wheel and os.path.isdir(os.path.join(envdir, "Lib", "site-packages", "pip-19.2.2.dist-info")):
  36. pep425tags = os.path.join(envdir, "Lib", "site-packages", "pip", "_internal", "pep425tags.py")
  37. if os.path.isfile(pep425tags):
  38. data = open(pep425tags, "r").read()
  39. data = data.replace(" m = 'm'\n", " m = ''\n")
  40. open(pep425tags, "w").write(data)
  41. # Install pytest into the environment, as well as our wheel.
  42. packages = [wheel]
  43. if sys.version_info >= (3, 10):
  44. packages += ["pytest>=6.2.4"]
  45. else:
  46. packages += ["pytest"]
  47. if sys.version_info[0:2] == (3, 4):
  48. if sys.platform == "win32":
  49. packages += ["colorama==0.4.1"]
  50. # See https://github.com/python-attrs/attrs/pull/807
  51. packages += ["attrs<21"]
  52. if subprocess.call([python, "-m", "pip", "install"] + packages) != 0:
  53. shutil.rmtree(envdir)
  54. sys.exit(1)
  55. # Run the test suite.
  56. test_cmd = [python, "-m", "pytest", "tests"]
  57. if verbose:
  58. test_cmd.append("--verbose")
  59. for ignore in ignores:
  60. test_cmd.append("--ignore")
  61. test_cmd.append(ignore)
  62. # Put the location of the python DLL on the path, for deploy-stub test
  63. # This is needed because venv does not install a copy of the python DLL
  64. env = None
  65. if sys.platform == "win32":
  66. deploy_libs = os.path.join(envdir, "Lib", "site-packages", "deploy_libs")
  67. if os.path.isdir(deploy_libs):
  68. # We have to do this dance because os.environ is case insensitive
  69. env = dict(os.environ)
  70. for key, value in env.items():
  71. if key.upper() == "PATH":
  72. env[key] = deploy_libs + ";" + value
  73. break
  74. else:
  75. env["PATH"] = deploy_libs
  76. exit_code = subprocess.call(test_cmd, env=env)
  77. shutil.rmtree(envdir)
  78. if exit_code != 0:
  79. sys.exit(exit_code)
  80. if __name__ == "__main__":
  81. parser = OptionParser(usage="%prog [options] file...")
  82. parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False)
  83. parser.add_option('', '--ignore', dest = 'ignores', help = 'Ignores given test directory (may be repeated)', action = 'append', default = [])
  84. (options, args) = parser.parse_args()
  85. if not args:
  86. parser.print_usage()
  87. sys.exit(1)
  88. for arg in args:
  89. test_wheel(arg, verbose=options.verbose, ignores=options.ignores)