Merge lp:~dholbach/developer-ubuntu-com/generalise-external-docs-branches into lp:~developer-ubuntu-com-dev/developer-ubuntu-com/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
Reviewer Review Type Date Requested Status
Michael Hall (community) Approve
Review via email: mp+266383@code.launchpad.net
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

Revision history for this message
Michael Hall (mhall119) wrote :

The subclassing makes this much easier to follow and maintain, good work

review: Approve

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 &rsaquo;"
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 &rsaquo;"
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 ""

Subscribers

People subscribed via source and target branches