[formatter] overload '.' operator

implement generic access of
* list items        (L[1]   -> L.1)
* dict vslues       (D[key] -> D.key)
* object attributes (O.attr -> O.attr)
in standard format strings
This commit is contained in:
Mike Fährmann
2026-01-11 17:49:55 +01:00
parent 084a6d73e0
commit a79a945494
2 changed files with 40 additions and 3 deletions

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2021-2025 Mike Fährmann
# Copyright 2021-2026 Mike Fährmann
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -298,7 +298,7 @@ def parse_field_name(field_name):
for is_attr, key in rest:
if is_attr:
func = operator.attrgetter
func = _attrgetter
else:
func = operator.itemgetter
try:
@@ -330,6 +330,22 @@ def _slice(indices):
)
def _attrgetter(key):
if key.isdecimal() or key[0] == "-":
try:
return operator.itemgetter(int(key))
except ValueError:
pass
def apply_key(obj):
try:
return obj[key]
except (TypeError, KeyError):
return getattr(obj, key)
return apply_key
def _bytesgetter(slice):
def apply_slice_bytes(obj):

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2021-2025 Mike Fährmann
# Copyright 2021-2026 Mike Fährmann
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
@@ -188,6 +188,27 @@ class TestFormatter(unittest.TestCase):
self._run_test("{d['a']}", "foo")
self._run_test('{d["a"]}', "foo")
def test_dot_index(self):
self._run_test("{l.1}" , "b")
self._run_test("{a.6}" , "w")
self._run_test("{a.99}" , "None")
self._run_test("{l.-1}" , "c")
self._run_test("{a.-7}" , "o")
self._run_test("{a.-0}" , "h") # same as a[0]
self._run_test("{a.-99}", "None")
def test_dot_access_dict(self):
self._run_test("{d.a}", "foo")
self._run_test("{d.d}", "None")
self._run_test("{a.d}", "None")
self._run_test("{L.0.age}", "42")
self._run_test("{L.-1.name.2}", "x")
self._run_test("{L.1:I}", self.kwdict["L"][1])
def test_dot_access_attr(self):
self._run_test("{t.real}", "1262304000")
self._run_test("{dt.year}", "2010")
def test_slice_str(self):
v = self.kwdict["a"]
self._run_test("{a[1:10]}" , v[1:10])