docsig 0.62.1__tar.gz → 0.63.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.62.1
3
+ Version: 0.63.0
4
4
  Summary: Check signature params for proper documentation
5
5
  Home-page: https://pypi.org/project/docsig/
6
6
  License: MIT
@@ -180,7 +180,7 @@ ensure your installation has registered `docsig`
180
180
  .. code-block:: console
181
181
 
182
182
  $ flake8 --version
183
- 7.1.0 (docsig: 0.62.1, mccabe: 0.7.0, pycodestyle: 2.12.0, pyflakes: 3.2.0) CPython 3.8.13 on Darwin
183
+ 7.1.0 (docsig: 0.63.0, mccabe: 0.7.0, pycodestyle: 2.12.0, pyflakes: 3.2.0) CPython 3.8.13 on Darwin
184
184
 
185
185
  And now use `flake8` to lint your files
186
186
 
@@ -269,7 +269,7 @@ Standalone
269
269
 
270
270
  repos:
271
271
  - repo: https://github.com/jshwi/docsig
272
- rev: v0.62.1
272
+ rev: v0.63.0
273
273
  hooks:
274
274
  - id: docsig
275
275
  args:
@@ -288,7 +288,7 @@ or integrated with ``flake8``
288
288
  hooks:
289
289
  - id: flake8
290
290
  additional_dependencies:
291
- - docsig==0.62.1
291
+ - docsig==0.63.0
292
292
  args:
293
293
  - "--sig-check-class"
294
294
  - "--sig-check-dunders"
@@ -153,7 +153,7 @@ ensure your installation has registered `docsig`
153
153
  .. code-block:: console
154
154
 
155
155
  $ flake8 --version
156
- 7.1.0 (docsig: 0.62.1, mccabe: 0.7.0, pycodestyle: 2.12.0, pyflakes: 3.2.0) CPython 3.8.13 on Darwin
156
+ 7.1.0 (docsig: 0.63.0, mccabe: 0.7.0, pycodestyle: 2.12.0, pyflakes: 3.2.0) CPython 3.8.13 on Darwin
157
157
 
158
158
  And now use `flake8` to lint your files
159
159
 
@@ -242,7 +242,7 @@ Standalone
242
242
 
243
243
  repos:
244
244
  - repo: https://github.com/jshwi/docsig
245
- rev: v0.62.1
245
+ rev: v0.63.0
246
246
  hooks:
247
247
  - id: docsig
248
248
  args:
@@ -261,7 +261,7 @@ or integrated with ``flake8``
261
261
  hooks:
262
262
  - id: flake8
263
263
  additional_dependencies:
264
- - docsig==0.62.1
264
+ - docsig==0.63.0
265
265
  args:
266
266
  - "--sig-check-class"
267
267
  - "--sig-check-dunders"
@@ -110,7 +110,7 @@ def parse_args(args: _t.Sequence[str] | None = None) -> _a.Namespace:
110
110
  :return: Parsed arguments.
