docsig 0.82.2__tar.gz → 0.83.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docsig
3
- Version: 0.82.2
3
+ Version: 0.83.0
4
4
  Summary: Check signature params for proper documentation
5
5
  License: MIT
6
6
  License-File: LICENSE
7
7
  Keywords: check,docs,docstring,params,signature
8
8
  Author: jshwi
9
- Author-email: stephen@jshwisolutions.com
9
+ Author-email: s.whitlock@live.com
10
10
  Maintainer: jshwi
11
- Maintainer-email: stephen@jshwisolutions.com
11
+ Maintainer-email: s.whitlock@live.com
12
12
  Requires-Python: >=3.10,<4.0
13
13
  Classifier: License :: OSI Approved :: MIT License
14
14
  Classifier: Programming Language :: Python :: 3
@@ -36,7 +36,7 @@ Description-Content-Type: text/x-rst
36
36
 
37
37
  |
38
38
 
39
- |License| |PyPI| |CI| |CodeQL| |pre-commit.ci status| |codecov.io| |readthedocs.org| |python3.10| |Black| |isort| |pylint| |Security Status| |Known Vulnerabilities|
39
+ |License| |PyPI| |CI| |CodeQL| |pre-commit.ci status| |codecov.io| |readthedocs.org| |python3.10| |Black| |isort| |pylint| |Security Status|
40
40
 
41
41
  .. |License| image:: https://img.shields.io/badge/License-MIT-yellow.svg
42
42
  :target: https://opensource.org/licenses/MIT
@@ -74,9 +74,6 @@ Description-Content-Type: text/x-rst
74
74
  .. |Security Status| image:: https://img.shields.io/badge/security-bandit-yellow.svg
75
75
  :target: https://github.com/PyCQA/bandit
76
76
  :alt: Security Status
77
- .. |Known Vulnerabilities| image:: https://snyk.io/test/github/jshwi/docsig/badge.svg
78
- :target: https://snyk.io/test/github/jshwi/docsig/badge.svg
79
- :alt: Known Vulnerabilities
80
77
 
81
78
  Check Python signature params for proper documentation
82
79
  -------------------------------------------------------
@@ -175,6 +172,20 @@ Options can also be configured with the pyproject.toml file
175
172
  "SIG201",
176
173
  ]
177
174
 
175
+ .. schema-info start
176
+
177
+ .. _here: https://docsig.io/en/latest/usage/configuration/schema.html
178
+
179
+ .. _schema: https://docsig.io/en/latest/usage/configuration/schema.json
180
+
181
+ .. _validate-pyproject: https://github.com/abravalheri/validate-pyproject
182
+
183
+ Configuration options can be found `here`_ or see the full JSON `schema`_
184
+
185
+ You can validate your `docsig` configuration with `validate-pyproject`_
186
+
187
+ .. schema-info end
188
+
178
189
  Flake8
179
190
  ******
180
191
 
@@ -184,7 +195,7 @@ ensure your installation has registered `docsig`
184
195
  .. code-block:: console
185
196
 
186
197
  $ flake8 --version
187
- 7.3.0 (docsig: 0.82.2, mccabe: 0.7.0, pycodestyle: 2.14.0, pyflakes: 3.4.0) CPython 3.10.19 on Darwin
198
+ 7.3.0 (docsig: 0.83.0, mccabe: 0.7.0, pycodestyle: 2.14.0, pyflakes: 3.4.0) CPython 3.10.19 on Darwin
188
199
 
189
200
  And now use `flake8` to lint your files
190
201
 
@@ -270,7 +281,7 @@ Standalone
270
281
 
271
282
  repos:
272
283
  - repo: https://github.com/jshwi/docsig
273
- rev: v0.82.2
284
+ rev: v0.83.0
274
285
  hooks:
275
286
  - id: docsig
276
287
  args:
@@ -289,7 +300,7 @@ or integrated with ``flake8``
289
300
  hooks:
290
301
  - id: flake8
291
302
  additional_dependencies:
292
- - docsig==0.82.2
303
+ - docsig==0.83.0
293
304
  args:
294
305
  - "--sig-check-class"
295
306
  - "--sig-check-dunders"
@@ -7,7 +7,7 @@
7
7
 
8
8
  |
9
9
 
