[damned-lies] Add preliminary support for meson build files



commit a7fd748ee732ec6b2c9eabace114dfaea1920ded
Author: Claude Paroz <claude 2xlibre net>
Date:   Tue Jun 27 22:22:49 2017 +0200

    Add preliminary support for meson build files

 stats/tests/help_mallard/meson.build |   22 ++++++++++
 stats/tests/tests.py                 |   15 ++++++-
 stats/utils.py                       |   78 +++++++++++++++++++++++++++-------
 3 files changed, 97 insertions(+), 18 deletions(-)
---
diff --git a/stats/tests/help_mallard/meson.build b/stats/tests/help_mallard/meson.build
new file mode 100644
index 0000000..e2b47fa
--- /dev/null
+++ b/stats/tests/help_mallard/meson.build
@@ -0,0 +1,22 @@
+help_media = [
+    'figures/gnome-hello.png',
+    'figures/gnome-hello-logo.png',
+]
+
+help_files = [
+    'index.page',
+    'what-is.page',
+    'legal.xml',
+]
+
+help_linguas = [
+    'es',
+    'fr',
+]
+
+gnome.yelp('gnome-hello',
+    sources: help_files,
+    media: help_media,
+    languages: help_linguas,
+    symlink_media: true,
+)
diff --git a/stats/tests/tests.py b/stats/tests/tests.py
index 4a8dfcd..02d61fd 100644
--- a/stats/tests/tests.py
+++ b/stats/tests/tests.py
@@ -544,6 +544,15 @@ class UtilsTests(TestCase):
         var_content = makefile.read_variable("HELP_FILES")
         self.assertEqual(var_content.split(), ['rnusers.xml', 'rnlookingforward.xml'])
 
