Repository navigation
Description
A caller who wants "Maria F." or "M. Ferreira" today has to join two calls, because render() writes a field only in full and initials() writes every field it is given as initials:
name = parse("Maria Santos Ferreira")
name.render("{given}") + " " + name.initials("{family}") # 'Maria F.'
name.render("{given} {family:initial}") # ValueError: Invalid format specifierThe glue is also wrong at the edges: it adds a stray space when one side is empty, which render()'s collapse (#254) would have removed. Basecamp's name_of_person gem ships these two views as familiar and abbreviated. Its first/last split is far simpler than ours, but the views themselves are reasonable things to want.
Proposal, in rule shape
When: a render() spec marks a field with the !i conversion, as in "{given} {family!i}".
Then: that field is written as the initials initials() gives for that one group, with the default delimiter . and separator , and the rest of the spec renders as it does now, collapse included.
Because: the initials view already settles which words initial and in what order (rules/R3, initials honor the fold; rules/R7, no initials in a script that writes none). One spec that mixes full fields with initials should reuse those answers, not create a second set of them.
- Except: only
given,middleandfamilytake!i, the three groupsinitials()reads.{title!i},{suffix!i},{nickname!i},{maiden!i}and the derived views ({surnames!i},{family_base!i}, ...) raiseValueErrornaming the three. R3 says titles, suffixes and nicknames contribute nothing, and a derived view that spans groups has no single group to initial."Dr. Juan Q. Xavier de la Vega III" "{title!i} {family}" → ValueError - Except: particles contribute nothing, as in R3.
"Juan de la Vega" "{given} {family!i}" → "Juan V." - Except: a script that writes no initials contributes nothing (R7), and the empty field collapses.
"김민준" "{given} {family!i}" → "민준" - Except: a folded family initials in its fold order (R3's
initials()ignores the folded-word ordering that thefamilyfield applies (der, y vangivesy. d. v.vs the facade'sy. v. d.) #408 clause)."Hassan, Mohamad Ahmad Ali" "{given} {family!i}" → "Mohamad A. A. H." (middle_as_family=True) "Maria Santos Ferreira" "{given} {family!i}" → "Maria S. F." (middle_as_family=True) "Maria Santos Ferreira" "{given} {family!i}" → "Maria F." (default) - Precedence:
!r,!sand!akeep Python's meaning. A format spec after the conversion applies to the initialled text ({family!i:>4}). - Accepted: a hyphenated word gives one initial, as in
initials()today ("Jean-Luc Picard","{given!i} {family}"→"J. Picard", not the French"J.-L. Picard"). That belongs to the initials view, not to this spec, and is a question of its own. - Accepted: the delimiter and separator are fixed. A caller who wants
"DH"keepsinitials("{given}{family}", delimiter="", separator="").
Open questions
- A one-word name.
parse("Smith")reads givenSmith, so"{given!i} {family}"gives"S."and the only name word is reduced to an initial.name_of_personreturns the first name whole when the last name is empty. Should!iskip a field when every other field the spec names is empty? Or is this a recipe note ("abbreviate the given name only when there is a family")? A rule that looks at other fields would be the first inrender()to do that. - Syntax.
!icomposes with format specs and leaves the field list alone. The alternatives are a format spec ({family:initial}, which takes over the field's padding and alignment) or derived keys ({family_initials}, no new syntax and listed in the KeyError message, but three more keys and nowhere to extend to).!iis the proposal. Is a one-letter conversion clear enough in the docs? - The default
str()and__format__. Is aParsedName.__format__that passes its spec torender()(sof"{name:{given} {family!i}}"works) in scope, or a separate question?
Done when
render()fills specs through astring.Formattersubclass whoseconvert_fieldhandlesi. The conversion needs the field's tokens, not its text, so the values passed in carry both.- A new rule beside R3 and R7 in
docs/design/rules/with the examples above, an index line, and a decisions entry for the syntax chosen. - A recipe doctest in
docs/usage.rst("Maria F.", "M. Ferreira") and a release-log bullet. - Tests: the field family
{given, middle, family} × !iand the refused fields parametrized together, plus each Except row.
Activity
derek73 commentedon Nov 6, 2026
A use case for this proposal that its "only
given,middleandfamilytake!i" exception rules out: the forms that Spanish and Catalan names, and Latin American names especially, initial in.A name with two surnames keeps the first (paternal) surname whole, because it is the one that identifies the person, and shortens the second, or drops it:
initials()givesJ. A. L. P.forJosep Antoni Lloret Palolunderparser_for(locales.ES), initialling the first surname too. The views these forms need already exist: rules/R11'ssurname1and rules/R10'ssurname2render in a spec today:So the first two forms would be
"{given} {middle!i} {surname1} {surname2!i}"and"{given!i} {middle!i} {surname1}", if!itooksurname2(andsurname1, for symmetry). The draft refuses them, with the reason "a derived view that spans groups has no single group to initial".surname1andsurname2don't span groups: each is one name unit of the family, which is what R11 and R10 exist to mark.Two things a clause for them would have to settle:
Lloret Palol, Josep Antonihassurname1'Lloret Palol' and an emptysurname2, and"{surname1} {surname2!i}"writesLloret Palolthere. Is the collapse enough, or should the docs warn that this form needs a name with no family comma?{surname2!i}onJuan García de la Vegashould follow R3 and giveV., as{family!i}does.The third form (
Lloret Palol, J. A.) needs nothing new:"{family}, {given!i} {middle!i}"already reaches it under the proposal as written.