plugin.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. # Licensed under a 3-clause BSD style license - see LICENSE.rst
  2. """
  3. This plugin provides command-line options for controlling whether and how tests
  4. make use of online data.
  5. """
  6. import pytest
  7. from .disable_internet import turn_off_internet, turn_on_internet
  8. from distutils.version import LooseVersion
  9. def pytest_addoption(parser):
  10. # The following means that if --remote-data is not specified, the default
  11. # is 'none', but if it is specified without arguments (--remote-data), it
  12. # defaults to '--remote-data=any'.
  13. parser.addoption(
  14. "--remote-data", nargs="?", const='any', default='none',
  15. help="run tests with online data")
  16. parser.addini(
  17. 'remote_data_strict',
  18. "If 'True', tests will fail if they attempt to access the internet "
  19. "but are not explicitly marked with 'remote_data'",
  20. type="bool", default=False)
  21. def pytest_configure(config):
  22. config.getini('markers').append(
  23. 'remote_data: Apply to tests that require data from remote servers')
  24. config.getini('markers').append(
  25. 'internet_off: Apply to tests that should only run when '
  26. 'network access is deactivated')
  27. strict_check = bool(config.getini('remote_data_strict'))
  28. remote_data = config.getoption('remote_data')
  29. if remote_data not in ['astropy', 'any', 'github', 'none']:
  30. raise pytest.UsageError(
  31. "'{}' is not a valid source for remote data".format(remote_data))
  32. # Monkeypatch to deny access to remote resources unless explicitly told
  33. # otherwise
  34. if strict_check:
  35. if remote_data == 'github': # GitHub only
  36. turn_off_internet(
  37. verbose=config.option.verbose, allow_github_data=True)
  38. elif remote_data != 'any': # Astropy + GitHub or nothing
  39. turn_off_internet(
  40. verbose=config.option.verbose,
  41. allow_astropy_data=(remote_data == 'astropy'))
  42. def pytest_unconfigure():
  43. """
  44. Cleanup post-testing
  45. """
  46. # restore internet connectivity (only lost if remote_data=False and
  47. # turn_off_internet previously called)
  48. # this is harmless / does nothing if socket connections were never disabled
  49. turn_on_internet()
  50. def pytest_runtest_setup(item):
  51. if LooseVersion(pytest.__version__) < LooseVersion("3.6"):
  52. remote_data = item.get_marker('remote_data')
  53. internet_off = item.get_marker('internet_off')
  54. else:
  55. remote_data = item.get_closest_marker('remote_data')
  56. internet_off = item.get_closest_marker('internet_off')
  57. remote_data_config = item.config.getvalue("remote_data")
  58. if remote_data is not None and internet_off is not None:
  59. raise ValueError("remote_data and internet_off are not compatible")
  60. if remote_data is not None:
  61. if len(remote_data.args) > 0:
  62. source = remote_data.args[0]
  63. else:
  64. source = remote_data.kwargs.get('source', 'any')
  65. if source not in ('astropy', 'any', 'github'):
  66. raise ValueError("source should be 'astropy', 'any', or 'github'")
  67. if remote_data_config == 'none':
  68. pytest.skip("need --remote-data option to run")
  69. elif remote_data_config == 'github':
  70. if source in ('any', 'astropy'):
  71. pytest.skip("need --remote-data or "
  72. "--remote-data=astropy option to run")
  73. elif remote_data_config == 'astropy':
  74. # When --remote-data=astropy is given, skip tests simply
  75. # marked as --remote-data
  76. if source == 'any':
  77. pytest.skip("need --remote-data option to run")
  78. if internet_off is not None:
  79. if remote_data_config != 'none':
  80. pytest.skip("run this test only when network access is disabled")