Skip to content

REF/TST: Add more pytest idiom to util/test_util #24141

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
merged 1 commit into from
Dec 7, 2018
Merged
Show file tree
Hide file tree
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
93 changes: 93 additions & 0 deletions pandas/tests/util/test_deprecate_kwarg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
import pytest

from pandas.util._decorators import deprecate_kwarg

import pandas.util.testing as tm


@deprecate_kwarg("old", "new")
def _f1(new=False):
return new


_f2_mappings = {"yes": True, "no": False}


@deprecate_kwarg("old", "new", _f2_mappings)
def _f2(new=False):
return new


def _f3_mapping(x):
return x + 1


@deprecate_kwarg("old", "new", _f3_mapping)
def _f3(new=0):
return new


@pytest.mark.parametrize("key,klass", [
("old", FutureWarning),
("new", None)
])
def test_deprecate_kwarg(key, klass):
x = 78

with tm.assert_produces_warning(klass):
assert _f1(**{key: x}) == x


@pytest.mark.parametrize("key", list(_f2_mappings.keys()))
def test_dict_deprecate_kwarg(key):
with tm.assert_produces_warning(FutureWarning):
assert _f2(old=key) == _f2_mappings[key]


@pytest.mark.parametrize("key", ["bogus", 12345, -1.23])
def test_missing_deprecate_kwarg(key):
with tm.assert_produces_warning(FutureWarning):
assert _f2(old=key) == key


@pytest.mark.parametrize("x", [1, -1.4, 0])
def test_callable_deprecate_kwarg(x):
with tm.assert_produces_warning(FutureWarning):
assert _f3(old=x) == _f3_mapping(x)


def test_callable_deprecate_kwarg_fail():
msg = "((can only|cannot) concatenate)|(must be str)|(Can't convert)"

with pytest.raises(TypeError, match=msg):
_f3(old="hello")


def test_bad_deprecate_kwarg():
msg = "mapping from old to new argument values must be dict or callable!"

with pytest.raises(TypeError, match=msg):
@deprecate_kwarg("old", "new", 0)
def f4(new=None):
return new


@deprecate_kwarg("old", None)
def _f4(old=True, unchanged=True):
return old, unchanged


@pytest.mark.parametrize("key", ["old", "unchanged"])
def test_deprecate_keyword(key):
x = 9

if key == "old":
klass = FutureWarning
expected = (x, True)
else:
klass = None
expected = (True, x)

with tm.assert_produces_warning(klass):
assert _f4(**{key: x}) == expected
94 changes: 94 additions & 0 deletions pandas/tests/util/test_locale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# -*- coding: utf-8 -*-
import codecs
import locale
import os

import pytest

from pandas.compat import is_platform_windows

import pandas.core.common as com
import pandas.util.testing as tm

_all_locales = tm.get_locales() or []
_current_locale = locale.getlocale()

# Don't run any of these tests if we are on Windows or have no locales.
pytestmark = pytest.mark.skipif(is_platform_windows() or not _all_locales,
reason="Need non-Windows and locales")

_skip_if_only_one_locale = pytest.mark.skipif(
len(_all_locales) <= 1, reason="Need multiple locales for meaningful test")


def test_can_set_locale_valid_set():
# Can set the default locale.
assert tm.can_set_locale("")


def test_can_set_locale_invalid_set():
# Cannot set an invalid locale.
assert not tm.can_set_locale("non-existent_locale")


def test_can_set_locale_invalid_get(monkeypatch):
# see gh-22129
#
# In some cases, an invalid locale can be set,
# but a subsequent getlocale() raises a ValueError.

def mock_get_locale():
raise ValueError()

with monkeypatch.context() as m:
m.setattr(locale, "getlocale", mock_get_locale)
assert not tm.can_set_locale("")


def test_get_locales_at_least_one():
# see gh-9744
assert len(_all_locales) > 0


@_skip_if_only_one_locale
def test_get_locales_prefix():
first_locale = _all_locales[0]
assert len(tm.get_locales(prefix=first_locale[:2])) > 0


@_skip_if_only_one_locale
def test_set_locale():
if com._all_none(_current_locale):
# Not sure why, but on some Travis runs with pytest,
# getlocale() returned (None, None).
pytest.skip("Current locale is not set.")

locale_override = os.environ.get("LOCALE_OVERRIDE", None)

