[Matplotlib-devel] Easier tick formatters

classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

[Matplotlib-devel] Easier tick formatters

Todd
Currently setting up the tick formatting on matplotlib requires you to import a formatter from the ticker module, create an instance of that formatter, then pass that to the axis.  This makes sense for complicated formatting.  However, there are some obvious cases where we can probably infer the type of formatting someone wants to do if we are just given the formatter content.  For example

   * '' is probably going to be the null formatter
   * A callable, besides a formatter instance, is probably going to be a function formatter
   * A sequence or numpy array is probably going to be an index or fixed formatter, depending on the locator
   * Any other string is probably going to be a format string formatter or string method formatter.

So I think we could allow the `set_major_formatter` and `set_minor_formatter` to take certain sorts of inputs and create the formatter automatically for the user, making such cases much, much easier.  Specifically, I propose the following inputs be accepted:

   * `None` sets it to the default formatter
   * A callable (besides a formatter instance) is set to be a FuncFormatter
   * An empty string, `''`, is set to be a NullFormatter
   * Any other string is a StrMethodFormatter
   * An abc.collections.Sequence subclass or numpy ndarray subclass is an IndexFormatter, unless the axis is using a FixedLocator in which case it is a FixedLocator.  We could restrict this to just lists and numpy arrays only.

Any thoughts?

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

tcaswell
Interesting, I am weakly in favor of this.

I am normally very hesitant about adopting heuristics, but these seem well defined.  If we do this, we should drop the last rule as IndexFormatter is scheduled to be deprecated in in 3.3 and is a bit problematic in other ways.

I don't see any back-compatibility concerns (as none of those inputs work now).

Tom

On Wed, Mar 4, 2020 at 10:03 PM Todd <[hidden email]> wrote:
Currently setting up the tick formatting on matplotlib requires you to import a formatter from the ticker module, create an instance of that formatter, then pass that to the axis.  This makes sense for complicated formatting.  However, there are some obvious cases where we can probably infer the type of formatting someone wants to do if we are just given the formatter content.  For example

   * '' is probably going to be the null formatter
   * A callable, besides a formatter instance, is probably going to be a function formatter
   * A sequence or numpy array is probably going to be an index or fixed formatter, depending on the locator
   * Any other string is probably going to be a format string formatter or string method formatter.

So I think we could allow the `set_major_formatter` and `set_minor_formatter` to take certain sorts of inputs and create the formatter automatically for the user, making such cases much, much easier.  Specifically, I propose the following inputs be accepted:

   * `None` sets it to the default formatter
   * A callable (besides a formatter instance) is set to be a FuncFormatter
   * An empty string, `''`, is set to be a NullFormatter
   * Any other string is a StrMethodFormatter
   * An abc.collections.Sequence subclass or numpy ndarray subclass is an IndexFormatter, unless the axis is using a FixedLocator in which case it is a FixedLocator.  We could restrict this to just lists and numpy arrays only.

Any thoughts?
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel


--
Thomas Caswell
[hidden email]

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Eric Firing
In reply to this post by Todd
I'm very sympathetic to the goal of making smoother and simpler
interfaces, but I'm not yet convinced that this proposal is the way to
go.  An example of a case long ago where a proposal something like this
made a big improvement is the specification of a cmap kwarg: originally
it had to be a Colormap instance, but then it was changed to accept a
string.  That worked well because it was an extremely common situation,
and only one change in behavior was made--it essentially yielded
expected behavior right away.

Using custom formatters is much less common, I presume, and the new
behavior is not as simple as supplying a colormap name.

Eric

On 2020/03/04 5:03 PM, Todd wrote:

> Currently setting up the tick formatting on matplotlib requires you to
> import a formatter from the ticker module, create an instance of that
> formatter, then pass that to the axis.  This makes sense for complicated
> formatting.  However, there are some obvious cases where we can probably
> infer the type of formatting someone wants to do if we are just given
> the formatter content.  For example
>
>     * '' is probably going to be the null formatter
>     * A callable, besides a formatter instance, is probably going to be
> a function formatter
>     * A sequence or numpy array is probably going to be an index or
> fixed formatter, depending on the locator
>     * Any other string is probably going to be a format string formatter
> or string method formatter.
>
> So I think we could allow the `set_major_formatter` and
> `set_minor_formatter` to take certain sorts of inputs and create the
> formatter automatically for the user, making such cases much, much
> easier.  Specifically, I propose the following inputs be accepted:
>
>     * `None` sets it to the default formatter
>     * A callable (besides a formatter instance) is set to be a FuncFormatter
>     * An empty string, `''`, is set to be a NullFormatter
>     * Any other string is a StrMethodFormatter
>     * An abc.collections.Sequence subclass or numpy ndarray subclass is
> an IndexFormatter, unless the axis is using a FixedLocator in which case
> it is a FixedLocator.  We could restrict this to just lists and numpy
> arrays only.
>
> Any thoughts?
>
> _______________________________________________
> Matplotlib-devel mailing list
> [hidden email]
> https://mail.python.org/mailman/listinfo/matplotlib-devel
>

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Michael Waters
As a frequent user of MultipleLocator, I'd suggest that
`set_major_formatter` should also accept a float if this API change is
made.

-Mike


On 3/4/20 9:57 PM, Eric Firing wrote:

> I'm very sympathetic to the goal of making smoother and simpler
> interfaces, but I'm not yet convinced that this proposal is the way to
> go.  An example of a case long ago where a proposal something like
> this made a big improvement is the specification of a cmap kwarg:
> originally it had to be a Colormap instance, but then it was changed
> to accept a string.  That worked well because it was an extremely
> common situation, and only one change in behavior was made--it
> essentially yielded expected behavior right away.
>
> Using custom formatters is much less common, I presume, and the new
> behavior is not as simple as supplying a colormap name.
>
> Eric
>
> On 2020/03/04 5:03 PM, Todd wrote:
>> Currently setting up the tick formatting on matplotlib requires you
>> to import a formatter from the ticker module, create an instance of
>> that formatter, then pass that to the axis.  This makes sense for
>> complicated formatting. However, there are some obvious cases where
>> we can probably infer the type of formatting someone wants to do if
>> we are just given the formatter content.  For example
>>
>>     * '' is probably going to be the null formatter
>>     * A callable, besides a formatter instance, is probably going to
>> be a function formatter
>>     * A sequence or numpy array is probably going to be an index or
>> fixed formatter, depending on the locator
>>     * Any other string is probably going to be a format string
>> formatter or string method formatter.
>>
>> So I think we could allow the `set_major_formatter` and
>> `set_minor_formatter` to take certain sorts of inputs and create the
>> formatter automatically for the user, making such cases much, much
>> easier.  Specifically, I propose the following inputs be accepted:
>>
>>     * `None` sets it to the default formatter
>>     * A callable (besides a formatter instance) is set to be a
>> FuncFormatter
>>     * An empty string, `''`, is set to be a NullFormatter
>>     * Any other string is a StrMethodFormatter
>>     * An abc.collections.Sequence subclass or numpy ndarray subclass
>> is an IndexFormatter, unless the axis is using a FixedLocator in
>> which case it is a FixedLocator.  We could restrict this to just
>> lists and numpy arrays only.
>>
>> Any thoughts?
>>
>> _______________________________________________
>> Matplotlib-devel mailing list
>> [hidden email]
>> https://mail.python.org/mailman/listinfo/matplotlib-devel
>>
>
> _______________________________________________
> Matplotlib-devel mailing list
> [hidden email]
> https://mail.python.org/mailman/listinfo/matplotlib-devel
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Antony Lee-3
In reply to this post by Todd
I am sympathetic to the idea.  A much simpler rule, though, would be to *just* additionally accept callables.  New-style format string formatters can then be implemented by passing bound methods (`set_major_formatter("tick {}".format)` -- the bound method quietly ignores the second (index) argument), which also makes it explicit that we talking about {}-format, not %s-format.  Even `set_major_formatter("".format)` would already be much shorter to type than importing NullFormatter and using it.  In any case, we could always first implement support for callables, which already buys us all these cases, and defer further cases to later.
The only case not covered by callables/bound methods is FixedLocator, but this is already handled by set_x/yticks, and anyways (usually) involves setting both the locator and the formatter at once (and in fact is semantically more associated with setting the locator rather than the formatter), so I think it's fine to keep it separate for now.
Antony

