From 4bc92d77a98cdef87f044623105a70805a7a8b12 Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 04:56:10 +0300 Subject: [PATCH 01/17] fix missing inline_comment_prefixes --- src/pydocstyle/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index f5226204..dca895cf 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -433,7 +433,7 @@ def _get_config_file_in_folder(cls, path): path = os.path.dirname(path) for fn in cls.PROJECT_CONFIG_FILES: - config = RawConfigParser() + config = RawConfigParser(inline_comment_prefixes=('#', ';')) full_path = os.path.join(path, fn) if config.read(full_path) and cls._get_section_name(config): return full_path From 999c5fb604b5c08e0a57044521409b5e14ec94cf Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 04:35:13 +0300 Subject: [PATCH 02/17] implement TomlParser --- src/pydocstyle/config.py | 96 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index dca895cf..be5acf2b 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -5,9 +5,11 @@ import os from collections import namedtuple from collections.abc import Set -from configparser import RawConfigParser +from configparser import NoOptionError, NoSectionError, RawConfigParser from re import compile as re +import toml + from .utils import __version__, log from .violations import ErrorRegistry, conventions @@ -23,6 +25,98 @@ def _decorator(self, *args, **kwargs): return _decorator +class TomlParser: + """ConfigParser that partially mimics RawConfigParser but for toml files. + + See RawConfigParser for more info. Also, please note that not all + RawConfigParser functionality is implemented, but only the subset, that is + currently used by pydocstyle. + """ + + def __init__(self): + """Create a toml parser.""" + self._config = {} + + def read(self, filenames, encoding=None): + """Read and parse a filename or an iterable of filenames. + + Files that cannot be opened are silently ignored; this is + designed so that you can specify an iterable of potential + configuration file locations (e.g. current directory, user's + home directory, systemwide directory), and all existing + configuration files in the iterable will be read. A single + filename may also be given. + + Return list of successfully read files. + """ + if isinstance(filenames, (str, bytes, os.PathLike)): + filenames = [filenames] + read_ok = [] + for filename in filenames: + try: + with open(filename, encoding=encoding) as fp: + self._config.update(toml.load(fp)) + except OSError: + continue + if isinstance(filename, os.PathLike): + filename = os.fspath(filename) + read_ok.append(filename) + return read_ok + + def _get_section(self, section, allow_none=False): + current = self._config + for p in section.split('.'): + if isinstance(current, dict) and p in current: + current = current[p] + else: + current = None + break + + if isinstance(current, dict): + return current + elif allow_none: + return None + else: + raise NoSectionError(section) + + def has_section(self, section): + """Indicate whether the named section is present in the configuration.""" + return self._get_section(section, allow_none=True) is not None + + def options(self, section): + """Return a list of option names for the given section name.""" + current = self._get_section(section) + # current = current.copy() + # current.update(self._defaults) + return list(current.keys()) + + def get(self, section, option, *, _conv=None): + """Get an option value for a given section.""" + d = self._get_section(section) + option = option.lower() + try: + value = d[option] + except KeyError: + raise NoOptionError(option, section) + + # toml should convert types automatically + # don't manually convert, just check, that the type is correct + if _conv is not None and not isinstance(value, _conv): + raise TypeError( + f"The type of {section}.{option} should be {_conv}" + ) + + return value + + def getboolean(self, section, option): + """Get a boolean option value for a given section.""" + return self.get(section, option, _conv=bool) + + def getint(self, section, option): + """Get an integer option value for a given section.""" + return self.get(section, option, _conv=int) + + class ConfigurationParser: """Responsible for parsing configuration from files and CLI. From 61a9d40e38928f5a965e46598b6c67933df1361f Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 04:35:45 +0300 Subject: [PATCH 03/17] add pyproject.toml support --- src/pydocstyle/config.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index be5acf2b..ba3b820f 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -179,6 +179,7 @@ class ConfigurationParser: '.pydocstyle.ini', '.pydocstylerc', '.pydocstylerc.ini', + 'pyproject.toml', # The following is deprecated, but remains for backwards compatibility. '.pep257', ) @@ -404,7 +405,10 @@ def _read_configuration_file(self, path): Returns (options, should_inherit). """ - parser = RawConfigParser(inline_comment_prefixes=('#', ';')) + if path.endswith('.toml'): + parser = TomlParser() + else: + parser = RawConfigParser(inline_comment_prefixes=('#', ';')) options = None should_inherit = True @@ -527,7 +531,10 @@ def _get_config_file_in_folder(cls, path): path = os.path.dirname(path) for fn in cls.PROJECT_CONFIG_FILES: - config = RawConfigParser(inline_comment_prefixes=('#', ';')) + if fn.endswith('.toml'): + config = TomlParser() + else: + config = RawConfigParser(inline_comment_prefixes=('#', ';')) full_path = os.path.join(path, fn) if config.read(full_path) and cls._get_section_name(config): return full_path From 7eee19984cb776681b1cb6f89909df7fbc88bdcb Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 04:36:05 +0300 Subject: [PATCH 04/17] add tool.pydocstyle section support --- src/pydocstyle/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index ba3b820f..75537ebb 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -184,7 +184,7 @@ class ConfigurationParser: '.pep257', ) - POSSIBLE_SECTION_NAMES = ('pydocstyle', 'pep257') + POSSIBLE_SECTION_NAMES = ('pydocstyle', 'pep257', 'tool.pydocstyle') def __init__(self): """Create a configuration parser.""" From 2ee9049331c7f1e02b8aaa4d8f790c16aacd541c Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 05:25:53 +0300 Subject: [PATCH 05/17] implement variable config_name for tests --- src/tests/test_integration.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/tests/test_integration.py b/src/tests/test_integration.py index c0209b19..62ae3c6e 100644 --- a/src/tests/test_integration.py +++ b/src/tests/test_integration.py @@ -32,12 +32,19 @@ class SandboxEnv: Result = namedtuple('Result', ('out', 'err', 'code')) - def __init__(self, script_name='pydocstyle'): + def __init__( + self, + script_name='pydocstyle', + section_name='pydocstyle', + config_name='tox.ini', + ): """Initialize the object.""" self.tempdir = None self.script_name = script_name + self.section_name = section_name + self.config_name = config_name - def write_config(self, prefix='', name='tox.ini', **kwargs): + def write_config(self, prefix='', name=None, **kwargs): """Change an environment config file. Applies changes to `tox.ini` relative to `tempdir/prefix`. @@ -48,10 +55,23 @@ def write_config(self, prefix='', name='tox.ini', **kwargs): if not os.path.isdir(base): self.makedirs(base) + name = self.config_name if name is None else name + if name.endswith('.toml'): + def convert_value(val): + if isinstance(val, bool): + return {True: 'true', False: 'false'}[val] + else: + return repr(val) + else: + def convert_value(val): + return val + with open(os.path.join(base, name), 'wt') as conf: - conf.write(f"[{self.script_name}]\n") + conf.write(f"[{self.section_name}]\n") for k, v in kwargs.items(): - conf.write("{} = {}\n".format(k.replace('_', '-'), v)) + conf.write("{} = {}\n".format( + k.replace('_', '-'), convert_value(v) + )) def open(self, path, *args, **kwargs): """Open a file in the environment. From ed42666ff83afe2a0b6efc3ac84e1ef21f3864eb Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 05:26:17 +0300 Subject: [PATCH 06/17] run all env tests for tox.ini and pyproject.toml --- src/tests/test_integration.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/tests/test_integration.py b/src/tests/test_integration.py index 62ae3c6e..9ed90c89 100644 --- a/src/tests/test_integration.py +++ b/src/tests/test_integration.py @@ -137,10 +137,20 @@ def install_package(request): ) -@pytest.yield_fixture(scope="function") +@pytest.yield_fixture(scope="function", params=['ini', 'toml']) def env(request): """Add a testing environment to a test method.""" - with SandboxEnv() as test_env: + sandbox_settings = { + 'ini': { + 'section_name': 'pydocstyle', + 'config_name': 'tox.ini', + }, + 'toml': { + 'section_name': 'tool.pydocstyle', + 'config_name': 'pyproject.toml', + }, + }[request.param] + with SandboxEnv(**sandbox_settings) as test_env: yield test_env From 752c8f187ecfeb94ef8db2cd1bb41fd75dc3249e Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 05:26:49 +0300 Subject: [PATCH 07/17] exclude ini-specific tests for toml --- src/tests/test_integration.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/tests/test_integration.py b/src/tests/test_integration.py index 9ed90c89..c253274e 100644 --- a/src/tests/test_integration.py +++ b/src/tests/test_integration.py @@ -335,6 +335,11 @@ def foo(): assert 'file does not contain a pydocstyle section' not in err +@pytest.mark.parametrize( + # Don't parametrize over 'pyproject.toml' + # since this test applies only to '.ini' files + 'env', ['ini'], indirect=True +) def test_multiple_lined_config_file(env): """Test that .ini files with multi-lined entries are parsed correctly.""" with env.open('example.py', 'wt') as example: @@ -506,6 +511,11 @@ def foo(): assert 'D300' not in out +@pytest.mark.parametrize( + # Don't parametrize over 'pyproject.toml' + # since this test applies only to '.ini' files + 'env', ['ini'], indirect=True +) def test_ignores_whitespace_in_fixed_option_set(env): with env.open('example.py', 'wt') as example: example.write("class Foo(object):\n 'Doc string'") From 2c46920f055777dd87fa07d9b67c94f50d7128a4 Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 05:04:06 +0300 Subject: [PATCH 08/17] add toml dependency --- requirements/runtime.txt | 1 + setup.py | 1 + 2 files changed, 2 insertions(+) diff --git a/requirements/runtime.txt b/requirements/runtime.txt index 96db5be8..80302751 100644 --- a/requirements/runtime.txt +++ b/requirements/runtime.txt @@ -1 +1,2 @@ snowballstemmer==1.2.1 +toml==0.10.2 diff --git a/setup.py b/setup.py index ba979f59..173fabef 100644 --- a/setup.py +++ b/setup.py @@ -6,6 +6,7 @@ requirements = [ 'snowballstemmer', + 'toml', ] From 39466c99cb669fd9d68688a3f4be37765670724b Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 05:14:22 +0300 Subject: [PATCH 09/17] support [] lists in toml config --- src/pydocstyle/config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index 75537ebb..759df864 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -653,8 +653,10 @@ def _get_set(value_str): file. """ + if not isinstance(value_str, list): + value_str = value_str.split(",") return cls._expand_error_codes( - {x.strip() for x in value_str.split(",")} - {""} + {x.strip() for x in value_str} - {""} ) for opt in optional_set_options: From 56acdbd037a300a623ed9954b2d70078aa64551d Mon Sep 17 00:00:00 2001 From: ruro Date: Sat, 1 May 2021 05:23:48 +0300 Subject: [PATCH 10/17] add tests for [] lists in toml configs --- src/tests/test_integration.py | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/tests/test_integration.py b/src/tests/test_integration.py index c253274e..874e5b62 100644 --- a/src/tests/test_integration.py +++ b/src/tests/test_integration.py @@ -363,6 +363,31 @@ def foo(): assert 'D103' not in out +@pytest.mark.parametrize( + # Don't parametrize over 'tox.ini' since + # this test applies only to '.toml' files + 'env', ['toml'], indirect=True +) +def test_accepts_select_error_code_list(env): + """Test that .ini files with multi-lined entries are parsed correctly.""" + with env.open('example.py', 'wt') as example: + example.write(textwrap.dedent("""\ + class Foo(object): + "Doc string" + def foo(): + pass + """)) + + env.write_config(select=['D100', 'D204', 'D300']) + + out, err, code = env.invoke() + assert code == 1 + assert 'D100' in out + assert 'D204' in out + assert 'D300' in out + assert 'D103' not in out + + def test_config_path(env): """Test that options are correctly loaded from a specific config file. @@ -526,6 +551,21 @@ def test_ignores_whitespace_in_fixed_option_set(env): assert err == '' +@pytest.mark.parametrize( + # Don't parametrize over 'tox.ini' since + # this test applies only to '.toml' files + 'env', ['toml'], indirect=True +) +def test_accepts_ignore_error_code_list(env): + with env.open('example.py', 'wt') as example: + example.write("class Foo(object):\n 'Doc string'") + env.write_config(ignore=['D100', 'D300']) + out, err, code = env.invoke() + assert code == 1 + assert 'D300' not in out + assert err == '' + + def test_bad_wildcard_add_ignore_cli(env): """Test adding a non-existent error codes with --add-ignore.""" with env.open('example.py', 'wt') as example: From b399aaeadb5d94bc12db556feaff13502cb2a6ad Mon Sep 17 00:00:00 2001 From: ruro Date: Sun, 2 May 2021 02:43:12 +0300 Subject: [PATCH 11/17] nitpicks & code quality improvements --- src/pydocstyle/config.py | 21 +++++++++++---------- src/tests/test_integration.py | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index 759df864..54e608c8 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -2,10 +2,12 @@ import copy import itertools +import operator import os from collections import namedtuple from collections.abc import Set from configparser import NoOptionError, NoSectionError, RawConfigParser +from functools import reduce from re import compile as re import toml @@ -29,7 +31,7 @@ class TomlParser: """ConfigParser that partially mimics RawConfigParser but for toml files. See RawConfigParser for more info. Also, please note that not all - RawConfigParser functionality is implemented, but only the subset, that is + RawConfigParser functionality is implemented, but only the subset that is currently used by pydocstyle. """ @@ -64,13 +66,14 @@ def read(self, filenames, encoding=None): return read_ok def _get_section(self, section, allow_none=False): - current = self._config - for p in section.split('.'): - if isinstance(current, dict) and p in current: - current = current[p] - else: - current = None - break + try: + current = reduce( + operator.getitem, + section.split('.'), + self._config, + ) + except KeyError: + current = None if isinstance(current, dict): return current @@ -86,8 +89,6 @@ def has_section(self, section): def options(self, section): """Return a list of option names for the given section name.""" current = self._get_section(section) - # current = current.copy() - # current.update(self._defaults) return list(current.keys()) def get(self, section, option, *, _conv=None): diff --git a/src/tests/test_integration.py b/src/tests/test_integration.py index 874e5b62..d268edde 100644 --- a/src/tests/test_integration.py +++ b/src/tests/test_integration.py @@ -59,7 +59,7 @@ def write_config(self, prefix='', name=None, **kwargs): if name.endswith('.toml'): def convert_value(val): if isinstance(val, bool): - return {True: 'true', False: 'false'}[val] + return repr(val).lower() else: return repr(val) else: From cecf6492ebbd3e63013d68d2a638c598569ce6c1 Mon Sep 17 00:00:00 2001 From: ruro Date: Tue, 4 May 2021 16:35:17 +0300 Subject: [PATCH 12/17] nitpicks & code quality improvements 2 --- src/pydocstyle/config.py | 7 ++++++- src/tests/test_integration.py | 9 +++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index 54e608c8..eddbfe55 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -100,6 +100,11 @@ def get(self, section, option, *, _conv=None): except KeyError: raise NoOptionError(option, section) + if isinstance(value, dict): + raise TypeError( + f"Expected {section}.{option} to be an option, not a section." + ) + # toml should convert types automatically # don't manually convert, just check, that the type is correct if _conv is not None and not isinstance(value, _conv): @@ -654,7 +659,7 @@ def _get_set(value_str): file. """ - if not isinstance(value_str, list): + if isinstance(value_str, str): value_str = value_str.split(",") return cls._expand_error_codes( {x.strip() for x in value_str} - {""} diff --git a/src/tests/test_integration.py b/src/tests/test_integration.py index d268edde..1aaac713 100644 --- a/src/tests/test_integration.py +++ b/src/tests/test_integration.py @@ -58,10 +58,11 @@ def write_config(self, prefix='', name=None, **kwargs): name = self.config_name if name is None else name if name.endswith('.toml'): def convert_value(val): - if isinstance(val, bool): - return repr(val).lower() - else: - return repr(val) + return ( + repr(val).lower() + if isinstance(val, bool) + else repr(val) + ) else: def convert_value(val): return val From d1631d8dd706f8db49b22cd870b5723ab916be9a Mon Sep 17 00:00:00 2001 From: ruro Date: Sun, 9 May 2021 14:32:01 +0300 Subject: [PATCH 13/17] only consider tool.* sections in toml files --- src/pydocstyle/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index eddbfe55..cc98c2e4 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -70,7 +70,7 @@ def _get_section(self, section, allow_none=False): current = reduce( operator.getitem, section.split('.'), - self._config, + self._config['tool'], ) except KeyError: current = None @@ -190,7 +190,7 @@ class ConfigurationParser: '.pep257', ) - POSSIBLE_SECTION_NAMES = ('pydocstyle', 'pep257', 'tool.pydocstyle') + POSSIBLE_SECTION_NAMES = ('pydocstyle', 'pep257') def __init__(self): """Create a configuration parser.""" From 06c13b4947bc4df32399c7c9e1ae7776963f7503 Mon Sep 17 00:00:00 2001 From: ruro Date: Sun, 9 May 2021 14:50:26 +0300 Subject: [PATCH 14/17] add file extension in test_config_path --- src/tests/test_integration.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/tests/test_integration.py b/src/tests/test_integration.py index 1aaac713..eb4994ff 100644 --- a/src/tests/test_integration.py +++ b/src/tests/test_integration.py @@ -402,8 +402,12 @@ def foo(): pass """)) + # either my_config.ini or my_config.toml + config_ext = env.config_name.split('.')[-1] + config_name = 'my_config.' + config_ext + env.write_config(ignore='D100') - env.write_config(name='my_config', ignore='D103') + env.write_config(name=config_name, ignore='D103') out, err, code = env.invoke() assert code == 1 @@ -411,7 +415,7 @@ def foo(): assert 'D103' in out out, err, code = env.invoke('--config={} -d' - .format(env.get_path('my_config'))) + .format(env.get_path(config_name))) assert code == 1, out + err assert 'D100' in out assert 'D103' not in out From 0a94320f607d470b73b96f8669cc546b5df19a6b Mon Sep 17 00:00:00 2001 From: ruro Date: Sun, 9 May 2021 18:00:10 +0300 Subject: [PATCH 15/17] make toml an optional dependency --- setup.py | 5 ++++- src/pydocstyle/config.py | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 173fabef..aa377a4a 100644 --- a/setup.py +++ b/setup.py @@ -6,8 +6,10 @@ requirements = [ 'snowballstemmer', - 'toml', ] +extra_requirements = { + 'toml': ['toml'], +} setup( @@ -37,6 +39,7 @@ package_dir={'': 'src'}, package_data={'pydocstyle': ['data/*.txt']}, install_requires=requirements, + extras_require=extra_requirements, entry_points={ 'console_scripts': [ 'pydocstyle = pydocstyle.cli:main', diff --git a/src/pydocstyle/config.py b/src/pydocstyle/config.py index cc98c2e4..ae1e6b58 100644 --- a/src/pydocstyle/config.py +++ b/src/pydocstyle/config.py @@ -10,11 +10,14 @@ from functools import reduce from re import compile as re -import toml - from .utils import __version__, log from .violations import ErrorRegistry, conventions +try: + import toml +except ImportError: # pragma: no cover + toml = None # type: ignore + def check_initialized(method): """Check that the configuration object was initialized.""" @@ -57,6 +60,13 @@ def read(self, filenames, encoding=None): for filename in filenames: try: with open(filename, encoding=encoding) as fp: + if not toml: + log.warning( + "The %s configuration file was ignored, " + "because the `toml` package is not installed.", + filename, + ) + continue self._config.update(toml.load(fp)) except OSError: continue From 572ec90f375bb4e6b8093598fc322bc1f3346b40 Mon Sep 17 00:00:00 2001 From: ruro Date: Sun, 9 May 2021 18:26:23 +0300 Subject: [PATCH 16/17] document the toml configuration support --- docs/snippets/config.rst | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/docs/snippets/config.rst b/docs/snippets/config.rst index 8db5a3e8..6d32e48c 100644 --- a/docs/snippets/config.rst +++ b/docs/snippets/config.rst @@ -1,6 +1,6 @@ -``pydocstyle`` supports *ini*-like configuration files. -In order for ``pydocstyle`` to use it, it must be named one of the following -options, and have a ``[pydocstyle]`` section. +``pydocstyle`` supports *ini*-like and *toml* configuration files. +In order for ``pydocstyle`` to use a configuration file automatically, it must +be named one of the following options. * ``setup.cfg`` * ``tox.ini`` @@ -8,11 +8,20 @@ options, and have a ``[pydocstyle]`` section. * ``.pydocstyle.ini`` * ``.pydocstylerc`` * ``.pydocstylerc.ini`` +* ``pyproject.toml`` When searching for a configuration file, ``pydocstyle`` looks for one of the -file specified above *in that exact order*. If a configuration file was not -found, it keeps looking for one up the directory tree until one is found or -uses the default configuration. +file specified above *in that exact order*. *ini*-like configuration files must +have a ``[pydocstyle]`` section while *toml* configuration files must have a +``[tool.pydocstyle]`` section. If a configuration file was not found, +``pydocstyle`` keeps looking for one up the directory tree until one is found +or uses the default configuration. + +.. note:: + + *toml* configuration file support is only enabled if the ``toml`` python + package is installed. You can ensure that this is the case by installing + the ``pydocstyle[toml]`` optional dependency. .. note:: From 65829811907b4059db939878092a3a75c8c46621 Mon Sep 17 00:00:00 2001 From: Sambhav Kothari Date: Mon, 10 May 2021 00:25:39 +0100 Subject: [PATCH 17/17] Update release_notes.rst --- docs/release_notes.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/release_notes.rst b/docs/release_notes.rst index 0c9b87fe..804ccece 100644 --- a/docs/release_notes.rst +++ b/docs/release_notes.rst @@ -4,6 +4,12 @@ Release Notes **pydocstyle** version numbers follow the `Semantic Versioning `_ specification. +Current Development Version +--------------------------- + +New Features + +* Enable full toml configuration and pyproject.toml (#534). 6.0.0 - March 18th, 2021 ---------------------------