Skip to content

Commit 71e8ae7

Browse files
committed
Minor wording improvements
1 parent 692fbbd commit 71e8ae7

File tree

3 files changed

+91
-91
lines changed

3 files changed

+91
-91
lines changed

docs/features/argument_processing.md

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ command which might have its own argument parsing.
3939
For each command in the `cmd2.Cmd` subclass which requires argument parsing, create a unique
4040
instance of `argparse.ArgumentParser()` which can parse the input appropriately for the command.
4141
Then decorate the command method with the `@with_argparser` decorator, passing the argument parser
42-
as the first parameter to the decorator. This changes the second argument to the command method,
42+
as the first parameter to the decorator. This changes the second argument of the command method,
4343
which will contain the results of `ArgumentParser.parse_args()`.
4444

4545
Here's what it looks like:
@@ -68,10 +68,11 @@ def do_speak(self, opts):
6868

6969
!!! note
7070

71-
`cmd2` sets the `prog` variable in the argument parser based on the name of the method it is decorating. This will override anything you specify in `prog` variable when creating the argument parser.
71+
`cmd2` sets the `prog` variable in the argument parser based on the name of the method it is decorating.
72+
This will override anything you specify in `prog` variable when creating the argument parser.
7273

73-
As of the 3.0.0 release, `cmd2` sets `prog` when the instance-specific parser is created, which is
74-
later than it did previously.
74+
As of the 3.0.0 release, `cmd2` sets `prog` when the instance-specific parser is created, which is later
75+
than in previous versions.
7576

7677
## Help Messages
7778

@@ -110,7 +111,7 @@ optional arguments:
110111
```
111112

112113
If you would prefer, you can set the `description` while instantiating the `argparse.ArgumentParser`
113-
and leave the docstring on your method empty:
114+
and leave the docstring on your method blank:
114115

115116
```py
116117
from cmd2 import Cmd2ArgumentParser, with_argparser
@@ -226,8 +227,8 @@ class CmdLineApp(cmd2.Cmd):
226227

227228
## Unknown Positional Arguments
228229

229-
If you want all unknown arguments to be passed to your command as a list of strings, then decorate
230-
the command method with the `@with_argparser(..., with_unknown_args=True)` decorator.
230+
To pass all unknown arguments to be passed to your command as a list of strings, then decorate the
231+
command method with the `@with_argparser(..., with_unknown_args=True)` decorator.
231232

232233
Here's what it looks like:
233234

@@ -256,8 +257,8 @@ def do_dir(self, args, unknown):
256257

257258
## Using A Custom Namespace
258259

259-
In some cases, it may be necessary to write custom `argparse` code that is dependent on state data
260-
of your application. To support this ability while still allowing use of the decorators,
260+
In some cases, it may be necessary to write custom `argparse` code that is dependent on your
261+
application's state data. To support this ability while still allowing use of the decorators,
261262
`@with_argparser` has an optional argument called `ns_provider`.
262263

263264
`ns_provider` is a Callable that accepts a `cmd2.Cmd` object as an argument and returns an
@@ -283,8 +284,8 @@ To use this function with the `@with_argparser` decorator, do the following:
283284
@with_argparser(my_parser, ns_provider=settings_ns_provider)
284285
```
285286

286-
The Namespace is passed by the decorators to the `argparse` parsing functions which gives your
287-
custom code access to the state data it needs for its parsing logic.
287+
The Namespace is passed by the decorators to the `argparse` parsing functions, giving your custom
288+
code access to the state data it needs for its parsing logic.
288289

289290
## Subcommands
290291

@@ -313,9 +314,9 @@ The [@as_subcommand_to][cmd2.as_subcommand_to] decorator makes adding subcommand
313314
## Decorator Order
314315

315316
If you are using custom decorators in combination with `@cmd2.with_argparser`, then the order of
316-
your custom decorator(s) relative to the `cmd2` decorator matters when it comes to runtime behavior
317-
and `argparse` errors. There is nothing `cmd2`-specific here, this is just a side-effect of how
318-
decorators work in Python. To learn more about how decorators work, see
317+
your custom decorator(s) relative to the `cmd2` decorator affects runtime behavior and `argparse`
318+
errors. There is nothing `cmd2`-specific here, this is just a side-effect of how decorators work in
319+
Python. To learn more about how decorators work, see
319320
[decorator_primer](https://realpython.com/primer-on-python-decorators).
320321

321322
If you want your custom decorator's runtime behavior to occur in the case of an `argparse` error,
@@ -329,8 +330,8 @@ def do_foo(self, args: argparse.Namespace) -> None:
329330
pass
330331
```
331332

332-
However, if you do NOT want the custom decorator runtime behavior to occur even in the case of an
333-
`argparse` error, then that decorator needs to go **before** the `argparse` one, e.g.:
333+
However, if you do NOT want the custom decorator runtime behavior to occur during an `argparse`
334+
error, then that decorator needs to go **before** the `argparse` one, e.g.:
334335

335336
```py
336337
@my_decorator

docs/features/scripting.md

Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Scripting
22

3-
Operating system shells have long had the ability to execute a sequence of commands saved in a text
4-
file. These script files make long sequences of commands easier to repeatedly execute. `cmd2`
5-
supports two similar mechanisms: command scripts and python scripts.
3+
Operating system shells have long been able to execute a sequence of commands saved in a text file.
4+
These script files simplify the repeated execution of long command sequences. `cmd2` supports two
5+
similar mechanisms: command scripts and python scripts.
66

77
## Command Scripts
88

@@ -25,20 +25,19 @@ it inside a `cmd2` application.
2525

2626
Command script files can be executed using the built-in
2727
[run_script](./builtin_commands.md#run_script) command or the `@` shortcut (if your application is
28-
using the default shortcuts). Both ASCII and UTF-8 encoded unicode text files are supported. The
28+
using the default shortcuts). Both ASCII and UTF-8 encoded Unicode text files are supported. The
2929
[run_script](./builtin_commands.md#run_script) command supports tab completion of file system paths.
3030
There is a variant [\_relative_run_script](./builtin_commands.md#_relative_run_script) command or
3131
`@@` shortcut (if using the default shortcuts) for use within a script which uses paths relative to
3232
the first script.
3333

3434
### Comments
3535

36-
Any command line input where the first non-whitespace character is a `#` will be treated as a
37-
comment. This means any `#` character appearing later in the command will be treated as a literal.
38-
The same applies to a `#` in the middle of a multiline command, even if it is the first character on
39-
a line.
36+
A command line is a comment if the first non-whitespace character is a `#`. This means any `#`
37+
character appearing later in the command will be treated as a literal. The same applies to a `#` in
38+
the middle of a multiline command, even if it is the first character on a line.
4039

41-
Comments are useful in scripts, but would be pointless within an interactive session.
40+
Comments are useful in scripts, but are generally not used within an interactive session.
4241

4342
(Cmd) # this is a comment
4443
(Cmd) command # this is not a comment
@@ -62,11 +61,11 @@ as shown above it has the ability to pass command-line arguments to the scripts
6261

6362
## Developing a cmd2 API
6463

65-
If you as an app designer have not explicitly disabled the `run_pyscript` command it must be assumed
66-
that your application is structured for use in higher level python scripting. The following sections
67-
are meant as guidelines and highlight possible pitfalls with both production and consumption of API
68-
functionality. For clarity when speaking of "scripter" we are referring to those writing scripts to
69-
be run by pyscript and "designer" as the `cmd2` application author.
64+
If you as an app designer have not explicitly disabled the `run_pyscript` command, you should assume
65+
your application will be used for higher-level Python scripting. The following sections are meant as
66+
guidelines and highlight possible pitfalls with both production and consumption of API
67+
functionality. For clarity, a "scripter" writes pyscripts, and a "designer" is the `cmd2`
68+
application author.
7069

7170
### Basics
7271

@@ -76,10 +75,9 @@ workflows using simple `app` calls. The result of a `run_pyscript` app call yiel
7675
`data`.
7776

7877
`stdout` and `stderr` are fairly straightforward representations of normal data streams and
79-
accurately reflect what is seen by the user during normal cmd2 interaction. `stop` contains
80-
information about how the invoked command has ended its lifecycle. Lastly `data` contains any
81-
information the designer sets via `self.last_result` or `self._cmd.last_result` if called from
82-
inside a CommandSet.
78+
accurately reflect what the user sees during normal cmd2 interaction. `stop` contains information
79+
about how the invoked command has ended its lifecycle. Lastly `data` contains any information the
80+
designer sets via `self.last_result` or `self._cmd.last_result` if called from inside a CommandSet.
8381

8482
Python scripts executed with [run_pyscript](./builtin_commands.md#run_pyscript) can run `cmd2`
8583
application commands by using the syntax:
@@ -94,7 +92,7 @@ where:
9492
attribute
9593
- `command` and `args` are entered exactly like they would be entered by a user of your application.
9694

97-
Using fstrings tends to be the most straight forward and easily readable way to provide parameters.:
95+
Using f-strings tends to be the most straightforward and easily readable way to provide parameters.:
9896

9997
```py
10098
first = 'first'
@@ -112,11 +110,10 @@ script for more information.
112110
### Design principles
113111

114112
If your cmd2 application follows the
115-
[unix_design_philosophy](https://en.wikipedia.org/wiki/Unix_philosophy) a scripter will have the
116-
most flexibility to piece together workflows using different commands. If the designer's application
117-
is more complete and less likely to be augmented in the future a scripter may opt for simple serial
118-
scripts with little control flow. In either case, choices made by the designer will have effects on
119-
scripters.
113+
[Unix design philosophy](https://en.wikipedia.org/wiki/Unix_philosophy) a scripter will have the
114+
most flexibility to create workflows using different commands. If the designer's application is more
115+
complete and less likely to be augmented in the future a scripter can use simple serial scripts with
116+
little control flow. In either case, choices made by the designer will have effects on scripters.
120117

121118
The following diagram illustrates the different boundaries to keep in mind.
122119

@@ -140,18 +137,18 @@ flowchart LR
140137

141138
!!! note
142139

143-
As a designer it is preferable to design from the inside out. Your code will be infinitely far easier to unit test than at the higher level. While there are regression testing extensions for cmd2, unit testing will always be faster for development.
140+
As a designer, you should design from the inside out. Your code will be much easier to unit test than at the higher level. While there are regression testing extensions for cmd2, unit testing will always be faster for development.
144141

145142
!!! warning
146143

147-
It is bad design for a high level pyscript to know about, let alone access, low level class libraries of an application. Resist this urge at all costs, unless it's necessary.
144+
It is bad design for a high-level pyscript to know about, let alone access, low-level class libraries of an application. Resist this urge as much as possible, unless it's necessary.
148145

149146
### Developing a Basic API
150147

151-
`cmd2` out of the box allows scripters to take advantage of all exposed `do_*` commands. As a
152-
scripter one can easily interact with the application via `stdout` and `stderr`.
148+
By default, `cmd2` allows scripters to take advantage of all exposed `do_*` commands. As a scripter,
149+
you can easily interact with the application via `stdout` and `stderr`.
153150

154-
As a baseline let's start off with the the following `cmd2` application called `FirstApp`
151+
As a baseline, let's start with the following `cmd2` application called `FirstApp`
155152

156153
```py
157154
#!/usr/bin/env python
@@ -198,7 +195,7 @@ if __name__ == '__main__':
198195
sys.exit(c.cmdloop())
199196
```
200197

201-
Let's start off on the wrong foot:
198+
Let's start with an example of what not to do:
202199

203200
```py
204201
app('speak'
@@ -212,20 +209,20 @@ SyntaxError: unexpected EOF while parsing
212209
SyntaxError: unexpected EOF while parsing
213210
```
214211

215-
cmd2 pyscripts require **valid** python code as a first step.
212+
`cmd2` pyscripts require **valid** Python code as a first step.
216213

217214
!!! warning
218215

219-
It is a common misconception that all application exceptions will "bubble" up from below. Unfortunately or fortunately this is not the case. `cmd2` sinkholes all application exceptions and there are no means to handle them.
216+
It is a common misconception that all application exceptions will propagate up from below. This is not the case. `cmd2` catches all application exceptions and there are no means to handle them.
220217

221218
When executing the `speak` command without parameters you see the following error:
222219

223220
(Cmd) speak
224221
Usage: speak [-h] [-p] [-s] [-r REPEAT] words [...]
225222
Error: the following arguments are required: words
226223

227-
Even though this is a fully qualified `cmd2` error the pyscript must look for this error and perform
228-
error checking.:
224+
Even though this is a fully qualified `cmd2` error, the pyscript must check for this error and
225+
perform error checking.:
229226

230227
```py
231228
app('speak')
@@ -247,7 +244,7 @@ print(result)
247244
(Cmd) run_pyscript script.py
248245
CommandResult(stdout='', stderr='Usage: speak [-h] [-p] [-s] [-r REPEAT] words [...]\nError: the following arguments are required: words\n\n', stop=False, data=None)
249246

250-
Now we can see that there has been an error. Let's re write the script to perform error checking.:
247+
Now we can see that there has been an error. Let's rewrite the script to perform error checking.:
251248

252249
```py
253250
result = app('speak')
@@ -259,7 +256,7 @@ if not result:
259256
(Cmd) run_pyscript script.py
260257
Something went wrong
261258

262-
In Python development, it is good practice to fail and exit quickly after user input.:
259+
In Python development, it is good practice to fail fast after user input.:
263260

264261
```py
265262
import sys
@@ -276,8 +273,8 @@ print("Continuing along..")
276273
(Cmd) run_pyscript script.py
277274
Continuing along..
278275

279-
We changed the input to be a valid `speak` command but no output. Again we must inspect the
280-
`CommandResult`:
276+
We changed the input to be a valid `speak` command, but there was no output. Again we must inspect
277+
the `CommandResult`:
281278

282279
```py
283280
import sys
@@ -294,18 +291,18 @@ print(result.stdout)
294291
(Cmd) run_pyscript script.py
295292
TRUTH!!!
296293

297-
By just using `stdout` and `stderr` it is possible to string together commands with rudimentary
298-
control flow. In the next section we will show how to take advantage of `cmd_result` data.
294+
By just using `stdout` and `stderr` it is possible to chain commands with rudimentary control flow.
295+
In the next section we will show how to use `cmd_result` data.
299296

300297
### Developing an Advanced API
301298

302-
Until now the application designer has paid little attention to scripters and their needs. Wouldn't
303-
it be nice if while creating pyscripts one did not have to parse data from `stdout`? We can
304-
accommodate the weary scripter by adding one small line at the end of our `do_*` commands.
299+
So far, we haven't focused on the scripter's needs. Wouldn't it be nice if while creating pyscripts
300+
you did not have to parse data from `stdout`? We can accommodate the scripter by adding one small
301+
line at the end of our `do_*` commands.
305302

306303
`self.last_result = <value>`
307304

308-
Adding the above line supercharges a cmd2 application and opens a new world of possibilities.
305+
Adding the above line enhances a cmd2 application and opens a new world of possibilities.
309306

310307
!!! tip
311308

@@ -315,7 +312,7 @@ Adding the above line supercharges a cmd2 application and opens a new world of p
315312
self._cmd.last_result = <value>
316313
```
317314

318-
In the following command example we return an array containing directory elements.:
315+
In the following command example we return a list containing directory elements.:
319316

320317
```py
321318
dir_parser = cmd2.Cmd2ArgumentParser()
@@ -353,22 +350,22 @@ Results:
353350
Cmd) run_pyscript script.py
354351
['.venv', 'app.py', 'script.py']
355352

356-
As a rule of thumb it is safer for the designer to return simple scalar types as command results
357-
instead of complex objects. If there is benefit in providing class objects designers should choose
358-
immutable over mutable types and never provide direct access to class members as this could
359-
potentially lead to violation of the
360-
[open_closed_principle](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle).
353+
As a rule of thumb, designers should return simple scalar types as command results instead of
354+
complex objects. If it is beneficial in providing class objects designers should choose immutable
355+
over mutable types and never provide direct access to class members as this could potentially lead
356+
to violation of the
357+
[open-closed_principle](https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle).
361358

362-
When possible, a frozen dataclass is a lightweight solution perfectly suited for data manipulation.
363-
Let's dive into an example.
359+
When possible, a frozen dataclass is a lightweight solution ideal for data manipulation. Let's look
360+
at an example.
364361

365-
The following fictional application has two commands: `build` and `status`. We can pretend that the
366-
build action happens somewhere else in the world at a REST API endpoint and has significant
367-
computational cost. The status command for all intents and purposes, will only show the current
368-
status of a build task. The application has provided all that is needed for a user to start a build
369-
and then determine its status. The problem however is that with a long running process the user may
370-
want to wait for it to finish. A designer may be tempted to create a command to start a build and
371-
then poll for status until finished, but this scenario is better solved as an extensible script.
362+
The following application has two commands: `build` and `status`. Let's assume that the build action
363+
happens somewhere else in the world at a REST API endpoint and has significant computational cost.
364+
The status command, will only show the current status of a build task. The application has provided
365+
everything that is needed for a user to start a build and then determine its status. However, the
366+
problem is that with a long running process the user may want to wait for it to finish. A designer
367+
may be tempted to create a command to start a build and then poll for status until finished, but
368+
this scenario is better solved as a script.
372369

373370
app.py:
374371

@@ -446,7 +443,7 @@ if __name__ == "__main__":
446443
sys.exit(c.cmdloop())
447444
```
448445

449-
The below is a possible solution via pyscript:
446+
Below is a possible solution via pyscript:
450447

451448
```py
452449
import sys
@@ -455,7 +452,7 @@ import time
455452
# start build
456453
result = app('build tower')
457454

458-
# If there was an error then quit now
455+
# If there was an error then exit
459456
if not result:
460457
print('Build failed')
461458
sys.exit()
@@ -465,7 +462,7 @@ build = result.data
465462

466463
print(f"Build {build.name} : {build.status}")
467464

468-
# Poll status (it would be wise to NOT hang here)
465+
# Poll status
469466
while True:
470467

471468
# Perform status check
@@ -478,7 +475,7 @@ while True:
478475

479476
build_status = result.data
480477

481-
# If the status shows complete then we are done
478+
# If the status shows complete then the script is done
482479
if build_status.status in ['finished', 'canceled']:
483480
print(f"Build {build.name} has completed")
484481
break

0 commit comments

Comments
 (0)