Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion configargparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ def get_syntax_description(self):
See https://docs.python.org/3/library/configparser.html for details.

Note: INI file sections names are still treated as comments.
DEFAULT-only files, including serialize() output, are also supported.
"""
return msg

Expand All @@ -310,7 +311,7 @@ def parse(self, stream):

# convert to dict and remove INI section names
result = OrderedDict()
for section in config.sections():
for section in config.sections() or [configparser.DEFAULTSECT]:
for k, v in config[section].items():
multiLine2SingleLine = v.replace("\n", " ").replace("\r", " ")
# handle special case for lists
Expand Down
58 changes: 58 additions & 0 deletions tests/test_configargparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -4327,6 +4327,64 @@ def make_parser():
self.assertEqual(contents, expected_contents)


class TestConfigparserDefaultSection(TestCase):
def test_default_only_values(self):
parser = configargparse.ConfigparserConfigFileParser()
contents = (
"[DEFAULT]\nName = alice\nlabel = %(name)s\nempty =\n"
"items = ['a', 'b']\nmessage = first\n second\n"
)
self.assertEqual(
parser.parse(StringIO(contents)),
OrderedDict(
[
("name", "alice"),
("label", "alice"),
("empty", ""),
("items", ["a", "b"]),
("message", "first second"),
]
),
)

def test_serialization_round_trip(self):
parser = configargparse.ConfigparserConfigFileParser()
items = OrderedDict([("name", "alice"), ("items", ["a", "b"])])
self.assertEqual(parser.parse(StringIO(parser.serialize(items))), items)

def test_saved_config_round_trip(self):
parser = self.initParser(
config_file_parser_class=configargparse.ConfigparserConfigFileParser
)
parser.add_argument("--name")
parser.add_argument("--count", type=int)
expected = parser.parse_args(["--name", "alice", "--count", "3"])
with tempfile.TemporaryDirectory() as directory:
path = os.path.join(directory, "saved.ini")
parser.write_config_file(expected, [path])
with open(path) as stream:
contents = stream.read()
actual = parser.parse_args([], config_file_contents=contents)
self.assertEqual(actual, expected)

def test_named_sections_keep_default_overrides(self):
parser = configargparse.ConfigparserConfigFileParser()
contents = (
"[DEFAULT]\nname = default\nshared = value\n"
"[first]\nname = alice\n[first_extra]\nname = bob\n"
)
self.assertEqual(
parser.parse(StringIO(contents)),
OrderedDict([("name", "bob"), ("shared", "value")]),
)

def test_empty_file(self):
parser = configargparse.ConfigparserConfigFileParser()
for contents in ("", "[DEFAULT]\n"):
with self.subTest(contents=contents):
self.assertEqual(parser.parse(StringIO(contents)), OrderedDict())


################################################################################
# since configargparse should work as a drop-in replacement for argparse
# in all situations, run argparse unittests on configargparse by modifying
Expand Down