[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [54809] trunk/blender/release/scripts/ modules: Big i18n tools update, I/II.

Bastien Montagne montagne29 at wanadoo.fr
Sun Feb 24 09:50:56 CET 2013


Revision: 54809
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=54809
Author:   mont29
Date:     2013-02-24 08:50:55 +0000 (Sun, 24 Feb 2013)
Log Message:
-----------
Big i18n tools update, I/II.

Notes:
* Everything is still a bit raw and sometimes hackish.
* Not every feature implemented yet.
* A bunch of cleanup is still needed.
* Doc needs to be updated too!

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/bl_i18n_utils/settings.py
    trunk/blender/release/scripts/modules/bl_i18n_utils/spell_check_utils.py
    trunk/blender/release/scripts/modules/bl_i18n_utils/utils.py
    trunk/blender/release/scripts/modules/bpy/utils.py

Added Paths:
-----------
    trunk/blender/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py
    trunk/blender/release/scripts/modules/bl_i18n_utils/languages_menu_utils.py
    trunk/blender/release/scripts/modules/bl_i18n_utils/rtl_utils.py

Removed Paths:
-------------
    trunk/blender/release/scripts/modules/bl_i18n_utils/bl_process_msg.py
    trunk/blender/release/scripts/modules/bl_i18n_utils/rtl_preprocess.py
    trunk/blender/release/scripts/modules/bl_i18n_utils/update_languages_menu.py

Copied: trunk/blender/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py (from rev 54315, trunk/blender/release/scripts/modules/bl_i18n_utils/bl_process_msg.py)
===================================================================
--- trunk/blender/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py	                        (rev 0)
+++ trunk/blender/release/scripts/modules/bl_i18n_utils/bl_extract_messages.py	2013-02-24 08:50:55 UTC (rev 54809)
@@ -0,0 +1,891 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+# <pep8 compliant>
+
+# Populate a template file (POT format currently) from Blender RNA/py/C data.
+# XXX: This script is meant to be used from inside Blender!
+#      You should not directly use this script, rather use update_msg.py!
+
+import collections
+import copy
+import datetime
+import os
+import re
+import sys
+
+# XXX Relative import does not work here when used from Blender...
+from bl_i18n_utils import settings as i18n_settings, utils
+
+import bpy
+
+##### Utils #####
+
+# check for strings like "+%f°"
+ignore_reg = re.compile(r"^(?:[-*.()/\\+%°0-9]|%d|%f|%s|%r|\s)*$")
+filter_message = ignore_reg.match
+
+
+def init_spell_check(settings, lang="en_US"):
+    try:
+        from bl_i18n_utils import spell_check_utils
+        return spell_check_utils.SpellChecker(settings, lang)
+    except Exception as e:
+        print("Failed to import spell_check_utils ({})".format(str(e)))
+        return None
+
+
+def _gen_check_ctxt(settings):
+    return {
+        "multi_rnatip": set(),
+        "multi_lines": set(),
+        "py_in_rna": set(),
+        "not_capitalized": set(),
+        "end_point": set(),
+        "undoc_ops": set(),
+        "spell_checker": init_spell_check(settings),
+        "spell_errors": {},
+    }
+
+
+def _gen_reports(check_ctxt):
+    return {
+        "check_ctxt": check_ctxt,
+        "rna_structs": [],
+        "rna_structs_skipped": [],
+        "rna_props": [],
+        "rna_props_skipped": [],
+        "py_messages": [],
+        "py_messages_skipped": [],
+        "src_messages": [],
+        "src_messages_skipped": [],
+        "messages_skipped": set(),
+    }
+
+
+def check(check_ctxt, msgs, key, msgsrc, settings):
+    """
+    Performs a set of checks over the given key (context, message)...
+    """
+    if check_ctxt is None:
+        return
+    multi_rnatip = check_ctxt.get("multi_rnatip")
+    multi_lines = check_ctxt.get("multi_lines")
+    py_in_rna = check_ctxt.get("py_in_rna")
+    not_capitalized = check_ctxt.get("not_capitalized")
+    end_point = check_ctxt.get("end_point")
+    undoc_ops = check_ctxt.get("undoc_ops")
+    spell_checker = check_ctxt.get("spell_checker")
+    spell_errors = check_ctxt.get("spell_errors")
+
+    if multi_rnatip is not None:
+        if key in msgs and key not in multi_rnatip:
+            multi_rnatip.add(key)
+    if multi_lines is not None:
+        if '\n' in key[1]:
+            multi_lines.add(key)
+    if py_in_rna is not None:
+        if key in py_in_rna[1]:
+            py_in_rna[0].add(key)
+    if not_capitalized is not None:
+        if(key[1] not in settings.WARN_MSGID_NOT_CAPITALIZED_ALLOWED and
+           key[1][0].isalpha() and not key[1][0].isupper()):
+            not_capitalized.add(key)
+    if end_point is not None:
+        if (key[1].strip().endswith('.') and not key[1].strip().endswith('...') and
+            key[1] not in settings.WARN_MSGID_END_POINT_ALLOWED):
+            end_point.add(key)
+    if undoc_ops is not None:
+        if key[1] == settings.UNDOC_OPS_STR:
+            undoc_ops.add(key)
+    if spell_checker is not None and spell_errors is not None:
+        err = spell_checker.check(key[1])
+        if err:
+            spell_errors[key] = err
+
+
+def print_info(reports, pot):
+    def _print(*args, **kwargs):
+        kwargs["file"] = sys.stderr
+        print(*args, **kwargs)
+
+    pot.update_info()
+
+    _print("{} RNA structs were processed (among which {} were skipped), containing {} RNA properties "
+           "(among which {} were skipped).".format(len(reports["rna_structs"]), len(reports["rna_structs_skipped"]),
+                                                   len(reports["rna_props"]), len(reports["rna_props_skipped"])))
+    _print("{} messages were extracted from Python UI code (among which {} were skipped), and {} from C source code "
+           "(among which {} were skipped).".format(len(reports["py_messages"]), len(reports["py_messages_skipped"]),
+                                                   len(reports["src_messages"]), len(reports["src_messages_skipped"])))
+    _print("{} messages were rejected.".format(len(reports["messages_skipped"])))
+    _print("\n")
+    _print("Current POT stats:")
+    pot.print_stats(prefix="\t", output=_print)
+    _print("\n")
+
+    check_ctxt = reports["check_ctxt"]
+    if check_ctxt is None:
+        return
+    multi_rnatip = check_ctxt.get("multi_rnatip")
+    multi_lines = check_ctxt.get("multi_lines")
+    py_in_rna = check_ctxt.get("py_in_rna")
+    not_capitalized = check_ctxt.get("not_capitalized")
+    end_point = check_ctxt.get("end_point")
+    undoc_ops = check_ctxt.get("undoc_ops")
+    spell_errors = check_ctxt.get("spell_errors")
+
+    # XXX Temp, no multi_rnatip nor py_in_rna, see below.
+    keys = multi_lines | not_capitalized | end_point | undoc_ops | spell_errors.keys()
+    if keys:
+        _print("WARNINGS:")
+        for key in keys:
+            if undoc_ops and key in undoc_ops:
+                _print("\tThe following operators are undocumented!")
+            else:
+                _print("\t“{}”|“{}”:".format(*key))
+                if multi_lines and key in multi_lines:
+                    _print("\t\t-> newline in this message!")
+                if not_capitalized and key in not_capitalized:
+                    _print("\t\t-> message not capitalized!")
+                if end_point and key in end_point:
+                    _print("\t\t-> message with endpoint!")
+                # XXX Hide this one for now, too much false positives.
+#                if multi_rnatip and key in multi_rnatip:
+#                    _print("\t\t-> tip used in several RNA items")
+#                if py_in_rna and key in py_in_rna:
+#                    _print("\t\t-> RNA message also used in py UI code!")
+                if spell_errors and spell_errors.get(key):
+                    lines = ["\t\t-> {}: misspelled, suggestions are ({})".format(w, "'" + "', '".join(errs) + "'")
+                             for w, errs in  spell_errors[key]]
+                    _print("\n".join(lines))
+            _print("\t\t{}".format("\n\t\t".join(pot.msgs[key].sources)))
+
+
+def enable_addons(addons={}, support={}, disable=False):
+    """
+    Enable (or disable) addons based either on a set of names, or a set of 'support' types.
+    Returns the list of all affected addons (as fake modules)!
+    """
+    import addon_utils
+
+    userpref = bpy.context.user_preferences
+    used_ext = {ext.module for ext in userpref.addons}
+
+    ret = [mod for mod in addon_utils.modules(addon_utils.addons_fake_modules)
+               if ((addons and mod.__name__ in addons) or
+                   (not addons and addon_utils.module_bl_info(mod)["support"] in support))]
+
+    for mod in ret:
+        module_name = mod.__name__
+        if disable:
+            if module_name not in used_ext:
+                continue
+            print("    Disabling module ", module_name)
+            bpy.ops.wm.addon_disable(module=module_name)
+        else:
+            if module_name in used_ext:
+                continue
+            print("    Enabling module ", module_name)
+            bpy.ops.wm.addon_enable(module=module_name)
+
+    # XXX There are currently some problems with bpy/rna...
+    #     *Very* tricky to solve!
+    #     So this is a hack to make all newly added operator visible by
+    #     bpy.types.OperatorProperties.__subclasses__()
+    for cat in dir(bpy.ops):
+        cat = getattr(bpy.ops, cat)
+        for op in dir(cat):
+            getattr(cat, op).get_rna()
+
+    return ret
+
+
+def process_msg(msgs, msgctxt, msgid, msgsrc, reports, check_ctxt, settings):
+    if filter_message(msgid):
+        reports["messages_skipped"].add((msgid, msgsrc))
+        return
+    if not msgctxt:
+        # We do *not* want any "" context!
+        msgctxt = settings.DEFAULT_CONTEXT
+    # Always unescape keys!
+    msgctxt = utils.I18nMessage.do_unescape(msgctxt)
+    msgid = utils.I18nMessage.do_unescape(msgid)
+    key = (msgctxt, msgid)
+    check(check_ctxt, msgs, key, msgsrc, settings)
+    msgsrc = settings.PO_COMMENT_PREFIX_SOURCE_CUSTOM + msgsrc
+    if key not in msgs:
+        msgs[key] = utils.I18nMessage([msgctxt], [msgid], [], [msgsrc], settings=settings)
+    else:
+        msgs[key].comment_lines.append(msgsrc)
+
+
+##### RNA #####
+def dump_messages_rna(msgs, reports, settings):
+    """
+    Dump into messages dict all RNA-defined UI messages (labels en tooltips).
+    """
+    def class_blacklist():
+        blacklist_rna_class = [
+            # core classes
+            "Context", "Event", "Function", "UILayout", "BlendData", "UnknownType",
+            # registerable classes
+            "Panel", "Menu", "Header", "RenderEngine", "Operator", "OperatorMacro", "Macro", "KeyingSetInfo",
+            # window classes
+            "Window",
+        ]
+
+        # Collect internal operators
+        # extend with all internal operators
+        # note that this uses internal api introspection functions
+        # all possible operator names

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list