Skip to content

Commit

Permalink
pyproject(ruff): Support pydocstyle w/ numpy convention (#891)
Browse files Browse the repository at this point in the history
  • Loading branch information
tony authored Dec 21, 2023
2 parents 83e9719 + f8055cb commit 6479e01
Show file tree
Hide file tree
Showing 97 changed files with 617 additions and 241 deletions.
5 changes: 5 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ $ pipx install --suffix=@next 'tmuxp' --pip-args '\--pre' --force
### CI

- Move CodeQL from advanced configuration file to GitHub's default
- Add pydocstyle rule to ruff (#891)

### Documentation

- Add docstrings to functions, methods, classes, and packages (#891)

## tmuxp 1.32.1 (2023-11-23)

Expand Down
18 changes: 15 additions & 3 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
"""Conftest.py (root-level)
"""Conftest.py (root-level).
We keep this in root pytest fixtures in pytest's doctest plugin to be available, as well
as avoiding conftest.py from being included in the wheel.
as avoiding conftest.py from being included in the wheel, in addition to pytest_plugin
for pytester only being available via the root directory.
See "pytest_plugins in non-top-level conftest files" in
https://docs.pytest.org/en/stable/deprecations.html
"""

import logging
import os
import pathlib
Expand All @@ -26,7 +31,7 @@
@pytest.mark.skipif(not USING_ZSH, reason="Using ZSH")
@pytest.fixture(autouse=USING_ZSH, scope="session")
def zshrc(user_path: pathlib.Path) -> pathlib.Path:
"""This quiets ZSH default message.
"""Quiets ZSH default message.
Needs a startup file .zshenv, .zprofile, .zshrc, .zlogin.
"""
Expand All @@ -37,11 +42,13 @@ def zshrc(user_path: pathlib.Path) -> pathlib.Path:

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


@pytest.fixture
def tmuxp_configdir(user_path: pathlib.Path) -> pathlib.Path:
"""Ensure and return tmuxp config directory."""
xdg_config_dir = user_path / ".config"
xdg_config_dir.mkdir(exist_ok=True)

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


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

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


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


Expand All @@ -89,6 +100,7 @@ def add_doctest_fixtures(
doctest_namespace: t.Dict[str, t.Any],
tmp_path: pathlib.Path,
) -> None:
"""Harness pytest fixtures to doctests namespace."""
if isinstance(request._pyfuncitem, DoctestItem) and shutil.which("tmux"):
doctest_namespace["server"] = request.getfixturevalue("server")
session: "Session" = request.getfixturevalue("session")
Expand Down
26 changes: 11 additions & 15 deletions docs/_ext/aafig.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""
sphinxcontrib.aafig
~~~~~~~~~~~~~~~~~~~
"""aafig plugin for sphinx.
sphinxcontrib.aafig.
~~~~~~~~~~~~~~~~~~~
Allow embedded ASCII art to be rendered as nice looking images
using the aafigure reStructuredText extension.
Allow embedded ASCII art to be rendered as nice looking images
using the aafigure reStructuredText extension.
See the README file for details.
See the README file for details.
:author: Leandro Lucarella <[email protected]>
:license: BOLA, see LICENSE for details
:author: Leandro Lucarella <[email protected]>
:license: BOLA, see LICENSE for details
"""
import logging
import posixpath
Expand Down Expand Up @@ -61,9 +62,7 @@ class AafigError(SphinxError):


class AafigDirective(images.Image): # type:ignore
"""
Directive to insert an ASCII art figure to be rendered by aafigure.
"""
"""Directive to insert an ASCII art figure to be rendered by aafigure."""

has_content = True
required_arguments = 0
Expand Down Expand Up @@ -155,10 +154,7 @@ def __init__(self, *args: object, **kwargs: object) -> None:
def render_aafigure(
app: "Sphinx", text: str, options: t.Dict[str, str]
) -> t.Tuple[str, str, t.Optional[str], t.Optional[str]]:
"""
Render an ASCII art figure into the requested format output file.
"""

"""Render an ASCII art figure into the requested format output file."""
if aafigure is None:
raise AafigureNotInstalled()

Expand Down
6 changes: 4 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# flake8: NOQA: E501
"""Sphinx documentation configuration for tmuxp."""
import contextlib
import inspect
import pathlib
Expand Down Expand Up @@ -142,7 +143,7 @@

def linkcode_resolve(domain: str, info: t.Dict[str, str]) -> t.Union[None, str]:
"""
Determine the URL corresponding to Python object
Determine the URL corresponding to Python object.
Notes
-----
Expand Down Expand Up @@ -212,12 +213,13 @@ def linkcode_resolve(domain: str, info: t.Dict[str, str]) -> t.Union[None, str]:


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


def setup(app: "Sphinx") -> None:
"""Sphinx setup hook."""
app.connect("build-finished", remove_tabs_js)
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ select = [
"TRY", # Trycertatops
"PERF", # Perflint
"RUF", # Ruff-specific rules
"D", # pydocstyle
]

[tool.ruff.isort]
Expand All @@ -154,6 +155,9 @@ known-first-party = [
]
combine-as-imports = true

[tool.ruff.pydocstyle]
convention = "numpy"

[tool.ruff.per-file-ignores]
"*/__init__.py" = ["F401"]
"src/tmuxp/workspace/finders.py" = ["PTH"]
Expand Down
1 change: 1 addition & 0 deletions src/tmuxp/__about__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Metadata for tmuxp package."""
__title__ = "tmuxp"
__package_name__ = "tmuxp"
__version__ = "1.32.1"
Expand Down
2 changes: 1 addition & 1 deletion src/tmuxp/_types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`type annotations <annotation>`
"""Internal, :const:`typing.TYPE_CHECKING` guarded :term:`typings <annotation>`.
These are _not_ to be imported at runtime as `typing_extensions` is not
bundled with tmuxp. Usage example:
Expand Down
15 changes: 6 additions & 9 deletions src/tmuxp/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
"""CLI utilities for tmuxp.
tmuxp.cli
~~~~~~~~~
"""
"""CLI utilities for tmuxp."""
import argparse
import logging
import os
Expand Down Expand Up @@ -45,6 +40,7 @@


def create_parser() -> argparse.ArgumentParser:
"""Create CLI :class:`argparse.ArgumentParser` for tmuxp."""
parser = argparse.ArgumentParser(prog="tmuxp")
parser.add_argument(
"--version",
Expand Down Expand Up @@ -97,6 +93,8 @@ def create_parser() -> argparse.ArgumentParser:


class CLINamespace(argparse.Namespace):
"""Typed :class:`argparse.Namespace` for tmuxp root-level CLI."""

log_level: "CLIVerbosity"
subparser_name: "CLISubparserName"
import_subparser_name: t.Optional["CLIImportSubparserName"]
Expand All @@ -111,8 +109,8 @@ def cli(_args: t.Optional[t.List[str]] = None) -> None:
Pass the "--help" argument to any command to see detailed help.
See detailed documentation and examples at:
http://tmuxp.git-pull.com/"""

http://tmuxp.git-pull.com/
"""
try:
has_minimum_version()
except TmuxCommandNotFound:
Expand Down Expand Up @@ -186,6 +184,5 @@ def startup(config_dir: pathlib.Path) -> None:
----------
str : get_workspace_dir(): Config directory to search
"""

if not os.path.exists(config_dir):
os.makedirs(config_dir)
6 changes: 5 additions & 1 deletion src/tmuxp/cli/convert.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""CLI for ``tmuxp convert`` subcommand."""
import argparse
import os
import pathlib
Expand All @@ -16,6 +17,7 @@
def create_convert_subparser(
parser: argparse.ArgumentParser,
) -> argparse.ArgumentParser:
"""Augment :class:`argparse.ArgumentParser` with ``convert`` subcommand."""
workspace_file = parser.add_argument(
dest="workspace_file",
type=str,
Expand All @@ -40,6 +42,8 @@ def create_convert_subparser(


class ConvertUnknownFileType(exc.TmuxpException):
"""Raise if tmuxp convert encounters an unknown filetype."""

def __init__(self, ext: str, *args: object, **kwargs: object) -> None:
return super().__init__(
f"Unknown filetype: {ext} (valid: [.json, .yaml, .yml])"
Expand All @@ -51,7 +55,7 @@ def command_convert(
answer_yes: bool,
parser: t.Optional[argparse.ArgumentParser] = None,
) -> None:
"""Convert a tmuxp config between JSON and YAML."""
"""Entrypoint for ``tmuxp convert`` convert a tmuxp config between JSON and YAML."""
workspace_file = find_workspace_file(
workspace_file, workspace_dir=get_workspace_dir()
)
Expand Down
18 changes: 6 additions & 12 deletions src/tmuxp/cli/debug_info.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""CLI for ``tmuxp debug-info`` subcommand."""
import argparse
import os
import pathlib
Expand All @@ -19,32 +20,25 @@
def create_debug_info_subparser(
parser: argparse.ArgumentParser,
) -> argparse.ArgumentParser:
"""Augment :class:`argparse.ArgumentParser` with ``debug-info`` subcommand."""
return parser


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

def prepend_tab(strings: t.List[str]) -> t.List[str]:
"""
Prepend tab to strings in list.
"""
"""Prepend tab to strings in list."""
return ["\t%s" % x for x in strings]

def output_break() -> str:
"""
Generate output break.
"""
"""Generate output break."""
return "-" * 25

def format_tmux_resp(std_resp: tmux_cmd) -> str:
"""
Format tmux command response for tmuxp stdout.
"""
"""Format tmux command response for tmuxp stdout."""
return "\n".join(
[
"\n".join(prepend_tab(std_resp.stdout)),
Expand Down
3 changes: 3 additions & 0 deletions src/tmuxp/cli/edit.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""CLI for ``tmuxp edit`` subcommand."""
import argparse
import os
import pathlib
Expand All @@ -10,6 +11,7 @@
def create_edit_subparser(
parser: argparse.ArgumentParser,
) -> argparse.ArgumentParser:
"""Augment :class:`argparse.ArgumentParser` with ``edit`` subcommand."""
parser.add_argument(
dest="workspace_file",
metavar="workspace-file",
Expand All @@ -23,6 +25,7 @@ def command_edit(
workspace_file: t.Union[str, pathlib.Path],
parser: t.Optional[argparse.ArgumentParser] = None,
) -> None:
"""Entrypoint for ``tmuxp edit``, open tmuxp workspace file in system editor."""
workspace_file = find_workspace_file(workspace_file)

sys_editor = os.environ.get("EDITOR", "vim")
Expand Down
11 changes: 8 additions & 3 deletions src/tmuxp/cli/freeze.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""CLI for ``tmuxp freeze`` subcommand."""
import argparse
import os
import pathlib
Expand All @@ -21,6 +22,8 @@


class CLIFreezeNamespace(argparse.Namespace):
"""Typed :class:`argparse.Namespace` for tmuxp freeze command."""

session_name: str
socket_name: t.Optional[str]
socket_path: t.Optional[str]
Expand All @@ -34,6 +37,7 @@ class CLIFreezeNamespace(argparse.Namespace):
def create_freeze_subparser(
parser: argparse.ArgumentParser,
) -> argparse.ArgumentParser:
"""Augment :class:`argparse.ArgumentParser` with ``freeze`` subcommand."""
parser.add_argument(
dest="session_name",
metavar="session-name",
Expand Down Expand Up @@ -87,10 +91,11 @@ def command_freeze(
args: CLIFreezeNamespace,
parser: t.Optional[argparse.ArgumentParser] = None,
) -> None:
"""Snapshot a tmux session into a tmuxp workspace.
"""Entrypoint for ``tmuxp freeze``, snapshot a tmux session into a tmuxp workspace.
If SESSION_NAME is provided, snapshot that session. Otherwise, use the
current session."""
If SESSION_NAME is provided, snapshot that session. Otherwise, use the current
session.
"""
server = Server(socket_name=args.socket_name, socket_path=args.socket_path)

try:
Expand Down
Loading

0 comments on commit 6479e01

Please sign in to comment.