Merge lp:~dholbach/developer-ubuntu-com/generalise-external-docs-branches into lp:~developer-ubuntu-com-dev/developer-ubuntu-com/snappy-docs-import
- generalise-external-docs-branches
- Merge into snappy-docs-import
Proposed by
Daniel Holbach
Status: | Merged |
---|---|
Merged at revision: | 140 |
Proposed branch: | lp:~dholbach/developer-ubuntu-com/generalise-external-docs-branches |
Merge into: | lp:~developer-ubuntu-com-dev/developer-ubuntu-com/snappy-docs-import |
Diff against target: |
434 lines (+151/-106) 5 files modified
developer_portal/admin.py (+5/-5) developer_portal/management/commands/import-snappy-branches.py (+114/-82) developer_portal/migrations/0003_add_external_docs_branches.py (+13/-13) developer_portal/models.py (+8/-5) locale/developer_portal.pot (+11/-1) |
To merge this branch: | bzr merge lp:~dholbach/developer-ubuntu-com/generalise-external-docs-branches |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Michael Hall (community) | Approve | ||
Review via email: mp+266383@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 150. By Daniel Holbach
-
move is_snappy_branch for replacing links earlier in the code
- 151. By Daniel Holbach
-
get rid of is_snappy_branch distinction, instead derive SnappyLocalBranch and SnappyMarkdownFile for special handling
- 152. By Daniel Holbach
-
fix overview page title for non-current snappy docs branches
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'developer_portal/admin.py' |
2 | --- developer_portal/admin.py 2015-07-27 13:56:37 +0000 |
3 | +++ developer_portal/admin.py 2015-07-31 12:58:39 +0000 |
4 | @@ -3,7 +3,7 @@ |
5 | from reversion.models import Revision, Version |
6 | from reversion.admin import VersionAdmin |
7 | |
8 | -from .models import SnappyDocsBranch |
9 | +from .models import ExternalDocsBranch |
10 | from django.core.management import call_command |
11 | |
12 | __all__ = ( |
13 | @@ -33,9 +33,9 @@ |
14 | admin.site.register(Version, VersionAdmin) |
15 | |
16 | |
17 | -class SnappyDocsBranchAdmin(admin.ModelAdmin): |
18 | - list_display = ('branch_origin', 'path_alias') |
19 | - list_filter = ('branch_origin', 'path_alias') |
20 | +class ExternalDocsBranchAdmin(admin.ModelAdmin): |
21 | + list_display = ('lp_origin', 'docs_namespace') |
22 | + list_filter = ('lp_origin', 'docs_namespace') |
23 | actions = [manual_snappy_doc_import] |
24 | |
25 | -admin.site.register(SnappyDocsBranch, SnappyDocsBranchAdmin) |
26 | +admin.site.register(ExternalDocsBranch, ExternalDocsBranchAdmin) |
27 | |
28 | === modified file 'developer_portal/management/commands/import-snappy-branches.py' |
29 | --- developer_portal/management/commands/import-snappy-branches.py 2015-07-27 13:56:37 +0000 |
30 | +++ developer_portal/management/commands/import-snappy-branches.py 2015-07-31 12:58:39 +0000 |
31 | @@ -1,5 +1,8 @@ |
32 | from django.core.management.base import BaseCommand |
33 | |
34 | +from cms.api import create_page, add_plugin |
35 | +from cms.models import Title |
36 | + |
37 | from bs4 import BeautifulSoup |
38 | import codecs |
39 | import glob |
40 | @@ -11,14 +14,14 @@ |
41 | import subprocess |
42 | import tempfile |
43 | |
44 | -from developer_portal.models import SnappyDocsBranch |
45 | +from developer_portal.models import ExternalDocsBranch |
46 | |
47 | +DOCS_DIRNAME = 'docs' |
48 | RELEASE_PAGES = {} |
49 | |
50 | |
51 | -class MarkdownFile(): |
52 | +class MarkdownFile: |
53 | html = None |
54 | - cms_path = '' |
55 | |
56 | def __init__(self, fn): |
57 | self.fn = fn |
58 | @@ -34,7 +37,8 @@ |
59 | self._use_developer_site_style() |
60 | |
61 | def _get_release_alias(self): |
62 | - alias = re.findall(r'/tmp/tmp\S+?/(\S+?)/docs/\S+?', self.fn) |
63 | + alias = re.findall(r'/tmp/tmp\S+?/(\S+?)/%s/\S+?' % DOCS_DIRNAME, |
64 | + self.fn) |
65 | return alias[0] |
66 | |
67 | def _read_title(self): |
68 | @@ -52,20 +56,8 @@ |
69 | flags=re.MULTILINE) |
70 | |
71 | def _use_developer_site_style(self): |
72 | - # Make sure the reader knows which documentation she is browsing |
73 | - if self.release_alias != "current": |
74 | - begin = (u"<div class=\"row no-border\">\n" |
75 | - "<div class=\"box pull-three three-col\">" |
76 | - "<p>You are browsing the Snappy <code>%s</code> " |
77 | - "documentation.</p>" |
78 | - "<p><a href=\"/snappy/guides/current/%s\">" |
79 | - "Back to the latest stable release ›" |
80 | - "</a></p></div>\n" |
81 | - "<div class=\"eight-col\">\n") % (self.release_alias, |
82 | - self.slug, ) |
83 | - else: |
84 | - begin = (u"<div class=\"row no-border\">" |
85 | - "\n<div class=\"eight-col\">\n") |
86 | + begin = (u"<div class=\"row no-border\">" |
87 | + "\n<div class=\"eight-col\">\n") |
88 | end = u"</div>\n</div>" |
89 | self.html = begin + self.html + end |
90 | self.html = self.html.replace( |
91 | @@ -86,8 +78,37 @@ |
92 | '''Publishes pages in their branch alias namespace.''' |
93 | from cms.api import create_page, add_plugin |
94 | |
95 | - page_title = self.title |
96 | - |
97 | + page = create_page( |
98 | + self.title, "default.html", "en", slug=self.slug, |
99 | + menu_title=self.title, parent=RELEASE_PAGES[self.release_alias], |
100 | + in_navigation=True, position="last-child") |
101 | + placeholder = page.placeholders.get() |
102 | + add_plugin(placeholder, 'RawHtmlPlugin', 'en', body=self.html) |
103 | + page.publish('en') |
104 | + |
105 | + |
106 | +class SnappyMarkdownFile(MarkdownFile): |
107 | + def __init__(self, fn): |
108 | + MarkdownFile.__init__(self, fn) |
109 | + self._make_snappy_mods() |
110 | + |
111 | + def _make_snappy_mods(self): |
112 | + # Make sure the reader knows which documentation she is browsing |
113 | + if self.release_alias != 'current': |
114 | + before = (u"<div class=\"row no-border\">" |
115 | + "\n<div class=\"eight-col\">\n") |
116 | + after = (u"<div class=\"row no-border\">\n" |
117 | + "<div class=\"box pull-three three-col\">" |
118 | + "<p>You are browsing the Snappy <code>%s</code> " |
119 | + "documentation.</p>" |
120 | + "<p><a href=\"/snappy/guides/current/%s\">" |
121 | + "Back to the latest stable release ›" |
122 | + "</a></p></div>\n" |
123 | + "<div class=\"eight-col\">\n") % (self.release_alias, |
124 | + self.slug, ) |
125 | + self.html.replace(before, after) |
126 | + |
127 | + def publish(self): |
128 | if self.release_alias == "current": |
129 | # Add a guides/<page> redirect to guides/current/<page> |
130 | page = create_page( |
131 | @@ -97,15 +118,8 @@ |
132 | redirect="/snappy/guides/current/%s" % (self.slug)) |
133 | page.publish('en') |
134 | else: |
135 | - page_title += " (%s)" % (self.release_alias,) |
136 | - |
137 | - page = create_page( |
138 | - page_title, "default.html", "en", slug=self.slug, |
139 | - menu_title=self.title, parent=RELEASE_PAGES[self.release_alias], |
140 | - in_navigation=True, position="last-child") |
141 | - placeholder = page.placeholders.get() |
142 | - add_plugin(placeholder, 'RawHtmlPlugin', 'en', body=self.html) |
143 | - page.publish('en') |
144 | + self.title += " (%s)" % (self.release_alias,) |
145 | + MarkdownFile.publish(self) |
146 | |
147 | |
148 | def slugify(filename): |
149 | @@ -117,24 +131,70 @@ |
150 | 'bzr', 'checkout', '--lightweight', origin, alias]) |
151 | |
152 | |
153 | -class LocalBranch(): |
154 | +class LocalBranch: |
155 | titles = {} |
156 | |
157 | - def __init__(self, dirname): |
158 | + def __init__(self, dirname, external_branch): |
159 | self.dirname = dirname |
160 | - self.docs_path = os.path.join(self.dirname, 'docs') |
161 | + self.docs_path = os.path.join(self.dirname, DOCS_DIRNAME) |
162 | self.doc_fns = glob.glob(self.docs_path+'/*.md') |
163 | self.md_files = [] |
164 | + self.external_branch = external_branch |
165 | + self.docs_namespace = self.external_branch.docs_namespace |
166 | + self.release_alias = os.path.basename(self.docs_namespace) |
167 | + self.overview_page_title = self.release_alias.title() |
168 | + self.markdown_class = MarkdownFile |
169 | |
170 | def import_markdown(self): |
171 | for doc_fn in self.doc_fns: |
172 | - md_file = MarkdownFile(doc_fn) |
173 | + md_file = self.markdown_class(doc_fn) |
174 | self.md_files += [md_file] |
175 | self.titles[md_file.fn] = md_file.title |
176 | + |
177 | + def publish(self): |
178 | + for md_file in self.md_files: |
179 | + md_file.publish() |
180 | + |
181 | + def refresh_landing_page(self): |
182 | + '''Creates a branch page at snappy/guides/<branch alias>.''' |
183 | + |
184 | + guides_page = Title.objects.filter( |
185 | + path="snappy/guides", published=True, |
186 | + language="en", publisher_is_draft=True)[0] |
187 | + RELEASE_PAGES['guides_page'] = guides_page.page |
188 | + |
189 | + if self.docs_namespace == "current": |
190 | + redirect = "/snappy/guides" |
191 | + else: |
192 | + redirect = None |
193 | + new_release_page = create_page( |
194 | + self.overview_page_title, "default.html", "en", |
195 | + slug=self.docs_namespace, parent=RELEASE_PAGES['guides_page'], |
196 | + in_navigation=False, position="last-child", redirect=redirect) |
197 | + placeholder = new_release_page.placeholders.get() |
198 | + landing = (u"<div class=\"row\"><div class=\"eight-col\">\n" |
199 | + "<p>This section contains documentation for the " |
200 | + "<code>%s</code> Snappy branch.</p>" |
201 | + "<p>Auto-imported from <a " |
202 | + "href=\"https://code.launchpad.net/snappy\">%s</a>.</p>\n" |
203 | + "</div></div>") % (self.docs_namespace, |
204 | + self.external_branch.lp_origin) |
205 | + add_plugin(placeholder, 'RawHtmlPlugin', 'en', body=landing) |
206 | + new_release_page.publish('en') |
207 | + RELEASE_PAGES[self.release_alias] = new_release_page |
208 | + |
209 | +class SnappyLocalBranch(LocalBranch): |
210 | + def __init__(self, dirname, external_branch): |
211 | + LocalBranch.__init__(self, dirname, external_branch) |
212 | + self.markdown_class = SnappyMarkdownFile |
213 | + self.overview_page_title = 'Snappy' |
214 | + if self.release_alias != 'current': |
215 | + self.overview_page_title += ' (%s)' % self.release_alias |
216 | + |
217 | + def import_markdown(self): |
218 | + LocalBranch.import_markdown(self) |
219 | for md_file in self.md_files: |
220 | md_file.replace_links(self.titles) |
221 | - md_file.publish() |
222 | - |
223 | |
224 | def remove_old_pages(selection): |
225 | # FIXME: |
226 | @@ -151,7 +211,7 @@ |
227 | |
228 | pages_to_remove = [] |
229 | aliases = "|".join( |
230 | - SnappyDocsBranch.objects.values_list('path_alias', flat=True)) |
231 | + ExternalDocsBranch.objects.values_list('docs_namespace', flat=True)) |
232 | if selection == "current": |
233 | # Select all pages that are not in other aliases paths, this allows |
234 | # removing existing redirections to current and current itself |
235 | @@ -168,59 +228,31 @@ |
236 | Page.objects.filter(id__in=pages_to_remove, created_by="script").delete() |
237 | |
238 | |
239 | -def refresh_landing_page(release_alias, lp_origin): |
240 | - '''Creates a branch page at snappy/guides/<branch alias>.''' |
241 | - from cms.api import create_page, add_plugin |
242 | - from cms.models import Title |
243 | - |
244 | - guides_page = Title.objects.filter( |
245 | - path="snappy/guides", published=True, |
246 | - language="en", publisher_is_draft=True)[0] |
247 | - RELEASE_PAGES['guides_page'] = guides_page.page |
248 | - |
249 | - if release_alias == "current": |
250 | - redirect = "/snappy/guides" |
251 | - else: |
252 | - redirect = None |
253 | - new_release_page = create_page( |
254 | - release_alias, "default.html", "en", slug=release_alias, |
255 | - parent=RELEASE_PAGES['guides_page'], in_navigation=False, |
256 | - position="last-child", redirect=redirect) |
257 | - placeholder = new_release_page.placeholders.get() |
258 | - landing = (u"<div class=\"row\"><div class=\"eight-col\">\n" |
259 | - "<p>This section contains documentation for the " |
260 | - "<code>%s</code> Snappy branch.</p>" |
261 | - "<p>Auto-imported from " |
262 | - "<a href=\"https://code.launchpad.net/snappy\">%s</a>.</p>\n" |
263 | - "</div></div>") % (release_alias, lp_origin) |
264 | - add_plugin(placeholder, 'RawHtmlPlugin', 'en', body=landing) |
265 | - new_release_page.publish('en') |
266 | - RELEASE_PAGES[release_alias] = new_release_page |
267 | - |
268 | - |
269 | def import_branches(selection): |
270 | - if not SnappyDocsBranch.objects.count(): |
271 | - logging.error('No Snappy branches registered in the ' |
272 | - 'SnappyDocsBranch table yet.') |
273 | + if not ExternalDocsBranch.objects.count(): |
274 | + logging.error('No branches registered in the ' |
275 | + 'ExternalDocsBranch table yet.') |
276 | return |
277 | # FIXME: Do the removal part last. Else we might end up in situations |
278 | # where some code breaks and we stay in a state without articles. |
279 | remove_old_pages(selection) |
280 | tempdir = tempfile.mkdtemp() |
281 | - pwd = os.getcwd() |
282 | - os.chdir(tempdir) |
283 | - for branch in SnappyDocsBranch.objects.filter(path_alias__regex=selection): |
284 | - if get_branch_from_lp(branch.branch_origin, branch.path_alias) != 0: |
285 | + for branch in ExternalDocsBranch.objects.filter( |
286 | + docs_namespace__regex=selection): |
287 | + checkout_location = os.path.join( |
288 | + tempdir, os.path.basename(branch.docs_namespace)) |
289 | + if get_branch_from_lp(branch.lp_origin, checkout_location) != 0: |
290 | logging.error( |
291 | - 'Could not check out branch "%s".' % branch.branch_origin) |
292 | - shutil.rmtree(os.path.join(tempdir, branch.path_alias)) |
293 | + 'Could not check out branch "%s".' % branch.lp_origin) |
294 | + shutil.rmtree(checkout_location) |
295 | break |
296 | - refresh_landing_page(branch.path_alias, branch.branch_origin) |
297 | - os.chdir(pwd) |
298 | - for local_branch in [a for a in glob.glob(tempdir+'/*') |
299 | - if os.path.isdir(a)]: |
300 | - branch = LocalBranch(local_branch) |
301 | - branch.import_markdown() |
302 | + if branch.lp_origin.startswith('lp:snappy'): |
303 | + local_branch = SnappyLocalBranch(checkout_location, branch) |
304 | + else: |
305 | + local_branch = LocalBranch(checkout_location, branch) |
306 | + local_branch.refresh_landing_page() |
307 | + local_branch.import_markdown() |
308 | + local_branch.publish() |
309 | shutil.rmtree(tempdir) |
310 | |
311 | |
312 | @@ -229,7 +261,7 @@ |
313 | |
314 | def handle(*args, **options): |
315 | logging.basicConfig( |
316 | - level=logging.DEBUG, |
317 | + level=logging.ERROR, |
318 | format='%(asctime)s %(levelname)-8s %(message)s', |
319 | datefmt='%F %T') |
320 | if len(args) < 2 or args[1] == "all": |
321 | |
322 | === renamed file 'developer_portal/migrations/0003_add_snappy_docs_branches.py' => 'developer_portal/migrations/0003_add_external_docs_branches.py' |
323 | --- developer_portal/migrations/0003_add_snappy_docs_branches.py 2015-07-08 12:35:57 +0000 |
324 | +++ developer_portal/migrations/0003_add_external_docs_branches.py 2015-07-31 12:58:39 +0000 |
325 | @@ -8,18 +8,18 @@ |
326 | class Migration(SchemaMigration): |
327 | |
328 | def forwards(self, orm): |
329 | - # Adding model 'SnappyDocsBranch' |
330 | - db.create_table(u'developer_portal_snappydocsbranch', ( |
331 | + # Adding model 'ExternalDocsBranch' |
332 | + db.create_table(u'developer_portal_externaldocsbranch', ( |
333 | (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), |
334 | - ('branch_origin', self.gf('django.db.models.fields.CharField')(max_length=200)), |
335 | - ('path_alias', self.gf('django.db.models.fields.CharField')(max_length=20)), |
336 | + ('lp_origin', self.gf('django.db.models.fields.CharField')(max_length=200)), |
337 | + ('docs_namespace', self.gf('django.db.models.fields.CharField')(max_length=120)), |
338 | )) |
339 | - db.send_create_signal(u'developer_portal', ['SnappyDocsBranch']) |
340 | + db.send_create_signal(u'developer_portal', ['ExternalDocsBranch']) |
341 | |
342 | |
343 | def backwards(self, orm): |
344 | - # Deleting model 'SnappyDocsBranch' |
345 | - db.delete_table(u'developer_portal_snappydocsbranch') |
346 | + # Deleting model 'ExternalDocsBranch' |
347 | + db.delete_table(u'developer_portal_externaldocsbranch') |
348 | |
349 | |
350 | models = { |
351 | @@ -44,16 +44,16 @@ |
352 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
353 | 'slot': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}) |
354 | }, |
355 | + u'developer_portal.externaldocsbranch': { |
356 | + 'Meta': {'object_name': 'ExternalDocsBranch'}, |
357 | + 'docs_namespace': ('django.db.models.fields.CharField', [], {'max_length': '120'}), |
358 | + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
359 | + 'lp_origin': ('django.db.models.fields.CharField', [], {'max_length': '200'}) |
360 | + }, |
361 | u'developer_portal.rawhtml': { |
362 | 'Meta': {'object_name': 'RawHtml'}, |
363 | 'body': ('django.db.models.fields.TextField', [], {}), |
364 | u'cmsplugin_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['cms.CMSPlugin']", 'unique': 'True', 'primary_key': 'True'}) |
365 | - }, |
366 | - u'developer_portal.snappydocsbranch': { |
367 | - 'Meta': {'object_name': 'SnappyDocsBranch'}, |
368 | - 'branch_origin': ('django.db.models.fields.CharField', [], {'max_length': '200'}), |
369 | - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), |
370 | - 'path_alias': ('django.db.models.fields.CharField', [], {'max_length': '20'}) |
371 | } |
372 | } |
373 | |
374 | |
375 | === modified file 'developer_portal/models.py' |
376 | --- developer_portal/models.py 2015-07-08 12:35:51 +0000 |
377 | +++ developer_portal/models.py 2015-07-31 12:58:39 +0000 |
378 | @@ -5,8 +5,9 @@ |
379 | from djangocms_text_ckeditor.html import extract_images |
380 | from djangocms_text_ckeditor.models import AbstractText |
381 | |
382 | + |
383 | class RawHtml(AbstractText): |
384 | - |
385 | + |
386 | class Meta: |
387 | abstract = False |
388 | |
389 | @@ -17,9 +18,11 @@ |
390 | AbstractText.save(self, *args, **kwargs) |
391 | |
392 | |
393 | -class SnappyDocsBranch(models.Model): |
394 | - branch_origin = models.CharField(max_length=200, |
395 | +class ExternalDocsBranch(models.Model): |
396 | + lp_origin = models.CharField( |
397 | + max_length=200, |
398 | help_text=_('Launchpad branch location, ie: lp:snappy/15.04')) |
399 | - path_alias = models.CharField(max_length=20, |
400 | + docs_namespace = models.CharField( |
401 | + max_length=120, |
402 | help_text=_('Path alias we want to use for the docs, ' |
403 | - 'ie "15.04" or "latest", etc.')) |
404 | + 'ie "snappy/guides/15.04" or "snappy/guides/latest", etc.')) |
405 | |
406 | === modified file 'locale/developer_portal.pot' |
407 | --- locale/developer_portal.pot 2015-05-11 20:00:59 +0000 |
408 | +++ locale/developer_portal.pot 2015-07-31 12:58:39 +0000 |
409 | @@ -8,7 +8,7 @@ |
410 | msgstr "" |
411 | "Project-Id-Version: PACKAGE VERSION\n" |
412 | "Report-Msgid-Bugs-To: \n" |
413 | -"POT-Creation-Date: 2015-04-24 09:17+0000\n" |
414 | +"POT-Creation-Date: 2015-07-27 14:41+0000\n" |
415 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
416 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
417 | "Language-Team: LANGUAGE <LL@li.org>\n" |
418 | @@ -21,6 +21,16 @@ |
419 | msgid "Raw HTML" |
420 | msgstr "" |
421 | |
422 | +#: developer_portal/models.py:24 |
423 | +msgid "Launchpad branch location, ie: lp:snappy/15.04" |
424 | +msgstr "" |
425 | + |
426 | +#: developer_portal/models.py:27 |
427 | +msgid "" |
428 | +"Path alias we want to use for the docs, ie \"snappy/guides/15.04\" or " |
429 | +"\"snappy/guides/latest\", etc." |
430 | +msgstr "" |
431 | + |
432 | #: developer_portal/settings.py:187 developer_portal/settings.py:195 |
433 | msgid "English" |
434 | msgstr "" |
The subclassing makes this much easier to follow and maintain, good work