docsig 0.55.0__tar.gz → 0.57.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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: docsig
3
- Version: 0.55.0
3
+ Version: 0.57.0
4
4
  Summary: Check signature params for proper documentation
5
5
  Home-page: https://pypi.org/project/docsig/
6
6
  License: MIT
@@ -9,10 +9,9 @@ Author: jshwi
9
9
  Author-email: stephen@jshwisolutions.com
10
10
  Maintainer: jshwi
11
11
  Maintainer-email: stephen@jshwisolutions.com
12
- Requires-Python: >=3.8,<4.0
12
+ Requires-Python: >=3.8.1,<4.0.0
13
13
  Classifier: License :: OSI Approved :: MIT License
14
14
  Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3.8
16
15
  Classifier: Programming Language :: Python :: 3.9
17
16
  Classifier: Programming Language :: Python :: 3.10
18
17
  Classifier: Programming Language :: Python :: 3.11
@@ -152,16 +151,49 @@ Options can also be configured with the pyproject.toml file
152
151
  check-overridden = false
153
152
  check-protected = false
154
153
  disable = [
155
- "E101",
156
- "E102",
157
- "E103",
154
+ "SIG101",
155
+ "SIG102",
156
+ "SIG402",
158
157
  ]
159
158
  target = [
160
- "E102",
161
- "E103",
162
- "E104",
159
+ "SIG202",
160
+ "SIG203",
161
+ "SIG201",
163
162
  ]
164
163
 
164
+ Flake8
165
+ ******
166
+
167
+ ``docsig`` can also be used as a ``flake8`` plugin. Install ``flake8`` and
168
+ ensure your installation has registered `docsig`
169
+
170
+ .. code-block:: console
171
+
172
+ $ flake8 --version
173
+ 7.1.0 (docsig: 0.57.0, mccabe: 0.7.0, pycodestyle: 2.12.0, pyflakes: 3.2.0) CPython 3.8.13 on Darwin
174
+
175
+ And now use `flake8` to lint your files
176
+
177
+ .. code-block:: console
178
+
179
+ $ flake8 example.py
180
+ example.py:1:1: SIG202 includes parameters that do not exist (params-do-not-exist) 'function'
181
+
182
+ With ``flake8`` the pyproject.toml config will still be the base config, though the
183
+ `ini files <https://flake8.pycqa.org/en/latest/user/configuration.html#configuration-locations>`_ ``flake8`` gets it config from will override the pyproject.toml config.
184
+ For ``flake8`` all args and config options are prefixed with ``sig`` to
185
+ avoid any potential conflicts with other plugins
186
+
187
+ .. code-block:: ini
188
+
189
+ [flake8]
190
+ sig-check-dunders = True
191
+ sig-check-overridden = True
192
+ sig-check-protected = True
193
+
194
+ ..
195
+ end flake8
196
+
165
197
  API
166
198
  ***
167
199
 
