Skip to content

Simplify table column format definition? - #2898

Merged
mhvk merged 2 commits into
astropy:masterfrom
mhvk:column-format-string
Sep 3, 2014
Merged

mhvk merged 2 commits into
astropy:masterfrom
mhvk:column-format-string

Conversation

@mhvk

@mhvk mhvk commented Aug 27, 2014

Copy link
Copy Markdown
Contributor

Following discussion in #2896: Currently, column formats can be set by either giving a string or a function [1], with the string an old or new-style format, e.g., '%5.2f' or '{:5.2f}'. It would seem more logical if the user would not have to care how typesetting is done in python and could just give the actual format specifier (i.e., just '5.2f'). This would leave the string format very simple, equal to what one would guess with the most careless thought. It would also be easy to describe in the documentation, as it would just be equal to what needs to be passed in to the format function. Specifically, in pprint._auto_format_func, one would the format function would be defined as

lambda format_, val: format(val, format_)

instead of the current

lambda format_, val: format_.format(val)

If the above makes sense, I'm happy to turn this into a PR. @taldcroft?

[1] http://astropy.readthedocs.org/en/latest/table/construct_table.html#format-specifier

@mhvk mhvk added the table label Aug 27, 2014
@taldcroft

Copy link
Copy Markdown
Member

Would we retain back compatibility for both other formats? I do have code that sets the format.

@mhvk

mhvk commented Aug 27, 2014

Copy link
Copy Markdown
Contributor Author

I don't see an issue with retaining backwards compatibility, and especially the '%5.2f' format is something I can see that people would do naively too. I think we can easily keep those options and not slow down things much If in the non-callable path in _auto_format_func one were to do something like :

try:
    out = format(val.tolist(), format_)
except ValueError:
    try:
        out = format_.format(val.tolist())
     [etc]

@taldcroft

Copy link
Copy Markdown
Member

OK, as long as there is no possible ambiguity between the new simplified format and the previous ones, then I'd be good with going ahead with this.

@mhvk

mhvk commented Aug 27, 2014

Copy link
Copy Markdown
Contributor Author

@taldcroft - OK, this is now a PR. @hamogu - you may want to check whether this would take care of #2896 as well - I did try to update the documentation.

@hamogu

hamogu commented Aug 27, 2014

Copy link
Copy Markdown
Member

Yes, that extra example is exactly what I am looking for. I like the code change that saved a lot of {}: ,too.

Comment thread astropy/table/pprint.py Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this should be limited to ValueError? I'm always worried about some bizarre input that ends up raising a different exception in format(). So I think that here we are just checking for "this didn't work for whatever reason", try something else. But maybe you though it through and there is a reason.

@taldcroft

Copy link
Copy Markdown
Member

Looks like there are some bona fide test failures for Python 3. On visual inspection I can't see why the test should be failing.

@mhvk

mhvk commented Aug 28, 2014

Copy link
Copy Markdown
Contributor Author

Hmm, very strange that I don't get that locally. However, the underlying problem is clear (and hopefully solved with the updated PR): with a masked table and a format set, one tries to format np.ma.masked with a numerical format specifier:

import numpy as np
format(np.ma.masked, '4.3f')
# TypeError: non-empty format string passed to object.__format__

Indeed, this is a problem generally in astropy (it just escaped testing before... now lots of tests added):

from astropy.table import Table
data_rows = [(1, 2.0, 'x'),
             (4, 5.0, 'y'),
             (5, 8.2, 'z')]
t = Table(rows=data_rows, names=('a', 'b', 'c'), meta={'name': 'first table'}, masked=True)
t['b'].format = '{:7.3f}'
print(t)
# a     b     c 
#--- ------- ---
#  1   2.000   x
#  4   5.000   y
#  5   8.200   z
t['b'].mask[0] = True
print(t)
# ... ValueError: Unknown format code 'f' for object of type 'str'

@mhvk

mhvk commented Aug 28, 2014

Copy link
Copy Markdown
Contributor Author

@taldcroft - OK, travis passes now. But please do check again, since the new PR comes with somewhat more intrusive changes to ensure np.ma.masked is processed correctly.

@taldcroft

Copy link
Copy Markdown
Member

@mhvk - gotta run, will look at this later, but did you just fix #1026? That would be good.

@mhvk

mhvk commented Aug 28, 2014

Copy link
Copy Markdown
Contributor Author

