Skip to content

ENH: Added dict support for pd.set_option #61151

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

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Other enhancements
- :class:`Rolling` and :class:`Expanding` now support ``pipe`` method (:issue:`57076`)
- :class:`Series` now supports the Arrow PyCapsule Interface for export (:issue:`59518`)
- :func:`DataFrame.to_excel` argument ``merge_cells`` now accepts a value of ``"columns"`` to only merge :class:`MultiIndex` column header header cells (:issue:`35384`)
- :func:`set_option` now accepts a dictionary of options, simplifying configuration of multiple settings at once (:issue:`61093`)
- :meth:`DataFrame.corrwith` now accepts ``min_periods`` as optional arguments, as in :meth:`DataFrame.corr` and :meth:`Series.corr` (:issue:`9490`)
- :meth:`DataFrame.cummin`, :meth:`DataFrame.cummax`, :meth:`DataFrame.cumprod` and :meth:`DataFrame.cumsum` methods now have a ``numeric_only`` parameter (:issue:`53072`)
- :meth:`DataFrame.ewm` now allows ``adjust=False`` when ``times`` is provided (:issue:`54328`)
Expand Down
35 changes: 29 additions & 6 deletions pandas/_config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,9 @@ def set_option(*args) -> None:

Parameters
----------
*args : str | object
Arguments provided in pairs, which will be interpreted as (pattern, value)
pairs.
*args : str | object | dict
Arguments provided in pairs, which will be interpreted as (pattern, value),
or as a single dictionary containing multiple option-value pairs.
pattern: str
Regexp which should match a single option
value: object
Expand Down Expand Up @@ -239,6 +239,8 @@ def set_option(*args) -> None:

Examples
--------
Option-Value Pair Input:

>>> pd.set_option("display.max_columns", 4)
>>> df = pd.DataFrame([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
>>> df
Expand All @@ -247,8 +249,23 @@ def set_option(*args) -> None:
1 6 7 ... 9 10
[2 rows x 5 columns]
>>> pd.reset_option("display.max_columns")

Dictionary Input:

>>> pd.set_option({"display.max_columns": 4, "display.precision": 1})
>>> df = pd.DataFrame([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
>>> df
0 1 ... 3 4
0 1 2 ... 4 5
1 6 7 ... 9 10
[2 rows x 5 columns]
>>> pd.reset_option("display.max_columns")
>>> pd.reset_option("display.precision")
"""
# must at least 1 arg deal with constraints later
# Handle dictionary input
if len(args) == 1 and isinstance(args[0], dict):
args = tuple(kv for item in args[0].items() for kv in item)

nargs = len(args)
if not nargs or nargs % 2 != 0:
raise ValueError("Must provide an even number of non-keyword arguments")
Expand Down Expand Up @@ -440,9 +457,10 @@ def option_context(*args) -> Generator[None]:

Parameters
----------
*args : str | object
*args : str | object | dict
An even amount of arguments provided in pairs which will be
interpreted as (pattern, value) pairs.
interpreted as (pattern, value) pairs. Alternatively, a single
dictionary of {pattern: value} may be provided.

Returns
-------
Expand Down Expand Up @@ -471,7 +489,12 @@ def option_context(*args) -> Generator[None]:
>>> from pandas import option_context
>>> with option_context("display.max_rows", 10, "display.max_columns", 5):
... pass
>>> with option_context({"display.max_rows": 10, "display.max_columns": 5}):
... pass
"""
if len(args) == 1 and isinstance(args[0], dict):
args = tuple(kv for item in args[0].items() for kv in item)

if len(args) % 2 != 0 or len(args) < 2:
raise ValueError(
"Provide an even amount of arguments as "
Expand Down
45 changes: 45 additions & 0 deletions pandas/tests/config/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,24 @@ def test_set_option_multiple(self):
assert cf.get_option("b.c") is None
assert cf.get_option("b.b") == 10.0

def test_set_option_dict(self):
# GH 61093

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

options_dict = {"a": "2", "b.c": None, "b.b": 10.0}
cf.set_option(options_dict)

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)
Expand Down Expand Up @@ -377,6 +395,33 @@ def f():

f()

def test_set_ContextManager_dict(self):
def eq(val):
assert cf.get_option("a") == val
assert cf.get_option("b.c") == val

cf.register_option("a", 0)
cf.register_option("b.c", 0)

eq(0)
with cf.option_context({"a": 15, "b.c": 15}):
eq(15)
with cf.option_context({"a": 25, "b.c": 25}):
eq(25)
eq(15)
eq(0)

cf.set_option("a", 17)
cf.set_option("b.c", 17)
eq(17)

# Test that option_context can be used as a decorator too
@cf.option_context({"a": 123, "b.c": 123})
def f():
eq(123)

f()

def test_attribute_access(self):
holder = []

Expand Down
Loading