On Thu, Mar 5, 2020 at 4:03 AM Todd <[hidden email]> wrote:
Currently setting up the tick formatting on matplotlib requires you to import a formatter from the ticker module, create an instance of that formatter, then pass that to the axis.  This makes sense for complicated formatting.  However, there are some obvious cases where we can probably infer the type of formatting someone wants to do if we are just given the formatter content.  For example

   * '' is probably going to be the null formatter
   * A callable, besides a formatter instance, is probably going to be a function formatter
   * A sequence or numpy array is probably going to be an index or fixed formatter, depending on the locator
   * Any other string is probably going to be a format string formatter or string method formatter.

So I think we could allow the `set_major_formatter` and `set_minor_formatter` to take certain sorts of inputs and create the formatter automatically for the user, making such cases much, much easier.  Specifically, I propose the following inputs be accepted:

   * `None` sets it to the default formatter
   * A callable (besides a formatter instance) is set to be a FuncFormatter
   * An empty string, `''`, is set to be a NullFormatter
   * Any other string is a StrMethodFormatter
   * An abc.collections.Sequence subclass or numpy ndarray subclass is an IndexFormatter, unless the axis is using a FixedLocator in which case it is a FixedLocator.  We could restrict this to just lists and numpy arrays only.

Any thoughts?
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Todd
In reply to this post by Eric Firing

On Wed, Mar 4, 2020 at 11:02 PM Eric Firing <[hidden email]> wrote:
I'm very sympathetic to the goal of making smoother and simpler
interfaces, but I'm not yet convinced that this proposal is the way to
go.  An example of a case long ago where a proposal something like this
made a big improvement is the specification of a cmap kwarg: originally
it had to be a Colormap instance, but then it was changed to accept a
string.  That worked well because it was an extremely common situation,
and only one change in behavior was made--it essentially yielded
expected behavior right away.

Using custom formatters is much less common, I presume, and the new
behavior is not as simple as supplying a colormap name.

Eric

First, I think this is a bit of a  chicken and egg problem.  Doing this isn't that common because it requires you jump through more hoops than most plot customization does.  I don't have any hard evidence, but I would think something like adding degrees symbols to polar plots or units to any sort of plot would be a natural thing to do if it was easy.  I know I personally have held off on doing it for throw-away plots because the amount of boilerplate needed.

Second, there are other places in matplotlib where simpler inputs are allowed in place of more complicated ones where the inputs are relatively unambiguous.  For example Axes.legend doesn't require that you manually specify which objects you are assigning labels to, you can just provide a sequence of strings.  Similarly Axes.set_position can either accept a sequence of floats for a position or a Bbox.  And there are lots of places you can either provide a dict of properties instead of a more complicated property object, or set_ functions where you can provide a string label and matplotlib will handle the underlying text object for you, even when the corresponding get_ function returns a text object.

I don't think the expected behavior is very ambiguous here, and the implementation is very easy.

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Todd
In reply to this post by Antony Lee-3
On Thu, Mar 5, 2020 at 5:37 AM Antony Lee <[hidden email]> wrote:
I am sympathetic to the idea.  A much simpler rule, though, would be to *just* additionally accept callables.  New-style format string formatters can then be implemented by passing bound methods (`set_major_formatter("tick {}".format)` -- the bound method quietly ignores the second (index) argument), which also makes it explicit that we talking about {}-format, not %s-format.  Even `set_major_formatter("".format)` would already be much shorter to type than importing NullFormatter and using it.  In any case, we could always first implement support for callables, which already buys us all these cases, and defer further cases to later.
The only case not covered by callables/bound methods is FixedLocator, but this is already handled by set_x/yticks, and anyways (usually) involves setting both the locator and the formatter at once (and in fact is semantically more associated with setting the locator rather than the formatter), so I think it's fine to keep it separate for now.
Antony


