Repository navigation
Expand file tree
/
Copy pathfetch_python_docs.py
More file actions
executable file
·146 lines (117 loc) · 4.2 KB
/
Copy pathfetch_python_docs.py
File metadata and controls
executable file
·146 lines (117 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python
"""Idempotently download, extract, and serve a mirror of <docs.python.org>."""
import argparse
import http.client
import shlex
import subprocess
import sys
import tarfile
from pathlib import Path
import requests
from send2trash import send2trash
HERE = Path(__file__).parent
# Something other than the default 8000 used by python -m http.server
PORT = "8004"
def get_options():
"""Parse command line options."""
parser = argparse.ArgumentParser(
description="Idempotently download and serve Python docs from a local copy"
)
parser.add_argument(
"--systemd",
action="store_true",
help="Also create, enable, and start a systemd service",
)
parser.add_argument(
"--clean",
action="store_true",
help="Clean out past downloads and unit files (uninstall)",
)
return parser.parse_args()
def clean():
"""Clean (trash) past downloads and unit files."""
print("Cleaning past downloads and unit files")
trash_targets = []
if (
p := Path.home() / ".config" / "systemd" / "user" / "python-docs.service"
).exists():
cmd = ["systemctl", "--user", "disable", "--now", "python-docs.service"]
print(f" {shlex.join(cmd)}")
subprocess.run(cmd).check_returncode()
trash_targets.append(p)
trash_targets.extend(HERE.glob("python-*.*-docs*/"))
trash_targets.extend(HERE.glob("python-*.*-docs*.tar.bz2"))
for p in trash_targets:
print(f" Trashing {p}")
send2trash(trash_targets)
def download_extract():
"""Download and extract Python docs to `HERE`."""
major, minor, *_ = sys.version_info
url = f"https://docs.python.org/{major}.{minor}/archives/python-{major}.{minor}-docs-html.tar.bz2"
outfile = HERE / f"python-{major}.{minor}-docs-html.tar.bz2"
print(f"Downloading {url}")
if outfile.is_file():
print(f" Already exists: {outfile}")
else:
with requests.get(url) as r, open(outfile, "wb") as f:
if r.status_code != 200:
descr = http.client.responses[r.status_code]
raise RuntimeError(f"{r.status_code = } ({descr})")
f.write(r.content)
print(f" Downloaded: {outfile} ({len(r.content)} bytes)")
print(f"Extracting {outfile}")
assert outfile.is_file()
outdir = HERE / f"python-{major}.{minor}-docs-html"
if (outdir / "index.html").is_file():
print(f" Already exists: {outdir}/index.html")
else:
with tarfile.open(outfile) as f:
f.extractall(path=HERE, filter="data") # Extracting HERE creates outdir
assert (outdir / "index.html").is_file()
return outdir
def define_user_service(outdir):
"""Create a systemd unit file to serve docs as a user service."""
print("Creating systemd unit file")
if not Path("/run/systemd/system").exists():
raise ValueError("Host appears not to use systemd")
dest = Path.home() / ".config" / "systemd" / "user" / "python-docs.service"
dest.parent.mkdir(parents=True, exist_ok=True)
cmd = shlex.join(
[sys.executable, "-m", "http.server", "-d", str(outdir.absolute()), PORT]
)
body = f"""\
# Autogenerated by {__file__}
[Service]
Type=simple
Description=Serve Python docs on port {PORT}
ExecStart={cmd}
[Install]
WantedBy=default.target
"""
if dest.is_file():
with open(dest) as f:
contents = f.read()
if contents == body:
print(f" Already defined: {dest}")
return
with open(dest, "w") as f:
f.write(body)
print(f" Saved: {dest}")
def enable_user_service():
"""Start and enable the systemd unit service."""
print("Enabling and starting systemd user service")
cmd = ["systemctl", "--user", "daemon-reload"]
print(f" {shlex.join(cmd)}")
subprocess.run(cmd).check_returncode()
cmd = ["systemctl", "--user", "enable", "--now", "python-docs"]
print(f" {shlex.join(cmd)}")
subprocess.run(cmd).check_returncode()
if __name__ == "__main__":
options = get_options()
if options.clean:
clean()
exit()
outdir = download_extract()
if options.systemd:
define_user_service(outdir)
enable_user_service()