Skip to content

Commit

Permalink
Merge pull request #247 from DiffSK/5.0.x
Browse files Browse the repository at this point in the history
Merge new release 5.0.9
  • Loading branch information
jelmer authored Sep 21, 2024
2 parents a58c2f4 + 242dfd0 commit 9618004
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 184 deletions.
28 changes: 1 addition & 27 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest coverage pytest-cov six mock
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install -e .
- name: Test with pytest
run: |
python src/tests/configobj_doctests.py
python -m configobj.validate
py.test -c setup.cfg --color=yes --cov=configobj --cov-report=term --cov-report=html --cov-report=xml
build-on-legacy:
runs-on: ubuntu-20.04
strategy:
fail-fast: false
matrix:
python-version: [ "2.7", "3.5", "3.6" ]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest coverage pytest-cov six mock
pip install pytest coverage pytest-cov
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install -e .
- name: Test with pytest
Expand Down
8 changes: 7 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
---------

Release 5.0.9
"""""""""""""

* drop support for Python 2 and <3.7
* fix CVE-2023-26112, ReDoS attack

Release 5.0.8
"""""""""""""

Expand Down Expand Up @@ -31,4 +37,4 @@ Older Releases
* Release 4.7.2 fixes several bugs in 4.7.1
* Release 4.7.1 fixes a bug with the deprecated options keyword in 4.7.0.
* Release 4.7.0 improves performance adds features for validation and
fixes some bugs.
fixes some bugs.
1 change: 0 additions & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

2014
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

Expand Down
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
Python 3+ compatible port of the [configobj](https://pypi.python.org/pypi/configobj/) library.

The Github CI/CD Pipeline runs tests on python versions:
- 2.7
- 3.5
- 3.6
- 3.7
- 3.8
- 3.9
- 3.10
- 3.11
- 3.12


## Documentation
Expand Down
6 changes: 6 additions & 0 deletions docs/configobj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2383,6 +2383,12 @@ CHANGELOG
This is an abbreviated changelog showing the major releases up to version 4.
From version 4 it lists all releases and changes.

2024/09/21 - Version 5.0.9
--------------------------

* drop support for Python 2 and <3.7
* fix CVE-2023-26112, ReDoS attack

2023/01/18 - Version 5.0.8
--------------------------

Expand Down
26 changes: 7 additions & 19 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,9 @@

from setuptools import setup

if sys.version_info < (2, 6):
print('for Python versions < 2.6 use configobj '
'version 4.7.2')
sys.exit(1)
elif sys.version_info < (2, 7):
print('for Python version 2.6 use configobj '
'version 5.0.6')
if sys.version_info[0] < 2:
print('for Python versions < 3 use configobj '
'version 5.0.8')
sys.exit(1)

__here__ = os.path.abspath(os.path.dirname(__file__))
Expand All @@ -40,10 +36,6 @@
DESCRIPTION = 'Config file reading, writing and validation.'
URL = 'https://github.com/DiffSK/configobj'

REQUIRES = """
six
"""

VERSION = ''
with closing(open(os.path.join(__here__, 'src', PACKAGES[0], '_version.py'), 'r')) as handle:
for line in handle.readlines():
Expand Down Expand Up @@ -88,16 +80,13 @@
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Operating System :: OS Independent',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules',
Expand All @@ -120,12 +109,11 @@
py_modules=MODULES,
package_dir={'': 'src'},
packages=PACKAGES,
install_requires=[i.strip() for i in REQUIRES.splitlines() if i.strip()],
python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
python_requires='>=3.7',
classifiers=CLASSIFIERS,
keywords=KEYWORDS,
license='BSD (2 clause)',
license='BSD-3-Clause',
)

if __name__ == '__main__':
setup(**project)
setup(**project)
53 changes: 22 additions & 31 deletions src/configobj/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

from codecs import BOM_UTF8, BOM_UTF16, BOM_UTF16_BE, BOM_UTF16_LE

import six
from ._version import __version__

# imported lazily to avoid startup performance hit if it isn't used
Expand Down Expand Up @@ -121,10 +120,6 @@ def match_utf8(encoding):
'write_empty_values': False,
}

# this could be replaced if six is used for compatibility, or there are no
# more assertions about items being a string


