Skip to content

Commit 7bcea08

Browse files
committed
Add tests of ConfigParser with "..." with " or \ inside
These are cases where just removing the outer quotes without doing anything to the text inside does not give the correct result, and where keeping the quotes may be preferable, in that it was the long-standing behavior of `GitConfigParser`. That this was the long-standing behavior may justify bringing it back when the `"`-`"`-enclosed text contains such characters, but it does not justify preserving it indefinitely: it will still be better to parse the escape sequences, at least in the type case that all of them in a value's representation are well-formed.
1 parent c8e4aa0 commit 7bcea08

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[custom]
2+
hasnewline = "first\nsecond"
3+
hasbackslash = "foo\\bar"
4+
hasquote = "ab\"cd"
5+
hastrailingbackslash = "word\\"
6+
hasunrecognized = "p\qrs"
7+
hasunescapedquotes = "ab"cd"e"
8+
ordinary = "hello world"
9+
unquoted = good evening

test/test_config.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,26 @@ def test_config_with_quotes_with_whitespace_outside_value(self):
428428
cr = GitConfigParser(fixture_path("git_config_with_quotes_whitespace_outside"), read_only=True)
429429
self.assertEqual(cr.get("init", "defaultBranch"), "trunk")
430430

431+
def test_config_with_quotes_containing_escapes(self):
432+
"""For now just suppress quote removal. But it would be good to interpret most of these."""
433+
cr = GitConfigParser(fixture_path("git_config_with_quotes_escapes"), read_only=True)
434+
435+
# These can eventually be supported by substituting the represented character.
436+
self.assertEqual(cr.get("custom", "hasnewline"), R'"first\nsecond"')
437+
self.assertEqual(cr.get("custom", "hasbackslash"), R'"foo\\bar"')
438+
self.assertEqual(cr.get("custom", "hasquote"), R'"ab\"cd"')
439+
self.assertEqual(cr.get("custom", "hastrailingbackslash"), R'"word\\"')
440+
self.assertEqual(cr.get("custom", "hasunrecognized"), R'"p\qrs"')
441+
442+
# It is less obvious whether and what to eventually do with this.
443+
self.assertEqual(cr.get("custom", "hasunescapedquotes"), '"ab"cd"e"')
444+
445+
# Cases where quote removal is clearly safe should happen even after those.
446+
self.assertEqual(cr.get("custom", "ordinary"), "hello world")
447+
448+
# Cases without quotes should still parse correctly even after those, too.
449+
self.assertEqual(cr.get("custom", "unquoted"), "good evening")
450+
431451
def test_get_values_works_without_requiring_any_other_calls_first(self):
432452
file_obj = self._to_memcache(fixture_path("git_config_multiple"))
433453
cr = GitConfigParser(file_obj, read_only=True)

0 commit comments

Comments
 (0)