I thought of that approach, but it seemed like it still requires some unnecessary boilerplate for what seemed to me to by fairly unambiguous situations.  And it also doesn't handle resetting the formatter to the default.

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Todd
In reply to this post by tcaswell
Okay, so then it would be `None` to reset, `''` for `NullFormatter`, a callable for `FuncFormatter`, and a string for `StrMethodFormatter`.  That avoids the complexity of determining what exactly constitutes a "sequence" for the purposes of IndexFormatter/FixedFormatter.

On Wed, Mar 4, 2020 at 10:15 PM Thomas Caswell <[hidden email]> wrote:
Interesting, I am weakly in favor of this.

I am normally very hesitant about adopting heuristics, but these seem well defined.  If we do this, we should drop the last rule as IndexFormatter is scheduled to be deprecated in in 3.3 and is a bit problematic in other ways.

I don't see any back-compatibility concerns (as none of those inputs work now).

Tom

On Wed, Mar 4, 2020 at 10:03 PM Todd <[hidden email]> wrote:
Currently setting up the tick formatting on matplotlib requires you to import a formatter from the ticker module, create an instance of that formatter, then pass that to the axis.  This makes sense for complicated formatting.  However, there are some obvious cases where we can probably infer the type of formatting someone wants to do if we are just given the formatter content.  For example

   * '' is probably going to be the null formatter
   * A callable, besides a formatter instance, is probably going to be a function formatter
   * A sequence or numpy array is probably going to be an index or fixed formatter, depending on the locator
   * Any other string is probably going to be a format string formatter or string method formatter.

So I think we could allow the `set_major_formatter` and `set_minor_formatter` to take certain sorts of inputs and create the formatter automatically for the user, making such cases much, much easier.  Specifically, I propose the following inputs be accepted:

   * `None` sets it to the default formatter
   * A callable (besides a formatter instance) is set to be a FuncFormatter
   * An empty string, `''`, is set to be a NullFormatter
   * Any other string is a StrMethodFormatter
   * An abc.collections.Sequence subclass or numpy ndarray subclass is an IndexFormatter, unless the axis is using a FixedLocator in which case it is a FixedLocator.  We could restrict this to just lists and numpy arrays only.

Any thoughts?
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel


--
Thomas Caswell
[hidden email]

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Antony Lee-3
In reply to this post by Todd
The point is that if we support callables, we'll already have all these cases supported, and while appending `.format` to your string *could* be considered boilerplate, it's already considerably shorter than `FuncFormatter` (or any of the others) + the import.  Finally this still doesn't preclude adding the other cases later.
Supporting None as default seems likely to confuse people who'd think it means NullFormatter...
Antony

On Thu, Mar 5, 2020 at 3:55 PM Todd <[hidden email]> wrote:
On Thu, Mar 5, 2020 at 5:37 AM Antony Lee <[hidden email]> wrote:
I am sympathetic to the idea.  A much simpler rule, though, would be to *just* additionally accept callables.  New-style format string formatters can then be implemented by passing bound methods (`set_major_formatter("tick {}".format)` -- the bound method quietly ignores the second (index) argument), which also makes it explicit that we talking about {}-format, not %s-format.  Even `set_major_formatter("".format)` would already be much shorter to type than importing NullFormatter and using it.  In any case, we could always first implement support for callables, which already buys us all these cases, and defer further cases to later.
The only case not covered by callables/bound methods is FixedLocator, but this is already handled by set_x/yticks, and anyways (usually) involves setting both the locator and the formatter at once (and in fact is semantically more associated with setting the locator rather than the formatter), so I think it's fine to keep it separate for now.
Antony


I thought of that approach, but it seemed like it still requires some unnecessary boilerplate for what seemed to me to by fairly unambiguous situations.  And it also doesn't handle resetting the formatter to the default.
_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Todd
In reply to this post by Todd
On Wed, Mar 4, 2020 at 10:03 PM Todd <[hidden email]> wrote:
Currently setting up the tick formatting on matplotlib requires you to import a formatter from the ticker module, create an instance of that formatter, then pass that to the axis.  This makes sense for complicated formatting.  However, there are some obvious cases where we can probably infer the type of formatting someone wants to do if we are just given the formatter content.  For example

   * '' is probably going to be the null formatter
   * A callable, besides a formatter instance, is probably going to be a function formatter
   * A sequence or numpy array is probably going to be an index or fixed formatter, depending on the locator
   * Any other string is probably going to be a format string formatter or string method formatter.

