Skip to content

Commit 4717b48

Browse files
committed
add a replace option to literalinclude, work on extension tutorial
1 parent 4868e3f commit 4717b48

File tree

17 files changed

+211
-126
lines changed

17 files changed

+211
-126
lines changed

check.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
poetry run ruff format django_typer
2+
poetry run ruff format --line-length 80 django_typer/examples
23
poetry run ruff check --fix --select I django_typer
34
poetry run ruff check --fix django_typer
45
poetry run mypy django_typer

django_typer/completers.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,5 +527,6 @@ def complete(ctx: Context, param: Parameter, incomplete: str):
527527

528528
databases = these_strings([alias for alias in settings.DATABASES.keys()])
529529
"""
530-
Get a completer that provides completion logic for Django database aliases.
530+
A completer that provides completion logic for the Django database aliases
531+
configured in settings.DATABASES.
531532
"""

django_typer/examples/multi.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,20 @@ class Command(TyperCommand):
1414
@command()
1515
def create(
1616
self,
17-
name: t.Annotated[str, Argument(help=_("The name of the object to create."))],
17+
name: t.Annotated[
18+
str, Argument(help=_("The name of the object to create."))
19+
],
1820
):
1921
"""
2022
Create an object.
2123
"""
2224

2325
@command()
2426
def delete(
25-
self, id: t.Annotated[int, Argument(help=_("The id of the object to delete."))]
27+
self,
28+
id: t.Annotated[
29+
int, Argument(help=_("The id of the object to delete."))
30+
],
2631
):
2732
"""
2833
Delete an object.

django_typer/examples/tutorial/backup/backup.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,12 @@ class Command(TyperCommand):
2424

2525
databases = [alias for alias in settings.DATABASES.keys()]
2626

27-
DEFAULT_DATABASE_FILENAME = "{database}.json"
28-
2927
output_directory: Path
3028

3129
@initialize(invoke_without_command=True)
32-
def default(
30+
def init_or_run_all(
3331
self,
32+
# if we add a context argument click will provide it
3433
context: typer.Context,
3534
output_directory: t.Annotated[
3635
Path,
@@ -50,24 +49,32 @@ def default(
5049
if not self.output_directory.is_dir():
5150
raise CommandError(f"{self.output_directory} is not a directory.")
5251

52+
# here we use the context to determine if a subcommand was invoked and
53+
# if it was not we run all the backup routines
5354
if not context.invoked_subcommand:
54-
for cmd in self.get_default_routines():
55+
for cmd in self.get_backup_routines():
5556
getattr(self, cmd)()
5657

57-
def get_default_routines(self) -> t.List[str]:
58+
def get_backup_routines(self) -> t.List[str]:
5859
"""
59-
Return the list of backup subcommands. This is every registered command except for the
60-
list command.
60+
Return the list of backup subcommands. This is every registered command
61+
except for the list command.
6162
"""
62-
return [cmd for cmd in self.get_subcommand().children.keys() if cmd != "list"]
63+
# fetch all the command names at the top level of our command tree,
64+
# except for list, which we know to not be a backup routine
65+
return [
66+
cmd
67+
for cmd in self.get_subcommand().children.keys()
68+
if cmd != "list"
69+
]
6370

6471
@command()
6572
def list(self):
6673
"""
6774
List the default backup routines in the order they will be run.
6875
"""
6976
self.echo("Default backup routines:")
70-
for cmd in self.get_default_routines():
77+
for cmd in self.get_backup_routines():
7178
kwargs = {
7279
name: str(param.default)
7380
for name, param in inspect.signature(
@@ -86,19 +93,20 @@ def database(
8693
"-f",
8794
"--filename",
8895
help=(
89-
"The name of the file to use for the backup fixture. The filename may "
90-
"optionally contain a {database} formatting placeholder."
96+
"The name of the file to use for the backup fixture. The "
97+
"filename may optionally contain a {database} formatting "
98+
"placeholder."
9199
),
92100
),
93-
] = DEFAULT_DATABASE_FILENAME,
101+
] = "{database}.json",
94102
databases: t.Annotated[
95103
t.Optional[t.List[str]],
96104
typer.Option(
97105
"-d",
98106
"--database",
99107
help=(
100-
"The name of the database(s) to backup. If not provided, all databases "
101-
"will be backed up."
108+
"The name of the database(s) to backup. If not provided, "
109+
"all databases will be backed up."
102110
),
103111
shell_complete=completers.databases,
104112
),

django_typer/examples/tutorial/backup/backup_inherit.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212

1313

1414
class Command(Backup):
15-
DEFAULT_MEDIA_FILENAME = "media.tar.gz"
16-
1715
@command()
1816
def media(
1917
self,
@@ -24,7 +22,7 @@ def media(
2422
"--filename",
2523
help=("The name of the file to use for the media backup tar."),
2624
),
27-
] = DEFAULT_MEDIA_FILENAME,
25+
] = "media.tar.gz",
2826
):
2927
"""
3028
Backup the media files (i.e. those files in MEDIA_ROOT).

django_typer/examples/tutorial/step2/closepoll.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ class Command(TyperCommand):
2020
def handle(
2121
self,
2222
poll_ids: Annotated[
23-
t.List[int], Argument(help=_("The database IDs of the poll(s) to close."))
23+
t.List[int],
24+
Argument(help=_("The database IDs of the poll(s) to close.")),
2425
],
2526
delete: Annotated[
2627
bool, Option(help=_("Delete poll instead of closing it."))

django_typer/examples/tutorial/step5/closepoll.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ def handle(
2222
t.List[Poll],
2323
Argument(
2424
parser=ModelObjectParser(Poll),
25-
shell_complete=ModelObjectCompleter(Poll, help_field="question_text"),
25+
shell_complete=ModelObjectCompleter(
26+
Poll, help_field="question_text"
27+
),
2628
help=_("The database IDs of the poll(s) to close."),
2729
),
2830
],

django_typer/examples/typer/hierarchy.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66

77
from django_typer import Typer
88

9-
app = Typer(help=_("A more complex command that defines a hierarchy of subcommands."))
9+
app = Typer(
10+
help=_("A more complex command that defines a hierarchy of subcommands.")
11+
)
1012

1113

1214
math_grp = Typer(help=_("Do some math at the given precision."))
@@ -27,7 +29,9 @@ def math(
2729
@math_grp.command(help=_("Multiply the given numbers."))
2830
def multiply(
2931
self,
30-
numbers: t.Annotated[t.List[float], Argument(help=_("The numbers to multiply"))],
32+
numbers: t.Annotated[
33+
t.List[float], Argument(help=_("The numbers to multiply"))
34+
],
3135
):
3236
return f"{reduce(lambda x, y: x * y, [1, *numbers]):.{self.precision}f}"
3337

django_typer/examples/typer/multi.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,19 @@
1010

1111
@app.command()
1212
def create(
13-
name: t.Annotated[str, Argument(help=_("The name of the object to create."))],
13+
name: t.Annotated[
14+
str, Argument(help=_("The name of the object to create."))
15+
],
1416
):
1517
"""
1618
Create an object.
1719
"""
1820

1921

2022
@app.command()
21-
def delete(id: t.Annotated[int, Argument(help=_("The id of the object to delete."))]):
23+
def delete(
24+
id: t.Annotated[int, Argument(help=_("The id of the object to delete."))],
25+
):
2226
"""
2327
Delete an object.
2428
"""

django_typer/tests/test_backup_example.py

Lines changed: 47 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -26,104 +26,87 @@ def tearDown(self) -> None:
2626
return super().tearDown()
2727

2828
def test_base_backup(self):
29-
lines = (
30-
run_command(
31-
"backup",
32-
"--no-color",
33-
"--settings",
34-
"django_typer.tests.settings.backup",
35-
"list",
36-
)[0]
37-
.strip()
38-
.splitlines()[1:]
29+
stdout, stderr, retcode = run_command(
30+
"backup",
31+
"--no-color",
32+
"--settings",
33+
"django_typer.tests.settings.backup",
34+
"list",
3935
)
36+
self.assertEqual(retcode, 0, msg=stderr)
37+
lines = stdout.strip().splitlines()[1:]
4038
self.assertEqual(len(lines), 1)
4139
self.assertEqual(
4240
lines[0].strip(),
4341
"database(filename={database}.json, databases=['default'])",
4442
)
4543

46-
self.assertEqual(
47-
run_command(
48-
"backup",
49-
"--settings",
50-
"django_typer.tests.settings.backup",
51-
"-o",
52-
str(BACKUP_DIRECTORY),
53-
)[-1],
54-
0,
44+
stdout, stderr, retcode = run_command(
45+
"backup",
46+
"--settings",
47+
"django_typer.tests.settings.backup",
48+
"-o",
49+
str(BACKUP_DIRECTORY),
5550
)
56-
51+
self.assertEqual(retcode, 0, msg=stderr)
5752
self.assertTrue(BACKUP_DIRECTORY.exists())
5853
self.assertTrue((BACKUP_DIRECTORY / "default.json").exists())
5954
self.assertTrue(len(os.listdir(BACKUP_DIRECTORY)) == 1)
6055

6156
def test_inherit_backup(self):
62-
lines = [
63-
line.strip()
64-
for line in run_command(
65-
"backup",
66-
"--no-color",
67-
"--settings",
68-
"django_typer.tests.settings.backup_inherit",
69-
"list",
70-
)[0]
71-
.strip()
72-
.splitlines()[1:]
73-
]
57+
stdout, stderr, retcode = run_command(
58+
"backup",
59+
"--no-color",
60+
"--settings",
61+
"django_typer.tests.settings.backup_inherit",
62+
"list",
63+
)
64+
self.assertEqual(retcode, 0, msg=stderr)
65+
lines = [line.strip() for line in stdout.strip().splitlines()[1:]]
7466
self.assertEqual(len(lines), 2)
7567
self.assertTrue(
7668
"database(filename={database}.json, databases=['default'])" in lines
7769
)
7870
self.assertTrue("media(filename=media.tar.gz)" in lines)
7971

80-
self.assertEqual(
81-
run_command(
82-
"backup",
83-
"--settings",
84-
"django_typer.tests.settings.backup_inherit",
85-
"-o",
86-
str(BACKUP_DIRECTORY),
87-
)[-1],
88-
0,
72+
stdout, stderr, retcode = run_command(
73+
"backup",
74+
"--settings",
75+
"django_typer.tests.settings.backup_inherit",
76+
"-o",
77+
str(BACKUP_DIRECTORY),
8978
)
90-
79+
self.assertEqual(retcode, 0, msg=stderr)
9180
self.assertTrue(BACKUP_DIRECTORY.exists())
9281
self.assertTrue((BACKUP_DIRECTORY / "default.json").exists())
9382
self.assertTrue((BACKUP_DIRECTORY / "media.tar.gz").exists())
9483
self.assertTrue(len(os.listdir(BACKUP_DIRECTORY)) == 2)
9584

9685
def test_extend_backup(self):
97-
lines = [
98-
line.strip()
99-
for line in run_command(
100-
"backup",
101-
"--no-color",
102-
"--settings",
103-
"django_typer.tests.settings.backup_ext",
104-
"list",
105-
)[0]
106-
.strip()
107-
.splitlines()[1:]
108-
]
86+
stdout, stderr, retcode = run_command(
87+
"backup",
88+
"--no-color",
89+
"--settings",
90+
"django_typer.tests.settings.backup_ext",
91+
"list",
92+
)
93+
self.assertEqual(retcode, 0, msg=stderr)
94+
lines = [line.strip() for line in stdout.strip().splitlines()[1:]]
10995
self.assertEqual(len(lines), 3)
11096
self.assertTrue(
11197
"database(filename={database}.json, databases=['default'])" in lines
11298
)
11399
self.assertTrue("environment(filename=requirements.txt)" in lines)
114100
self.assertTrue("media(filename=media.tar.gz)" in lines)
115101

116-
self.assertEqual(
117-
run_command(
118-
"backup",
119-
"--settings",
120-
"django_typer.tests.settings.backup_ext",
121-
"-o",
122-
str(BACKUP_DIRECTORY),
123-
)[-1],
124-
0,
102+
stdout, stderr, retcode = run_command(
103+
"backup",
104+
"--settings",
105+
"django_typer.tests.settings.backup_ext",
106+
"-o",
107+
str(BACKUP_DIRECTORY),
125108
)
126-
109+
self.assertEqual(retcode, 0, msg=stderr)
127110
self.assertTrue(BACKUP_DIRECTORY.exists())
128111
self.assertTrue((BACKUP_DIRECTORY / "default.json").exists())
129112
self.assertTrue((BACKUP_DIRECTORY / "media.tar.gz").exists())

0 commit comments

Comments
 (0)