10637.3.1
by Guilherme Salgado
Use the default python version instead of a hard-coded version |
1 |
#! /usr/bin/python -S
|
8687.15.4
by Karl Fogel
Add the copyright header block to more files; tweak format in a few files. |
2 |
#
|
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
3 |
# Copyright 2010 Canonical Ltd. This software is licensed under the
|
8687.15.4
by Karl Fogel
Add the copyright header block to more files; tweak format in a few files. |
4 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
5 |
|
6 |
"""Create a static WADL file describing the current webservice.
|
|
11369.3.1
by Benji York
checkpoint |
7 |
|
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
8 |
Example:
|
11369.3.1
by Benji York
checkpoint |
9 |
|
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
10 |
% LPCONFIG=development bin/py utilities/create-lp-wadl-and-apidoc.py \\
|
11 |
"lib/canonical/launchpad/apidoc/wadl-development-%(version)s.xml"
|
|
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
12 |
"""
|
13289.2.3
by Gary Poster
lint |
13 |
import _pythonpath # Not lint, actually needed. |
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
14 |
|
11929.14.1
by Benji York
parallelize the WADL generation |
15 |
from multiprocessing import Process |
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
16 |
import optparse |
10466.8.1
by Leonard Richardson
Initial implementation. |
17 |
import os |
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
18 |
import sys |
10420.4.1
by Leonard Richardson
Initial implementation. |
19 |
|
13289.2.2
by Gary Poster
set mtime of generated wadl files to correspond to last checkin of branch. This can let Apache serve ETags consistently across machines. |
20 |
import bzrlib |
21 |
from bzrlib.branch import Branch |
|
10420.4.1
by Leonard Richardson
Initial implementation. |
22 |
from zope.component import getUtility |
10466.8.1
by Leonard Richardson
Initial implementation. |
23 |
from zope.pagetemplate.pagetemplatefile import PageTemplateFile |
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
24 |
|
13289.2.1
by Gary Poster
make changes so that the wadl can be served directly from Apache. |
25 |
from canonical.launchpad.rest.wadl import ( |
26 |
generate_html, |
|
27 |
generate_json, |
|
28 |
generate_wadl, |
|
13289.2.3
by Gary Poster
lint |
29 |
)
|
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
30 |
from canonical.launchpad.scripts import execute_zcml_for_scripts |
7182.3.2
by Gary Poster
change code to keep launchpad code in launchpad, not lazr; add tests. Once (or if) lint is happy, this should be ready for review. |
31 |
from canonical.launchpad.systemhomes import WebServiceApplication |
10420.4.1
by Leonard Richardson
Initial implementation. |
32 |
from lazr.restful.interfaces import IWebServiceConfiguration |
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
33 |
|
10736.1.1
by Jonathan Lange
Use non-testing login in script required to build Launchpad |
34 |
|
13289.2.2
by Gary Poster
set mtime of generated wadl files to correspond to last checkin of branch. This can let Apache serve ETags consistently across machines. |
35 |
def write(filename, content, timestamp): |
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
36 |
"""Replace the named file with the given string."""
|
37 |
f = open(filename, 'w') |
|
38 |
f.write(content) |
|
39 |
f.close() |
|
13289.2.3
by Gary Poster
lint |
40 |
os.utime(filename, (timestamp, timestamp)) # (atime, mtime) |
41 |
||
13289.2.2
by Gary Poster
set mtime of generated wadl files to correspond to last checkin of branch. This can let Apache serve ETags consistently across machines. |
42 |
|
43 |
def make_files(directory, version, timestamp, force): |
|
13289.2.1
by Gary Poster
make changes so that the wadl can be served directly from Apache. |
44 |
version_directory = os.path.join(directory, version) |
45 |
base_filename = os.path.join(version_directory, os.environ['LPCONFIG']) |
|
46 |
wadl_filename = base_filename + '.wadl' |
|
47 |
json_filename = base_filename + '.json' |
|
48 |
html_filename = os.path.join(directory, version + ".html") |
|
49 |
wadl_index = os.path.join(version_directory, 'index.wadl') |
|
50 |
json_index = os.path.join(version_directory, 'index.json') |
|
51 |
html_index = os.path.join(version_directory, 'index.html') |
|
52 |
brokenwadl_index = os.path.join(version_directory, 'index.brokenwadl') |
|
53 |
||
54 |
# Make sure we have our dir.
|
|
55 |
if not os.path.exists(version_directory): |
|
56 |
# We expect the main directory to exist.
|
|
57 |
os.mkdir(version_directory) |
|
58 |
||
59 |
# Make wadl and json files.
|
|
60 |
for src, dest, gen, name in ( |
|
61 |
(wadl_filename, wadl_index, generate_wadl, 'WADL'), |
|
62 |
(json_filename, json_index, generate_json, 'JSON')): |
|
63 |
# If the src doesn't exist or we are forced to regenerate it...
|
|
64 |
if (not os.path.exists(src) or force): |
|
65 |
print "Writing %s for version %s to %s." % ( |
|
66 |
name, version, src) |
|
13289.2.2
by Gary Poster
set mtime of generated wadl files to correspond to last checkin of branch. This can let Apache serve ETags consistently across machines. |
67 |
write(src, gen(version), timestamp) |
13289.2.1
by Gary Poster
make changes so that the wadl can be served directly from Apache. |
68 |
else: |
69 |
print "Skipping already present %s file: %s" % ( |
|
70 |
name, src) |
|
71 |
# Make "index" symlinks, removing any preexisting ones.
|
|
72 |
if os.path.exists(dest): |
|
73 |
os.remove(dest) |
|
74 |
os.symlink(os.path.basename(src), dest) |
|
75 |
||
76 |
# Make the brokenwadl symlink. This is because we need to support a
|
|
77 |
# misspelled wadl mimetype that some legacy launchpadlib versions used.
|
|
78 |
# Multiple attempts have been made to make this unnecessary, and removing
|
|
79 |
# it is welcome. In particular, these two approaches were attempted in
|
|
80 |
# Apache.
|
|
81 |
#
|
|
82 |
# Approach 1 (a variant of example 4
|
|
83 |
# from http://httpd.apache.org/docs/2.0/mod/mod_headers.html)
|
|
84 |
# SetEnvIf Accept \Qapplication/vd.sun.wadl+xml\E X_WADL_MIME
|
|
85 |
# RequestHeader set Accept "application/vnd.sun.wadl+xml" env=X_WADL_MIME
|
|
86 |
# This, at least in combination with Apache's MultiViews, doesn't work
|
|
87 |
# in developer tests.
|
|
88 |
#
|
|
89 |
# Approach 2:
|
|
90 |
# In mime.conf,
|
|
91 |
# AddType application/vnd.sun.wadl+xml .wadl
|
|
92 |
# AddType application/vd.sun.wadl+xml .wadl
|
|
93 |
# In developer tests, it seems Apache only allows a single mime type
|
|
94 |
# for a given extension.
|
|
95 |
#
|
|
96 |
# Therefore, the approach we use is
|
|
97 |
# AddType application/vnd.sun.wadl+xml .wadl
|
|
98 |
# AddType application/vd.sun.wadl+xml .brokenwadl
|
|
99 |
# We support that here.
|
|
100 |
if not os.path.exists(brokenwadl_index): |
|
101 |
os.symlink(os.path.basename(wadl_index), brokenwadl_index) |
|
13289.2.3
by Gary Poster
lint |
102 |
|
11929.14.1
by Benji York
parallelize the WADL generation |
103 |
# Now, convert the WADL into an human-readable description and
|
104 |
# put the HTML in the same directory as the WADL.
|
|
105 |
# If the HTML file doesn't exist or we're being forced to regenerate
|
|
106 |
# it...
|
|
107 |
if (not os.path.exists(html_filename) or force): |
|
108 |
print "Writing apidoc for version %s to %s" % ( |
|
109 |
version, html_filename) |
|
110 |
write(html_filename, generate_html(wadl_filename, |
|
13289.2.2
by Gary Poster
set mtime of generated wadl files to correspond to last checkin of branch. This can let Apache serve ETags consistently across machines. |
111 |
suppress_stderr=False), timestamp) |
11929.14.1
by Benji York
parallelize the WADL generation |
112 |
else: |
113 |
print "Skipping already present HTML file:", html_filename |
|
114 |
||
13289.2.1
by Gary Poster
make changes so that the wadl can be served directly from Apache. |
115 |
# Symlink the top-level version html in the version directory for
|
116 |
# completeness.
|
|
117 |
if not os.path.exists(html_index): |
|
118 |
os.symlink( |
|
119 |
os.path.join(os.path.pardir, os.path.basename(html_filename)), |
|
120 |
html_index) |
|
121 |
||
122 |
||
123 |
def main(directory, force=False): |
|
13289.2.3
by Gary Poster
lint |
124 |
WebServiceApplication.cached_wadl = None # do not use cached file version |
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
125 |
execute_zcml_for_scripts() |
10420.4.1
by Leonard Richardson
Initial implementation. |
126 |
config = getUtility(IWebServiceConfiguration) |
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
127 |
|
10524.1.2
by Leonard Richardson
Style the apidoc index and simplify its generation. |
128 |
# First, create an index.html with links to all the HTML
|
129 |
# documentation files we're about to generate.
|
|
130 |
template_file = 'apidoc-index.pt' |
|
131 |
template = PageTemplateFile(template_file) |
|
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
132 |
index_filename = os.path.join(directory, "index.html") |
133 |
print "Writing index:", index_filename |
|
134 |
f = open(index_filename, 'w') |
|
10524.1.3
by Leonard Richardson
Simplified template code even more thanks to gary's code. |
135 |
f.write(template(config=config)) |
10524.1.2
by Leonard Richardson
Style the apidoc index and simplify its generation. |
136 |
|
13289.2.2
by Gary Poster
set mtime of generated wadl files to correspond to last checkin of branch. This can let Apache serve ETags consistently across machines. |
137 |
# Get the time of the last commit. We will use this as the mtime for the
|
138 |
# generated files so that we can safely use it as part of Apache's etag
|
|
139 |
# generation in the face of multiple servers/filesystems.
|
|
140 |
with bzrlib.initialize(): |
|
141 |
branch = Branch.open(os.path.dirname(os.path.dirname(__file__))) |
|
142 |
timestamp = branch.repository.get_revision( |
|
143 |
branch.last_revision()).timestamp |
|
144 |
||
11929.14.1
by Benji York
parallelize the WADL generation |
145 |
# Start a process to build each set of WADL and HTML files.
|
146 |
processes = [] |
|
10466.8.2
by Leonard Richardson
Minor cleanup. |
147 |
for version in config.active_versions: |
11929.14.1
by Benji York
parallelize the WADL generation |
148 |
p = Process(target=make_files, |
13289.2.2
by Gary Poster
set mtime of generated wadl files to correspond to last checkin of branch. This can let Apache serve ETags consistently across machines. |
149 |
args=(directory, version, timestamp, force)) |
11929.14.1
by Benji York
parallelize the WADL generation |
150 |
p.start() |
151 |
processes.append(p) |
|
10466.8.1
by Leonard Richardson
Initial implementation. |
152 |
|
11929.14.1
by Benji York
parallelize the WADL generation |
153 |
# Wait for all the subprocesses to finish.
|
154 |
for p in processes: |
|
155 |
p.join() |
|
10466.8.1
by Leonard Richardson
Initial implementation. |
156 |
|
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
157 |
return 0 |
158 |
||
11604.1.3
by Benji York
fix lint |
159 |
|
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
160 |
def parse_args(args): |
13289.2.1
by Gary Poster
make changes so that the wadl can be served directly from Apache. |
161 |
usage = "usage: %prog [options] DIR" |
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
162 |
parser = optparse.OptionParser(usage=usage) |
163 |
parser.add_option( |
|
164 |
"--force", action="store_true", |
|
165 |
help="Replace any already-existing files.") |
|
166 |
parser.set_defaults(force=False) |
|
167 |
options, args = parser.parse_args(args) |
|
168 |
if len(args) != 2: |
|
13289.2.1
by Gary Poster
make changes so that the wadl can be served directly from Apache. |
169 |
parser.error("A directory is required.") |
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
170 |
|
171 |
return options, args |
|
172 |
||
11604.1.3
by Benji York
fix lint |
173 |
|
6770.2.1
by Francis J. Lacoste
Add create-lp-wadl.py |
174 |
if __name__ == '__main__': |
11604.1.1
by Benji York
extract just the refactorings from my (now abandoned) check-in-wadl branch and |
175 |
options, args = parse_args(sys.argv) |
176 |
sys.exit(main(args[1], options.force)) |