Skip to content

Commit 6479e01

Browse files
authored
pyproject(ruff): Support pydocstyle w/ numpy convention (#891)
See also: - https://www.pydocstyle.org/en/stable/ - https://docs.astral.sh/ruff/settings/#pydocstyle
2 parents 83e9719 + f8055cb commit 6479e01

File tree

97 files changed

+617
-241
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+617
-241
lines changed

CHANGES

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ $ pipx install --suffix=@next 'tmuxp' --pip-args '\--pre' --force
2222
### CI
2323

2424
- Move CodeQL from advanced configuration file to GitHub's default
25+
- Add pydocstyle rule to ruff (#891)
26+
27+
### Documentation
28+
29+
- Add docstrings to functions, methods, classes, and packages (#891)
2530

2631
## tmuxp 1.32.1 (2023-11-23)
2732

conftest.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
"""Conftest.py (root-level)
1+
"""Conftest.py (root-level).
22
33
We keep this in root pytest fixtures in pytest's doctest plugin to be available, as well
4-
as avoiding conftest.py from being included in the wheel.
4+
as avoiding conftest.py from being included in the wheel, in addition to pytest_plugin
5+
for pytester only being available via the root directory.
6+
7+
See "pytest_plugins in non-top-level conftest files" in
8+
https://docs.pytest.org/en/stable/deprecations.html
59
"""
10+
611
import logging
712
import os
813
import pathlib
@@ -26,7 +31,7 @@
2631
@pytest.mark.skipif(not USING_ZSH, reason="Using ZSH")
2732
@pytest.fixture(autouse=USING_ZSH, scope="session")
2833
def zshrc(user_path: pathlib.Path) -> pathlib.Path:
29-
"""This quiets ZSH default message.
34+
"""Quiets ZSH default message.
3035
3136
Needs a startup file .zshenv, .zprofile, .zshrc, .zlogin.
3237
"""
@@ -37,11 +42,13 @@ def zshrc(user_path: pathlib.Path) -> pathlib.Path:
3742

3843
@pytest.fixture(autouse=True)
3944
def home_path_default(monkeypatch: pytest.MonkeyPatch, user_path: pathlib.Path) -> None:
45+
"""Set HOME to user_path (random, temporary directory)."""
4046
monkeypatch.setenv("HOME", str(user_path))
4147

4248

4349
@pytest.fixture
4450
def tmuxp_configdir(user_path: pathlib.Path) -> pathlib.Path:
51+
"""Ensure and return tmuxp config directory."""
4552
xdg_config_dir = user_path / ".config"
4653
xdg_config_dir.mkdir(exist_ok=True)
4754

@@ -54,12 +61,14 @@ def tmuxp_configdir(user_path: pathlib.Path) -> pathlib.Path:
5461
def tmuxp_configdir_default(
5562
monkeypatch: pytest.MonkeyPatch, tmuxp_configdir: pathlib.Path
5663
) -> None:
64+
"""Set tmuxp configuration directory for ``TMUXP_CONFIGDIR``."""
5765
monkeypatch.setenv("TMUXP_CONFIGDIR", str(tmuxp_configdir))
5866
assert get_workspace_dir() == str(tmuxp_configdir)
5967

6068

6169
@pytest.fixture(scope="function")
6270
def monkeypatch_plugin_test_packages(monkeypatch: pytest.MonkeyPatch) -> None:
71+
"""Monkeypatch tmuxp plugin fixtures to python path."""
6372
paths = [
6473
"tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bwb/",
6574
"tests/fixtures/pluginsystem/plugins/tmuxp_test_plugin_bs/",
@@ -74,12 +83,14 @@ def monkeypatch_plugin_test_packages(monkeypatch: pytest.MonkeyPatch) -> None:
7483

7584
@pytest.fixture(scope="function")
7685
def session_params(session_params: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]:
86+
"""Terminal-friendly tmuxp session_params for dimensions."""
7787
session_params.update({"x": 800, "y": 600})
7888
return session_params
7989

8090

8191
@pytest.fixture(scope="function")
8292
def socket_name(request: pytest.FixtureRequest) -> str:
93+
"""Random socket name for tmuxp."""
8394
return "tmuxp_test%s" % next(namer)
8495

8596

@@ -89,6 +100,7 @@ def add_doctest_fixtures(
89100
doctest_namespace: t.Dict[str, t.Any],
90101
tmp_path: pathlib.Path,
91102
) -> None:
103+
"""Harness pytest fixtures to doctests namespace."""
92104
if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"):
93105
doctest_namespace["server"] = request.getfixturevalue("server")
94106
session: "Session" = request.getfixturevalue("session")

docs/_ext/aafig.py

+11-15
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
"""
2-
sphinxcontrib.aafig
3-
~~~~~~~~~~~~~~~~~~~
1+
"""aafig plugin for sphinx.
2+
3+
sphinxcontrib.aafig.
4+
~~~~~~~~~~~~~~~~~~~
45
5-
Allow embedded ASCII art to be rendered as nice looking images
6-
using the aafigure reStructuredText extension.
6+
Allow embedded ASCII art to be rendered as nice looking images
7+
using the aafigure reStructuredText extension.
78
8-
See the README file for details.
9+
See the README file for details.
910
10-
:author: Leandro Lucarella <[email protected]>
11-
:license: BOLA, see LICENSE for details
11+
:author: Leandro Lucarella <[email protected]>
12+
:license: BOLA, see LICENSE for details
1213
"""
1314
import logging
1415
import posixpath
@@ -61,9 +62,7 @@ class AafigError(SphinxError):
6162

6263

6364
class AafigDirective(images.Image): # type:ignore
64-
"""
65-
Directive to insert an ASCII art figure to be rendered by aafigure.
66-
"""
65+
"""Directive to insert an ASCII art figure to be rendered by aafigure."""
6766

6867
has_content = True
6968
required_arguments = 0
@@ -155,10 +154,7 @@ def __init__(self, *args: object, **kwargs: object) -> None:
155154
def render_aafigure(
156155
app: "Sphinx", text: str, options: t.Dict[str, str]
157156
) -> t.Tuple[str, str, t.Optional[str], t.Optional[str]]:
158-
"""
159-
Render an ASCII art figure into the requested format output file.
160-
"""
161-
157+
"""Render an ASCII art figure into the requested format output file."""
162158
if aafigure is None:
163159
raise AafigureNotInstalled()
164160

docs/conf.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# flake8: NOQA: E501
2+
"""Sphinx documentation configuration for tmuxp."""
23
import contextlib
34
import inspect
45
import pathlib
@@ -142,7 +143,7 @@
142143

143144
def linkcode_resolve(domain: str, info: t.Dict[str, str]) -> t.Union[None, str]:
144145
"""
145-
Determine the URL corresponding to Python object
146+
Determine the URL corresponding to Python object.
146147
147148
Notes
148149
-----
@@ -212,12 +213,13 @@ def linkcode_resolve(domain: str, info: t.Dict[str, str]) -> t.Union[None, str]:
212213

213214

214215
def remove_tabs_js(app: "Sphinx", exc: Exception) -> None:
215-
# Fix for sphinx-inline-tabs#18
216+
"""Fix for sphinx-inline-tabs#18."""
216217
if app.builder.format == "html" and not exc:
217218
tabs_js = pathlib.Path(app.builder.outdir) / "_static" / "tabs.js"
218219
with contextlib.suppress(FileNotFoundError):
219220
tabs_js.unlink() # When python 3.7 deprecated, use missing_ok=True
220221

221222

222223
def setup(app: "Sphinx") -> None:
224+
"""Sphinx setup hook."""
223225
app.connect("build-finished", remove_tabs_js)

pyproject.toml

+4
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ select = [
146146
"TRY", # Trycertatops
147147
"PERF", # Perflint
148148
"RUF", # Ruff-specific rules
149+
"D", # pydocstyle
149150
]
150151

151152
[tool.ruff.isort]
@@ -154,6 +155,9 @@ known-first-party = [
154155
]
155156
combine-as-imports = true
156157

158+
[tool.ruff.pydocstyle]
159+
convention = "numpy"
160+
157161
[tool.ruff.per-file-ignores]
158162
"*/__init__.py" = ["F401"]
159163
"src/tmuxp/workspace/finders.py" = ["PTH"]

src/tmuxp/__about__.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"""Metadata for tmuxp package."""
12
__title__ = "tmuxp"
23
__package_name__ = "tmuxp"
34
__version__ = "1.32.1"

src/tmuxp/_types.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`type annotations <annotation>`
1+
"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`typings <annotation>`.
22
33
These are _not_ to be imported at runtime as `typing_extensions` is not
44
bundled with tmuxp. Usage example:

src/tmuxp/cli/__init__.py

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
"""CLI utilities for tmuxp.
2-
3-
tmuxp.cli
4-
~~~~~~~~~
5-
6-
"""
1+
"""CLI utilities for tmuxp."""
72
import argparse
83
import logging
94
import os
@@ -45,6 +40,7 @@
4540

4641

4742
def create_parser() -> argparse.ArgumentParser:
43+
"""Create CLI :class:`argparse.ArgumentParser` for tmuxp."""
4844
parser = argparse.ArgumentParser(prog="tmuxp")
4945
parser.add_argument(
5046
"--version",
@@ -97,6 +93,8 @@ def create_parser() -> argparse.ArgumentParser:
9793

9894

9995
class CLINamespace(argparse.Namespace):
96+
"""Typed :class:`argparse.Namespace` for tmuxp root-level CLI."""
97+
10098
log_level: "CLIVerbosity"
10199
subparser_name: "CLISubparserName"
102100
import_subparser_name: t.Optional["CLIImportSubparserName"]
@@ -111,8 +109,8 @@ def cli(_args: t.Optional[t.List[str]] = None) -> None:
111109
112110
Pass the "--help" argument to any command to see detailed help.
113111
See detailed documentation and examples at:
114-
http://tmuxp.git-pull.com/"""
115-
112+
http://tmuxp.git-pull.com/
113+
"""
116114
try:
117115
has_minimum_version()
118116
except TmuxCommandNotFound:
@@ -186,6 +184,5 @@ def startup(config_dir: pathlib.Path) -> None:
186184
----------
187185
str : get_workspace_dir(): Config directory to search
188186
"""
189-
190187
if not os.path.exists(config_dir):
191188
os.makedirs(config_dir)

src/tmuxp/cli/convert.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"""CLI for ``tmuxp convert`` subcommand."""
12
import argparse
23
import os
34
import pathlib
@@ -16,6 +17,7 @@
1617
def create_convert_subparser(
1718
parser: argparse.ArgumentParser,
1819
) -> argparse.ArgumentParser:
20+
"""Augment :class:`argparse.ArgumentParser` with ``convert`` subcommand."""
1921
workspace_file = parser.add_argument(
2022
dest="workspace_file",
2123
type=str,
@@ -40,6 +42,8 @@ def create_convert_subparser(
4042

4143

4244
class ConvertUnknownFileType(exc.TmuxpException):
45+
"""Raise if tmuxp convert encounters an unknown filetype."""
46+
4347
def __init__(self, ext: str, *args: object, **kwargs: object) -> None:
4448
return super().__init__(
4549
f"Unknown filetype: {ext} (valid: [.json, .yaml, .yml])"
@@ -51,7 +55,7 @@ def command_convert(
5155
answer_yes: bool,
5256
parser: t.Optional[argparse.ArgumentParser] = None,
5357
) -> None:
54-
"""Convert a tmuxp config between JSON and YAML."""
58+
"""Entrypoint for ``tmuxp convert`` convert a tmuxp config between JSON and YAML."""
5559
workspace_file = find_workspace_file(
5660
workspace_file, workspace_dir=get_workspace_dir()
5761
)

src/tmuxp/cli/debug_info.py

+6-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"""CLI for ``tmuxp debug-info`` subcommand."""
12
import argparse
23
import os
34
import pathlib
@@ -19,32 +20,25 @@
1920
def create_debug_info_subparser(
2021
parser: argparse.ArgumentParser,
2122
) -> argparse.ArgumentParser:
23+
"""Augment :class:`argparse.ArgumentParser` with ``debug-info`` subcommand."""
2224
return parser
2325

2426

2527
def command_debug_info(
2628
parser: t.Optional[argparse.ArgumentParser] = None,
2729
) -> None:
28-
"""
29-
Print debug info to submit with Issues.
30-
"""
30+
"""Entrypoint for ``tmuxp debug-info`` to print debug info to submit with issues."""
3131

3232
def prepend_tab(strings: t.List[str]) -> t.List[str]:
33-
"""
34-
Prepend tab to strings in list.
35-
"""
33+
"""Prepend tab to strings in list."""
3634
return ["\t%s" % x for x in strings]
3735

3836
def output_break() -> str:
39-
"""
40-
Generate output break.
41-
"""
37+
"""Generate output break."""
4238
return "-" * 25
4339

4440
def format_tmux_resp(std_resp: tmux_cmd) -> str:
45-
"""
46-
Format tmux command response for tmuxp stdout.
47-
"""
41+
"""Format tmux command response for tmuxp stdout."""
4842
return "\n".join(
4943
[
5044
"\n".join(prepend_tab(std_resp.stdout)),

src/tmuxp/cli/edit.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"""CLI for ``tmuxp edit`` subcommand."""
12
import argparse
23
import os
34
import pathlib
@@ -10,6 +11,7 @@
1011
def create_edit_subparser(
1112
parser: argparse.ArgumentParser,
1213
) -> argparse.ArgumentParser:
14+
"""Augment :class:`argparse.ArgumentParser` with ``edit`` subcommand."""
1315
parser.add_argument(
1416
dest="workspace_file",
1517
metavar="workspace-file",
@@ -23,6 +25,7 @@ def command_edit(
2325
workspace_file: t.Union[str, pathlib.Path],
2426
parser: t.Optional[argparse.ArgumentParser] = None,
2527
) -> None:
28+
"""Entrypoint for ``tmuxp edit``, open tmuxp workspace file in system editor."""
2629
workspace_file = find_workspace_file(workspace_file)
2730

2831
sys_editor = os.environ.get("EDITOR", "vim")

src/tmuxp/cli/freeze.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
"""CLI for ``tmuxp freeze`` subcommand."""
12
import argparse
23
import os
34
import pathlib
@@ -21,6 +22,8 @@
2122

2223

2324
class CLIFreezeNamespace(argparse.Namespace):
25+
"""Typed :class:`argparse.Namespace` for tmuxp freeze command."""
26+
2427
session_name: str
2528
socket_name: t.Optional[str]
2629
socket_path: t.Optional[str]
@@ -34,6 +37,7 @@ class CLIFreezeNamespace(argparse.Namespace):
3437
def create_freeze_subparser(
3538
parser: argparse.ArgumentParser,
3639
) -> argparse.ArgumentParser:
40+
"""Augment :class:`argparse.ArgumentParser` with ``freeze`` subcommand."""
3741
parser.add_argument(
3842
dest="session_name",
3943
metavar="session-name",
@@ -87,10 +91,11 @@ def command_freeze(
8791
args: CLIFreezeNamespace,
8892
parser: t.Optional[argparse.ArgumentParser] = None,
8993
) -> None:
90-
"""Snapshot a tmux session into a tmuxp workspace.
94+
"""Entrypoint for ``tmuxp freeze``, snapshot a tmux session into a tmuxp workspace.
9195
92-
If SESSION_NAME is provided, snapshot that session. Otherwise, use the
93-
current session."""
96+
If SESSION_NAME is provided, snapshot that session. Otherwise, use the current
97+
session.
98+
"""
9499
server = Server(socket_name=args.socket_name, socket_path=args.socket_path)
95100

96101
try:

0 commit comments

Comments
 (0)