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
7 changes: 4 additions & 3 deletions docs/configobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,10 @@ ConfigObj takes the following arguments (with the default values shown) :
* Nothing. In which case the ``filename`` attribute of your ConfigObj will be
``None``. You can set a filename at any time.

* A filename. What happens if the file doesn't already exist is determined by
the options ``file_error`` and ``create_empty``. The filename will be
preserved as the ``filename`` attribute. This can be changed at any time.
* A filename or pathlib.Path object. What happens if the file doesn't already
exist is determined by the options ``file_error`` and ``create_empty``. The
filename will be preserved as the ``filename`` attribute. This can be
changed at any time.

* A list of lines. Any trailing newlines will be removed from the lines. The
``filename`` attribute of your ConfigObj will be ``None``.
Expand Down
18 changes: 16 additions & 2 deletions src/configobj/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import sys

from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE
from pathlib import Path

from ._version import __version__

Expand Down Expand Up @@ -1241,7 +1242,20 @@ def _load(self, infile, configspec):
with open(infile, 'w') as h:
h.write('')
content = []


elif isinstance(infile, Path):
self.filename = str(infile)
if infile.is_file():
with infile.open('rb') as h:
content = h.readlines() or []
elif self.file_error:
raise IOError('Config file not found: "%s".' % self.filename)
else:
if self.create_empty:
with infile.open('w') as h:
h.write('')
content = []

elif isinstance(infile, (list, tuple)):
content = list(infile)

Expand Down Expand Up @@ -1275,7 +1289,7 @@ def set_section(in_section, this_section):
# needs splitting into lines - but needs doing *after* decoding
# in case it's not an 8 bit encoding
else:
raise TypeError('infile must be a filename, file like object, or list of lines.')
raise TypeError('infile must be a filename, file like object, pathlib.Path or list of lines.')

if content:
# don't do it for the empty ConfigObj
Expand Down
19 changes: 19 additions & 0 deletions src/tests/test_configobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import re

from codecs import BOM_UTF8
from pathlib import Path
from warnings import catch_warnings
from tempfile import NamedTemporaryFile

Expand Down Expand Up @@ -1104,6 +1105,24 @@ def test_creating_with_a_dictionary():
assert dictionary_cfg_content == cfg.dict()
assert dictionary_cfg_content is not cfg.dict()

def test_reading_a_pathlib_path(cfg_contents):
cfg = cfg_contents("""
[section]
foo = bar""")
c = ConfigObj(Path(cfg))
assert 'foo' in c['section']

def test_creating_a_file_from_pathlib_path(tmp_path):
infile = tmp_path / 'config.ini'
assert not Path(tmp_path / 'config.ini').is_file()
c = ConfigObj(Path(infile), create_empty=True)
assert Path(tmp_path / 'config.ini').is_file()

def test_creating_a_file_from_string(tmp_path):
infile = str(tmp_path / 'config.ini')
assert not Path(infile).is_file()
c = ConfigObj(infile, create_empty=True)
assert Path(infile).is_file()

class TestComments(object):
@pytest.fixture
Expand Down