Plans for PrettyTable 0.6

4 views
Skip to first unread message

Luke Maurits

unread,
May 27, 2009, 6:21:10 AM5/27/09
to prettytable-devel
Hi list,

After yesterday's release of PrettyTable 0.5, it's time to get to work
on 0.6!

My plan for 0.6 is fairly straightforward: to add no new "features" as
such and just focus on making the API simpler, more consistent and
more Pythonic. This is in response to the recent rapid growth of
fiddly extra arguments in the printing / stringing methods, which have
left PrettyTable with something of an ugly or cluttered feeling.
Unfortunately, it is necessary to have all these fiddly options in
there in order to let everybody print the kinds of table they want,
but I strongly believe that it should not be necessary to expose users
to more of this complexity than necessary.

Here is my game plan to make PrettyTable a bit neater and friendlier,
it basically boils down to one simple change which has a lot of nice
follow on effects:

At the moment, some formatting related options - like alignments,
paddings, etc - can be set using a setter method and they will persist
through all subsequent calls to printt and friends. Other formatting
related options - like the "border" and "header" arguments - cannot be
set this way and they need to be included in the list of arguments to
each and every call of printt and friends.

In 0.6 this will change so that *every* formatting option can be set
with a setter method and then persist through subsequent calls to
printt etc. (of course you will still be able to override these on a
per-printt basis using method arguments). There are many reasons for
this:

* It is more consistent overall if all options behave the same way
than if some arbitrary subset can be set persistently and the rest
can't. Consistent APIs are easier to learn and use.

* If your program currently calls printt or a similar method on the
same table with the same formatting options in many different places,
being able to rewrite things so the options are set once in one place
will make your code shorter and easier to maintain - a simple "print
x" repeated many times looks nicer than many instances of "x.printt
(foo, bar, baz,...)", and if you ever decide to change your table
format you only have to do it once rather than copying and pasting a
long list of arguments all over your program.

* It will enable the introduction of a new "set_style" method. This
is the nearest thing to a new "feature" in 0.6.

The idea is that the most common/popular formats will be made very
easy to use through this new method. Suppose that, like some users,
you want your table formatted in a particular way so that it works
well with a command line program that expects plain columns of data,
or so it can be nicely imported into MS Word, etc. Instead of forcing
you to look up all the options to do with alignments and paddings and
borders, etc., in 0.6 I would like you to be able to do this:

x.set_style(MSWORD_FRIENDLY)
x.printt()

The set_style method will use the new setter functions - available now
for every formatting option - to set the alignments, paddings, borders
etc. for your particular use case and thus there is no need for you to
remember them all or know the intricacies of how they interact with
one another. All you have to remember is the variable name
MSWORD_FRIENDLY. I'm hoping that there can be, say, no greater than 5
variables like this which cover the most popular / common / useful
table styles, so that the majority of users will never have to learn
anything other than set_style and the days of having to painstakingly
set individual left and right paddings etc. will be over!

I will happily listen to suggestions and requests posted in reply to
this on which 5 or so pre-set styles you would most like to see in
0.6. Remember that the idea is that the pre-set styles should cater
to the most common anticipated usage cases. I'm happy to add an
MSWORD_FRIENDLY option, for instance, because millions of people use
MS Word. The same goes for a command line friendly columnising
option. I would hesitate to use up a pre-set style for any really
obscure or application specific formats, so keep this in mind when
making suggestions.

That's about it. The new setter functions will probably be written in
accordance with the "property" philosophy - see
http://docs.python.org/library/functions.html#property for details.
There will be other minor changes, not visible to the user, like using
decorators to reduce code duplication where possible, and perhaps
replacing the current ugly and ad-hoc "testing framework" with proper
unit tests.

As always I am very happy to listen to your comments and suggestions.
Please remember that I am not interested in adding new features for
0.6, I want to focus on getting the API "right", making it as easy and
clean as possible. New features *will* be welcome in 0.7! I might
start a separate thread on the -devel list for 0.7 feature suggestions
so that people can discuss and refine suggestions while the boring
tidy up work for 0.6 goes ahead.

As always, thanks for your interest in helping with the development of
PrettyTable.

Luke

Luke Maurits

unread,
May 30, 2009, 1:39:41 AM5/30/09
to prettytable-devel
Progress on 0.6 is coming along fairly nicely. Those of you who want
to see what things are like at the moment can check out a copy of the
SVN repository's "trunk" directory - or, if you don't have an SVN
client, use Google code's web SVN browser to just download the trunk
copy of prettytable.py. There's a Wiki page that will show you how to
use the new version at: http://code.google.com/p/prettytable/wiki/Tutorial06

There's just one final issue that I'm wrestling with before branching
trunk to 0.6 and tagging the first release candidate - how to handle
setting column alignment.

The alignments of the columns in a PrettyTable are stored internally
as a list of alignment strings ("l", "c" or "r"). If you have a table
with five columns and they're all centred, self._align (or just
self.align in <= 0.5) will be ["c", "c", "c", "c", "c"]. I think it
would be best if no reasonable changes to the alignment settings
require users to directly manipulate this list, because it's too easy
to make mistakes.

Now, in PrettyTable <= 0.5, there's been one alignment related method
- set_field_align, which takes as arguments a field name and an
alignment string ("l"," "c" or "r"). As of right now, in trunk, this
is the *only* remaining set_* method. Everything else that used to be
done with a setter method is now done with an attribute assignment,
thanks to the magic of property decorators. It would be nice if we
could get rid of set_field_align so that there were no setters at all
for maximum consistency, but I'm not sure how we could really do this.

Note that currently there is no way to set the alignment of *all*
columns to a common value with a single method call. If you have a
table with 5 centred columns, getting all columns left aligned
requires 5 separate calls to set_field_align. This is gross and there
should be a way to set all columns to the same alignment with a single
line of Python code. This *could* be done with an attribute
assignment, quite easily. But I'm not sure if I should do this or add
a set_aligns method that takes a single alignment string argument.
Doing it the first way is consistent with 0.6's overall feel of
"attribute assignments, not setter calls", but doing it the second way
makes alignment control as a whole consistent - you don't use one
method to set all alignments and another to set individual
alignments. It seems like whichever option I choose, we fall short of
complete API consistency.

Maybe I'm making too big a deal of this. Do any users feel strongly
about this issue, one way or the other?

How do people feel about this syntax:

x.align = "c" # To centre align all columns
x.align["Population"] = "r" # To right align the "Population"
column

I think this should be possible though a combination of using
__setattr__ to handle the first case and having an "alignment setting
storage" object with appropriate __setitem__ and __getitem__ methods,
but it feels like maybe this is going too far out of the way just to
achieve nice syntax.

If anybody has any input on this matter, feel free to reply.

Luke
Reply all
Reply to author
Forward
0 new messages