[damned-lies] Add support for building Docbook docs



commit 95e0c9e7d377c552af85087761c5bddb5874b4af
Author: Claude Paroz <claude 2xlibre net>
Date:   Mon Sep 17 14:32:41 2018 +0200

    Add support for building Docbook docs

 stats/models.py                                    |  2 +-
 .../testmodule/help_docbook/C/release-notes.xml    |  2 +-
 stats/tests/tests.py                               |  7 ++
 vertimus/tests/tests.py                            | 79 +++++++++++++++-------
 vertimus/views.py                                  | 26 +++++--
 5 files changed, 84 insertions(+), 32 deletions(-)
---
diff --git a/stats/models.py b/stats/models.py
index dcf98cbc..ca1eb27e 100644
--- a/stats/models.py
+++ b/stats/models.py
@@ -787,7 +787,7 @@ class Domain(models.Model):
 
     def can_build_docs(self, branch):
         try:
-            return self.dtype == 'doc' and self.doc_format(branch).format == 'mallard'
+            return self.dtype == 'doc' and self.doc_format(branch)
         except utils.UndetectableDocFormat:
             return False
 
diff --git a/stats/tests/git/testmodule/help_docbook/C/release-notes.xml 
b/stats/tests/git/testmodule/help_docbook/C/release-notes.xml
index a0176273..771fa703 100644
--- a/stats/tests/git/testmodule/help_docbook/C/release-notes.xml
+++ b/stats/tests/git/testmodule/help_docbook/C/release-notes.xml
@@ -6,7 +6,7 @@
 <!ENTITY lastversion "2.30">
 ]>
 
-<article lang="en" id="index">
+<article lang="en" id="release-notes">
   <articleinfo>
      <title>GNOME &gnomeversion; Release Notes</title>
 
diff --git a/stats/tests/tests.py b/stats/tests/tests.py
index 2a930965..f078b7ef 100644
--- a/stats/tests/tests.py
+++ b/stats/tests/tests.py
@@ -451,6 +451,13 @@ class TestModuleBase(TestCase):
         cls.branch = Branch(module=cls.mod, name="master")
         cls.branch.save(update_statistics=False)
 
+    @classmethod
+    def tearDownClass(cls):
+        html_dir = Path(settings.SCRATCHDIR) / 'HTML'
+        if html_dir.exists():
+            shutil.rmtree(str(html_dir))
+        super().tearDownClass()
+
 
 class DomainTests(TestModuleBase):
     def setUp(self):
diff --git a/vertimus/tests/tests.py b/vertimus/tests/tests.py
index 5a719c23..3a919d7c 100644
--- a/vertimus/tests/tests.py
+++ b/vertimus/tests/tests.py
@@ -18,6 +18,7 @@ from people.models import Person
 from teams.models import Role
 from teams.tests import TeamsAndRolesMixin
 from stats.models import Module, Branch, Release, Category, CategoryName, Domain, Statistics