@@ -196,7 +228,7 @@ API
196
228
  ... """
197
229
  >>> docsig(string=string, no_ansi=True)
198
230
  2 in function
199
- E102: includes parameters that do not exist (params-do-not-exist)
231
+ SIG202: includes parameters that do not exist (params-do-not-exist)
200
232
  1
201
233
 
202
234
  A full list of checks can be found `here <https://docsig.readthedocs.io/en/latest/usage/messages.html>`__
@@ -204,6 +236,9 @@ A full list of checks can be found `here <https://docsig.readthedocs.io/en/lates
204
236
  Message Control
205
237
  ***************
206
238
 
239
+ If you have been using ``docsig`` prior to ``v0.56.0``, please see
240
+ `updated messages <https://docsig.readthedocs.io/en/latest/deprecated/messages.html>`_
241
+
207
242
  `Documentation on message control <https://docsig.readthedocs.io/en/latest/usage/message-control.html>`_
208
243
 
209
244
  Classes
@@ -222,7 +257,7 @@ It can be added to your .pre-commit-config.yaml as follows:
222
257
 
223
258
  repos:
224
259
  - repo: https://github.com/jshwi/docsig
225
- rev: v0.55.0
260
+ rev: v0.57.0
226
261
  hooks:
227
262
  - id: docsig
228
263
  args:
@@ -124,16 +124,49 @@ Options can also be configured with the pyproject.toml file
124
124
  check-overridden = false
125
125
  check-protected = false
126
126
  disable = [
127
- "E101",
128
- "E102",
129
- "E103",
127
+ "SIG101",
128
+ "SIG102",
129
+ "SIG402",
130
130
  ]
131
131
  target = [
132
- "E102",
133
- "E103",
134
- "E104",
132
+ "SIG202",
133
+ "SIG203",
134
+ "SIG201",
135
135
  ]
136
136
 
137
+ Flake8
138
+ ******
139
+
140
+ ``docsig`` can also be used as a ``flake8`` plugin. Install ``flake8`` and
141
+ ensure your installation has registered `docsig`
142
+
143
+ .. code-block:: console
144
+
145
+ $ flake8 --version
146
+ 7.1.0 (docsig: 0.57.0, mccabe: 0.7.0, pycodestyle: 2.12.0, pyflakes: 3.2.0) CPython 3.8.13 on Darwin
147
+
148
+ And now use `flake8` to lint your files
149
+
150
+ .. code-block:: console
151
+
152
+ $ flake8 example.py
153
+ example.py:1:1: SIG202 includes parameters that do not exist (params-do-not-exist) 'function'
154
+
155
+ With ``flake8`` the pyproject.toml config will still be the base config, though the
156
+ `ini files <https://flake8.pycqa.org/en/latest/user/configuration.html#configuration-locations>`_ ``flake8`` gets it config from will override the pyproject.toml config.
157
+ For ``flake8`` all args and config options are prefixed with ``sig`` to
158
+ avoid any potential conflicts with other plugins
159
+
160
+ .. code-block:: ini
161
+
162
+ [flake8]
163
+ sig-check-dunders = True
164
+ sig-check-overridden = True
165
+ sig-check-protected = True
166
+
167
+ ..
168
+ end flake8
169
+
137
170
  API
138
171
  ***
139
172
 
@@ -168,7 +201,7 @@ API
168
201
  ... """
169
202
  >>> docsig(string=string, no_ansi=True)
170
203
  2 in function
171
- E102: includes parameters that do not exist (params-do-not-exist)
204
+ SIG202: includes parameters that do not exist (params-do-not-exist)
172
205
  1
173
206
 
174
207
  A full list of checks can be found `here <https://docsig.readthedocs.io/en/latest/usage/messages.html>`__
@@ -176,6 +209,9 @@ A full list of checks can be found `here <https://docsig.readthedocs.io/en/lates
176
209
  Message Control
177
210
  ***************
178
211
 
212
+ If you have been using ``docsig`` prior to ``v0.56.0``, please see
213
+ `updated messages <https://docsig.readthedocs.io/en/latest/deprecated/messages.html>`_
214
+
179
215
  `Documentation on message control <https://docsig.readthedocs.io/en/latest/usage/message-control.html>`_
180
216
 
181
217
  Classes
@@ -194,7 +230,7 @@ It can be added to your .pre-commit-config.yaml as follows:
194
230
 
195
231
  repos:
196
232
  - repo: https://github.com/jshwi/docsig
197
- rev: v0.55.0
233
+ rev: v0.57.0
198
234
  hooks:
199
235
  - id: docsig
200
236
  args:
@@ -14,7 +14,7 @@ def excepthook(no_ansi: bool = False) -> None:
14
14
 
15
15
  :param no_ansi: Disable ANSI output.
16
16
  """
17
- if _e.get("DOCSIG_DEBUG", None) != "1":
17
+ if _e.get("DOCSIG_DEBUG") != "1":
18
18
  _sys.excepthook = lambda x, y, _: _pretty_print_error(
19
19
  x, str(y), no_ansi
20
20
  )
@@ -80,24 +80,24 @@ class Failure(_t.List[str]):
80
80
  if not comment.isvalid:
81
81
  if comment.ismodule:
82
82
  # unknown-module-directive
83
- self._add(_E[201], directive=comment.kind)
83
+ self._add(_E[1], directive=comment.kind)
84
84
  else:
85
85
  # unknown-inline-directive
86
- self._add(_E[202], directive=comment.kind)
86
+ self._add(_E[2], directive=comment.kind)
87
87
  else:
88
88
  for rule in comment:
89
89
  if not rule.isknown:
90
90
  if comment.ismodule:
91
91
  # unknown-module-directive-option
92
92
  self._add(
93
- _E[203],
93
+ _E[3],
94
94
  directive=comment.kind,
95
95
  option=rule.description,
96
96
  )
97
97
  else:
98
98
  # unknown-inline-directive-option
99
99
  self._add(
100
- _E[204],
100
+ _E[4],
101
101
  directive=comment.kind,
102
102
  option=rule.description,
103
103
  )
@@ -105,10 +105,10 @@ class Failure(_t.List[str]):
105
105
  def _sig1xx_missing(self) -> None:
106
106
  if not self._func.isinit:
107
107
  # function-doc-missing
108
- self._add(_E[113])
108
+ self._add(_E[101])
109
109
  else:
110
110
  # class-doc-missing
111
- self._add(_E[114])
111
+ self._add(_E[102])
112
112
 
113
113
  def _sig2xx_signature(self) -> None:
114
114
  if self._func.docstring.args.duplicated:
@@ -120,7 +120,7 @@ class Failure(_t.List[str]):
120
120
  self._func.docstring.args.pop(count)
121
121
 
122
122
  # duplicate-params-found
123
- self._add(_E[106])
123
+ self._add(_E[201])
124
124
  # there are non-existing params in the docstring
125
125
  elif len(self._func.docstring.args) > len(self._func.signature.args):
126
126
  # pop the parameters that do not exist so that they are
@@ -133,7 +133,7 @@ class Failure(_t.List[str]):
133
133
  if count > len(self._func.signature.args):
134
134
  self._func.docstring.args.pop(count - 1)
135
135
  # params-do-not-exist
136
- self._add(_E[102])
136
+ self._add(_E[202])
137
137
  # there are more args in sig than doc, so doc params missing
138
138
  elif len(self._func.signature.args) > len(self._func.docstring.args):
139
139
  # append the parameters that are missing so that they are
@@ -148,33 +148,33 @@ class Failure(_t.List[str]):
148
148
  _Param(arg.kind, arg.name, _VALID_DESCRIPTION, 0)
149
149
  )
150
150
  # params-missing
151
- self._add(_E[103])
151
+ self._add(_E[203])
152
152
 
153
153
  def _sig3xx_description(self, doc: _Param) -> None:
154
154
  if doc.description is None:
155
- self._add(_E[117])
155
+ self._add(_E[301])
156
156
  elif doc.description is not None and not doc.description.startswith(
157
157
  " "
158
158
  ):
159
159
  # syntax-error-in-description
160
- self._add(_E[115])
160
+ self._add(_E[302])
161
161
  # if the parameter does not have a name, but exists, then it
162
162
  # must be incorrectly documented
163
163
  elif doc.name == _UNNAMED:
164
164
  # param-incorrectly-documented
165
- self._add(_E[107])
165
+ self._add(_E[303])
166
166
 
167
167
  def _sig4xx_parameters(self, doc: _Param, sig: _Param) -> None:
168
168
  if doc.indent > 0:
169
169
  # incorrect-indent
170
- self._add(_E[116])
170
+ self._add(_E[401])
171
171
  elif doc != sig:
172
172
  if (
173
173
  sig.name in self._func.docstring.args.names
174
174
  or doc.name in self.func.signature.args.names
175
175
  ):
176
176
  # params-out-of-order
177
- self._add(_E[101])
177
+ self._add(_E[402])
178
178
  elif (
179
179
  doc.name != _UNNAMED
180
180
  and sig.name is not None
@@ -182,10 +182,10 @@ class Failure(_t.List[str]):
182
182
  ):
183
183
  if _almost_equal(sig.name, doc.name, _MIN_MATCH, _MAX_MATCH):
184
184
  # spelling-error
185
- self._add(_E[112])
185
+ self._add(_E[403])
186
186
  else:
187
187
  # param-not-equal-to-arg
188
- self._add(_E[110])
188
+ self._add(_E[404])
189
189
 
190
190
  def _sig5xx_returns(self) -> None:
191
191
  if not self._func.isinit and not (
@@ -194,28 +194,28 @@ class Failure(_t.List[str]):
194
194
  # no types, cannot know either way
195
195
  if self._func.signature.rettype == _RetType.UNTYPED:
196
196
  # confirm-return-needed
197
- self._add(_E[109], hint=True)
197
+ self._add(_E[501], hint=True)
198
198
  # return type is none, so no return should be documented
199
199
  elif self._func.docstring.returns:
200
200
  if self._func.signature.rettype == _RetType.NONE:
201
201
  # return-documented-for-none
202
- self._add(_E[104])
202
+ self._add(_E[502])
203
203
  # return type is some, so return should be documented
204
204
  elif self._func.signature.returns:
205
205
  # return-missing
206
206
  self._add(
207
- _E[105],
207
+ _E[503],
208
208
  hint=_has_bad_return(str(self._func.docstring.string)),
209
209
  )
210
210
  elif self._func.docstring.returns:
211
211
  # method is init, so no return should be documented
212
212
  if self._func.isinit:
213
213
  # class-return-documented
214
- self._add(_E[111], hint=True)
214
+ self._add(_E[504], hint=True)
215
215
  # method is property and not set to document property
216
216
  elif self._func.isproperty and not self._check_property_returns:
217
217
  # return-documented-for-property
218
- self._add(_E[108], hint=True)
218
+ self._add(_E[505], hint=True)
219
219
 
220
220
  @property
221
221
  def func(self) -> _Function:
@@ -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.55.0"
11
+ __version__ = "0.57.0"
@@ -6,12 +6,16 @@ docsig.messages
6
6
  from __future__ import annotations
7
7
 
8
8
  import typing as _t
9
+ from warnings import warn as _warn
9
10
 
10
11
  #: Error code for unknown errors.
11
- UNKNOWN = "E000"
12
+ UNKNOWN = "SIG000"
12
13
 
13
14
  #: Default template to format message strings.
14
- TEMPLATE = "{code}: {description} ({symbolic})"
15
+ TEMPLATE = "{ref}: {description} ({symbolic})"
16
+
17
+ #: Flake8 template to format message strings.
18
+ FLAKE8 = "{ref} {description} ({symbolic})"
15
19
 
16
20
 
17
21
  class Message(_t.NamedTuple):
@@ -39,7 +43,7 @@ class Message(_t.NamedTuple):
39
43
  This might exist due to a typo or an attempt to retrieve an
40
44
  error that does not exist.
41
45
  """