111
111
  """
112
112
  parser = _ArgumentParser(
113
- description="Check signature params for proper documentation",
113
+ description="Check signature params for proper documentation"
114
114
  )
115
115
  parser.add_argument(
116
116
  "-V",
@@ -5,6 +5,7 @@ docsig._core
5
5
 
6
6
  from __future__ import annotations as _
7
7
 
8
+ import logging as _logging
8
9
  import sys as _sys
9
10
  from pathlib import Path as _Path
10
11
 
@@ -20,7 +21,6 @@ from ._module import Parent as _Parent
20
21
  from ._report import Failure as _Failure
21
22
  from ._report import Failures as _Failures
22
23
  from ._utils import print_checks as _print_checks
23
- from ._utils import vprint as _vprint
24
24
  from .messages import TEMPLATE as _TEMPLATE
25
25
  from .messages import Messages as _Messages
26
26
 
@@ -44,6 +44,21 @@ _DEFAULT_EXCLUDES = """\
44
44
  """
45
45
 
46
46
 
47
+ def setup_logger(verbose: bool) -> None:
48
+ """Setup docsig logger.
49
+
50
+ Only log if verbose mode is enabled.
51
+
52
+ :param verbose: Whether to enable verbose mode.
53
+ """
54
+ loglevel = _logging.DEBUG if verbose else _logging.INFO
55
+ logger = _logging.getLogger(__package__)
56
+ logger.setLevel(loglevel)
57
+ if not logger.handlers:
58
+ stream_handler = _logging.StreamHandler(_sys.stdout)
59
+ logger.addHandler(stream_handler)
60
+
61
+
47
62
  def _run_check( # pylint: disable=too-many-arguments,too-many-locals
48
63
  child: _Parent,
49
64
  parent: _Parent,
@@ -123,10 +138,10 @@ def _parse_ast( # pylint: disable=too-many-arguments
123
138
  ignore_args: bool,
124
139
  ignore_kwargs: bool,
125
140
  check_class_constructor,
126
- verbose: bool,
127
141
  root: _Path | None = None,
128
142
  string: str | None = None,
129
143
  ) -> _Parent:
144
+ logger = _logging.getLogger(__package__)
130
145
  parent = _Parent()
131
146
  try:
132
147
  if root is not None:
@@ -143,29 +158,21 @@ def _parse_ast( # pylint: disable=too-many-arguments
143
158
  ignore_kwargs,
144
159
  check_class_constructor,
145
160
  )
146
- _vprint(
147
- _FILE_INFO.format(
148
- path=root or "stdin", msg="Parsing Python code successful"
149
- ),
150
- verbose,
161
+ logger.debug(
162
+ _FILE_INFO, root or "stdin", "Parsing Python code successful"
151
163
  )
152
164
  return parent
153
165
  except (_ast.AstroidSyntaxError, UnicodeDecodeError) as err:
154
166
  msg = str(err).replace("\n", " ")
155
167
  if root is not None and root.name.endswith(".py"):
156
- # pass by silently for files that do not end with .py, may
157
- # result in a 123 syntax error exit status in the future
158
168
  parent = _Parent(error=_Error.SYNTAX)
159
169
 
160
- _vprint(
161
- _FILE_INFO.format(path=root or "stdin", msg=msg),
162
- verbose,
163
- )
170
+ logger.debug(_FILE_INFO, root or "stdin", msg)
164
171
 
165
172
  return parent
166
173
 
167
174
 
168
- def _get_failures( # pylint: disable=too-many-locals,too-many-arguments
175
+ def _get_failures( # pylint: disable=too-many-arguments
169
176
  module: _Parent,
170
177
  check_class: bool,
171
178
  check_class_constructor: bool,
@@ -209,8 +216,10 @@ def _get_failures( # pylint: disable=too-many-locals,too-many-arguments
209
216
 
210
217
  def _report(
211
218
  failures: _Failures, path: str | None = None, no_ansi: bool = False
212
- ) -> None:
219
+ ) -> int:
220
+ retcodes = []
213
221
  for failure in failures:
222
+ retcodes.append(failure.retcode)
214
223
  module = f"{path}:" if path is not None else ""
215
224
  header = f"{module}{failure.lineno} in {failure.name}"
216
225
  if not no_ansi and _sys.stdout.isatty():
@@ -229,6 +238,8 @@ def _report(
229
238
  if item.hint:
230
239
  print(f" hint: {item.hint}")
231
240
 
241
+ return max(retcodes)
242
+
232
243
 
233
244
  def runner( # pylint: disable=too-many-locals,too-many-arguments
234
245
  file: str | _Path,
@@ -246,7 +257,6 @@ def runner( # pylint: disable=too-many-locals,too-many-arguments
246
257
  ignore_typechecker: bool = False,
247
258
  check_protected_class_methods: bool = False,
248
259
  no_ansi: bool = False,
249
- verbose: bool = False,
250
260
  target: _Messages | None = None,
251
261
  ) -> _Failures:
252
262
  """Per path runner.
