[formatter] implement slicing strings as bytes (#4087)

prefixing a slice '[10:30]' with a lowercase b '[b10:30]' encodes
the string to bytes in filesystem encoding before applying the slice
This commit is contained in:
Mike Fährmann
2023-05-22 18:30:45 +02:00
parent 56b8b8cd36
commit 69865dcc05
3 changed files with 66 additions and 16 deletions

View File

@@ -9,6 +9,7 @@
"""String formatters"""
import os
import sys
import time
import string
import _string
@@ -255,7 +256,11 @@ def parse_field_name(field_name):
func = operator.itemgetter
try:
if ":" in key:
key = _slice(key)
if key[0] == "b":
func = _bytesgetter
key = _slice(key[1:])
else:
key = _slice(key)
else:
key = key.strip("\"'")
except TypeError:
@@ -276,6 +281,14 @@ def _slice(indices):
)
def _bytesgetter(slice, encoding=sys.getfilesystemencoding()):
def apply_slice_bytes(obj):
return obj.encode(encoding)[slice].decode(encoding, "ignore")
return apply_slice_bytes
def _build_format_func(format_spec, default):
if format_spec:
return _FORMAT_SPECIFIERS.get(
@@ -295,11 +308,20 @@ def _parse_optional(format_spec, default):
def _parse_slice(format_spec, default):
indices, _, format_spec = format_spec.partition("]")
slice = _slice(indices[1:])
fmt = _build_format_func(format_spec, default)
def apply_slice(obj):
return fmt(obj[slice])
if indices[1] == "b":
slice_bytes = _bytesgetter(_slice(indices[2:]))
def apply_slice(obj):
return fmt(slice_bytes(obj))
else:
slice = _slice(indices[1:])
def apply_slice(obj):
return fmt(obj[slice])
return apply_slice