|
import pytest |
|
|
|
from pandas._config import config as cf |
|
from pandas._config.config import OptionError |
|
|
|
import pandas as pd |
|
import pandas._testing as tm |
|
|
|
|
|
class TestConfig: |
|
@pytest.fixture(autouse=True) |
|
def clean_config(self, monkeypatch): |
|
with monkeypatch.context() as m: |
|
m.setattr(cf, "_global_config", {}) |
|
m.setattr(cf, "options", cf.DictWrapper(cf._global_config)) |
|
m.setattr(cf, "_deprecated_options", {}) |
|
m.setattr(cf, "_registered_options", {}) |
|
|
|
|
|
|
|
|
|
|
|
cf.register_option("chained_assignment", "raise") |
|
yield |
|
|
|
def test_api(self): |
|
|
|
assert hasattr(pd, "get_option") |
|
assert hasattr(pd, "set_option") |
|
assert hasattr(pd, "reset_option") |
|
assert hasattr(pd, "describe_option") |
|
|
|
def test_is_one_of_factory(self): |
|
v = cf.is_one_of_factory([None, 12]) |
|
|
|
v(12) |
|
v(None) |
|
msg = r"Value must be one of None\|12" |
|
with pytest.raises(ValueError, match=msg): |
|
v(1.1) |
|
|
|
def test_register_option(self): |
|
cf.register_option("a", 1, "doc") |
|
|
|
|
|
msg = "Option 'a' has already been registered" |
|
with pytest.raises(OptionError, match=msg): |
|
cf.register_option("a", 1, "doc") |
|
|
|
|
|
msg = "Path prefix to option 'a' is already an option" |
|
with pytest.raises(OptionError, match=msg): |
|
cf.register_option("a.b.c.d1", 1, "doc") |
|
with pytest.raises(OptionError, match=msg): |
|
cf.register_option("a.b.c.d2", 1, "doc") |
|
|
|
|
|
msg = "for is a python keyword" |
|
with pytest.raises(ValueError, match=msg): |
|
cf.register_option("for", 0) |
|
with pytest.raises(ValueError, match=msg): |
|
cf.register_option("a.for.b", 0) |
|
|
|
msg = "oh my goddess! is not a valid identifier" |
|
with pytest.raises(ValueError, match=msg): |
|
cf.register_option("Oh my Goddess!", 0) |
|
|
|
|
|
|
|
|
|
|
|
cf.register_option("k.b.c.d1", 1, "doc") |
|
cf.register_option("k.b.c.d2", 1, "doc") |
|
|
|
def test_describe_option(self): |
|
cf.register_option("a", 1, "doc") |
|
cf.register_option("b", 1, "doc2") |
|
cf.deprecate_option("b") |
|
|
|
cf.register_option("c.d.e1", 1, "doc3") |
|
cf.register_option("c.d.e2", 1, "doc4") |
|
cf.register_option("f", 1) |
|
cf.register_option("g.h", 1) |
|
cf.register_option("k", 2) |
|
cf.deprecate_option("g.h", rkey="k") |
|
cf.register_option("l", "foo") |
|
|
|
|
|
msg = r"No such keys\(s\)" |
|
with pytest.raises(OptionError, match=msg): |
|
cf.describe_option("no.such.key") |
|
|
|
|
|
assert "doc" in cf.describe_option("a", _print_desc=False) |
|
assert "doc2" in cf.describe_option("b", _print_desc=False) |
|
assert "precated" in cf.describe_option("b", _print_desc=False) |
|
assert "doc3" in cf.describe_option("c.d.e1", _print_desc=False) |
|
assert "doc4" in cf.describe_option("c.d.e2", _print_desc=False) |
|
|
|
|
|
|
|
assert "available" in cf.describe_option("f", _print_desc=False) |
|
assert "available" in cf.describe_option("g.h", _print_desc=False) |
|
assert "precated" in cf.describe_option("g.h", _print_desc=False) |
|
assert "k" in cf.describe_option("g.h", _print_desc=False) |
|
|
|
|
|
assert "foo" in cf.describe_option("l", _print_desc=False) |
|
|
|
assert "bar" not in cf.describe_option("l", _print_desc=False) |
|
cf.set_option("l", "bar") |
|
assert "bar" in cf.describe_option("l", _print_desc=False) |
|
|
|
def test_case_insensitive(self): |
|
cf.register_option("KanBAN", 1, "doc") |
|
|
|
assert "doc" in cf.describe_option("kanbaN", _print_desc=False) |
|
assert cf.get_option("kanBaN") == 1 |
|
cf.set_option("KanBan", 2) |
|
assert cf.get_option("kAnBaN") == 2 |
|
|
|
|
|
msg = r"No such keys\(s\): 'no_such_option'" |
|
with pytest.raises(OptionError, match=msg): |
|
cf.get_option("no_such_option") |
|
cf.deprecate_option("KanBan") |
|
|
|
assert cf._is_deprecated("kAnBaN") |
|
|
|
def test_get_option(self): |
|
cf.register_option("a", 1, "doc") |
|
cf.register_option("b.c", "hullo", "doc2") |
|
cf.register_option("b.b", None, "doc2") |
|
|
|
|
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b.c") == "hullo" |
|
assert cf.get_option("b.b") is None |
|
|
|
|
|
msg = r"No such keys\(s\): 'no_such_option'" |
|
with pytest.raises(OptionError, match=msg): |
|
cf.get_option("no_such_option") |
|
|
|
def test_set_option(self): |
|
cf.register_option("a", 1, "doc") |
|
cf.register_option("b.c", "hullo", "doc2") |
|
cf.register_option("b.b", None, "doc2") |
|
|
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b.c") == "hullo" |
|
assert cf.get_option("b.b") is None |
|
|
|
cf.set_option("a", 2) |
|
cf.set_option("b.c", "wurld") |
|
cf.set_option("b.b", 1.1) |
|
|
|
assert cf.get_option("a") == 2 |
|
assert cf.get_option("b.c") == "wurld" |
|
assert cf.get_option("b.b") == 1.1 |
|
|
|
msg = r"No such keys\(s\): 'no.such.key'" |
|
with pytest.raises(OptionError, match=msg): |
|
cf.set_option("no.such.key", None) |
|
|
|
def test_set_option_empty_args(self): |
|
msg = "Must provide an even number of non-keyword arguments" |
|
with pytest.raises(ValueError, match=msg): |
|
cf.set_option() |
|
|
|
def test_set_option_uneven_args(self): |
|
msg = "Must provide an even number of non-keyword arguments" |
|
with pytest.raises(ValueError, match=msg): |
|
cf.set_option("a.b", 2, "b.c") |
|
|
|
def test_set_option_invalid_single_argument_type(self): |
|
msg = "Must provide an even number of non-keyword arguments" |
|
with pytest.raises(ValueError, match=msg): |
|
cf.set_option(2) |
|
|
|
def test_set_option_multiple(self): |
|
cf.register_option("a", 1, "doc") |
|
cf.register_option("b.c", "hullo", "doc2") |
|
cf.register_option("b.b", None, "doc2") |
|
|
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b.c") == "hullo" |
|
assert cf.get_option("b.b") is None |
|
|
|
cf.set_option("a", "2", "b.c", None, "b.b", 10.0) |
|
|
|
assert cf.get_option("a") == "2" |
|
assert cf.get_option("b.c") is None |
|
assert cf.get_option("b.b") == 10.0 |
|
|
|
def test_validation(self): |
|
cf.register_option("a", 1, "doc", validator=cf.is_int) |
|
cf.register_option("d", 1, "doc", validator=cf.is_nonnegative_int) |
|
cf.register_option("b.c", "hullo", "doc2", validator=cf.is_text) |
|
|
|
msg = "Value must have type '<class 'int'>'" |
|
with pytest.raises(ValueError, match=msg): |
|
cf.register_option("a.b.c.d2", "NO", "doc", validator=cf.is_int) |
|
|
|
cf.set_option("a", 2) |
|
cf.set_option("b.c", "wurld") |
|
cf.set_option("d", 2) |
|
cf.set_option("d", None) |
|
|
|
|
|
with pytest.raises(ValueError, match=msg): |
|
cf.set_option("a", None) |
|
with pytest.raises(ValueError, match=msg): |
|
cf.set_option("a", "ab") |
|
|
|
msg = "Value must be a nonnegative integer or None" |
|
with pytest.raises(ValueError, match=msg): |
|
cf.register_option("a.b.c.d3", "NO", "doc", validator=cf.is_nonnegative_int) |
|
with pytest.raises(ValueError, match=msg): |
|
cf.register_option("a.b.c.d3", -2, "doc", validator=cf.is_nonnegative_int) |
|
|
|
msg = r"Value must be an instance of <class 'str'>\|<class 'bytes'>" |
|
with pytest.raises(ValueError, match=msg): |
|
cf.set_option("b.c", 1) |
|
|
|
validator = cf.is_one_of_factory([None, cf.is_callable]) |
|
cf.register_option("b", lambda: None, "doc", validator=validator) |
|
|
|
cf.set_option("b", "%.1f".format) |
|
cf.set_option("b", None) |
|
with pytest.raises(ValueError, match="Value must be a callable"): |
|
cf.set_option("b", "%.1f") |
|
|
|
def test_reset_option(self): |
|
cf.register_option("a", 1, "doc", validator=cf.is_int) |
|
cf.register_option("b.c", "hullo", "doc2", validator=cf.is_str) |
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b.c") == "hullo" |
|
|
|
cf.set_option("a", 2) |
|
cf.set_option("b.c", "wurld") |
|
assert cf.get_option("a") == 2 |
|
assert cf.get_option("b.c") == "wurld" |
|
|
|
cf.reset_option("a") |
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b.c") == "wurld" |
|
cf.reset_option("b.c") |
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b.c") == "hullo" |
|
|
|
def test_reset_option_all(self): |
|
cf.register_option("a", 1, "doc", validator=cf.is_int) |
|
cf.register_option("b.c", "hullo", "doc2", validator=cf.is_str) |
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b.c") == "hullo" |
|
|
|
cf.set_option("a", 2) |
|
cf.set_option("b.c", "wurld") |
|
assert cf.get_option("a") == 2 |
|
assert cf.get_option("b.c") == "wurld" |
|
|
|
cf.reset_option("all") |
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b.c") == "hullo" |
|
|
|
def test_deprecate_option(self): |
|
|
|
cf.deprecate_option("foo") |
|
|
|
assert cf._is_deprecated("foo") |
|
with tm.assert_produces_warning(FutureWarning, match="deprecated"): |
|
with pytest.raises(KeyError, match="No such keys.s.: 'foo'"): |
|
cf.get_option("foo") |
|
|
|
cf.register_option("a", 1, "doc", validator=cf.is_int) |
|
cf.register_option("b.c", "hullo", "doc2") |
|
cf.register_option("foo", "hullo", "doc2") |
|
|
|
cf.deprecate_option("a", removal_ver="nifty_ver") |
|
with tm.assert_produces_warning(FutureWarning, match="eprecated.*nifty_ver"): |
|
cf.get_option("a") |
|
|
|
msg = "Option 'a' has already been defined as deprecated" |
|
with pytest.raises(OptionError, match=msg): |
|
cf.deprecate_option("a") |
|
|
|
cf.deprecate_option("b.c", "zounds!") |
|
with tm.assert_produces_warning(FutureWarning, match="zounds!"): |
|
cf.get_option("b.c") |
|
|
|
|
|
cf.register_option("d.a", "foo", "doc2") |
|
cf.register_option("d.dep", "bar", "doc2") |
|
assert cf.get_option("d.a") == "foo" |
|
assert cf.get_option("d.dep") == "bar" |
|
|
|
cf.deprecate_option("d.dep", rkey="d.a") |
|
with tm.assert_produces_warning(FutureWarning, match="eprecated"): |
|
assert cf.get_option("d.dep") == "foo" |
|
|
|
with tm.assert_produces_warning(FutureWarning, match="eprecated"): |
|
cf.set_option("d.dep", "baz") |
|
|
|
with tm.assert_produces_warning(FutureWarning, match="eprecated"): |
|
assert cf.get_option("d.dep") == "baz" |
|
|
|
def test_config_prefix(self): |
|
with cf.config_prefix("base"): |
|
cf.register_option("a", 1, "doc1") |
|
cf.register_option("b", 2, "doc2") |
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b") == 2 |
|
|
|
cf.set_option("a", 3) |
|
cf.set_option("b", 4) |
|
assert cf.get_option("a") == 3 |
|
assert cf.get_option("b") == 4 |
|
|
|
assert cf.get_option("base.a") == 3 |
|
assert cf.get_option("base.b") == 4 |
|
assert "doc1" in cf.describe_option("base.a", _print_desc=False) |
|
assert "doc2" in cf.describe_option("base.b", _print_desc=False) |
|
|
|
cf.reset_option("base.a") |
|
cf.reset_option("base.b") |
|
|
|
with cf.config_prefix("base"): |
|
assert cf.get_option("a") == 1 |
|
assert cf.get_option("b") == 2 |
|
|
|
def test_callback(self): |
|
k = [None] |
|
v = [None] |
|
|
|
def callback(key): |
|
k.append(key) |
|
v.append(cf.get_option(key)) |
|
|
|
cf.register_option("d.a", "foo", cb=callback) |
|
cf.register_option("d.b", "foo", cb=callback) |
|
|
|
del k[-1], v[-1] |
|
cf.set_option("d.a", "fooz") |
|
assert k[-1] == "d.a" |
|
assert v[-1] == "fooz" |
|
|
|
del k[-1], v[-1] |
|
cf.set_option("d.b", "boo") |
|
assert k[-1] == "d.b" |
|
assert v[-1] == "boo" |
|
|
|
del k[-1], v[-1] |
|
cf.reset_option("d.b") |
|
assert k[-1] == "d.b" |
|
|
|
def test_set_ContextManager(self): |
|
def eq(val): |
|
assert cf.get_option("a") == val |
|
|
|
cf.register_option("a", 0) |
|
eq(0) |
|
with cf.option_context("a", 15): |
|
eq(15) |
|
with cf.option_context("a", 25): |
|
eq(25) |
|
eq(15) |
|
eq(0) |
|
|
|
cf.set_option("a", 17) |
|
eq(17) |
|
|
|
|
|
@cf.option_context("a", 123) |
|
def f(): |
|
eq(123) |
|
|
|
f() |
|
|
|
def test_attribute_access(self): |
|
holder = [] |
|
|
|
def f3(key): |
|
holder.append(True) |
|
|
|
cf.register_option("a", 0) |
|
cf.register_option("c", 0, cb=f3) |
|
options = cf.options |
|
|
|
assert options.a == 0 |
|
with cf.option_context("a", 15): |
|
assert options.a == 15 |
|
|
|
options.a = 500 |
|
assert cf.get_option("a") == 500 |
|
|
|
cf.reset_option("a") |
|
assert options.a == cf.get_option("a", 0) |
|
|
|
msg = "You can only set the value of existing options" |
|
with pytest.raises(OptionError, match=msg): |
|
options.b = 1 |
|
with pytest.raises(OptionError, match=msg): |
|
options.display = 1 |
|
|
|
|
|
options.c = 1 |
|
assert len(holder) == 1 |
|
|
|
def test_option_context_scope(self): |
|
|
|
|
|
|
|
|
|
original_value = 60 |
|
context_value = 10 |
|
option_name = "a" |
|
|
|
cf.register_option(option_name, original_value) |
|
|
|
|
|
ctx = cf.option_context(option_name, context_value) |
|
assert cf.get_option(option_name) == original_value |
|
|
|
|
|
with ctx: |
|
assert cf.get_option(option_name) == context_value |
|
|
|
|
|
assert cf.get_option(option_name) == original_value |
|
|
|
def test_dictwrapper_getattr(self): |
|
options = cf.options |
|
|
|
with pytest.raises(OptionError, match="No such option"): |
|
options.bananas |
|
assert not hasattr(options, "bananas") |
|
|