Validate that float_format option is callable
State: closed

- [x] closes #12706
- [ ] tests added / passed
- [x] passes `git diff upstream/master | flake8 --diff`
- [x] whatsnew entry


Labels:
name: Error Reporting
description: Incorrect or improved errors from pandas

Comments:
Some of [my travis builds](https://travis-ci.org/tdhopper/pandas) are failing for reasons unclear to me. This is my first attempt at a pandas PR, so I'd love some help if it's available. 

Also, I'm having a hard time seeing where a test would go for this. I haven't been able to find where option validators are tested.

can you add a test in `test_config.py` (`test_validation`) section. and pls add a whatsnew note (bug fix is good)

http://pandas.pydata.org/pandas-docs/stable/contributing.html

try:

```
git checkout yourbranch
git rebase -i originmaster
```

fix anything if needed

```
git push yourorigin yourbranchname --tags
git push yourorigin yourbranchname
```

I suspect you have a fairly old fork, which means its tags aren't updating. this is an annoying git/travis thing.

Just an FYI, as I'm not sure what changes you are adding: every time you push, you start a new build on Travis, and right now you have three builds that haven't been run yet.  It seems prudent perhaps to test locally before you push.  Also, from a selfish standpoint, I am impatient and would like Travis to run the most recent build for my PR :smile:

@jreback: Could you cancel the old builds for this PR?

@gfyoung: Oy, I wasn't thinking about it triggering builds on the Pandas Travis. (I'm watching it on mine.) I can't have the tests cooking my work computer at the moment, so I was letting Travis handle it for me. 

@gfyoung That's just how things work. I don't see it as a problem.

@gfyoung you of course have travis running on YOUR own branches, the pydata/pandas builder is just for final confirmation. 

In any case, I think I'm getting close to having this thing ready, @jreback 

https://travis-ci.org/tdhopper/pandas

https://travis-ci.org/gfyoung/pandas (@gfyoung), not running on your branch for some reason

@tdhopper yep that looks good. minor doc change. ping when green.

@tdhopper : Ah, no worries.  Just wanted to point that out for future reference.  It also was driven partially be selfish motives as I didn't try hard to conceal. :smile:

@jreback : Fair point.  For future reference, would that be considered valid confirmation in case there is a traffic jam on the main `pandas` account?

@gfyoung no, but its simple better to ping me if you want me to look. But I would certainly fix up your personal branch on travis, it runs MUCH faster as there is NO contention, except your own builds. pydata builds are contending with LOTS of things.

@jreback: Sadly `validator=is_instance_factory([type(None), is_callable)` won't work because `isinstance(x, is_callable)` doesn't work.

My current solution (tested fine locally and now running in travis) is adding a `is_callable_or_none` validator. The only other option I can think of is a factor function that can essentially `or` a list of validators and pass it `is_callable` and `is_None`. However, `or` ends up being a pain since we're using validators that either return `True` and otherwise raise. 

This is tricker than I thought!

I think this will work. 

```
 from types import FunctionType

In [2]: f = is_instance_factory([type(None), FunctionType])

In [3]: f(None)

In [4]: f(lambda x: x)

# you can't make this any more generic that a single function
In [5]: f(lambda x, y: x)

In [6]: f(1)
ValueError: Value must be an instance of <type 'NoneType'>|<type 'function'>
```

@jreback: That would exclude callable objects. Maybe it's not a concern, but 😬

yeah I suppose. ok, then `is_callable_or_none` it is.

pls rebase as well.

Rebased and fixed a comment. I'm heading out for the weekend. Thanks for the help Jeff.

@tdhopper thanks!

I changed the approach to use `is_one_of_factory`....but otherwise the same

Great solution! Much better that way.