Skip to content

Commit e6dfbaa

Browse files
authored
Merge pull request #149 from opengisch/upgrade
Add Upgrade capability
2 parents 5d10c48 + f1b5f43 commit e6dfbaa

19 files changed

+470
-137
lines changed

docs/docs/cli.md

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
usage: create_cli_help.py [-h] [-c CONFIG_FILE] -s PG_SERVICE [-d DIR] [-v] [--version]
2-
- `{info,install,role,check,dump,restore,baseline,upgrade} ...`
3-
1+
usage: update_cli_docs.py [-h] [-c CONFIG_FILE] -s PG_SERVICE [-d DIR] [-v] [--version]
2+
{info,install,role,check,dump,restore,baseline,upgrade} ...
43
### options:
54
- `-h, --help`: show this help message and exit
6-
- `-c CONFIG_FILE, --config_file CONFIG_FILE`
7-
- `set the config file. Default: .pum.yaml`
8-
- `-s PG_SERVICE, --pg-service PG_SERVICE`
9-
- `Name of the postgres service`
5+
- `-c CONFIG_FILE, --config_file CONFIG_FILE`: set the config file. Default: .pum.yaml
6+
- `-s PG_SERVICE, --pg-service PG_SERVICE`: Name of the postgres service
107
- `-d DIR, --dir DIR`: Directory or URL of the module. Default: .
118
- `-v, --verbose`: Increase output verbosity (e.g. -v, -vv)
129
- `--version`: Show program's version number and exit.
13-
1410
### commands:
15-
- `valid pum commands`
16-
17-
- `{info,install,role,check,dump,restore,baseline,upgrade}`
11+
valid pum commands
12+
{info,install,role,check,dump,restore,baseline,upgrade}
1813
- `info`: show info about schema migrations history.
1914
- `install`: Installs the module.
2015
- `role`: manage roles in the database

docs/docs/cli/baseline.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
usage: create_cli_help.py baseline [-h] -b BASELINE
2-
1+
usage: update_cli_docs.py baseline [-h] -b BASELINE
32
### options:
43
- `-h, --help`: show this help message and exit
5-
- `-b BASELINE, --baseline BASELINE`: set baseline in the format x.x.x
6-
- `--create-table`: create the pum_migrations table if it does not exist
4+
- `-b BASELINE, --baseline BASELINE`: Set baseline in the format x.x.x

docs/docs/cli/check.md

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
usage: create_cli_help.py check [-h]
2-
- `[-i {tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} [{tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} ...]]`
3-
- `[-N EXCLUDE_SCHEMA] [-P EXCLUDE_FIELD_PATTERN] [-o OUTPUT_FILE]`
4-
1+
usage: update_cli_docs.py check [-h]
2+
[-i {tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} [{tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} ...]]
3+
[-N EXCLUDE_SCHEMA] [-P EXCLUDE_FIELD_PATTERN] [-o OUTPUT_FILE]
54
### options:
65
- `-h, --help`: show this help message and exit
7-
- `-i {tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} [{tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} ...], --ignore {tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} [{tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} ...]`
8-
- `Elements to be ignored`
9-
- `-N EXCLUDE_SCHEMA, --exclude-schema EXCLUDE_SCHEMA`
10-
- `Schema to be ignored.`
11-
- `-P EXCLUDE_FIELD_PATTERN, --exclude-field-pattern EXCLUDE_FIELD_PATTERN`
12-
- `Fields to be ignored based on a pattern compatible with SQL LIKE.`
13-
- `-o OUTPUT_FILE, --output_file OUTPUT_FILE`
14-
- `Output file`
6+
- `-i {tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} [{tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} ...], --ignore {tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} [{tables,columns,constraints,views,sequences,indexes,triggers,functions,rules} ...]`: Elements to be ignored
7+
- `-N EXCLUDE_SCHEMA, --exclude-schema EXCLUDE_SCHEMA`: Schema to be ignored.
8+
- `-P EXCLUDE_FIELD_PATTERN, --exclude-field-pattern EXCLUDE_FIELD_PATTERN`: Fields to be ignored based on a pattern compatible with SQL LIKE.
9+
- `-o OUTPUT_FILE, --output_file OUTPUT_FILE`: Output file

