tommikaikkonen / prettyprinter

Syntax-highlighting, declarative and composable pretty printer for Python 3.5+
https://prettyprinter.readthedocs.io
MIT License
336 stars 20 forks source link

Improve printing of "C namedtuples" #37

Closed anntzer closed 5 years ago

anntzer commented 5 years ago

Description

Some Python builtins, such as os.uname or time.strptime return a "C namedtuple" (per https://docs.python.org/3/c-api/tuple.html#struct-sequence-objects). prettyprinter's output for them is less than optimal:

from prettyprinter import cpprint as pp
import os, time
print(os.uname())
pp(os.uname())
print(time.strptime("2000", "%Y"))
pp(time.strptime("2000", "%Y"))

gives

posix.uname_result(sysname='Linux', nodename='PC-Bon-C101', release='4.20.6-200.fc29.x86_64', version='#1 SMP Thu Jan 31 15:50:43 UTC 2019', machine='x86_64')
posix.uname_result((
    'Linux',
    'PC-Bon-C101',
    '4.20.6-200.fc29.x86_64',
    '#1 SMP Thu Jan 31 15:50:43 UTC 2019',
    'x86_64'
))
time.struct_time(tm_year=2000, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=-1)
time.struct_time((2000, 1, 1, 0, 0, 0, 5, 1, -1))

One can detect whether a type is a "C-namedtuple" by checking that it is a tuple subclass with the additional fields n_fields, n_sequence_fields, and n_unnamed_fields. However, to the best of my knowledge, there is no simple API (at the Python-level) to list the field names in their order. One hack could be perhaps to build a new instance of the C-namedtuple by passing enough (i.e. n_fields) zeros to the constructor, then parsing the str() of the object...

tp = type(os.uname())
print(tp([0] * tp.n_fields))

gives

posix.uname_result(sysname=0, nodename=0, release=0, version=0, machine=0)

What I Did

See above.

tommikaikkonen commented 5 years ago

Opened up a PR for this https://github.com/tommikaikkonen/prettyprinter/pull/38