Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 176 lines (155 sloc) 6.518 kb
3764bb8 @ericholscher No more 'make html' for html building. This makes the code much simpler,...
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_writ...
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 simpler,...
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_writ...
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
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular dep...
dcolish authored
82 def _whitelisted(self):
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 dep...
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 dep...
dcolish authored
91 'current_version': self.version,
a251351 @dcolish add decorator to restore cwd after running build commands, use safe_writ...
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
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular dep...
dcolish authored
100 def clean(self):
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_writ...
dcolish authored
108 @restoring_chdir
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular dep...
dcolish authored
109 def build(self):
110 project = self.version.project
111 os.chdir(project.conf_dir(self.version.slug))
5cee6b0 @ericholscher Have a way to make clean builds. Fixes #101.
ericholscher authored
112 force_str = " -E " if self.force else ""
17db270 @ericholscher The great whitelist removal!
ericholscher authored
113 if project.use_virtualenv:
5cee6b0 @ericholscher Have a way to make clean builds. Fixes #101.
ericholscher authored
114 build_command = '%s %s -b html . _build/html' % (project.venv_bin(
115 version=self.version.slug, bin='sphinx-build'), force_str)
e29fb7f @ericholscher Added virtualenv support and build PDFs for everyone.
ericholscher authored
116 else:
5cee6b0 @ericholscher Have a way to make clean builds. Fixes #101.
ericholscher authored
117 build_command = "sphinx-build %s -b html . _build/html" % force_str
3764bb8 @ericholscher No more 'make html' for html building. This makes the code much simpler,...
ericholscher authored
118 build_results = run(build_command)
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
119 self._zip_html()
47e7106 @ericholscher Added the changed property to Backend classes.
ericholscher authored
120 if 'no targets are out of date.' in build_results[1]:
121 self._changed = False
2998430 @ericholscher Initial buildout of the doc_builder API.
ericholscher authored
122 return build_results
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
123
92d14b5 @ericholscher Fix zip files to make sense.
ericholscher authored
124 @restoring_chdir
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
125 def _zip_html(self):
126 from_path = self.version.project.full_build_path(self.version.slug)
127 from_file = os.path.join(from_path, '%s.zip' % self.version.project.slug)
128 to_path = self.version.project.checkout_path(self.version.slug)
129 to_file = os.path.join(to_path, '%s.zip' % self.version.project.slug)
130
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
131 log.info("Creating zip file from %s" % from_path)
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
132 # Create a <slug>.zip file containing all files in file_path
92d14b5 @ericholscher Fix zip files to make sense.
ericholscher authored
133 os.chdir(from_path)
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
134 archive = zipfile.ZipFile(to_file, 'w')
92d14b5 @ericholscher Fix zip files to make sense.
ericholscher authored
135 for root, subfolders, files in os.walk('.'):
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
136 for file in files:
fd06758 @ericholscher Put the files in a directory named after the project and version.
ericholscher authored
137 to_write = os.path.join(root, file)
138 archive.write(
139 filename=to_write,
140 arcname=os.path.join("%s-%s" % (self.version.project.slug, self.version.slug), to_write)
141 )
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
142 archive.close()
143
144 return to_file
145
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular dep...
dcolish authored
146 def move(self):
147 project = self.version.project
148 if project.full_build_path(self.version.slug):
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
149 #Copy the html files.
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular dep...
dcolish authored
150 target = project.rtd_build_path(self.version.slug)
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
151 if getattr(settings, "MULTIPLE_APP_SERVERS", None):
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
152 log.info("Copying docs to remote server.")
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular dep...
dcolish authored
153 copy_to_app_servers(project.full_build_path(self.version.slug), target)
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
154 else:
155 if os.path.exists(target):
156 shutil.rmtree(target)
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
157 log.info("Copying docs on the local filesystem")
91c868f @dcolish change how builders are discovered, add core.utils to avoid circular dep...
dcolish authored
158 shutil.copytree(project.full_build_path(self.version.slug), target)
53ac580 @ericholscher Add zipped html to the things that we build.
ericholscher authored
159
160 #Copy the zip file.
161 to_path = os.path.join(settings.MEDIA_ROOT,
162 'htmlzip',
163 project.slug,
164 self.version.slug)
165 to_file = os.path.join(to_path, '%s.zip' % project.slug)
166 from_path = project.checkout_path(self.version.slug)
167 from_file = os.path.join(from_path, '%s.zip' % project.slug)
168 if getattr(settings, "MULTIPLE_APP_SERVERS", None):
169 copy_file_to_app_servers(from_file, to_file)
170 else:
171 if not os.path.exists(to_path):
172 os.makedirs(to_path)
173 run('mv -f %s %s' % (from_file, to_file))
8cf716a @ericholscher Refactor moving of docs into Builder backends.
ericholscher authored
174 else:
a50f152 @Nagyman Mass conversion of print statements to logging calls
Nagyman authored
175 log.warning("Not moving docs, because the build dir is unknown.")
Something went wrong with that request. Please try again.