[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:
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user