Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 183 lines (162 sloc) 6.845 kb
3764bb8 @ericholscher No more 'make html' for html building. This makes the code much simpl…
ericholscher authored
1 import os
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
2 import shutil
67639d5 @ericholscher Try and fix the whitelisting for UTF-8
ericholscher authored
3 import codecs
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
4 import zipfile
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
5 import logging
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
6
7 from django.template.loader import render_to_string
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
8 from django.template import Template, Context
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
9 from django.contrib.auth.models import SiteProfileNotAvailable
10 from django.core.exceptions import ObjectDoesNotExist
11 from django.conf import settings
12
a251351 @dcolish add decorator to restore cwd after running build commands, use safe_w…
dcolish authored
13 from doc_builder.base import BaseBuilder, restoring_chdir
3764bb8 @ericholscher No more 'make html' for html building. This makes the code much simpl…
ericholscher authored
14 from projects.utils import safe_write, run
b87a808 @ericholscher Fix import.
ericholscher authored
15 from core.utils import copy_to_app_servers, copy_file_to_app_servers
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
16
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
17 log = logging.getLogger(__name__)
18
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
19
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
20 RTD_CONF_ADDITIONS = """
d3df075 @dangra sort available doc versions using NormalizedVersion
dangra authored
21 {% load projects_tags %}
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
22 #Add RTD Template Path.
23 if 'templates_path' in locals():
24 templates_path.insert(0, '{{ template_path }}')
25 else:
26 templates_path = ['{{ template_path }}', 'templates', '_templates', '.templates']
27
594f690 @ericholscher Try and fix static file overwriting.
ericholscher authored
28 #Add RTD Static Path. Add to the end because it overwrites previous files.
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
29 if 'html_static_path' in locals():
594f690 @ericholscher Try and fix static file overwriting.
ericholscher authored
30 html_static_path.append('{{ static_path }}')
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
31 else:
594f690 @ericholscher Try and fix static file overwriting.
ericholscher authored
32 html_static_path = ['_static', '{{ static_path }}']
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
33
34 #Add RTD CSS File only if they aren't overriding it already
35 using_rtd_theme = False
bedc3f0 @ericholscher Make the python whitelisting a bit nicer.
ericholscher authored
36 if project == "Python":
37 #Do nothing for Python theme-wise
38 pass
39 elif 'html_theme' in locals():
35b83e5 @ericholscher Use the RTD theme instead of the Sphinx default.
ericholscher authored
40 if html_theme in ['default']:
bedc3f0 @ericholscher Make the python whitelisting a bit nicer.
ericholscher authored
41 if not 'html_style' in locals():
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
42 html_style = 'rtd.css'
43 html_theme = 'default'
44 html_theme_options = {}
45 using_rtd_theme = True
0983bc3 @ericholscher Theme docs that don't have a theme set.
ericholscher authored
46 else:
47 html_style = 'rtd.css'
48 html_theme = 'default'
49 html_theme_options = {}
50 using_rtd_theme = True
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
51
52 #Add sponsorship and project information to the template context.
53 context = {
54 'using_theme': using_rtd_theme,
4c31b1c @ericholscher Build in alerting for old versions of documentation.
ericholscher authored
55 'current_version': "{{ current_version.slug }}",
56 'MEDIA_URL': "{{ settings.MEDIA_URL }}",
d3df075 @dangra sort available doc versions using NormalizedVersion
dangra authored
57 'versions': [{% for version in versions|sort_version_aware %}
2880753 @ericholscher Remove another DB dependency. They hide everywhere.
ericholscher authored
58 ("{{ version.slug }}", "{{ version.absolute_url }}"),{% endfor %}
a132808 @ericholscher Make a list to preserve order.
ericholscher authored
59 ],
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
60 'slug': '{{ project.slug }}',
6be37c1 @ericholscher Make unicode strings for project name.
ericholscher authored
61 'name': u'{{ project.name }}',
9b3f6e0 @ericholscher Add first alternate builder backend, which is sphinx's htmldir.
ericholscher authored
62 'badge_revsys': {{ project.sponsored }},
63 'analytics_code': '{{ project.analytics_code }}',
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
64 }
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
65 if 'html_context' in locals():
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
66 html_context.update(context)
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
67 else:
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
68 html_context = context
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
69 """
70
c6795cb @ericholscher Find the right templates in the html builder.
ericholscher authored
71 TEMPLATE_DIR = '%s/readthedocs/templates/sphinx' % settings.SITE_ROOT
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
72 STATIC_DIR = '%s/_static' % TEMPLATE_DIR
5c6f3d2 @ericholscher Integrate versions into pdf building.
ericholscher authored
73
a251351 @dcolish add decorator to restore cwd after running build commands, use safe_w…
dcolish authored
74
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
75 class Builder(BaseBuilder):
47e7106 @ericholscher Added the changed property to Backend classes.
ericholscher authored
76 """
77 The parent for most sphinx builders.
78
79 Also handles the default sphinx output of html.
80 """
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
81
ff31583 @ericholscher Initial spike of teeing files out.
ericholscher authored
82 def _whitelisted(self, **kwargs):
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
83 """Modify the given ``conf.py`` file from a whitelisted user's project.
84 """
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular …
dcolish authored
85 project = self.version.project
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
86 #Open file for appending.
67639d5 @ericholscher Try and fix the whitelisting for UTF-8
ericholscher authored
87 outfile = codecs.open(project.conf_file(self.version.slug), encoding='utf-8', mode='a')
7f8393f @ericholscher Fix writing output of conf.py files.
ericholscher authored
88 outfile.write("\n")
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
89 rtd_ctx = Context({
16a194a @ericholscher Use api_versions and have it sorted correctly.
ericholscher authored
90 'versions': project.api_versions(),
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular …
dcolish authored
91 'current_version': self.version,
a251351 @dcolish add decorator to restore cwd after running build commands, use safe_w…
dcolish authored
92 'project': project,
93 'settings': settings,
94 'static_path': STATIC_DIR,
95 'template_path': TEMPLATE_DIR,
96 })
7269561 @ericholscher Support a Standard RTD Theme!
ericholscher authored
97 rtd_string = Template(RTD_CONF_ADDITIONS).render(rtd_ctx)
7f8393f @ericholscher Fix writing output of conf.py files.
ericholscher authored
98 outfile.write(rtd_string)
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
99
ff31583 @ericholscher Initial spike of teeing files out.
ericholscher authored
100 def clean(self, **kwargs):
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
101 log.info("Project whitelisted")
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
102 try:
17db270 @ericholscher The great whitelist removal!
ericholscher authored
103 self._whitelisted()
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
104 except (OSError, SiteProfileNotAvailable, ObjectDoesNotExist):
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
105 log.error("Conf file not found. Error writing to disk.", exc_info=True)
17db270 @ericholscher The great whitelist removal!
ericholscher authored
106 return ('', 'Conf file not found. Error writing to disk.', -1)
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
107
a251351 @dcolish add decorator to restore cwd after running build commands, use safe_w…
dcolish authored
108 @restoring_chdir
ff31583 @ericholscher Initial spike of teeing files out.
ericholscher authored
109 def build(self, id, **kwargs):
110 id_dir = "/tmp/"
111 id_file = "docs-build-%s" % id
112 id_path = os.path.join(id_dir, id_file)
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular …
dcolish authored
113 project = self.version.project
114 os.chdir(project.conf_dir(self.version.slug))
5cee6b0 @ericholscher Have a way to make clean builds. Fixes #101.
ericholscher authored
115 force_str = " -E " if self.force else ""
17db270 @ericholscher The great whitelist removal!
ericholscher authored
116 if project.use_virtualenv:
ff31583 @ericholscher Initial spike of teeing files out.
ericholscher authored
117 build_command = "%s %s -b html . _build/html | tee %s" % (
118 project.venv_bin( version=self.version.slug, bin='sphinx-build'),
119 force_str,
120 id_path,
121 )
e29fb7f @ericholscher Added virtualenv support and build PDFs for everyone.
ericholscher authored
122 else:
ff31583 @ericholscher Initial spike of teeing files out.
ericholscher authored
123 build_command = "sphinx-build %s -b html . _build/html | tee %s " % (force_str, id_path)
124 build_results = run(build_command, shell=True)
125 remove_results = run('rm %s' % id_path)
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
126 self._zip_html()
47e7106 @ericholscher Added the changed property to Backend classes.
ericholscher authored
127 if 'no targets are out of date.' in build_results[1]:
128 self._changed = False
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
129 return build_results
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
130
92d14b5 @ericholscher Fix zip files to make sense.
ericholscher authored
131 @restoring_chdir
ff31583 @ericholscher Initial spike of teeing files out.
ericholscher authored
132 def _zip_html(self, **kwargs):
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
133 from_path = self.version.project.full_build_path(self.version.slug)
134 from_file = os.path.join(from_path, '%s.zip' % self.version.project.slug)
135 to_path = self.version.project.checkout_path(self.version.slug)
136 to_file = os.path.join(to_path, '%s.zip' % self.version.project.slug)
137
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
138 log.info("Creating zip file from %s" % from_path)
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
139 # Create a <slug>.zip file containing all files in file_path
92d14b5 @ericholscher Fix zip files to make sense.
ericholscher authored
140 os.chdir(from_path)
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
141 archive = zipfile.ZipFile(to_file, 'w')
92d14b5 @ericholscher Fix zip files to make sense.
ericholscher authored
142 for root, subfolders, files in os.walk('.'):
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
143 for file in files:
fd06758 @ericholscher Put the files in a directory named after the project and version.
ericholscher authored
144 to_write = os.path.join(root, file)
145 archive.write(
ff31583 @ericholscher Initial spike of teeing files out.
ericholscher authored
146 filename=to_write,
fd06758 @ericholscher Put the files in a directory named after the project and version.
ericholscher authored
147 arcname=os.path.join("%s-%s" % (self.version.project.slug, self.version.slug), to_write)
148 )
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
149 archive.close()
150
151 return to_file
152
ff31583 @ericholscher Initial spike of teeing files out.
ericholscher authored
153 def move(self, **kwargs):
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular …
dcolish authored
154 project = self.version.project
155 if project.full_build_path(self.version.slug):
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
156 #Copy the html files.
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular …
dcolish authored
157 target = project.rtd_build_path(self.version.slug)
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
158 if getattr(settings, "MULTIPLE_APP_SERVERS", None):
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
159 log.info("Copying docs to remote server.")
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular …
dcolish authored
160 copy_to_app_servers(project.full_build_path(self.version.slug), target)
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
161 else:
162 if os.path.exists(target):
163 shutil.rmtree(target)
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
164 log.info("Copying docs on the local filesystem")
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular …
dcolish authored
165 shutil.copytree(project.full_build_path(self.version.slug), target)
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
166
167 #Copy the zip file.
168 to_path = os.path.join(settings.MEDIA_ROOT,
169 'htmlzip',
170 project.slug,
171 self.version.slug)
172 to_file = os.path.join(to_path, '%s.zip' % project.slug)
173 from_path = project.checkout_path(self.version.slug)
174 from_file = os.path.join(from_path, '%s.zip' % project.slug)
175 if getattr(settings, "MULTIPLE_APP_SERVERS", None):
176 copy_file_to_app_servers(from_file, to_file)
177 else:
178 if not os.path.exists(to_path):
179 os.makedirs(to_path)
180 run('mv -f %s %s' % (from_file, to_file))
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
181 else:
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
182 log.warning("Not moving docs, because the build dir is unknown.")
Something went wrong with that request. Please try again.