pytest_remotedata-0.4.3/.mailmap0000644000000000000000000000134613615410400013620 0ustar00Adam Ginsburg Brigitta Sipőcz Brigitta Sipőcz Dan D'Avella Dan D'Avella E. Madison Bray E. Madison Bray Kirill Tchernyshyov Matt Davis Matteo Bachetti Pey Lian Lim <2090236+pllim@users.noreply.github.com> Pratik Patel Simon Conseil pytest_remotedata-0.4.3/CHANGES.rst0000644000000000000000000000503713615410400014002 0ustar000.4.3 (2026-10-27) ================== - The ``--remote-data`` option now sets its ``dest`` explicitly so that it can share it with a short option defined by another plugin (e.g., ``-R`` in ``pytest-astropy``) with the development version of pytest. [#102] - The socket blocker no longer calls ``socket.getfqdn()`` on every intercepted connection. This could take tens of seconds per call on some systems (e.g. macOS CI runners). Connections to the machine's own hostname or fully qualified domain name are now detected by checking whether the resolved address is local. The addresses of the allowed data hosts are also now only resolved once per process. [#106] - Versions of Python <3.11 and pytest <7.2 are no longer supported. [#106] - The package is now built with ``hatchling`` and all packaging metadata lives in ``pyproject.toml``. [#106] - Fixed a ``TypeError`` in the socket blocker when ``socket.socket`` has been replaced (e.g. by a mock) in the test being run. 0.4.2 (2026-08-03) ================== - Versions of Python <3.9 are no longer supported. [#81, #93] 0.4.1 (2023-09-25) ================== - Reverting the short option of ``-R`` due to a clash with ``pytest-leaks``. The short option is added to ``pytest-astropy`` instead. [#70] 0.4.0 (2022-12-11) ================== - ``-R`` is added as a short version for the command-line option ``--remote-data``. [#62] - Versions of Python <3.7 are no longer supported. [#65] 0.3.3 (2021-12-21) ================== - Various infrastructure and packaging updates. If you have trouble installing an older version, try upgrading to this one. 0.3.2 (2019-07-20) ================== - Fixed compatibility with pytest 4.2 and later. [#38, #40] 0.3.1 (2018-10-23) ================== - Fix warnings that occur with pytest 3.7 and later. [#34] 0.3.0 (2018-05-29) ================== - Allow ``remote_data`` argument to be passed without ``source`` keyword. [#27] - Add ``source='github'`` option. Also fix IP lookup error for ``source='astropy'`` option. [#28] 0.2.1 (2018-04-20) ================== - Fix packaging error: tests are no longer included in package distribution. [#24] 0.2.0 (2017-11-10) ================== - Do not accept invalid values passed to ``--remote-data`` argument. [#15] - Update list of valid hosts URLs recognized as astropy data sources. [#13] - Remove test dependency on astropy core. [#14] - Allow strict remote data checking to be configurable. This introduces a dependency on ``pytest>=3.1``. [#18] 0.1 (2017-10-10) ================ - Alpha release. pytest_remotedata-0.4.3/tox.ini0000644000000000000000000000165713615410400013517 0ustar00[tox] envlist = py{311,312,313,314}-test{,-devdeps} codestyle isolated_build = true [testenv] changedir = .tmp/{envname} description = run tests deps = pytestoldest: pytest==7.2.0 pytest72: pytest==7.2.* pytest73: pytest==7.3.* pytest74: pytest==7.4.* pytest81: pytest==8.1.* pytest82: pytest==8.2.* pytest83: pytest==8.3.* pytestdev: git+https://github.com/pytest-dev/pytest#egg=pytest commands = pip freeze pytest {toxinidir}/tests {posargs} pytest {toxinidir}/tests --remote-data {posargs} pytest {toxinidir}/tests --remote-data=none {posargs} pytest {toxinidir}/tests --remote-data=github {posargs} pytest {toxinidir}/tests --remote-data=astropy {posargs} pytest {toxinidir}/tests --remote-data=any {posargs} [testenv:codestyle] changedir = skip_install = true description = check code style, e.g. with flake8 deps = flake8 commands = flake8 pytest_remotedata --count pytest_remotedata-0.4.3/.github/dependabot.yml0000644000000000000000000000043113615410400016361 0ustar00version: 2 updates: - package-ecosystem: "github-actions" directory: ".github/workflows" schedule: interval: "monthly" groups: actions: patterns: - "*" labels: - "no-changelog-entry-needed" cooldown: default-days: 14 pytest_remotedata-0.4.3/.github/workflows/publish.yml0000644000000000000000000000362513615410400017767 0ustar00name: Release on: pull_request: # We also want this workflow triggered if the 'Build wheels' label is added # or present when PR is updated types: - synchronize - labeled push: tags: - '*' jobs: build: name: Build and test Python 🐍 distributions 📦 runs-on: ubuntu-latest if: ((github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) || contains(github.event.pull_request.labels.*.name, 'Build wheels')) steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0 with: python-version: '3.11' - name: Install python-build and twine run: python -m pip install pip build "twine>=3.3" -U - name: Build package run: python -m build --sdist --wheel . - name: List result run: ls -l dist - name: Check long_description run: python -m twine check --strict dist/* - name: Test package run: | cd .. python -m venv testenv testenv/bin/pip install pytest pytest-remotedata/dist/*.whl testenv/bin/pytest pytest-remotedata/tests --remote-data - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: dist path: dist/* publish: name: Publish Python 🐍 distributions 📦 to PyPI needs: build runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags') environment: name: pypi url: https://pypi.org/p/pytest-remotedata permissions: id-token: write # for trusted publishing steps: - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: dist path: dist - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3 pytest_remotedata-0.4.3/.github/workflows/python-tests.yml0000644000000000000000000000341113615410400020773 0ustar00name: Run unit tests on: pull_request: push: branches: [ main ] tags: workflow_dispatch: schedule: # Run every Tuesday at 03:53 UTC - cron: 53 3 * * 2 jobs: tests: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - os: ubuntu-latest python-version: '3.11' toxenv: py311-test-pytestoldest - os: macos-latest python-version: '3.11' toxenv: py311-test-pytest72 - os: ubuntu-latest python-version: '3.11' toxenv: py311-test-pytest73 - os: windows-latest python-version: '3.11' toxenv: py311-test-pytest74 - os: ubuntu-latest python-version: '3.12' toxenv: py312-test-pytest81 - os: ubuntu-latest python-version: '3.12' toxenv: py312-test-pytest82 - os: ubuntu-latest python-version: '3.13' toxenv: py313-test-pytest83 - os: macos-latest python-version: '3.14' toxenv: py314-test-pytestdev - os: windows-latest python-version: '3.14' toxenv: py314-test-pytestdev - os: ubuntu-latest python-version: '3.14' toxenv: py314-test-pytestdev steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0 with: python-version: ${{ matrix.python-version }} - name: Install Tox run: python -m pip install tox - name: Run Tox run: tox -v -e ${{ matrix.toxenv }} pytest_remotedata-0.4.3/pytest_remotedata/__init__.py0000644000000000000000000000016513615410400020043 0ustar00# Licensed under a 3-clause BSD style license - see LICENSE.rst from .version import version as __version__ # noqa pytest_remotedata-0.4.3/pytest_remotedata/disable_internet.py0000644000000000000000000001631413615410400021622 0ustar00# Licensed under a 3-clause BSD style license - see LICENSE.rst import contextlib import functools import socket import urllib.request # save original socket method for restoration # These are global so that re-calling the turn_off_internet function doesn't # overwrite them again socket_original = socket.socket socket_create_connection = socket.create_connection socket_bind = socket.socket.bind socket_connect = socket.socket.connect GITHUB_HOSTS = ['www.github.io'] ASTROPY_HOSTS = (['data.astropy.org', 'astropy.stsci.edu', 'www.astropy.org'] + GITHUB_HOSTS) INTERNET_OFF = False # urllib2 uses a global variable to cache its default "opener" for opening # connections for various protocols; we store it off here so we can restore to # the default after re-enabling internet use _orig_opener = None @functools.lru_cache def _resolve_host_ips(hostname, port=80): """ Obtain all the IPs, including aliases, in a way that supports IPv4/v6 dual stack. """ try: ips = {s[-1][0] for s in socket.getaddrinfo(hostname, port)} except socket.gaierror: ips = set() ips.add(hostname) return ips def _is_local_address(addrinfos): """ Return `True` if any of the addresses in ``addrinfos`` (as returned by `socket.getaddrinfo`) is owned by this machine, e.g. because the host is the machine's own hostname or fully qualified domain name. This is determined by trying to bind to each address, which only succeeds for local interfaces. Unlike `socket.getfqdn`, this does not require a reverse DNS lookup, which can take tens of seconds on some systems (e.g. macOS CI runners). """ for family, _, _, _, sockaddr in addrinfos: try: with socket_original(family, socket.SOCK_STREAM) as sock: socket_bind(sock, (sockaddr[0], 0) + sockaddr[2:]) return True except OSError: continue return False # ::1 is apparently another valid name for localhost? # it is returned by getaddrinfo when that function is given localhost def check_internet_off(original_function, allow_astropy_data=False, allow_github_data=False): """ Wraps ``original_function``, which in most cases is assumed to be a `socket.socket` method, to raise an `IOError` for any operations on non-local AF_INET sockets. Allowing Astropy data also automatically allow GitHub data. """ def new_function(*args, **kwargs): # Check against the saved class rather than socket.socket, which # may have been replaced (e.g. by a mock) in the calling test if isinstance(args[0], socket_original): if not args[0].family in (socket.AF_INET, socket.AF_INET6): # Should be fine in all but some very obscure cases # More to the point, we don't want to affect AF_UNIX # sockets. return original_function(*args, **kwargs) host = args[1][0] addr_arg = 1 valid_hosts = {'localhost', '127.0.0.1', '::1'} else: # The only other function this is used to wrap currently is # socket.create_connection, which should be passed a 2-tuple, but # we'll check just in case if not (isinstance(args[0], tuple) and len(args[0]) == 2): return original_function(*args, **kwargs) host = args[0][0] addr_arg = 0 valid_hosts = {'localhost', '127.0.0.1'} # Astropy + GitHub data if allow_astropy_data: for valid_host in ASTROPY_HOSTS: valid_hosts = valid_hosts.union(_resolve_host_ips(valid_host)) # Only GitHub data elif allow_github_data: for valid_host in GITHUB_HOSTS: valid_hosts = valid_hosts.union(_resolve_host_ips(valid_host)) if host in valid_hosts: return original_function(*args, **kwargs) port = args[addr_arg][1] if host == socket.gethostname(): new_addr = ('localhost', port) args = args[:addr_arg] + (new_addr,) + args[addr_arg + 1:] return original_function(*args, **kwargs) try: addrinfos = socket.getaddrinfo(host, port, type=socket.SOCK_STREAM) except socket.gaierror: addrinfos = [] host_ips = {info[-1][0] for info in addrinfos} if host_ips & valid_hosts or _is_local_address(addrinfos): return original_function(*args, **kwargs) raise OSError("An attempt was made to connect to the internet " "by a test that was not marked `remote_data`. The " "requested host was: {}".format(host)) return new_function def turn_off_internet(verbose=False, allow_astropy_data=False, allow_github_data=False): """ Disable internet access via python by preventing connections from being created using the socket module. Presumably this could be worked around by using some other means of accessing the internet, but all default python modules (urllib, requests, etc.) use socket [citation needed]. """ global INTERNET_OFF global _orig_opener if INTERNET_OFF: return INTERNET_OFF = True __tracebackhide__ = True if verbose: print("Internet access disabled") # Update urllib2 to force it not to use any proxies # Must use {} here (the default of None will kick off an automatic search # for proxies) _orig_opener = urllib.request.build_opener() no_proxy_handler = urllib.request.ProxyHandler({}) opener = urllib.request.build_opener(no_proxy_handler) urllib.request.install_opener(opener) socket.create_connection = check_internet_off( socket_create_connection, allow_astropy_data=allow_astropy_data, allow_github_data=allow_github_data) socket.socket.bind = check_internet_off( socket_bind, allow_astropy_data=allow_astropy_data, allow_github_data=allow_github_data) socket.socket.connect = check_internet_off( socket_connect, allow_astropy_data=allow_astropy_data, allow_github_data=allow_github_data) return socket def turn_on_internet(verbose=False): """ Restore internet access. Not used, but kept in case it is needed. """ global INTERNET_OFF global _orig_opener if not INTERNET_OFF: return INTERNET_OFF = False if verbose: print("Internet access enabled") urllib.request.install_opener(_orig_opener) socket.create_connection = socket_create_connection socket.socket.bind = socket_bind socket.socket.connect = socket_connect return socket @contextlib.contextmanager def no_internet(verbose=False): """Context manager to temporarily disable internet access (if not already disabled). If it was already disabled before entering the context manager (i.e. `turn_off_internet` was called previously) then this is a no-op and leaves internet access disabled until a manual call to `turn_on_internet`. """ already_disabled = INTERNET_OFF turn_off_internet(verbose=verbose) try: yield finally: if not already_disabled: turn_on_internet(verbose=verbose) pytest_remotedata-0.4.3/pytest_remotedata/plugin.py0000644000000000000000000000661013615410400017603 0ustar00# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This plugin provides command-line options for controlling whether and how tests make use of online data. """ import pytest from .disable_internet import turn_off_internet, turn_on_internet def pytest_addoption(parser): # The following means that if --remote-data is not specified, the default # is 'none', but if it is specified without arguments (--remote-data), it # defaults to '--remote-data=any'. parser.addoption( "--remote-data", nargs="?", const='any', default='none', dest="remote_data", help="run tests with online data", choices=['astropy', 'any', 'github', 'none']) parser.addini( 'remote_data_strict', "If 'True', tests will fail if they attempt to access the internet " "but are not explicitly marked with 'remote_data'", type="bool", default=False) def pytest_configure(config): config.getini('markers').append( 'remote_data: Apply to tests that require data from remote servers') config.getini('markers').append( 'internet_off: Apply to tests that should only run when ' 'network access is deactivated') strict_check = bool(config.getini('remote_data_strict')) remote_data = config.getoption('remote_data') # Monkeypatch to deny access to remote resources unless explicitly told # otherwise if strict_check: if remote_data == 'github': # GitHub only turn_off_internet( verbose=config.option.verbose, allow_github_data=True) elif remote_data != 'any': # Astropy + GitHub or nothing turn_off_internet( verbose=config.option.verbose, allow_astropy_data=(remote_data == 'astropy')) def pytest_unconfigure(): """ Cleanup post-testing """ # restore internet connectivity (only lost if remote_data=False and # turn_off_internet previously called) # this is harmless / does nothing if socket connections were never disabled turn_on_internet() def pytest_runtest_setup(item): remote_data = item.get_closest_marker('remote_data') internet_off = item.get_closest_marker('internet_off') remote_data_config = item.config.getvalue("remote_data") if remote_data is not None and internet_off is not None: raise ValueError("remote_data and internet_off are not compatible") if remote_data is not None: if len(remote_data.args) > 0: source = remote_data.args[0] else: source = remote_data.kwargs.get('source', 'any') if source not in ('astropy', 'any', 'github'): raise ValueError("source should be 'astropy', 'any', or 'github'") if remote_data_config == 'none': pytest.skip("need --remote-data option to run") elif remote_data_config == 'github': if source in ('any', 'astropy'): pytest.skip("need --remote-data or " "--remote-data=astropy option to run") elif remote_data_config == 'astropy': # When --remote-data=astropy is given, skip tests simply # marked as --remote-data if source == 'any': pytest.skip("need --remote-data option to run") if internet_off is not None: if remote_data_config != 'none': pytest.skip("run this test only when network access is disabled") pytest_remotedata-0.4.3/pytest_remotedata/version.py0000644000000000000000000000101013615410400017757 0ustar00# file generated by vcs-versioning # don't change, don't track in version control from __future__ import annotations __all__ = [ "__version__", "__version_tuple__", "version", "version_tuple", "__commit_id__", "commit_id", ] version: str __version__: str __version_tuple__: tuple[int | str, ...] version_tuple: tuple[int | str, ...] commit_id: str | None __commit_id__: str | None __version__ = version = '0.4.3' __version_tuple__ = version_tuple = (0, 4, 3) __commit_id__ = commit_id = None pytest_remotedata-0.4.3/tests/__init__.py0000644000000000000000000000000013615410400015434 0ustar00pytest_remotedata-0.4.3/tests/conftest.py0000644000000000000000000000014513615410400015534 0ustar00# This enables the meta-testing of this plugin via the testdir fixture pytest_plugins = ['pytester'] pytest_remotedata-0.4.3/tests/test_skip_remote_data.py0000644000000000000000000001064113615410400020262 0ustar00# Licensed under a 3-clause BSD style license - see LICENSE.rst # this test doesn't actually use any online data, it should just be skipped # by run_tests because it has the remote_data decorator. from contextlib import closing from urllib.error import URLError from urllib.request import urlopen import pytest ASTROPY_DATA_URL = "http://data.astropy.org/" GITHUB_DATA_URL = "http://astropy.github.io/" EXTERNAL_URL = "http://www.google.com" TIMEOUT = 10 def download_file(remote_url): with closing(urlopen(remote_url, timeout=TIMEOUT)) as remote: remote.read() @pytest.mark.remote_data def test_skip_remote_data(pytestconfig): # astropy.test() has remote_data=none or remote_data=astropy but we still # got here somehow, so fail with a helpful message if pytestconfig.getoption('remote_data') == 'none': pytest.fail('@remote_data was not skipped with remote_data=none') elif pytestconfig.getoption('remote_data') == 'astropy': pytest.fail('@remote_data was not skipped with remote_data=astropy') elif pytestconfig.getoption('remote_data') == 'github': pytest.fail('@remote_data was not skipped with remote_data=github') # Test Astropy URL download_file(ASTROPY_DATA_URL + 'galactic_center/gc_2mass_k.fits') # Test GitHub URL download_file(GITHUB_DATA_URL) # Test unrelated URL download_file(EXTERNAL_URL) @pytest.mark.remote_data(source='astropy') def test_skip_remote_data_astropy(pytestconfig): # astropy.test() has remote_data=none but we still got here somehow, # so fail with a helpful message if pytestconfig.getoption('remote_data') in ('none', 'github'): pytest.fail('@remote_data was not skipped with remote_data=none' 'or remote_data=github') # Test Astropy URL download_file(ASTROPY_DATA_URL + 'galactic_center/gc_2mass_k.fits') # Test non-Astropy URL if pytestconfig.getoption('remote_data') == 'astropy': with pytest.raises(Exception) as exc: download_file(EXTERNAL_URL) assert "An attempt was made to connect to the internet" in str(exc.value) # noqa else: # remote_data=any download_file(EXTERNAL_URL) @pytest.mark.remote_data(source='github') def test_skip_remote_data_github(pytestconfig): if pytestconfig.getoption('remote_data') == 'none': pytest.fail('@remote_data was not skipped with remote_data=none') # Test GitHub URL download_file(GITHUB_DATA_URL) # Test non-GitHub URL if pytestconfig.getoption('remote_data') == 'github': with pytest.raises(Exception) as exc: download_file(ASTROPY_DATA_URL) assert "An attempt was made to connect to the internet" in str(exc.value) else: # remote_data=any or remote_data=astropy download_file(ASTROPY_DATA_URL) @pytest.mark.internet_off def test_internet_off_decorator(pytestconfig): # This test should only run when internet access has been disabled if pytestconfig.getoption('remote_data') != 'none': pytest.fail('@internet_off test ran when remote_data!=none') def test_block_internet_connection(pytestconfig): if pytestconfig.getoption('remote_data') == 'none': with pytest.raises(URLError): download_file(EXTERNAL_URL) elif pytestconfig.getoption('remote_data') == 'astropy': with pytest.raises(URLError): download_file(EXTERNAL_URL) elif pytestconfig.getoption('remote_data') == 'github': with pytest.raises(URLError): download_file(EXTERNAL_URL) else: download_file(EXTERNAL_URL) @pytest.mark.internet_off def test_block_internet_connection_internet_off(): with pytest.raises(URLError): download_file(EXTERNAL_URL) def test_shared_option_dest(testdir): # Another plugin (e.g., pytest-astropy with -R) can register an # option that shares the "remote_data" dest and be loaded before # this plugin. testdir.makepyfile(alias_plugin=""" def pytest_addoption(parser): parser.addoption('--online', nargs='?', const='any', default='none', dest='remote_data') """) testdir.makepyfile(""" def test_remote_data_option(pytestconfig): assert pytestconfig.getoption('remote_data') == 'any' """) for option in ('--online', '--remote-data'): result = testdir.runpytest_subprocess('-p', 'alias_plugin', option) result.assert_outcomes(passed=1) pytest_remotedata-0.4.3/tests/test_socketblocker.py0000644000000000000000000000607613615410400017611 0ustar00# Licensed under a 3-clause BSD style license - see LICENSE.rst import socket import time from http.server import HTTPServer, SimpleHTTPRequestHandler from socketserver import TCPServer from threading import Thread from unittest import mock from urllib.request import urlopen import pytest from pytest_remotedata.disable_internet import no_internet, socket_original def test_outgoing_fails(): with pytest.raises(IOError): with no_internet(): urlopen('http://www.python.org') def test_outgoing_fails_with_patched_socket(): # Regression test for the blocker raising TypeError when a test has # replaced socket.socket with something that is not a type sock = socket_original(socket.AF_INET, socket.SOCK_STREAM) with sock, no_internet(), mock.patch('socket.socket'): with pytest.raises(OSError, match='connect to the internet'): sock.connect(('www.python.org', 80)) class StoppableHTTPServer(HTTPServer): def __init__(self, *args): super().__init__(*args) self.stop = False def server_bind(self): # Bypass HTTPServer.server_bind, which calls socket.getfqdn() and # can take tens of seconds on some systems (e.g. macOS CI runners) TCPServer.server_bind(self) self.server_name, self.server_port = self.server_address[:2] def handle_request(self): self.stop = True super().handle_request() def serve_forever(self): """ Serve until stop set, which will happen if any request is handled """ while not self.stop: self.handle_request() @pytest.mark.parametrize(('localhost'), ('localhost', '127.0.0.1', socket.gethostname())) def test_localconnect_succeeds(localhost): """ Ensure that connections to localhost are allowed, since these are genuinely not remotedata. """ with no_internet(): # port "0" means find open port # see http://stackoverflow.com/questions/1365265/on-localhost-how-to-pick-a-free-port-number httpd = StoppableHTTPServer(('localhost', 0), SimpleHTTPRequestHandler) port = httpd.socket.getsockname()[1] server = Thread(target=httpd.serve_forever) server.daemon = True server.start() time.sleep(0.1) urlopen(f'http://{localhost:s}:{port:d}').close() httpd.server_close() # Used for the below test--inline functions aren't pickleable # by multiprocessing? def _square(x): return x ** 2 @pytest.mark.skipif('sys.platform == "win32" or sys.platform.startswith("gnu0")') def test_multiprocessing_forkserver(): """ Test that using multiprocessing with forkserver works. Perhaps a simpler more direct test would be to just open some local sockets and pass something through them. Regression test for https://github.com/astropy/astropy/pull/3713 """ import multiprocessing ctx = multiprocessing.get_context('forkserver') pool = ctx.Pool(1) result = pool.map(_square, [1, 2, 3, 4, 5]) pool.close() pool.join() assert result == [1, 4, 9, 16, 25] pytest_remotedata-0.4.3/tests/test_strict_check.py0000644000000000000000000000331113615410400017411 0ustar00# Licensed under a 3-clause BSD style license - see LICENSE.rst import os import pytest PYFILE_CONTENTS = """ import pytest from urllib.request import urlopen def test_config_setting(pytestconfig): assert pytestconfig.getini('remote_data_strict') == {} {} def test_internet_access(): urlopen('http://astropy.org') """ def _write_config_file(testdir, entry): config = testdir.tmpdir.join('setup.cfg') config.write(""" [tool:pytest] {} """.format(entry)) # Just a sanity check to make sure we actually write the config file assert os.path.exists(str(testdir.tmpdir.join('setup.cfg'))) def test_local_config(pytestconfig): assert pytestconfig.getini('remote_data_strict') is True def test_default_behavior(testdir): _write_config_file(testdir, '') testdir.makepyfile(PYFILE_CONTENTS.format('False', '')) result = testdir.runpytest_subprocess() result.assert_outcomes(passed=2) def test_strict_behavior(testdir): _write_config_file(testdir, 'remote_data_strict = true') testdir.makepyfile(PYFILE_CONTENTS.format('True', '')) result = testdir.runpytest_subprocess() result.assert_outcomes(passed=1, failed=1) @pytest.mark.parametrize('source', ['none', 'any']) def test_strict_with_decorator(testdir, source): _write_config_file(testdir, 'remote_data_strict = true') decorator = '@pytest.mark.remote_data' testdir.makepyfile(PYFILE_CONTENTS.format('True', decorator)) clarg = '--remote-data=' + source result = testdir.runpytest_subprocess(clarg) if source == 'none': outcomes = dict(passed=1, skipped=1) else: outcomes = dict(passed=2) result.assert_outcomes(**outcomes) pytest_remotedata-0.4.3/.gitignore0000644000000000000000000000116013615410400014161 0ustar00# Compiled files *.py[cod] *.a *.o *.so *.pyd __pycache__ # Ignore .c files by default to avoid including generated code. If you want to # add a non-generated .c extension, use `git add -f filename.c`. *.c # Other generated files MANIFEST # Sphinx _build _generated docs/api docs/generated # Packages/installer info *.egg *.egg-info dist build eggs .eggs parts bin var sdist develop-eggs .installed.cfg distribute-*.tar.gz # Other .cache .tox .*.swp .*.swo *~ .project .pydevproject .settings .coverage cover htmlcov .pytest_cache # Mac OSX .DS_Store # PyCharm .idea pytest_remotedata/version.py pip-wheel-metadata/ pytest_remotedata-0.4.3/LICENSE.rst0000644000000000000000000000273013615410400014011 0ustar00Copyright (c) 2011-2017, Astropy Developers All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Astropy Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pytest_remotedata-0.4.3/README.rst0000644000000000000000000001037413615410400013667 0ustar00================= pytest-remotedata ================= .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.5796951.svg :target: https://doi.org/10.5281/zenodo.5796951 :alt: 10.5281/zenodo.5796951 .. image:: https://github.com/astropy/pytest-remotedata/workflows/Run%20unit%20tests/badge.svg :target: https://github.com/astropy/pytest-remotedata/actions :alt: CI Status This package provides a plugin for the `pytest`_ framework that allows developers to control unit tests that require access to data from the internet. It was originally part of the `astropy`_ core package, but has been moved to a separate package in order to be of more general use. .. _pytest: https://pytest.org/en/latest/ .. _astropy: https://astropy.org/ Motivation ---------- Many software packages provide features that require access to data from the internet. These features need to be tested, but unit tests that access the internet can dominate the overall runtime of a test suite. The ``pytest-remotedata`` plugin allows developers to indicate which unit tests require access to the internet, and to control when and whether such tests should execute as part of any given run of the test suite. Installation ------------ The ``pytest-remotedata`` plugin can be installed using ``pip``:: $ pip install pytest-remotedata It is also possible to install the latest development version from the source repository:: $ git clone https://github.com/astropy/pytest-remotedata $ cd pytest-remotedata $ pip install . In either case, the plugin will automatically be registered for use with ``pytest``. Usage ----- Installing this plugin makes two decorators available for use with ``pytest``: * ``remote_data`` for marking tests that require data from the internet * ``internet_off`` for marking tests that should run only when internet access is disabled These decorators can be used to mark test functions, methods, and classes using ``@pytest.mark``. For example, consider the following test function that requires access to data from the internet: .. code-block:: python import pytest from urllib.request import urlopen @pytest.mark.remote_data def test_remote_data(): urlopen('https://astropy.org') Marking the ``test_remote_data`` function with ``@pytest.mark.remote_data`` indicates to ``pytest`` that this test should be run only when access to remote data sources is explicitly requested. When this plugin is installed, the ``--remote-data`` command line option is added to the ``pytest`` command line interface. The default behavior is to skip tests that are marked with ``remote_data``. If the ``--remote-data`` option is not provided to the ``pytest`` command, or if ``--remote-data=none`` is provided, all tests that are marked with ``remote_data`` will be skipped. All tests that are marked with ``internet_off`` will be executed. Sometimes it is useful to check that certain tests do not unexpectedly access the internet. Strict remote data access checking can be enabled by setting ``remote_data_strict = true`` in the tested package's ``setup.cfg`` file. If this option is enabled, any test that attempts to access the network but is not marked with ``@pytest.mark.remote_data`` will fail. Providing either the ``--remote-data`` option, or ``--remote-data=any`` to the ``pytest`` command line interface will cause all tests that are marked with ``remote-data`` to execute. Any tests that are marked with ``internet_off`` will be skipped. Running the tests with ``--remote-data=astropy`` will cause only tests that receive remote data from Astropy data sources to be run. Tests with any other data sources will be skipped. This is indicated in the test code by marking test functions with ``@pytest.mark.remote_data(source='astropy')``. Running only the tests marked as ``remote_data``, use the built-in pytest machinery, e.g., ``pytest -m remote_data --remote-data``. In the future, we intend to support a configurable way to indicate specific remote data sources in addition to ``astropy``. Development Status ------------------ Questions, bug reports, and feature requests can be submitted on `github`_. .. _github: https://github.com/astropy/pytest-remotedata License ------- This plugin is licensed under a 3-clause BSD style license - see the ``LICENSE.rst`` file. pytest_remotedata-0.4.3/pyproject.toml0000644000000000000000000000313613615410400015112 0ustar00[build-system] requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" [project] name = "pytest-remotedata" description = "Pytest plugin for controlling remote data access." readme = "README.rst" license = "BSD-3-Clause" license-files = ["LICENSE.rst"] authors = [ { name = "The Astropy Developers", email = "astropy.team@gmail.com" }, ] keywords = ["remote", "data", "pytest", "py.test"] classifiers = [ "Development Status :: 5 - Production/Stable", "Framework :: Pytest", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development :: Testing", "Topic :: Utilities", ] requires-python = ">=3.11" dependencies = [ "pytest>=7.2", "packaging", ] dynamic = ["version"] [project.urls] Homepage = "https://github.com/astropy/pytest-remotedata" [project.entry-points.pytest11] pytest_remotedata = "pytest_remotedata.plugin" [tool.hatch.version] source = "vcs" [tool.hatch.build.hooks.vcs] version-file = "pytest_remotedata/version.py" [tool.hatch.build.targets.wheel] packages = ["pytest_remotedata"] [tool.pytest.ini_options] minversion = "7.2" testpaths = ["tests"] addopts = "--durations=10" remote_data_strict = true filterwarnings = ["error"] pytest_remotedata-0.4.3/PKG-INFO0000644000000000000000000001256613615410400013302 0ustar00Metadata-Version: 2.5 Name: pytest-remotedata Version: 0.4.3 Summary: Pytest plugin for controlling remote data access. Project-URL: Homepage, https://github.com/astropy/pytest-remotedata Author-email: The Astropy Developers License-Expression: BSD-3-Clause License-File: LICENSE.rst Keywords: data,py.test,pytest,remote Classifier: Development Status :: 5 - Production/Stable Classifier: Framework :: Pytest Classifier: Intended Audience :: Developers Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Programming Language :: Python :: 3.14 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Topic :: Software Development :: Testing Classifier: Topic :: Utilities Requires-Python: >=3.11 Requires-Dist: packaging Requires-Dist: pytest>=7.2 Description-Content-Type: text/x-rst ================= pytest-remotedata ================= .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.5796951.svg :target: https://doi.org/10.5281/zenodo.5796951 :alt: 10.5281/zenodo.5796951 .. image:: https://github.com/astropy/pytest-remotedata/workflows/Run%20unit%20tests/badge.svg :target: https://github.com/astropy/pytest-remotedata/actions :alt: CI Status This package provides a plugin for the `pytest`_ framework that allows developers to control unit tests that require access to data from the internet. It was originally part of the `astropy`_ core package, but has been moved to a separate package in order to be of more general use. .. _pytest: https://pytest.org/en/latest/ .. _astropy: https://astropy.org/ Motivation ---------- Many software packages provide features that require access to data from the internet. These features need to be tested, but unit tests that access the internet can dominate the overall runtime of a test suite. The ``pytest-remotedata`` plugin allows developers to indicate which unit tests require access to the internet, and to control when and whether such tests should execute as part of any given run of the test suite. Installation ------------ The ``pytest-remotedata`` plugin can be installed using ``pip``:: $ pip install pytest-remotedata It is also possible to install the latest development version from the source repository:: $ git clone https://github.com/astropy/pytest-remotedata $ cd pytest-remotedata $ pip install . In either case, the plugin will automatically be registered for use with ``pytest``. Usage ----- Installing this plugin makes two decorators available for use with ``pytest``: * ``remote_data`` for marking tests that require data from the internet * ``internet_off`` for marking tests that should run only when internet access is disabled These decorators can be used to mark test functions, methods, and classes using ``@pytest.mark``. For example, consider the following test function that requires access to data from the internet: .. code-block:: python import pytest from urllib.request import urlopen @pytest.mark.remote_data def test_remote_data(): urlopen('https://astropy.org') Marking the ``test_remote_data`` function with ``@pytest.mark.remote_data`` indicates to ``pytest`` that this test should be run only when access to remote data sources is explicitly requested. When this plugin is installed, the ``--remote-data`` command line option is added to the ``pytest`` command line interface. The default behavior is to skip tests that are marked with ``remote_data``. If the ``--remote-data`` option is not provided to the ``pytest`` command, or if ``--remote-data=none`` is provided, all tests that are marked with ``remote_data`` will be skipped. All tests that are marked with ``internet_off`` will be executed. Sometimes it is useful to check that certain tests do not unexpectedly access the internet. Strict remote data access checking can be enabled by setting ``remote_data_strict = true`` in the tested package's ``setup.cfg`` file. If this option is enabled, any test that attempts to access the network but is not marked with ``@pytest.mark.remote_data`` will fail. Providing either the ``--remote-data`` option, or ``--remote-data=any`` to the ``pytest`` command line interface will cause all tests that are marked with ``remote-data`` to execute. Any tests that are marked with ``internet_off`` will be skipped. Running the tests with ``--remote-data=astropy`` will cause only tests that receive remote data from Astropy data sources to be run. Tests with any other data sources will be skipped. This is indicated in the test code by marking test functions with ``@pytest.mark.remote_data(source='astropy')``. Running only the tests marked as ``remote_data``, use the built-in pytest machinery, e.g., ``pytest -m remote_data --remote-data``. In the future, we intend to support a configurable way to indicate specific remote data sources in addition to ``astropy``. Development Status ------------------ Questions, bug reports, and feature requests can be submitted on `github`_. .. _github: https://github.com/astropy/pytest-remotedata License ------- This plugin is licensed under a 3-clause BSD style license - see the ``LICENSE.rst`` file.