def getObj(s):
global compiler
if compiler is None:
Expand Down Expand Up @@ -553,11 +548,11 @@ def __getitem__(self, key):
"""Fetch the item and do string interpolation."""
val = dict.__getitem__(self, key)
if self.main.interpolation:
if isinstance(val, six.string_types):
if isinstance(val, str):
return self._interpolate(key, val)
if isinstance(val, list):
def _check(entry):
if isinstance(entry, six.string_types):
if isinstance(entry, str):
return self._interpolate(key, entry)
return entry
new = [_check(entry) for entry in val]
Expand All @@ -580,7 +575,7 @@ def __setitem__(self, key, value, unrepr=False):
``unrepr`` must be set when setting a value to a dictionary, without
creating a new sub-section.
"""
if not isinstance(key, six.string_types):
if not isinstance(key, str):
raise ValueError('The key "%s" is not a string.' % key)

# add the comment
Expand Down Expand Up @@ -614,11 +609,11 @@ def __setitem__(self, key, value, unrepr=False):
if key not in self:
self.scalars.append(key)
if not self.main.stringify:
if isinstance(value, six.string_types):
if isinstance(value, str):
pass
elif isinstance(value, (list, tuple)):
for entry in value:
if not isinstance(entry, six.string_types):
if not isinstance(entry, str):
raise TypeError('Value is not a string "%s".' % entry)
else:
raise TypeError('Value is not a string "%s".' % value)
Expand Down Expand Up @@ -959,7 +954,7 @@ def as_bool(self, key):
return False
else:
try:
if not isinstance(val, six.string_types):
if not isinstance(val, str):
# TODO: Why do we raise a KeyError here?
raise KeyError()
else:
Expand Down Expand Up @@ -1230,7 +1225,7 @@ def __init__(self, infile=None, options=None, configspec=None, encoding=None,


def _load(self, infile, configspec):
if isinstance(infile, six.string_types):
if isinstance(infile, str):
self.filename = infile
if os.path.isfile(infile):
with open(infile, 'rb') as h:
Expand Down Expand Up @@ -1298,7 +1293,7 @@ def set_section(in_section, this_section):
break
break

assert all(isinstance(line, six.string_types) for line in content), repr(content)
assert all(isinstance(line, str) for line in content), repr(content)
content = [line.rstrip('\r\n') for line in content]

self._parse(content)
Expand Down Expand Up @@ -1403,7 +1398,7 @@ def _handle_bom(self, infile):
else:
line = infile

if isinstance(line, six.text_type):
if isinstance(line, str):
# it's already decoded and there's no need to do anything
# else, just use the _decode utility method to handle
# listifying appropriately
Expand Down Expand Up @@ -1448,7 +1443,7 @@ def _handle_bom(self, infile):

# No encoding specified - so we need to check for UTF8/UTF16
for BOM, (encoding, final_encoding) in list(BOMS.items()):
if not isinstance(line, six.binary_type) or not line.startswith(BOM):
if not isinstance(line, bytes) or not line.startswith(BOM):
# didn't specify a BOM, or it's not a bytestring
continue
else:
Expand All @@ -1464,30 +1459,26 @@ def _handle_bom(self, infile):
else:
infile = newline
# UTF-8
if isinstance(infile, six.text_type):
if isinstance(infile, str):
return infile.splitlines(True)
elif isinstance(infile, six.binary_type):
elif isinstance(infile, bytes):
return infile.decode('utf-8').splitlines(True)
else:
return self._decode(infile, 'utf-8')
# UTF16 - have to decode
return self._decode(infile, encoding)


if six.PY2 and isinstance(line, str):
# don't actually do any decoding, since we're on python 2 and
# returning a bytestring is fine
return self._decode(infile, None)
# No BOM discovered and no encoding specified, default to UTF-8
if isinstance(infile, six.binary_type):
if isinstance(infile, bytes):
return infile.decode('utf-8').splitlines(True)
else:
return self._decode(infile, 'utf-8')


def _a_to_u(self, aString):
"""Decode ASCII strings to unicode if a self.encoding is specified."""
if isinstance(aString, six.binary_type) and self.encoding:
if isinstance(aString, bytes) and self.encoding:
return aString.decode(self.encoding)
else:
return aString
Expand All @@ -1499,9 +1490,9 @@ def _decode(self, infile, encoding):
if is a string, it also needs converting to a list.
"""
if isinstance(infile, six.string_types):
if isinstance(infile, str):
return infile.splitlines(True)
if isinstance(infile, six.binary_type):
if isinstance(infile, bytes):
# NOTE: Could raise a ``UnicodeDecodeError``
if encoding:
return infile.decode(encoding).splitlines(True)
Expand All @@ -1510,7 +1501,7 @@ def _decode(self, infile, encoding):

if encoding:
for i, line in enumerate(infile):
if isinstance(line, six.binary_type):
if isinstance(line, bytes):
# NOTE: The isinstance test here handles mixed lists of unicode/string
# NOTE: But the decode will break on any non-string values
# NOTE: Or could raise a ``UnicodeDecodeError``
Expand All @@ -1520,7 +1511,7 @@ def _decode(self, infile, encoding):

def _decode_element(self, line):
"""Decode element to unicode if necessary."""
if isinstance(line, six.binary_type) and self.default_encoding:
if isinstance(line, bytes) and self.default_encoding:
return line.decode(self.default_encoding)
else:
return line
Expand All @@ -1532,7 +1523,7 @@ def _str(self, value):
Used by ``stringify`` within validate, to turn non-string values
into strings.
"""
if not isinstance(value, six.string_types):
if not isinstance(value, str):
# intentially 'str' because it's just whatever the "normal"
# string type is for the python version we're dealing with
return str(value)
Expand Down Expand Up @@ -1786,7 +1777,7 @@ def _quote(self, value, multiline=True):
return self._quote(value[0], multiline=False) + ','
return ', '.join([self._quote(val, multiline=False)
for val in value])
if not isinstance(value, six.string_types):
if not isinstance(value, str):
if self.stringify:
# intentially 'str' because it's just whatever the "normal"
# string type is for the python version we're dealing with
Expand Down Expand Up @@ -2111,7 +2102,7 @@ def write(self, outfile=None, section=None):
if not output.endswith(newline):
output += newline

if isinstance(output, six.binary_type):
if isinstance(output, bytes):
output_bytes = output
else:
output_bytes = output.encode(self.encoding or
Expand Down Expand Up @@ -2353,7 +2344,7 @@ def reload(self):
This method raises a ``ReloadError`` if the ConfigObj doesn't have
a filename attribute pointing to a file.
"""
if not isinstance(self.filename, six.string_types):
if not isinstance(self.filename, str):
raise ReloadError()

filename = self.filename
Expand Down
2 changes: 1 addition & 1 deletion src/configobj/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '5.0.8'
__version__ = '5.0.9'
Loading

0 comments on commit 9618004

Please sign in to comment.