42
- return self.code != UNKNOWN
46
+ return self.ref != UNKNOWN
43
47
 
44
48
  def fstring(self, template: str) -> str:
45
49
  """Return message values as a string.
@@ -48,7 +52,7 @@ class Message(_t.NamedTuple):
48
52
  :return: Formatted string.
49
53
  """
50
54
  return template.format(
51
- code=self.code,
55
+ ref=self.ref,
52
56
  description=self.description,
53
57
  symbolic=self.symbolic,
54
58
  )
@@ -68,7 +72,18 @@ class MessageMap(_t.Dict[int, Message]):
68
72
  :return: Message if valid ref else an unknown message type.
69
73
  """
70
74
  for value in self.values():
71
- if ref in (value.ref, value.code, value.symbolic):
75
+ if ref == value.code:
76
+ _warn(
77
+ "Exxx errors are deprecated and might not be supported in "
78
+ "a future version, see "
79
+ "https://docsig.readthedocs.io/en/latest/deprecated/"
80
+ "messages.html",
81
+ category=DeprecationWarning,
82
+ stacklevel=6,
83
+ )
84
+ return value
85
+
86
+ if ref in (value.ref, value.symbolic):
72
87
  return value
73
88
 
74
89
  return Message(UNKNOWN, UNKNOWN, ref)
@@ -84,144 +99,142 @@ class MessageMap(_t.Dict[int, Message]):
84
99
  @property
85
100
  def all(self) -> Messages:
86
101
  """Get all messages that aren't a config error."""
87
- return Messages(
88
- v for k, v in self.items() if str(k).startswith(str(1))
89
- )
102
+ return Messages(v for k, v in self.items() if len(str(k)) > 1)
90
103
 
91
104
 
92
105
  # SIGxxx: Error