if locale_override is None:
lang, enc = "it_CH", "UTF-8"
elif locale_override == "C":
lang, enc = "en_US", "ascii"
else:
lang, enc = locale_override.split(".")

enc = codecs.lookup(enc).name
new_locale = lang, enc

if not tm.can_set_locale(new_locale):
msg = "unsupported locale setting"

with pytest.raises(locale.Error, match=msg):
with tm.set_locale(new_locale):
pass
else:
with tm.set_locale(new_locale) as normalized_locale:
new_lang, new_enc = normalized_locale.split(".")
new_enc = codecs.lookup(enc).name

normalized_locale = new_lang, new_enc
assert normalized_locale == new_locale

# Once we exit the "with" statement, locale should be back to what it was.
current_locale = locale.getlocale()
assert current_locale == _current_locale
79 changes: 79 additions & 0 deletions pandas/tests/util/test_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
import sys
from uuid import uuid4

import pytest

from pandas.compat import PY3, intern
from pandas.util._move import BadMove, move_into_mutable_buffer, stolenbuf


def test_cannot_create_instance_of_stolen_buffer():
# Stolen buffers need to be created through the smart constructor
# "move_into_mutable_buffer," which has a bunch of checks in it.

msg = "cannot create 'pandas.util._move.stolenbuf' instances"
with pytest.raises(TypeError, match=msg):
stolenbuf()


def test_more_than_one_ref():
# Test case for when we try to use "move_into_mutable_buffer"
# when the object being moved has other references.

b = b"testing"

with pytest.raises(BadMove) as e:
def handle_success(type_, value, tb):
assert value.args[0] is b
return type(e).handle_success(e, type_, value, tb) # super

e.handle_success = handle_success
move_into_mutable_buffer(b)


def test_exactly_one_ref():
# Test case for when the object being moved has exactly one reference.

b = b"testing"

# We need to pass an expression on the stack to ensure that there are
# not extra references hanging around. We cannot rewrite this test as
# buf = b[:-3]
# as_stolen_buf = move_into_mutable_buffer(buf)
# because then we would have more than one reference to buf.
as_stolen_buf = move_into_mutable_buffer(b[:-3])

# Materialize as byte-array to show that it is mutable.
assert bytearray(as_stolen_buf) == b"test"


@pytest.mark.skipif(PY3, reason="bytes objects cannot be interned in PY3")
def test_interned():
salt = uuid4().hex

def make_string():
# We need to actually create a new string so that it has refcount
# one. We use a uuid so that we know the string could not already
# be in the intern table.
return "".join(("testing: ", salt))

# This should work, the string has one reference on the stack.
move_into_mutable_buffer(make_string())
refcount = [None] # nonlocal

def ref_capture(ob):
# Subtract two because those are the references owned by this frame:
# 1. The local variables of this stack frame.
# 2. The python data stack of this stack frame.
refcount[0] = sys.getrefcount(ob) - 2
return ob

with pytest.raises(BadMove, match="testing"):
# If we intern the string, it will still have one reference. Now,
# it is in the intern table, so if other people intern the same
# string while the mutable buffer holds the first string they will
# be the same instance.
move_into_mutable_buffer(ref_capture(intern(make_string()))) # noqa

assert refcount[0] == 1
45 changes: 45 additions & 0 deletions pandas/tests/util/test_safe_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
import sys
import types

import pytest

import pandas.util._test_decorators as td


@pytest.mark.parametrize("name", ["foo", "hello123"])
def test_safe_import_non_existent(name):
assert not td.safe_import(name)


def test_safe_import_exists():
assert td.safe_import("pandas")


@pytest.mark.parametrize("min_version,valid", [
("0.0.0", True),
("99.99.99", False)
])
def test_safe_import_versions(min_version, valid):
result = td.safe_import("pandas", min_version=min_version)
result = result if valid else not result
assert result


@pytest.mark.parametrize("min_version,valid", [
(None, False),
("1.0", True),
("2.0", False)
])
def test_safe_import_dummy(monkeypatch, min_version, valid):
mod_name = "hello123"

mod = types.ModuleType(mod_name)
mod.__version__ = "1.5"

if min_version is not None:
monkeypatch.setitem(sys.modules, mod_name, mod)

result = td.safe_import(mod_name, min_version=min_version)
result = result if valid else not result
assert result
Loading