Skip to content

Commit 248809d

Browse files
authored

Some content is hidden

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

46 files changed

+446
-281
lines changed

CHANGES

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,25 @@ $ pipx install --suffix=@next 'tmuxp' --pip-args '\--pre' --force
2525

2626
Doc string + linting stringency updates.
2727

28+
### Development
29+
30+
- Strengthen linting (#907)
31+
32+
- Add flake8-commas (COM)
33+
34+
- https://docs.astral.sh/ruff/rules/#flake8-commas-com
35+
- https://pypi.org/project/flake8-commas/
36+
37+
- Add flake8-builtins (A)
38+
39+
- https://docs.astral.sh/ruff/rules/#flake8-builtins-a
40+
- https://pypi.org/project/flake8-builtins/
41+
42+
- Add flake8-errmsg (EM)
43+
44+
- https://docs.astral.sh/ruff/rules/#flake8-errmsg-em
45+
- https://pypi.org/project/flake8-errmsg/
46+
2847
## tmuxp 1.34.0 (2023-12-21)
2948

3049
_Maintenance only, no bug fixes or new features_

conftest.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@
2828
USING_ZSH = "zsh" in os.getenv("SHELL", "")
2929

3030

31-
@pytest.mark.skipif(not USING_ZSH, reason="Using ZSH")
3231
@pytest.fixture(autouse=USING_ZSH, scope="session")
33-
def zshrc(user_path: pathlib.Path) -> pathlib.Path:
32+
def zshrc(user_path: pathlib.Path) -> t.Optional[pathlib.Path]:
3433
"""Quiets ZSH default message.
3534
3635
Needs a startup file .zshenv, .zprofile, .zshrc, .zlogin.
3736
"""
37+
if not USING_ZSH:
38+
return None
3839
p = user_path / ".zshrc"
3940
p.touch()
4041
return p
@@ -59,7 +60,8 @@ def tmuxp_configdir(user_path: pathlib.Path) -> pathlib.Path:
5960

6061
@pytest.fixture
6162
def tmuxp_configdir_default(
62-
monkeypatch: pytest.MonkeyPatch, tmuxp_configdir: pathlib.Path
63+
monkeypatch: pytest.MonkeyPatch,
64+
tmuxp_configdir: pathlib.Path,
6365
) -> None:
6466
"""Set tmuxp configuration directory for ``TMUXP_CONFIGDIR``."""
6567
monkeypatch.setenv("TMUXP_CONFIGDIR", str(tmuxp_configdir))

docs/_ext/aafig.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838

3939

4040
def merge_dict(
41-
dst: t.Dict[str, t.Optional[str]], src: t.Dict[str, t.Optional[str]]
41+
dst: t.Dict[str, t.Optional[str]],
42+
src: t.Dict[str, t.Optional[str]],
4243
) -> t.Dict[str, t.Optional[str]]:
4344
for k, v in src.items():
4445
if k not in dst:
@@ -47,14 +48,16 @@ def merge_dict(
4748

4849

4950
def get_basename(
50-
text: str, options: t.Dict[str, str], prefix: t.Optional[str] = "aafig"
51+
text: str,
52+
options: t.Dict[str, str],
53+
prefix: t.Optional[str] = "aafig",
5154
) -> str:
5255
options = options.copy()
5356
if "format" in options:
5457
del options["format"]
5558
hashkey = text + str(options)
56-
id = sha(hashkey.encode("utf-8")).hexdigest()
57-
return f"{prefix}-{id}"
59+
_id = sha(hashkey.encode("utf-8")).hexdigest()
60+
return f"{prefix}-{_id}"
5861

5962

6063
class AafigError(SphinxError):
@@ -106,7 +109,7 @@ def render_aafig_images(app: "Sphinx", doctree: nodes.Node) -> None:
106109
if aafigure is None:
107110
logger.warn(
108111
"aafigure module not installed, ASCII art images "
109-
"will be rendered as literal text"
112+
"will be rendered as literal text",
110113
)
111114
for img in doctree.traverse(nodes.image):
112115
if not hasattr(img, "aafig"):
@@ -115,23 +118,23 @@ def render_aafig_images(app: "Sphinx", doctree: nodes.Node) -> None:
115118
continue
116119
options = img.aafig["options"]
117120
text = img.aafig["text"]
118-
format = app.builder.format
121+
_format = app.builder.format
119122
merge_dict(options, app.builder.config.aafig_default_options)
120-
if format in format_map:
121-
options["format"] = format_map[format]
123+
if _format in format_map:
124+
options["format"] = format_map[_format]
122125
else:
123126
logger.warn(
124127
'unsupported builder format "%s", please '
125128
"add a custom entry in aafig_format config "
126-
"option for this builder" % format
129+
"option for this builder" % _format,
127130
)
128131
img.replace_self(nodes.literal_block(text, text))
129132
continue
130133
if options["format"] is None:
131134
img.replace_self(nodes.literal_block(text, text))
132135
continue
133136
try:
134-
fname, outfn, id, extra = render_aafigure(app, text, options)
137+
fname, outfn, _id, extra = render_aafigure(app, text, options)
135138
except AafigError as exc:
136139
logger.warn("aafigure error: " + str(exc))
137140
img.replace_self(nodes.literal_block(text, text))
@@ -152,7 +155,9 @@ def __init__(self, *args: object, **kwargs: object) -> None:
152155

153156

154157
def render_aafigure(
155-
app: "Sphinx", text: str, options: t.Dict[str, str]
158+
app: "Sphinx",
159+
text: str,
160+
options: t.Dict[str, str],
156161
) -> t.Tuple[str, str, t.Optional[str], t.Optional[str]]:
157162
"""Render an ASCII art figure into the requested format output file."""
158163
if aafigure is None:
@@ -172,7 +177,7 @@ def render_aafigure(
172177
"aafig: the builder format %s is not officially "
173178
"supported, aafigure images could not work. "
174179
"Please report problems and working builder to "
175-
"avoid this warning in the future" % app.builder.format
180+
"avoid this warning in the future" % app.builder.format,
176181
)
177182
relfn = fname
178183
outfn = path.join(app.builder.outdir, fname)

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
master_doc = "index"
5757

5858
project = about["__title__"]
59-
copyright = about["__copyright__"]
59+
project_copyright = about["__copyright__"]
6060

6161
version = "%s" % (".".join(about["__version__"].split("."))[:2])
6262
release = "%s" % (about["__version__"])
@@ -99,7 +99,7 @@
9999
"sidebar/navigation.html",
100100
"sidebar/projects.html",
101101
"sidebar/scroll-end.html",
102-
]
102+
],
103103
}
104104