@@ -269,7 +279,6 @@ def runner( # pylint: disable=too-many-locals,too-many-arguments
269
279
  :param check_protected_class_methods: Check public methods belonging
270
280
  to protected classes.
271
281
  :param no_ansi: Disable ANSI output.
272
- :param verbose: increase output verbosity.
273
282
  :param target: List of errors to target.
274
283
  :return: Exit status for whether test failed or not.
275
284
  """
@@ -279,7 +288,6 @@ def runner( # pylint: disable=too-many-locals,too-many-arguments
279
288
  ignore_args,
280
289
  ignore_kwargs,
281
290
  check_class_constructor,
282
- verbose,
283
291
  root=_Path(file),
284
292
  )
285
293
  if module or module.error is not None:
@@ -367,6 +375,7 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
367
375
  :param excludes: Files or dirs to exclude from checks.
368
376
  :return: Exit status for whether test failed or not.
369
377
  """
378
+ setup_logger(verbose)
370
379
  if list_checks:
371
380
  return int(bool(_print_checks())) # type: ignore
372
381
 
@@ -375,13 +384,12 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
375
384
  patterns.append(exclude)
376
385
 
377
386
  if string is None:
378
- retcode = 0
387
+ retcodes = [0]
379
388
  paths = _Paths(
380
389
  *tuple(_Path(i) for i in path),
381
390
  patterns=patterns,
382
391
  excludes=excludes or [],
383
392
  include_ignored=include_ignored,
384
- verbose=verbose,
385
393
  )
386
394
  for file in paths:
387
395
  failures = runner(
@@ -400,21 +408,18 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
400
408
  ignore_typechecker,
401
409
  check_protected_class_methods,
402
410
  no_ansi,
403
- verbose,
404
411
  target,
405
412
  )
406
413
  if failures:
407
- _report(failures, str(file), no_ansi)
408
- retcode = 1
414
+ retcodes.append(_report(failures, str(file), no_ansi))
409
415
 
410
- return retcode
416
+ return max(retcodes)
411
417
 
412
418
  module = _parse_ast(
413
419
  disable or _Messages(),
414
420
  ignore_args,
415
421
  ignore_kwargs,
416
422
  check_class_constructor,
417
- verbose,
418
423
  string=string,
419
424
  )
420
425
  if module or module.error is not None:
@@ -434,7 +439,6 @@ def docsig( # pylint: disable=too-many-locals,too-many-arguments
434
439
  target or _Messages(),
435
440
  )
436
441
  if failures:
437
- _report(failures, no_ansi=no_ansi)
438
- return 1
442
+ return _report(failures, no_ansi=no_ansi)
439
443
 
440
444
  return 0
@@ -5,6 +5,7 @@ docsig._files
5
5
 
6
6
  from __future__ import annotations as _
7
7
 
8
+ import logging as _logging
8
9
  import os as _os
9
10
  import re as _re
10
11
  import typing as _t
@@ -14,9 +15,7 @@ from pathspec import PathSpec as _PathSpec
14
15
  from pathspec.patterns import GitWildMatchPattern as _GitWildMatchPattern
15
16
  from wcmatch.pathlib import Path as _WcPath
16
17
 
17
- from ._utils import vprint as _vprint
18
-
19
- FILE_INFO = "{path}: {msg}"
18
+ FILE_INFO = "%s: %s"
20
19
 
21
20
 
22
21
  class _Gitignore(_PathSpec):
@@ -68,7 +67,7 @@ def _glob(path: _Path, pattern: str) -> bool:
68
67
  return _WcPath(str(path)).globmatch(pattern) # type: ignore
69
68
 
70
69
 
71
- class Paths(_t.List[_Path]): # pylint: disable=too-many-instance-attributes
70
+ class Paths(_t.List[_Path]):
72
71
  """Collect a list of valid paths.
73
72
 
74
73
  :param paths: Path(s) to parse ``Module``(s) from.
@@ -77,23 +76,21 @@ class Paths(_t.List[_Path]): # pylint: disable=too-many-instance-attributes
77
76
  :param excludes: Files or dirs to exclude from checks.
78
77
  :param include_ignored: Check files even if they match a gitignore
79
78
  pattern.
80
- :param verbose: increase output verbosity.
81
79
  """
82
80
 
83
- def __init__( # pylint: disable=too-many-arguments
81
+ def __init__(
84
82
  self,
85
83
  *paths: _Path,
86
84
  patterns: list[str],
87
85
  excludes: list[str],
88
86
  include_ignored: bool = False,
89
- verbose: bool = False,
90
87
  ) -> None:
91
88
  super().__init__()
92
89
  self._patterns = patterns
93
90
  self._excludes = excludes
94
91
  self._include_ignored = include_ignored
95
- self._verbose = verbose
96
92
  self._gitignore = _Gitignore()
93
+ self._logger = _logging.getLogger(__package__)
97
94
  for path in paths:
98
95
  self._populate(path)
99
96
 
@@ -102,11 +99,8 @@ class Paths(_t.List[_Path]): # pylint: disable=too-many-instance-attributes
102
99
  any(_re.match(i, str(path)) for i in self._patterns)
103
100
  or any(_glob(path, i) for i in self._excludes)
104
101
  ):
105
- _vprint(
106
- FILE_INFO.format(
107
- path=path, msg="in exclude list, skipping"
108
- ),
109
- self._verbose,
102
+ self._logger.debug(
103
+ FILE_INFO, path, "in exclude list, skipping"
110
104
  )
111
105
  self.remove(path)
112
106
 
@@ -117,10 +111,7 @@ class Paths(_t.List[_Path]): # pylint: disable=too-many-instance-attributes
117
111
  raise FileNotFoundError(root)
118
112
 
119
113
  if not self._include_ignored and self._gitignore.match_file(root):
120
- _vprint(
121
- FILE_INFO.format(path=root, msg="in gitignore, skipping"),
122
- self._verbose,
123
- )
114
+ self._logger.debug(FILE_INFO, root, "in gitignore, skipping")
124
115
  return
125
116
 
126
117
  if root.is_file():
@@ -60,6 +60,9 @@ class Parent(_t.List["Parent"]):
60
60
  super().__init__()
61
61
  self._name = "module"
62
62
  self._error = error
63
+ self._ignore_args = ignore_args
64
+ self._ignore_kwargs = ignore_kwargs
65
+ self._check_class_constructor = check_class_constructor
63
66
  if node is None:
64
67
  if not isinstance(self, Function) and error is not None:
65
68
  self.append(Function(path, error=error))
@@ -67,28 +70,18 @@ class Parent(_t.List["Parent"]):
67
70
  self._name = node.name
68
71
  self._overloads = _Overloads()
69
72
  self._imports = imports or _Imports()
70
- self._parse_ast(
71
- node,
72
- directives or _Directives(),
73
- path,
74
- ignore_args,
75
- ignore_kwargs,
76
- check_class_constructor,
77
- )
73
+ self._parse_ast(node, directives or _Directives(), path)
78
74
 
79
75
  def _parse_imports(self, names: list[tuple[str, str | None]]) -> None:
80
76
  for name in names:
81
77
  original, alias = name
82
78
  self._imports[original] = alias or original
83
79
 
84
- def _parse_ast( # pylint: disable=protected-access,too-many-arguments
80
+ def _parse_ast(
85
81
  self,
86
82
  node: _ast.Module | _ast.ClassDef | _ast.FunctionDef | _ast.NodeNG,
87
83
  directives: _Directives,
88
84
  path: _Path | None = None,
89
- ignore_args: bool = False,
90
- ignore_kwargs: bool = False,
91
- check_class_constructor: bool = False,
92
85
  ) -> None:
93
86
  # need to keep track of `comments` as, even though they are
94
87
  # resolved in directives object, they are needed to notify user
@@ -112,9 +105,9 @@ class Parent(_t.List["Parent"]):
112
105
  directives,
113
106
  disabled,
114
107
  path,
115
- ignore_args,
116
- ignore_kwargs,
117
- check_class_constructor,
108
+ self._ignore_args,
109
+ self._ignore_kwargs,
110
+ self._check_class_constructor,
118
111
  self._imports,
119
112
  )
120
113
  if func.isoverloaded:
@@ -137,21 +130,14 @@ class Parent(_t.List["Parent"]):
137
130
  subnode,
138
131
  directives,
139
132
  path,
140
- ignore_args,
141
- ignore_kwargs,
142
- check_class_constructor,
133
+ self._ignore_args,
134
+ self._ignore_kwargs,
135
+ self._check_class_constructor,
143
136
  self._imports,
144
137
  )
145
138
  )
146
139
  else:
147
- self._parse_ast(
148
- subnode,
149
- directives,
150
- path,
151
- ignore_args,
152
- ignore_kwargs,
153
- check_class_constructor,
154
- )
140
+ self._parse_ast(subnode, directives, path)
155
141
 
156
142
  @property
157
143
  def isprotected(self) -> bool:
@@ -216,13 +202,14 @@ class Function(Parent):
216
202
  self._parent = node.parent.frame()
217
203
  self._decorators = node.decorators
218
204
  self._lineno = node.lineno
205
+ if self.ismethod and not self.isstaticmethod:
206
+ if node.args.posonlyargs:
207
+ node.args.posonlyargs.pop(0)
208
+ elif node.args.args:
209
+ node.args.args.pop(0)
210
+
219
211
  self._signature = self._signature.from_ast(
220
- node.args,
221
- node.returns,
222
- self.ismethod,
223
- self.isstaticmethod,
224
- ignore_args,
225
- ignore_kwargs,
212
+ node, ignore_args, ignore_kwargs
226
213
  )
227
214
  if self.isinit and not check_class_constructor:
228
215
  # docstring for __init__ is expected on the class
@@ -232,9 +219,7 @@ class Function(Parent):
232
219
  relevant_doc_node = node.doc_node
233
220
 
234
221
  if relevant_doc_node is not None:
235
- self._docstring = self.docstring.from_ast(
236
- relevant_doc_node, ignore_kwargs
237
- )
222
+ self._docstring = self.docstring.from_ast(relevant_doc_node)
238
223
 
239
224
  def __len__(self) -> int:
240
225
  """Length of the longest sequence of args."""
@@ -51,6 +51,7 @@ class Failure(_t.List[Failed]):
51
51
  ignore_typechecker: bool,
52
52
  ) -> None:
53
53
  super().__init__()
54
+ self._retcode = 0
54
55
  self._func = func
55
56
  if target:
56
57
  self._func.messages.extend(i for i in _E.all if i not in target)
@@ -79,6 +80,7 @@ class Failure(_t.List[Failed]):
79
80
  self.sort()
80
81
 
81
82
  def _add(self, value: _Message, hint: bool = False, **kwargs) -> None:
83
+ self._retcode = 1
82
84
  failed = Failed(
83
85
  self._name,
84
86
  value.ref,
@@ -236,6 +238,7 @@ class Failure(_t.List[Failed]):
236
238
  # invalid-syntax
237
239
  if self._func.error == _Error.SYNTAX:
238
240
  self._add(_E[901])
241
+ self._retcode = 123
239
242
 
240
243
  @property
241
244
  def name(self) -> str:
@@ -247,6 +250,11 @@ class Failure(_t.List[Failed]):
247
250
  """Function line number."""
248
251
  return self._func.lineno
249
252
 
253
+ @property
254
+ def retcode(self) -> int:
255
+ """How to exit the program."""
256
+ return self._retcode
257
+
250
258
 
251
259
  class Failures(_t.List[Failure]):
252
260
  """Sequence of failed functions."""
@@ -112,15 +112,18 @@ class _Params(_t.List[Param]):
112
112
  self._ignore_kwargs = ignore_kwargs
113
113
  self._duplicates: list[Param] = []
114
114
 
115
- # pylint: disable=too-many-boolean-expressions
116
115
  def append(self, value: Param) -> None:
117
- if not value.isprotected and (
118
- value.kind == DocType.PARAM
119
- or (value.kind == DocType.ARG and not self._ignore_args)
120
- or (
121
- value.kind == DocType.KWARG
122
- and not self._ignore_kwargs
123
- and not any(i.kind == DocType.KWARG for i in self)
116
+ if not value.isprotected and any(
117
+ (
118
+ value.kind == DocType.PARAM,
119
+ (value.kind == DocType.ARG and not self._ignore_args),
120
+ (
121
+ value.kind == DocType.KWARG
122
+ and not (
123
+ self._ignore_kwargs
124
+ or any(i.kind == DocType.KWARG for i in self)
125
+ )
126
+ ),
124
127
  )
125
128
  ):
126
129
  super().append(value)
@@ -189,6 +192,7 @@ class _Stub:
189
192
  class Signature(_Stub):
190
193
  """Represents a function signature.
191
194
 
195
+ :param rettype: The return type.
192
196
  :param returns: Returns declared in signature.
193
197
  :param ignore_args: Ignore args prefixed with an asterisk.
194
198
  :param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
@@ -196,51 +200,40 @@ class Signature(_Stub):
196
200
 
197
201
  def __init__(
198
202
  self,
199
- returns: _ast.Module | str | None = None,
203
+ rettype: RetType = RetType.NONE,
204
+ returns: bool = False,
200
205
  ignore_args: bool = False,
201
206
  ignore_kwargs: bool = False,
202
207
  ) -> None:
203
208
  super().__init__(ignore_args, ignore_kwargs)
204
-
205
- self._rettype = RetType.from_ast(returns)
206
- self._returns = self._rettype == RetType.SOME
209
+ self._rettype = rettype
210
+ self._returns = returns
207
211
 
208
212
  @classmethod
209
- def from_ast( # pylint: disable=too-many-arguments
213
+ def from_ast(
210
214
  cls,
211
- arguments: _ast.Arguments,
212
- returns: _ast.Module | str,
213
- ismethod: bool = False,
214
- isstaticmethod: bool = False,
215
+ node: _ast.Module | _ast.ClassDef | _ast.FunctionDef,
215
216
  ignore_args: bool = False,
216
217
  ignore_kwargs: bool = False,
217
218
  ) -> Signature:
218
219
  """Parse signature from ast.
219
220
 
220
- :param arguments: Arguments provided to signature.
221
- :param returns: Returns declared in signature.
222
- :param ismethod: Whether this signature belongs to a method.
223
- :param isstaticmethod: Whether this signature belongs to a
224
- static method.
221
+ :param node: Abstract syntax tree.
225
222
  :param ignore_args: Ignore args prefixed with an asterisk.
226
223
  :param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
227
224
  :return: Instantiated signature object.
228
225
  """
229
- if ismethod and not isstaticmethod:
230
- if arguments.posonlyargs:
231
- arguments.posonlyargs.pop(0)
232
- elif arguments.args:
233
- arguments.args.pop(0)
234
-
235
- signature = cls(returns, ignore_args, ignore_kwargs)
226
+ rettype = RetType.from_ast(node.returns)
227
+ returns = rettype == RetType.SOME
228
+ signature = cls(rettype, returns, ignore_args, ignore_kwargs)
236
229
  for i in [
237
230
  a if isinstance(a, Param) else Param(name=a.name)
238
231
  for a in [
239
- *arguments.posonlyargs,
240
- *arguments.args,
241
- Param(DocType.ARG, name=arguments.vararg),
242
- *arguments.kwonlyargs,
243
- Param(DocType.KWARG, name=arguments.kwarg),
232
+ *node.args.posonlyargs,
233
+ *node.args.args,
234
+ Param(DocType.ARG, name=node.args.vararg),
235
+ *node.args.kwonlyargs,
236
+ Param(DocType.KWARG, name=node.args.kwarg),
244
237
  ]
245
238
  if a is not None and a.name
246
239
  ]:
@@ -270,13 +263,11 @@ class Docstring(_Stub):
270
263
  """Represents a function docstring.
271
264
 
272
265
  :param string: The raw docstring.
273
- :param ignore_args: Ignore args prefixed with an asterisk.
274
- :param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
266
+ :param returns: Whether this docstring has a return.
275
267
  """
276
268
 
277
269
  @staticmethod
278
270
  def _indent_anomaly(string: str) -> bool:
279
- leading_spaces = []
280
271
  for line in string.splitlines():
281
272
  # only check params
282
273
  # description or anything else is out of scope
@@ -285,10 +276,9 @@ class Docstring(_Stub):
285
276
  if match is not None:
286
277
  spaces = len(match.group())
287
278
  if spaces > 0:
288
- leading_spaces.append(spaces)
279
+ return spaces % 2 != 0
289
280
 
290
- # look for spaces in odd intervals
291
- return bool(any(i % 2 != 0 for i in leading_spaces))
281
+ return False
292
282
 
293
283
  @staticmethod
294
284
  def _normalize_docstring(string: str) -> str:
@@ -307,30 +297,23 @@ class Docstring(_Stub):
307
297
  )
308
298
 
309
299
  def __init__(
310
- self,
311
- string: str | None = None,
312
- ignore_args: bool = False,
313
- ignore_kwargs: bool = False,
300
+ self, string: str | None = None, returns: bool = False
314
301
  ) -> None:
315
- super().__init__(ignore_args, ignore_kwargs)
302
+ super().__init__()
316
303
  self._string = string
317
- self._returns = self._string is not None and bool(
318
- _re.search(":returns?:", self._string)
319
- )
304
+ self._returns = returns
320
305
 
321
306
  @classmethod
322
- def from_ast(
323
- cls, node: _ast.Const, ignore_kwargs: bool = False
324
- ) -> Docstring:
307
+ def from_ast(cls, node: _ast.Const) -> Docstring:
325
308
  """Parse function docstring from ast.
326
309
 
327
310
  :param node: Docstring ast node.
328
- :param ignore_kwargs: Ignore kwargs prefixed with two asterisks.
329
311
  :return: Instantiated docstring object.
330
312
  """
331
- string = cls._normalize_docstring(node.value)
332
- docstring = cls(string, ignore_kwargs)
333
313
  indent_anomaly = cls._indent_anomaly(node.value)
314
+ string = cls._normalize_docstring(node.value)
315
+ returns = bool(_re.search(r":returns?:", string))
316
+ docstring = cls(string, returns)
334
317
  for match in _re.findall(r":(.*?):((?:.|\n)*?)(?=\n:|$)", string):
335
318
  if match:
336
319
  kinds = match[0].split()
@@ -26,16 +26,6 @@ def almost_equal(str1: str, str2: str, mini: float, maxi: float) -> bool:
26
26
  return mini < _SequenceMatcher(a=str1, b=str2).ratio() < maxi
27
27
 
28
28
 
29
- def vprint(msg: str, verbose: bool = False) -> None:
30
- """Print messages only if verbose is true.
31
-
32
- :param msg: Message to print.
33
- :param verbose: Whether verbose mode is enabled.
34
- """
35
- if verbose:
36
- print(msg)
37
-
38
-
39
29
  def pretty_print_error(
40
30
  exception_type: _t.Type[BaseException], msg: str, no_ansi: bool
41
31
  ) -> None:
@@ -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.62.1"
11
+ __version__ = "0.63.0"
@@ -6,7 +6,7 @@ from argparse import Namespace
6
6
 
7
7
  from ._config import get_config as _get_config
8
8
  from ._config import merge_configs as _merge_configs
9
- from ._core import runner
9
+ from ._core import runner, setup_logger
10
10
  from ._version import __version__
11
11
  from .messages import FLAKE8, E
12
12
 
@@ -141,10 +141,11 @@ class Docsig:
141
141
  ref=E[5].ref,
142
142
  description=E[5].description,
143
143
  symbolic=E[5].symbolic,
144
- ),
144
+ )
145
145
  )
146
146
  yield 0, 0, line, self.__class__
147
147
  else:
148
+ setup_logger(self.a.verbose)
148
149
  results = runner(
149
150
  self.filename,
150
151
  check_class=self.a.check_class,
@@ -161,7 +162,6 @@ class Docsig:
161
162
  ignore_args=self.a.ignore_args,
162
163
  ignore_kwargs=self.a.ignore_kwargs,
163
164
  ignore_typechecker=self.a.ignore_typechecker,
164
- verbose=self.a.verbose,
165
165
  )
166
166
  for result in results:
167
167
  for info in result:
@@ -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.62.1"
14
+ current_version = "0.63.0"
15
15
  message = "bump: version {current_version} → {new_version}"
16
16
  sign_tags = true
17
17
  tag = true
@@ -131,7 +131,7 @@ maintainers = [
131
131
  name = "docsig"
132
132
  readme = "README.rst"
133
133
  repository = "https://github.com/jshwi/docsig"
134
- version = "0.62.1"
134
+ version = "0.63.0"
135
135
 
136
136
  [tool.poetry.dependencies]
137
137
  Sphinx = "^7.0.0"
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