docs/docs/cli/dump.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
usage: create_cli_help.py dump [-h] [-f {DumpFormat.CUSTOM,DumpFormat.PLAIN}] [-N EXCLUDE_SCHEMA] file
2-
1+
usage: update_cli_docs.py dump [-h] [-f {DumpFormat.CUSTOM,DumpFormat.PLAIN}] [-N EXCLUDE_SCHEMA] file
32
### positional arguments:
43
- `file`: The backup file
5-
64
### options:
75
- `-h, --help`: show this help message and exit
86
- `-f {DumpFormat.CUSTOM,DumpFormat.PLAIN}, --format {DumpFormat.CUSTOM,DumpFormat.PLAIN}`: Dump format. Choices: ['custom', 'plain']. Default: plain.

docs/docs/cli/info.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
usage: create_cli_help.py info [-h]
2-
1+
usage: update_cli_docs.py info [-h]
32
### options:
43
- `-h, --help`: show this help message and exit

docs/docs/cli/install.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
usage: create_cli_help.py install [-h] [-p PARAMETER PARAMETER] [--max-version MAX_VERSION] [-r] [-g]
2-
1+
usage: update_cli_docs.py install [-h] [-p PARAMETER PARAMETER] [--max-version MAX_VERSION] [-r] [-g]
2+
[-d DEMO_DATA] [--beta-testing]
33
### options:
44
- `-h, --help`: show this help message and exit
5-
- `-p PARAMETER PARAMETER, --parameter PARAMETER PARAMETER`
6-
- `Assign variable for running SQL deltas. Format is name value.`
7-
- `--max-version MAX_VERSION`
8-
- `maximum version to install`
5+
- `-p PARAMETER PARAMETER, --parameter PARAMETER PARAMETER`: Assign variable for running SQL deltas. Format is name value.
6+
- `--max-version MAX_VERSION`: maximum version to install
97
- `-r, --roles`: Create roles
108
- `-g, --grant`: Grant permissions to roles
9+
- `-d DEMO_DATA, --demo-data DEMO_DATA`: Load demo data with the given name
10+
- `--beta-testing`: This will install the module in beta testing, meaning that it will not be possible to receive any future updates.

docs/docs/cli/restore.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
usage: create_cli_help.py restore [-h] [-x] [-N EXCLUDE_SCHEMA] file
2-
1+
usage: update_cli_docs.py restore [-h] [-x] [-N EXCLUDE_SCHEMA] file
32
### positional arguments:
43
- `file`: The backup file
5-
64
### options:
75
- `-h, --help`: show this help message and exit
86
- `-x`: ignore pg_restore errors
9-
- `-N EXCLUDE_SCHEMA, --exclude-schema EXCLUDE_SCHEMA`
10-
- `Schema to be ignored.`
7+
- `-N EXCLUDE_SCHEMA, --exclude-schema EXCLUDE_SCHEMA`: Schema to be ignored.

docs/docs/cli/role.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
usage: create_cli_help.py role [-h] {create,grant,revoke,drop}
2-
1+
usage: update_cli_docs.py role [-h] {create,grant,revoke,drop}
32
### positional arguments:
4-
- `{create,grant,revoke,drop}`
5-
- `Action to perform`
6-
3+
{create,grant,revoke,drop}
4+
Action to perform
75
### options:
86
- `-h, --help`: show this help message and exit

docs/docs/cli/upgrade.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
usage: create_cli_help.py upgrade [-h] [-u MAX_VERSION] [-p PARAMETER PARAMETER]
2-
1+
usage: update_cli_docs.py upgrade [-h] [-u MAX_VERSION] [-p PARAMETER PARAMETER]
32
### options:
43
- `-h, --help`: show this help message and exit
5-
- `-u MAX_VERSION, --max-version MAX_VERSION`
6-
- `upper bound limit version`
7-
- `-p PARAMETER PARAMETER, --parameter PARAMETER PARAMETER`
8-
- `Assign variable for running SQL deltas. Format is: name value.`
4+
- `-u MAX_VERSION, --max-version MAX_VERSION`: upper bound limit version
5+
- `-p PARAMETER PARAMETER, --parameter PARAMETER PARAMETER`: Assign variable for running SQL deltas. Format is: name value.

