Skip to content

Commit f45a8e3

Browse files
authored
feat: use tomllib for Python 3.11+ (#208)
* feat: use tomllib for Python 3.11+ * doc: update documentation for installing with TOML support
1 parent d05e873 commit f45a8e3

File tree

9 files changed

+101
-122
lines changed

9 files changed

+101
-122
lines changed

.pre-commit-config.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
33
rev: v4.4.0
44
hooks:
5-
- id: check-docstring-first
65
- id: check-merge-conflict
76
- id: check-toml
87
- id: check-yaml

README.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ From pip::
7777

7878
$ pip install --upgrade docformatter
7979

80-
Or, if you want to use pyproject.toml to configure docformatter::
80+
Or, if you want to use pyproject.toml to configure docformatter and you're using
81+
Python < 3.11::
8182

8283
$ pip install --upgrade docformatter[tomli]
8384

docs/source/installation.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ to install with TOML support:
1919
2020
$ pip install --upgrade docformatter[tomli]
2121
22+
This is only necessary if you are using Python < 3.11. Beginning with Python 3.11,
23+
docformatter will utilize ``tomllib`` from the standard library.
24+
2225
Install from GitHub
2326
-------------------
2427

pyproject.toml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ include = ["LICENSE"]
3434
[tool.poetry.dependencies]
3535
python = "^3.7"
3636
charset_normalizer = "^3.0.0"
37-
tomli = {version = "^2.0.0", optional = true}
37+
tomli = {version = "^2.0.0", python = "<3.11", optional = true}
3838
untokenize = "^0.1.1"
3939

4040
[tool.poetry.dev-dependencies]
@@ -52,6 +52,7 @@ pylint = [
5252
]
5353
pytest = "^7.1.0"
5454
pytest-cov = "^4.0.0"
55+
ruff = "^0.0.267"
5556
rstcheck = "^6.1.0"
5657
tox = "<4.0.0"
5758
Sphinx = [
@@ -134,7 +135,7 @@ show_missing = true
134135
output = 'coverage.xml'
135136

136137
[tool.black]
137-
line-length = 79
138+
line-length = 88
138139
target-version = ['py37', 'py38', 'py39', 'py310', 'py311']
139140
include = '\.pyi?$'
140141
exclude = '''
@@ -164,7 +165,7 @@ include_trailing_comma = true
164165
force_grid_wrap = 0
165166
use_parentheses = true
166167
ensure_newline_before_comments = true
167-
line_length = 79
168+
line_length = 88
168169

169170
[tool.tox]
170171
legacy_tox_ini = """
@@ -242,7 +243,7 @@ deps =
242243
charset_normalizer
243244
pycodestyle
244245
pydocstyle
245-
pylint
246+
ruff
246247
rstcheck
247248
toml
248249
untokenize
@@ -252,6 +253,6 @@ commands =
252253
docformatter --black --recursive {toxinidir}/src/docformatter
253254
pycodestyle --exclude=.git,.tox,*.pyc,*.pyo,build,dist,*.egg-info,config,docs,locale,tests,tools --ignore=C326,C330,E121,E123,E126,E133,E203,E242,E265,E402,W503,W504 --format=pylint --max-line-length=88 {toxinidir}/src/docformatter
254255
pydocstyle {toxinidir}/src/docformatter
255-
pylint --rcfile={toxinidir}/pyproject.toml {toxinidir}/src/docformatter
256+
ruff check --select "PL" --select "F" {toxinidir}/src/docformatter
256257
rstcheck --report-level=1 {toxinidir}/README.rst
257258
"""

src/docformatter/__init__.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@
2727

2828
# docformatter Local Imports
2929
from .__pkginfo__ import __version__
30-
from .strings import *
31-
from .syntax import *
32-
from .util import *
30+
from .strings import * # noqa F403
31+
from .syntax import * # noqa F403
32+
from .util import * # noqa F403
3333

3434
# Have isort skip these they require the functions above.
35-
from .configuration import Configurater # isort: skip
36-
from .encode import Encoder # isort: skip
37-
from .format import Formatter, FormatResult # isort: skip
35+
from .configuration import Configurater # isort: skip # noqa F401
36+
from .encode import Encoder # isort: skip # noqa F401
37+
from .format import Formatter, FormatResult # isort: skip # noqa F401

src/docformatter/configuration.py

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,28 @@
2323
# SOFTWARE.
2424
"""This module provides docformatter's Configurater class."""
2525

26+
2627
# Standard Library Imports
2728
import argparse
29+
import contextlib
2830
import os
31+
import sys
2932
from configparser import ConfigParser
3033
from typing import Dict, List, Union
3134

32-
try:
33-
# Third Party Imports
34-
import tomli
35+
TOMLLIB_INSTALLED = False
36+
TOMLI_INSTALLED = False
37+
with contextlib.suppress(ImportError):
38+
if sys.version_info >= (3, 11):
39+
# Standard Library Imports
40+
import tomllib
41+
42+
TOMLLIB_INSTALLED = True
43+
else:
44+
# Third Party Imports
45+
import tomli
3546

36-
TOMLI_INSTALLED = True
37-
except ImportError:
38-
TOMLI_INSTALLED = False
47+
TOMLI_INSTALLED = True
3948

4049
# docformatter Package Imports
4150
from docformatter import __pkginfo__
@@ -44,7 +53,7 @@
4453
class Configurater:
4554
"""Read and store all the docformatter configuration information."""
4655

47-
parser = None
56+
parser: argparse.ArgumentParser = argparse.ArgumentParser()
4857
"""Parser object."""
4958

5059
flargs_dct: Dict[str, Union[bool, float, int, str]] = {}
@@ -57,7 +66,7 @@ class Configurater:
5766
]
5867
"""List of supported configuration files."""
5968

60-
args: argparse.Namespace = None
69+
args: argparse.Namespace = argparse.Namespace()
6170

6271
def __init__(self, args: List[Union[bool, int, str]]) -> None:
6372
"""Initialize a Configurater class instance.
@@ -75,9 +84,7 @@ def __init__(self, args: List[Union[bool, int, str]]) -> None:
7584
)
7685

7786
try:
78-
self.config_file = self.args_lst[
79-
self.args_lst.index("--config") + 1
80-
]
87+
self.config_file = self.args_lst[self.args_lst.index("--config") + 1]
8188
except ValueError:
8289
for _configuration_file in self.configuration_file_lst:
8390
if os.path.isfile(_configuration_file):
@@ -116,8 +123,7 @@ def do_parse_arguments(self) -> None:
116123
"-r",
117124
"--recursive",
118125
action="store_true",
119-
default=self.flargs_dct.get("recursive", "false").lower()
120-
== "true",
126+
default=self.flargs_dct.get("recursive", "false").lower() == "true",
121127
help="drill down directories recursively",
122128
)
123129
self.parser.add_argument(
@@ -163,13 +169,11 @@ def do_parse_arguments(self) -> None:
163169
"--style",
164170
default=self.flargs_dct.get("style", "sphinx"),
165171
help="name of the docstring style to use when formatting "
166-
"parameter lists (default: sphinx)",
172+
"parameter lists (default: sphinx)",
167173
)
168174
self.parser.add_argument(
169175
"--wrap-summaries",
170-
default=int(
171-
self.flargs_dct.get("wrap-summaries", _default_wrap_summaries)
172-
),
176+
default=int(self.flargs_dct.get("wrap-summaries", _default_wrap_summaries)),
173177
type=int,
174178
metavar="length",
175179
help="wrap long summary lines at this length; "
@@ -179,9 +183,7 @@ def do_parse_arguments(self) -> None:
179183
self.parser.add_argument(
180184
"--wrap-descriptions",
181185
default=int(
182-
self.flargs_dct.get(
183-
"wrap-descriptions", _default_wrap_descriptions
184-
)
186+
self.flargs_dct.get("wrap-descriptions", _default_wrap_descriptions)
185187
),
186188
type=int,
187189
metavar="length",
@@ -192,8 +194,7 @@ def do_parse_arguments(self) -> None:
192194
self.parser.add_argument(
193195
"--force-wrap",
194196
action="store_true",
195-
default=self.flargs_dct.get("force-wrap", "false").lower()
196-
== "true",
197+
default=self.flargs_dct.get("force-wrap", "false").lower() == "true",
197198
help="force descriptions to be wrapped even if it may "
198199
"result in a mess (default: False)",
199200
)
@@ -228,25 +229,20 @@ def do_parse_arguments(self) -> None:
228229
"pre-summary-space", _default_pre_summary_space
229230
).lower()
230231
== "true",
231-
help="add a space after the opening triple quotes "
232-
"(default: False)",
232+
help="add a space after the opening triple quotes " "(default: False)",
233233
)
234234
self.parser.add_argument(
235235
"--make-summary-multi-line",
236236
action="store_true",
237-
default=self.flargs_dct.get(
238-
"make-summary-multi-line", "false"
239-
).lower()
237+
default=self.flargs_dct.get("make-summary-multi-line", "false").lower()
240238
== "true",
241239
help="add a newline before and after the summary of a one-line "
242240
"docstring (default: False)",
243241
)
244242
self.parser.add_argument(
245243
"--close-quotes-on-newline",
246244
action="store_true",
247-
default=self.flargs_dct.get(
248-
"close-quotes-on-newline", "false"
249-
).lower()
245+
default=self.flargs_dct.get("close-quotes-on-newline", "false").lower()
250246
== "true",
251247
help="place closing triple quotes on a new-line when a "
252248
"one-line docstring wraps to two or more lines "
@@ -275,8 +271,7 @@ def do_parse_arguments(self) -> None:
275271
self.parser.add_argument(
276272
"--non-strict",
277273
action="store_true",
278-
default=self.flargs_dct.get("non-strict", "false").lower()
279-
== "true",
274+
default=self.flargs_dct.get("non-strict", "false").lower() == "true",
280275
help="don't strictly follow reST syntax to identify lists (see "
281276
"issue #67) (default: False)",
282277
)
@@ -309,9 +304,7 @@ def do_parse_arguments(self) -> None:
309304

310305
if self.args.length_range:
311306
if self.args.length_range[0] <= 0:
312-
self.parser.error(
313-
"--docstring-length must be positive numbers"
314-
)
307+
self.parser.error("--docstring-length must be positive numbers")
315308
if self.args.length_range[0] > self.args.length_range[1]:
316309
self.parser.error(
317310
"First value of --docstring-length should be less "
@@ -328,7 +321,11 @@ def _do_read_configuration_file(self) -> None:
328321
fullpath, ext = os.path.splitext(self.config_file)
329322
filename = os.path.basename(fullpath)
330323

331-
if ext == ".toml" and TOMLI_INSTALLED and filename == "pyproject":
324+
if (
325+
ext == ".toml"
326+
and (TOMLI_INSTALLED or TOMLLIB_INSTALLED)
327+
and filename == "pyproject"
328+
):
332329
self._do_read_toml_configuration()
333330

334331
if (ext == ".cfg" and filename == "setup") or (
@@ -339,13 +336,15 @@ def _do_read_configuration_file(self) -> None:
339336
def _do_read_toml_configuration(self) -> None:
340337
"""Load configuration information from a *.toml file."""
341338
with open(self.config_file, "rb") as f:
342-
config = tomli.load(f)
339+
if TOMLI_INSTALLED:
340+
config = tomli.load(f)
341+
elif TOMLLIB_INSTALLED:
342+
config = tomllib.load(f)
343343

344344
result = config.get("tool", {}).get("docformatter", None)
345345
if result is not None:
346346
self.flargs_dct = {
347-
k: v if isinstance(v, list) else str(v)
348-
for k, v in result.items()
347+
k: v if isinstance(v, list) else str(v) for k, v in result.items()
349348
}
350349

351350
def _do_read_parser_configuration(self) -> None:

0 commit comments

Comments
 (0)