Skip to content

ENH: enhance set_option syntax #3677

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
May 30, 2013
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
4 changes: 4 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pandas 0.11.1
Note: The default value will change in 0.12 to make the default *to* write and
read multi-index columns in the new format. (GH3571_, GH1651_, GH3141_)
- Add iterator to ``Series.str`` (GH3638_)
- ``pd.set_option()`` now allows N option, value pairs (GH3667_).



**Improvements to existing features**

Expand Down Expand Up @@ -269,6 +272,7 @@ pandas 0.11.1
.. _GH3702: https://github.com/pydata/pandas/issues/3702
.. _GH3691: https://github.com/pydata/pandas/issues/3691
.. _GH3696: https://github.com/pydata/pandas/issues/3696
.. _GH3667: https://github.com/pydata/pandas/issues/3667

pandas 0.11.0
=============
Expand Down
25 changes: 25 additions & 0 deletions doc/source/v0.11.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,30 @@ Enhancements
GH3572_). This happens before any drawing takes place which elimnates any
spurious plots from showing up.

- ``pd.set_option()`` now allows N option, value pairs (GH3667_).

Let's say that we had an option ``'a.b'`` and another option ``'b.c'``.
We can set them at the same time:

.. ipython:: python
:suppress:

pd.core.config.register_option('a.b', 2, 'ay dot bee')
pd.core.config.register_option('b.c', 3, 'bee dot cee')

.. ipython:: python

pd.get_option('a.b')
pd.get_option('b.c')
pd.set_option('a.b', 1, 'b.c', 4)
pd.get_option('a.b')
pd.get_option('b.c')

You can of course still do it sequentially if you want. You can use up to
N arguments here, the only stipulation is that the number of arguments
must be even (since if they weren't then that would mean you provided an
argument name with no value).

Bug Fixes
~~~~~~~~~

Expand Down Expand Up @@ -305,3 +329,4 @@ on GitHub for a complete list.
.. _GH3702: https://github.com/pydata/pandas/issues/3702
.. _GH3691: https://github.com/pydata/pandas/issues/3691
.. _GH3696: https://github.com/pydata/pandas/issues/3696
.. _GH3667: https://github.com/pydata/pandas/issues/3667
54 changes: 41 additions & 13 deletions pandas/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def _get_option(pat, silent=False):
return root[k]


def _set_option(pat, value, silent=False):
def _set_single_option(pat, value, silent):
key = _get_single_key(pat, silent)

o = _get_registered_option(key)
Expand All @@ -109,6 +109,40 @@ def _set_option(pat, value, silent=False):
o.cb(key)


def _set_multiple_options(args, silent):
for k, v in zip(args[::2], args[1::2]):
_set_single_option(k, v, silent)


def _set_option(*args, **kwargs):
# must at least 1 arg deal with constraints later
nargs = len(args)
if not nargs or nargs % 2 != 0:
raise AssertionError("Must provide an even number of non-keyword "
"arguments")

# must be 0 or 1 kwargs
nkwargs = len(kwargs)
if nkwargs not in (0, 1):
raise AssertionError("The can only be 0 or 1 keyword arguments")

# if 1 kwarg then it must be silent=True or silent=False
if nkwargs:
k, = kwargs.keys()
v, = kwargs.values()

if k != 'silent':
raise ValueError("the only allowed keyword argument is 'silent', "
"you passed '{0}'".format(k))
if not isinstance(v, bool):
raise TypeError("the type of the keyword argument passed must be "
"bool, you passed a {0}".format(v.__class__))

# default to false
silent = kwargs.get('silent', False)
_set_multiple_options(args, silent)


def _describe_option(pat='', _print_desc=True):

keys = _select_options(pat)
Expand Down Expand Up @@ -186,7 +220,7 @@ def __dir__(self):
# of options, and option descriptions.


class CallableDyanmicDoc(object):
class CallableDynamicDoc(object):

def __init__(self, func, doc_tmpl):
self.__doc_tmpl__ = doc_tmpl
Expand Down Expand Up @@ -301,10 +335,10 @@ def __doc__(self):

# bind the functions with their docstrings into a Callable
# and use that as the functions exposed in pd.api
get_option = CallableDyanmicDoc(_get_option, _get_option_tmpl)
set_option = CallableDyanmicDoc(_set_option, _set_option_tmpl)
reset_option = CallableDyanmicDoc(_reset_option, _reset_option_tmpl)
describe_option = CallableDyanmicDoc(_describe_option, _describe_option_tmpl)
get_option = CallableDynamicDoc(_get_option, _get_option_tmpl)
set_option = CallableDynamicDoc(_set_option, _set_option_tmpl)
reset_option = CallableDynamicDoc(_reset_option, _reset_option_tmpl)
describe_option = CallableDynamicDoc(_describe_option, _describe_option_tmpl)
options = DictWrapper(_global_config)

######################################################
Expand Down Expand Up @@ -505,13 +539,7 @@ def _get_registered_option(key):
-------
RegisteredOption (namedtuple) if key is deprecated, None otherwise
"""

try:
d = _registered_options[key]
except KeyError:
return None
else:
return d
return _registered_options.get(key)


def _translate_key(key):
Expand Down
38 changes: 38 additions & 0 deletions pandas/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,44 @@ def test_set_option(self):

self.assertRaises(KeyError, self.cf.set_option, 'no.such.key', None)


def test_set_option_empty_args(self):
self.assertRaises(AssertionError, self.cf.set_option)

def test_set_option_uneven_args(self):
self.assertRaises(AssertionError, self.cf.set_option, 'a.b', 2, 'b.c')


def test_set_option_2_kwargs(self):
self.assertRaises(AssertionError, self.cf.set_option, 'a.b', 2,
silenadf=2, asdf=2)

def test_set_option_invalid_kwargs_key(self):
self.assertRaises(ValueError, self.cf.set_option, 'a.b', 2,
silenadf=2)

def test_set_option_invalid_kwargs_value_type(self):
self.assertRaises(TypeError, self.cf.set_option, 'a.b', 2,
silent=2)

def test_set_option_invalid_single_argument_type(self):
self.assertRaises(AssertionError, self.cf.set_option, 2)

def test_set_option_multiple(self):
self.cf.register_option('a', 1, 'doc')
self.cf.register_option('b.c', 'hullo', 'doc2')
self.cf.register_option('b.b', None, 'doc2')

self.assertEqual(self.cf.get_option('a'), 1)
self.assertEqual(self.cf.get_option('b.c'), 'hullo')
self.assertTrue(self.cf.get_option('b.b') is None)

self.cf.set_option('a', '2', 'b.c', None, 'b.b', 10.0)

self.assertEqual(self.cf.get_option('a'), '2')
self.assertTrue(self.cf.get_option('b.c') is None)
self.assertEqual(self.cf.get_option('b.b'), 10.0)

def test_validation(self):
self.cf.register_option('a', 1, 'doc', validator=self.cf.is_int)
self.cf.register_option('b.c', 'hullo', 'doc2',
Expand Down