+from stats.tests.tests import TestModuleBase
 from stats.tests.utils import patch_shell_command, test_scratchdir
 from vertimus.models import (
     Action, ActionArchived, ActionCI, ActionUNDO, ActionWC, State, StateCommitted,
@@ -741,32 +742,6 @@ class VertimusTest(TeamsAndRolesMixin, TestCase):
         response = self.client.get(reverse('stats-quality-check', args=[po_stat.pk]))
         self.assertContains(response, "The po file looks good!")
 
-    @test_scratchdir
-    def test_doc_building(self):
-        dom = Domain.objects.create(
-            module=self.m, name='help', description='User Guide', dtype='doc',
-            layout='help/{lang}/{lang}.po'
-        )
-        state = StateTranslating(branch=self.b, domain=dom, language=self.l, person=self.pt)
-        state.save()
-
-        file_path = Path(__file__).parent / "gnome-hello.help.fr.po"
-        with file_path.open() as test_file:
-            action = Action.new_by_name('UT', person=self.pt, file=File(test_file))
-            action.apply_on(state, {'send_to_ml': action.send_mail_to_ml, 'comment': "Done by translator."})
-        self.assertTrue(action.can_build)
-        self.assertIsNone(action.build_url)
-        response = self.client.post(reverse('action-build-help', args=[action.pk]))
-        self.assertRedirects(
-            response, '/HTML/%d/index.html' % action.pk, fetch_redirect_response=False
-        )
-        self.assertEqual(action.build_url, '/HTML/%d/index.html' % action.pk)
-        index_file = Path(
-            settings.SCRATCHDIR, 'HTML', str(action.pk), 'index.html'
-        )
-        with index_file.open('r') as ifile:
-            self.assertIn('<h2><span class="title">À propos</span></h2>', ifile.read())
-
     def test_mysql(self):
         # Copied from test_action_undo() with minor changes
         state = StateNone(branch=self.b, domain=self.d, language=self.l)
@@ -802,3 +777,55 @@ class VertimusTest(TeamsAndRolesMixin, TestCase):
         # Here be dragons! A call to len() workaround the Django/MySQL bug!
         len(actions_db)
         self.assertIsInstance(actions_db[0], ActionUNDO)
+
+
+class DocsBuildingTests(TeamsAndRolesMixin, TestModuleBase):
+    def test_doc_building(self):
+        dom = Domain.objects.create(
+            module=self.mod, name='help', description='User Guide', dtype='doc',
+            layout='help_mallard/{lang}/{lang}.po'
+        )
+        state = StateTranslating(branch=self.branch, domain=dom, language=self.l, person=self.pt)
+        state.save()
+
+        file_path = Path(__file__).parent / "gnome-hello.help.fr.po"
+        with file_path.open() as test_file:
+            action = Action.new_by_name('UT', person=self.pt, file=File(test_file))
+            action.apply_on(state, {'send_to_ml': action.send_mail_to_ml, 'comment': "Done by translator."})
+        self.assertTrue(action.can_build)
+        self.assertIsNone(action.build_url)
+        response = self.client.post(reverse('action-build-help', args=[action.pk]))
+        self.assertRedirects(
+            response, '/HTML/%d/index.html' % action.pk, fetch_redirect_response=False
+        )
+        self.assertEqual(action.build_url, '/HTML/%d/index.html' % action.pk)
+        index_file = Path(
+            settings.SCRATCHDIR, 'HTML', str(action.pk), 'index.html'
+        )
+        with index_file.open('r') as ifile:
+            self.assertIn('<h2><span class="title">À propos</span></h2>', ifile.read())
+
+    def test_docbook_building(self):
+        dom = Domain.objects.create(
+            module=self.mod, name='help', description='User Guide', dtype='doc',
+            layout='help_docbook/{lang}/{lang}.po'
+        )
+        state = StateTranslating(branch=self.branch, domain=dom, language=self.l, person=self.pt)
+        state.save()
+
+        file_path = Path(__file__).parent / "gnome-hello.help.fr.po"
+        with file_path.open() as test_file:
+            action = Action.new_by_name('UT', person=self.pt, file=File(test_file))
+            action.apply_on(state, {'send_to_ml': action.send_mail_to_ml, 'comment': "Done by translator."})
+        self.assertTrue(action.can_build)
+        self.assertIsNone(action.build_url)
+        response = self.client.post(reverse('action-build-help', args=[action.pk]))
+        self.assertRedirects(
+            response, '/HTML/%d/index.html' % action.pk, fetch_redirect_response=False
+        )
+        self.assertEqual(action.build_url, '/HTML/%d/index.html' % action.pk)
+        index_file = Path(
+            settings.SCRATCHDIR, 'HTML', str(action.pk), 'index.html'
+        )
+        with index_file.open('r') as ifile:
+            self.assertIn('<h2><span class="title">À propos</span></h2>', ifile.read())
diff --git a/vertimus/views.py b/vertimus/views.py
index 728c0b3e..60c2c417 100644
--- a/vertimus/views.py
+++ b/vertimus/views.py
@@ -4,6 +4,7 @@ import re
 import subprocess
 import tempfile
 from pathlib import Path
+from xml.dom.minidom import parse
 
 from django.conf import settings
 from django.contrib import messages
@@ -16,7 +17,7 @@ from django.utils.translation import gettext as _
 from django.views.generic import View
 
 from stats.models import Statistics, FakeLangStatistics, Module, Branch, Domain, Language
-from stats.utils import DocFormat, check_po_quality, is_po_reduced
+from stats.utils import DocFormat, UndetectableDocFormat, check_po_quality, is_po_reduced
 from vertimus.models import State, Action, ActionArchived, SendMailFailed
 from vertimus.forms import ActionForm
 
@@ -296,14 +297,14 @@ class BuildTranslatedDocsView(PoFileActionBase):
             raise Http404('No target po file for this action')
 
         html_dir = Path(settings.SCRATCHDIR, 'HTML', str(self.kwargs['action_pk']))
-        if (html_dir / 'index.html').exists():
+        if html_dir.exists():
             # If the build already ran, redirect to the static results
             return HttpResponseRedirect(self.action.build_url)
 
         state = self.action.state_db
         try:
             doc_format = DocFormat(state.domain, state.branch)
-        except Exception as err:
+        except UndetectableDocFormat as err:
             messages.error(request, err)
             return HttpResponseRedirect(state.get_absolute_url())
         build_error = _('Build failed (%(program)s): %(err)s')
@@ -333,15 +334,32 @@ class BuildTranslatedDocsView(PoFileActionBase):
             # Now build the html version
             if not html_dir.exists():
                 html_dir.mkdir(parents=True)
+            if doc_format.format == 'mallard':
+                # With mallard, specifying the directory is enough.
+                build_ref = [str(build_dir)]
+            else:
+                build_ref = [os.path.join(build_dir, s.name) for s in sources]
             cmd = [
                 'yelp-build', 'html', '-o', str(html_dir),
                 '-p', str(doc_format.vcs_path / 'C'),
-                str(build_dir)
+                *build_ref
             ]
             result = subprocess.run(cmd, cwd=str(build_dir), stderr=subprocess.PIPE)
             if result.returncode != 0:
                 messages.error(request, build_error % {
                     'program': 'yelp-build', 'err': result.stderr.decode()
                 })
+                shutil.rmtree(str(html_dir))
                 return HttpResponseRedirect(state.get_absolute_url())
+
+            if not (html_dir / 'index.html').exists():
+                # Create an index.html symlink to the base html doc if needed
+                try:
+                    doc = parse(build_ref[0])
+                    base_name = doc.getElementsByTagName("article")[0].attributes.get('id').value
+                except (AttributeError, IndexError):
+                    pass
+                else:
+                    html_name = '%s.html' % base_name
+                    (html_dir / 'index.html').symlink_to(html_dir / html_name)
         return HttpResponseRedirect(self.action.build_url)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]