105105
# linkify_issues

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,11 @@ select = [
140140
"F", # pyflakes
141141
"I", # isort
142142
"UP", # pyupgrade
143+
"A", # flake8-builtins
143144
"B", # flake8-bugbear
144145
"C4", # flake8-comprehensions
146+
"COM", # flake8-commas
147+
"EM", # flake8-errmsg
145148
"Q", # flake8-quotes
146149
"PTH", # flake8-use-pathlib
147150
"SIM", # flake8-simplify
@@ -150,6 +153,9 @@ select = [
150153
"RUF", # Ruff-specific rules
151154
"D", # pydocstyle
152155
]
156+
ignore = [
157+
"COM812", # missing trailing comma, ruff format conflict
158+
]
153159

154160
[tool.ruff.lint.isort]
155161
known-first-party = [

src/tmuxp/_internal/config_reader.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def __init__(self, content: "RawConfigData") -> None:
2727
self.content = content
2828

2929
@staticmethod
30-
def _load(format: "FormatLiteral", content: str) -> t.Dict[str, t.Any]:
30+
def _load(fmt: "FormatLiteral", content: str) -> t.Dict[str, t.Any]:
3131
"""Load raw config data and directly return it.
3232
3333
>>> ConfigReader._load("json", '{ "session_name": "my session" }')
@@ -36,21 +36,22 @@ def _load(format: "FormatLiteral", content: str) -> t.Dict[str, t.Any]:
3636
>>> ConfigReader._load("yaml", 'session_name: my session')
3737
{'session_name': 'my session'}
3838
"""
39-
if format == "yaml":
39+
if fmt == "yaml":
4040
return t.cast(
4141
t.Dict[str, t.Any],
4242
yaml.load(
4343
content,
4444
Loader=yaml.SafeLoader,
4545
),
4646
)
47-
elif format == "json":
47+
elif fmt == "json":
4848
return t.cast(t.Dict[str, t.Any], json.loads(content))
4949
else:
50-
raise NotImplementedError(f"{format} not supported in configuration")
50+
msg = f"{fmt} not supported in configuration"
51+
raise NotImplementedError(msg)
5152

5253
@classmethod
53-
def load(cls, format: "FormatLiteral", content: str) -> "ConfigReader":
54+
def load(cls, fmt: "FormatLiteral", content: str) -> "ConfigReader":
5455
"""Load raw config data into a ConfigReader instance (to dump later).
5556
5657
>>> cfg = ConfigReader.load("json", '{ "session_name": "my session" }')
@@ -67,7 +68,7 @@ def load(cls, format: "FormatLiteral", content: str) -> "ConfigReader":
6768
"""
6869
return cls(
6970
content=cls._load(
70-
format=format,
71+
fmt=fmt,
7172
content=content,
7273
),
7374
)
@@ -106,14 +107,15 @@ def _from_file(cls, path: pathlib.Path) -> t.Dict[str, t.Any]:
106107
content = path.open().read()
107108

108109
if path.suffix in [".yaml", ".yml"]:
109-
format: "FormatLiteral" = "yaml"
110+
fmt: "FormatLiteral" = "yaml"
110111
elif path.suffix == ".json":
111-
format = "json"
112+
fmt = "json"
112113
else:
113-
raise NotImplementedError(f"{path.suffix} not supported in {path}")
114+
msg = f"{path.suffix} not supported in {path}"
115+
raise NotImplementedError(msg)
114116

115117
return cls._load(
116-
format=format,
118+
fmt=fmt,
117119
content=content,
118120
)
119121

@@ -159,7 +161,7 @@ def from_file(cls, path: pathlib.Path) -> "ConfigReader":
159161

160162
@staticmethod
161163
def _dump(
162-
format: "FormatLiteral",
164+
fmt: "FormatLiteral",
163165
content: "RawConfigData",
164166
indent: int = 2,
165167
**kwargs: t.Any,
@@ -172,22 +174,23 @@ def _dump(
172174
>>> ConfigReader._dump("json", { "session_name": "my session" })
173175
'{\n "session_name": "my session"\n}'
174176
"""
175-
if format == "yaml":
177+
if fmt == "yaml":
176178
return yaml.dump(
177179
content,
178180
indent=2,
179181
default_flow_style=False,
180182
Dumper=yaml.SafeDumper,
181183
)
182-
elif format == "json":
184+
elif fmt == "json":
183185
return json.dumps(
184186
content,
185187
indent=2,
186188
)
187189
else:
188-
raise NotImplementedError(f"{format} not supported in config")
190+
msg = f"{fmt} not supported in config"
191+
raise NotImplementedError(msg)
189192

190-
def dump(self, format: "FormatLiteral", indent: int = 2, **kwargs: t.Any) -> str:
193+
def dump(self, fmt: "FormatLiteral", indent: int = 2, **kwargs: t.Any) -> str:
191194
r"""Dump via ConfigReader instance.
192195
193196
>>> cfg = ConfigReader({ "session_name": "my session" })
@@ -197,7 +200,7 @@ def dump(self, format: "FormatLiteral", indent: int = 2, **kwargs: t.Any) -> str
197200
'{\n "session_name": "my session"\n}'
198201
"""
199202
return self._dump(
200-
format=format,
203+
fmt=fmt,
201204
content=self.content,
202205
indent=indent,
203206
**kwargs,

src/tmuxp/cli/__init__.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@
3434

3535
CLIVerbosity: TypeAlias = t.Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
3636
CLISubparserName: TypeAlias = t.Literal[
37-
"ls", "load", "freeze", "convert", "edit", "import", "shell", "debug-info"
37+
"ls",
38+
"load",
39+
"freeze",
40+
"convert",
41+
"edit",
42+
"import",
43+
"shell",
44+
"debug-info",
3845
]
3946
CLIImportSubparserName: TypeAlias = t.Literal["teamocil", "tmuxinator"]
4047

@@ -60,21 +67,25 @@ def create_parser() -> argparse.ArgumentParser:
6067
load_parser = subparsers.add_parser("load", help="load tmuxp workspaces")
6168
create_load_subparser(load_parser)
6269
shell_parser = subparsers.add_parser(
63-
"shell", help="launch python shell for tmux server, session, window and pane"
70+
"shell",
71+
help="launch python shell for tmux server, session, window and pane",
6472
)
6573
create_shell_subparser(shell_parser)
6674
import_parser = subparsers.add_parser(
67-
"import", help="import workspaces from teamocil and tmuxinator."
75+
"import",
76+
help="import workspaces from teamocil and tmuxinator.",
6877
)
6978
create_import_subparser(import_parser)
7079

7180
convert_parser = subparsers.add_parser(
72-
"convert", help="convert workspace files between yaml and json."
81+
"convert",
82+
help="convert workspace files between yaml and json.",
7383
)
7484
create_convert_subparser(convert_parser)
7585

7686
debug_info_parser = subparsers.add_parser(
77-
"debug-info", help="print out all diagnostic info"
87+
"debug-info",
88+
help="print out all diagnostic info",
7889
)
7990
create_debug_info_subparser(debug_info_parser)
8091

@@ -85,7 +96,8 @@ def create_parser() -> argparse.ArgumentParser:
8596
create_edit_subparser(edit_parser)
8697

8798
freeze_parser = subparsers.add_parser(
88-
"freeze", help="freeze a live tmux session to a tmuxp workspace file"
99+
"freeze",
100+
help="freeze a live tmux session to a tmuxp workspace file",
89101
)
90102
create_freeze_subparser(freeze_parser)
91103

src/tmuxp/cli/convert.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class ConvertUnknownFileType(exc.TmuxpException):
4646

4747
def __init__(self, ext: str, *args: object, **kwargs: object) -> None:
4848
return super().__init__(
49-
f"Unknown filetype: {ext} (valid: [.json, .yaml, .yml])"
49+
f"Unknown filetype: {ext} (valid: [.json, .yaml, .yml])",
5050
)
5151

5252

@@ -57,7 +57,8 @@ def command_convert(
5757
) -> None:
5858
"""Entrypoint for ``tmuxp convert`` convert a tmuxp config between JSON and YAML."""
5959
workspace_file = find_workspace_file(
60-
workspace_file, workspace_dir=get_workspace_dir()
60+
workspace_file,
61+
workspace_dir=get_workspace_dir(),
6162
)
6263

6364
if isinstance(workspace_file, str):
@@ -77,7 +78,7 @@ def command_convert(
7778
newfile = workspace_file.parent / (str(workspace_file.stem) + f".{to_filetype}")
7879

7980
new_workspace = configparser.dump(
80-
format=to_filetype,
81+
fmt=to_filetype,
8182
indent=2,
8283
**{"default_flow_style": False} if to_filetype == "yaml" else {},
8384
)

src/tmuxp/cli/debug_info.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def format_tmux_resp(std_resp: tmux_cmd) -> str:
4545
Fore.RED,
4646
"\n".join(prepend_tab(std_resp.stderr)),
4747
Fore.RESET,
48-
]
48+
],
4949
)
5050

5151
output = [
@@ -58,8 +58,8 @@ def format_tmux_resp(std_resp: tmux_cmd) -> str:
5858
"arch: %s" % platform.machine(),
5959
"uname: %s" % "; ".join(platform.uname()[:3]),
6060
"version: %s" % platform.version(),
61-
]
62-
)
61+
],
62+
),
6363
),
6464
output_break(),
6565
"python version: %s" % " ".join(sys.version.split("\n")),

0 commit comments

Comments
 (0)