93
106
  E = MessageMap(
94
107
  {
95
108
  #: SIG0xx Config
96
- 201: Message(
109
+ 1: Message(
97
110
  "SIG001",
98
111
  "E201",
99
112
  "unknown module comment directive '{directive}'",
100
113
  "unknown-module-directive",
101
114
  ),
102
- 202: Message(
115
+ 2: Message(
103
116
  "SIG002",
104
117
  "E202",
105
118
  "unknown inline comment directive '{directive}'",
106
119
  "unknown-inline-directive",
107
120
  ),
108
- 203: Message(
121
+ 3: Message(
109
122
  "SIG003",
110
123
  "E203",
111
124
  "unknown module comment option for {directive} '{option}'",
112
125
  "unknown-module-directive-option",
113
126
  ),
114
- 204: Message(
127
+ 4: Message(
115
128
  "SIG004",
116
129
  "E204",
117
130
  "unknown inline comment option for {directive} '{option}'",
118
131
  "unknown-inline-directive-option",
119
132
  ),
120
133
  #: SIG1xx Missing
121
- 113: Message(
134
+ 101: Message(
122
135
  "SIG101",
123
136
  "E113",
124
137
  "function is missing a docstring",
125
138
  "function-doc-missing",
126
139
  ),
127
- 114: Message(
140
+ 102: Message(
128
141
  "SIG102",
129
142
  "E114",
130
143
  "class is missing a docstring",
131
144
  "class-doc-missing",
132
145
  ),
133
146
  #: SIG2xx Signature
134
- 106: Message(
147
+ 201: Message(
135
148
  "SIG201",
136
149
  "E106",
137
150
  "duplicate parameters found",
138
151
  "duplicate-params-found",
139
152
  ),
140
- 102: Message(
153
+ 202: Message(
141
154
  "SIG202",
142
155
  "E102",
143
156
  "includes parameters that do not exist",
144
157
  "params-do-not-exist",
145
158
  ),
146
- 103: Message(
159
+ 203: Message(
147
160
  "SIG203",
148
161
  "E103",
149
162
  "parameters missing",
150
163
  "params-missing",
151
164
  ),
152
165
  #: SIG3xx Parameters
153
- 117: Message(
166
+ 301: Message(
154
167
  "SIG301",
155
168
  "E117",
156
169
  "description missing from parameter",
157
170
  "description-missing",
158
171
  ),
159
- 115: Message(
172
+ 302: Message(
160
173
  "SIG302",
161
174
  "E115",
162
175
  "syntax error in description",
163
176
  "syntax-error-in-description",
164
177
  ),
165
- 107: Message(
178
+ 303: Message(
166
179
  "SIG303",
167
180
  "E107",
168
181
  "parameter appears to be incorrectly documented",
169
182
  "param-incorrectly-documented",
170
183
  ),
171
184
  #: SIG4xx Description
172
- 116: Message(
185
+ 401: Message(
173
186
  "SIG401",
174
187
  "E116",
175
188
  "param not indented correctly",
176
189
  "incorrect-indent",
177
190
  ),
178
- 101: Message(
191
+ 402: Message(
179
192
  "SIG402",
180
193
  "E101",
181
194
  "parameters out of order",
182
195
  "params-out-of-order",
183
196
  ),
184
- 112: Message(
197
+ 403: Message(
185
198
  "SIG403",
186
199
  "E112",
187
200
  "spelling error found in documented parameter",
188
201
  "spelling-error",
189
202
  ),
190
- 110: Message(
203
+ 404: Message(
191
204
  "SIG404",
192
205
  "E110",
193
206
  "documented parameter not equal to its respective argument",
194
207
  "param-not-equal-to-arg",
195
208
  ),
196
209
  #: SIG5xx Returns
197
- 109: Message(
210
+ 501: Message(
198
211
  "SIG501",
199
212
  "E109",
200
213
  "cannot determine whether a return statement should exist",
201
214
  "confirm-return-needed",
202
215
  "annotate type to indicate whether return documentation needed",
203
216
  ),
204
- 104: Message(
217
+ 502: Message(
205
218
  "SIG502",
206
219
  "E104",
207
220
  "return statement documented for None",
208
221
  "return-documented-for-none",
209
222
  ),
210
- 105: Message(
223
+ 503: Message(
211
224
  "SIG503",
212
225
  "E105",
213
226
  "return missing from docstring",
214
227
  "return-missing",
215
228
  "it is possible a syntax error could be causing this",
216
229
  ),
217
- 111: Message(
230
+ 504: Message(
218
231
  "SIG504",
219
232
  "E111",
220
233
  "return statement documented for class",
221
234
  "class-return-documented",
222
235
  "a class does not return a value during instantiation",
223
236
  ),
224
- 108: Message(
237
+ 505: Message(
225
238
  "SIG505",
226
239
  "E108",
227
240
  "return statement documented for property",
@@ -0,0 +1,165 @@
1
+ """Flake8 implementation of docsig."""
2
+
3
+ import ast
4
+ import contextlib
5
+ import io
6
+ import re
7
+ import sys
8
+ import typing as t
9
+ from argparse import Namespace
10
+
11
+ import docsig
12
+
13
+ Flake8Error = t.Tuple[int, int, str, t.Type]
14
+
15
+
16
+ class Docsig:
17
+ """Flake8 implementation of docsig class.
18
+
19
+ :param tree: Ast module, which will not be used by flake8 will
20
+ provide.
21
+ :param filename: Filename to pass to docsig.
22
+ """
23
+
24
+ off_by_default = False
25
+ name = docsig.__name__
26
+ version = docsig.__version__
27
+ options_dict: t.Dict[str, bool] = {}
28
+
29
+ def __init__(self, tree: ast.Module, filename: str) -> None:
30
+ _tree = tree # noqa
31
+ self.filename = filename
32
+
33
+ # won't import flake8 type
34
+ # conflicts with this module name
35
+ # might require that flake8 actually be installed, which is not a
36
+ # requirement for this package
37
+ @classmethod
38
+ def add_options(cls, parser) -> None:
39
+ """Add flake8 commandline and config options.sig_
40
+
41
+ :param parser: Flake8 option manager.
42
+ """
43
+ parser.add_option(
44
+ "--sig-check-class",
45
+ action="store_true",
46
+ parse_from_config=True,
47
+ help="check class docstrings",
48
+ )
49
+ parser.add_option(
50
+ "--sig-check-class-constructor",
51
+ action="store_true",
52
+ parse_from_config=True,
53
+ help="check __init__ methods. Note: mutually incompatible with -c",
54
+ )
55
+ parser.add_option(
56
+ "--sig-check-dunders",
57
+ action="store_true",
58
+ parse_from_config=True,
59
+ help="check dunder methods",
60
+ )
61
+ parser.add_option(
62
+ "--sig-check-protected-class-methods",
63
+ action="store_true",
64
+ parse_from_config=True,
65
+ help="check public methods belonging to protected classes",
66
+ )
67
+ parser.add_option(
68
+ "--sig-check-nested",
69
+ action="store_true",
70
+ parse_from_config=True,
71
+ help="check nested functions and classes",
72
+ )
73
+ parser.add_option(
74
+ "--sig-check-overridden",
75
+ action="store_true",
76
+ parse_from_config=True,
77
+ help="check overridden methods",
78
+ )
79
+ parser.add_option(
80
+ "--sig-check-protected",
81
+ action="store_true",
82
+ parse_from_config=True,
83
+ help="check protected functions and classes",
84
+ )
85
+ parser.add_option(
86
+ "--sig-check-property-returns",
87
+ action="store_true",
88
+ parse_from_config=True,
89
+ help="check property return values",
90
+ )
91
+ parser.add_option(
92
+ "--sig-ignore-no-params",
93
+ action="store_true",
94
+ parse_from_config=True,
95
+ help="ignore docstrings where parameters are not documented",
96
+ )
97
+ parser.add_option(
98
+ "--sig-ignore-args",
99
+ action="store_true",
100
+ parse_from_config=True,
101
+ help="ignore args prefixed with an asterisk",
102
+ )
103
+ parser.add_option(
104
+ "--sig-ignore-kwargs",
105
+ action="store_true",
106
+ parse_from_config=True,
107
+ help="ignore kwargs prefixed with two asterisks",
108
+ )
109
+ parser.add_option(
110
+ "--sig-ignore-typechecker",
111
+ action="store_true",
112
+ parse_from_config=True,
113
+ help="ignore checking return values",
114
+ )
115
+
116
+ @classmethod
117
+ def parse_options(cls, options: Namespace) -> None:
118
+ """Parse flake8 options into am instance accessible dict.
119
+
120
+ :param options: Argparse namespace.
121
+ """
122
+ cls.options_dict = {
123
+ "check_class": options.sig_check_class,
124
+ "check_class_constructor": options.sig_check_class_constructor,
125
+ "check_dunders": options.sig_check_dunders,
126
+ "check_protected_class_methods": (
127
+ options.sig_check_protected_class_methods
128
+ ),
129
+ "check_nested": options.sig_check_nested,
130
+ "check_overridden": options.sig_check_overridden,
131
+ "check_protected": options.sig_check_protected,
132
+ "check_property_returns": options.sig_check_property_returns,
133
+ "ignore_no_params": options.sig_ignore_no_params,
134
+ "ignore_args": options.sig_ignore_args,
135
+ "ignore_kwargs": options.sig_ignore_kwargs,
136
+ "ignore_typechecker": options.sig_ignore_typechecker,
137
+ }
138
+
139
+ def run(self) -> t.Generator[Flake8Error, None, None]:
140
+ """Run docsig and possibly yield a flake8 error.
141
+
142
+ :return: Flake8 error, if there is one.
143
+ """
144
+ buffer = io.StringIO()
145
+ with contextlib.redirect_stdout(buffer):
146
+ sys.argv = [
147
+ __package__,
148
+ self.filename,
149
+ *[
150
+ f"--{k.replace('_', '-')}"
151
+ for k, v in self.options_dict.items()
152
+ if v
153
+ ],
154
+ ]
155
+ docsig.main()
156
+
157
+ results = re.split(r"^(?!\s)", buffer.getvalue(), flags=re.MULTILINE)
158
+ for result in results:
159
+ if not result:
160
+ continue
161
+
162
+ header, remainder = result.splitlines()[:2]
163
+ lineno, func_name = header.split(":", 1)[1].split(" in ", 1)
164
+ line = f"{remainder.lstrip().replace(':', '')} '{func_name}'"
165
+ yield int(lineno), 0, line, self.__class__
@@ -7,12 +7,56 @@ requires = [
7
7
  [tool.black]
8
8
  line-length = 79
9
9
 
10
+ [tool.bumpversion]
11
+ allow_dirty = true
12
+ commit = true
13
+ commit_args = "-sS"
14
+ current_version = "0.57.0"
15
+ message = "bump: version {current_version} → {new_version}"
16
+ sign_tags = true
17
+ tag = true
18
+
19
+ [[tool.bumpversion.files]]
20
+ filename = "docs/conf.py"
21
+
22
+ [[tool.bumpversion.files]]
23
+ filename = "docsig/_version.py"
24
+
25
+ [[tool.bumpversion.files]]
26
+ filename = "pyproject.toml"
27
+ replace = 'version = "{new_version}"'
28
+ search = 'version = "{current_version}"'
29
+
30
+ [[tool.bumpversion.files]]
31
+ filename = "package.json"
32
+ replace = '"version": "{new_version}"'
33
+ search = '"version": "{current_version}"'
34
+
35
+ [[tool.bumpversion.files]]
36
+ filename = "README.rst"
37
+ replace = "rev: v{new_version}"
38
+ search = "rev: v{current_version}"
39
+
40
+ [[tool.bumpversion.files]]
41
+ filename = "README.rst"
42
+ replace = "docsig: {new_version}"
43
+ search = "docsig: {current_version}"
44
+
45
+ [[tool.bumpversion.files]]
46
+ filename = "SECURITY.md"
47
+
48
+ [[tool.bumpversion.files]]
49
+ filename = "Makefile"
50
+ replace = "VERSION := {new_version}"
51
+ search = "VERSION := {current_version}"
52
+
10
53
  [tool.codespell]
11
54
  ignore-words-list = "astroid"
12
55
 
13
56
  [tool.coverage.report]
14
57
  exclude_lines = [
15
- "@_t.overload"
58
+ "@_t.overload",
59
+ "if __name__ == .__main__.:"
16
60
  ]
17
61
  fail_under = 100
18
62
 
@@ -24,7 +68,14 @@ omit = [
24
68
  ]
25
69
 
26
70
  [tool.deptry.per_rule_ignores]
27
- DEP004 = ["yaml"]
71
+ DEP004 = [
72
+ "flake8",
73
+ "git",
74
+ "pytest",
75
+ "tomli",
76
+ "tomli_w",
77
+ "yaml"
78
+ ]
28
79
 
29
80
  [tool.docformatter]
30
81
  in-place = true
@@ -76,7 +127,7 @@ maintainers = [
76
127
  name = "docsig"
77
128
  readme = "README.rst"
78
129
  repository = "https://github.com/jshwi/docsig"
79
- version = "0.55.0"
130
+ version = "0.57.0"
80
131
 
81
132
  [tool.poetry.dependencies]
82
133
  Sphinx = "^7.0.0"
@@ -84,18 +135,22 @@ arcon = ">=0.4.0"
84
135
  astroid = "^3.0.1"
85
136
  click = "^8.1.7"
86
137
  pathspec = "^0.12.1"
87
- python = "^3.8"
138
+ python = "^3.8.1"
88
139
 
89
140
  [tool.poetry.group.dev.dependencies]
90
141
  black = "^24.4.2"
91
- bump2version = "^1.0.1"
142
+ bump-my-version = "^0.24.1"
92
143
  deptry = "^0.16.1"
93
144
  docformatter = "^1.7.5"
94
145
  flynt = "^1.0.1"
146
+ gitpython = "^3.1.43"
95
147
  isort = "^5.13.2"
96
148
  mypy = "^1.10.0"
97
149
  pre-commit = "^3.3.3"
98
150
  pylint = "^3.1.0"
151
+ tomli = "^2.0.1"
152
+ tomli-w = "^1.0.0"
153
+ towncrier = "^23.11.0"
99
154
  tox = "^4.15.0"
100
155
  vulture = "^2.11"
101
156
 
@@ -108,6 +163,9 @@ sphinx-copybutton = "^0.5.2"
108
163
  sphinx-markdown-builder = ">=0.5.5,<0.7.0"
109
164
  templatest = "^0.10.1"
110
165
 
166
+ [tool.poetry.group.flake8.dependencies]
167
+ flake8 = "^7.1.0"
168
+
111
169
  [tool.poetry.group.tests.dependencies]
112
170
  pytest = "^8.2.0"
113
171
  pytest-benchmark = "^4.0.0"
@@ -117,6 +175,9 @@ pytest-sugar = "^1.0.0"
117
175
  pytest-xdist = "^3.6.1"
118
176
  templatest = "^0.10.1"
119
177
 
178
+ [tool.poetry.plugins."flake8.extension"]
179
+ SIG = "docsig.plugin:Docsig"
180
+
120
181
  [tool.poetry.scripts]
121
182
  docsig = "docsig.__main__:main"
122
183
 
@@ -149,3 +210,32 @@ norecursedirs = [
149
210
  ".pytest_cache",
150
211
  "docs"
151
212
  ]
213
+
214
+ [tool.towncrier]
215
+ directory = "changelog"
216
+ filename = "CHANGELOG.md"
217
+ issue_format = "[#{issue}](https://github.com/jshwi/docsig/issues/{issue})"
218
+ package = "docsig"
219
+ start_string = "<!-- release notes start -->\n"
220
+ template = "changelog/_template.md"
221
+
222
+ [tool.towncrier.fragment.add]
223
+ name = "Added"
224
+
225
+ [tool.towncrier.fragment.change]
226
+ name = "Changed"
227
+
228
+ [tool.towncrier.fragment.deprecate]
229
+ name = "Deprecated"
230
+
231
+ [tool.towncrier.fragment.fix]
232
+ name = "Fixed"
233
+
234
+ [tool.towncrier.fragment.hack]
235
+ name = "Hacked"
236
+
237
+ [tool.towncrier.fragment.remove]
238
+ name = "Removed"
239
+
240
+ [tool.towncrier.fragment.security]
241
+ name = "Security"
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