+    def test_read_meson_variables(self):
+        path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "help_mallard")
+        meson_file = utils.MakefileWrapper.find_file([path], file_name='meson.build')
+        self.assertEqual(meson_file.read_variable('languages'), ['es', 'fr'])
+        self.assertEqual(
+            meson_file.read_variable('sources'),
+            ['index.page', 'what-is.page', 'legal.xml']
+        )
+
     def test_generate_doc_potfile_docbook(self):
         """
         Test Docbook-style help
@@ -551,7 +560,8 @@ class UtilsTests(TestCase):
         help_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "help_docbook")
         self.addCleanup(os.remove, os.path.join(help_path, 'C', "release-notes.pot"))
         potfile, errs, doc_format = utils.generate_doc_pot_file(help_path, 'release-notes', 'release-notes')
-        self.assertEqual(doc_format.__dict__, {'tool': 'xml2po', 'format': 'docbook'})
+        self.assertEqual(doc_format.tool, 'xml2po')
+        self.assertEqual(doc_format.format, 'docbook')
         pot_path = os.path.join(help_path, "C", "release-notes.pot")
         self.assertTrue(os.access(pot_path, os.R_OK))
         res = utils.get_fig_stats(pot_path, doc_format=doc_format)
@@ -567,7 +577,8 @@ class UtilsTests(TestCase):
         potfile, errs, doc_format = utils.generate_doc_pot_file(help_path, 'gnome-hello', 'gnome-hello')
         self.assertEqual(potfile, os.path.join(help_path, 'C', 'gnome-hello.pot'))
         self.assertEqual(errs, [])
-        self.assertEqual(doc_format.__dict__, {'tool': 'itstool', 'format': 'mallard'})
+        self.assertEqual(doc_format.tool, 'itstool')
+        self.assertEqual(doc_format.format, 'mallard')
         res = utils.get_fig_stats(potfile, doc_format=doc_format)
         self.assertEqual(len(res), 1)
         self.assertEqual(res[0]['path'], "figures/gnome-hello-logo.png")
diff --git a/stats/utils.py b/stats/utils.py
index 7fcb453..dc98afb 100644
--- a/stats/utils.py
+++ b/stats/utils.py
@@ -7,6 +7,7 @@ import shutil
 import time
 from itertools import islice
 from subprocess import Popen, PIPE
+from unittest.mock import Mock
 
 try:
     from translate.tools import pogrep, pocount
@@ -38,9 +39,10 @@ ITS_DATA_DIR = os.path.join(settings.SCRATCHDIR, 'data', 'its')
 class DocFormat:
     itstool_regex = re.compile("^msgid \"external ref=\'(?P<path>[^\']*)\' md5=\'(?P<hash>[^\']*)\'\"")
     xml2po_regex = re.compile("^msgid \"@@image: \'(?P<path>[^\']*)\'; md5=(?P<hash>[^\"]*)\"")
-    def __init__(self, is_itstool, is_mallard):
+    def __init__(self, is_itstool, is_mallard, use_meson):
         self.format = is_mallard and "mallard" or "docbook"
         self.tool = is_itstool and "itstool" or "xml2po"
+        self.use_meson = use_meson
 
     def command(self, potfile, files):
         if self.tool == "itstool":
@@ -54,7 +56,9 @@ class DocFormat:
 
     @property
     def module_var(self):
-        if self.tool == "itstool":
+        if self.use_meson:
+            return "project_id"
+        elif self.tool == "itstool":
             return "HELP_ID"
         elif self.format == "mallard":
             return "DOC_ID"
@@ -63,6 +67,8 @@ class DocFormat:
 
     @property
     def include_var(self):
+        if self.use_meson:
+            return "sources"
         if self.tool == "itstool":
             return "HELP_FILES"
         elif self.format == "mallard":
@@ -88,7 +94,7 @@ class DocFormat:
 
 
 class MakefileWrapper:
-    default_makefiles = ['Makefile.am']
+    default_makefiles = ['Makefile.am', 'meson.build']
 
     @classmethod
     def find_file(cls, vcs_paths, file_name=None):
@@ -98,7 +104,10 @@ class MakefileWrapper:
             for file_name in names:
                 file_path = os.path.join(path, file_name)
                 if os.access(file_path, os.R_OK):
-                    return MakefileWrapper(file_path)
+                    if file_name == 'meson.build':
+                        return MesonfileWrapper(file_path)
+                    else:
+                        return MakefileWrapper(file_path)
 
     def __init__(self, path):
         self.path = path
@@ -112,7 +121,7 @@ class MakefileWrapper:
             return None
         return content
 
-    def read_variable(self, variable):
+    def read_variable(self, *variables):
         if self.content is None:
             return None
         non_terminated_content = ""
@@ -130,10 +139,11 @@ class MakefileWrapper:
             else:
                 non_terminated_content = ""
                 # Search for variable
-                match = re.search('%s\s*[=,]\s*"?([^"]*)"?' % variable, line)
-                if match:
-                    found = match.group(1)
-                    break
+                for var in variables:
+                    match = re.search('%s\s*[=,]\s*"?([^"]*)"?' % var, line)
+                    if match:
+                        found = match.group(1)
+                        break
 
         # Try to expand '$(var)' variables
         if found:
@@ -145,6 +155,37 @@ class MakefileWrapper:
         return found
 
 
+class MesonfileWrapper(MakefileWrapper):
+    @cached_property
+    def content(self):
+        content = super().content
+        # Here be dragons: Try to make meson content look like Python
+        content = re.sub(r'(sources|media|languages):', r'\1=', content)
+        content = content.replace('true', 'True').replace('false', 'False')
+        return content
+
+    def read_variable(self, *variables):
+        if self.content is None:
+            return None
+        catched = {}
+
+        class VarCatcher:
+            def yelp(self, *args, **kwargs):
+                catched['project_id'] = args[0]
+                for var_name in {'sources', 'languages'}:
+                    if var_name in kwargs:
+                        catched[var_name] = kwargs[var_name]
+
+        gnome = VarCatcher()
+        try:
+            exec(self.content, {}, {'gnome': gnome, 'meson': Mock()})
+        except Exception:
+            pass
+        for var in variables:
+            if var in catched and not isinstance(catched[var], Mock):
+                return catched[var]
+
+
 def sort_object_list(lst, sort_meth):
     """ Sort an object list with sort_meth (which should return a translated string) """
     templist = [(getattr(obj_, sort_meth)().lower(), obj_) for obj_ in lst]
@@ -260,17 +301,20 @@ def generate_doc_pot_file(vcs_path, potbase, moduleid):
         )
         return "", errors, None
 
-    doc_id = makefile.read_variable("HELP_ID")
-    uses_itstool = doc_id is not None
+    doc_id = makefile.read_variable("HELP_ID", "project_id")
+    uses_itstool = doc_id is not None or isinstance(makefile, MesonfileWrapper)
     all_C_files = os.listdir(os.path.join(vcs_path, "C"))
     has_page_files = any(f.endswith('.page') for f in all_C_files)
-    doc_format = DocFormat(is_itstool=uses_itstool, is_mallard=has_page_files)
+    doc_format = DocFormat(
+        is_itstool=uses_itstool, is_mallard=has_page_files,
+        use_meson=isinstance(makefile, MesonfileWrapper)
+    )
 
     files = []
     if doc_format.format == "docbook":
         modulename = makefile.read_variable(doc_format.module_var)
         if not modulename:
-            return "", (("error", ugettext_noop("Module %s doesn’t look like gnome-doc-utils module.") % 
moduleid),), doc_format
+            modulename = moduleid
         for index_page in ("index.docbook", modulename + ".xml", moduleid + ".xml"):
             if os.access(os.path.join(vcs_path, "C", index_page), os.R_OK):
                 files.append(index_page)
@@ -286,7 +330,9 @@ def generate_doc_pot_file(vcs_path, potbase, moduleid):
 
     includes = makefile.read_variable(doc_format.include_var)
     if includes:
-        files.extend(filter(lambda x:x not in ("", "$(NULL)"), includes.split()))
+        if isinstance(includes, str):
+            includes = includes.split()
+        files.extend(filter(lambda x:x not in ("", "$(NULL)"), includes))
     elif includes is None and doc_format.format == "mallard":
         # fallback to directory listing
         files.extend([f for f in all_C_files if f.endswith(".page")])
@@ -459,11 +505,11 @@ def get_doc_linguas(module_path, po_path):
     linguas = None
     linguas_file = MakefileWrapper.find_file([po_path, module_path])
     if linguas_file:
-        linguas = linguas_file.read_variable("(?:DOC|HELP)_LINGUAS")
+        linguas = linguas_file.read_variable("DOC_LINGUAS", "HELP_LINGUAS", "languages")
     if linguas is None:
         return {'langs':None,
                 'error': ugettext_noop("Don’t know where to look for the DOC_LINGUAS variable, ask the 
module maintainer.") }
-    return {'langs': linguas.split(),
+    return {'langs': linguas.split() if isinstance(linguas, str) else linguas,
             'error': ugettext_noop("DOC_LINGUAS list doesn’t include this language.") }
 
 


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