10
- |License| |PyPI| |CI| |CodeQL| |pre-commit.ci status| |codecov.io| |readthedocs.org| |python3.10| |Black| |isort| |pylint| |Security Status| |Known Vulnerabilities|
10
+ |License| |PyPI| |CI| |CodeQL| |pre-commit.ci status| |codecov.io| |readthedocs.org| |python3.10| |Black| |isort| |pylint| |Security Status|
11
11
 
12
12
  .. |License| image:: https://img.shields.io/badge/License-MIT-yellow.svg
13
13
  :target: https://opensource.org/licenses/MIT
@@ -45,9 +45,6 @@
45
45
  .. |Security Status| image:: https://img.shields.io/badge/security-bandit-yellow.svg
46
46
  :target: https://github.com/PyCQA/bandit
47
47
  :alt: Security Status
48
- .. |Known Vulnerabilities| image:: https://snyk.io/test/github/jshwi/docsig/badge.svg
49
- :target: https://snyk.io/test/github/jshwi/docsig/badge.svg
50
- :alt: Known Vulnerabilities
51
48
 
52
49
  Check Python signature params for proper documentation
53
50
  -------------------------------------------------------
@@ -146,6 +143,20 @@ Options can also be configured with the pyproject.toml file
146
143
  "SIG201",
147
144
  ]
148
145
 
146
+ .. schema-info start
147
+
148
+ .. _here: https://docsig.io/en/latest/usage/configuration/schema.html
149
+
150
+ .. _schema: https://docsig.io/en/latest/usage/configuration/schema.json
151
+
152
+ .. _validate-pyproject: https://github.com/abravalheri/validate-pyproject
153
+
154
+ Configuration options can be found `here`_ or see the full JSON `schema`_
155
+
156
+ You can validate your `docsig` configuration with `validate-pyproject`_
157
+
158
+ .. schema-info end
159
+
149
160
  Flake8
150
161
  ******
151
162
 
@@ -155,7 +166,7 @@ ensure your installation has registered `docsig`
155
166
  .. code-block:: console
156
167
 
157
168
  $ flake8 --version
158
- 7.3.0 (docsig: 0.82.2, mccabe: 0.7.0, pycodestyle: 2.14.0, pyflakes: 3.4.0) CPython 3.10.19 on Darwin
169
+ 7.3.0 (docsig: 0.83.0, mccabe: 0.7.0, pycodestyle: 2.14.0, pyflakes: 3.4.0) CPython 3.10.19 on Darwin
159
170
 
160
171
  And now use `flake8` to lint your files
161
172
 
@@ -241,7 +252,7 @@ Standalone
241
252
 
242
253
  repos:
243
254
  - repo: https://github.com/jshwi/docsig
244
- rev: v0.82.2
255
+ rev: v0.83.0
245
256
  hooks:
246
257
  - id: docsig
247
258
  args:
@@ -260,7 +271,7 @@ or integrated with ``flake8``
260
271
  hooks:
261
272
  - id: flake8
262
273
  additional_dependencies:
263
- - docsig==0.82.2
274
+ - docsig==0.83.0
264
275
  args:
265
276
  - "--sig-check-class"
266
277
  - "--sig-check-dunders"
@@ -97,11 +97,10 @@ class _ArgumentParser(_argparse.ArgumentParser):
97
97
  return namespace, args
98
98
 
99
99
 
100
- def parse_args(args: _t.Sequence[str] | None = None) -> _argparse.Namespace:
101
- """Parse CLI arguments and merge in config from pyproject.toml.
100
+ def build_parser() -> _ArgumentParser:
101
+ """Build and return the argument parser.
102
102
 