Yes, this fixes #1026; the test cases I added are quite similar to the first example there.

Comment thread astropy/table/pprint.py Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a niggle, but it might be conceptually cleaner to make this a function defined inside of _auto_format_func. That would also provide a better context for the comment later about "everywhere convert val to Python object...".

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One other thing, there is a slight performance penalty to making this a function instead of just inlining the expression in a few places. It might be negligible on the scale of things, not sure. OTOH this is really in the very inner loop of printing a table.

@taldcroft

Copy link
Copy Markdown
Member

@mhvk - I've reviewed this and I don't see any logic problems. Somehow I feel like it might be possible to refactor the different cases into a single common basis for a cleaner code, but that's outside the scope of this PR. In any case I mostly just suggested adding comments so it's a bit easier to understand the flow. Other than that I'm good with this.

@taldcroft

Copy link
Copy Markdown
Member

And thanks for doing this, in particular picking up the long-standing #1026!

@taldcroft

Copy link
Copy Markdown
Member

Also there is the usual CHANGES.rst update, which in this case probably needs two entries, one for the new feature (added simpler way of specifying column format) and bug fix #1026.

@mhvk
mhvk force-pushed the column-format-string branch from e17ae06 to 3c96ad9 Compare August 29, 2014 19:05
… values.

Also refactored the string tests, and added regression test against formatting
of np.float32, etc.  Because masked values now are OK: [closes astropy#1026]
@mhvk
mhvk force-pushed the column-format-string branch from 3c96ad9 to e8af22e Compare August 29, 2014 19:06
@mhvk

mhvk commented Aug 29, 2014

Copy link
Copy Markdown
Contributor Author

@taldcroft - thanks for the comments. Like you, I did feel that the code could be refactored, so I now did that, by iterating over the possible string-based format functions. I also checked speeds, and the tolist() function call itself was most costly. So, I now only use that conversion if numpy <= 1.6 (hopefully, got that OK; travis will telll... [did add a test for it]).

All this means that it is probably wise to have another look...

@embray - this PR now combines a bug fix [#1026] with a new feature. Your call whether it is for 1.0 or 0.4.2 (it is possible to disentangle the changes, though a bit of a pain).

@taldcroft

Copy link
Copy Markdown
Member

@mhvk - Wow, this is a great improvement! Very clever with the generator function. I'm good to go with this.

@embray - if we can bend the rules just a bit and get this into 0.4.2 that would be nice. The enhancement part of this PR is strictly a back-compatible addition to the API. Of course one must confess that the bug being fixed has been around for a while and there have not been a flood of complaints...

@embray

embray commented Sep 2, 2014

Copy link
Copy Markdown
Member

I have no problem with it.

@taldcroft taldcroft added this to the v0.4.2 milestone Sep 2, 2014
@taldcroft

Copy link
Copy Markdown
Member

@mhvk - since this can go in 0.4.2 you need to update CHANGES.rst accordingly. In the 0.4.2 section there is something like "Other changes and additions", which is presumably where the format enhancement comment should go. @embray?

@embray

embray commented Sep 2, 2014

Copy link
Copy Markdown
Member

Sure.

@mhvk

mhvk commented Sep 3, 2014

Copy link
Copy Markdown
Contributor Author

@taldcroft, @embray - OK, I moved the descriptions in the changelog to 0.4.2. Will merge now.

mhvk added a commit that referenced this pull request Sep 3, 2014
Simplify table column format definition; fix printing of masked values for formatted columns
@mhvk
mhvk merged commit 6509dd4 into astropy:master Sep 3, 2014
@mhvk
mhvk deleted the column-format-string branch September 3, 2014 12:52
@embray

embray commented Sep 16, 2014

Copy link
Copy Markdown
Member

This is marked "affects-dev" and "affects-release". Only one of these should be used on an issue (for the way I'm using them to help organize issues). For now I'm going to assume the latter.

@embray embray removed the Affects-dev PRs and issues that do not impact an existing Astropy release label Sep 16, 2014
@embray

embray commented Sep 16, 2014

Copy link
Copy Markdown
Member

(To clarify, "affects-dev" should be read as "affects dev only"--that is, this is not an issue that applies to any released version of Astropy).

mhvk added a commit that referenced this pull request Sep 18, 2014
Simplify table column format definition; fix printing of masked values for formatted columns
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants