Skip to content

ENH: Validation to only allow positive integers for options #27382

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 20 commits into from
Aug 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
def4005
Created a new validation function (is_pos_int) to allow options to be
Adam-Klaum Jul 12, 2019
e50961d
Added positive and negative tests for is_pos_int in test_validation.
Adam-Klaum Jul 13, 2019
32e8c67
Updating whatsnew
Adam-Klaum Jul 13, 2019
9618877
Fixing order as per isort
Adam-Klaum Jul 13, 2019
7a5593b
Simplified the is_pos_int function to be used standalone rather than
Adam-Klaum Jul 15, 2019
d6fa258
Updated is_pos_int docstring with Returns and Raises
Adam-Klaum Jul 16, 2019
eb09813
Clarifying documentation
Adam-Klaum Jul 18, 2019
8f46673
Merge branch 'master' into 23348_max_rows
Adam-Klaum Jul 24, 2019
21bf599
Removed Returns section from docstring. Set dash length to be the same
Adam-Klaum Jul 24, 2019
ea09cc2
Moved whatsnew documentation from v25 to v26
Adam-Klaum Jul 24, 2019
6c2ff43
Added documentation to Other section
Adam-Klaum Jul 24, 2019
25e0247
Merge remote-tracking branch 'origin/master' into 23348_max_rows
Adam-Klaum Jul 27, 2019
d18a01a
Moving comments to v1.0.0 file
Adam-Klaum Jul 27, 2019
4e76640
Added double ticks around display parameters in whatsnew.
Adam-Klaum Jul 29, 2019
80d2f1a
Merge remote-tracking branch 'origin/master' into 23348_max_rows
Adam-Klaum Jul 29, 2019
2d783ef
Corrected is_pos_int ValueError message in test suite
Adam-Klaum Jul 30, 2019
7163990
Merge remote-tracking branch 'upstream/master' into 23348_max_rows
Adam-Klaum Jul 30, 2019
033339f
Refactored is_pos_int to is_nonnegative_int and updated whatsnew.
Adam-Klaum Aug 4, 2019
42d844e
Merge remote-tracking branch 'upstream/master' into 23348_max_rows
Adam-Klaum Aug 4, 2019
1a25d06
Fixing import sorting issue
Adam-Klaum Aug 5, 2019
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
6 changes: 6 additions & 0 deletions doc/source/whatsnew/v1.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@ ExtensionArray
-
-


Other
^^^^^
- Trying to set the ``display.precision``, ``display.max_rows`` or ``display.max_columns`` using :meth:`set_option` to anything but a ``None`` or a positive int will raise a ``ValueError`` (:issue:`23348`)


.. _whatsnew_1000.contributors:

Contributors
Expand Down
27 changes: 27 additions & 0 deletions pandas/_config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,7 @@ def is_instance_factory(_type):
ValueError if x is not an instance of `_type`

"""

if isinstance(_type, (tuple, list)):
_type = tuple(_type)
type_repr = "|".join(map(str, _type))
Expand Down Expand Up @@ -820,6 +821,32 @@ def inner(x):
return inner


def is_nonnegative_int(value):
"""
Verify that value is None or a positive int.

Parameters
----------
value : None or int
The `value` to be checked.

Raises
------
ValueError
When the value is not None or is a negative integer
"""

if value is None:
return

elif isinstance(value, int):
if value >= 0:
return

msg = "Value must be a nonnegative integer or None"
raise ValueError(msg)


# common type validators, for convenience
# usage: register_option(... , validator = is_int)
is_int = is_type_factory(int)
Expand Down
15 changes: 4 additions & 11 deletions pandas/core/config_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
is_callable,
is_instance_factory,
is_int,
is_nonnegative_int,
is_one_of_factory,
is_text,
)
Expand Down Expand Up @@ -319,7 +320,7 @@ def is_terminal():


with cf.config_prefix("display"):
cf.register_option("precision", 6, pc_precision_doc, validator=is_int)
cf.register_option("precision", 6, pc_precision_doc, validator=is_nonnegative_int)
cf.register_option(
"float_format",
None,
Expand All @@ -333,12 +334,7 @@ def is_terminal():
pc_max_info_rows_doc,
validator=is_instance_factory((int, type(None))),
)
cf.register_option(
"max_rows",
60,
pc_max_rows_doc,
validator=is_instance_factory([type(None), int]),
)
cf.register_option("max_rows", 60, pc_max_rows_doc, validator=is_nonnegative_int)
cf.register_option(
"min_rows",
10,
Expand All @@ -352,10 +348,7 @@ def is_terminal():
else:
max_cols = 20 # cannot determine optimal number of columns
cf.register_option(
"max_columns",
max_cols,
pc_max_cols_doc,
validator=is_instance_factory([type(None), int]),
"max_columns", max_cols, pc_max_cols_doc, validator=is_nonnegative_int
)
cf.register_option(
"large_repr",
Expand Down
13 changes: 13 additions & 0 deletions pandas/tests/config/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,33 @@ def test_set_option_multiple(self):

def test_validation(self):
self.cf.register_option("a", 1, "doc", validator=self.cf.is_int)
self.cf.register_option("d", 1, "doc", validator=self.cf.is_nonnegative_int)
self.cf.register_option("b.c", "hullo", "doc2", validator=self.cf.is_text)

msg = "Value must have type '<class 'int'>'"
with pytest.raises(ValueError, match=msg):
self.cf.register_option("a.b.c.d2", "NO", "doc", validator=self.cf.is_int)

self.cf.set_option("a", 2) # int is_int
self.cf.set_option("b.c", "wurld") # str is_str
self.cf.set_option("d", 2)

# None not is_int
with pytest.raises(ValueError, match=msg):
self.cf.set_option("a", None)
with pytest.raises(ValueError, match=msg):
self.cf.set_option("a", "ab")

msg = "Value must be a nonnegative integer or None"
with pytest.raises(ValueError, match=msg):
self.cf.register_option(
"a.b.c.d3", "NO", "doc", validator=self.cf.is_nonnegative_int
)
with pytest.raises(ValueError, match=msg):
self.cf.register_option(
"a.b.c.d3", -2, "doc", validator=self.cf.is_nonnegative_int
)

msg = r"Value must be an instance of <class 'str'>\|<class 'bytes'>"
with pytest.raises(ValueError, match=msg):
self.cf.set_option("b.c", 1)
Expand Down