[Python-3000] Substantial rewrite of PEP 3101
Talin
talin at acm.org
Mon Jun 4 18:34:47 CEST 2007
Eric V. Smith wrote:
> > Formatter Creation and Initialization
> >
> > The Formatter class takes a single initialization argument, 'flags':
> >
> > Formatter(flags=0)
> >
> > The 'flags' argument is used to control certain subtle behavioral
> > differences in formatting that would be cumbersome to change via
> > subclassing. The flags values are defined as static variables
> > in the "Formatter" class:
> >
> > Formatter.ALLOW_LEADING_UNDERSCORES
> >
> > By default, leading underscores are not allowed in
> identifier
> > lookups (getattr or getitem). Setting this flag will allow
> > this.
> >
> > Formatter.CHECK_UNUSED_POSITIONAL
> >
> > If this flag is set, the any positional arguments which are
> > supplied to the 'format' method but which are not used by
> > the format string will cause an error.
> >
> > Formatter.CHECK_UNUSED_NAME
> >
> > If this flag is set, the any named arguments which are
> > supplied to the 'format' method but which are not used by
> > the format string will cause an error.
>
> I'm not sure I'm wild about these flags which would have to be or'd
> together, as opposed to discrete parameters. I realize have a single
> flag field is likely more extensible, but my impression of the
> standard library is a move away from bitfield flags. Perhaps that's
> only in my own mind, though!
Making them separate fields is fine if that's easier.
Another possibility is to make them setter methods rather than
constructor params.
> Also, why put this in the base class at all? These could all be
> implemented in a derived class (or classes), which would leave the
> base class state-free and therefore without a constructor.
My reason for doing this is as follows.
Certain kinds of customizations are pretty easy to do via subclassing.
For example, supporting a default namespace takes only a few lines of
code in a subclass.
Other kinds of customization require replacing a much larger chunk of
code. Changing the "underscores" and "check-unused" behavior requires
overriding 'vformat', which means replacing the entire template string
parser. I figured that there would be a lot of people who might want
these features, but didn't want to rewrite all of vformat.
Now, some of this could be resolved by breaking up vformat into a set of
smaller, overridable functions which controlled these behaviors.
However, I didn't do this because I didn't want the PEP to micro-manage
the implementation of vformat - I wanted to leave you guys some leeway
as to design choices.
For example, I had thought perhaps to break out a separate method that
would just do the parsing of a replacement field (the part inside the
brackets) - so in other words, you'd have one function that recognizes
the start of a replacement field, which then calls a method which
consumes the contents of that field, and so on. You could also break
that up into two pieces, one which recognizes the field reference, and
one which recognizes the conversion string.
However, these various parsing functions aren't entirely isolated from
each other. The various parsers would need to pass the current parse
position (character iterator or whatever) and other state back and
forth. Exposing this requires codifying in the API a lot of the internal
state of parsing.
Also, the syntax defining the end of a replacement field is a mirror of
the syntax that starts one; And conversion specs can contain
replacement fields too. Which means that the various parsing methods
aren't entirely independent. (Although I think that in your earlier
proposal, the syntax for 'internal' replacement fields inside conversion
specifiers was always the same, regardless of the markup syntax chosen.)
What I wanted to avoid in the PEP was having to specify how all of these
different parts fit together and the exact nature of the parameters
being passed between them.
And I think that even if we do break up vformat this way, we still end
up with people having to replace a fairly substantial chunk of code in
order to change the behaviors represented by these flags.
> > Formatter Methods
> >
> > The methods of class Formatter are as follows:
> >
> > -- format(format_string, *args, **kwargs)
> > -- vformat(format_string, args, kwargs)
> > -- get_positional(args, index)
> > -- get_named(kwds, name)
> > -- format_field(value, conversion)
>
> I've started a sample implementation to test this API. For starters,
> I'm writing it in pure Python, but my intention is to use the code in
> the pep3101 sandbox once I have some tests written and we're happy
> with the API.
Cool.
-- Talin
More information about the Python-3000
mailing list