summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Dennis <rdennis@gmail.com>2014-04-11 00:23:32 -0400
committerRob Dennis <rdennis@gmail.com>2014-04-11 00:23:32 -0400
commit6ae299fdabcf177e7f6176af34f43dbb067ddf1a (patch)
treec22a8481535bb5bfeb7b5c83dd10ce7d17031a44
parent54a2572fb9d6c9b1f63585938ad246ddada49982 (diff)
parenta7d62f8e08bf107ad378801134db8942ecaf5d49 (diff)
downloadconfigobj-git-6ae299fdabcf177e7f6176af34f43dbb067ddf1a.tar.gz
Merge pull request #54 from robdennis/release
Release 5.0.4
-rw-r--r--README.md2
-rw-r--r--_version.py2
-rw-r--r--configobj.py2
-rw-r--r--docs/conf.py4
-rw-r--r--docs/configobj.rst11
-rw-r--r--setup.py4
-rw-r--r--test_configobj.py30
-rw-r--r--tests/test_configobj.py326
8 files changed, 249 insertions, 132 deletions
diff --git a/README.md b/README.md
index 400e82e..84d87fa 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Found at [readthedocs](http://configobj.readthedocs.org/)
Status
=========
-This project has is now maintained by [Eli Courtwright](https://github.com/EliAndrewC) and [Rob Dennis](https://github.com/robdennis) with the blessing of original creator [Michael Foord](http://www.voidspace.org.uk/) and the most recent release is version *5.0.3* (view [changelog](http://configobj.readthedocs.org/en/v5.0.3/configobj.html#version-5-0-3)).
+This project has is now maintained by [Eli Courtwright](https://github.com/EliAndrewC) and [Rob Dennis](https://github.com/robdennis) with the blessing of original creator [Michael Foord](http://www.voidspace.org.uk/) and the most recent release is version *5.0.4* (view [changelog](http://configobj.readthedocs.org/en/latest/configobj.html#version-5-0-4)).
For long time ConfigObj users, the biggest change is in the officially supported python versions:
- 2.6
diff --git a/_version.py b/_version.py
index 245a3aa..742c20e 100644
--- a/_version.py
+++ b/_version.py
@@ -1 +1 @@
-__version__ = '5.0.3' \ No newline at end of file
+__version__ = '5.0.4' \ No newline at end of file
diff --git a/configobj.py b/configobj.py
index 8ad7c8f..d730a13 100644
--- a/configobj.py
+++ b/configobj.py
@@ -1234,7 +1234,7 @@ class ConfigObj(Section):
self.filename = infile
if os.path.isfile(infile):
with open(infile, 'rb') as h:
- content = h.read() or []
+ content = h.readlines() or []
elif self.file_error:
# raise an error if the file doesn't exist
raise IOError('Config file not found: "%s".' % self.filename)
diff --git a/docs/conf.py b/docs/conf.py
index b6f83e1..1e4f78c 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -12,8 +12,6 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
-from _version import __version__
-
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
@@ -52,7 +50,7 @@ copyright = u'2014, Michael Foord, Nicola Larosa, Rob Dennis, Eli Courtwright'
# built documents.
#
# The full version, including alpha/beta/rc tags.
-release = __version__
+release = '5.0.4'
# The short X.Y version.
version = '.'.join(release.split('.')[:2])
diff --git a/docs/configobj.rst b/docs/configobj.rst
index 763fee2..445d694 100644
--- a/docs/configobj.rst
+++ b/docs/configobj.rst
@@ -8,7 +8,7 @@
----------------------------------------
:Authors: Michael Foord, Nicola Larosa, Rob Dennis, Eli Courtwright
-:Version: ConfigObj 5.0.3
+:Version: ConfigObj 5.0.4
:Date: 2014/02/08
:PyPI Entry: `ConfigObj on PyPI <http://pypi.python.org/pypi/configobj/>`_
:Homepage: `Github Page`_
@@ -64,7 +64,7 @@ For support and bug reports please use the ConfigObj `Github Page`_.
Downloading
===========
-The current version is **5.0.3**, dated 4th April 2014. ConfigObj 5 is
+The current version is **5.0.4**, dated 11th April 2014. ConfigObj 5 is
stable and mature. We still expect to pick up a few bugs along the way though, particularly with respect to Python 3 compatibility [#]_.
We recommend downloading and installing using pip:
@@ -895,7 +895,7 @@ newlines
When a config file is read, ConfigObj records the type of newline separators in the
file and uses this separator when writing. It defaults to ``None``, and ConfigObj
-uses the system default (``os.sep``) if write is called without newlines having
+uses the system default (``os.linesep``) if write is called without newlines having
been set.
@@ -2383,6 +2383,11 @@ CHANGELOG
This is an abbreviated changelog showing the major releases up to version 4.
From version 4 it lists all releases and changes.
+2014/04/11 - Version 5.0.4
+--------------------------
+* BUGFIX: correcting that the code path fixed in 5.0.3 didn't cover reading in
+ config files
+
2014/04/04 - Version 5.0.3
--------------------------
* BUGFIX: not handling unicode encoding well, especially with respect to writing out files
diff --git a/setup.py b/setup.py
index 6825606..ec6d7a3 100644
--- a/setup.py
+++ b/setup.py
@@ -51,6 +51,8 @@ It has lots of other features though :
* The order of keys/sections is preserved
* Powerful ``unrepr`` mode for storing/retrieving Python data-types
+| Release 5.0.4 corrects a unicode-bug that still existed in reading files after
+| fixing lists of string in 5.0.3
| Release 5.0.3 corrects errors related to the incorrectly handling unicode
| encoding and writing out files
| Release 5.0.2 adds a specific error message when trying to install on
@@ -90,7 +92,7 @@ KEYWORDS = "config, ini, dictionary, application, admin, sysadmin, configuration
setup(name=NAME,
version=VERSION,
- install_requires=['six==1.5.2'],
+ install_requires=['six'],
description=DESCRIPTION,
long_description=LONG_DESCRIPTION,
author=AUTHOR,
diff --git a/test_configobj.py b/test_configobj.py
index 49ebd78..2133a7d 100644
--- a/test_configobj.py
+++ b/test_configobj.py
@@ -487,36 +487,6 @@ def _test_errors():
"""
-def _test_unrepr_comments():
- """
- >>> config = '''
- ... # initial comments
- ... # with two lines
- ... key = "value"
- ... # section comment
- ... [section] # inline section comment
- ... # key comment
- ... key = "value"
- ... # final comment
- ... # with two lines
- ... '''.splitlines()
- >>> c = ConfigObj(config, unrepr=True)
- >>> c == { 'key': 'value',
- ... 'section': { 'key': 'value'}}
- 1
- >>> c.initial_comment == ['', '# initial comments', '# with two lines']
- 1
- >>> c.comments == {'section': ['# section comment'], 'key': []}
- 1
- >>> c.inline_comments == {'section': '# inline section comment', 'key': ''}
- 1
- >>> c['section'].comments == { 'key': ['# key comment']}
- 1
- >>> c.final_comment == ['# final comment', '# with two lines']
- 1
- """
-
-
def _test_validate_with_copy_and_many():
"""
>>> spec = '''
diff --git a/tests/test_configobj.py b/tests/test_configobj.py
index 98210f1..c37bd73 100644
--- a/tests/test_configobj.py
+++ b/tests/test_configobj.py
@@ -1,5 +1,8 @@
# coding=utf-8
+from __future__ import unicode_literals
import os
+import re
+
from codecs import BOM_UTF8
from warnings import catch_warnings
from tempfile import NamedTemporaryFile
@@ -12,6 +15,72 @@ from configobj import ConfigObj, flatten_errors, ReloadError, DuplicateError, Mi
from validate import Validator, VdtValueTooSmallError
+def cfg_lines(config_string_representation):
+ """
+ :param config_string_representation: string representation of a config
+ file (typically a triple-quoted string)
+ :type config_string_representation: str or unicode
+ :return: a list of lines of that config. Whitespace on the left will be
+ trimmed based on the indentation level to make it a bit saner to assert
+ content of a particular line
+ :rtype: str or unicode
+ """
+ lines = config_string_representation.splitlines()
+
+ for idx, line in enumerate(lines):
+ if line.strip():
+ line_no_with_content = idx
+ break
+ else:
+ raise ValueError('no content in provided config file: '
+ '{!r}'.format(config_string_representation))
+
+ first_content = lines[line_no_with_content]
+ if isinstance(first_content, six.binary_type):
+ first_content = first_content.decode('utf-8')
+ ws_chars = len(re.search('^(\s*)', first_content).group(1))
+
+ def yield_stringified_line():
+ for line in lines:
+ if isinstance(line, six.binary_type):
+ yield line.decode('utf-8')
+ else:
+ yield line
+
+
+ return [re.sub('^\s{0,%s}' % ws_chars, '', line).encode('utf-8')
+ for line in yield_stringified_line()]
+
+
+@pytest.fixture
+def cfg_contents(request):
+
+ def make_file_with_contents_and_return_name(config_string_representation):
+ """
+ :param config_string_representation: string representation of a config
+ file (typically a triple-quoted string)
+ :type config_string_representation: str or unicode
+ :return: a list of lines of that config. Whitespace on the left will be
+ trimmed based on the indentation level to make it a bit saner to assert
+ content of a particular line
+ :rtype: basestring
+ """
+
+ lines = cfg_lines(config_string_representation)
+
+ with NamedTemporaryFile(delete=False, mode='wb') as cfg_file:
+ for line in lines:
+ if isinstance(line, six.binary_type):
+ cfg_file.write(line + os.linesep.encode('utf-8'))
+ else:
+ cfg_file.write((line + os.linesep).encode('utf-8'))
+ request.addfinalizer(lambda : os.unlink(cfg_file.name))
+
+ return cfg_file.name
+
+ return make_file_with_contents_and_return_name
+
+
def test_order_preserved():
c = ConfigObj()
c['a'] = 1
@@ -75,8 +144,8 @@ def test_with_default():
c.pop('c')
-def test_interpolation_with_section_names():
- cfg = """
+def test_interpolation_with_section_names(cfg_contents):
+ cfg = cfg_contents("""
item1 = 1234
[section]
[[item1]]
@@ -85,7 +154,7 @@ item1 = 1234
[[[item1]]]
why = would you do this?
[[other-subsection]]
- item2 = '$item1'""".splitlines()
+ item2 = '$item1'""")
c = ConfigObj(cfg, interpolation='Template')
# This raises an exception in 4.7.1 and earlier due to the section
@@ -103,11 +172,17 @@ def test_interoplation_repr():
class TestEncoding(object):
+ @pytest.fixture
+ def ant_cfg(self):
+ return """
+ [tags]
+ [[bug]]
+ translated = \U0001f41c
+ """
+
#issue #18
- def test_unicode_conversion_when_encoding_is_set(self):
- cfg = """
- test = some string
- """.splitlines()
+ def test_unicode_conversion_when_encoding_is_set(self, cfg_contents):
+ cfg = cfg_contents(b"test = some string")
c = ConfigObj(cfg, encoding='utf8')
@@ -119,10 +194,8 @@ class TestEncoding(object):
#issue #18
- def test_no_unicode_conversion_when_encoding_is_omitted(self):
- cfg = """
- test = some string
- """.splitlines()
+ def test_no_unicode_conversion_when_encoding_is_omitted(self, cfg_contents):
+ cfg = cfg_contents(b"test = some string")
c = ConfigObj(cfg)
if six.PY2:
@@ -132,15 +205,36 @@ class TestEncoding(object):
assert isinstance(c['test'], str)
#issue #44
- def test_that_encoding_argument_is_used_to_decode(self):
+ def test_that_encoding_using_list_of_strings(self):
cfg = [b'test = \xf0\x9f\x90\x9c']
c = ConfigObj(cfg, encoding='utf8')
- assert isinstance(c['test'], six.text_type)
+ if six.PY2:
+ assert isinstance(c['test'], unicode)
+ assert not isinstance(c['test'], str)
+ else:
+ assert isinstance(c['test'], str)
+
#TODO: this can be made more explicit if we switch to unicode_literals
assert c['test'] == b'\xf0\x9f\x90\x9c'.decode('utf8')
+ #issue #44
+ def test_encoding_in_subsections(self, ant_cfg, cfg_contents):
+ c = cfg_contents(ant_cfg)
+ cfg = ConfigObj(c, encoding='utf-8')
+
+ assert isinstance(cfg['tags']['bug']['translated'], six.text_type)
+
+ #issue #44
+ def test_encoding_in_config_files(self, request, ant_cfg):
+ # the cfg_contents fixture is doing this too, but be explicit
+ with NamedTemporaryFile(delete=False, mode='wb') as cfg_file:
+ cfg_file.write(ant_cfg.encode('utf-8'))
+ request.addfinalizer(lambda : os.unlink(cfg_file.name))
+
+ cfg = ConfigObj(cfg_file.name, encoding='utf-8')
+ assert isinstance(cfg['tags']['bug']['translated'], six.text_type)
@pytest.fixture
def testconfig1():
@@ -196,10 +290,10 @@ def testconfig2():
@pytest.fixture
def testconfig6():
return b'''
- name1 = """ a single line value """ # comment
- name2 = \''' another single line value \''' # comment
- name3 = """ a single line value """
- name4 = \''' another single line value \'''
+ name1 = """ a single line value """ # comment
+ name2 = \''' another single line value \''' # comment
+ name3 = """ a single line value """
+ name4 = \''' another single line value \'''
[ "multi section" ]
name1 = """
Well, this is a
@@ -221,30 +315,30 @@ def testconfig6():
@pytest.fixture
-def a(testconfig1):
+def a(testconfig1, cfg_contents):
"""
also copied from main doc tests
"""
- return ConfigObj(testconfig1.splitlines(), raise_errors=True)
+ return ConfigObj(cfg_contents(testconfig1), raise_errors=True)
@pytest.fixture
-def b(testconfig2):
+def b(testconfig2, cfg_contents):
"""
also copied from main doc tests
"""
- return ConfigObj(testconfig2.splitlines(), raise_errors=True)
+ return ConfigObj(cfg_contents(testconfig2), raise_errors=True)
@pytest.fixture
-def i(testconfig6):
+def i(testconfig6, cfg_contents):
"""
also copied from main doc tests
"""
- return ConfigObj(testconfig6.splitlines(), raise_errors=True)
+ return ConfigObj(cfg_contents(testconfig6), raise_errors=True)
-def test_configobj_dict_representation(a, b):
+def test_configobj_dict_representation(a, b, cfg_contents):
assert a.depth == 0
assert a == {
@@ -293,10 +387,10 @@ def test_configobj_dict_representation(a, b):
},
}
- t = '''
+ t = cfg_lines("""
'a' = b # !"$%^&*(),::;'@~#= 33
"b" = b #= 6, 33
-''' .split('\n')
+ """)
t2 = ConfigObj(t)
assert t2 == {'a': 'b', 'b': 'b'}
t2.inline_comments['b'] = ''
@@ -311,7 +405,7 @@ def test_behavior_when_list_values_is_false():
key3 = "double quotes"
key4 = "list", 'with', several, "quotes"
'''
- cfg = ConfigObj(c.splitlines(), list_values=False)
+ cfg = ConfigObj(cfg_lines(c), list_values=False)
assert cfg == {
'key1': 'no quotes',
'key2': "'single quotes'",
@@ -334,8 +428,8 @@ def test_behavior_when_list_values_is_false():
]
-def test_flatten_errors(val):
- config = '''
+def test_flatten_errors(val, cfg_contents):
+ config = cfg_contents("""
test1=40
test2=hello
test3=3
@@ -350,8 +444,8 @@ def test_flatten_errors(val):
test2=hello
test3=3
test4=5.0
- '''.split('\n')
- configspec = '''
+ """)
+ configspec = cfg_contents("""
test1= integer(30,50)
test2= string
test3=integer
@@ -366,7 +460,7 @@ def test_flatten_errors(val):
test2=string
test3=integer
test4=float(6.0)
- '''.split('\n')
+ """)
c1 = ConfigObj(config, configspec=configspec)
res = c1.validate(val)
assert flatten_errors(c1, res) == [([], 'test4', False), (['section'], 'test4', False), (['section', 'sub section'], 'test4', False)]
@@ -395,6 +489,8 @@ def test_unicode_handling():
# final comment2
'''
+ # needing to keep line endings means this isn't a good candidate
+ # for the cfg_lines utility method
u = u_base.encode('utf_8').splitlines(True)
u[0] = BOM_UTF8 + u[0]
uc = ConfigObj(u)
@@ -483,12 +579,12 @@ class TestWritingConfigs(object):
class TestUnrepr(object):
def test_in_reading(self):
- config_to_be_unreprd = '''
+ config_to_be_unreprd = cfg_lines("""
key1 = (1, 2, 3) # comment
key2 = True
key3 = 'a string'
key4 = [1, 2, 3, 'a mixed list']
- '''.splitlines()
+ """)
cfg = ConfigObj(config_to_be_unreprd, unrepr=True)
assert cfg == {
'key1': (1, 2, 3),
@@ -499,11 +595,12 @@ class TestUnrepr(object):
assert cfg == ConfigObj(cfg.write(), unrepr=True)
- def test_in_multiline_values(self):
- config_with_multiline_value = '''k = \"""{
-'k1': 3,
-'k2': 6.0}\"""
-'''.splitlines()
+ def test_in_multiline_values(self, cfg_contents):
+ config_with_multiline_value = cfg_contents('''
+ k = \"""{
+ 'k1': 3,
+ 'k2': 6.0}\"""
+ ''')
cfg = ConfigObj(config_with_multiline_value, unrepr=True)
assert cfg == {'k': {'k1': 3, 'k2': 6.0}}
@@ -596,24 +693,30 @@ class TestSectionBehavior(object):
assert n == a
assert n is not a
- def test_merging(self):
- config_with_subsection = '''[section1]
- option1 = True
- [[subsection]]
- more_options = False
- # end of file'''.splitlines()
- config_that_overwrites_parameter = '''# File is user.ini
- [section1]
- option1 = False
- # end of file'''.splitlines()
+ def test_merging(self, cfg_contents):
+ config_with_subsection = cfg_contents("""
+ [section1]
+ option1 = True
+ [[subsection]]
+ more_options = False
+ # end of file
+ """)
+ config_that_overwrites_parameter = cfg_contents("""
+ # File is user.ini
+ [section1]
+ option1 = False
+ # end of file
+ """)
c1 = ConfigObj(config_that_overwrites_parameter)
c2 = ConfigObj(config_with_subsection)
c2.merge(c1)
assert c2.dict() == {'section1': {'option1': 'False', 'subsection': {'more_options': 'False'}}}
- def test_walking_with_in_place_updates(self):
- config = '''[XXXXsection]
- XXXXkey = XXXXvalue'''.splitlines()
+ def test_walking_with_in_place_updates(self, cfg_contents):
+ config = cfg_contents("""
+ [XXXXsection]
+ XXXXkey = XXXXvalue
+ """)
cfg = ConfigObj(config)
assert cfg.dict() == {'XXXXsection': {'XXXXkey': 'XXXXvalue'}}
def transform(section, key):
@@ -715,14 +818,14 @@ class TestReloading(object):
assert str(excinfo.value) == 'reload failed, filename is not set.'
def test_reloading_with_an_actual_file(self, request,
- reloadable_cfg_content):
+ reloadable_cfg_content,
+ cfg_contents):
- # with open('temp', 'w') as cfg_file:
- with NamedTemporaryFile(delete=False, mode='w') as cfg_file:
- cfg_file.write(reloadable_cfg_content)
+ with NamedTemporaryFile(delete=False, mode='wb') as cfg_file:
+ cfg_file.write(reloadable_cfg_content.encode('utf-8'))
request.addfinalizer(lambda : os.unlink(cfg_file.name))
- configspec = '''
+ configspec = cfg_contents("""
test1= integer(30,50)
test2= string
test3=integer
@@ -742,7 +845,7 @@ class TestReloading(object):
test2=string
test3=integer
test4=float(4.5)
- '''.splitlines()
+ """)
cfg = ConfigObj(cfg_file.name, configspec=configspec)
cfg.configspec['test1'] = 'integer(50,60)'
@@ -813,7 +916,7 @@ class TestInterpolation(object):
return cfg
@pytest.fixture
- def template_cfg(self):
+ def template_cfg(self, cfg_contents):
interp_cfg = '''
[DEFAULT]
keyword1 = value1
@@ -841,7 +944,7 @@ class TestInterpolation(object):
[[[ sub-sub-section ]]]
convoluted = "$bar + $baz + $quux + $bar"
'''
- return ConfigObj(interp_cfg.splitlines(), interpolation='Template')
+ return ConfigObj(cfg_contents(interp_cfg), interpolation='Template')
def test_interpolation(self, config_parser_cfg):
test_section = config_parser_cfg['section']
@@ -932,23 +1035,23 @@ class TestValues(object):
Tests specifics about behaviors with types of values
"""
@pytest.fixture
- def testconfig3(self):
- return '''
- a = ,
- b = test,
- c = test1, test2 , test3
- d = test1, test2, test3,
- '''.splitlines()
-
- def test_empty_values(self):
- cfg_with_empty = '''
+ def testconfig3(self, cfg_contents):
+ return cfg_contents("""
+ a = ,
+ b = test,
+ c = test1, test2 , test3
+ d = test1, test2, test3,
+ """)
+
+ def test_empty_values(self, cfg_contents):
+ cfg_with_empty = cfg_contents("""
k =
k2 =# comment test
val = test
val2 = ,
val3 = 1,
val4 = 1, 2
- val5 = 1, 2, '''.splitlines()
+ val5 = 1, 2, """)
cwe = ConfigObj(cfg_with_empty)
# see a comma? it's a list
assert cwe == {'k': '', 'k2': '', 'val': 'test', 'val2': [],
@@ -1014,27 +1117,39 @@ def test_creating_with_a_dictionary():
assert dictionary_cfg_content is not cfg.dict()
-def test_multiline_comments(i):
- assert i == {
- 'name4': ' another single line value ',
- 'multi section': {
- 'name4': '\n Well, this is a\n multiline '
- 'value\n ',
- 'name2': '\n Well, this is a\n multiline '
- 'value\n ',
- 'name3': '\n Well, this is a\n multiline '
- 'value\n ',
- 'name1': '\n Well, this is a\n multiline '
- 'value\n ',
- },
- 'name2': ' another single line value ',
- 'name3': ' a single line value ',
- 'name1': ' a single line value ',
- }
-
-
class TestComments(object):
- def test_starting_and_ending_comments(self, a, testconfig1):
+ @pytest.fixture
+ def comment_filled_cfg(self, cfg_contents):
+ return cfg_contents("""
+ # initial comments
+ # with two lines
+ key = "value"
+ # section comment
+ [section] # inline section comment
+ # key comment
+ key = "value"
+
+ # final comment
+ # with two lines"""
+ )
+
+ def test_multiline_comments(self, i):
+
+ expected_multiline_value = '\nWell, this is a\nmultiline value\n'
+ assert i == {
+ 'name4': ' another single line value ',
+ 'multi section': {
+ 'name4': expected_multiline_value,
+ 'name2': expected_multiline_value,
+ 'name3': expected_multiline_value,
+ 'name1': expected_multiline_value,
+ },
+ 'name2': ' another single line value ',
+ 'name3': ' a single line value ',
+ 'name1': ' a single line value ',
+ }
+
+ def test_starting_and_ending_comments(self, a, testconfig1, cfg_contents):
filename = a.filename
a.filename = None
@@ -1061,6 +1176,33 @@ class TestComments(object):
c.inline_comments['foo'] = 'Nice bar'
assert c.write() == ['foo = bar # Nice bar']
+ def test_unrepr_comments(self, comment_filled_cfg):
+ c = ConfigObj(comment_filled_cfg, unrepr=True)
+ assert c == { 'key': 'value', 'section': { 'key': 'value'}}
+ assert c.initial_comment == [
+ '', '# initial comments', '# with two lines'
+ ]
+ assert c.comments == {'section': ['# section comment'], 'key': []}
+ assert c.inline_comments == {
+ 'section': '# inline section comment', 'key': ''
+ }
+ assert c['section'].comments == { 'key': ['# key comment']}
+ assert c.final_comment == ['', '# final comment', '# with two lines']
+
+ def test_comments(self, comment_filled_cfg):
+ c = ConfigObj(comment_filled_cfg)
+ assert c == { 'key': 'value', 'section': { 'key': 'value'}}
+ assert c.initial_comment == [
+ '', '# initial comments', '# with two lines'
+ ]
+ assert c.comments == {'section': ['# section comment'], 'key': []}
+ assert c.inline_comments == {
+ 'section': '# inline section comment', 'key': None
+ }
+ assert c['section'].comments == { 'key': ['# key comment']}
+ assert c.final_comment == ['', '# final comment', '# with two lines']
+
+
def test_overwriting_filenames(a, b, i):
#TODO: I'm not entirely sure what this test is actually asserting
@@ -1150,7 +1292,7 @@ class TestEdgeCasesWhenWritingOut(object):
def test_writing_out_dict_value_with_unrepr(self):
# issue #42
- cfg = ['thing = {"a": 1}']
+ cfg = [str('thing = {"a": 1}')]
c = ConfigObj(cfg, unrepr=True)
assert repr(c) == "ConfigObj({'thing': {'a': 1}})"
assert c.write() == ["thing = {'a': 1}"]