docs/update_cli_docs.py

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
11
#!/usr/bin/env python3
2+
"""Generate Markdown documentation from the CLI argparse help output.
3+
4+
This script renders the `pum` CLI help (and each subcommand help) into Markdown.
5+
It also normalizes wrapped help text so option/parameter descriptions are
6+
single-line in the generated docs.
7+
"""
8+
29
import argparse
310
import io
411
import contextlib
12+
import re
513

614
from pum.cli import create_parser
715
from pathlib import Path
816

917

1018
def parser_to_markdown(parser: argparse.ArgumentParser) -> str:
19+
"""Convert an argparse parser's help text to Markdown.
20+
21+
Args:
22+
parser: The argparse parser to render.
23+
24+
Returns:
25+
The generated Markdown string.
26+
27+
"""
1128
buf = io.StringIO()
1229
with contextlib.redirect_stdout(buf):
1330
parser.print_help()
@@ -16,17 +33,55 @@ def parser_to_markdown(parser: argparse.ArgumentParser) -> str:
1633
# Simple Markdown formatting
1734
lines = help_text.strip().splitlines()
1835
md_lines = []
36+
entry_re = re.compile(r"^\s{2,}(?P<key>\S.*?)\s{2,}(?P<desc>.+)$")
37+
38+
def norm(text: str) -> str:
39+
# Collapse any wrapping/newlines/tabs into single spaces.
40+
return " ".join(text.split())
41+
42+
last_entry_index: int | None = None
1943
for line in lines:
20-
if line.strip().endswith(":"):
21-
md_lines.append(f"### {line.strip()}")
22-
elif line.startswith(" "): # typically an argument line
23-
parts = line.strip().split(" ", 1)
24-
if len(parts) == 2:
25-
md_lines.append(f"- `{parts[0]}`: {parts[1].strip()}")
44+
stripped = line.rstrip("\n")
45+
if not stripped:
46+
continue
47+
48+
indent = len(stripped) - len(stripped.lstrip(" "))
49+
50+
# Section headers from argparse typically end with ':' and are not indented.
51+
if stripped.strip().endswith(":") and not stripped.startswith(" "):
52+
md_lines.append(f"### {stripped.strip()}")
53+
last_entry_index = None
54+
continue
55+
56+
match = entry_re.match(stripped)
57+
if match:
58+
key = match.group("key").strip()
59+
desc = norm(match.group("desc"))
60+
md_lines.append(f"- `{key}`: {desc}")
61+
last_entry_index = len(md_lines) - 1
62+
continue
63+
64+
# Some argparse formats print the option/arg key on its own line, with the
65+
# description starting on the next (more-indented) line.
66+
if indent >= 2 and indent <= 4:
67+
key_only = stripped.strip()
68+
if key_only.startswith("-") and not key_only.endswith(":"):
69+
md_lines.append(f"- `{key_only}`:")
70+
last_entry_index = len(md_lines) - 1
71+
continue
72+
73+
# Wrapped description lines are indented, but don't start a new entry.
74+
if stripped.startswith(" ") and last_entry_index is not None:
75+
addition = norm(stripped)
76+
if md_lines[last_entry_index].endswith(":"):
77+
md_lines[last_entry_index] = f"{md_lines[last_entry_index]} {addition}"
2678
else:
27-
md_lines.append(f"- `{line.strip()}`")
28-
else:
29-
md_lines.append(line.strip())
79+
md_lines[last_entry_index] = f"{md_lines[last_entry_index]} {addition}"
80+
continue
81+
82+
# Plain text paragraph.
83+
md_lines.append(stripped.strip())
84+
last_entry_index = None
3085
return "\n".join(md_lines)
3186

3287

0 commit comments

Comments
 (0)