103
- :param args: Argument list to parse (defaults to sys.argv).
104
- :return: Parsed namespace with config merged in.
103
+ :return: The argument parser.
105
104
  """
106
105
  parser = _ArgumentParser(
107
106
  description="Check signature params for proper documentation",
@@ -305,6 +304,16 @@ def parse_args(args: _t.Sequence[str] | None = None) -> _argparse.Namespace:
305
304
  metavar="STR",
306
305
  help="string to parse instead of files",
307
306
  )
307
+ return parser
308
+
309
+
310
+ def parse_args(args: _t.Sequence[str] | None = None) -> _argparse.Namespace:
311
+ """Parse CLI arguments and merge in config from pyproject.toml.
312
+
313
+ :param args: Argument list to parse (defaults to sys.argv).
314
+ :return: Parsed namespace with config merged in.
315
+ """
316
+ parser = build_parser()
308
317
  return parser.parse_args(args)
309
318
 
310
319
 
@@ -11,6 +11,7 @@ import logging as _logging
11
11
  import sys as _sys
12
12
  import warnings as _warnings
13
13
  from pathlib import Path as _Path
14
+ from pprint import pformat as _pformat
14
15
 
15
16
  from . import _decorators
16
17
  from ._check import run_checks as _run_checks
@@ -202,6 +203,8 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
202
203
  excludes=excludes or [],
203
204
  )
204
205
  setup_logger(config.verbose)
206
+ logger = _logging.getLogger(__package__)
207
+ logger.debug(_pformat(config))
205
208
  if config.list_checks:
206
209
  return int(bool(_print_checks())) # type: ignore
207
210
 
@@ -52,9 +52,13 @@ def parse_from_string(
52
52
  )
53
53
 
54
54
  parent = _Parent(node, directives, file, config)
55
- logger.debug(_FILE_INFO, source_name, "Parsing Python code successful")
55
+ logger.debug(_FILE_INFO, source_name, "parsing python code successful")
56
56
  except _ERRORS as err:
57
- logger.debug(_FILE_INFO, source_name, str(err).replace("\n", " "))
57
+ logger.debug(
58
+ _FILE_INFO,
59
+ source_name,
60
+ str(err).replace("\n", " ").lower(),
61
+ )
58
62
  parent = _Parent(error=type(err))
59
63
 
60
64
  return parent
@@ -16,7 +16,6 @@ import typing as _t
16
16
  from warnings import warn as _warn
17
17
 
18
18
  import astroid as _ast
19
- from astroid.nodes.scoped_nodes import scoped_nodes as _scoped_nodes
20
19
 
21
20
  from ._config import Config as _Config
22
21
  from ._module import Function as _Function
@@ -75,7 +74,7 @@ class Failure(list[Failed]):
75
74
  if (
76
75
  self._func.parent is not None
77
76
  and self._func.parent.name
78
- and not isinstance(self._func.parent, _scoped_nodes.Module)
77
+ and not isinstance(self._func.parent, _ast.nodes.Module)
79
78
  ):
80
79
  self._name = f"{self._func.parent.name}.{self._name}"
81
80
 
@@ -8,4 +8,4 @@ Allows for access to the version internally without cyclic imports
8
8
  caused by accessing it through __init__.
9
9
  """
10
10
 
