implement 'format-separator' option (#2737)
a global option, that servers as a workaround for shortcomings due to lack of a proper format string parser
This commit is contained in:
@@ -3710,6 +3710,20 @@ Description
|
|||||||
this cache.
|
this cache.
|
||||||
|
|
||||||
|
|
||||||
|
format-separator
|
||||||
|
----------------
|
||||||
|
Type
|
||||||
|
``string``
|
||||||
|
Default
|
||||||
|
``"/"``
|
||||||
|
Description
|
||||||
|
Character(s) used as argument separator in format string
|
||||||
|
`format specifiers <formatting.md#format-specifiers>`__.
|
||||||
|
|
||||||
|
For example, setting this option to ``"#"`` would allow a replacement
|
||||||
|
operation to be ``Rold#new#`` instead of the default ``Rold/new/``
|
||||||
|
|
||||||
|
|
||||||
signals-ignore
|
signals-ignore
|
||||||
--------------
|
--------------
|
||||||
Type
|
Type
|
||||||
|
|||||||
@@ -177,6 +177,12 @@ def main():
|
|||||||
extractor.modules = modules
|
extractor.modules = modules
|
||||||
extractor._module_iter = iter(modules)
|
extractor._module_iter = iter(modules)
|
||||||
|
|
||||||
|
# format string separator
|
||||||
|
separator = config.get((), "format-separator")
|
||||||
|
if separator:
|
||||||
|
from . import formatter
|
||||||
|
formatter._SEPARATOR = separator
|
||||||
|
|
||||||
# loglevels
|
# loglevels
|
||||||
output.configure_logging(args.loglevel)
|
output.configure_logging(args.loglevel)
|
||||||
if args.loglevel >= logging.ERROR:
|
if args.loglevel >= logging.ERROR:
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ def _build_format_func(format_spec, default):
|
|||||||
|
|
||||||
|
|
||||||
def _parse_optional(format_spec, default):
|
def _parse_optional(format_spec, default):
|
||||||
before, after, format_spec = format_spec.split("/", 2)
|
before, after, format_spec = format_spec.split(_SEPARATOR, 2)
|
||||||
before = before[1:]
|
before = before[1:]
|
||||||
fmt = _build_format_func(format_spec, default)
|
fmt = _build_format_func(format_spec, default)
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ def _parse_slice(format_spec, default):
|
|||||||
|
|
||||||
|
|
||||||
def _parse_maxlen(format_spec, default):
|
def _parse_maxlen(format_spec, default):
|
||||||
maxlen, replacement, format_spec = format_spec.split("/", 2)
|
maxlen, replacement, format_spec = format_spec.split(_SEPARATOR, 2)
|
||||||
maxlen = text.parse_int(maxlen[1:])
|
maxlen = text.parse_int(maxlen[1:])
|
||||||
fmt = _build_format_func(format_spec, default)
|
fmt = _build_format_func(format_spec, default)
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ def _parse_maxlen(format_spec, default):
|
|||||||
|
|
||||||
|
|
||||||
def _parse_join(format_spec, default):
|
def _parse_join(format_spec, default):
|
||||||
separator, _, format_spec = format_spec.partition("/")
|
separator, _, format_spec = format_spec.partition(_SEPARATOR)
|
||||||
separator = separator[1:]
|
separator = separator[1:]
|
||||||
fmt = _build_format_func(format_spec, default)
|
fmt = _build_format_func(format_spec, default)
|
||||||
|
|
||||||
@@ -305,7 +305,7 @@ def _parse_join(format_spec, default):
|
|||||||
|
|
||||||
|
|
||||||
def _parse_replace(format_spec, default):
|
def _parse_replace(format_spec, default):
|
||||||
old, new, format_spec = format_spec.split("/", 2)
|
old, new, format_spec = format_spec.split(_SEPARATOR, 2)
|
||||||
old = old[1:]
|
old = old[1:]
|
||||||
fmt = _build_format_func(format_spec, default)
|
fmt = _build_format_func(format_spec, default)
|
||||||
|
|
||||||
@@ -315,7 +315,7 @@ def _parse_replace(format_spec, default):
|
|||||||
|
|
||||||
|
|
||||||
def _parse_datetime(format_spec, default):
|
def _parse_datetime(format_spec, default):
|
||||||
dt_format, _, format_spec = format_spec.partition("/")
|
dt_format, _, format_spec = format_spec.partition(_SEPARATOR)
|
||||||
dt_format = dt_format[1:]
|
dt_format = dt_format[1:]
|
||||||
fmt = _build_format_func(format_spec, default)
|
fmt = _build_format_func(format_spec, default)
|
||||||
|
|
||||||
@@ -325,7 +325,7 @@ def _parse_datetime(format_spec, default):
|
|||||||
|
|
||||||
|
|
||||||
def _parse_offset(format_spec, default):
|
def _parse_offset(format_spec, default):
|
||||||
offset, _, format_spec = format_spec.partition("/")
|
offset, _, format_spec = format_spec.partition(_SEPARATOR)
|
||||||
offset = offset[1:]
|
offset = offset[1:]
|
||||||
fmt = _build_format_func(format_spec, default)
|
fmt = _build_format_func(format_spec, default)
|
||||||
|
|
||||||
@@ -363,6 +363,7 @@ class Literal():
|
|||||||
_literal = Literal()
|
_literal = Literal()
|
||||||
|
|
||||||
_CACHE = {}
|
_CACHE = {}
|
||||||
|
_SEPARATOR = "/"
|
||||||
_GLOBALS = {
|
_GLOBALS = {
|
||||||
"_env": lambda: os.environ,
|
"_env": lambda: os.environ,
|
||||||
"_lit": lambda: _literal,
|
"_lit": lambda: _literal,
|
||||||
|
|||||||
@@ -236,6 +236,26 @@ class TestFormatter(unittest.TestCase):
|
|||||||
# parse and format datetime
|
# parse and format datetime
|
||||||
self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z/%Y%m%d}", "20100101")
|
self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z/%Y%m%d}", "20100101")
|
||||||
|
|
||||||
|
def test_separator(self):
|
||||||
|
orig_separator = formatter._SEPARATOR
|
||||||
|
try:
|
||||||
|
formatter._SEPARATOR = "|"
|
||||||
|
self._run_test("{a:Rh|C|RE|e|RL|l|}", "Cello wOrld")
|
||||||
|
self._run_test("{d[b]!s:R1|Q|R2|A|R0|Y|}", "Y")
|
||||||
|
|
||||||
|
formatter._SEPARATOR = "##"
|
||||||
|
self._run_test("{l:J-##Rb##E##}", "a-E-c")
|
||||||
|
self._run_test("{l:J-##[1:-1]}", "-b-")
|
||||||
|
|
||||||
|
formatter._SEPARATOR = "\0"
|
||||||
|
self._run_test("{d[a]:?<\0>\0L1\0too long\0}", "<too long>")
|
||||||
|
self._run_test("{d[c]:?<\0>\0L5\0too long\0}", "")
|
||||||
|
|
||||||
|
formatter._SEPARATOR = "?"
|
||||||
|
self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z?%Y%m%d}", "20100101")
|
||||||
|
finally:
|
||||||
|
formatter._SEPARATOR = orig_separator
|
||||||
|
|
||||||
def test_globals_env(self):
|
def test_globals_env(self):
|
||||||
os.environ["FORMATTER_TEST"] = value = self.kwdict["a"]
|
os.environ["FORMATTER_TEST"] = value = self.kwdict["a"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user