So I think we could allow the `set_major_formatter` and `set_minor_formatter` to take certain sorts of inputs and create the formatter automatically for the user, making such cases much, much easier.  Specifically, I propose the following inputs be accepted:

   * `None` sets it to the default formatter
   * A callable (besides a formatter instance) is set to be a FuncFormatter
   * An empty string, `''`, is set to be a NullFormatter
   * Any other string is a StrMethodFormatter
   * An abc.collections.Sequence subclass or numpy ndarray subclass is an IndexFormatter, unless the axis is using a FixedLocator in which case it is a FixedLocator.  We could restrict this to just lists and numpy arrays only.

Any thoughts?

Based on the input I have gotten so far, I have made a simplified version of the approach [1].  It only handles the cases for str and function (or rather callable, but I call it a function in the documentation).  These seem to handle most use-cases reasonably well.  As Antony pointed out, None is potentially confusing, and as Thomas pointed out IndexFormatter is deprecated.  That left only the empty NullFormatter (with an empty str), StrMethodFormatter (with any other str), and FuncFormatter (with a callable). 

Antony made a good case that we should keep the number of approaches as small as possible.  Since the NullFormatter is trivially handled with an empty str, and that is really what it is behind-the-scenes, that was an obvious one to cut.

Antony made the good case that any str could be handled with str.format.  I tried that approach initially, but the issue I ended up having is that, although it is obvious to experienced Python users, it isn't as obvious to newer users.  That would mean I would need to properly communicate this workaround to users in the documentation.  However, my attempts to do this ended up being longer, more complicated, and harder to understand than simply implementing the str case directly.  So I ended up keeping the str and function approaches.  Of course this decision is open to discussion.

I also updated the documentation, tests, and examples to explain these new features.  Please take a look and let me know what you think. 

One open issue is that I did not change any examples currently using any of these formatters, I only added the new approach. I think it might be good to change some of the simpler examples of using formatters to use this new feature in order to make formatters seem more approachable, but I haven't done that yet.


_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

tcaswell
It looks like something funny is going on with your branch (It looks like there are some extra rebased commits), but other than that it look like a good start.

Could you please open a PR so it can go through the normal code review process / have CI run?

Tom

On Mon, Mar 9, 2020 at 10:45 AM Todd <[hidden email]> wrote:
On Wed, Mar 4, 2020 at 10:03 PM Todd <[hidden email]> wrote:
Currently setting up the tick formatting on matplotlib requires you to import a formatter from the ticker module, create an instance of that formatter, then pass that to the axis.  This makes sense for complicated formatting.  However, there are some obvious cases where we can probably infer the type of formatting someone wants to do if we are just given the formatter content.  For example

   * '' is probably going to be the null formatter
   * A callable, besides a formatter instance, is probably going to be a function formatter
   * A sequence or numpy array is probably going to be an index or fixed formatter, depending on the locator
   * Any other string is probably going to be a format string formatter or string method formatter.

So I think we could allow the `set_major_formatter` and `set_minor_formatter` to take certain sorts of inputs and create the formatter automatically for the user, making such cases much, much easier.  Specifically, I propose the following inputs be accepted:

   * `None` sets it to the default formatter
   * A callable (besides a formatter instance) is set to be a FuncFormatter
   * An empty string, `''`, is set to be a NullFormatter
   * Any other string is a StrMethodFormatter
   * An abc.collections.Sequence subclass or numpy ndarray subclass is an IndexFormatter, unless the axis is using a FixedLocator in which case it is a FixedLocator.  We could restrict this to just lists and numpy arrays only.

Any thoughts?

Based on the input I have gotten so far, I have made a simplified version of the approach [1].  It only handles the cases for str and function (or rather callable, but I call it a function in the documentation).  These seem to handle most use-cases reasonably well.  As Antony pointed out, None is potentially confusing, and as Thomas pointed out IndexFormatter is deprecated.  That left only the empty NullFormatter (with an empty str), StrMethodFormatter (with any other str), and FuncFormatter (with a callable). 

Antony made a good case that we should keep the number of approaches as small as possible.  Since the NullFormatter is trivially handled with an empty str, and that is really what it is behind-the-scenes, that was an obvious one to cut.

Antony made the good case that any str could be handled with str.format.  I tried that approach initially, but the issue I ended up having is that, although it is obvious to experienced Python users, it isn't as obvious to newer users.  That would mean I would need to properly communicate this workaround to users in the documentation.  However, my attempts to do this ended up being longer, more complicated, and harder to understand than simply implementing the str case directly.  So I ended up keeping the str and function approaches.  Of course this decision is open to discussion.

I also updated the documentation, tests, and examples to explain these new features.  Please take a look and let me know what you think. 

One open issue is that I did not change any examples currently using any of these formatters, I only added the new approach. I think it might be good to change some of the simpler examples of using formatters to use this new feature in order to make formatters seem more approachable, but I haven't done that yet.

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel


--
Thomas Caswell
[hidden email]

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel
Reply | Threaded
Open this post in threaded view
|

Re: Easier tick formatters

Todd
The PR is number 16715 [1]


On Mon, Mar 9, 2020 at 2:16 PM Thomas Caswell <[hidden email]> wrote:
It looks like something funny is going on with your branch (It looks like there are some extra rebased commits), but other than that it look like a good start.

Could you please open a PR so it can go through the normal code review process / have CI run?

Tom

On Mon, Mar 9, 2020 at 10:45 AM Todd <[hidden email]> wrote:
On Wed, Mar 4, 2020 at 10:03 PM Todd <[hidden email]> wrote:
Currently setting up the tick formatting on matplotlib requires you to import a formatter from the ticker module, create an instance of that formatter, then pass that to the axis.  This makes sense for complicated formatting.  However, there are some obvious cases where we can probably infer the type of formatting someone wants to do if we are just given the formatter content.  For example

   * '' is probably going to be the null formatter
   * A callable, besides a formatter instance, is probably going to be a function formatter
   * A sequence or numpy array is probably going to be an index or fixed formatter, depending on the locator
   * Any other string is probably going to be a format string formatter or string method formatter.

So I think we could allow the `set_major_formatter` and `set_minor_formatter` to take certain sorts of inputs and create the formatter automatically for the user, making such cases much, much easier.  Specifically, I propose the following inputs be accepted:

   * `None` sets it to the default formatter
   * A callable (besides a formatter instance) is set to be a FuncFormatter
   * An empty string, `''`, is set to be a NullFormatter
   * Any other string is a StrMethodFormatter
   * An abc.collections.Sequence subclass or numpy ndarray subclass is an IndexFormatter, unless the axis is using a FixedLocator in which case it is a FixedLocator.  We could restrict this to just lists and numpy arrays only.

Any thoughts?

Based on the input I have gotten so far, I have made a simplified version of the approach [1].  It only handles the cases for str and function (or rather callable, but I call it a function in the documentation).  These seem to handle most use-cases reasonably well.  As Antony pointed out, None is potentially confusing, and as Thomas pointed out IndexFormatter is deprecated.  That left only the empty NullFormatter (with an empty str), StrMethodFormatter (with any other str), and FuncFormatter (with a callable). 

Antony made a good case that we should keep the number of approaches as small as possible.  Since the NullFormatter is trivially handled with an empty str, and that is really what it is behind-the-scenes, that was an obvious one to cut.

Antony made the good case that any str could be handled with str.format.  I tried that approach initially, but the issue I ended up having is that, although it is obvious to experienced Python users, it isn't as obvious to newer users.  That would mean I would need to properly communicate this workaround to users in the documentation.  However, my attempts to do this ended up being longer, more complicated, and harder to understand than simply implementing the str case directly.  So I ended up keeping the str and function approaches.  Of course this decision is open to discussion.

I also updated the documentation, tests, and examples to explain these new features.  Please take a look and let me know what you think. 

One open issue is that I did not change any examples currently using any of these formatters, I only added the new approach. I think it might be good to change some of the simpler examples of using formatters to use this new feature in order to make formatters seem more approachable, but I haven't done that yet.

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel


--
Thomas Caswell
[hidden email]

_______________________________________________
Matplotlib-devel mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-devel