11
- __version__ = "0.82.2"
11
+ __version__ = "0.83.0"
@@ -198,7 +198,7 @@ E = MessageMap(
198
198
  #: SIG4xx Parameters
199
199
  401: Message(
200
200
  "SIG401",
201
- "param not indented correctly",
201
+ "parameter not indented correctly",
202
202
  "incorrect-indent",
203
203
  ),
204
204
  402: Message(
@@ -0,0 +1,12 @@
1
+ """
2
+ docsig.plugin
3
+ =============
4
+ """
5
+
6
+ from ._flake8 import Flake8
7
+ from ._validate_pyproject import ValidatePyproject
8
+
9
+ __all__ = [
10
+ "Flake8",
11
+ "ValidatePyproject",
12
+ ]
@@ -1,32 +1,36 @@
1
1
  """
2
- docsig.plugin
3
- =============
2
+ docsig.plugin._flake8
3
+ =====================
4
4
 
5
5
  Flake8 plugin entry point that runs docsig checks and reports as flake8
6
6
  errors.
7
7
  """
8
8
 
9
- import ast
10
- import os
11
- import sys
12
- import typing as t
13
- from argparse import SUPPRESS, Namespace
14
- from pathlib import Path
15
-
16
- from ._config import Check as _Check
17
- from ._config import Config as _Config
18
- from ._config import Ignore as _Ignore
19
- from ._config import get_config as _get_config
20
- from ._config import merge_configs as _merge_configs
21
- from ._core import handle_deprecations, runner, setup_logger
22
- from ._version import __version__
23
- from .messages import FLAKE8, E
24
-
25
- Flake8Error = tuple[int, int, str, type[t.Any]]
26
- sys.path.append(os.path.abspath(os.getcwd()))
27
-
28
-
29
- class Docsig:
9
+ import ast as _ast
10
+ import os as _os
11
+ import sys as _sys
12
+ import typing as _t
13
+ from argparse import SUPPRESS as _SUPPRESS
14
+ from argparse import Namespace as _Namespace
15
+ from pathlib import Path as _Path
16
+
17
+ from .._config import Check as _Check
18
+ from .._config import Config as _Config
19
+ from .._config import Ignore as _Ignore
20
+ from .._config import get_config as _get_config
21
+ from .._config import merge_configs as _merge_configs
22
+ from .._core import handle_deprecations as _handle_deprecations
23
+ from .._core import runner as _runner
24
+ from .._core import setup_logger as _setup_logger
25
+ from .._version import __version__
26
+ from ..messages import FLAKE8 as _FLAKE8
27
+ from ..messages import E as _E
28
+
29
+ _Flake8Error = tuple[int, int, str, type[_t.Any]]
30
+ _sys.path.append(_os.path.abspath(_os.getcwd()))
31
+
32
+
33
+ class Flake8:
30
34
  """Plugin that runs docsig on a file and yields flake8 errors.
31
35
 
32
36
  :param tree: Parsed AST module (unused; flake8 requires it for the
@@ -37,9 +41,9 @@ class Docsig:
37
41
  off_by_default = False
38
42
  name = __package__
39
43
  version = __version__
40
- a = Namespace()
44
+ a = _Namespace()
41
45
 
42
- def __init__(self, tree: ast.Module, filename: str) -> None:
46
+ def __init__(self, tree: _ast.Module, filename: str) -> None:
43
47
  _tree = tree # noqa
44
48
  self.filename = filename
45
49
 
@@ -48,7 +52,7 @@ class Docsig:
48
52
  # might require that flake8 actually be installed, which is not a
49
53
  # requirement for this package
50
54
  @classmethod
51
- def add_options(cls, parser: t.Any) -> None:
55
+ def add_options(cls, parser: _t.Any) -> None:
52
56
  """Register CLI and config opts with the flake8 option parser.
53
57
 
54
58
  :param parser: Flake8 option manager to extend.
@@ -132,18 +136,18 @@ class Docsig:
132
136
  "--sig-ignore-typechecker",
133
137
  action="store_true",
134
138
  parse_from_config=True,
135
- help=SUPPRESS,
139
+ help=_SUPPRESS,
136
140
  )
137
141
 
138
142
  @classmethod
139
- def parse_options(cls, a: Namespace) -> None:
143
+ def parse_options(cls, a: _Namespace) -> None:
140
144
  """Merge parsed options with pyproject config into class state.
141
145
 
142
146
  :param a: Argparse namespace from flake8.
143
147
  """
144
148
  if getattr(a, "sig_ignore_typechecker", False):
145
149
  a.extend_ignore = list(a.extend_ignore or [])
146
- handle_deprecations(
150
+ _handle_deprecations(
147
151
  getattr(a, "sig_ignore_typechecker", False),
148
152
  a.extend_ignore,
149
153
  ["SIG501", "SIG502", "SIG503", "SIG504", "SIG505", "SIG506"],
@@ -155,7 +159,7 @@ class Docsig:
155
159
  _get_config(__package__),
156
160
  )
157
161
 
158
- def run(self) -> t.Generator[Flake8Error, None, None]:
162
+ def run(self) -> _t.Generator[_Flake8Error, None, None]:
159
163
  """Run docsig on the file and yield flake8 errors per failure.
160
164
 
161
165
  If both class and class-constructor checks are enabled,
@@ -167,15 +171,15 @@ class Docsig:
167
171
  """
168
172
  if self.a.check_class and self.a.check_class_constructor:
169
173
  line = "{msg}".format(
170
- msg=FLAKE8.format(
171
- ref=E[5].ref,
172
- description=E[5].description,
173
- symbolic=E[5].symbolic,
174
+ msg=_FLAKE8.format(
175
+ ref=_E[5].ref,
176
+ description=_E[5].description,
177
+ symbolic=_E[5].symbolic,
174
178
  ),
175
179
  )
176
180
  yield 0, 0, line, self.__class__
177
181
  else:
178
- setup_logger(self.a.verbose)
182
+ _setup_logger(self.a.verbose)
179
183
  check = _Check(
180
184
  class_=self.a.check_class,
181
185
  class_constructor=self.a.check_class_constructor,
@@ -196,14 +200,14 @@ class Docsig:
196
200
  ignore=ignore,
197
201
  verbose=self.a.verbose,
198
202
  )
199
- results = runner(Path(self.filename), config)
203
+ results = _runner(_Path(self.filename), config)
200
204
  for result in results:
201
205
  if not result.retcode:
202
206
  continue
203
207
 
204
208
  for info in result:
205
209
  line = "{msg} '{name}'".format(
206
- msg=FLAKE8.format(
210
+ msg=_FLAKE8.format(
207
211
  ref=info.ref,
208
212
  description=info.description,
209
213
  symbolic=info.symbolic,
@@ -0,0 +1,103 @@
1
+ """
2
+ docsig.plugin._validate_pyproject
3
+ =================================
4
+ """
5
+
6
+ # pylint: disable=protected-access
7
+
8
+ import typing as _t
9
+
10
+ # noinspection PyFinal
11
+ from argparse import SUPPRESS as _SUPPRESS
12
+ from argparse import Action as _Action
13
+
14
+ import docsig as _docsig
15
+
16
+ from .._config import build_parser as _build_parser
17
+
18
+ _ID = "https://docsig.io/en/latest/usage/configuration/schema.json"
19
+ _SCHEMA = "http://json-schema.org/draft-07/schema#"
20
+ _DESCRIPTION_EXCLUDE = ("comma separated ",)
21
+ _NARGS = ("+", "*")
22
+ _EXCLUDED_OPTIONS = ("help", "list-checks", "string", "version")
23
+
24
+
25
+ class ValidatePyproject(dict[str, _t.Any]):
26
+ """Schema for the docsig tool section in pyproject.toml.
27
+
28
+ :param tool_name: The tool name to validate.
29
+ """
30
+
31
+ def __init__(self, tool_name: str = "docsig") -> None:
32
+ assert tool_name == "docsig", "Only docsig is supported."
33
+ self._parser = _build_parser()
34
+ super().__init__(
35
+ {
36
+ "$comment": _CMT,
37
+ "$id": _ID,
38
+ "$schema": _SCHEMA,
39
+ "type": "object",
40
+ "additionalProperties": False,
41
+ },
42
+ )
43
+ self._get_properties()
44
+ self._get_mutually_exclusive_options()
45
+
46
+ @staticmethod
47
+ def _skip_action(action: _Action, name: str) -> bool:
48
+ if not action.option_strings:
49
+ return True
50
+
51
+ if action.help == _SUPPRESS:
52
+ return True
53
+
54
+ if name in _EXCLUDED_OPTIONS:
55
+ return True
56
+
57
+ return False
58
+
59
+ def _get_properties(self) -> None:
60
+ self["properties"] = {}
61
+ for action in self._parser._actions:
62
+ name = action.dest.replace("_", "-")
63
+ if self._skip_action(action, name):
64
+ continue
65
+
66
+ self["properties"][name] = {"default": action.default}
67
+ if isinstance(action.default, bool):
68
+ self["properties"][name]["type"] = "boolean"
69
+ elif isinstance(action.default, list) or action.nargs in _NARGS:
70
+ self["properties"][name]["type"] = "array"
71
+ self["properties"][name]["items"] = {"type": "string"}
72
+ elif action.type is None:
73
+ self["properties"][name]["type"] = "string"
74
+
75
+ if action.help:
76
+ description = action.help
77
+ for exclude in _DESCRIPTION_EXCLUDE:
78
+ description = description.replace(exclude, "")
79
+
80
+ self["properties"][name]["description"] = description
81
+
82
+ def _get_mutually_exclusive_options(self) -> None:
83
+ for group in self._parser._mutually_exclusive_groups:
84
+ names = []
85
+ for action in group._group_actions:
86
+ name = action.dest.replace("_", "-")
87
+ if self._skip_action(action, name):
88
+ continue
89
+
90
+ names.append(name)
91
+
92
+ if len(names) > 1:
93
+ if "allOf" not in self:
94
+ self["allOf"] = []
95
+
96
+ self["allOf"].append({"not": {"required": names}})
97
+
98
+
99
+ _CMT = ValidatePyproject.__doc__.splitlines()[0].lower()[:-1] # type: ignore
100
+
101
+ # for
102
+ # $ validate-pyproject --help
103
+ ValidatePyproject.__doc__ = _docsig.__doc__
@@ -11,7 +11,7 @@ line-length = 79
11
11
  allow_dirty = true
12
12
  commit = true
13
13
  commit_args = "-sS"
14
- current_version = "0.82.2"
14
+ current_version = "0.83.0"
15
15
  message = "bump: version {current_version} → {new_version}"
16
16
  sign_tags = true
17
17
  tag = true
@@ -103,7 +103,7 @@ non_interactive = true
103
103
 
104
104
  [tool.poetry]
105
105
  authors = [
106
- "jshwi <stephen@jshwisolutions.com>"
106
+ "jshwi <s.whitlock@live.com>"
107
107
  ]
108
108
  description = "Check signature params for proper documentation"
109
109
  documentation = "https://docsig.io/en/latest"
@@ -117,12 +117,12 @@ keywords = [
117
117
  ]
118
118
  license = "MIT"
119
119
  maintainers = [
120
- "jshwi <stephen@jshwisolutions.com>"
120
+ "jshwi <s.whitlock@live.com>"
121
121
  ]
122
122
  name = "docsig"
123
123
  readme = "README.rst"
124
124
  repository = "https://github.com/jshwi/docsig"
125
- version = "0.82.2"
125
+ version = "0.83.0"
126
126
 
127
127
  [tool.poetry.dependencies]
128
128
  Sphinx = ">=7,<9"
@@ -146,15 +146,17 @@ tomli = "^2.0.1"
146
146
  tomli-w = "^1.0.0"
147
147
  towncrier = ">=23.11,<26.0"
148
148
  tox = "^4.15.0"
149
+ validate-pyproject = {extras = ["all", "store"], version = "^0.25"}
149
150
  vulture = "^2.11"
150
151
 
151
152
  [tool.poetry.group.docs.dependencies]
152
153
  furo = ">=2024.4.27,<2026.0.0"
153
154
  myst-parser = ">=3.0.1,<5.0.0"
154
- pytest = "8.3.5"
155
+ pytest = "9.0.3"
155
156
  pyyaml = "^6.0.1"
156
157
  roman-numerals = "4.1.0"
157
158
  sphinx-copybutton = "^0.5.2"
159
+ sphinx-jsonschema = "^1.19.2"
158
160
  sphinx-markdown-builder = ">=0.5.5,<0.7.0"
159
161
  sphinx-sitemap = "^2.9.0"
160
162
  templatest = ">=0.10.1,<0.13.0"
@@ -163,7 +165,7 @@ templatest = ">=0.10.1,<0.13.0"
163
165
  flake8 = "^7.1.0"
164
166
 
165
167
  [tool.poetry.group.tests.dependencies]
166
- pytest = "^8.2.0"
168
+ pytest = ">=8.2,<10.0"
167
169
  pytest-benchmark = ">=4,<6"
168
170
  pytest-cov = ">=5,<8"
169
171
  pytest-gitignore = "^1.3"
@@ -173,7 +175,10 @@ pytest-xdist = "^3.6.1"
173
175
  templatest = ">=0.10.1,<0.13.0"
174
176
 
175
177
  [tool.poetry.plugins."flake8.extension"]
176
- SIG = "docsig.plugin:Docsig"
178
+ SIG = "docsig.plugin:Flake8"
179
+
180
+ [tool.poetry.plugins."validate_pyproject.tool_schema"]
181
+ docsig = "docsig.plugin:ValidatePyproject"
177
182
 
178
183
  [tool.poetry.scripts]
179
184
  docsig = "docsig.__main__:main"
@@ -225,6 +230,9 @@ name = "Changed"
225
230
  [tool.towncrier.fragment.deprecate]
226
231
  name = "Deprecated"
227
232
 
233
+ [tool.towncrier.fragment.feat]
234
+ name = "Feature"
235
+
228
236
  [tool.towncrier.fragment.fix]
229
237
  name = "Fixed"
230
238
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes