Skip to content

Commit f363707

Browse files
authored
Update ruff to version 0.16.5 (#1738)
* Update typos to 1.50.0 * Upgrade ruff to 0.15.6 This new version of ruff now auto-formats Python code blocks in Markdown files. The main changes applies are whitespace and converting single quotes to double quotes in our Python code blocks in the Markdown documentation. I had to add a couple Markdown comments to turn formatting off and back on in some limited sections that use extra syntax for snippet inclusion that isn't supported by generic Markdown.
1 parent 6191df8 commit f363707

25 files changed

Lines changed: 276 additions & 199 deletions

‎.pre-commit-config.yaml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ repos:
1414
- id: trailing-whitespace
1515

1616
- repo: https://github.com/astral-sh/ruff-pre-commit
17-
rev: "v0.16.4"
17+
rev: "v0.16.5"
1818
hooks:
1919
- id: ruff-format
2020
args: [--config=ruff.toml]
@@ -30,7 +30,7 @@ repos:
3030
- prettier-plugin-toml@2.0.6
3131

3232
- repo: https://github.com/crate-ci/typos
33-
rev: v1.49.1
33+
rev: v1.50.0
3434
hooks:
3535
- id: typos
3636
exclude: |

‎README.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,22 @@ examples.
121121
```python
122122
#!/usr/bin/env python
123123
"""A simple cmd2 application."""
124+
124125
import cmd2
125126

126127

127128
class FirstApp(cmd2.Cmd):
128129
"""A simple cmd2 application."""
129130

130131
def do_hello_world(self, _: cmd2.Statement):
131-
self.poutput('Hello World')
132+
self.poutput("Hello World")
132133

133134

134-
if __name__ == '__main__':
135+
if __name__ == "__main__":
135136
import sys
136137

137138
c = FirstApp()
138139
sys.exit(c.cmdloop())
139-
140140
```
141141

142142
## Found a bug?

‎docs/examples/alternate_event_loops.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ by using code like the following:
3636
```py
3737
import cmd2
3838

39+
3940
class Cmd2EventBased(cmd2.Cmd):
4041
def __init__(self):
4142
cmd2.Cmd.__init__(self)
4243

4344
# ... your class code here ...
4445

45-
if __name__ == '__main__':
46+
47+
if __name__ == "__main__":
4648
app = Cmd2EventBased()
4749
app.preloop()
4850

‎docs/examples/getting_started.md‎

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ click the **Copy** button in the top-right):
1919

2020
!!! example "getting_started.py"
2121

22+
<!-- fmt:off -->
2223
```py
2324
--8<-- "examples/getting_started.py"
2425
```
26+
<!-- fmt:on -->
2527

2628
## Basic Application
2729

@@ -31,15 +33,17 @@ following contents:
3133
```py
3234
#!/usr/bin/env python
3335
"""A basic cmd2 application."""
36+
3437
import cmd2
3538

3639

3740
class BasicApp(cmd2.Cmd):
3841
"""Cmd2 application to demonstrate many common features."""
3942

4043

41-
if __name__ == '__main__':
44+
if __name__ == "__main__":
4245
import sys
46+
4347
app = BasicApp()
4448
sys.exit(app.cmdloop())
4549
```
@@ -69,7 +73,7 @@ def __init__(self):
6973

7074
# Make maxrepeats settable at runtime
7175
self.maxrepeats = 3
72-
self.add_settable(cmd2.Settable('maxrepeats', int, 'max repetitions for speak command', self))
76+
self.add_settable(cmd2.Settable("maxrepeats", int, "max repetitions for speak command", self))
7377
```
7478

7579
In that initializer, the first thing to do is to make sure we initialize `cmd2`. That's what the
@@ -94,25 +98,26 @@ that the `speak_parser` attribute and the `do_speak()` method are part of the `B
9498

9599
```py
96100
speak_parser = cmd2.Cmd2ArgumentParser()
97-
speak_parser.add_argument('-p', '--piglatin', action='store_true', help='atinLay')
98-
speak_parser.add_argument('-s', '--shout', action='store_true', help='N00B EMULATION MODE')
99-
speak_parser.add_argument('-r', '--repeat', type=int, help='output [n] times')
100-
speak_parser.add_argument('words', nargs='+', help='words to say')
101+
speak_parser.add_argument("-p", "--piglatin", action="store_true", help="atinLay")
102+
speak_parser.add_argument("-s", "--shout", action="store_true", help="N00B EMULATION MODE")
103+
speak_parser.add_argument("-r", "--repeat", type=int, help="output [n] times")
104+
speak_parser.add_argument("words", nargs="+", help="words to say")
105+
101106

102107
@cmd2.with_argparser(speak_parser)
103108
def do_speak(self, args):
104109
"""Repeats what you tell me to."""
105110
words = []
106111
for word in args.words:
107112
if args.piglatin:
108-
word = '%s%say' % (word[1:], word[0])
113+
word = "%s%say" % (word[1:], word[0])
109114
if args.shout:
110115
word = word.upper()
111116
words.append(word)
112117
repetitions = args.repeat or 1
113118
for _ in range(min(repetitions, self.maxrepeats)):
114119
# .poutput handles newlines, and accommodates output redirection too
115-
self.poutput(' '.join(words))
120+
self.poutput(" ".join(words))
116121
```
117122

118123
Up at the top of the script, you'll also need to add:
@@ -186,12 +191,12 @@ Let's add a shortcut for our `speak` command. Change the `__init__()` method so
186191
```py
187192
def __init__(self):
188193
shortcuts = cmd2.DEFAULT_SHORTCUTS
189-
shortcuts.update({'&': 'speak'})
194+
shortcuts.update({"&": "speak"})
190195
super().__init__(shortcuts=shortcuts)
191196

192197
# Make maxrepeats settable at runtime
193198
self.maxrepeats = 3
194-
self.add_settable(cmd2.Settable('maxrepeats', int, 'max repetitions for speak command', self))
199+
self.add_settable(cmd2.Settable("maxrepeats", int, "max repetitions for speak command", self))
195200
```
196201

197202
Shortcuts are passed to the `cmd2` initializer, and if you want the built-in shortcuts of `cmd2` you
@@ -224,14 +229,15 @@ def do_speak(self, args):
224229
words = []
225230
for word in args.words:
226231
if args.piglatin:
227-
word = '%s%say' % (word[1:], word[0])
232+
word = "%s%say" % (word[1:], word[0])
228233
if args.shout:
229234
word = word.upper()
230235
words.append(word)
231236
repetitions = args.repeat or 1
232237
for _ in range(min(repetitions, self.maxrepeats)):
233238
# .poutput handles newlines, and accommodates output redirection too
234-
self.poutput(' '.join(words))
239+
self.poutput(" ".join(words))
240+
235241

236242
# orate is a synonym for speak which takes multiline input
237243
do_orate = do_speak
@@ -241,7 +247,7 @@ With the new command created, we need to tell `cmd2` to treat that command as a
241247
Modify the super initialization line to look like this:
242248

243249
```py
244-
super().__init__(multiline_commands=['orate'], shortcuts=shortcuts)
250+
super().__init__(multiline_commands=["orate"], shortcuts=shortcuts)
245251
```
246252

247253
Now when you run the example, you can type something like this:

‎docs/features/annotated.md‎

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ The two decorators are interchangeable -- here is the same command written both
3131

3232
```py
3333
parser = Cmd2ArgumentParser()
34-
parser.add_argument('name', help='person to greet')
35-
parser.add_argument('--count', type=int, default=1, help='repetitions')
36-
parser.add_argument('--loud', action='store_true', help='shout')
34+
parser.add_argument("name", help="person to greet")
35+
parser.add_argument("--count", type=int, default=1, help="repetitions")
36+
parser.add_argument("--loud", action="store_true", help="shout")
37+
3738

3839
@with_argparser(parser)
3940
def do_greet(self, args):
@@ -61,6 +62,7 @@ Underscores in parameter names are converted to dashes in the generated flag, so
6162
```py
6263
from cmd2.annotated import with_annotated
6364

65+
6466
class MyApp(cmd2.Cmd):
6567
@with_annotated
6668
def do_greet(self, name: str, count: int = 1, loud: bool = False):
@@ -132,22 +134,30 @@ For finer control, use `typing.Annotated` with [Argument][cmd2.annotated.Argumen
132134
from typing import Annotated
133135
from cmd2.annotated import Argument, Option, with_annotated
134136

137+
135138
class MyApp(cmd2.Cmd):
136139
def sport_choices(self) -> cmd2.Choices:
137140
return cmd2.Choices.from_values(["football", "basketball"])
138141

139142
@with_annotated
140143
def do_play(
141144
self,
142-
sport: Annotated[str, Argument(
143-
choices_provider=sport_choices,
144-
help_text="Sport to play",
145-
)],
146-
venue: Annotated[str, Option(
147-
"--venue", "-v",
148-
help_text="Where to play",
149-
completer=cmd2.Cmd.path_complete,
150-
)] = "home",
145+
sport: Annotated[
146+
str,
147+
Argument(
148+
choices_provider=sport_choices,
149+
help_text="Sport to play",
150+
),
151+
],
152+
venue: Annotated[
153+
str,
154+
Option(
155+
"--venue",
156+
"-v",
157+
help_text="Where to play",
158+
completer=cmd2.Cmd.path_complete,
159+
),
160+
] = "home",
151161
):
152162
self.poutput(f"Playing {sport} at {venue}")
153163
```
@@ -173,6 +183,7 @@ import enum
173183
from typing import Annotated
174184
from cmd2.annotated import Argument, with_annotated
175185

186+
176187
class Color(enum.Enum):
177188
red = "red"
178189
green = "green"
@@ -183,6 +194,7 @@ class Color(enum.Enum):
183194
# map a special keyword onto a real member; return None to reject
184195
return cls.red if str(value).lower() == "auto" else None
185196

197+
186198
class MyApp(cmd2.Cmd):
187199
@with_annotated
188200
def do_theme(self, choice: Annotated[Color, Argument(allow_unknown_entry=True)]) -> None:
@@ -265,6 +277,7 @@ class UpperAction(argparse.Action):
265277
def __call__(self, parser, namespace, values, option_string=None):
266278
setattr(namespace, self.dest, values.upper())
267279

280+
268281
@with_annotated
269282
def do_shout(self, name: Annotated[str, Option("--name", action=UpperAction)] = ""):
270283
self.poutput(name)
@@ -298,6 +311,7 @@ forms are equivalent:
298311
# Signature default
299312
def do_x(self, name: Annotated[str, Option("--name")] = "HI"): ...
300313

314+
301315
# Metadata default (same behaviour)
302316
def do_x(self, name: Annotated[str, Option("--name", default="HI")]): ...
303317
```
@@ -359,11 +373,13 @@ import datetime
359373
from typing import Annotated
360374
from cmd2.annotated import Argument, Option, with_annotated
361375

376+
362377
def parse_size(value: str) -> int:
363378
"""Parse an integer with an optional K/M/G suffix."""
364379
multiplier = {"K": 1_000, "M": 1_000_000, "G": 1_000_000_000}.get(value[-1:].upper(), 1)
365380
return int(value[:-1] if multiplier != 1 else value) * multiplier
366381

382+
367383
class MyApp(cmd2.Cmd):
368384
@with_annotated
369385
def do_alloc(self, size: Annotated[int, Argument(converter=parse_size)]) -> None:
@@ -382,9 +398,11 @@ instead infer `nargs` and split the input across several tokens:
382398
```py
383399
from typing import Annotated, Any
384400

401+
385402
def parse_intset(value: str) -> set[int]:
386403
return {int(piece) for piece in value.split(",")}
387404

405+
388406
@with_annotated
389407
def do_select(self, idx: Annotated[Any, Option("--idx", converter=parse_intset)]) -> None:
390408
self.poutput(sorted(idx)) # `select --idx 1,3,5` -> [1, 3, 5]
@@ -404,6 +422,7 @@ import os
404422
from typing import Annotated
405423
from cmd2.annotated import Argument, with_annotated
406424

425+
407426
class MyApp(cmd2.Cmd):
408427
@with_annotated
409428
def do_tag(self, color: Annotated[Color, Argument(preprocess=str.lower)]) -> None:
@@ -486,6 +505,7 @@ and `description` for a titled help section (omit them for an untitled group):
486505
```py
487506
from cmd2.annotated import Group, with_annotated
488507

508+
489509
class App(cmd2.Cmd):
490510
@with_annotated(
491511
description="Open a network connection.",
@@ -509,6 +529,8 @@ def do_greet(self, name: str):
509529
:param name: who to greet
510530
"""
511531
self.poutput(f"hello {name}")
532+
533+
512534
# parser.description == "Greet someone by name."
513535
```
514536

@@ -532,9 +554,7 @@ choice reads as `[--json | --csv]` instead of expanding to `--json`/`--no-json`
532554

533555
```py
534556
@with_annotated(
535-
mutually_exclusive_groups=(
536-
Group("json", "csv", title="output", description="how to write results"),
537-
),
557+
mutually_exclusive_groups=(Group("json", "csv", title="output", description="how to write results"),),
538558
)
539559
def do_render(
540560
self,
@@ -560,6 +580,7 @@ class Conn(ArgumentBlock):
560580
host: Annotated[str, Option("--host")] = "localhost"
561581
port: Annotated[int, Option("--port")] = 8080
562582

583+
563584
@with_annotated(groups=(Group("host", "port", title="connection"),))
564585
def do_connect(self, conn: Conn) -> None: ...
565586
```
@@ -611,6 +632,7 @@ def do_manage(self, *, cmd2_subcommand_func):
611632
if cmd2_subcommand_func:
612633
cmd2_subcommand_func()
613634

635+
614636
@with_annotated(subcommand_to="manage", help="list projects")
615637
def manage_list(self):
616638
self.poutput("listing")
@@ -626,6 +648,7 @@ def manage_project(self, *, cmd2_subcommand_func):
626648
if cmd2_subcommand_func:
627649
cmd2_subcommand_func()
628650

651+
629652
@with_annotated(subcommand_to="manage project", help="add a project")
630653
def manage_project_add(self, name: str):
631654
self.poutput(f"added {name}")
@@ -770,9 +793,11 @@ decorator, it skips the first parameter as the method receiver (`self`/`cls`).
770793
```py
771794
from cmd2.annotated import build_parser_from_function
772795

796+
773797
def greet(self, name: str, count: int = 1):
774798
"""Greet someone."""
775799

800+
776801
parser = build_parser_from_function(greet)
777802
namespace = parser.parse_args(["Alice", "--count", "3"])
778803
# namespace.name == "Alice", namespace.count == 3

0 commit comments

Comments
 (0)