Skip to content

Replace network decorator with with_connectivity_check #6111

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
1 commit merged into from
Jan 28, 2014
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 28 additions & 109 deletions pandas/util/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -971,106 +971,6 @@ def dec(f):
_network_error_classes = IOError, httplib.HTTPException


@optional_args
def network(t, raise_on_error=_RAISE_NETWORK_ERROR_DEFAULT,
error_classes=_network_error_classes, num_runs=2):
"""
Label a test as requiring network connection and skip test if it encounters a ``URLError``.

In some cases it is not possible to assume network presence (e.g. Debian
build hosts).

You can pass an optional ``raise_on_error`` argument to the decorator, in
which case it will always raise an error even if it's not a subclass of
``error_classes``.

Parameters
----------
t : callable
The test requiring network connectivity.
raise_on_error : bool, optional
If True, never catches errors.
error_classes : tuple, optional
error classes to ignore. If not in ``error_classes``, raises the error.
defaults to URLError. Be careful about changing the error classes here,
it may result in undefined behavior.
num_runs : int, optional
Number of times to run test. If fails on last try, will raise. Default
is 2 runs.

Returns
-------
t : callable
The decorated test `t`.

Examples
--------
A test can be decorated as requiring network like this::

>>> from pandas.util.testing import network
>>> from pandas.io.common import urlopen
>>> import nose
>>> @network
... def test_network():
... with urlopen("rabbit://bonanza.com") as f:
... pass
...
>>> try:
... test_network()
... except nose.SkipTest:
... print("SKIPPING!")
...
SKIPPING!

Alternatively, you can use set ``raise_on_error`` in order to get
the error to bubble up, e.g.::

>>> @network(raise_on_error=True)
... def test_network():
... with urlopen("complaint://deadparrot.com") as f:
... pass
...
>>> test_network()
Traceback (most recent call last):
...
URLError: <urlopen error unknown url type: complaint>

And use ``nosetests -a '!network'`` to exclude running tests requiring
network connectivity. ``_RAISE_NETWORK_ERROR_DEFAULT`` in
``pandas/util/testing.py`` sets the default behavior (currently False).
"""
from nose import SkipTest

if num_runs < 1:
raise ValueError("Must set at least 1 run")
t.network = True

@wraps(t)
def network_wrapper(*args, **kwargs):
if raise_on_error:
return t(*args, **kwargs)
else:
runs = 0

for _ in range(num_runs):
try:
try:
return t(*args, **kwargs)
except error_classes as e:
raise SkipTest("Skipping test %s" % e)
except SkipTest:
raise
except Exception as e:
if runs < num_runs - 1:
print("Failed: %r" % e)
else:
raise

runs += 1

return network_wrapper


def can_connect(url, error_classes=_network_error_classes):
"""Try to connect to the given url. True if succeeds, False if IOError
raised
Expand All @@ -1096,10 +996,9 @@ def can_connect(url, error_classes=_network_error_classes):


@optional_args
def with_connectivity_check(t, url="http://www.google.com",
raise_on_error=_RAISE_NETWORK_ERROR_DEFAULT,
check_before_test=False,
error_classes=_network_error_classes):
def network(t, url="http://www.google.com",
raise_on_error=_RAISE_NETWORK_ERROR_DEFAULT,
check_before_test=False, error_classes=_network_error_classes):
"""
Label a test as requiring network connection and, if an error is
encountered, only raise if it does not find a network connection.
Expand Down Expand Up @@ -1138,25 +1037,42 @@ def with_connectivity_check(t, url="http://www.google.com",
Example
-------

In this example, you see how it will raise the error if it can connect to
the url::
>>> @with_connectivity_check("http://www.yahoo.com")
Tests decorated with @network will fail if it's possible to make a network
connection to another URL (defaults to google.com)::

>>> from pandas.util.testing import network
>>> from pandas.io.common import urlopen
>>> @network
... def test_network():
... with urlopen("rabbit://bonanza.com"):
... pass
Traceback
...
URLError: <urlopen error unknown url type: rabit>

You can specify alternative URLs::

>>> @network("http://www.yahoo.com")
... def test_something_with_yahoo():
... raise IOError("Failure Message")
>>> test_something_with_yahoo()
Traceback (most recent call last):
...
IOError: Failure Message

I you set check_before_test, it will check the url first and not run the test on failure::
>>> @with_connectivity_check("failing://url.blaher", check_before_test=True)
If you set check_before_test, it will check the url first and not run the
test on failure::

>>> @network("failing://url.blaher", check_before_test=True)
... def test_something():
... print("I ran!")
... raise ValueError("Failure")
>>> test_something()
Traceback (most recent call last):
...
SkipTest

Errors not related to networking will always be raised.
"""
from nose import SkipTest
t.network = True
Expand All @@ -1178,6 +1094,9 @@ def wrapper(*args, **kwargs):
return wrapper


with_connectivity_check = network


class SimpleMock(object):

"""
Expand Down