summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--LICENSE25
-rw-r--r--PRESUBMIT.py22
-rw-r--r--README8
-rw-r--r--codereview.settings6
-rwxr-xr-xgrit.py16
-rw-r--r--grit/__init__.py10
-rw-r--r--grit/clique.py483
-rw-r--r--grit/clique_unittest.py261
-rw-r--r--grit/constants.py18
-rw-r--r--grit/exception.py138
-rw-r--r--grit/extern/BogoFP.py22
-rw-r--r--grit/extern/FP.py71
-rw-r--r--grit/extern/__init__.py0
-rw-r--r--grit/extern/tclib.py503
-rw-r--r--grit/format/__init__.py10
-rw-r--r--grit/format/android_xml.py200
-rw-r--r--grit/format/android_xml_unittest.py110
-rw-r--r--grit/format/c_format.py86
-rw-r--r--grit/format/c_format_unittest.py78
-rw-r--r--grit/format/chrome_messages_json.py39
-rw-r--r--grit/format/chrome_messages_json_unittest.py128
-rwxr-xr-xgrit/format/data_pack.py212
-rw-r--r--grit/format/data_pack_unittest.py64
-rwxr-xr-xgrit/format/html_inline.py423
-rwxr-xr-xgrit/format/html_inline_unittest.py352
-rw-r--r--grit/format/js_map_format.py44
-rw-r--r--grit/format/js_map_format_unittest.py92
-rw-r--r--grit/format/policy_templates/PRESUBMIT.py29
-rw-r--r--grit/format/policy_templates/__init__.py10
-rw-r--r--grit/format/policy_templates/policy_template_generator.py154
-rw-r--r--grit/format/policy_templates/policy_template_generator_unittest.py395
-rw-r--r--grit/format/policy_templates/template_formatter.py73
-rw-r--r--grit/format/policy_templates/writer_configuration.py61
-rw-r--r--grit/format/policy_templates/writers/__init__.py10
-rw-r--r--grit/format/policy_templates/writers/adm_writer.py274
-rw-r--r--grit/format/policy_templates/writers/adm_writer_unittest.py1127
-rw-r--r--grit/format/policy_templates/writers/adml_writer.py186
-rw-r--r--grit/format/policy_templates/writers/adml_writer_unittest.py437
-rw-r--r--grit/format/policy_templates/writers/admx_writer.py382
-rw-r--r--grit/format/policy_templates/writers/admx_writer_unittest.py573
-rw-r--r--grit/format/policy_templates/writers/android_policy_writer.py100
-rw-r--r--grit/format/policy_templates/writers/android_policy_writer_unittest.py82
-rw-r--r--grit/format/policy_templates/writers/doc_writer.py748
-rw-r--r--grit/format/policy_templates/writers/doc_writer_unittest.py951
-rw-r--r--grit/format/policy_templates/writers/ios_plist_writer.py125
-rw-r--r--grit/format/policy_templates/writers/ios_plist_writer_unittest.py240
-rw-r--r--grit/format/policy_templates/writers/json_writer.py95
-rw-r--r--grit/format/policy_templates/writers/json_writer_unittest.py429
-rw-r--r--grit/format/policy_templates/writers/mock_writer.py30
-rw-r--r--grit/format/policy_templates/writers/plist_helper.py15
-rw-r--r--grit/format/policy_templates/writers/plist_strings_writer.py82
-rw-r--r--grit/format/policy_templates/writers/plist_strings_writer_unittest.py411
-rw-r--r--grit/format/policy_templates/writers/plist_writer.py149
-rw-r--r--grit/format/policy_templates/writers/plist_writer_unittest.py691
-rw-r--r--grit/format/policy_templates/writers/reg_writer.py117
-rw-r--r--grit/format/policy_templates/writers/reg_writer_unittest.py392
-rw-r--r--grit/format/policy_templates/writers/template_writer.py318
-rw-r--r--grit/format/policy_templates/writers/template_writer_unittest.py84
-rw-r--r--grit/format/policy_templates/writers/writer_unittest_common.py83
-rw-r--r--grit/format/policy_templates/writers/xml_formatted_writer.py91
-rw-r--r--grit/format/policy_templates/writers/xml_writer_base_unittest.py40
-rw-r--r--grit/format/rc.py481
-rw-r--r--grit/format/rc_header.py204
-rw-r--r--grit/format/rc_header_unittest.py193
-rw-r--r--grit/format/rc_unittest.py409
-rwxr-xr-xgrit/format/repack.py37
-rw-r--r--grit/format/resource_map.py132
-rw-r--r--grit/format/resource_map_unittest.py279
-rw-r--r--grit/gather/__init__.py9
-rw-r--r--grit/gather/admin_template.py61
-rw-r--r--grit/gather/admin_template_unittest.py117
-rw-r--r--grit/gather/chrome_html.py360
-rw-r--r--grit/gather/chrome_html_unittest.py523
-rw-r--r--grit/gather/chrome_scaled_image.py157
-rw-r--r--grit/gather/chrome_scaled_image_unittest.py193
-rw-r--r--grit/gather/igoogle_strings.py123
-rw-r--r--grit/gather/igoogle_strings_unittest.py29
-rw-r--r--grit/gather/interface.py171
-rw-r--r--grit/gather/json_loader.py26
-rw-r--r--grit/gather/muppet_strings.py133
-rw-r--r--grit/gather/muppet_strings_unittest.py67
-rw-r--r--grit/gather/policy_json.py251
-rw-r--r--grit/gather/policy_json_unittest.py190
-rw-r--r--grit/gather/rc.py343
-rw-r--r--grit/gather/rc_unittest.py370
-rw-r--r--grit/gather/regexp.py85
-rw-r--r--grit/gather/skeleton_gatherer.py147
-rw-r--r--grit/gather/tr_html.py745
-rw-r--r--grit/gather/tr_html_unittest.py522
-rw-r--r--grit/gather/txt.py37
-rw-r--r--grit/gather/txt_unittest.py34
-rw-r--r--grit/grd_reader.py221
-rw-r--r--grit/grd_reader_unittest.py314
-rw-r--r--grit/grit-todo.xml62
-rw-r--r--grit/grit_runner.py272
-rw-r--r--grit/grit_runner_unittest.py40
-rw-r--r--grit/lazy_re.py45
-rw-r--r--grit/lazy_re_unittest.py38
-rw-r--r--grit/node/__init__.py9
-rw-r--r--grit/node/base.py613
-rw-r--r--grit/node/base_unittest.py258
-rw-r--r--grit/node/custom/__init__.py9
-rw-r--r--grit/node/custom/filename.py28
-rw-r--r--grit/node/custom/filename_unittest.py34
-rw-r--r--grit/node/empty.py64
-rw-r--r--grit/node/include.py152
-rw-r--r--grit/node/include_unittest.py74
-rw-r--r--grit/node/io.py119
-rw-r--r--grit/node/io_unittest.py167
-rw-r--r--grit/node/mapping.py61
-rw-r--r--grit/node/message.py301
-rw-r--r--grit/node/message_unittest.py90
-rwxr-xr-xgrit/node/misc.py552
-rw-r--r--grit/node/misc_unittest.py479
-rw-r--r--grit/node/structure.py370
-rw-r--r--grit/node/structure_unittest.py69
-rw-r--r--grit/node/variant.py42
-rw-r--r--grit/pseudo.py128
-rw-r--r--grit/pseudo_rtl.py103
-rw-r--r--grit/pseudo_unittest.py53
-rwxr-xr-xgrit/scons.py255
-rw-r--r--grit/shortcuts.py93
-rw-r--r--grit/shortcuts_unittests.py80
-rw-r--r--grit/tclib.py235
-rw-r--r--grit/tclib_unittest.py179
-rw-r--r--grit/test_suite_all.py162
-rw-r--r--grit/testdata/GoogleDesktop.adm945
-rw-r--r--grit/testdata/README.txt87
-rw-r--r--grit/testdata/about.html45
-rw-r--r--grit/testdata/android.xml24
-rw-r--r--grit/testdata/bad_browser.html16
-rw-r--r--grit/testdata/browser.html42
-rw-r--r--grit/testdata/buildinfo.grd46
-rw-r--r--grit/testdata/cache_prefix.html24
-rw-r--r--grit/testdata/cache_prefix_file.html25
-rw-r--r--grit/testdata/chat_result.html24
-rw-r--r--grit/testdata/chrome/app/generated_resources.grd199
-rw-r--r--grit/testdata/chrome_html.html6
-rw-r--r--grit/testdata/default_100_percent/a.png1
-rw-r--r--grit/testdata/default_100_percent/b.png1
-rw-r--r--grit/testdata/del_footer.html8
-rw-r--r--grit/testdata/del_header.html60
-rw-r--r--grit/testdata/deleted.html21
-rw-r--r--grit/testdata/details.html10
-rw-r--r--grit/testdata/duplicate-name-input.xml26
-rw-r--r--grit/testdata/email_result.html34
-rw-r--r--grit/testdata/email_thread.html10
-rw-r--r--grit/testdata/error.html8
-rw-r--r--grit/testdata/explicit_web.html11
-rw-r--r--grit/testdata/footer.html14
-rw-r--r--grit/testdata/generated_resources_fr.xtb3090
-rw-r--r--grit/testdata/generated_resources_iw.xtb4
-rw-r--r--grit/testdata/generated_resources_no.xtb4
-rw-r--r--grit/testdata/header.html39
-rw-r--r--grit/testdata/homepage.html37
-rw-r--r--grit/testdata/hover.html177
-rw-r--r--grit/testdata/include_test.html31
-rw-r--r--grit/testdata/included_sample.html1
-rw-r--r--grit/testdata/indexing_speed.html58
-rw-r--r--grit/testdata/install_prefs.html92
-rw-r--r--grit/testdata/install_prefs2.html52
-rw-r--r--grit/testdata/klonk-alternate-skeleton.rcbin1088 -> 0 bytes
-rw-r--r--grit/testdata/klonk.icobin766 -> 0 bytes
-rw-r--r--grit/testdata/klonk.rcbin9824 -> 0 bytes
-rw-r--r--grit/testdata/ko_oem_enable_bug.html1
-rw-r--r--grit/testdata/ko_oem_non_admin_bug.html1
-rw-r--r--grit/testdata/mini.html36
-rw-r--r--grit/testdata/oem_enable.html106
-rw-r--r--grit/testdata/oem_non_admin.html39
-rw-r--r--grit/testdata/onebox.html21
-rw-r--r--grit/testdata/oneclick.html34
-rw-r--r--grit/testdata/password.html37
-rw-r--r--grit/testdata/preferences.html234
-rw-r--r--grit/testdata/privacy.html35
-rw-r--r--grit/testdata/quit_apps.html49
-rw-r--r--grit/testdata/recrawl.html30
-rw-r--r--grit/testdata/resource_ids13
-rw-r--r--grit/testdata/script.html38
-rw-r--r--grit/testdata/searchbox.html22
-rw-r--r--grit/testdata/sidebar_h.html82
-rw-r--r--grit/testdata/sidebar_v.html267
-rw-r--r--grit/testdata/simple-input.xml52
-rw-r--r--grit/testdata/simple.html3
-rw-r--r--grit/testdata/source.rc57
-rw-r--r--grit/testdata/special_100_percent/a.png1
-rw-r--r--grit/testdata/status.html44
-rw-r--r--grit/testdata/structure_variables.html4
-rw-r--r--grit/testdata/substitute.grd31
-rw-r--r--grit/testdata/substitute.xmb10
-rw-r--r--grit/testdata/substitute_no_ids.grd31
-rw-r--r--grit/testdata/time_related.html11
-rw-r--r--grit/testdata/toolbar_about.html138
-rw-r--r--grit/testdata/tools/grit/resource_ids175
-rw-r--r--grit/testdata/transl.rc56
-rw-r--r--grit/testdata/versions.html7
-rw-r--r--grit/testdata/whitelist.txt4
-rw-r--r--grit/testdata/whitelist_resources.grd54
-rw-r--r--grit/testdata/whitelist_strings.grd23
-rw-r--r--grit/tool/__init__.py10
-rw-r--r--grit/tool/android2grd.py479
-rw-r--r--grit/tool/android2grd_unittest.py180
-rw-r--r--grit/tool/build.py499
-rw-r--r--grit/tool/build_unittest.py353
-rw-r--r--grit/tool/buildinfo.py68
-rw-r--r--grit/tool/buildinfo_unittest.py87
-rw-r--r--grit/tool/count.py35
-rw-r--r--grit/tool/diff_structures.py114
-rw-r--r--grit/tool/interface.py58
-rw-r--r--grit/tool/menu_from_parts.py79
-rw-r--r--grit/tool/newgrd.py70
-rw-r--r--grit/tool/postprocess_interface.py32
-rw-r--r--grit/tool/postprocess_unittest.py63
-rw-r--r--grit/tool/preprocess_interface.py28
-rw-r--r--grit/tool/preprocess_unittest.py49
-rw-r--r--grit/tool/rc2grd.py409
-rw-r--r--grit/tool/rc2grd_unittest.py137
-rw-r--r--grit/tool/resize.py289
-rw-r--r--grit/tool/test.py24
-rw-r--r--grit/tool/toolbar_postprocess.py126
-rw-r--r--grit/tool/toolbar_preprocess.py61
-rw-r--r--grit/tool/transl2tc.py252
-rw-r--r--grit/tool/transl2tc_unittest.py131
-rw-r--r--grit/tool/unit.py26
-rw-r--r--grit/tool/xmb.py291
-rw-r--r--grit/tool/xmb_unittest.py103
-rw-r--r--grit/util.py661
-rw-r--r--grit/util_unittest.py119
-rw-r--r--grit/xtb_reader.py141
-rw-r--r--grit/xtb_reader_unittest.py106
-rwxr-xr-xgrit_info.py193
230 files changed, 6 insertions, 36889 deletions
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 2aa3944..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2012 The Chromium Authors.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-Redistributions of source code must retain the above copyright notice,
-this list of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
deleted file mode 100644
index 7001689..0000000
--- a/PRESUBMIT.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""grit unittests presubmit script.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
-details on the presubmit API built into gcl.
-"""
-
-
-def RunUnittests(input_api, output_api):
- return input_api.canned_checks.RunPythonUnitTests(input_api, output_api,
- ['grit.test_suite_all'])
-
-
-def CheckChangeOnUpload(input_api, output_api):
- return RunUnittests(input_api, output_api)
-
-
-def CheckChangeOnCommit(input_api, output_api):
- return RunUnittests(input_api, output_api)
diff --git a/README b/README
index 8fcdafe..2409716 100644
--- a/README
+++ b/README
@@ -1,2 +1,6 @@
-GRIT (Google Resource and Internationalization Tool) is a tool for Windows
-projects to manage resources and simplify the localization workflow.
+GRIT's code now lives in Chromium's repository at
+https://chromium.googlesource.com/chromium/src/+/master/tools/grit
+
+There is a read-only mirror of just that directory at
+https://chromium.googlesource.com/chromium/src/tools/grit/
+if you don't want to check out all of Chromium.
diff --git a/codereview.settings b/codereview.settings
deleted file mode 100644
index 4535052..0000000
--- a/codereview.settings
+++ /dev/null
@@ -1,6 +0,0 @@
-# This file is used by gcl to get repository specific information.
-CODE_REVIEW_SERVER: codereview.chromium.org
-CC_LIST: grit-developer@googlegroups.com
-VIEW_VC: http://code.google.com/p/grit-i18n/source/detail?r=
-TRY_ON_UPLOAD: False
-
diff --git a/grit.py b/grit.py
deleted file mode 100755
index b17ceb9..0000000
--- a/grit.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Bootstrapping for GRIT.
-'''
-
-import sys
-
-import grit.grit_runner
-
-
-if __name__ == '__main__':
- grit.grit_runner.Main(sys.argv[1:])
-
diff --git a/grit/__init__.py b/grit/__init__.py
deleted file mode 100644
index 57e6709..0000000
--- a/grit/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Package 'grit'
-'''
-
-pass
-
diff --git a/grit/clique.py b/grit/clique.py
deleted file mode 100644
index 3a97989..0000000
--- a/grit/clique.py
+++ /dev/null
@@ -1,483 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Collections of messages and their translations, called cliques. Also
-collections of cliques (uber-cliques).
-'''
-
-import re
-import types
-
-from grit import constants
-from grit import exception
-from grit import lazy_re
-from grit import pseudo
-from grit import pseudo_rtl
-from grit import tclib
-
-
-class UberClique(object):
- '''A factory (NOT a singleton factory) for making cliques. It has several
- methods for working with the cliques created using the factory.
- '''
-
- def __init__(self):
- # A map from message ID to list of cliques whose source messages have
- # that ID. This will contain all cliques created using this factory.
- # Different messages can have the same ID because they have the
- # same translateable portion and placeholder names, but occur in different
- # places in the resource tree.
- #
- # Each list of cliques is kept sorted by description, to achieve
- # stable results from the BestClique method, see below.
- self.cliques_ = {}
-
- # A map of clique IDs to list of languages to indicate translations where we
- # fell back to English.
- self.fallback_translations_ = {}
-
- # A map of clique IDs to list of languages to indicate missing translations.
- self.missing_translations_ = {}
-
- def _AddMissingTranslation(self, lang, clique, is_error):
- tl = self.fallback_translations_
- if is_error:
- tl = self.missing_translations_
- id = clique.GetId()
- if id not in tl:
- tl[id] = {}
- if lang not in tl[id]:
- tl[id][lang] = 1
-
- def HasMissingTranslations(self):
- return len(self.missing_translations_) > 0
-
- def MissingTranslationsReport(self):
- '''Returns a string suitable for printing to report missing
- and fallback translations to the user.
- '''
- def ReportTranslation(clique, langs):
- text = clique.GetMessage().GetPresentableContent()
- # The text 'error' (usually 'Error:' but we are conservative)
- # can trigger some build environments (Visual Studio, we're
- # looking at you) to consider invocation of grit to have failed,
- # so we make sure never to output that word.
- extract = re.sub('(?i)error', 'REDACTED', text[0:40])[0:40]
- ellipsis = ''
- if len(text) > 40:
- ellipsis = '...'
- langs_extract = langs[0:6]
- describe_langs = ','.join(langs_extract)
- if len(langs) > 6:
- describe_langs += " and %d more" % (len(langs) - 6)
- return " %s \"%s%s\" %s" % (clique.GetId(), extract, ellipsis,
- describe_langs)
- lines = []
- if len(self.fallback_translations_):
- lines.append(
- "WARNING: Fell back to English for the following translations:")
- for (id, langs) in self.fallback_translations_.items():
- lines.append(ReportTranslation(self.cliques_[id][0], langs.keys()))
- if len(self.missing_translations_):
- lines.append("ERROR: The following translations are MISSING:")
- for (id, langs) in self.missing_translations_.items():
- lines.append(ReportTranslation(self.cliques_[id][0], langs.keys()))
- return '\n'.join(lines)
-
- def MakeClique(self, message, translateable=True):
- '''Create a new clique initialized with a message.
-
- Args:
- message: tclib.Message()
- translateable: True | False
- '''
- clique = MessageClique(self, message, translateable)
-
- # Enable others to find this clique by its message ID
- if message.GetId() in self.cliques_:
- presentable_text = clique.GetMessage().GetPresentableContent()
- if not message.HasAssignedId():
- for c in self.cliques_[message.GetId()]:
- assert c.GetMessage().GetPresentableContent() == presentable_text
- self.cliques_[message.GetId()].append(clique)
- # We need to keep each list of cliques sorted by description, to
- # achieve stable results from the BestClique method, see below.
- self.cliques_[message.GetId()].sort(
- key=lambda c:c.GetMessage().GetDescription())
- else:
- self.cliques_[message.GetId()] = [clique]
-
- return clique
-
- def FindCliqueAndAddTranslation(self, translation, language):
- '''Adds the specified translation to the clique with the source message
- it is a translation of.
-
- Args:
- translation: tclib.Translation()
- language: 'en' | 'fr' ...
-
- Return:
- True if the source message was found, otherwise false.
- '''
- if translation.GetId() in self.cliques_:
- for clique in self.cliques_[translation.GetId()]:
- clique.AddTranslation(translation, language)
- return True
- else:
- return False
-
- def BestClique(self, id):
- '''Returns the "best" clique from a list of cliques. All the cliques
- must have the same ID. The "best" clique is chosen in the following
- order of preference:
- - The first clique that has a non-ID-based description.
- - If no such clique found, the first clique with an ID-based description.
- - Otherwise the first clique.
-
- This method is stable in terms of always returning a clique with
- an identical description (on different runs of GRIT on the same
- data) because self.cliques_ is sorted by description.
- '''
- clique_list = self.cliques_[id]
- clique_with_id = None
- clique_default = None
- for clique in clique_list:
- if not clique_default:
- clique_default = clique
-
- description = clique.GetMessage().GetDescription()
- if description and len(description) > 0:
- if not description.startswith('ID:'):
- # this is the preferred case so we exit right away
- return clique
- elif not clique_with_id:
- clique_with_id = clique
- if clique_with_id:
- return clique_with_id
- else:
- return clique_default
-
- def BestCliquePerId(self):
- '''Iterates over the list of all cliques and returns the best clique for
- each ID. This will be the first clique with a source message that has a
- non-empty description, or an arbitrary clique if none of them has a
- description.
- '''
- for id in self.cliques_:
- yield self.BestClique(id)
-
- def BestCliqueByOriginalText(self, text, meaning):
- '''Finds the "best" (as in BestClique()) clique that has original text
- 'text' and meaning 'meaning'. Returns None if there is no such clique.
- '''
- # If needed, this can be optimized by maintaining a map of
- # fingerprints of original text+meaning to cliques.
- for c in self.BestCliquePerId():
- msg = c.GetMessage()
- if msg.GetRealContent() == text and msg.GetMeaning() == meaning:
- return msg
- return None
-
- def AllMessageIds(self):
- '''Returns a list of all defined message IDs.
- '''
- return self.cliques_.keys()
-
- def AllCliques(self):
- '''Iterates over all cliques. Note that this can return multiple cliques
- with the same ID.
- '''
- for cliques in self.cliques_.values():
- for c in cliques:
- yield c
-
- def GenerateXtbParserCallback(self, lang, debug=False):
- '''Creates a callback function as required by grit.xtb_reader.Parse().
- This callback will create Translation objects for each message from
- the XTB that exists in this uberclique, and add them as translations for
- the relevant cliques. The callback will add translations to the language
- specified by 'lang'
-
- Args:
- lang: 'fr'
- debug: True | False
- '''
- def Callback(id, structure):
- if id not in self.cliques_:
- if debug: print "Ignoring translation #%s" % id
- return
-
- if debug: print "Adding translation #%s" % id
-
- # We fetch placeholder information from the original message (the XTB file
- # only contains placeholder names).
- original_msg = self.BestClique(id).GetMessage()
-
- translation = tclib.Translation(id=id)
- for is_ph,text in structure:
- if not is_ph:
- translation.AppendText(text)
- else:
- found_placeholder = False
- for ph in original_msg.GetPlaceholders():
- if ph.GetPresentation() == text:
- translation.AppendPlaceholder(tclib.Placeholder(
- ph.GetPresentation(), ph.GetOriginal(), ph.GetExample()))
- found_placeholder = True
- break
- if not found_placeholder:
- raise exception.MismatchingPlaceholders(
- 'Translation for message ID %s had <ph name="%s"/>, no match\n'
- 'in original message' % (id, text))
- self.FindCliqueAndAddTranslation(translation, lang)
- return Callback
-
-
-class CustomType(object):
- '''A base class you should implement if you wish to specify a custom type
- for a message clique (i.e. custom validation and optional modification of
- translations).'''
-
- def Validate(self, message):
- '''Returns true if the message (a tclib.Message object) is valid,
- otherwise false.
- '''
- raise NotImplementedError()
-
- def ValidateAndModify(self, lang, translation):
- '''Returns true if the translation (a tclib.Translation object) is valid,
- otherwise false. The language is also passed in. This method may modify
- the translation that is passed in, if it so wishes.
- '''
- raise NotImplementedError()
-
- def ModifyTextPart(self, lang, text):
- '''If you call ModifyEachTextPart, it will turn around and call this method
- for each text part of the translation. You should return the modified
- version of the text, or just the original text to not change anything.
- '''
- raise NotImplementedError()
-
- def ModifyEachTextPart(self, lang, translation):
- '''Call this to easily modify one or more of the textual parts of a
- translation. It will call ModifyTextPart for each part of the
- translation.
- '''
- contents = translation.GetContent()
- for ix in range(len(contents)):
- if (isinstance(contents[ix], types.StringTypes)):
- contents[ix] = self.ModifyTextPart(lang, contents[ix])
-
-
-class OneOffCustomType(CustomType):
- '''A very simple custom type that performs the validation expressed by
- the input expression on all languages including the source language.
- The expression can access the variables 'lang', 'msg' and 'text()' where 'lang'
- is the language of 'msg', 'msg' is the message or translation being
- validated and 'text()' returns the real contents of 'msg' (for shorthand).
- '''
- def __init__(self, expression):
- self.expr = expression
- def Validate(self, message):
- return self.ValidateAndModify(MessageClique.source_language, message)
- def ValidateAndModify(self, lang, msg):
- def text():
- return msg.GetRealContent()
- return eval(self.expr, {},
- {'lang' : lang,
- 'text' : text,
- 'msg' : msg,
- })
-
-
-class MessageClique(object):
- '''A message along with all of its translations. Also code to bring
- translations together with their original message.'''
-
- # change this to the language code of Messages you add to cliques_.
- # TODO(joi) Actually change this based on the <grit> node's source language
- source_language = 'en'
-
- # A constant translation we use when asked for a translation into the
- # special language constants.CONSTANT_LANGUAGE.
- CONSTANT_TRANSLATION = tclib.Translation(text='TTTTTT')
-
- # A pattern to match messages that are empty or whitespace only.
- WHITESPACE_MESSAGE = lazy_re.compile(u'^\s*$')
-
- def __init__(self, uber_clique, message, translateable=True, custom_type=None):
- '''Create a new clique initialized with just a message.
-
- Note that messages with a body comprised only of whitespace will implicitly
- be marked non-translatable.
-
- Args:
- uber_clique: Our uber-clique (collection of cliques)
- message: tclib.Message()
- translateable: True | False
- custom_type: instance of clique.CustomType interface
- '''
- # Our parent
- self.uber_clique = uber_clique
- # If not translateable, we only store the original message.
- self.translateable = translateable
-
- # We implicitly mark messages that have a whitespace-only body as
- # non-translateable.
- if MessageClique.WHITESPACE_MESSAGE.match(message.GetRealContent()):
- self.translateable = False
-
- # A mapping of language identifiers to tclib.BaseMessage and its
- # subclasses (i.e. tclib.Message and tclib.Translation).
- self.clique = { MessageClique.source_language : message }
- # A list of the "shortcut groups" this clique is
- # part of. Within any given shortcut group, no shortcut key (e.g. &J)
- # must appear more than once in each language for all cliques that
- # belong to the group.
- self.shortcut_groups = []
- # An instance of the CustomType interface, or None. If this is set, it will
- # be used to validate the original message and translations thereof, and
- # will also get a chance to modify translations of the message.
- self.SetCustomType(custom_type)
-
- def GetMessage(self):
- '''Retrieves the tclib.Message that is the source for this clique.'''
- return self.clique[MessageClique.source_language]
-
- def GetId(self):
- '''Retrieves the message ID of the messages in this clique.'''
- return self.GetMessage().GetId()
-
- def IsTranslateable(self):
- return self.translateable
-
- def AddToShortcutGroup(self, group):
- self.shortcut_groups.append(group)
-
- def SetCustomType(self, custom_type):
- '''Makes this clique use custom_type for validating messages and
- translations, and optionally modifying translations.
- '''
- self.custom_type = custom_type
- if custom_type and not custom_type.Validate(self.GetMessage()):
- raise exception.InvalidMessage(self.GetMessage().GetRealContent())
-
- def MessageForLanguage(self, lang, pseudo_if_no_match=True, fallback_to_english=False):
- '''Returns the message/translation for the specified language, providing
- a pseudotranslation if there is no available translation and a pseudo-
- translation is requested.
-
- The translation of any message whatsoever in the special language
- 'x_constant' is the message "TTTTTT".
-
- Args:
- lang: 'en'
- pseudo_if_no_match: True
- fallback_to_english: False
-
- Return:
- tclib.BaseMessage
- '''
- if not self.translateable:
- return self.GetMessage()
-
- if lang == constants.CONSTANT_LANGUAGE:
- return self.CONSTANT_TRANSLATION
-
- for msglang in self.clique.keys():
- if lang == msglang:
- return self.clique[msglang]
-
- if lang == constants.FAKE_BIDI:
- return pseudo_rtl.PseudoRTLMessage(self.GetMessage())
-
- if fallback_to_english:
- self.uber_clique._AddMissingTranslation(lang, self, is_error=False)
- return self.GetMessage()
-
- # If we're not supposed to generate pseudotranslations, we add an error
- # report to a list of errors, then fail at a higher level, so that we
- # get a list of all messages that are missing translations.
- if not pseudo_if_no_match:
- self.uber_clique._AddMissingTranslation(lang, self, is_error=True)
-
- return pseudo.PseudoMessage(self.GetMessage())
-
- def AllMessagesThatMatch(self, lang_re, include_pseudo = True):
- '''Returns a map of all messages that match 'lang', including the pseudo
- translation if requested.
-
- Args:
- lang_re: re.compile('fr|en')
- include_pseudo: True
-
- Return:
- { 'en' : tclib.Message,
- 'fr' : tclib.Translation,
- pseudo.PSEUDO_LANG : tclib.Translation }
- '''
- if not self.translateable:
- return [self.GetMessage()]
-
- matches = {}
- for msglang in self.clique:
- if lang_re.match(msglang):
- matches[msglang] = self.clique[msglang]
-
- if include_pseudo:
- matches[pseudo.PSEUDO_LANG] = pseudo.PseudoMessage(self.GetMessage())
-
- return matches
-
- def AddTranslation(self, translation, language):
- '''Add a translation to this clique. The translation must have the same
- ID as the message that is the source for this clique.
-
- If this clique is not translateable, the function just returns.
-
- Args:
- translation: tclib.Translation()
- language: 'en'
-
- Throws:
- grit.exception.InvalidTranslation if the translation you're trying to add
- doesn't have the same message ID as the source message of this clique.
- '''
- if not self.translateable:
- return
- if translation.GetId() != self.GetId():
- raise exception.InvalidTranslation(
- 'Msg ID %s, transl ID %s' % (self.GetId(), translation.GetId()))
-
- assert not language in self.clique
-
- # Because two messages can differ in the original content of their
- # placeholders yet share the same ID (because they are otherwise the
- # same), the translation we are getting may have different original
- # content for placeholders than our message, yet it is still the right
- # translation for our message (because it is for the same ID). We must
- # therefore fetch the original content of placeholders from our original
- # English message.
- #
- # See grit.clique_unittest.MessageCliqueUnittest.testSemiIdenticalCliques
- # for a concrete explanation of why this is necessary.
-
- original = self.MessageForLanguage(self.source_language, False)
- if len(original.GetPlaceholders()) != len(translation.GetPlaceholders()):
- print ("ERROR: '%s' translation of message id %s does not match" %
- (language, translation.GetId()))
- assert False
-
- transl_msg = tclib.Translation(id=self.GetId(),
- text=translation.GetPresentableContent(),
- placeholders=original.GetPlaceholders())
-
- if self.custom_type and not self.custom_type.ValidateAndModify(language, transl_msg):
- print "WARNING: %s translation failed validation: %s" % (
- language, transl_msg.GetId())
-
- self.clique[language] = transl_msg
-
diff --git a/grit/clique_unittest.py b/grit/clique_unittest.py
deleted file mode 100644
index faf5483..0000000
--- a/grit/clique_unittest.py
+++ /dev/null
@@ -1,261 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.clique'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
-
-import re
-import StringIO
-import unittest
-
-from grit import clique
-from grit import exception
-from grit import pseudo
-from grit import tclib
-from grit import grd_reader
-from grit import util
-
-class MessageCliqueUnittest(unittest.TestCase):
- def testClique(self):
- factory = clique.UberClique()
- msg = tclib.Message(text='Hello USERNAME, how are you?',
- placeholders=[
- tclib.Placeholder('USERNAME', '%s', 'Joi')])
- c = factory.MakeClique(msg)
-
- self.failUnless(c.GetMessage() == msg)
- self.failUnless(c.GetId() == msg.GetId())
-
- msg_fr = tclib.Translation(text='Bonjour USERNAME, comment ca va?',
- id=msg.GetId(), placeholders=[
- tclib.Placeholder('USERNAME', '%s', 'Joi')])
- msg_de = tclib.Translation(text='Guten tag USERNAME, wie geht es dir?',
- id=msg.GetId(), placeholders=[
- tclib.Placeholder('USERNAME', '%s', 'Joi')])
-
- c.AddTranslation(msg_fr, 'fr')
- factory.FindCliqueAndAddTranslation(msg_de, 'de')
-
- # sort() sorts lists in-place and does not return them
- for lang in ('en', 'fr', 'de'):
- self.failUnless(lang in c.clique)
-
- self.failUnless(c.MessageForLanguage('fr').GetRealContent() ==
- msg_fr.GetRealContent())
-
- try:
- c.MessageForLanguage('zh-CN', False)
- self.fail('Should have gotten exception')
- except:
- pass
-
- self.failUnless(c.MessageForLanguage('zh-CN', True) != None)
-
- rex = re.compile('fr|de|bingo')
- self.failUnless(len(c.AllMessagesThatMatch(rex, False)) == 2)
- self.failUnless(c.AllMessagesThatMatch(rex, True)[pseudo.PSEUDO_LANG] != None)
-
- def testBestClique(self):
- factory = clique.UberClique()
- factory.MakeClique(tclib.Message(text='Alfur', description='alfaholl'))
- factory.MakeClique(tclib.Message(text='Alfur', description=''))
- factory.MakeClique(tclib.Message(text='Vaettur', description=''))
- factory.MakeClique(tclib.Message(text='Vaettur', description=''))
- factory.MakeClique(tclib.Message(text='Troll', description=''))
- factory.MakeClique(tclib.Message(text='Gryla', description='ID: IDS_GRYLA'))
- factory.MakeClique(tclib.Message(text='Gryla', description='vondakerling'))
- factory.MakeClique(tclib.Message(text='Leppaludi', description='ID: IDS_LL'))
- factory.MakeClique(tclib.Message(text='Leppaludi', description=''))
-
- count_best_cliques = 0
- for c in factory.BestCliquePerId():
- count_best_cliques += 1
- msg = c.GetMessage()
- text = msg.GetRealContent()
- description = msg.GetDescription()
- if text == 'Alfur':
- self.failUnless(description == 'alfaholl')
- elif text == 'Gryla':
- self.failUnless(description == 'vondakerling')
- elif text == 'Leppaludi':
- self.failUnless(description == 'ID: IDS_LL')
- self.failUnless(count_best_cliques == 5)
-
- def testAllInUberClique(self):
- resources = grd_reader.Parse(
- StringIO.StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <messages>
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- </messages>
- <structures>
- <structure type="dialog" name="IDD_ABOUTBOX" encoding="utf-16" file="grit/testdata/klonk.rc" />
- <structure type="tr_html" name="ID_HTML" file="grit/testdata/simple.html" />
- </structures>
- </release>
-</grit>'''), util.PathFromRoot('.'))
- resources.SetOutputLanguage('en')
- resources.RunGatherers()
- content_list = []
- for clique_list in resources.UberClique().cliques_.values():
- for clique in clique_list:
- content_list.append(clique.GetMessage().GetRealContent())
- self.failUnless('Hello %s, how are you doing today?' in content_list)
- self.failUnless('Jack "Black" Daniels' in content_list)
- self.failUnless('Hello!' in content_list)
-
- def testCorrectExceptionIfWrongEncodingOnResourceFile(self):
- '''This doesn't really belong in this unittest file, but what the heck.'''
- resources = grd_reader.Parse(
- StringIO.StringIO(u'''<?xml version="1.0" encoding="UTF-8"?>
-<grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="3">
- <structures>
- <structure type="dialog" name="IDD_ABOUTBOX" file="grit/testdata/klonk.rc" />
- </structures>
- </release>
-</grit>'''), util.PathFromRoot('.'))
- self.assertRaises(exception.SectionNotFound, resources.RunGatherers)
-
- def testSemiIdenticalCliques(self):
- messages = [
- tclib.Message(text='Hello USERNAME',
- placeholders=[tclib.Placeholder('USERNAME', '$1', 'Joi')]),
- tclib.Message(text='Hello USERNAME',
- placeholders=[tclib.Placeholder('USERNAME', '%s', 'Joi')]),
- ]
- self.failUnless(messages[0].GetId() == messages[1].GetId())
-
- # Both of the above would share a translation.
- translation = tclib.Translation(id=messages[0].GetId(),
- text='Bonjour USERNAME',
- placeholders=[tclib.Placeholder(
- 'USERNAME', '$1', 'Joi')])
-
- factory = clique.UberClique()
- cliques = [factory.MakeClique(msg) for msg in messages]
-
- for clq in cliques:
- clq.AddTranslation(translation, 'fr')
-
- self.failUnless(cliques[0].MessageForLanguage('fr').GetRealContent() ==
- 'Bonjour $1')
- self.failUnless(cliques[1].MessageForLanguage('fr').GetRealContent() ==
- 'Bonjour %s')
-
- def testMissingTranslations(self):
- messages = [ tclib.Message(text='Hello'), tclib.Message(text='Goodbye') ]
- factory = clique.UberClique()
- cliques = [factory.MakeClique(msg) for msg in messages]
-
- cliques[1].MessageForLanguage('fr', False, True)
-
- self.failUnless(not factory.HasMissingTranslations())
-
- cliques[0].MessageForLanguage('de', False, False)
-
- self.failUnless(factory.HasMissingTranslations())
-
- report = factory.MissingTranslationsReport()
- self.failUnless(report.count('WARNING') == 1)
- self.failUnless(report.count('8053599568341804890 "Goodbye" fr') == 1)
- self.failUnless(report.count('ERROR') == 1)
- self.failUnless(report.count('800120468867715734 "Hello" de') == 1)
-
- def testCustomTypes(self):
- factory = clique.UberClique()
- message = tclib.Message(text='Bingo bongo')
- c = factory.MakeClique(message)
- try:
- c.SetCustomType(DummyCustomType())
- self.fail()
- except:
- pass # expected case - 'Bingo bongo' does not start with 'jjj'
-
- message = tclib.Message(text='jjjBingo bongo')
- c = factory.MakeClique(message)
- c.SetCustomType(util.NewClassInstance(
- 'grit.clique_unittest.DummyCustomType', clique.CustomType))
- translation = tclib.Translation(id=message.GetId(), text='Bilingo bolongo')
- c.AddTranslation(translation, 'fr')
- self.failUnless(c.MessageForLanguage('fr').GetRealContent().startswith('jjj'))
-
- def testWhitespaceMessagesAreNontranslateable(self):
- factory = clique.UberClique()
-
- message = tclib.Message(text=' \t')
- c = factory.MakeClique(message, translateable=True)
- self.failIf(c.IsTranslateable())
-
- message = tclib.Message(text='\n \n ')
- c = factory.MakeClique(message, translateable=True)
- self.failIf(c.IsTranslateable())
-
- message = tclib.Message(text='\n hello')
- c = factory.MakeClique(message, translateable=True)
- self.failUnless(c.IsTranslateable())
-
- def testEachCliqueKeptSorted(self):
- factory = clique.UberClique()
- msg_a = tclib.Message(text='hello', description='a')
- msg_b = tclib.Message(text='hello', description='b')
- msg_c = tclib.Message(text='hello', description='c')
- # Insert out of order
- clique_b = factory.MakeClique(msg_b, translateable=True)
- clique_a = factory.MakeClique(msg_a, translateable=True)
- clique_c = factory.MakeClique(msg_c, translateable=True)
- clique_list = factory.cliques_[clique_a.GetId()]
- self.failUnless(len(clique_list) == 3)
- self.failUnless(clique_list[0] == clique_a)
- self.failUnless(clique_list[1] == clique_b)
- self.failUnless(clique_list[2] == clique_c)
-
- def testBestCliqueSortIsStable(self):
- factory = clique.UberClique()
- text = 'hello'
- msg_no_description = tclib.Message(text=text)
- msg_id_description_a = tclib.Message(text=text, description='ID: a')
- msg_id_description_b = tclib.Message(text=text, description='ID: b')
- msg_description_x = tclib.Message(text=text, description='x')
- msg_description_y = tclib.Message(text=text, description='y')
- clique_id = msg_no_description.GetId()
-
- # Insert in an order that tests all outcomes.
- clique_no_description = factory.MakeClique(msg_no_description,
- translateable=True)
- self.failUnless(factory.BestClique(clique_id) == clique_no_description)
- clique_id_description_b = factory.MakeClique(msg_id_description_b,
- translateable=True)
- self.failUnless(factory.BestClique(clique_id) == clique_id_description_b)
- clique_id_description_a = factory.MakeClique(msg_id_description_a,
- translateable=True)
- self.failUnless(factory.BestClique(clique_id) == clique_id_description_a)
- clique_description_y = factory.MakeClique(msg_description_y,
- translateable=True)
- self.failUnless(factory.BestClique(clique_id) == clique_description_y)
- clique_description_x = factory.MakeClique(msg_description_x,
- translateable=True)
- self.failUnless(factory.BestClique(clique_id) == clique_description_x)
-
-
-class DummyCustomType(clique.CustomType):
- def Validate(self, message):
- return message.GetRealContent().startswith('jjj')
- def ValidateAndModify(self, lang, translation):
- is_ok = self.Validate(translation)
- self.ModifyEachTextPart(lang, translation)
- def ModifyTextPart(self, lang, text):
- return 'jjj%s' % text
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/constants.py b/grit/constants.py
deleted file mode 100644
index 77faf2a..0000000
--- a/grit/constants.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Constant definitions for GRIT.
-'''
-
-
-# This is the Icelandic noun meaning "grit" and is used to check that our
-# input files are in the correct encoding. The middle character gets encoded
-# as two bytes in UTF-8, so this is sufficient to detect incorrect encoding.
-ENCODING_CHECK = u'm\u00f6l'
-
-# A special language, translations into which are always "TTTTTT".
-CONSTANT_LANGUAGE = 'x_constant'
-
-FAKE_BIDI = 'fake-bidi'
diff --git a/grit/exception.py b/grit/exception.py
deleted file mode 100644
index a9584a0..0000000
--- a/grit/exception.py
+++ /dev/null
@@ -1,138 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Exception types for GRIT.
-'''
-
-class Base(Exception):
- '''A base exception that uses the class's docstring in addition to any
- user-provided message as the body of the Base.
- '''
- def __init__(self, msg=''):
- if len(msg):
- if self.__doc__:
- msg = self.__doc__ + ': ' + msg
- else:
- msg = self.__doc__
- super(Base, self).__init__(msg)
-
-
-class Parsing(Base):
- '''An error occurred parsing a GRD or XTB file.'''
- pass
-
-
-class UnknownElement(Parsing):
- '''An unknown node type was encountered.'''
- pass
-
-
-class MissingElement(Parsing):
- '''An expected element was missing.'''
- pass
-
-
-class UnexpectedChild(Parsing):
- '''An unexpected child element was encountered (on a leaf node).'''
- pass
-
-
-class UnexpectedAttribute(Parsing):
- '''The attribute was not expected'''
- pass
-
-
-class UnexpectedContent(Parsing):
- '''This element should not have content'''
- pass
-
-
-class MissingMandatoryAttribute(Parsing):
- '''This element is missing a mandatory attribute'''
- pass
-
-
-class MutuallyExclusiveMandatoryAttribute(Parsing):
- '''This element has 2 mutually exclusive mandatory attributes'''
- pass
-
-
-class DuplicateKey(Parsing):
- '''A duplicate key attribute was found.'''
- pass
-
-
-class TooManyExamples(Parsing):
- '''Only one <ex> element is allowed for each <ph> element.'''
- pass
-
-
-class GotPathExpectedFilenameOnly(Parsing):
- '''The 'filename' attribute of <output> and the 'file' attribute of <part>
- must be bare filenames, not paths.
- '''
- pass
-
-
-class FileNotFound(Parsing):
- '''The resource file was not found.
- '''
- pass
-
-
-class InvalidMessage(Base):
- '''The specified message failed validation.'''
- pass
-
-
-class InvalidTranslation(Base):
- '''Attempt to add an invalid translation to a clique.'''
- pass
-
-
-class NoSuchTranslation(Base):
- '''Requested translation not available'''
- pass
-
-
-class NotReady(Base):
- '''Attempt to use an object before it is ready, or attempt to translate
- an empty document.'''
- pass
-
-
-class TooManyPlaceholders(Base):
- '''Too many placeholders for elements of the same type.'''
- pass
-
-
-class MismatchingPlaceholders(Base):
- '''Placeholders do not match.'''
- pass
-
-
-class InvalidPlaceholderName(Base):
- '''Placeholder name can only contain A-Z, a-z, 0-9 and underscore.'''
- pass
-
-
-class BlockTagInTranslateableChunk(Base):
- '''A block tag was encountered where it wasn't expected.'''
- pass
-
-
-class SectionNotFound(Base):
- '''The section you requested was not found in the RC file. Make
-sure the section ID is correct (matches the section's ID in the RC file).
-Also note that you may need to specify the RC file's encoding (using the
-encoding="" attribute) if it is not in the default Windows-1252 encoding.
- '''
- pass
-
-
-class IdRangeOverlap(Base):
- '''ID range overlap.'''
- pass
-
diff --git a/grit/extern/BogoFP.py b/grit/extern/BogoFP.py
deleted file mode 100644
index 3d9cad3..0000000
--- a/grit/extern/BogoFP.py
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Bogus fingerprint implementation, do not use for production,
-provided only as an example.
-
-Usage:
- grit.py -h grit.extern.BogoFP xmb /tmp/foo
-"""
-
-
-import grit.extern.FP
-
-
-def UnsignedFingerPrint(str, encoding='utf-8'):
- """Generate a fingerprint not intended for production from str (it
- reduces the precision of the production fingerprint by one bit).
- """
- return (0xFFFFF7FFFFFFFFFF &
- grit.extern.FP._UnsignedFingerPrintImpl(str, encoding))
diff --git a/grit/extern/FP.py b/grit/extern/FP.py
deleted file mode 100644
index 3bde18d..0000000
--- a/grit/extern/FP.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-try:
- import hashlib
- _new_md5 = hashlib.md5
-except ImportError:
- import md5
- _new_md5 = md5.new
-
-
-"""64-bit fingerprint support for strings.
-
-Usage:
- from extern import FP
- print 'Fingerprint is %ld' % FP.FingerPrint('Hello world!')
-"""
-
-
-def _UnsignedFingerPrintImpl(str, encoding='utf-8'):
- """Generate a 64-bit fingerprint by taking the first half of the md5
- of the string.
- """
- hex128 = _new_md5(str).hexdigest()
- int64 = long(hex128[:16], 16)
- return int64
-
-
-def UnsignedFingerPrint(str, encoding='utf-8'):
- """Generate a 64-bit fingerprint.
-
- The default implementation uses _UnsignedFingerPrintImpl, which
- takes the first half of the md5 of the string, but the
- implementation may be switched using SetUnsignedFingerPrintImpl.
- """
- return _UnsignedFingerPrintImpl(str, encoding)
-
-
-def FingerPrint(str, encoding='utf-8'):
- fp = UnsignedFingerPrint(str, encoding=encoding)
- # interpret fingerprint as signed longs
- if fp & 0x8000000000000000L:
- fp = - ((~fp & 0xFFFFFFFFFFFFFFFFL) + 1)
- return fp
-
-
-def UseUnsignedFingerPrintFromModule(module_name):
- """Imports module_name and replaces UnsignedFingerPrint in the
- current module with the function of the same name from the imported
- module.
-
- Returns the function object previously known as
- grit.extern.FP.UnsignedFingerPrint.
- """
- hash_module = __import__(module_name, fromlist=[module_name])
- return SetUnsignedFingerPrint(hash_module.UnsignedFingerPrint)
-
-
-def SetUnsignedFingerPrint(function_object):
- """Sets grit.extern.FP.UnsignedFingerPrint to point to
- function_object.
-
- Returns the function object previously known as
- grit.extern.FP.UnsignedFingerPrint.
- """
- global UnsignedFingerPrint
- original_function_object = UnsignedFingerPrint
- UnsignedFingerPrint = function_object
- return original_function_object
diff --git a/grit/extern/__init__.py b/grit/extern/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/grit/extern/__init__.py
+++ /dev/null
diff --git a/grit/extern/tclib.py b/grit/extern/tclib.py
deleted file mode 100644
index e84f177..0000000
--- a/grit/extern/tclib.py
+++ /dev/null
@@ -1,503 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# The tclib module contains tools for aggregating, verifying, and storing
-# messages destined for the Translation Console, as well as for reading
-# translations back and outputting them in some desired format.
-#
-# This has been stripped down to include only the functionality needed by grit
-# for creating Windows .rc and .h files. These are the only parts needed by
-# the Chrome build process.
-
-import exceptions
-
-from grit.extern import FP
-
-# This module assumes that within a bundle no two messages can have the
-# same id unless they're identical.
-
-# The basic classes defined here for external use are Message and Translation,
-# where the former is used for English messages and the latter for
-# translations. These classes have a lot of common functionality, as expressed
-# by the common parent class BaseMessage. Perhaps the most important
-# distinction is that translated text is stored in UTF-8, whereas original text
-# is stored in whatever encoding the client uses (presumably Latin-1).
-
-# --------------------
-# The public interface
-# --------------------
-
-# Generate message id from message text and meaning string (optional),
-# both in utf-8 encoding
-#
-def GenerateMessageId(message, meaning=''):
- fp = FP.FingerPrint(message)
- if meaning:
- # combine the fingerprints of message and meaning
- fp2 = FP.FingerPrint(meaning)
- if fp < 0:
- fp = fp2 + (fp << 1) + 1
- else:
- fp = fp2 + (fp << 1)
- # To avoid negative ids we strip the high-order bit
- return str(fp & 0x7fffffffffffffffL)
-
-# -------------------------------------------------------------------------
-# The MessageTranslationError class is used to signal tclib-specific errors.
-
-class MessageTranslationError(exceptions.Exception):
- def __init__(self, args = ''):
- self.args = args
-
-
-# -----------------------------------------------------------
-# The Placeholder class represents a placeholder in a message.
-
-class Placeholder(object):
- # String representation
- def __str__(self):
- return '%s, "%s", "%s"' % \
- (self.__presentation, self.__original, self.__example)
-
- # Getters
- def GetOriginal(self):
- return self.__original
-
- def GetPresentation(self):
- return self.__presentation
-
- def GetExample(self):
- return self.__example
-
- def __eq__(self, other):
- return self.EqualTo(other, strict=1, ignore_trailing_spaces=0)
-
- # Equality test
- #
- # ignore_trailing_spaces: TC is using varchar to store the
- # phrwr fields, as a result of that, the trailing spaces
- # are removed by MySQL when the strings are stored into TC:-(
- # ignore_trailing_spaces parameter is used to ignore
- # trailing spaces during equivalence comparison.
- #
- def EqualTo(self, other, strict = 1, ignore_trailing_spaces = 1):
- if type(other) is not Placeholder:
- return 0
- if StringEquals(self.__presentation, other.__presentation,
- ignore_trailing_spaces):
- if not strict or (StringEquals(self.__original, other.__original,
- ignore_trailing_spaces) and
- StringEquals(self.__example, other.__example,
- ignore_trailing_spaces)):
- return 1
- return 0
-
-
-# -----------------------------------------------------------------
-# BaseMessage is the common parent class of Message and Translation.
-# It is not meant for direct use.
-
-class BaseMessage(object):
- # Three types of message construction is supported. If the message text is a
- # simple string with no dynamic content, you can pass it to the constructor
- # as the "text" parameter. Otherwise, you can omit "text" and assemble the
- # message step by step using AppendText() and AppendPlaceholder(). Or, as an
- # alternative, you can give the constructor the "presentable" version of the
- # message and a list of placeholders; it will then parse the presentation and
- # build the message accordingly. For example:
- # Message(text = "There are NUM_BUGS bugs in your code",
- # placeholders = [Placeholder("NUM_BUGS", "%d", "33")],
- # description = "Bla bla bla")
- def __eq__(self, other):
- # "source encoding" is nonsense, so ignore it
- return _ObjectEquals(self, other, ['_BaseMessage__source_encoding'])
-
- def GetName(self):
- return self.__name
-
- def GetSourceEncoding(self):
- return self.__source_encoding
-
- # Append a placeholder to the message
- def AppendPlaceholder(self, placeholder):
- if not isinstance(placeholder, Placeholder):
- raise MessageTranslationError, ("Invalid message placeholder %s in "
- "message %s" % (placeholder, self.GetId()))
- # Are there other placeholders with the same presentation?
- # If so, they need to be the same.
- for other in self.GetPlaceholders():
- if placeholder.GetPresentation() == other.GetPresentation():
- if not placeholder.EqualTo(other):
- raise MessageTranslationError, \
- "Conflicting declarations of %s within message" % \
- placeholder.GetPresentation()
- # update placeholder list
- dup = 0
- for item in self.__content:
- if isinstance(item, Placeholder) and placeholder.EqualTo(item):
- dup = 1
- break
- if not dup:
- self.__placeholders.append(placeholder)
-
- # update content
- self.__content.append(placeholder)
-
- # Strips leading and trailing whitespace, and returns a tuple
- # containing the leading and trailing space that was removed.
- def Strip(self):
- leading = trailing = ''
- if len(self.__content) > 0:
- s0 = self.__content[0]
- if not isinstance(s0, Placeholder):
- s = s0.lstrip()
- leading = s0[:-len(s)]
- self.__content[0] = s
-
- s0 = self.__content[-1]
- if not isinstance(s0, Placeholder):
- s = s0.rstrip()
- trailing = s0[len(s):]
- self.__content[-1] = s
- return leading, trailing
-
- # Return the id of this message
- def GetId(self):
- if self.__id is None:
- return self.GenerateId()
- return self.__id
-
- # Set the id of this message
- def SetId(self, id):
- if id is None:
- self.__id = None
- else:
- self.__id = str(id) # Treat numerical ids as strings
-
- # Return content of this message as a list (internal use only)
- def GetContent(self):
- return self.__content
-
- # Return a human-readable version of this message
- def GetPresentableContent(self):
- presentable_content = ""
- for item in self.__content:
- if isinstance(item, Placeholder):
- presentable_content += item.GetPresentation()
- else:
- presentable_content += item
-
- return presentable_content
-
- # Return a fragment of a message in escaped format
- def EscapeFragment(self, fragment):
- return fragment.replace('%', '%%')
-
- # Return the "original" version of this message, doing %-escaping
- # properly. If source_msg is specified, the placeholder original
- # information inside source_msg will be used instead.
- def GetOriginalContent(self, source_msg = None):
- original_content = ""
- for item in self.__content:
- if isinstance(item, Placeholder):
- if source_msg:
- ph = source_msg.GetPlaceholder(item.GetPresentation())
- if not ph:
- raise MessageTranslationError, \
- "Placeholder %s doesn't exist in message: %s" % \
- (item.GetPresentation(), source_msg);
- original_content += ph.GetOriginal()
- else:
- original_content += item.GetOriginal()
- else:
- original_content += self.EscapeFragment(item)
- return original_content
-
- # Return the example of this message
- def GetExampleContent(self):
- example_content = ""
- for item in self.__content:
- if isinstance(item, Placeholder):
- example_content += item.GetExample()
- else:
- example_content += item
- return example_content
-
- # Return a list of all unique placeholders in this message
- def GetPlaceholders(self):
- return self.__placeholders
-
- # Return a placeholder in this message
- def GetPlaceholder(self, presentation):
- for item in self.__content:
- if (isinstance(item, Placeholder) and
- item.GetPresentation() == presentation):
- return item
- return None
-
- # Return this message's description
- def GetDescription(self):
- return self.__description
-
- # Add a message source
- def AddSource(self, source):
- self.__sources.append(source)
-
- # Return this message's sources as a list
- def GetSources(self):
- return self.__sources
-
- # Return this message's sources as a string
- def GetSourcesAsText(self, delimiter = "; "):
- return delimiter.join(self.__sources)
-
- # Set the obsolete flag for a message (internal use only)
- def SetObsolete(self):
- self.__obsolete = 1
-
- # Get the obsolete flag for a message (internal use only)
- def IsObsolete(self):
- return self.__obsolete
-
- # Get the sequence number (0 by default)
- def GetSequenceNumber(self):
- return self.__sequence_number
-
- # Set the sequence number
- def SetSequenceNumber(self, number):
- self.__sequence_number = number
-
- # Increment instance counter
- def AddInstance(self):
- self.__num_instances += 1
-
- # Return instance count
- def GetNumInstances(self):
- return self.__num_instances
-
- def GetErrors(self, from_tc=0):
- """
- Returns a description of the problem if the message is not
- syntactically valid, or None if everything is fine.
-
- Args:
- from_tc: indicates whether this message came from the TC. We let
- the TC get away with some things we normally wouldn't allow for
- historical reasons.
- """
- # check that placeholders are unambiguous
- pos = 0
- phs = {}
- for item in self.__content:
- if isinstance(item, Placeholder):
- phs[pos] = item
- pos += len(item.GetPresentation())
- else:
- pos += len(item)
- presentation = self.GetPresentableContent()
- for ph in self.GetPlaceholders():
- for pos in FindOverlapping(presentation, ph.GetPresentation()):
- # message contains the same text as a placeholder presentation
- other_ph = phs.get(pos)
- if ((not other_ph
- and not IsSubstringInPlaceholder(pos, len(ph.GetPresentation()), phs))
- or
- (other_ph and len(other_ph.GetPresentation()) < len(ph.GetPresentation()))):
- return "message contains placeholder name '%s':\n%s" % (
- ph.GetPresentation(), presentation)
- return None
-
-
- def __CopyTo(self, other):
- """
- Returns a copy of this BaseMessage.
- """
- assert isinstance(other, self.__class__) or isinstance(self, other.__class__)
- other.__source_encoding = self.__source_encoding
- other.__content = self.__content[:]
- other.__description = self.__description
- other.__id = self.__id
- other.__num_instances = self.__num_instances
- other.__obsolete = self.__obsolete
- other.__name = self.__name
- other.__placeholders = self.__placeholders[:]
- other.__sequence_number = self.__sequence_number
- other.__sources = self.__sources[:]
-
- return other
-
- def HasText(self):
- """Returns true iff this message has anything other than placeholders."""
- for item in self.__content:
- if not isinstance(item, Placeholder):
- return True
- return False
-
-# --------------------------------------------------------
-# The Message class represents original (English) messages
-
-class Message(BaseMessage):
- # See BaseMessage constructor
- def __init__(self, source_encoding, text=None, id=None,
- description=None, meaning="", placeholders=None,
- source=None, sequence_number=0, clone_from=None,
- time_created=0, name=None, is_hidden = 0):
-
- if clone_from is not None:
- BaseMessage.__init__(self, None, clone_from=clone_from)
- self.__meaning = clone_from.__meaning
- self.__time_created = clone_from.__time_created
- self.__is_hidden = clone_from.__is_hidden
- return
-
- BaseMessage.__init__(self, source_encoding, text, id, description,
- placeholders, source, sequence_number,
- name=name)
- self.__meaning = meaning
- self.__time_created = time_created
- self.SetIsHidden(is_hidden)
-
- # String representation
- def __str__(self):
- s = 'source: %s, id: %s, content: "%s", meaning: "%s", ' \
- 'description: "%s"' % \
- (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
- self.__meaning, self.GetDescription())
- if self.GetName() is not None:
- s += ', name: "%s"' % self.GetName()
- placeholders = self.GetPlaceholders()
- for i in range(len(placeholders)):
- s += ", placeholder[%d]: %s" % (i, placeholders[i])
- return s
-
- # Strips leading and trailing whitespace, and returns a tuple
- # containing the leading and trailing space that was removed.
- def Strip(self):
- leading = trailing = ''
- content = self.GetContent()
- if len(content) > 0:
- s0 = content[0]
- if not isinstance(s0, Placeholder):
- s = s0.lstrip()
- leading = s0[:-len(s)]
- content[0] = s
-
- s0 = content[-1]
- if not isinstance(s0, Placeholder):
- s = s0.rstrip()
- trailing = s0[len(s):]
- content[-1] = s
- return leading, trailing
-
- # Generate an id by hashing message content
- def GenerateId(self):
- self.SetId(GenerateMessageId(self.GetPresentableContent(),
- self.__meaning))
- return self.GetId()
-
- def GetMeaning(self):
- return self.__meaning
-
- def GetTimeCreated(self):
- return self.__time_created
-
- # Equality operator
- def EqualTo(self, other, strict = 1):
- # Check id, meaning, content
- if self.GetId() != other.GetId():
- return 0
- if self.__meaning != other.__meaning:
- return 0
- if self.GetPresentableContent() != other.GetPresentableContent():
- return 0
- # Check descriptions if comparison is strict
- if (strict and
- self.GetDescription() is not None and
- other.GetDescription() is not None and
- self.GetDescription() != other.GetDescription()):
- return 0
- # Check placeholders
- ph1 = self.GetPlaceholders()
- ph2 = other.GetPlaceholders()
- if len(ph1) != len(ph2):
- return 0
- for i in range(len(ph1)):
- if not ph1[i].EqualTo(ph2[i], strict):
- return 0
-
- return 1
-
- def Copy(self):
- """
- Returns a copy of this Message.
- """
- assert isinstance(self, Message)
- return Message(None, clone_from=self)
-
- def SetIsHidden(self, is_hidden):
- """Sets whether this message should be hidden.
-
- Args:
- is_hidden : 0 or 1 - if the message should be hidden, 0 otherwise
- """
- if is_hidden not in [0, 1]:
- raise MessageTranslationError, "is_hidden must be 0 or 1, got %s"
- self.__is_hidden = is_hidden
-
- def IsHidden(self):
- """Returns 1 if this message is hidden, and 0 otherwise."""
- return self.__is_hidden
-
-# ----------------------------------------------------
-# The Translation class represents translated messages
-
-class Translation(BaseMessage):
- # See BaseMessage constructor
- def __init__(self, source_encoding, text=None, id=None,
- description=None, placeholders=None, source=None,
- sequence_number=0, clone_from=None, ignore_ph_errors=0,
- name=None):
- if clone_from is not None:
- BaseMessage.__init__(self, None, clone_from=clone_from)
- return
-
- BaseMessage.__init__(self, source_encoding, text, id, description,
- placeholders, source, sequence_number,
- ignore_ph_errors=ignore_ph_errors, name=name)
-
- # String representation
- def __str__(self):
- s = 'source: %s, id: %s, content: "%s", description: "%s"' % \
- (self.GetSourcesAsText(), self.GetId(), self.GetPresentableContent(),
- self.GetDescription());
- placeholders = self.GetPlaceholders()
- for i in range(len(placeholders)):
- s += ", placeholder[%d]: %s" % (i, placeholders[i])
- return s
-
- # Equality operator
- def EqualTo(self, other, strict=1):
- # Check id and content
- if self.GetId() != other.GetId():
- return 0
- if self.GetPresentableContent() != other.GetPresentableContent():
- return 0
- # Check placeholders
- ph1 = self.GetPlaceholders()
- ph2 = other.GetPlaceholders()
- if len(ph1) != len(ph2):
- return 0
- for i in range(len(ph1)):
- if not ph1[i].EqualTo(ph2[i], strict):
- return 0
-
- return 1
-
- def Copy(self):
- """
- Returns a copy of this Translation.
- """
- return Translation(None, clone_from=self)
-
diff --git a/grit/format/__init__.py b/grit/format/__init__.py
deleted file mode 100644
index 2a3c59c..0000000
--- a/grit/format/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Module grit.format
-'''
-
-pass
-
diff --git a/grit/format/android_xml.py b/grit/format/android_xml.py
deleted file mode 100644
index be9d795..0000000
--- a/grit/format/android_xml.py
+++ /dev/null
@@ -1,200 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Produces localized strings.xml files for Android.
-
-In cases where an "android" type output file is requested in a grd, the classes
-in android_xml will process the messages and translations to produce a valid
-strings.xml that is properly localized with the specified language.
-
-For example if the following output tag were to be included in a grd file
- <outputs>
- ...
- <output filename="values-es/strings.xml" type="android" lang="es" />
- ...
- </outputs>
-
-for a grd file with the following messages:
-
- <message name="IDS_HELLO" desc="Simple greeting">Hello</message>
- <message name="IDS_WORLD" desc="The world">world</message>
-
-and there existed an appropriate xtb file containing the Spanish translations,
-then the output would be:
-
- <?xml version="1.0" encoding="utf-8"?>
- <resources xmlns:android="http://schemas.android.com/apk/res/android">
- <string name="hello">"Hola"</string>
- <string name="world">"mundo"</string>
- </resources>
-
-which would be written to values-es/strings.xml and usable by the Android
-resource framework.
-
-Advanced usage
---------------
-
-To process only certain messages in a grd file, tag each desired message by
-adding "android_java" to formatter_data. Then set the environmental variable
-ANDROID_JAVA_TAGGED_ONLY to "true" when building the grd file. For example:
-
- <message name="IDS_HELLO" formatter_data="android_java">Hello</message>
-
-To generate Android plurals (aka "quantity strings"), use the ICU plural syntax
-in the grd file. This will automatically be transformed into a <purals> element
-in the output xml file. For example:
-
- <message name="IDS_CATS">
- {NUM_CATS, plural,
- =1 {1 cat}
- other {# cats}}
- </message>
-
- will produce
-
- <plurals name="cats">
- <item quantity="one">1 Katze</item>
- <item quantity="other">%d Katzen</item>
- </plurals>
-"""
-
-import os
-import re
-import types
-import xml.sax.saxutils
-
-from grit import lazy_re
-from grit.node import message
-
-
-# When this environmental variable has value "true", only tagged messages will
-# be outputted.
-_TAGGED_ONLY_ENV_VAR = 'ANDROID_JAVA_TAGGED_ONLY'
-_TAGGED_ONLY_DEFAULT = False
-
-# In tagged-only mode, only messages with this tag will be ouputted.
-_EMIT_TAG = 'android_java'
-
-_NAME_PATTERN = lazy_re.compile('IDS_(?P<name>[A-Z0-9_]+)\Z')
-
-# Most strings are output as a <string> element. Note the double quotes
-# around the value to preserve whitespace.
-_STRING_TEMPLATE = u'<string name="%s">"%s"</string>\n'
-
-# Some strings are output as a <plurals> element.
-_PLURALS_TEMPLATE = '<plurals name="%s">\n%s</plurals>\n'
-_PLURALS_ITEM_TEMPLATE = ' <item quantity="%s">%s</item>\n'
-_PLURALS_PATTERN = lazy_re.compile(r'\{[A-Z_]+,\s*plural,(?P<items>.*)\}$', flags=re.S)
-_PLURALS_ITEM_PATTERN = lazy_re.compile(r'(?P<quantity>\S+)\s*\{(?P<value>.*?)\}')
-_PLURALS_QUANTITY_MAP = {
- '=0': 'zero',
- 'zero': 'zero',
- '=1': 'one',
- 'one': 'one',
- '=2': 'two',
- 'two': 'two',
- 'few': 'few',
- 'many': 'many',
- 'other': 'other',
-}
-
-
-def Format(root, lang='en', output_dir='.'):
- yield ('<?xml version="1.0" encoding="utf-8"?>\n'
- '<resources '
- 'xmlns:android="http://schemas.android.com/apk/res/android">\n')
-
- tagged_only = _TAGGED_ONLY_DEFAULT
- if _TAGGED_ONLY_ENV_VAR in os.environ:
- tagged_only = os.environ[_TAGGED_ONLY_ENV_VAR].lower()
- if tagged_only == 'true':
- tagged_only = True
- elif tagged_only == 'false':
- tagged_only = False
- else:
- raise Exception('env variable ANDROID_JAVA_TAGGED_ONLY must have value '
- 'true or false. Invalid value: %s' % tagged_only)
-
- for item in root.ActiveDescendants():
- with item:
- if ShouldOutputNode(item, tagged_only):
- yield _FormatMessage(item, lang)
-
- yield '</resources>\n'
-
-
-def ShouldOutputNode(node, tagged_only):
- """Returns true if node should be outputted.
-
- Args:
- node: a Node from the grd dom
- tagged_only: true, if only tagged messages should be outputted
- """
- return (isinstance(node, message.MessageNode) and
- (not tagged_only or _EMIT_TAG in node.formatter_data))
-
-
-def _FormatPluralMessage(message):
- """Compiles ICU plural syntax to the body of an Android <plurals> element.
-
- 1. In a .grd file, we can write a plural string like this:
-
- <message name="IDS_THINGS">
- {NUM_THINGS, plural,
- =1 {1 thing}
- other {# things}}
- </message>
-
- 2. The Android equivalent looks like this:
-
- <plurals name="things">
- <item quantity="one">1 thing</item>
- <item quantity="other">%d things</item>
- </plurals>
-
- This method takes the body of (1) and converts it to the body of (2).
-
- If the message is *not* a plural string, this function returns `None`.
- If the message includes quantities without an equivalent format in Android,
- it raises an exception.
- """
- ret = {}
- plural_match = _PLURALS_PATTERN.match(message)
- if not plural_match:
- return None
- body_in = plural_match.group('items').strip()
- lines = []
- for item_match in _PLURALS_ITEM_PATTERN.finditer(body_in):
- quantity_in = item_match.group('quantity')
- quantity_out = _PLURALS_QUANTITY_MAP.get(quantity_in)
- value_in = item_match.group('value')
- value_out = '"' + value_in.replace('#', '%d') + '"'
- if quantity_out:
- lines.append(_PLURALS_ITEM_TEMPLATE % (quantity_out, value_out))
- else:
- raise Exception('Unsupported plural quantity for android '
- 'strings.xml: %s' % quantity_in)
- return ''.join(lines)
-
-
-def _FormatMessage(item, lang):
- """Writes out a single string as a <resource/> element."""
-
- mangled_name = item.GetTextualIds()[0]
- match = _NAME_PATTERN.match(mangled_name)
- if not match:
- raise Exception('Unexpected resource name: %s' % mangled_name)
- name = match.group('name').lower()
-
- value = item.ws_at_start + item.Translate(lang) + item.ws_at_end
- # Replace < > & with &lt; &gt; &amp; to ensure we generate valid XML and
- # replace ' " with \' \" to conform to Android's string formatting rules.
- value = xml.sax.saxutils.escape(value, {"'": "\\'", '"': '\\"'})
-
- plurals = _FormatPluralMessage(value)
- if plurals:
- return _PLURALS_TEMPLATE % (name, plurals)
- else:
- return _STRING_TEMPLATE % (name, value)
diff --git a/grit/format/android_xml_unittest.py b/grit/format/android_xml_unittest.py
deleted file mode 100644
index cdec6c9..0000000
--- a/grit/format/android_xml_unittest.py
+++ /dev/null
@@ -1,110 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Unittest for android_xml.py."""
-
-import os
-import StringIO
-import sys
-import unittest
-
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-from grit import util
-from grit.format import android_xml
-from grit.node import message
-from grit.tool import build
-
-
-class AndroidXmlUnittest(unittest.TestCase):
-
- def testMessages(self):
- root = util.ParseGrdForUnittest(ur"""
- <messages>
- <message name="IDS_SIMPLE" desc="A vanilla string">
- Martha
- </message>
- <message name="IDS_ONE_LINE" desc="On one line">sat and wondered</message>
- <message name="IDS_QUOTES" desc="A string with quotation marks">
- out loud, "Why don't I build a flying car?"
- </message>
- <message name="IDS_MULTILINE" desc="A string split over several lines">
- She gathered
-wood, charcoal, and
-a sledge hammer.
- </message>
- <message name="IDS_WHITESPACE" desc="A string with extra whitespace.">
- ''' How old fashioned -- she thought. '''
- </message>
- <message name="IDS_PLACEHOLDERS" desc="A string with placeholders">
- I'll buy a <ph name="WAVELENGTH">%d<ex>200</ex></ph> nm laser at <ph name="STORE_NAME">%s<ex>the grocery store</ex></ph>.
- </message>
- <message name="IDS_PLURALS" desc="A string using the ICU plural format">
- {NUM_THINGS, plural,
- =1 {Maybe I'll get one laser.}
- other {Maybe I'll get # lasers.}}
- </message>
- </messages>
- """)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('android', 'en'), buf)
- output = buf.getvalue()
- expected = ur"""
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
-<string name="simple">"Martha"</string>
-<string name="one_line">"sat and wondered"</string>
-<string name="quotes">"out loud, \"Why don\'t I build a flying car?\""</string>
-<string name="multiline">"She gathered
-wood, charcoal, and
-a sledge hammer."</string>
-<string name="whitespace">" How old fashioned -- she thought. "</string>
-<string name="placeholders">"I\'ll buy a %d nm laser at %s."</string>
-<plurals name="plurals">
- <item quantity="one">"Maybe I\'ll get one laser."</item>
- <item quantity="other">"Maybe I\'ll get %d lasers."</item>
-</plurals>
-</resources>
-"""
- self.assertEqual(output.strip(), expected.strip())
-
- def testTaggedOnly(self):
- root = util.ParseGrdForUnittest(ur"""
- <messages>
- <message name="IDS_HELLO" desc="" formatter_data="android_java">
- Hello
- </message>
- <message name="IDS_WORLD" desc="">
- world
- </message>
- </messages>
- """)
-
- msg_hello, msg_world = root.GetChildrenOfType(message.MessageNode)
- self.assertTrue(android_xml.ShouldOutputNode(msg_hello, tagged_only=True))
- self.assertFalse(android_xml.ShouldOutputNode(msg_world, tagged_only=True))
- self.assertTrue(android_xml.ShouldOutputNode(msg_hello, tagged_only=False))
- self.assertTrue(android_xml.ShouldOutputNode(msg_world, tagged_only=False))
-
-
-class DummyOutput(object):
-
- def __init__(self, type, language):
- self.type = type
- self.language = language
-
- def GetType(self):
- return self.type
-
- def GetLanguage(self):
- return self.language
-
- def GetOutputFilename(self):
- return 'hello.gif'
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/c_format.py b/grit/format/c_format.py
deleted file mode 100644
index 5e10b98..0000000
--- a/grit/format/c_format.py
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Formats as a .C file for compilation.
-"""
-
-import os
-import re
-import types
-
-from grit import util
-
-
-def _FormatHeader(root, output_dir):
- """Returns the required preamble for C files."""
- # Find the location of the resource header file, so that we can include
- # it.
- resource_header = 'resource.h' # fall back to this
- for output in root.GetOutputFiles():
- if output.attrs['type'] == 'rc_header':
- resource_header = os.path.abspath(output.GetOutputFilename())
- resource_header = util.MakeRelativePath(output_dir, resource_header)
- return """// This file is automatically generated by GRIT. Do not edit.
-
-#include "%s"
-
-// All strings are UTF-8
-""" % (resource_header)
-# end _FormatHeader() function
-
-
-def Format(root, lang='en', output_dir='.'):
- """Outputs a C switch statement representing the string table."""
- from grit.node import message
- assert isinstance(lang, types.StringTypes)
-
- yield _FormatHeader(root, output_dir)
-
- yield 'const char* GetString(int id) {\n switch (id) {'
-
- for item in root.ActiveDescendants():
- with item:
- if isinstance(item, message.MessageNode):
- yield _FormatMessage(item, lang)
-
- yield '\n default:\n return 0;\n }\n}\n'
-
-
-def _HexToOct(match):
- "Return the octal form of the hex numbers"
- hex = match.group("hex")
- result = ""
- while len(hex):
- next_num = int(hex[2:4], 16)
- result += "\\" + '%03d' % int(oct(next_num), 10)
- hex = hex[4:]
- return match.group("escaped_backslashes") + result
-
-
-def _FormatMessage(item, lang):
- """Format a single <message> element."""
-
- message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
- # output message with non-ascii chars escaped as octal numbers
- # C's grammar allows escaped hexadecimal numbers to be infinite,
- # but octal is always of the form \OOO
- message = message.encode('utf-8').encode('string_escape')
- # an escaped char is (\xHH)+ but only if the initial
- # backslash is not escaped.
- not_a_backslash = r"(^|[^\\])" # beginning of line or a non-backslash char
- escaped_backslashes = not_a_backslash + r"(\\\\)*"
- hex_digits = r"((\\x)[0-9a-f]{2})+"
- two_digit_hex_num = re.compile(
- r"(?P<escaped_backslashes>%s)(?P<hex>%s)"
- % (escaped_backslashes, hex_digits))
- message = two_digit_hex_num.sub(_HexToOct, message)
- # unescape \ (convert \\ back to \)
- message = message.replace('\\\\', '\\')
- message = message.replace('"', '\\"')
- message = util.LINEBREAKS.sub(r'\\n', message)
-
- name_attr = item.GetTextualIds()[0]
-
- return '\n case %s:\n return "%s";' % (name_attr, message)
diff --git a/grit/format/c_format_unittest.py b/grit/format/c_format_unittest.py
deleted file mode 100644
index ba1c5c7..0000000
--- a/grit/format/c_format_unittest.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Unittest for c_format.py.
-"""
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import unittest
-import StringIO
-
-from grit import util
-from grit.tool import build
-
-
-class CFormatUnittest(unittest.TestCase):
-
- def testMessages(self):
- root = util.ParseGrdForUnittest("""
- <messages>
- <message name="IDS_QUESTIONS">Do you want to play questions?</message>
- <message name="IDS_QUOTES">
- "What's in a name, <ph name="NAME">%s<ex>Brandon</ex></ph>?"
- </message>
- <message name="IDS_LINE_BREAKS">
- Was that rhetoric?
-No.
-Statement. Two all. Game point.
-</message>
- <message name="IDS_NON_ASCII">
- \xc3\xb5\\xc2\\xa4\\\xc2\xa4\\\\xc3\\xb5\xe4\xa4\xa4
- </message>
- </messages>
- """)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('c_format', 'en'), buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- self.assertEqual(u"""\
-#include "resource.h"
-const char* GetString(int id) {
- switch (id) {
- case IDS_QUESTIONS:
- return "Do you want to play questions?";
- case IDS_QUOTES:
- return "\\"What\\'s in a name, %s?\\"";
- case IDS_LINE_BREAKS:
- return "Was that rhetoric?\\nNo.\\nStatement. Two all. Game point.";
- case IDS_NON_ASCII:
- return "\\303\\265\\xc2\\xa4\\\\302\\244\\\\xc3\\xb5\\344\\244\\244";
- default:
- return 0;
- }
-}""", output)
-
-
-class DummyOutput(object):
-
- def __init__(self, type, language):
- self.type = type
- self.language = language
-
- def GetType(self):
- return self.type
-
- def GetLanguage(self):
- return self.language
-
- def GetOutputFilename(self):
- return 'hello.gif'
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/chrome_messages_json.py b/grit/format/chrome_messages_json.py
deleted file mode 100644
index be934ab..0000000
--- a/grit/format/chrome_messages_json.py
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Formats as a .json file that can be used to localize Google Chrome
-extensions."""
-
-from json import JSONEncoder
-import re
-import types
-
-from grit import util
-from grit.node import message
-
-def Format(root, lang='en', output_dir='.'):
- """Format the messages as JSON."""
- yield '{\n'
-
- encoder = JSONEncoder();
- format = (' "%s": {\n'
- ' "message": %s\n'
- ' }')
- first = True
- for child in root.ActiveDescendants():
- if isinstance(child, message.MessageNode):
- id = child.attrs['name']
- if id.startswith('IDR_') or id.startswith('IDS_'):
- id = id[4:]
-
- loc_message = encoder.encode(child.ws_at_start + child.Translate(lang) +
- child.ws_at_end)
-
- if not first:
- yield ',\n'
- first = False
- yield format % (id, loc_message)
-
- yield '\n}\n'
diff --git a/grit/format/chrome_messages_json_unittest.py b/grit/format/chrome_messages_json_unittest.py
deleted file mode 100644
index 373751e..0000000
--- a/grit/format/chrome_messages_json_unittest.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Unittest for chrome_messages_json.py.
-"""
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import unittest
-import StringIO
-
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-class ChromeMessagesJsonFormatUnittest(unittest.TestCase):
-
- def testMessages(self):
- root = util.ParseGrdForUnittest(u"""
- <messages>
- <message name="IDS_SIMPLE_MESSAGE">
- Simple message.
- </message>
- <message name="IDS_QUOTES">
- element\u2019s \u201c<ph name="NAME">%s<ex>name</ex></ph>\u201d attribute
- </message>
- <message name="IDS_PLACEHOLDERS">
- <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
- </message>
- <message name="IDS_STARTS_WITH_SPACE">
- ''' (<ph name="COUNT">%d<ex>2</ex></ph>)
- </message>
- <message name="IDS_ENDS_WITH_SPACE">
- (<ph name="COUNT">%d<ex>2</ex></ph>) '''
- </message>
- <message name="IDS_SPACE_AT_BOTH_ENDS">
- ''' (<ph name="COUNT">%d<ex>2</ex></ph>) '''
- </message>
- <message name="IDS_DOUBLE_QUOTES">
- A "double quoted" message.
- </message>
- <message name="IDS_BACKSLASH">
- \\
- </message>
- </messages>
- """)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'en'), buf)
- output = buf.getvalue()
- test = u"""
-{
- "SIMPLE_MESSAGE": {
- "message": "Simple message."
- },
- "QUOTES": {
- "message": "element\\u2019s \\u201c%s\\u201d attribute"
- },
- "PLACEHOLDERS": {
- "message": "%1$d error, %2$d warning"
- },
- "STARTS_WITH_SPACE": {
- "message": " (%d)"
- },
- "ENDS_WITH_SPACE": {
- "message": "(%d) "
- },
- "SPACE_AT_BOTH_ENDS": {
- "message": " (%d) "
- },
- "DOUBLE_QUOTES": {
- "message": "A \\"double quoted\\" message."
- },
- "BACKSLASH": {
- "message": "\\\\"
- }
-}
-"""
- self.assertEqual(test.strip(), output.strip())
-
- def testTranslations(self):
- root = util.ParseGrdForUnittest("""
- <messages>
- <message name="ID_HELLO">Hello!</message>
- <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
- Joi</ex></ph></message>
- </messages>
- """)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('chrome_messages_json', 'fr'), buf)
- output = buf.getvalue()
- test = u"""
-{
- "ID_HELLO": {
- "message": "H\\u00e9P\\u00e9ll\\u00f4P\\u00f4!"
- },
- "ID_HELLO_USER": {
- "message": "H\\u00e9P\\u00e9ll\\u00f4P\\u00f4 %s"
- }
-}
-"""
- self.assertEqual(test.strip(), output.strip())
-
-
-class DummyOutput(object):
-
- def __init__(self, type, language):
- self.type = type
- self.language = language
-
- def GetType(self):
- return self.type
-
- def GetLanguage(self):
- return self.language
-
- def GetOutputFilename(self):
- return 'hello.gif'
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/data_pack.py b/grit/format/data_pack.py
deleted file mode 100755
index 02616c3..0000000
--- a/grit/format/data_pack.py
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Support for formatting a data pack file used for platform agnostic resource
-files.
-"""
-
-import collections
-import exceptions
-import os
-import struct
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-from grit import util
-from grit.node import include
-from grit.node import message
-from grit.node import structure
-
-
-PACK_FILE_VERSION = 4
-HEADER_LENGTH = 2 * 4 + 1 # Two uint32s. (file version, number of entries) and
- # one uint8 (encoding of text resources)
-BINARY, UTF8, UTF16 = range(3)
-
-
-class WrongFileVersion(Exception):
- pass
-
-
-DataPackContents = collections.namedtuple(
- 'DataPackContents', 'resources encoding')
-
-
-def Format(root, lang='en', output_dir='.'):
- """Writes out the data pack file format (platform agnostic resource file)."""
- data = {}
- for node in root.ActiveDescendants():
- with node:
- if isinstance(node, (include.IncludeNode, message.MessageNode,
- structure.StructureNode)):
- id, value = node.GetDataPackPair(lang, UTF8)
- if value is not None:
- data[id] = value
- return WriteDataPackToString(data, UTF8)
-
-
-def ReadDataPack(input_file):
- """Reads a data pack file and returns a dictionary."""
- data = util.ReadFile(input_file, util.BINARY)
- original_data = data
-
- # Read the header.
- version, num_entries, encoding = struct.unpack('<IIB', data[:HEADER_LENGTH])
- if version != PACK_FILE_VERSION:
- print 'Wrong file version in ', input_file
- raise WrongFileVersion
-
- resources = {}
- if num_entries == 0:
- return DataPackContents(resources, encoding)
-
- # Read the index and data.
- data = data[HEADER_LENGTH:]
- kIndexEntrySize = 2 + 4 # Each entry is a uint16 and a uint32.
- for _ in range(num_entries):
- id, offset = struct.unpack('<HI', data[:kIndexEntrySize])
- data = data[kIndexEntrySize:]
- next_id, next_offset = struct.unpack('<HI', data[:kIndexEntrySize])
- resources[id] = original_data[offset:next_offset]
-
- return DataPackContents(resources, encoding)
-
-
-def WriteDataPackToString(resources, encoding):
- """Returns a string with a map of id=>data in the data pack format."""
- ids = sorted(resources.keys())
- ret = []
-
- # Write file header.
- ret.append(struct.pack('<IIB', PACK_FILE_VERSION, len(ids), encoding))
- HEADER_LENGTH = 2 * 4 + 1 # Two uint32s and one uint8.
-
- # Each entry is a uint16 + a uint32s. We have one extra entry for the last
- # item.
- index_length = (len(ids) + 1) * (2 + 4)
-
- # Write index.
- data_offset = HEADER_LENGTH + index_length
- for id in ids:
- ret.append(struct.pack('<HI', id, data_offset))
- data_offset += len(resources[id])
-
- ret.append(struct.pack('<HI', 0, data_offset))
-
- # Write data.
- for id in ids:
- ret.append(resources[id])
- return ''.join(ret)
-
-
-def WriteDataPack(resources, output_file, encoding):
- """Writes a map of id=>data into output_file as a data pack."""
- content = WriteDataPackToString(resources, encoding)
- with open(output_file, 'wb') as file:
- file.write(content)
-
-
-def RePack(output_file, input_files, whitelist_file=None):
- """Write a new data pack file by combining input pack files.
-
- Args:
- output_file: path to the new data pack file.
- input_files: a list of paths to the data pack files to combine.
- whitelist_file: path to the file that contains the list of resource IDs
- that should be kept in the output file or None to include
- all resources.
-
- Raises:
- KeyError: if there are duplicate keys or resource encoding is
- inconsistent.
- """
- input_data_packs = [ReadDataPack(filename) for filename in input_files]
- whitelist = None
- if whitelist_file:
- whitelist = util.ReadFile(whitelist_file, util.RAW_TEXT).strip().split('\n')
- whitelist = set(map(int, whitelist))
- resources, encoding = RePackFromDataPackStrings(input_data_packs, whitelist)
- WriteDataPack(resources, output_file, encoding)
-
-
-def RePackFromDataPackStrings(inputs, whitelist):
- """Returns a data pack string that combines the resources from inputs.
-
- Args:
- inputs: a list of data pack strings that need to be combined.
- whitelist: a list of resource IDs that should be kept in the output string
- or None to include all resources.
-
- Returns:
- DataPackContents: a tuple containing the new combined data pack and its
- encoding.
-
- Raises:
- KeyError: if there are duplicate keys or resource encoding is
- inconsistent.
- """
- resources = {}
- encoding = None
- for content in inputs:
- # Make sure we have no dups.
- duplicate_keys = set(content.resources.keys()) & set(resources.keys())
- if duplicate_keys:
- raise exceptions.KeyError('Duplicate keys: ' + str(list(duplicate_keys)))
-
- # Make sure encoding is consistent.
- if encoding in (None, BINARY):
- encoding = content.encoding
- elif content.encoding not in (BINARY, encoding):
- raise exceptions.KeyError('Inconsistent encodings: ' + str(encoding) +
- ' vs ' + str(content.encoding))
-
- if whitelist:
- whitelisted_resources = dict([(key, content.resources[key])
- for key in content.resources.keys()
- if key in whitelist])
- resources.update(whitelisted_resources)
- removed_keys = [key for key in content.resources.keys()
- if key not in whitelist]
- for key in removed_keys:
- print 'RePackFromDataPackStrings Removed Key:', key
- else:
- resources.update(content.resources)
-
- # Encoding is 0 for BINARY, 1 for UTF8 and 2 for UTF16
- if encoding is None:
- encoding = BINARY
- return DataPackContents(resources, encoding)
-
-
-# Temporary hack for external programs that import data_pack.
-# TODO(benrg): Remove this.
-class DataPack(object):
- pass
-DataPack.ReadDataPack = staticmethod(ReadDataPack)
-DataPack.WriteDataPackToString = staticmethod(WriteDataPackToString)
-DataPack.WriteDataPack = staticmethod(WriteDataPack)
-DataPack.RePack = staticmethod(RePack)
-
-
-def main():
- if len(sys.argv) > 1:
- # When an argument is given, read and explode the file to text
- # format, for easier diffing.
- data = ReadDataPack(sys.argv[1])
- print data.encoding
- for (resource_id, text) in data.resources.iteritems():
- print '%s: %s' % (resource_id, text)
- else:
- # Just write a simple file.
- data = {1: '', 4: 'this is id 4', 6: 'this is id 6', 10: ''}
- WriteDataPack(data, 'datapack1.pak', UTF8)
- data2 = {1000: 'test', 5: 'five'}
- WriteDataPack(data2, 'datapack2.pak', UTF8)
- print 'wrote datapack1 and datapack2 to current directory.'
-
-
-if __name__ == '__main__':
- main()
diff --git a/grit/format/data_pack_unittest.py b/grit/format/data_pack_unittest.py
deleted file mode 100644
index f6e9edc..0000000
--- a/grit/format/data_pack_unittest.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.data_pack'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import unittest
-
-from grit.format import data_pack
-
-
-class FormatDataPackUnittest(unittest.TestCase):
- def testWriteDataPack(self):
- expected = (
- '\x04\x00\x00\x00' # header(version
- '\x04\x00\x00\x00' # no. entries,
- '\x01' # encoding)
- '\x01\x00\x27\x00\x00\x00' # index entry 1
- '\x04\x00\x27\x00\x00\x00' # index entry 4
- '\x06\x00\x33\x00\x00\x00' # index entry 6
- '\x0a\x00\x3f\x00\x00\x00' # index entry 10
- '\x00\x00\x3f\x00\x00\x00' # extra entry for the size of last
- 'this is id 4this is id 6') # data
- input = {1: '', 4: 'this is id 4', 6: 'this is id 6', 10: ''}
- output = data_pack.WriteDataPackToString(input, data_pack.UTF8)
- self.failUnless(output == expected)
-
- def testRePackUnittest(self):
- expected_with_whitelist = {
- 1: 'Never gonna', 10: 'give you up', 20: 'Never gonna let',
- 30: 'you down', 40: 'Never', 50: 'gonna run around and',
- 60: 'desert you'}
- expected_without_whitelist = {
- 1: 'Never gonna', 10: 'give you up', 20: 'Never gonna let', 65: 'Close',
- 30: 'you down', 40: 'Never', 50: 'gonna run around and', 4: 'click',
- 60: 'desert you', 6: 'chirr', 32: 'oops, try again', 70: 'Awww, snap!'}
- inputs = [{1: 'Never gonna', 4: 'click', 6: 'chirr', 10: 'give you up'},
- {20: 'Never gonna let', 30: 'you down', 32: 'oops, try again'},
- {40: 'Never', 50: 'gonna run around and', 60: 'desert you'},
- {65: 'Close', 70: 'Awww, snap!'}]
- whitelist = [1, 10, 20, 30, 40, 50, 60]
- inputs = [data_pack.DataPackContents(input, data_pack.UTF8) for input
- in inputs]
-
- # RePack using whitelist
- output, _ = data_pack.RePackFromDataPackStrings(inputs, whitelist)
- self.assertDictEqual(expected_with_whitelist, output,
- 'Incorrect resource output')
-
- # RePack a None whitelist
- output, _ = data_pack.RePackFromDataPackStrings(inputs, None)
- self.assertDictEqual(expected_without_whitelist, output,
- 'Incorrect resource output')
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/html_inline.py b/grit/format/html_inline.py
deleted file mode 100755
index f532496..0000000
--- a/grit/format/html_inline.py
+++ /dev/null
@@ -1,423 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Flattens a HTML file by inlining its external resources.
-
-This is a small script that takes a HTML file, looks for src attributes
-and inlines the specified file, producing one HTML file with no external
-dependencies. It recursively inlines the included files.
-"""
-
-import os
-import re
-import sys
-import base64
-import mimetypes
-
-from grit import lazy_re
-from grit import util
-
-# There is a python bug that makes mimetypes crash if the Windows
-# registry contains non-Latin keys ( http://bugs.python.org/issue9291
-# ). Initing manually and blocking external mime-type databases will
-# prevent that bug and if we add svg manually, it will still give us
-# the data we need.
-mimetypes.init([])
-mimetypes.add_type('image/svg+xml', '.svg')
-
-DIST_DEFAULT = 'chromium'
-DIST_ENV_VAR = 'CHROMIUM_BUILD'
-DIST_SUBSTR = '%DISTRIBUTION%'
-
-# Matches beginning of an "if" block with trailing spaces.
-_BEGIN_IF_BLOCK = lazy_re.compile(
- '<if [^>]*?expr="(?P<expression>[^"]*)"[^>]*?>\s*')
-
-# Matches ending of an "if" block with preceding spaces.
-_END_IF_BLOCK = lazy_re.compile('\s*</if>')
-
-# Used by DoInline to replace various links with inline content.
-_STYLESHEET_RE = lazy_re.compile(
- '<link rel="stylesheet"[^>]+?href="(?P<filename>[^"]*)".*?>(\s*</link>)?',
- re.DOTALL)
-_INCLUDE_RE = lazy_re.compile(
- '<include[^>]+?src="(?P<filename>[^"\']*)".*?>(\s*</include>)?',
- re.DOTALL)
-_SRC_RE = lazy_re.compile(
- r'<(?!script)(?:[^>]+?\s)src=(?P<quote>")(?!\[\[|{{)(?P<filename>[^"\']*)\1',
- re.MULTILINE)
-_ICON_RE = lazy_re.compile(
- r'<link rel="icon"\s(?:[^>]+?\s)?'
- 'href=(?P<quote>")(?P<filename>[^"\']*)\1',
- re.MULTILINE)
-
-
-def GetDistribution():
- """Helper function that gets the distribution we are building.
-
- Returns:
- string
- """
- distribution = DIST_DEFAULT
- if DIST_ENV_VAR in os.environ.keys():
- distribution = os.environ[DIST_ENV_VAR]
- if len(distribution) > 1 and distribution[0] == '_':
- distribution = distribution[1:].lower()
- return distribution
-
-
-def SrcInlineAsDataURL(
- src_match, base_path, distribution, inlined_files, names_only=False,
- filename_expansion_function=None):
- """regex replace function.
-
- Takes a regex match for src="filename", attempts to read the file
- at 'filename' and returns the src attribute with the file inlined
- as a data URI. If it finds DIST_SUBSTR string in file name, replaces
- it with distribution.
-
- Args:
- src_match: regex match object with 'filename' and 'quote' named capturing
- groups
- base_path: path that to look for files in
- distribution: string that should replace DIST_SUBSTR
- inlined_files: The name of the opened file is appended to this list.
- names_only: If true, the function will not read the file but just return "".
- It will still add the filename to |inlined_files|.
-
- Returns:
- string
- """
- filename = src_match.group('filename')
- if filename_expansion_function:
- filename = filename_expansion_function(filename)
- quote = src_match.group('quote')
-
- if filename.find(':') != -1:
- # filename is probably a URL, which we don't want to bother inlining
- return src_match.group(0)
-
- filename = filename.replace(DIST_SUBSTR , distribution)
- filepath = os.path.normpath(os.path.join(base_path, filename))
- inlined_files.add(filepath)
-
- if names_only:
- return ""
-
- mimetype = mimetypes.guess_type(filename)[0]
- if mimetype is None:
- raise Exception('%s is of an an unknown type and '
- 'cannot be stored in a data url.' % filename)
- inline_data = base64.standard_b64encode(util.ReadFile(filepath, util.BINARY))
-
- prefix = src_match.string[src_match.start():src_match.start('filename')]
- suffix = src_match.string[src_match.end('filename'):src_match.end()]
- return '%sdata:%s;base64,%s%s' % (prefix, mimetype, inline_data, suffix)
-
-
-class InlinedData:
- """Helper class holding the results from DoInline().
-
- Holds the inlined data and the set of filenames of all the inlined
- files.
- """
- def __init__(self, inlined_data, inlined_files):
- self.inlined_data = inlined_data
- self.inlined_files = inlined_files
-
-def DoInline(
- input_filename, grd_node, allow_external_script=False, names_only=False,
- rewrite_function=None, filename_expansion_function=None):
- """Helper function that inlines the resources in a specified file.
-
- Reads input_filename, finds all the src attributes and attempts to
- inline the files they are referring to, then returns the result and
- the set of inlined files.
-
- Args:
- input_filename: name of file to read in
- grd_node: html node from the grd file for this include tag
- names_only: |nil| will be returned for the inlined contents (faster).
- rewrite_function: function(filepath, text, distribution) which will be
- called to rewrite html content before inlining images.
- filename_expansion_function: function(filename) which will be called to
- rewrite filenames before attempting to read them.
- Returns:
- a tuple of the inlined data as a string and the set of filenames
- of all the inlined files
- """
- if filename_expansion_function:
- input_filename = filename_expansion_function(input_filename)
- input_filepath = os.path.dirname(input_filename)
- distribution = GetDistribution()
-
- # Keep track of all the files we inline.
- inlined_files = set()
-
- def SrcReplace(src_match, filepath=input_filepath,
- inlined_files=inlined_files):
- """Helper function to provide SrcInlineAsDataURL with the base file path"""
- return SrcInlineAsDataURL(
- src_match, filepath, distribution, inlined_files, names_only=names_only,
- filename_expansion_function=filename_expansion_function)
-
- def GetFilepath(src_match, base_path = input_filepath):
- filename = src_match.group('filename')
-
- if filename.find(':') != -1:
- # filename is probably a URL, which we don't want to bother inlining
- return None
-
- filename = filename.replace('%DISTRIBUTION%', distribution)
- if filename_expansion_function:
- filename = filename_expansion_function(filename)
- return os.path.normpath(os.path.join(base_path, filename))
-
- def IsConditionSatisfied(src_match):
- expression = src_match.group('expression')
- return grd_node is None or grd_node.EvaluateCondition(expression)
-
- def CheckConditionalElements(str):
- """Helper function to conditionally inline inner elements"""
- while True:
- begin_if = _BEGIN_IF_BLOCK.search(str)
- if begin_if is None:
- if _END_IF_BLOCK.search(str) is not None:
- raise Exception('Unmatched </if>')
- return str
-
- condition_satisfied = IsConditionSatisfied(begin_if)
- leading = str[0:begin_if.start()]
- content_start = begin_if.end()
-
- # Find matching "if" block end.
- count = 1
- pos = begin_if.end()
- while True:
- end_if = _END_IF_BLOCK.search(str, pos)
- if end_if is None:
- raise Exception('Unmatched <if>')
-
- next_if = _BEGIN_IF_BLOCK.search(str, pos)
- if next_if is None or next_if.start() >= end_if.end():
- count = count - 1
- if count == 0:
- break
- pos = end_if.end()
- else:
- count = count + 1
- pos = next_if.end()
-
- content = str[content_start:end_if.start()]
- trailing = str[end_if.end():]
-
- if condition_satisfied:
- str = leading + CheckConditionalElements(content) + trailing
- else:
- str = leading + trailing
-
- def InlineFileContents(src_match, pattern, inlined_files=inlined_files):
- """Helper function to inline external files of various types"""
- filepath = GetFilepath(src_match)
- if filepath is None:
- return src_match.group(0)
- inlined_files.add(filepath)
-
- if names_only:
- inlined_files.update(GetResourceFilenames(
- filepath,
- allow_external_script,
- rewrite_function,
- filename_expansion_function=filename_expansion_function))
- return ""
-
- return pattern % InlineToString(
- filepath, grd_node, allow_external_script,
- filename_expansion_function=filename_expansion_function)
-
- def InlineIncludeFiles(src_match):
- """Helper function to directly inline generic external files (without
- wrapping them with any kind of tags).
- """
- return InlineFileContents(src_match, '%s')
-
- def InlineScript(match):
- """Helper function to inline external script files"""
- attrs = (match.group('attrs1') + match.group('attrs2')).strip()
- if attrs:
- attrs = ' ' + attrs
- return InlineFileContents(match, '<script' + attrs + '>%s</script>')
-
- def InlineCSSText(text, css_filepath):
- """Helper function that inlines external resources in CSS text"""
- filepath = os.path.dirname(css_filepath)
- # Allow custom modifications before inlining images.
- if rewrite_function:
- text = rewrite_function(filepath, text, distribution)
- text = InlineCSSImages(text, filepath)
- return InlineCSSImports(text, filepath)
-
- def InlineCSSFile(src_match, pattern, base_path=input_filepath):
- """Helper function to inline external CSS files.
-
- Args:
- src_match: A regular expression match with a named group named "filename".
- pattern: The pattern to replace with the contents of the CSS file.
- base_path: The base path to use for resolving the CSS file.
-
- Returns:
- The text that should replace the reference to the CSS file.
- """
- filepath = GetFilepath(src_match, base_path)
- if filepath is None:
- return src_match.group(0)
-
- # Even if names_only is set, the CSS file needs to be opened, because it
- # can link to images that need to be added to the file set.
- inlined_files.add(filepath)
- # When resolving CSS files we need to pass in the path so that relative URLs
- # can be resolved.
- return pattern % InlineCSSText(util.ReadFile(filepath, util.BINARY),
- filepath)
-
- def InlineCSSImages(text, filepath=input_filepath):
- """Helper function that inlines external images in CSS backgrounds."""
- # Replace contents of url() for css attributes: content, background,
- # or *-image.
- return re.sub('(content|background|[\w-]*-image):[^;]*' +
- '(url\((?P<quote1>"|\'|)[^"\'()]*(?P=quote1)\)|' +
- 'image-set\(' +
- '([ ]*url\((?P<quote2>"|\'|)[^"\'()]*(?P=quote2)\)' +
- '[ ]*[0-9.]*x[ ]*(,[ ]*)?)+\))',
- lambda m: InlineCSSUrls(m, filepath),
- text)
-
- def InlineCSSUrls(src_match, filepath=input_filepath):
- """Helper function that inlines each url on a CSS image rule match."""
- # Replace contents of url() references in matches.
- return re.sub('url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)(?P=quote)\)',
- lambda m: SrcReplace(m, filepath),
- src_match.group(0))
-
- def InlineCSSImports(text, filepath=input_filepath):
- """Helper function that inlines CSS files included via the @import
- directive.
- """
- return re.sub('@import\s+url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)' +
- '(?P=quote)\);',
- lambda m: InlineCSSFile(m, '%s', filepath),
- text)
-
-
- flat_text = util.ReadFile(input_filename, util.BINARY)
-
- # Check conditional elements, remove unsatisfied ones from the file. We do
- # this twice. The first pass is so that we don't even bother calling
- # InlineScript, InlineCSSFile and InlineIncludeFiles on text we're eventually
- # going to throw out anyway.
- flat_text = CheckConditionalElements(flat_text)
-
- if not allow_external_script:
- # We need to inline css and js before we inline images so that image
- # references gets inlined in the css and js
- flat_text = re.sub('<script (?P<attrs1>.*?)src="(?P<filename>[^"\']*)"' +
- '(?P<attrs2>.*?)></script>',
- InlineScript,
- flat_text)
-
- flat_text = _STYLESHEET_RE.sub(
- lambda m: InlineCSSFile(m, '<style>%s</style>'),
- flat_text)
-
- flat_text = _INCLUDE_RE.sub(InlineIncludeFiles, flat_text)
-
- # Check conditional elements, second pass. This catches conditionals in any
- # of the text we just inlined.
- flat_text = CheckConditionalElements(flat_text)
-
- # Allow custom modifications before inlining images.
- if rewrite_function:
- flat_text = rewrite_function(input_filepath, flat_text, distribution)
-
- flat_text = _SRC_RE.sub(SrcReplace, flat_text)
-
- # TODO(arv): Only do this inside <style> tags.
- flat_text = InlineCSSImages(flat_text)
-
- flat_text = _ICON_RE.sub(SrcReplace, flat_text)
-
- if names_only:
- flat_text = None # Will contains garbage if the flag is set anyway.
- return InlinedData(flat_text, inlined_files)
-
-
-def InlineToString(input_filename, grd_node, allow_external_script=False,
- rewrite_function=None, filename_expansion_function=None):
- """Inlines the resources in a specified file and returns it as a string.
-
- Args:
- input_filename: name of file to read in
- grd_node: html node from the grd file for this include tag
- Returns:
- the inlined data as a string
- """
- try:
- return DoInline(
- input_filename,
- grd_node,
- allow_external_script=allow_external_script,
- rewrite_function=rewrite_function,
- filename_expansion_function=filename_expansion_function).inlined_data
- except IOError, e:
- raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
- (e.filename, input_filename, e.strerror))
-
-
-def InlineToFile(input_filename, output_filename, grd_node):
- """Inlines the resources in a specified file and writes it.
-
- Reads input_filename, finds all the src attributes and attempts to
- inline the files they are referring to, then writes the result
- to output_filename.
-
- Args:
- input_filename: name of file to read in
- output_filename: name of file to be written to
- grd_node: html node from the grd file for this include tag
- Returns:
- a set of filenames of all the inlined files
- """
- inlined_data = InlineToString(input_filename, grd_node)
- with open(output_filename, 'wb') as out_file:
- out_file.writelines(inlined_data)
-
-
-def GetResourceFilenames(filename,
- allow_external_script=False,
- rewrite_function=None,
- filename_expansion_function=None):
- """For a grd file, returns a set of all the files that would be inline."""
- try:
- return DoInline(
- filename,
- None,
- names_only=True,
- allow_external_script=allow_external_script,
- rewrite_function=rewrite_function,
- filename_expansion_function=filename_expansion_function).inlined_files
- except IOError, e:
- raise Exception("Failed to open %s while trying to flatten %s. (%s)" %
- (e.filename, filename, e.strerror))
-
-
-def main():
- if len(sys.argv) <= 2:
- print "Flattens a HTML file by inlining its external resources.\n"
- print "html_inline.py inputfile outputfile"
- else:
- InlineToFile(sys.argv[1], sys.argv[2], None)
-
-if __name__ == '__main__':
- main()
diff --git a/grit/format/html_inline_unittest.py b/grit/format/html_inline_unittest.py
deleted file mode 100755
index ea76d37..0000000
--- a/grit/format/html_inline_unittest.py
+++ /dev/null
@@ -1,352 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.html_inline'''
-
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import unittest
-
-from grit import util
-from grit.format import html_inline
-
-
-class HtmlInlineUnittest(unittest.TestCase):
- '''Unit tests for HtmlInline.'''
-
- def testGetResourceFilenames(self):
- '''Tests that all included files are returned by GetResourceFilenames.'''
-
- files = {
- 'index.html': '''
- <!DOCTYPE HTML>
- <html>
- <head>
- <link rel="stylesheet" href="test.css">
- <link rel="stylesheet"
- href="really-long-long-long-long-long-test.css">
- </head>
- <body>
- <include src="test.html">
- <include
- src="really-long-long-long-long-long-test-file-omg-so-long.html">
- <iron-icon src="[[icon]]"></iron-icon><!-- Should be ignored. -->
- <iron-icon src="{{src}}"></iron-icon><!-- Also ignored. -->
- </body>
- </html>
- ''',
-
- 'test.html': '''
- <include src="test2.html">
- ''',
-
- 'really-long-long-long-long-long-test-file-omg-so-long.html': '''
- <!-- This really long named resource should be included. -->
- ''',
-
- 'test2.html': '''
- <!-- This second level resource should also be included. -->
- ''',
-
- 'test.css': '''
- .image {
- background: url('test.png');
- }
- ''',
-
- 'really-long-long-long-long-long-test.css': '''
- a:hover {
- font-weight: bold; /* Awesome effect is awesome! */
- }
- ''',
-
- 'test.png': 'PNG DATA',
- }
-
- source_resources = set()
- tmp_dir = util.TempDir(files)
- for filename in files:
- source_resources.add(tmp_dir.GetPath(filename))
-
- resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'))
- resources.add(tmp_dir.GetPath('index.html'))
- self.failUnlessEqual(resources, source_resources)
- tmp_dir.CleanUp()
-
- def testUnmatchedEndIfBlock(self):
- '''Tests that an unmatched </if> raises an exception.'''
-
- files = {
- 'index.html': '''
- <!DOCTYPE HTML>
- <html>
- <if expr="lang == 'fr'">
- bonjour
- </if>
- </if>
- </html>
- ''',
- }
-
- tmp_dir = util.TempDir(files)
-
- with self.assertRaises(Exception) as cm:
- html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'))
- self.failUnlessEqual(cm.exception.message, 'Unmatched </if>')
- tmp_dir.CleanUp()
-
- def testCompressedJavaScript(self):
- '''Tests that ".src=" doesn't treat as a tag.'''
-
- files = {
- 'index.js': '''
- if(i<j)a.src="hoge.png";
- ''',
- }
-
- source_resources = set()
- tmp_dir = util.TempDir(files)
- for filename in files:
- source_resources.add(tmp_dir.GetPath(filename))
-
- resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.js'))
- resources.add(tmp_dir.GetPath('index.js'))
- self.failUnlessEqual(resources, source_resources)
- tmp_dir.CleanUp()
-
- def testInlineCSSImports(self):
- '''Tests that @import directives in inlined CSS files are inlined too.
- '''
-
- files = {
- 'index.html': '''
- <html>
- <head>
- <link rel="stylesheet" href="css/test.css">
- </head>
- </html>
- ''',
-
- 'css/test.css': '''
- @import url('test2.css');
- blink {
- display: none;
- }
- ''',
-
- 'css/test2.css': '''
- .image {
- background: url('../images/test.png');
- }
- '''.strip(),
-
- 'images/test.png': 'PNG DATA'
- }
-
- expected_inlined = '''
- <html>
- <head>
- <style>
- .image {
- background: url('data:image/png;base64,UE5HIERBVEE=');
- }
- blink {
- display: none;
- }
- </style>
- </head>
- </html>
- '''
-
- source_resources = set()
- tmp_dir = util.TempDir(files)
- for filename in files:
- source_resources.add(tmp_dir.GetPath(util.normpath(filename)))
-
- result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
- resources = result.inlined_files
- resources.add(tmp_dir.GetPath('index.html'))
- self.failUnlessEqual(resources, source_resources)
- self.failUnlessEqual(expected_inlined,
- util.FixLineEnd(result.inlined_data, '\n'))
-
- tmp_dir.CleanUp()
-
- def testInlineCSSLinks(self):
- '''Tests that only CSS files referenced via relative URLs are inlined.'''
-
- files = {
- 'index.html': '''
- <html>
- <head>
- <link rel="stylesheet" href="foo.css">
- <link rel="stylesheet" href="chrome://resources/bar.css">
- </head>
- </html>
- ''',
-
- 'foo.css': '''
- @import url(chrome://resources/blurp.css);
- blink {
- display: none;
- }
- ''',
- }
-
- expected_inlined = '''
- <html>
- <head>
- <style>
- @import url(chrome://resources/blurp.css);
- blink {
- display: none;
- }
- </style>
- <link rel="stylesheet" href="chrome://resources/bar.css">
- </head>
- </html>
- '''
-
- source_resources = set()
- tmp_dir = util.TempDir(files)
- for filename in files:
- source_resources.add(tmp_dir.GetPath(filename))
-
- result = html_inline.DoInline(tmp_dir.GetPath('index.html'), None)
- resources = result.inlined_files
- resources.add(tmp_dir.GetPath('index.html'))
- self.failUnlessEqual(resources, source_resources)
- self.failUnlessEqual(expected_inlined,
- util.FixLineEnd(result.inlined_data, '\n'))
-
- def testFilenameVariableExpansion(self):
- '''Tests that variables are expanded in filenames before inlining.'''
-
- files = {
- 'index.html': '''
- <html>
- <head>
- <link rel="stylesheet" href="style[WHICH].css">
- <script src="script[WHICH].js"></script>
- </head>
- <include src="tmpl[WHICH].html">
- <img src="img[WHICH].png">
- </html>
- ''',
- 'style1.css': '''h1 {}''',
- 'tmpl1.html': '''<h1></h1>''',
- 'script1.js': '''console.log('hello');''',
- 'img1.png': '''abc''',
- }
-
- expected_inlined = '''
- <html>
- <head>
- <style>h1 {}</style>
- <script>console.log('hello');</script>
- </head>
- <h1></h1>
- <img src="data:image/png;base64,YWJj">
- </html>
- '''
-
- source_resources = set()
- tmp_dir = util.TempDir(files)
- for filename in files:
- source_resources.add(tmp_dir.GetPath(filename))
-
- def replacer(var, repl):
- return lambda filename: filename.replace('[%s]' % var, repl)
-
- # Test normal inlining.
- result = html_inline.DoInline(
- tmp_dir.GetPath('index.html'),
- None,
- filename_expansion_function=replacer('WHICH', '1'))
- resources = result.inlined_files
- resources.add(tmp_dir.GetPath('index.html'))
- self.failUnlessEqual(resources, source_resources)
- self.failUnlessEqual(expected_inlined,
- util.FixLineEnd(result.inlined_data, '\n'))
-
- # Test names-only inlining.
- result = html_inline.DoInline(
- tmp_dir.GetPath('index.html'),
- None,
- names_only=True,
- filename_expansion_function=replacer('WHICH', '1'))
- resources = result.inlined_files
- resources.add(tmp_dir.GetPath('index.html'))
- self.failUnlessEqual(resources, source_resources)
-
- def testWithCloseTags(self):
- '''Tests that close tags are removed.'''
-
- files = {
- 'index.html': '''
- <html>
- <head>
- <link rel="stylesheet" href="style1.css"></link>
- <link rel="stylesheet" href="style2.css">
- </link>
- <link rel="stylesheet" href="style2.css"
- >
- </link>
- <script src="script1.js"></script>
- </head>
- <include src="tmpl1.html"></include>
- <include src="tmpl2.html">
- </include>
- <include src="tmpl2.html"
- >
- </include>
- <img src="img1.png">
- </html>
- ''',
- 'style1.css': '''h1 {}''',
- 'style2.css': '''h2 {}''',
- 'tmpl1.html': '''<h1></h1>''',
- 'tmpl2.html': '''<h2></h2>''',
- 'script1.js': '''console.log('hello');''',
- 'img1.png': '''abc''',
- }
-
- expected_inlined = '''
- <html>
- <head>
- <style>h1 {}</style>
- <style>h2 {}</style>
- <style>h2 {}</style>
- <script>console.log('hello');</script>
- </head>
- <h1></h1>
- <h2></h2>
- <h2></h2>
- <img src="data:image/png;base64,YWJj">
- </html>
- '''
-
- source_resources = set()
- tmp_dir = util.TempDir(files)
- for filename in files:
- source_resources.add(tmp_dir.GetPath(filename))
-
- # Test normal inlining.
- result = html_inline.DoInline(
- tmp_dir.GetPath('index.html'),
- None)
- resources = result.inlined_files
- resources.add(tmp_dir.GetPath('index.html'))
- self.failUnlessEqual(resources, source_resources)
- self.failUnlessEqual(expected_inlined,
- util.FixLineEnd(result.inlined_data, '\n'))
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/js_map_format.py b/grit/format/js_map_format.py
deleted file mode 100644
index 8cc8eb2..0000000
--- a/grit/format/js_map_format.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Formats as a .js file using a map: <english text> -> <localized text>.
-"""
-
-import re
-
-from grit import util
-
-
-"""The required preamble for JS files."""
-_HEADER = '// This file is automatically generated by GRIT. Do not edit.\n'
-
-
-def Format(root, lang='en', output_dir='.'):
- from grit.node import empty, message
- yield _HEADER
- for item in root.ActiveDescendants():
- with item:
- if isinstance(item, message.MessageNode):
- yield _FormatMessage(item, lang)
- elif isinstance(item, empty.MessagesNode):
- yield '\n'
-
-
-def _FormatMessage(item, lang):
- """Format a single message."""
-
- en_message = item.ws_at_start + item.Translate('en') + item.ws_at_end
- # Remove position numbers from placeholders.
- en_message = re.sub(r'%\d\$([a-z])', r'%\1', en_message)
- # Escape double quotes.
- en_message = re.sub(r'\\', r'\\\\', en_message)
- en_message = re.sub(r'"', r'\"', en_message)
-
- loc_message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
- # Escape double quotes.
- loc_message = re.sub(r'\\', r'\\\\', loc_message)
- loc_message = re.sub(r'"', r'\"', loc_message)
-
- return '\nlocalizedStrings["%s"] = "%s";' % (en_message, loc_message)
diff --git a/grit/format/js_map_format_unittest.py b/grit/format/js_map_format_unittest.py
deleted file mode 100644
index cac0b2e..0000000
--- a/grit/format/js_map_format_unittest.py
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Unittest for js_map_format.py.
-"""
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import unittest
-import StringIO
-
-from grit import util
-from grit.tool import build
-
-
-class JsMapFormatUnittest(unittest.TestCase):
-
- def testMessages(self):
- root = util.ParseGrdForUnittest(u"""
- <messages>
- <message name="IDS_SIMPLE_MESSAGE">
- Simple message.
- </message>
- <message name="IDS_QUOTES">
- element\u2019s \u201c<ph name="NAME">%s<ex>name</ex></ph>\u201d attribute
- </message>
- <message name="IDS_PLACEHOLDERS">
- <ph name="ERROR_COUNT">%1$d<ex>1</ex></ph> error, <ph name="WARNING_COUNT">%2$d<ex>1</ex></ph> warning
- </message>
- <message name="IDS_STARTS_WITH_SPACE">
- ''' (<ph name="COUNT">%d<ex>2</ex></ph>)
- </message>
- <message name="IDS_DOUBLE_QUOTES">
- A "double quoted" message.
- </message>
- <message name="IDS_BACKSLASH">
- \\
- </message>
- </messages>
- """)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('js_map_format', 'en'), buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- self.assertEqual(u"""\
-localizedStrings["Simple message."] = "Simple message.";
-localizedStrings["element\u2019s \u201c%s\u201d attribute"] = "element\u2019s \u201c%s\u201d attribute";
-localizedStrings["%d error, %d warning"] = "%1$d error, %2$d warning";
-localizedStrings[" (%d)"] = " (%d)";
-localizedStrings["A \\\"double quoted\\\" message."] = "A \\\"double quoted\\\" message.";
-localizedStrings["\\\\"] = "\\\\";""", output)
-
- def testTranslations(self):
- root = util.ParseGrdForUnittest("""
- <messages>
- <message name="ID_HELLO">Hello!</message>
- <message name="ID_HELLO_USER">Hello <ph name="USERNAME">%s<ex>
- Joi</ex></ph></message>
- </messages>
- """)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('js_map_format', 'fr'), buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- self.assertEqual(u"""\
-localizedStrings["Hello!"] = "H\xe9P\xe9ll\xf4P\xf4!";
-localizedStrings["Hello %s"] = "H\xe9P\xe9ll\xf4P\xf4 %s";\
-""", output)
-
-
-class DummyOutput(object):
-
- def __init__(self, type, language):
- self.type = type
- self.language = language
-
- def GetType(self):
- return self.type
-
- def GetLanguage(self):
- return self.language
-
- def GetOutputFilename(self):
- return 'hello.gif'
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/PRESUBMIT.py b/grit/format/policy_templates/PRESUBMIT.py
deleted file mode 100644
index dca24a0..0000000
--- a/grit/format/policy_templates/PRESUBMIT.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-UNIT_TESTS = [
- 'policy_template_generator_unittest',
- 'writers.adm_writer_unittest',
- 'writers.adml_writer_unittest',
- 'writers.admx_writer_unittest',
- 'writers.android_policy_writer_unittest',
- 'writers.doc_writer_unittest',
- 'writers.json_writer_unittest',
- 'writers.plist_strings_writer_unittest',
- 'writers.plist_writer_unittest',
- 'writers.reg_writer_unittest',
- 'writers.template_writer_unittest'
-]
-
-def CheckChangeOnUpload(input_api, output_api):
- return input_api.canned_checks.RunPythonUnitTests(input_api,
- output_api,
- UNIT_TESTS)
-
-
-def CheckChangeOnCommit(input_api, output_api):
- return input_api.canned_checks.RunPythonUnitTests(input_api,
- output_api,
- UNIT_TESTS)
diff --git a/grit/format/policy_templates/__init__.py b/grit/format/policy_templates/__init__.py
deleted file mode 100644
index 21cab65..0000000
--- a/grit/format/policy_templates/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Module grit.format.policy_templates
-'''
-
-pass
-
diff --git a/grit/format/policy_templates/policy_template_generator.py b/grit/format/policy_templates/policy_template_generator.py
deleted file mode 100644
index a1eb123..0000000
--- a/grit/format/policy_templates/policy_template_generator.py
+++ /dev/null
@@ -1,154 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-import copy
-
-
-class PolicyTemplateGenerator:
- '''Generates template text for a particular platform.
-
- This class is used to traverse a JSON structure from a .json template
- definition metafile and merge GUI message string definitions that come
- from a .grd resource tree onto it. After this, it can be used to output
- this data to policy template files using TemplateWriter objects.
- '''
-
- def _ImportMessage(self, msg_txt):
- msg_txt = msg_txt.decode('utf-8')
- # Replace the placeholder of app name.
- msg_txt = msg_txt.replace('$1', self._config['app_name'])
- msg_txt = msg_txt.replace('$2', self._config['os_name'])
- msg_txt = msg_txt.replace('$3', self._config['frame_name'])
- # Strip spaces and escape newlines.
- lines = msg_txt.split('\n')
- lines = [line.strip() for line in lines]
- return "\n".join(lines)
-
- def __init__(self, config, policy_data):
- '''Initializes this object with all the data necessary to output a
- policy template.
-
- Args:
- messages: An identifier to string dictionary of all the localized
- messages that might appear in the policy template.
- policy_definitions: The list of defined policies and groups, as
- parsed from the policy metafile. Note that this list is passed by
- reference and its contents are modified.
- See chrome/app/policy.policy_templates.json for description and
- content.
- '''
- # List of all the policies:
- self._policy_data = copy.deepcopy(policy_data)
- # Localized messages to be inserted to the policy_definitions structure:
- self._messages = self._policy_data['messages']
- self._config = config
- for key in self._messages.keys():
- self._messages[key]['text'] = self._ImportMessage(
- self._messages[key]['text'])
- self._policy_definitions = self._policy_data['policy_definitions']
- self._ProcessPolicyList(self._policy_definitions)
-
- def _ProcessSupportedOn(self, supported_on):
- '''Parses and converts the string items of the list of supported platforms
- into dictionaries.
-
- Args:
- supported_on: The list of supported platforms. E.g.:
- ['chrome.win:8-10', 'chrome_frame:10-']
-
- Returns:
- supported_on: The list with its items converted to dictionaries. E.g.:
- [{
- 'product': 'chrome',
- 'platform': 'win',
- 'since_version': '8',
- 'until_version': '10'
- }, {
- 'product': 'chrome_frame',
- 'platform': 'win',
- 'since_version': '10',
- 'until_version': ''
- }]
- '''
- result = []
- for supported_on_item in supported_on:
- product_platform_part, version_part = supported_on_item.split(':')
-
- if '.' in product_platform_part:
- product, platform = product_platform_part.split('.')
- if platform == '*':
- # e.g.: 'chrome.*:8-10'
- platforms = ['linux', 'mac', 'win']
- else:
- # e.g.: 'chrome.win:-10'
- platforms = [platform]
- else:
- # e.g.: 'chrome_frame:7-'
- product, platform = {
- 'android': ('chrome', 'android'),
- 'chrome_os': ('chrome_os', 'chrome_os'),
- 'chrome_frame': ('chrome_frame', 'win'),
- 'ios': ('chrome', 'ios'),
- }[product_platform_part]
- platforms = [platform]
- since_version, until_version = version_part.split('-')
- result.append({
- 'product': product,
- 'platforms': platforms,
- 'since_version': since_version,
- 'until_version': until_version
- })
- return result
-
- def _ProcessPolicy(self, policy):
- '''Processes localized message strings in a policy or a group.
- Also breaks up the content of 'supported_on' attribute into a list.
-
- Args:
- policy: The data structure of the policy or group, that will get message
- strings here.
- '''
- policy['desc'] = self._ImportMessage(policy['desc'])
- policy['caption'] = self._ImportMessage(policy['caption'])
- if 'label' in policy:
- policy['label'] = self._ImportMessage(policy['label'])
-
- if policy['type'] == 'group':
- self._ProcessPolicyList(policy['policies'])
- elif policy['type'] in ('string-enum', 'int-enum', 'string-enum-list'):
- # Iterate through all the items of an enum-type policy, and add captions.
- for item in policy['items']:
- item['caption'] = self._ImportMessage(item['caption'])
- if policy['type'] != 'group':
- if not 'label' in policy:
- # If 'label' is not specified, then it defaults to 'caption':
- policy['label'] = policy['caption']
- policy['supported_on'] = self._ProcessSupportedOn(policy['supported_on'])
-
- def _ProcessPolicyList(self, policy_list):
- '''Adds localized message strings to each item in a list of policies and
- groups. Also breaks up the content of 'supported_on' attributes into lists
- of dictionaries.
-
- Args:
- policy_list: A list of policies and groups. Message strings will be added
- for each item and to their child items, recursively.
- '''
- for policy in policy_list:
- self._ProcessPolicy(policy)
-
- def GetTemplateText(self, template_writer):
- '''Generates the text of the template from the arguments given
- to the constructor, using a given TemplateWriter.
-
- Args:
- template_writer: An object implementing TemplateWriter. Its methods
- are called here for each item of self._policy_groups.
-
- Returns:
- The text of the generated template.
- '''
- return template_writer.WriteTemplate(self._policy_data)
diff --git a/grit/format/policy_templates/policy_template_generator_unittest.py b/grit/format/policy_templates/policy_template_generator_unittest.py
deleted file mode 100644
index adc4a22..0000000
--- a/grit/format/policy_templates/policy_template_generator_unittest.py
+++ /dev/null
@@ -1,395 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../..'))
-
-import unittest
-
-from grit.format.policy_templates import policy_template_generator
-from grit.format.policy_templates.writers import mock_writer
-from grit.format.policy_templates.writers import template_writer
-
-
-class PolicyTemplateGeneratorUnittest(unittest.TestCase):
- '''Unit tests for policy_template_generator.py.'''
-
- def do_test(self, policy_data, writer):
- '''Executes a test case.
-
- Creates and invokes an instance of PolicyTemplateGenerator with
- the given arguments.
-
- Notice: Plain comments are used in test methods instead of docstrings,
- so that method names do not get overridden by the docstrings in the
- test output.
-
- Args:
- policy_data: The list of policies and groups as it would be
- loaded from policy_templates.json.
- writer: A writer used for this test. It is usually derived from
- mock_writer.MockWriter.
- '''
- writer.tester = self
- config = {
- 'app_name': '_app_name',
- 'frame_name': '_frame_name',
- 'os_name': '_os_name',
- }
- if not 'messages' in policy_data:
- policy_data['messages'] = {}
- if not 'placeholders' in policy_data:
- policy_data['placeholders'] = []
- if not 'policy_definitions' in policy_data:
- policy_data['policy_definitions'] = []
- policy_generator = policy_template_generator.PolicyTemplateGenerator(
- config,
- policy_data)
- res = policy_generator.GetTemplateText(writer)
- writer.Test()
- return res
-
- def testSequence(self):
- # Test the sequence of invoking the basic PolicyWriter operations,
- # in case of empty input data structures.
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.log = 'init;'
- def Init(self):
- self.log += 'prepare;'
- def BeginTemplate(self):
- self.log += 'begin;'
- def EndTemplate(self):
- self.log += 'end;'
- def GetTemplateText(self):
- self.log += 'get_text;'
- return 'writer_result_string'
- def Test(self):
- self.tester.assertEquals(self.log,
- 'init;prepare;begin;end;get_text;')
- result = self.do_test({}, LocalMockWriter())
- self.assertEquals(result, 'writer_result_string')
-
- def testEmptyGroups(self):
- # Test that empty policy groups are not passed to the writer.
- policies_mock = {
- 'policy_definitions': [
- {'name': 'Group1', 'type': 'group', 'policies': [],
- 'desc': '', 'caption': ''},
- {'name': 'Group2', 'type': 'group', 'policies': [],
- 'desc': '', 'caption': ''},
- {'name': 'Group3', 'type': 'group', 'policies': [],
- 'desc': '', 'caption': ''},
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.log = ''
- def BeginPolicyGroup(self, group):
- self.log += '['
- def EndPolicyGroup(self):
- self.log += ']'
- def Test(self):
- self.tester.assertEquals(self.log, '')
- self.do_test(policies_mock, LocalMockWriter())
-
- def testGroups(self):
- # Test that policy groups are passed to the writer in the correct order.
- policies_mock = {
- 'policy_definitions': [
- {
- 'name': 'Group1', 'type': 'group',
- 'caption': '', 'desc': '',
- 'policies': [{'name': 'TAG1', 'type': 'mock', 'supported_on': [],
- 'caption': '', 'desc': ''}]
- },
- {
- 'name': 'Group2', 'type': 'group',
- 'caption': '', 'desc': '',
- 'policies': [{'name': 'TAG2', 'type': 'mock', 'supported_on': [],
- 'caption': '', 'desc': ''}]
- },
- {
- 'name': 'Group3', 'type': 'group',
- 'caption': '', 'desc': '',
- 'policies': [{'name': 'TAG3', 'type': 'mock', 'supported_on': [],
- 'caption': '', 'desc': ''}]
- },
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.log = ''
- def BeginPolicyGroup(self, group):
- self.log += '[' + group['policies'][0]['name']
- def EndPolicyGroup(self):
- self.log += ']'
- def Test(self):
- self.tester.assertEquals(self.log, '[TAG1][TAG2][TAG3]')
- self.do_test(policies_mock, LocalMockWriter())
-
- def testPolicies(self):
- # Test that policies are passed to the writer in the correct order.
- policy_defs_mock = {
- 'policy_definitions': [
- {
- 'name': 'Group1',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [
- {'name': 'Group1Policy1', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- {'name': 'Group1Policy2', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- ]
- },
- {
- 'name': 'Group2',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [
- {'name': 'Group2Policy3', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- ]
- }
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.policy_name = None
- self.policy_list = []
- def BeginPolicyGroup(self, group):
- self.group = group;
- def EndPolicyGroup(self):
- self.group = None
- def WritePolicy(self, policy):
- self.tester.assertEquals(policy['name'][0:6], self.group['name'])
- self.policy_list.append(policy['name'])
- def Test(self):
- self.tester.assertEquals(
- self.policy_list,
- ['Group1Policy1', 'Group1Policy2', 'Group2Policy3'])
- self.do_test( policy_defs_mock, LocalMockWriter())
-
- def testPolicyTexts(self):
- # Test that GUI messages of policies all get placeholders replaced.
- policy_data_mock = {
- 'policy_definitions': [
- {
- 'name': 'Group1',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [
- {
- 'name': 'Policy1',
- 'caption': '1. app_name -- $1',
- 'label': '2. os_name -- $2',
- 'desc': '3. frame_name -- $3',
- 'type': 'string',
- 'supported_on': []
- },
- ]
- }
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def WritePolicy(self, policy):
- if policy['name'] == 'Policy1':
- self.tester.assertEquals(policy['caption'],
- '1. app_name -- _app_name')
- self.tester.assertEquals(policy['label'],
- '2. os_name -- _os_name')
- self.tester.assertEquals(policy['desc'],
- '3. frame_name -- _frame_name')
- elif policy['name'] == 'Group1':
- pass
- else:
- self.tester.fail()
- self.do_test(policy_data_mock, LocalMockWriter())
-
- def testIntEnumTexts(self):
- # Test that GUI messages are assigned correctly to int-enums
- # (aka dropdown menus).
- policy_defs_mock = {
- 'policy_definitions': [{
- 'name': 'Policy1',
- 'type': 'int-enum',
- 'caption': '', 'desc': '',
- 'supported_on': [],
- 'items': [
- {'name': 'item1', 'value': 0, 'caption': 'string1', 'desc': ''},
- {'name': 'item2', 'value': 1, 'caption': 'string2', 'desc': ''},
- {'name': 'item3', 'value': 3, 'caption': 'string3', 'desc': ''},
- ]
- }]
- }
-
- class LocalMockWriter(mock_writer.MockWriter):
- def WritePolicy(self, policy):
- self.tester.assertEquals(policy['items'][0]['caption'], 'string1')
- self.tester.assertEquals(policy['items'][1]['caption'], 'string2')
- self.tester.assertEquals(policy['items'][2]['caption'], 'string3')
- self.do_test(policy_defs_mock, LocalMockWriter())
-
- def testStringEnumTexts(self):
- # Test that GUI messages are assigned correctly to string-enums
- # (aka dropdown menus).
- policy_data_mock = {
- 'policy_definitions': [{
- 'name': 'Policy1',
- 'type': 'string-enum',
- 'caption': '', 'desc': '',
- 'supported_on': [],
- 'items': [
- {'name': 'item1', 'value': 'one', 'caption': 'string1', 'desc': ''},
- {'name': 'item2', 'value': 'two', 'caption': 'string2', 'desc': ''},
- {'name': 'item3', 'value': 'three', 'caption': 'string3', 'desc': ''},
- ]
- }]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def WritePolicy(self, policy):
- self.tester.assertEquals(policy['items'][0]['caption'], 'string1')
- self.tester.assertEquals(policy['items'][1]['caption'], 'string2')
- self.tester.assertEquals(policy['items'][2]['caption'], 'string3')
- self.do_test(policy_data_mock, LocalMockWriter())
-
- def testStringEnumTexts(self):
- # Test that GUI messages are assigned correctly to string-enums
- # (aka dropdown menus).
- policy_data_mock = {
- 'policy_definitions': [{
- 'name': 'Policy1',
- 'type': 'string-enum-list',
- 'caption': '', 'desc': '',
- 'supported_on': [],
- 'items': [
- {'name': 'item1', 'value': 'one', 'caption': 'string1', 'desc': ''},
- {'name': 'item2', 'value': 'two', 'caption': 'string2', 'desc': ''},
- {'name': 'item3', 'value': 'three', 'caption': 'string3', 'desc': ''},
- ]
- }]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def WritePolicy(self, policy):
- self.tester.assertEquals(policy['items'][0]['caption'], 'string1')
- self.tester.assertEquals(policy['items'][1]['caption'], 'string2')
- self.tester.assertEquals(policy['items'][2]['caption'], 'string3')
- self.do_test(policy_data_mock, LocalMockWriter())
-
- def testPolicyFiltering(self):
- # Test that policies are filtered correctly based on their annotations.
- policy_data_mock = {
- 'policy_definitions': [
- {
- 'name': 'Group1',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [
- {
- 'name': 'Group1Policy1',
- 'type': 'string',
- 'caption': '',
- 'desc': '',
- 'supported_on': [
- 'chrome.aaa:8-', 'chrome.bbb:8-', 'chrome.ccc:8-'
- ]
- },
- {
- 'name': 'Group1Policy2',
- 'type': 'string',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome.ddd:8-']
- },
- ]
- }, {
- 'name': 'Group2',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [
- {
- 'name': 'Group2Policy3',
- 'type': 'string',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome.eee:8-']
- },
- ]
- }, {
- 'name': 'SinglePolicy',
- 'type': 'int',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome.eee:8-']
- }
- ]
- }
- # This writer accumulates the list of policies it is asked to write.
- # This list is stored in the result_list member variable and can
- # be used later for assertions.
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self, platforms):
- self.platforms = platforms
- self.policy_name = None
- self.result_list = []
- def BeginPolicyGroup(self, group):
- self.group = group;
- self.result_list.append('begin_' + group['name'])
- def EndPolicyGroup(self):
- self.result_list.append('end_group')
- self.group = None
- def WritePolicy(self, policy):
- self.result_list.append(policy['name'])
- def IsPolicySupported(self, policy):
- # Call the original (non-mock) implementation of this method.
- return template_writer.TemplateWriter.IsPolicySupported(self, policy)
-
- local_mock_writer = LocalMockWriter(['eee'])
- self.do_test(policy_data_mock, local_mock_writer)
- # Test that only policies of platform 'eee' were written:
- self.assertEquals(
- local_mock_writer.result_list,
- ['begin_Group2', 'Group2Policy3', 'end_group', 'SinglePolicy'])
-
- local_mock_writer = LocalMockWriter(['ddd', 'bbb'])
- self.do_test(policy_data_mock, local_mock_writer)
- # Test that only policies of platforms 'ddd' and 'bbb' were written:
- self.assertEquals(
- local_mock_writer.result_list,
- ['begin_Group1', 'Group1Policy1', 'Group1Policy2', 'end_group'])
-
- def testSortingInvoked(self):
- # Tests that policy-sorting happens before passing policies to the writer.
- policy_data = {
- 'policy_definitions': [
- {'name': 'zp', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- {'name': 'ap', 'type': 'string', 'supported_on': [],
- 'caption': '', 'desc': ''},
- ]
- }
- class LocalMockWriter(mock_writer.MockWriter):
- def __init__(self):
- self.result_list = []
- def WritePolicy(self, policy):
- self.result_list.append(policy['name'])
- def Test(self):
- self.tester.assertEquals(
- self.result_list,
- ['ap', 'zp'])
- self.do_test(policy_data, LocalMockWriter())
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/template_formatter.py b/grit/format/policy_templates/template_formatter.py
deleted file mode 100644
index 53b84ec..0000000
--- a/grit/format/policy_templates/template_formatter.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-import sys
-from functools import partial
-
-from grit.format.policy_templates import policy_template_generator
-from grit.format.policy_templates import writer_configuration
-from grit.node import misc
-from grit.node import structure
-
-
-def GetFormatter(type):
- return partial(_TemplateFormatter,
- 'grit.format.policy_templates.writers.%s_writer' % type)
-
-
-def _TemplateFormatter(writer_module_name, root, lang, output_dir):
- '''Creates a template file corresponding to an <output> node of the grit
- tree.
-
- More precisely, processes the whole grit tree for a given <output> node whose
- type is one of adm, plist, plist_strings, admx, adml, doc, json, reg.
- The result of processing is a policy template file with the given type and
- language of the <output> node. This function does the interfacing with
- grit, but the actual template-generating work is done in
- policy_template_generator.PolicyTemplateGenerator.
-
- Args:
- writer_name: A string identifying the TemplateWriter subclass used
- for generating the output.
- root: the <grit> root node of the grit tree.
- lang: the language of outputted text, e.g.: 'en'
- output_dir: The output directory, currently unused here.
-
- Yields the text of the template file.
- '''
- __import__(writer_module_name)
- writer_module = sys.modules[writer_module_name]
- config = writer_configuration.GetConfigurationForBuild(root.defines)
- policy_data = _ParseGritNodes(root, lang)
- policy_generator = \
- policy_template_generator.PolicyTemplateGenerator(config, policy_data)
- writer = writer_module.GetWriter(config)
- yield policy_generator.GetTemplateText(writer)
-
-
-def _ParseGritNodes(root, lang):
- '''Collects the necessary information from the grit tree:
- the message strings and the policy definitions.
-
- Args:
- root: The root of the grit tree.
- lang: the language of outputted text, e.g.: 'en'
-
- Returns:
- Policy data.
- '''
- policy_data = None
- for item in root.ActiveDescendants():
- with item:
- if (isinstance(item, structure.StructureNode) and
- item.attrs['type'] == 'policy_template_metafile'):
- assert policy_data is None
- json_text = item.gatherer.Translate(
- lang,
- pseudo_if_not_available=item.PseudoIsAllowed(),
- fallback_to_english=item.ShouldFallbackToEnglish())
- policy_data = eval(json_text)
- return policy_data
diff --git a/grit/format/policy_templates/writer_configuration.py b/grit/format/policy_templates/writer_configuration.py
deleted file mode 100644
index db9613b..0000000
--- a/grit/format/policy_templates/writer_configuration.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-def GetConfigurationForBuild(defines):
- '''Returns a configuration dictionary for the given build that contains
- build-specific settings and information.
-
- Args:
- defines: Definitions coming from the build system.
-
- Raises:
- Exception: If 'defines' contains an unknown build-type.
- '''
- # The prefix of key names in config determines which writer will use their
- # corresponding values:
- # win: Both ADM and ADMX.
- # mac: Only plist.
- # admx: Only ADMX.
- # none/other: Used by all the writers.
- if '_chromium' in defines:
- config = {
- 'build': 'chromium',
- 'app_name': 'Chromium',
- 'frame_name': 'Chromium Frame',
- 'os_name': 'Chromium OS',
- 'win_reg_mandatory_key_name': 'Software\\Policies\\Chromium',
- 'win_reg_recommended_key_name':
- 'Software\\Policies\\Chromium\\Recommended',
- 'win_mandatory_category_path': ['chromium'],
- 'win_recommended_category_path': ['chromium_recommended'],
- 'admx_namespace': 'Chromium.Policies.Chromium',
- 'admx_prefix': 'chromium',
- 'linux_policy_path': '/etc/chromium/policies/',
- }
- elif '_google_chrome' in defines:
- config = {
- 'build': 'chrome',
- 'app_name': 'Google Chrome',
- 'frame_name': 'Google Chrome Frame',
- 'os_name': 'Google Chrome OS',
- 'win_reg_mandatory_key_name': 'Software\\Policies\\Google\\Chrome',
- 'win_reg_recommended_key_name':
- 'Software\\Policies\\Google\\Chrome\\Recommended',
- 'win_mandatory_category_path': ['google', 'googlechrome'],
- 'win_recommended_category_path': ['google', 'googlechrome_recommended'],
- 'admx_namespace': 'Google.Policies.Chrome',
- 'admx_prefix': 'chrome',
- 'linux_policy_path': '/etc/opt/chrome/policies/',
- }
- else:
- raise Exception('Unknown build')
- if 'version' in defines:
- config['version'] = defines['version']
- config['win_group_policy_class'] = 'Both'
- config['win_supported_os'] = 'SUPPORTED_WINXPSP2'
- if 'mac_bundle_id' in defines:
- config['mac_bundle_id'] = defines['mac_bundle_id']
- return config
diff --git a/grit/format/policy_templates/writers/__init__.py b/grit/format/policy_templates/writers/__init__.py
deleted file mode 100644
index fe6d139..0000000
--- a/grit/format/policy_templates/writers/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Module grit.format.policy_templates.writers
-'''
-
-pass
-
diff --git a/grit/format/policy_templates/writers/adm_writer.py b/grit/format/policy_templates/writers/adm_writer.py
deleted file mode 100644
index 91aeef6..0000000
--- a/grit/format/policy_templates/writers/adm_writer.py
+++ /dev/null
@@ -1,274 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-from grit.format.policy_templates.writers import template_writer
-
-
-NEWLINE = '\r\n'
-
-
-def GetWriter(config):
- '''Factory method for creating AdmWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return AdmWriter(['win'], config)
-
-
-class IndentedStringBuilder:
- '''Utility class for building text with indented lines.'''
-
- def __init__(self):
- self.lines = []
- self.indent = ''
-
- def AddLine(self, string='', indent_diff=0):
- '''Appends a string with indentation and a linebreak to |self.lines|.
-
- Args:
- string: The string to print.
- indent_diff: the difference of indentation of the printed line,
- compared to the next/previous printed line. Increment occurs
- after printing the line, while decrement occurs before that.
- '''
- indent_diff *= 2
- if indent_diff < 0:
- self.indent = self.indent[(-indent_diff):]
- if string != '':
- self.lines.append(self.indent + string)
- else:
- self.lines.append('')
- if indent_diff > 0:
- self.indent += ''.ljust(indent_diff)
-
- def AddLines(self, other):
- '''Appends the content of another |IndentedStringBuilder| to |self.lines|.
- Indentation of the added lines will be the sum of |self.indent| and
- their original indentation.
-
- Args:
- other: The buffer from which lines are copied.
- '''
- for line in other.lines:
- self.AddLine(line)
-
- def ToString(self):
- '''Returns |self.lines| as text string.'''
- return NEWLINE.join(self.lines)
-
-
-class AdmWriter(template_writer.TemplateWriter):
- '''Class for generating policy templates in Windows ADM format.
- It is used by PolicyTemplateGenerator to write ADM files.
- '''
-
- TYPE_TO_INPUT = {
- 'string': 'EDITTEXT',
- 'int': 'NUMERIC',
- 'string-enum': 'DROPDOWNLIST',
- 'int-enum': 'DROPDOWNLIST',
- 'list': 'LISTBOX',
- 'string-enum-list': 'LISTBOX',
- 'dict': 'EDITTEXT'
- }
-
- def _Escape(self, string):
- return string.replace('.', '_')
-
- def _AddGuiString(self, name, value):
- # The |name| must be escaped.
- assert name == self._Escape(name)
- # Escape newlines in the value.
- value = value.replace('\n', '\\n')
- if name in self.strings_seen:
- err = ('%s was added as "%s" and now added again as "%s"' %
- (name, self.strings_seen[name], value))
- assert value == self.strings_seen[name], err
- else:
- self.strings_seen[name] = value
- line = '%s="%s"' % (name, value)
- self.strings.AddLine(line)
-
- def _WriteSupported(self, builder):
- builder.AddLine('#if version >= 4', 1)
- builder.AddLine('SUPPORTED !!SUPPORTED_WINXPSP2')
- builder.AddLine('#endif', -1)
-
- def _WritePart(self, policy, key_name, builder):
- '''Writes the PART ... END PART section of a policy.
-
- Args:
- policy: The policy to write to the output.
- key_name: The registry key backing the policy.
- builder: Builder to append lines to.
- '''
- policy_part_name = self._Escape(policy['name'] + '_Part')
- self._AddGuiString(policy_part_name, policy['label'])
-
- # Print the PART ... END PART section:
- builder.AddLine()
- adm_type = self.TYPE_TO_INPUT[policy['type']]
- builder.AddLine('PART !!%s %s' % (policy_part_name, adm_type), 1)
- if policy['type'] in ('list', 'string-enum-list'):
- # Note that the following line causes FullArmor ADMX Migrator to create
- # corrupt ADMX files. Please use admx_writer to get ADMX files.
- builder.AddLine('KEYNAME "%s\\%s"' % (key_name, policy['name']))
- builder.AddLine('VALUEPREFIX ""')
- else:
- builder.AddLine('VALUENAME "%s"' % policy['name'])
- if policy['type'] == 'int':
- # The default max for NUMERIC values is 9999 which is too small for us.
- builder.AddLine('MIN 0 MAX 2000000000')
- if policy['type'] in ('string', 'dict'):
- # The default max for EDITTEXT values is 1023, which is too small for
- # big JSON blobs and other string policies.
- builder.AddLine('MAXLEN 1000000')
- if policy['type'] in ('int-enum', 'string-enum'):
- builder.AddLine('ITEMLIST', 1)
- for item in policy['items']:
- if policy['type'] == 'int-enum':
- value_text = 'NUMERIC ' + str(item['value'])
- else:
- value_text = '"' + item['value'] + '"'
- string_id = self._Escape(item['name'] + '_DropDown')
- builder.AddLine('NAME !!%s VALUE %s' % (string_id, value_text))
- self._AddGuiString(string_id, item['caption'])
- builder.AddLine('END ITEMLIST', -1)
- builder.AddLine('END PART', -1)
-
- def _WritePolicy(self, policy, key_name, builder):
- if policy['type'] == 'external':
- # This type can only be set through cloud policy.
- return
-
- policy_name = self._Escape(policy['name'] + '_Policy')
- self._AddGuiString(policy_name, policy['caption'])
- builder.AddLine('POLICY !!%s' % policy_name, 1)
- self._WriteSupported(builder)
- policy_explain_name = self._Escape(policy['name'] + '_Explain')
- self._AddGuiString(policy_explain_name, policy['desc'])
- builder.AddLine('EXPLAIN !!' + policy_explain_name)
-
- if policy['type'] == 'main':
- builder.AddLine('VALUENAME "%s"' % policy['name'])
- builder.AddLine('VALUEON NUMERIC 1')
- builder.AddLine('VALUEOFF NUMERIC 0')
- else:
- self._WritePart(policy, key_name, builder)
-
- builder.AddLine('END POLICY', -1)
- builder.AddLine()
-
- def WriteComment(self, comment):
- self.lines.AddLine('; ' + comment)
-
- def WritePolicy(self, policy):
- if self.CanBeMandatory(policy):
- self._WritePolicy(policy,
- self.config['win_reg_mandatory_key_name'],
- self.policies)
-
- def WriteRecommendedPolicy(self, policy):
- self._WritePolicy(policy,
- self.config['win_reg_recommended_key_name'],
- self.recommended_policies)
-
- def BeginPolicyGroup(self, group):
- category_name = self._Escape(group['name'] + '_Category')
- self._AddGuiString(category_name, group['caption'])
- self.policies.AddLine('CATEGORY !!' + category_name, 1)
-
- def EndPolicyGroup(self):
- self.policies.AddLine('END CATEGORY', -1)
- self.policies.AddLine('')
-
- def BeginRecommendedPolicyGroup(self, group):
- category_name = self._Escape(group['name'] + '_Category')
- self._AddGuiString(category_name, group['caption'])
- self.recommended_policies.AddLine('CATEGORY !!' + category_name, 1)
-
- def EndRecommendedPolicyGroup(self):
- self.recommended_policies.AddLine('END CATEGORY', -1)
- self.recommended_policies.AddLine('')
-
- def _CreateTemplate(self, category_path, key_name, policies):
- '''Creates the whole ADM template except for the [Strings] section, and
- returns it as an |IndentedStringBuilder|.
-
- Args:
- category_path: List of strings representing the category path.
- key_name: Main registry key backing the policies.
- policies: ADM code for all the policies in an |IndentedStringBuilder|.
- '''
- lines = IndentedStringBuilder()
- for part in category_path:
- lines.AddLine('CATEGORY !!' + part, 1)
- lines.AddLine('KEYNAME "%s"' % key_name)
- lines.AddLine()
-
- lines.AddLines(policies)
-
- for part in category_path:
- lines.AddLine('END CATEGORY', -1)
- lines.AddLine()
-
- return lines
-
- def BeginTemplate(self):
- if self._GetChromiumVersionString() is not None:
- self.WriteComment(self.config['build'] + ' version: ' + \
- self._GetChromiumVersionString())
- self._AddGuiString(self.config['win_supported_os'],
- self.messages['win_supported_winxpsp2']['text'])
- category_path = self.config['win_mandatory_category_path']
- recommended_category_path = self.config['win_recommended_category_path']
- recommended_name = '%s - %s' % \
- (self.config['app_name'], self.messages['doc_recommended']['text'])
- if self.config['build'] == 'chrome':
- self._AddGuiString(category_path[0], 'Google')
- self._AddGuiString(category_path[1], self.config['app_name'])
- self._AddGuiString(recommended_category_path[1], recommended_name)
- elif self.config['build'] == 'chromium':
- self._AddGuiString(category_path[0], self.config['app_name'])
- self._AddGuiString(recommended_category_path[0], recommended_name)
- # All the policies will be written into self.policies.
- # The final template text will be assembled into self.lines by
- # self.EndTemplate().
-
- def EndTemplate(self):
- # Copy policies into self.lines.
- policy_class = self.config['win_group_policy_class'].upper()
- for class_name in ['MACHINE', 'USER']:
- if policy_class != 'BOTH' and policy_class != class_name:
- continue
- self.lines.AddLine('CLASS ' + class_name, 1)
- self.lines.AddLines(self._CreateTemplate(
- self.config['win_mandatory_category_path'],
- self.config['win_reg_mandatory_key_name'],
- self.policies))
- self.lines.AddLines(self._CreateTemplate(
- self.config['win_recommended_category_path'],
- self.config['win_reg_recommended_key_name'],
- self.recommended_policies))
- self.lines.AddLine('', -1)
- # Copy user strings into self.lines.
- self.lines.AddLine('[Strings]')
- self.lines.AddLines(self.strings)
-
- def Init(self):
- # String buffer for building the whole ADM file.
- self.lines = IndentedStringBuilder()
- # String buffer for building the strings section of the ADM file.
- self.strings = IndentedStringBuilder()
- # Map of strings seen, to avoid duplicates.
- self.strings_seen = {}
- # String buffer for building the policies of the ADM file.
- self.policies = IndentedStringBuilder()
- # String buffer for building the recommended policies of the ADM file.
- self.recommended_policies = IndentedStringBuilder()
-
- def GetTemplateText(self):
- return self.lines.ToString()
diff --git a/grit/format/policy_templates/writers/adm_writer_unittest.py b/grit/format/policy_templates/writers/adm_writer_unittest.py
deleted file mode 100644
index c5c64f7..0000000
--- a/grit/format/policy_templates/writers/adm_writer_unittest.py
+++ /dev/null
@@ -1,1127 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.policy_templates.writers.adm_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import writer_unittest_common
-
-
-class AdmWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for AdmWriter.'''
-
- def ConstructOutput(self, classes, body, strings):
- result = []
- for clazz in classes:
- result.append('CLASS ' + clazz)
- result.append(body)
- result.append(strings)
- return ''.join(result)
-
- def CompareOutputs(self, output, expected_output):
- '''Compares the output of the adm_writer with its expected output.
-
- Args:
- output: The output of the adm writer as returned by grit.
- expected_output: The expected output.
-
- Raises:
- AssertionError: if the two strings are not equivalent.
- '''
- self.assertEquals(
- output.strip(),
- expected_output.strip().replace('\n', '\r\n'))
-
- def testEmpty(self):
- # Test PListWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least "Windows 3.11', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium': '1',}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least "Windows 3.11"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"''')
- self.CompareOutputs(output, expected_output)
-
- def testVersionAnnotation(self):
- # Test PListWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least "Windows 3.11', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(
- grd, 'fr', {'_chromium': '1', 'version':'39.0.0.0'}, 'adm', 'en')
- expected_output = '; chromium version: 39.0.0.0\n' + \
- self.ConstructOutput(['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least "Windows 3.11"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"''')
- self.CompareOutputs(output, expected_output)
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainPolicy',
- 'type': 'main',
- 'supported_on': ['chrome.win:8-'],
- 'features': { 'can_be_recommended': True },
- 'caption': 'Caption of main.',
- 'desc': 'Description of main.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.12', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- POLICY !!MainPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!MainPolicy_Explain
- VALUENAME "MainPolicy"
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
- CATEGORY !!google
- CATEGORY !!googlechrome_recommended
- KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
-
- POLICY !!MainPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!MainPolicy_Explain
- VALUENAME "MainPolicy"
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.12"
-google="Google"
-googlechrome="Google Chrome"
-googlechrome_recommended="Google Chrome - Recommended"
-MainPolicy_Policy="Caption of main."
-MainPolicy_Explain="Description of main."''')
- self.CompareOutputs(output, expected_output)
-
- def testMainPolicyRecommendedOnly(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainPolicy',
- 'type': 'main',
- 'supported_on': ['chrome.win:8-'],
- 'features': {
- 'can_be_recommended': True,
- 'can_be_mandatory': False
- },
- 'caption': 'Caption of main.',
- 'desc': 'Description of main.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.12', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- END CATEGORY
- END CATEGORY
-
- CATEGORY !!google
- CATEGORY !!googlechrome_recommended
- KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
-
- POLICY !!MainPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!MainPolicy_Explain
- VALUENAME "MainPolicy"
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.12"
-google="Google"
-googlechrome="Google Chrome"
-googlechrome_recommended="Google Chrome - Recommended"
-MainPolicy_Policy="Caption of main."
-MainPolicy_Explain="Description of main."''')
- self.CompareOutputs(output, expected_output)
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'StringPolicy',
- 'type': 'string',
- 'supported_on': ['chrome.win:8-'],
- 'features': { 'can_be_recommended': True },
- 'desc': """Description of group.
-With a newline.""",
- 'caption': 'Caption of policy.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.13', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- POLICY !!StringPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!StringPolicy_Explain
-
- PART !!StringPolicy_Part EDITTEXT
- VALUENAME "StringPolicy"
- MAXLEN 1000000
- END PART
- END POLICY
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- POLICY !!StringPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!StringPolicy_Explain
-
- PART !!StringPolicy_Part EDITTEXT
- VALUENAME "StringPolicy"
- MAXLEN 1000000
- END PART
- END POLICY
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.13"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"
-StringPolicy_Policy="Caption of policy."
-StringPolicy_Explain="Description of group.\\nWith a newline."
-StringPolicy_Part="Caption of policy."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testIntPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'IntPolicy',
- 'type': 'int',
- 'caption': 'Caption of policy.',
- 'features': { 'can_be_recommended': True },
- 'desc': 'Description of policy.',
- 'supported_on': ['chrome.win:8-']
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.13', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- POLICY !!IntPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!IntPolicy_Explain
-
- PART !!IntPolicy_Part NUMERIC
- VALUENAME "IntPolicy"
- MIN 0 MAX 2000000000
- END PART
- END POLICY
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- POLICY !!IntPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!IntPolicy_Explain
-
- PART !!IntPolicy_Part NUMERIC
- VALUENAME "IntPolicy"
- MIN 0 MAX 2000000000
- END PART
- END POLICY
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.13"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"
-IntPolicy_Policy="Caption of policy."
-IntPolicy_Explain="Description of policy."
-IntPolicy_Part="Caption of policy."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumPolicy',
- 'type': 'int-enum',
- 'items': [
- {
- 'name': 'ProxyServerDisabled',
- 'value': 0,
- 'caption': 'Option1',
- },
- {
- 'name': 'ProxyServerAutoDetect',
- 'value': 1,
- 'caption': 'Option2',
- },
- ],
- 'desc': 'Description of policy.',
- 'caption': 'Caption of policy.',
- 'supported_on': ['chrome.win:8-'],
- 'features': { 'can_be_recommended': True },
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.14', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- POLICY !!EnumPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!EnumPolicy_Explain
-
- PART !!EnumPolicy_Part DROPDOWNLIST
- VALUENAME "EnumPolicy"
- ITEMLIST
- NAME !!ProxyServerDisabled_DropDown VALUE NUMERIC 0
- NAME !!ProxyServerAutoDetect_DropDown VALUE NUMERIC 1
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
- CATEGORY !!google
- CATEGORY !!googlechrome_recommended
- KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
-
- POLICY !!EnumPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!EnumPolicy_Explain
-
- PART !!EnumPolicy_Part DROPDOWNLIST
- VALUENAME "EnumPolicy"
- ITEMLIST
- NAME !!ProxyServerDisabled_DropDown VALUE NUMERIC 0
- NAME !!ProxyServerAutoDetect_DropDown VALUE NUMERIC 1
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.14"
-google="Google"
-googlechrome="Google Chrome"
-googlechrome_recommended="Google Chrome - Recommended"
-EnumPolicy_Policy="Caption of policy."
-EnumPolicy_Explain="Description of policy."
-EnumPolicy_Part="Caption of policy."
-ProxyServerDisabled_DropDown="Option1"
-ProxyServerAutoDetect_DropDown="Option2"
-''')
- self.CompareOutputs(output, expected_output)
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumPolicy',
- 'type': 'string-enum',
- 'caption': 'Caption of policy.',
- 'desc': 'Description of policy.',
- 'items': [
- {'name': 'ProxyServerDisabled', 'value': 'one',
- 'caption': 'Option1'},
- {'name': 'ProxyServerAutoDetect', 'value': 'two',
- 'caption': 'Option2'},
- ],
- 'supported_on': ['chrome.win:8-'],
- 'features': { 'can_be_recommended': True },
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.14', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- POLICY !!EnumPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!EnumPolicy_Explain
-
- PART !!EnumPolicy_Part DROPDOWNLIST
- VALUENAME "EnumPolicy"
- ITEMLIST
- NAME !!ProxyServerDisabled_DropDown VALUE "one"
- NAME !!ProxyServerAutoDetect_DropDown VALUE "two"
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
- CATEGORY !!google
- CATEGORY !!googlechrome_recommended
- KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
-
- POLICY !!EnumPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!EnumPolicy_Explain
-
- PART !!EnumPolicy_Part DROPDOWNLIST
- VALUENAME "EnumPolicy"
- ITEMLIST
- NAME !!ProxyServerDisabled_DropDown VALUE "one"
- NAME !!ProxyServerAutoDetect_DropDown VALUE "two"
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.14"
-google="Google"
-googlechrome="Google Chrome"
-googlechrome_recommended="Google Chrome - Recommended"
-EnumPolicy_Policy="Caption of policy."
-EnumPolicy_Explain="Description of policy."
-EnumPolicy_Part="Caption of policy."
-ProxyServerDisabled_DropDown="Option1"
-ProxyServerAutoDetect_DropDown="Option2"
-''')
- self.CompareOutputs(output, expected_output)
-
- def testListPolicy(self):
- # Tests a policy group with a single policy of type 'list'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'ListPolicy',
- 'type': 'list',
- 'supported_on': ['chrome.win:8-'],
- 'features': { 'can_be_recommended': True },
- 'desc': """Description of list policy.
-With a newline.""",
- 'caption': 'Caption of list policy.',
- 'label': 'Label of list policy.'
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.15', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- },
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- POLICY !!ListPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!ListPolicy_Explain
-
- PART !!ListPolicy_Part LISTBOX
- KEYNAME "Software\\Policies\\Chromium\\ListPolicy"
- VALUEPREFIX ""
- END PART
- END POLICY
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- POLICY !!ListPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!ListPolicy_Explain
-
- PART !!ListPolicy_Part LISTBOX
- KEYNAME "Software\\Policies\\Chromium\\Recommended\\ListPolicy"
- VALUEPREFIX ""
- END PART
- END POLICY
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.15"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"
-ListPolicy_Policy="Caption of list policy."
-ListPolicy_Explain="Description of list policy.\\nWith a newline."
-ListPolicy_Part="Label of list policy."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testStringEnumListPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum-list'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'ListPolicy',
- 'type': 'string-enum-list',
- 'supported_on': ['chrome.win:8-'],
- 'features': { 'can_be_recommended': True },
- 'desc': """Description of list policy.
-With a newline.""",
- 'items': [
- {'name': 'ProxyServerDisabled', 'value': 'one',
- 'caption': 'Option1'},
- {'name': 'ProxyServerAutoDetect', 'value': 'two',
- 'caption': 'Option2'},
- ],
- 'caption': 'Caption of list policy.',
- 'label': 'Label of list policy.'
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.15', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- },
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- POLICY !!ListPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!ListPolicy_Explain
-
- PART !!ListPolicy_Part LISTBOX
- KEYNAME "Software\\Policies\\Chromium\\ListPolicy"
- VALUEPREFIX ""
- END PART
- END POLICY
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- POLICY !!ListPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!ListPolicy_Explain
-
- PART !!ListPolicy_Part LISTBOX
- KEYNAME "Software\\Policies\\Chromium\\Recommended\\ListPolicy"
- VALUEPREFIX ""
- END PART
- END POLICY
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.15"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"
-ListPolicy_Policy="Caption of list policy."
-ListPolicy_Explain="Description of list policy.\\nWith a newline."
-ListPolicy_Part="Label of list policy."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testDictionaryPolicy(self):
- # Tests a policy group with a single policy of type 'dict'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'DictionaryPolicy',
- 'type': 'dict',
- 'supported_on': ['chrome.win:8-'],
- 'features': { 'can_be_recommended': True },
- 'desc': 'Description of group.',
- 'caption': 'Caption of policy.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.13', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- POLICY !!DictionaryPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!DictionaryPolicy_Explain
-
- PART !!DictionaryPolicy_Part EDITTEXT
- VALUENAME "DictionaryPolicy"
- MAXLEN 1000000
- END PART
- END POLICY
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- POLICY !!DictionaryPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!DictionaryPolicy_Explain
-
- PART !!DictionaryPolicy_Part EDITTEXT
- VALUENAME "DictionaryPolicy"
- MAXLEN 1000000
- END PART
- END POLICY
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.13"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"
-DictionaryPolicy_Policy="Caption of policy."
-DictionaryPolicy_Explain="Description of group."
-DictionaryPolicy_Part="Caption of policy."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Windows, so it shouldn't
- # be included in the ADM file.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'NonWinGroup',
- 'type': 'group',
- 'policies': [{
- 'name': 'NonWinPolicy',
- 'type': 'list',
- 'supported_on': ['chrome.linux:8-', 'chrome.mac:8-'],
- 'caption': 'Caption of list policy.',
- 'desc': 'Desc of list policy.',
- }],
- 'caption': 'Group caption.',
- 'desc': 'Group description.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.16', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.16"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"
-''')
- self.CompareOutputs(output, expected_output)
-
- def testNonRecommendedPolicy(self):
- # Tests a policy that is not recommended, so it should be included.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainPolicy',
- 'type': 'main',
- 'supported_on': ['chrome.win:8-'],
- 'caption': 'Caption of main.',
- 'desc': 'Description of main.',
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.12', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- POLICY !!MainPolicy_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!MainPolicy_Explain
- VALUENAME "MainPolicy"
- VALUEON NUMERIC 1
- VALUEOFF NUMERIC 0
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
- CATEGORY !!google
- CATEGORY !!googlechrome_recommended
- KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
-
- END CATEGORY
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.12"
-google="Google"
-googlechrome="Google Chrome"
-googlechrome_recommended="Google Chrome - Recommended"
-MainPolicy_Policy="Caption of main."
-MainPolicy_Explain="Description of main."''')
- self.CompareOutputs(output, expected_output)
-
- def testPolicyGroup(self):
- # Tests a policy group that has more than one policies.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'Group1',
- 'type': 'group',
- 'desc': 'Description of group.',
- 'caption': 'Caption of group.',
- 'policies': [{
- 'name': 'Policy1',
- 'type': 'list',
- 'supported_on': ['chrome.win:8-'],
- 'features': { 'can_be_recommended': True },
- 'caption': 'Caption of policy1.',
- 'desc': """Description of policy1.
-With a newline."""
- },{
- 'name': 'Policy2',
- 'type': 'string',
- 'supported_on': ['chrome.win:8-'],
- 'caption': 'Caption of policy2.',
- 'desc': """Description of policy2.
-With a newline."""
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.16', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!chromium
- KEYNAME "Software\\Policies\\Chromium"
-
- CATEGORY !!Group1_Category
- POLICY !!Policy1_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!Policy1_Explain
-
- PART !!Policy1_Part LISTBOX
- KEYNAME "Software\\Policies\\Chromium\\Policy1"
- VALUEPREFIX ""
- END PART
- END POLICY
-
- POLICY !!Policy2_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!Policy2_Explain
-
- PART !!Policy2_Part EDITTEXT
- VALUENAME "Policy2"
- MAXLEN 1000000
- END PART
- END POLICY
-
- END CATEGORY
-
- END CATEGORY
-
- CATEGORY !!chromium_recommended
- KEYNAME "Software\\Policies\\Chromium\\Recommended"
-
- CATEGORY !!Group1_Category
- POLICY !!Policy1_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!Policy1_Explain
-
- PART !!Policy1_Part LISTBOX
- KEYNAME "Software\\Policies\\Chromium\\Recommended\\Policy1"
- VALUEPREFIX ""
- END PART
- END POLICY
-
- END CATEGORY
-
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.16"
-chromium="Chromium"
-chromium_recommended="Chromium - Recommended"
-Group1_Category="Caption of group."
-Policy1_Policy="Caption of policy1."
-Policy1_Explain="Description of policy1.\\nWith a newline."
-Policy1_Part="Caption of policy1."
-Policy2_Policy="Caption of policy2."
-Policy2_Explain="Description of policy2.\\nWith a newline."
-Policy2_Part="Caption of policy2."
-''')
- self.CompareOutputs(output, expected_output)
-
- def testDuplicatedStringEnumPolicy(self):
- # Verifies that duplicated enum constants get merged, and that
- # string constants get escaped.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumPolicy.A',
- 'type': 'string-enum',
- 'caption': 'Caption of policy A.',
- 'desc': 'Description of policy A.',
- 'items': [
- {'name': 'tls1.2', 'value': 'tls1.2', 'caption': 'tls1.2' },
- ],
- 'supported_on': ['chrome.win:39-'],
- },
- {
- 'name': 'EnumPolicy.B',
- 'type': 'string-enum',
- 'caption': 'Caption of policy B.',
- 'desc': 'Description of policy B.',
- 'items': [
- {'name': 'tls1.2', 'value': 'tls1.2', 'caption': 'tls1.2' },
- ],
- 'supported_on': ['chrome.win:39-'],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'win_supported_winxpsp2': {
- 'text': 'At least Windows 3.14', 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended', 'desc': 'bleh'
- }
- }
- }''')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'adm', 'en')
- expected_output = self.ConstructOutput(
- ['MACHINE', 'USER'], '''
- CATEGORY !!google
- CATEGORY !!googlechrome
- KEYNAME "Software\\Policies\\Google\\Chrome"
-
- POLICY !!EnumPolicy_A_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!EnumPolicy_A_Explain
-
- PART !!EnumPolicy_A_Part DROPDOWNLIST
- VALUENAME "EnumPolicy.A"
- ITEMLIST
- NAME !!tls1_2_DropDown VALUE "tls1.2"
- END ITEMLIST
- END PART
- END POLICY
-
- POLICY !!EnumPolicy_B_Policy
- #if version >= 4
- SUPPORTED !!SUPPORTED_WINXPSP2
- #endif
- EXPLAIN !!EnumPolicy_B_Explain
-
- PART !!EnumPolicy_B_Part DROPDOWNLIST
- VALUENAME "EnumPolicy.B"
- ITEMLIST
- NAME !!tls1_2_DropDown VALUE "tls1.2"
- END ITEMLIST
- END PART
- END POLICY
-
- END CATEGORY
- END CATEGORY
-
- CATEGORY !!google
- CATEGORY !!googlechrome_recommended
- KEYNAME "Software\\Policies\\Google\\Chrome\\Recommended"
-
- END CATEGORY
- END CATEGORY
-
-
-''', '''[Strings]
-SUPPORTED_WINXPSP2="At least Windows 3.14"
-google="Google"
-googlechrome="Google Chrome"
-googlechrome_recommended="Google Chrome - Recommended"
-EnumPolicy_A_Policy="Caption of policy A."
-EnumPolicy_A_Explain="Description of policy A."
-EnumPolicy_A_Part="Caption of policy A."
-tls1_2_DropDown="tls1.2"
-EnumPolicy_B_Policy="Caption of policy B."
-EnumPolicy_B_Explain="Description of policy B."
-EnumPolicy_B_Part="Caption of policy B."
-''')
- self.CompareOutputs(output, expected_output)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/adml_writer.py b/grit/format/policy_templates/writers/adml_writer.py
deleted file mode 100644
index 64f8562..0000000
--- a/grit/format/policy_templates/writers/adml_writer.py
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import xml_formatted_writer
-
-
-def GetWriter(config):
- '''Factory method for instanciating the ADMLWriter. Every Writer needs a
- GetWriter method because the TemplateFormatter uses this method to
- instantiate a Writer.
- '''
- return ADMLWriter(['win'], config)
-
-
-class ADMLWriter(xml_formatted_writer.XMLFormattedWriter):
- ''' Class for generating an ADML policy template. It is used by the
- PolicyTemplateGenerator to write the ADML file.
- '''
-
- # DOM root node of the generated ADML document.
- _doc = None
-
- # The string-table contains all ADML "string" elements.
- _string_table_elem = None
-
- # The presentation-table is the container for presentation elements, that
- # describe the presentation of Policy-Groups and Policies.
- _presentation_table_elem = None
-
- def _AddString(self, id, text):
- ''' Adds an ADML "string" element to _string_table_elem. The following
- ADML snippet contains an example:
-
- <string id="$(id)">$(text)</string>
-
- Args:
- id: ID of the newly created "string" element.
- text: Value of the newly created "string" element.
- '''
- id = id.replace('.', '_')
- if id in self.strings_seen:
- assert text == self.strings_seen[id]
- else:
- self.strings_seen[id] = text
- string_elem = self.AddElement(
- self._string_table_elem, 'string', {'id': id})
- string_elem.appendChild(self._doc.createTextNode(text))
-
- def WritePolicy(self, policy):
- '''Generates the ADML elements for a Policy.
- <stringTable>
- ...
- <string id="$(policy_group_name)">$(caption)</string>
- <string id="$(policy_group_name)_Explain">$(description)</string>
- </stringTable>
-
- <presentationTables>
- ...
- <presentation id=$(policy_group_name)/>
- </presentationTables>
-
- Args:
- policy: The Policy to generate ADML elements for.
- '''
- policy_type = policy['type']
- policy_name = policy['name']
- if 'caption' in policy:
- policy_caption = policy['caption']
- else:
- policy_caption = policy_name
- if 'desc' in policy:
- policy_description = policy['desc']
- else:
- policy_description = policy_name
- if 'label' in policy:
- policy_label = policy['label']
- else:
- policy_label = policy_name
-
- self._AddString(policy_name, policy_caption)
- self._AddString(policy_name + '_Explain', policy_description)
- presentation_elem = self.AddElement(
- self._presentation_table_elem, 'presentation', {'id': policy_name})
-
- if policy_type == 'main':
- pass
- elif policy_type in ('string', 'dict'):
- # 'dict' policies are configured as JSON-encoded strings on Windows.
- textbox_elem = self.AddElement(presentation_elem, 'textBox',
- {'refId': policy_name})
- label_elem = self.AddElement(textbox_elem, 'label')
- label_elem.appendChild(self._doc.createTextNode(policy_label))
- elif policy_type == 'int':
- textbox_elem = self.AddElement(presentation_elem, 'decimalTextBox',
- {'refId': policy_name})
- textbox_elem.appendChild(self._doc.createTextNode(policy_label + ':'))
- elif policy_type in ('int-enum', 'string-enum'):
- for item in policy['items']:
- self._AddString(item['name'], item['caption'])
- dropdownlist_elem = self.AddElement(presentation_elem, 'dropdownList',
- {'refId': policy_name})
- dropdownlist_elem.appendChild(self._doc.createTextNode(policy_label))
- elif policy_type in ('list', 'string-enum-list'):
- self._AddString(policy_name + 'Desc', policy_caption)
- listbox_elem = self.AddElement(presentation_elem, 'listBox',
- {'refId': policy_name + 'Desc'})
- listbox_elem.appendChild(self._doc.createTextNode(policy_label))
- elif policy_type == 'group':
- pass
- elif policy_type == 'external':
- # This type can only be set through cloud policy.
- pass
- else:
- raise Exception('Unknown policy type %s.' % policy_type)
-
- def BeginPolicyGroup(self, group):
- '''Generates ADML elements for a Policy-Group. For each Policy-Group two
- ADML "string" elements are added to the string-table. One contains the
- caption of the Policy-Group and the other a description. A Policy-Group also
- requires an ADML "presentation" element that must be added to the
- presentation-table. The "presentation" element is the container for the
- elements that define the visual presentation of the Policy-Goup's Policies.
- The following ADML snippet shows an example:
-
- Args:
- group: The Policy-Group to generate ADML elements for.
- '''
- # Add ADML "string" elements to the string-table that are required by a
- # Policy-Group.
- self._AddString(group['name'] + '_group', group['caption'])
-
- def _AddBaseStrings(self, build):
- ''' Adds ADML "string" elements to the string-table that are referenced by
- the ADMX file but not related to any specific Policy-Group or Policy.
- '''
- self._AddString(self.config['win_supported_os'],
- self.messages['win_supported_winxpsp2']['text'])
- recommended_name = '%s - %s' % \
- (self.config['app_name'], self.messages['doc_recommended']['text'])
- if build == 'chrome':
- self._AddString(self.config['win_mandatory_category_path'][0],
- 'Google')
- self._AddString(self.config['win_mandatory_category_path'][1],
- self.config['app_name'])
- self._AddString(self.config['win_recommended_category_path'][1],
- recommended_name)
- elif build == 'chromium':
- self._AddString(self.config['win_mandatory_category_path'][0],
- self.config['app_name'])
- self._AddString(self.config['win_recommended_category_path'][0],
- recommended_name)
-
- def BeginTemplate(self):
- dom_impl = minidom.getDOMImplementation('')
- self._doc = dom_impl.createDocument(None, 'policyDefinitionResources',
- None)
- if self._GetChromiumVersionString() is not None:
- self.AddComment(self._doc.documentElement, self.config['build'] + \
- ' version: ' + self._GetChromiumVersionString())
- policy_definitions_resources_elem = self._doc.documentElement
- policy_definitions_resources_elem.attributes['revision'] = '1.0'
- policy_definitions_resources_elem.attributes['schemaVersion'] = '1.0'
-
- self.AddElement(policy_definitions_resources_elem, 'displayName')
- self.AddElement(policy_definitions_resources_elem, 'description')
- resources_elem = self.AddElement(policy_definitions_resources_elem,
- 'resources')
- self._string_table_elem = self.AddElement(resources_elem, 'stringTable')
- self._AddBaseStrings(self.config['build'])
- self._presentation_table_elem = self.AddElement(resources_elem,
- 'presentationTable')
-
- def Init(self):
- # Map of all strings seen.
- self.strings_seen = {}
-
- def GetTemplateText(self):
- # Using "toprettyxml()" confuses the Windows Group Policy Editor
- # (gpedit.msc) because it interprets whitespace characters in text between
- # the "string" tags. This prevents gpedit.msc from displaying the category
- # names correctly.
- # TODO(markusheintz): Find a better formatting that works with gpedit.
- return self._doc.toxml()
diff --git a/grit/format/policy_templates/writers/adml_writer_unittest.py b/grit/format/policy_templates/writers/adml_writer_unittest.py
deleted file mode 100644
index 08bec58..0000000
--- a/grit/format/policy_templates/writers/adml_writer_unittest.py
+++ /dev/null
@@ -1,437 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-"""Unittests for grit.format.policy_templates.writers.adml_writer."""
-
-
-import os
-import sys
-import unittest
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-
-from grit.format.policy_templates.writers import adml_writer
-from grit.format.policy_templates.writers import xml_writer_base_unittest
-
-
-class AdmlWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest):
-
- def setUp(self):
- config = {
- 'app_name': 'test',
- 'build': 'test',
- 'win_supported_os': 'SUPPORTED_TESTOS',
- }
- self.writer = adml_writer.GetWriter(config)
- self.writer.messages = {
- 'win_supported_winxpsp2': {
- 'text': 'Supported on Test OS or higher',
- 'desc': 'blah'
- },
- 'doc_recommended': {
- 'text': 'Recommended',
- 'desc': 'bleh'
- },
- }
- self.writer.Init()
-
- def _InitWriterForAddingPolicyGroups(self, writer):
- '''Initialize the writer for adding policy groups. This method must be
- called before the method "BeginPolicyGroup" can be called. It initializes
- attributes of the writer.
- '''
- writer.BeginTemplate()
-
- def _InitWriterForAddingPolicies(self, writer, policy):
- '''Initialize the writer for adding policies. This method must be
- called before the method "WritePolicy" can be called. It initializes
- attributes of the writer.
- '''
- self._InitWriterForAddingPolicyGroups(writer)
- policy_group = {
- 'name': 'PolicyGroup',
- 'caption': 'Test Caption',
- 'desc': 'This is the test description of the test policy group.',
- 'policies': policy,
- }
- writer.BeginPolicyGroup(policy_group)
-
- string_elements = \
- self.writer._string_table_elem.getElementsByTagName('string')
- for elem in string_elements:
- self.writer._string_table_elem.removeChild(elem)
-
- def testEmpty(self):
- self.writer.BeginTemplate()
- self.writer.EndTemplate()
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?><policyDefinitionResources'
- ' revision="1.0" schemaVersion="1.0"><displayName/><description/>'
- '<resources><stringTable><string id="SUPPORTED_TESTOS">Supported on'
- ' Test OS or higher</string></stringTable><presentationTable/>'
- '</resources></policyDefinitionResources>')
- self.AssertXMLEquals(output, expected_output)
-
- def testVersionAnnotation(self):
- self.writer.config['version'] = '39.0.0.0'
- self.writer.BeginTemplate()
- self.writer.EndTemplate()
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?><policyDefinitionResources'
- ' revision="1.0" schemaVersion="1.0"><!--test version: 39.0.0.0-->'
- '<displayName/><description/><resources><stringTable>'
- '<string id="SUPPORTED_TESTOS">Supported on'
- ' Test OS or higher</string></stringTable><presentationTable/>'
- '</resources></policyDefinitionResources>')
- self.AssertXMLEquals(output, expected_output)
-
- def testPolicyGroup(self):
- empty_policy_group = {
- 'name': 'PolicyGroup',
- 'caption': 'Test Group Caption',
- 'desc': 'This is the test description of the test policy group.',
- 'policies': [
- {'name': 'PolicyStub2',
- 'type': 'main'},
- {'name': 'PolicyStub1',
- 'type': 'main'},
- ],
- }
- self._InitWriterForAddingPolicyGroups(self.writer)
- self.writer.BeginPolicyGroup(empty_policy_group)
- self.writer.EndPolicyGroup
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="SUPPORTED_TESTOS">'
- 'Supported on Test OS or higher</string>\n'
- '<string id="PolicyGroup_group">Test Group Caption</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = ''
- self.AssertXMLEquals(output, expected_output)
-
- def testMainPolicy(self):
- main_policy = {
- 'name': 'DummyMainPolicy',
- 'type': 'main',
- 'caption': 'Main policy caption',
- 'desc': 'Main policy test description.'
- }
- self. _InitWriterForAddingPolicies(self.writer, main_policy)
- self.writer.WritePolicy(main_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="DummyMainPolicy">Main policy caption</string>\n'
- '<string id="DummyMainPolicy_Explain">'
- 'Main policy test description.</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = '<presentation id="DummyMainPolicy"/>'
- self.AssertXMLEquals(output, expected_output)
-
- def testStringPolicy(self):
- string_policy = {
- 'name': 'StringPolicyStub',
- 'type': 'string',
- 'caption': 'String policy caption',
- 'label': 'String policy label',
- 'desc': 'This is a test description.',
- }
- self. _InitWriterForAddingPolicies(self.writer, string_policy)
- self.writer.WritePolicy(string_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="StringPolicyStub">String policy caption</string>\n'
- '<string id="StringPolicyStub_Explain">'
- 'This is a test description.</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="StringPolicyStub">\n'
- ' <textBox refId="StringPolicyStub">\n'
- ' <label>String policy label</label>\n'
- ' </textBox>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testIntPolicy(self):
- int_policy = {
- 'name': 'IntPolicyStub',
- 'type': 'int',
- 'caption': 'Int policy caption',
- 'label': 'Int policy label',
- 'desc': 'This is a test description.',
- }
- self. _InitWriterForAddingPolicies(self.writer, int_policy)
- self.writer.WritePolicy(int_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="IntPolicyStub">Int policy caption</string>\n'
- '<string id="IntPolicyStub_Explain">'
- 'This is a test description.</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="IntPolicyStub">\n'
- ' <decimalTextBox refId="IntPolicyStub">'
- 'Int policy label:</decimalTextBox>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testIntEnumPolicy(self):
- enum_policy = {
- 'name': 'EnumPolicyStub',
- 'type': 'int-enum',
- 'caption': 'Enum policy caption',
- 'label': 'Enum policy label',
- 'desc': 'This is a test description.',
- 'items': [
- {
- 'name': 'item 1',
- 'value': 1,
- 'caption': 'Caption Item 1',
- },
- {
- 'name': 'item 2',
- 'value': 2,
- 'caption': 'Caption Item 2',
- },
- ],
- }
- self. _InitWriterForAddingPolicies(self.writer, enum_policy)
- self.writer.WritePolicy(enum_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="EnumPolicyStub">Enum policy caption</string>\n'
- '<string id="EnumPolicyStub_Explain">'
- 'This is a test description.</string>\n'
- '<string id="item 1">Caption Item 1</string>\n'
- '<string id="item 2">Caption Item 2</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="EnumPolicyStub">\n'
- ' <dropdownList refId="EnumPolicyStub">'
- 'Enum policy label</dropdownList>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testStringEnumPolicy(self):
- enum_policy = {
- 'name': 'EnumPolicyStub',
- 'type': 'string-enum',
- 'caption': 'Enum policy caption',
- 'label': 'Enum policy label',
- 'desc': 'This is a test description.',
- 'items': [
- {
- 'name': 'item 1',
- 'value': 'value 1',
- 'caption': 'Caption Item 1',
- },
- {
- 'name': 'item 2',
- 'value': 'value 2',
- 'caption': 'Caption Item 2',
- },
- ],
- }
- self. _InitWriterForAddingPolicies(self.writer, enum_policy)
- self.writer.WritePolicy(enum_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="EnumPolicyStub">Enum policy caption</string>\n'
- '<string id="EnumPolicyStub_Explain">'
- 'This is a test description.</string>\n'
- '<string id="item 1">Caption Item 1</string>\n'
- '<string id="item 2">Caption Item 2</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="EnumPolicyStub">\n'
- ' <dropdownList refId="EnumPolicyStub">'
- 'Enum policy label</dropdownList>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testListPolicy(self):
- list_policy = {
- 'name': 'ListPolicyStub',
- 'type': 'list',
- 'caption': 'List policy caption',
- 'label': 'List policy label',
- 'desc': 'This is a test description.',
- }
- self. _InitWriterForAddingPolicies(self.writer, list_policy)
- self.writer.WritePolicy(list_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="ListPolicyStub">List policy caption</string>\n'
- '<string id="ListPolicyStub_Explain">'
- 'This is a test description.</string>\n'
- '<string id="ListPolicyStubDesc">List policy caption</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="ListPolicyStub">\n'
- ' <listBox refId="ListPolicyStubDesc">List policy label</listBox>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testStringEnumListPolicy(self):
- list_policy = {
- 'name': 'ListPolicyStub',
- 'type': 'string-enum-list',
- 'caption': 'List policy caption',
- 'label': 'List policy label',
- 'desc': 'This is a test description.',
- 'items': [
- {
- 'name': 'item 1',
- 'value': 'value 1',
- 'caption': 'Caption Item 1',
- },
- {
- 'name': 'item 2',
- 'value': 'value 2',
- 'caption': 'Caption Item 2',
- },
- ],
- }
- self. _InitWriterForAddingPolicies(self.writer, list_policy)
- self.writer.WritePolicy(list_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="ListPolicyStub">List policy caption</string>\n'
- '<string id="ListPolicyStub_Explain">'
- 'This is a test description.</string>\n'
- '<string id="ListPolicyStubDesc">List policy caption</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="ListPolicyStub">\n'
- ' <listBox refId="ListPolicyStubDesc">List policy label</listBox>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testDictionaryPolicy(self):
- dict_policy = {
- 'name': 'DictionaryPolicyStub',
- 'type': 'dict',
- 'caption': 'Dictionary policy caption',
- 'label': 'Dictionary policy label',
- 'desc': 'This is a test description.',
- }
- self. _InitWriterForAddingPolicies(self.writer, dict_policy)
- self.writer.WritePolicy(dict_policy)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="DictionaryPolicyStub">Dictionary policy caption</string>\n'
- '<string id="DictionaryPolicyStub_Explain">'
- 'This is a test description.</string>')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="DictionaryPolicyStub">\n'
- ' <textBox refId="DictionaryPolicyStub">\n'
- ' <label>Dictionary policy label</label>\n'
- ' </textBox>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
- def testPlatform(self):
- # Test that the writer correctly chooses policies of platform Windows.
- self.assertTrue(self.writer.IsPolicySupported({
- 'supported_on': [
- {'platforms': ['win', 'zzz']}, {'platforms': ['aaa']}
- ]
- }))
- self.assertFalse(self.writer.IsPolicySupported({
- 'supported_on': [
- {'platforms': ['mac', 'linux']}, {'platforms': ['aaa']}
- ]
- }))
-
- def testStringEncodings(self):
- enum_policy_a = {
- 'name': 'EnumPolicy.A',
- 'type': 'string-enum',
- 'caption': 'Enum policy A caption',
- 'label': 'Enum policy A label',
- 'desc': 'This is a test description.',
- 'items': [
- {
- 'name': 'tls1.2',
- 'value': 'tls1.2',
- 'caption': 'tls1.2',
- }
- ],
- }
- enum_policy_b = {
- 'name': 'EnumPolicy.B',
- 'type': 'string-enum',
- 'caption': 'Enum policy B caption',
- 'label': 'Enum policy B label',
- 'desc': 'This is a test description.',
- 'items': [
- {
- 'name': 'tls1.2',
- 'value': 'tls1.2',
- 'caption': 'tls1.2',
- }
- ],
- }
- self. _InitWriterForAddingPolicies(self.writer, enum_policy_a)
- self.writer.WritePolicy(enum_policy_a)
- self.writer.WritePolicy(enum_policy_b)
- # Assert generated string elements.
- output = self.GetXMLOfChildren(self.writer._string_table_elem)
- expected_output = (
- '<string id="EnumPolicy_A">Enum policy A caption</string>\n'
- '<string id="EnumPolicy_A_Explain">'
- 'This is a test description.</string>\n'
- '<string id="tls1_2">tls1.2</string>\n'
- '<string id="EnumPolicy_B">Enum policy B caption</string>\n'
- '<string id="EnumPolicy_B_Explain">'
- 'This is a test description.</string>\n')
- self.AssertXMLEquals(output, expected_output)
- # Assert generated presentation elements.
- output = self.GetXMLOfChildren(self.writer._presentation_table_elem)
- expected_output = (
- '<presentation id="EnumPolicy.A">\n'
- ' <dropdownList refId="EnumPolicy.A">'
- 'Enum policy A label</dropdownList>\n'
- '</presentation>\n'
- '<presentation id="EnumPolicy.B">\n'
- ' <dropdownList refId="EnumPolicy.B">'
- 'Enum policy B label</dropdownList>\n'
- '</presentation>')
- self.AssertXMLEquals(output, expected_output)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/admx_writer.py b/grit/format/policy_templates/writers/admx_writer.py
deleted file mode 100644
index d657834..0000000
--- a/grit/format/policy_templates/writers/admx_writer.py
+++ /dev/null
@@ -1,382 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import xml_formatted_writer
-
-
-def GetWriter(config):
- '''Factory method for instanciating the ADMXWriter. Every Writer needs a
- GetWriter method because the TemplateFormatter uses this method to
- instantiate a Writer.
- '''
- return ADMXWriter(['win'], config)
-
-
-class ADMXWriter(xml_formatted_writer.XMLFormattedWriter):
- '''Class for generating an ADMX policy template. It is used by the
- PolicyTemplateGenerator to write the admx file.
- '''
-
- # DOM root node of the generated ADMX document.
- _doc = None
-
- # The ADMX "policies" element that contains the ADMX "policy" elements that
- # are generated.
- _active_policies_elem = None
-
- def _AdmlString(self, name):
- '''Creates a reference to the named string in an ADML file.
- Args:
- name: Name of the referenced ADML string.
- '''
- name = name.replace('.', '_')
- return '$(string.' + name + ')'
-
- def _AdmlStringExplain(self, name):
- '''Creates a reference to the named explanation string in an ADML file.
- Args:
- name: Name of the referenced ADML explanation.
- '''
- name = name.replace('.', '_')
- return '$(string.' + name + '_Explain)'
-
- def _AdmlPresentation(self, name):
- '''Creates a reference to the named presentation element in an ADML file.
- Args:
- name: Name of the referenced ADML presentation element.
- '''
- return '$(presentation.' + name + ')'
-
- def _AddPolicyNamespaces(self, parent, prefix, namespace):
- '''Generates the ADMX "policyNamespace" element and adds the elements to the
- passed parent element. The namespace of the generated ADMX document is
- define via the ADMX "target" element. Used namespaces are declared with an
- ADMX "using" element. ADMX "target" and "using" elements are children of the
- ADMX "policyNamespace" element.
-
- Args:
- parent: The parent node to which all generated elements are added.
- prefix: A logical name that can be used in the generated ADMX document to
- refere to this namespace.
- namespace: Namespace of the generated ADMX document.
- '''
- policy_namespaces_elem = self.AddElement(parent, 'policyNamespaces')
- attributes = {
- 'prefix': prefix,
- 'namespace': namespace,
- }
- self.AddElement(policy_namespaces_elem, 'target', attributes)
- attributes = {
- 'prefix': 'windows',
- 'namespace': 'Microsoft.Policies.Windows',
- }
- self.AddElement(policy_namespaces_elem, 'using', attributes)
-
- def _AddCategory(self, parent, name, display_name,
- parent_category_name=None):
- '''Adds an ADMX category element to the passed parent node. The following
- snippet shows an example of a category element where "chromium" is the value
- of the parameter name:
-
- <category displayName="$(string.chromium)" name="chromium"/>
-
- Each parent node can have only one category with a given name. Adding the
- same category again with the same attributes is ignored, but adding it
- again with different attributes is an error.
-
- Args:
- parent: The parent node to which all generated elements are added.
- name: Name of the category.
- display_name: Display name of the category.
- parent_category_name: Name of the parent category. Defaults to None.
- '''
- existing = filter(lambda e: e.getAttribute('name') == name,
- parent.getElementsByTagName('category'))
- if existing:
- assert len(existing) == 1
- assert existing[0].getAttribute('name') == name
- assert existing[0].getAttribute('displayName') == display_name
- return
- attributes = {
- 'name': name,
- 'displayName': display_name,
- }
- category_elem = self.AddElement(parent, 'category', attributes)
- if parent_category_name:
- attributes = {'ref': parent_category_name}
- self.AddElement(category_elem, 'parentCategory', attributes)
-
- def _AddCategories(self, categories):
- '''Generates the ADMX "categories" element and adds it to the categories
- main node. The "categories" element defines the category for the policies
- defined in this ADMX document. Here is an example of an ADMX "categories"
- element:
-
- <categories>
- <category displayName="$(string.google)" name="google"/>
- <category displayName="$(string.googlechrome)" name="googlechrome">
- <parentCategory ref="google"/>
- </category>
- </categories>
-
- Args:
- categories_path: The categories path e.g. ['google', 'googlechrome']. For
- each level in the path a "category" element will be generated. Except
- for the root level, each level refers to its parent. Since the root
- level category has no parent it does not require a parent reference.
- '''
- category_name = None
- for category in categories:
- parent_category_name = category_name
- category_name = category
- self._AddCategory(self._categories_elem, category_name,
- self._AdmlString(category_name), parent_category_name)
-
- def _AddSupportedOn(self, parent, supported_os):
- '''Generates the "supportedOn" ADMX element and adds it to the passed
- parent node. The "supportedOn" element contains information about supported
- Windows OS versions. The following code snippet contains an example of a
- "supportedOn" element:
-
- <supportedOn>
- <definitions>
- <definition name="SUPPORTED_WINXPSP2"
- displayName="$(string.SUPPORTED_WINXPSP2)"/>
- </definitions>
- ...
- </supportedOn>
-
- Args:
- parent: The parent element to which all generated elements are added.
- supported_os: List with all supported Win OSes.
- '''
- supported_on_elem = self.AddElement(parent, 'supportedOn')
- definitions_elem = self.AddElement(supported_on_elem, 'definitions')
- attributes = {
- 'name': supported_os,
- 'displayName': self._AdmlString(supported_os)
- }
- self.AddElement(definitions_elem, 'definition', attributes)
-
- def _AddStringPolicy(self, parent, name):
- '''Generates ADMX elements for a String-Policy and adds them to the
- passed parent node.
- '''
- attributes = {
- 'id': name,
- 'valueName': name,
- 'maxLength': '1000000',
- }
- self.AddElement(parent, 'text', attributes)
-
- def _AddIntPolicy(self, parent, name):
- '''Generates ADMX elements for an Int-Policy and adds them to the passed
- parent node.
- '''
- attributes = {
- 'id': name,
- 'valueName': name,
- 'maxValue': '2000000000',
- }
- self.AddElement(parent, 'decimal', attributes)
-
- def _AddEnumPolicy(self, parent, policy):
- '''Generates ADMX elements for an Enum-Policy and adds them to the
- passed parent element.
- '''
- name = policy['name']
- items = policy['items']
- attributes = {
- 'id': name,
- 'valueName': name,
- }
- enum_elem = self.AddElement(parent, 'enum', attributes)
- for item in items:
- attributes = {'displayName': self._AdmlString(item['name'])}
- item_elem = self.AddElement(enum_elem, 'item', attributes)
- value_elem = self.AddElement(item_elem, 'value')
- value_string = str(item['value'])
- if policy['type'] == 'int-enum':
- self.AddElement(value_elem, 'decimal', {'value': value_string})
- else:
- self.AddElement(value_elem, 'string', {}, value_string)
-
- def _AddListPolicy(self, parent, key, name):
- '''Generates ADMX XML elements for a List-Policy and adds them to the
- passed parent element.
- '''
- attributes = {
- # The ID must be in sync with ID of the corresponding element in the ADML
- # file.
- 'id': name + 'Desc',
- 'valuePrefix': '',
- 'key': key + '\\' + name,
- }
- self.AddElement(parent, 'list', attributes)
-
- def _AddMainPolicy(self, parent):
- '''Generates ADMX elements for a Main-Policy amd adds them to the
- passed parent element.
- '''
- enabled_value_elem = self.AddElement(parent, 'enabledValue');
- self.AddElement(enabled_value_elem, 'decimal', {'value': '1'})
- disabled_value_elem = self.AddElement(parent, 'disabledValue');
- self.AddElement(disabled_value_elem, 'decimal', {'value': '0'})
-
- def _GetElements(self, policy_group_elem):
- '''Returns the ADMX "elements" child from an ADMX "policy" element. If the
- "policy" element has no "elements" child yet, a new child is created.
-
- Args:
- policy_group_elem: The ADMX "policy" element from which the child element
- "elements" is returned.
-
- Raises:
- Exception: The policy_group_elem does not contain a ADMX "policy" element.
- '''
- if policy_group_elem.tagName != 'policy':
- raise Exception('Expected a "policy" element but got a "%s" element'
- % policy_group_elem.tagName)
- elements_list = policy_group_elem.getElementsByTagName('elements');
- if len(elements_list) == 0:
- return self.AddElement(policy_group_elem, 'elements')
- elif len(elements_list) == 1:
- return elements_list[0]
- else:
- raise Exception('There is supposed to be only one "elements" node but'
- ' there are %s.' % str(len(elements_list)))
-
- def _WritePolicy(self, policy, name, key, parent):
- '''Generates AMDX elements for a Policy. There are four different policy
- types: Main-Policy, String-Policy, Enum-Policy and List-Policy.
- '''
- policies_elem = self._active_policies_elem
- policy_type = policy['type']
- policy_name = policy['name']
- if policy_type == 'external':
- # This type can only be set through cloud policy.
- return
-
- attributes = {
- 'name': name,
- 'class': self.config['win_group_policy_class'],
- 'displayName': self._AdmlString(policy_name),
- 'explainText': self._AdmlStringExplain(policy_name),
- 'presentation': self._AdmlPresentation(policy_name),
- 'key': key,
- }
- # Store the current "policy" AMDX element in self for later use by the
- # WritePolicy method.
- policy_elem = self.AddElement(policies_elem, 'policy',
- attributes)
- self.AddElement(policy_elem, 'parentCategory',
- {'ref': parent})
- self.AddElement(policy_elem, 'supportedOn',
- {'ref': self.config['win_supported_os']})
- if policy_type == 'main':
- self.AddAttribute(policy_elem, 'valueName', policy_name)
- self._AddMainPolicy(policy_elem)
- elif policy_type in ('string', 'dict'):
- # 'dict' policies are configured as JSON-encoded strings on Windows.
- parent = self._GetElements(policy_elem)
- self._AddStringPolicy(parent, policy_name)
- elif policy_type == 'int':
- parent = self._GetElements(policy_elem)
- self._AddIntPolicy(parent, policy_name)
- elif policy_type in ('int-enum', 'string-enum'):
- parent = self._GetElements(policy_elem)
- self._AddEnumPolicy(parent, policy)
- elif policy_type in ('list', 'string-enum-list'):
- parent = self._GetElements(policy_elem)
- self._AddListPolicy(parent, key, policy_name)
- elif policy_type == 'group':
- pass
- else:
- raise Exception('Unknown policy type %s.' % policy_type)
-
- def WritePolicy(self, policy):
- if self.CanBeMandatory(policy):
- self._WritePolicy(policy,
- policy['name'],
- self.config['win_reg_mandatory_key_name'],
- self._active_mandatory_policy_group_name)
-
- def WriteRecommendedPolicy(self, policy):
- self._WritePolicy(policy,
- policy['name'] + '_recommended',
- self.config['win_reg_recommended_key_name'],
- self._active_recommended_policy_group_name)
-
- def _BeginPolicyGroup(self, group, name, parent):
- '''Generates ADMX elements for a Policy-Group.
- '''
- attributes = {
- 'name': name,
- 'displayName': self._AdmlString(group['name'] + '_group'),
- }
- category_elem = self.AddElement(self._categories_elem,
- 'category',
- attributes)
- attributes = {
- 'ref': parent
- }
- self.AddElement(category_elem, 'parentCategory', attributes)
-
- def BeginPolicyGroup(self, group):
- self._BeginPolicyGroup(group,
- group['name'],
- self.config['win_mandatory_category_path'][-1])
- self._active_mandatory_policy_group_name = group['name']
-
- def EndPolicyGroup(self):
- self._active_mandatory_policy_group_name = \
- self.config['win_mandatory_category_path'][-1]
-
- def BeginRecommendedPolicyGroup(self, group):
- self._BeginPolicyGroup(group,
- group['name'] + '_recommended',
- self.config['win_recommended_category_path'][-1])
- self._active_recommended_policy_group_name = group['name'] + '_recommended'
-
- def EndRecommendedPolicyGroup(self):
- self._active_recommended_policy_group_name = \
- self.config['win_recommended_category_path'][-1]
-
- def BeginTemplate(self):
- '''Generates the skeleton of the ADMX template. An ADMX template contains
- an ADMX "PolicyDefinitions" element with four child nodes: "policies"
- "policyNamspaces", "resources", "supportedOn" and "categories"
- '''
- dom_impl = minidom.getDOMImplementation('')
- self._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
- if self._GetChromiumVersionString() is not None:
- self.AddComment(self._doc.documentElement, self.config['build'] + \
- ' version: ' + self._GetChromiumVersionString())
- policy_definitions_elem = self._doc.documentElement
-
- policy_definitions_elem.attributes['revision'] = '1.0'
- policy_definitions_elem.attributes['schemaVersion'] = '1.0'
-
- self._AddPolicyNamespaces(policy_definitions_elem,
- self.config['admx_prefix'],
- self.config['admx_namespace'])
- self.AddElement(policy_definitions_elem, 'resources',
- {'minRequiredRevision' : '1.0'})
- self._AddSupportedOn(policy_definitions_elem,
- self.config['win_supported_os'])
- self._categories_elem = self.AddElement(policy_definitions_elem,
- 'categories')
- self._AddCategories(self.config['win_mandatory_category_path'])
- self._AddCategories(self.config['win_recommended_category_path'])
- self._active_policies_elem = self.AddElement(policy_definitions_elem,
- 'policies')
- self._active_mandatory_policy_group_name = \
- self.config['win_mandatory_category_path'][-1]
- self._active_recommended_policy_group_name = \
- self.config['win_recommended_category_path'][-1]
-
- def GetTemplateText(self):
- return self.ToPrettyXml(self._doc)
diff --git a/grit/format/policy_templates/writers/admx_writer_unittest.py b/grit/format/policy_templates/writers/admx_writer_unittest.py
deleted file mode 100644
index 8bdb7a4..0000000
--- a/grit/format/policy_templates/writers/admx_writer_unittest.py
+++ /dev/null
@@ -1,573 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-"""Unittests for grit.format.policy_templates.writers.admx_writer."""
-
-
-import os
-import sys
-import unittest
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-
-from grit.format.policy_templates.writers import admx_writer
-from grit.format.policy_templates.writers import xml_writer_base_unittest
-from xml.dom import minidom
-
-
-class AdmxWriterUnittest(xml_writer_base_unittest.XmlWriterBaseTest):
-
- def _CreateDocumentElement(self):
- dom_impl = minidom.getDOMImplementation('')
- doc = dom_impl.createDocument(None, 'root', None)
- return doc.documentElement
-
- def setUp(self):
- # Writer configuration. This dictionary contains parameter used by the ADMX
- # Writer
- config = {
- 'win_group_policy_class': 'TestClass',
- 'win_supported_os': 'SUPPORTED_TESTOS',
- 'win_reg_mandatory_key_name': 'Software\\Policies\\Test',
- 'win_reg_recommended_key_name': 'Software\\Policies\\Test\\Recommended',
- 'win_mandatory_category_path': ['test_category'],
- 'win_recommended_category_path': ['test_recommended_category'],
- 'admx_namespace': 'ADMXWriter.Test.Namespace',
- 'admx_prefix': 'test_prefix',
- 'build': 'test_product',
- }
- self.writer = admx_writer.GetWriter(config)
- self.writer.Init()
-
- def _GetPoliciesElement(self, doc):
- node_list = doc.getElementsByTagName('policies')
- self.assertTrue(node_list.length == 1)
- return node_list.item(0)
-
- def _GetCategoriesElement(self, doc):
- node_list = doc.getElementsByTagName('categories')
- self.assertTrue(node_list.length == 1)
- return node_list.item(0)
-
- def testEmpty(self):
- self.writer.BeginTemplate()
- self.writer.EndTemplate()
-
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?>\n'
- '<policyDefinitions revision="1.0" schemaVersion="1.0">\n'
- ' <policyNamespaces>\n'
- ' <target namespace="ADMXWriter.Test.Namespace"'
- ' prefix="test_prefix"/>\n'
- ' <using namespace="Microsoft.Policies.Windows" prefix="windows"/>\n'
- ' </policyNamespaces>\n'
- ' <resources minRequiredRevision="1.0"/>\n'
- ' <supportedOn>\n'
- ' <definitions>\n'
- ' <definition displayName="'
- '$(string.SUPPORTED_TESTOS)" name="SUPPORTED_TESTOS"/>\n'
- ' </definitions>\n'
- ' </supportedOn>\n'
- ' <categories>\n'
- ' <category displayName="$(string.test_category)"'
- ' name="test_category"/>\n'
- ' <category displayName="$(string.test_recommended_category)"'
- ' name="test_recommended_category"/>\n'
- ' </categories>\n'
- ' <policies/>\n'
- '</policyDefinitions>')
- self.AssertXMLEquals(output, expected_output)
-
- def testEmptyVersion(self):
- self.writer.config['version'] = '39.0.0.0'
- self.writer.BeginTemplate()
- self.writer.EndTemplate()
-
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?>\n'
- '<policyDefinitions revision="1.0" schemaVersion="1.0">\n'
- ' <!--test_product version: 39.0.0.0-->\n'
- ' <policyNamespaces>\n'
- ' <target namespace="ADMXWriter.Test.Namespace"'
- ' prefix="test_prefix"/>\n'
- ' <using namespace="Microsoft.Policies.Windows" prefix="windows"/>\n'
- ' </policyNamespaces>\n'
- ' <resources minRequiredRevision="1.0"/>\n'
- ' <supportedOn>\n'
- ' <definitions>\n'
- ' <definition displayName="'
- '$(string.SUPPORTED_TESTOS)" name="SUPPORTED_TESTOS"/>\n'
- ' </definitions>\n'
- ' </supportedOn>\n'
- ' <categories>\n'
- ' <category displayName="$(string.test_category)"'
- ' name="test_category"/>\n'
- ' <category displayName="$(string.test_recommended_category)"'
- ' name="test_recommended_category"/>\n'
- ' </categories>\n'
- ' <policies/>\n'
- '</policyDefinitions>')
- self.AssertXMLEquals(output, expected_output)
-
- def testEmptyPolicyGroup(self):
- empty_policy_group = {
- 'name': 'PolicyGroup',
- 'policies': []
- }
- # Initialize writer to write a policy group.
- self.writer.BeginTemplate()
- # Write policy group
- self.writer.BeginPolicyGroup(empty_policy_group)
- self.writer.EndPolicyGroup()
-
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = ''
- self.AssertXMLEquals(output, expected_output)
-
- output = self.GetXMLOfChildren(
- self._GetCategoriesElement(self.writer._doc))
- expected_output = (
- '<category displayName="$(string.test_category)"'
- ' name="test_category"/>\n'
- '<category displayName="$(string.test_recommended_category)"'
- ' name="test_recommended_category"/>\n'
- '<category displayName="$(string.PolicyGroup_group)"'
- ' name="PolicyGroup">\n'
- ' <parentCategory ref="test_category"/>\n'
- '</category>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testPolicyGroup(self):
- empty_policy_group = {
- 'name': 'PolicyGroup',
- 'policies': [
- {'name': 'PolicyStub2',
- 'type': 'main'},
- {'name': 'PolicyStub1',
- 'type': 'main'},
- ]
- }
- # Initialize writer to write a policy group.
- self.writer.BeginTemplate()
- # Write policy group
- self.writer.BeginPolicyGroup(empty_policy_group)
- self.writer.EndPolicyGroup()
-
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = ''
- self.AssertXMLEquals(output, expected_output)
-
- output = self.GetXMLOfChildren(
- self._GetCategoriesElement(self.writer._doc))
- expected_output = (
- '<category displayName="$(string.test_category)"'
- ' name="test_category"/>\n'
- '<category displayName="$(string.test_recommended_category)"'
- ' name="test_recommended_category"/>\n'
- '<category displayName="$(string.PolicyGroup_group)"'
- ' name="PolicyGroup">\n'
- ' <parentCategory ref="test_category"/>\n'
- '</category>')
- self.AssertXMLEquals(output, expected_output)
-
-
- def _initWriterForPolicy(self, writer, policy):
- '''Initializes the writer to write the given policy next.
- '''
- policy_group = {
- 'name': 'PolicyGroup',
- 'policies': [policy]
- }
- writer.BeginTemplate()
- writer.BeginPolicyGroup(policy_group)
-
- def testMainPolicy(self):
- main_policy = {
- 'name': 'DummyMainPolicy',
- 'type': 'main',
- }
-
- self._initWriterForPolicy(self.writer, main_policy)
-
- self.writer.WritePolicy(main_policy)
-
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.DummyMainPolicy)"'
- ' explainText="$(string.DummyMainPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="DummyMainPolicy"'
- ' presentation="$(presentation.DummyMainPolicy)"'
- ' valueName="DummyMainPolicy">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <enabledValue>\n'
- ' <decimal value="1"/>\n'
- ' </enabledValue>\n'
- ' <disabledValue>\n'
- ' <decimal value="0"/>\n'
- ' </disabledValue>\n'
- '</policy>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testRecommendedPolicy(self):
- main_policy = {
- 'name': 'DummyMainPolicy',
- 'type': 'main',
- }
-
- policy_group = {
- 'name': 'PolicyGroup',
- 'policies': [main_policy],
- }
- self.writer.BeginTemplate()
- self.writer.BeginRecommendedPolicyGroup(policy_group)
-
- self.writer.WriteRecommendedPolicy(main_policy)
-
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.DummyMainPolicy)"'
- ' explainText="$(string.DummyMainPolicy_Explain)"'
- ' key="Software\\Policies\\Test\\Recommended"'
- ' name="DummyMainPolicy_recommended"'
- ' presentation="$(presentation.DummyMainPolicy)"'
- ' valueName="DummyMainPolicy">\n'
- ' <parentCategory ref="PolicyGroup_recommended"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <enabledValue>\n'
- ' <decimal value="1"/>\n'
- ' </enabledValue>\n'
- ' <disabledValue>\n'
- ' <decimal value="0"/>\n'
- ' </disabledValue>\n'
- '</policy>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testRecommendedOnlyPolicy(self):
- main_policy = {
- 'name': 'DummyMainPolicy',
- 'type': 'main',
- 'features': {
- 'can_be_recommended': True,
- 'can_be_mandatory': False,
- }
- }
-
- policy_group = {
- 'name': 'PolicyGroup',
- 'policies': [main_policy],
- }
- self.writer.BeginTemplate()
- self.writer.BeginRecommendedPolicyGroup(policy_group)
-
- self.writer.WritePolicy(main_policy)
- self.writer.WriteRecommendedPolicy(main_policy)
-
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.DummyMainPolicy)"'
- ' explainText="$(string.DummyMainPolicy_Explain)"'
- ' key="Software\\Policies\\Test\\Recommended"'
- ' name="DummyMainPolicy_recommended"'
- ' presentation="$(presentation.DummyMainPolicy)"'
- ' valueName="DummyMainPolicy">\n'
- ' <parentCategory ref="PolicyGroup_recommended"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <enabledValue>\n'
- ' <decimal value="1"/>\n'
- ' </enabledValue>\n'
- ' <disabledValue>\n'
- ' <decimal value="0"/>\n'
- ' </disabledValue>\n'
- '</policy>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testStringPolicy(self):
- string_policy = {
- 'name': 'SampleStringPolicy',
- 'type': 'string',
- }
- self._initWriterForPolicy(self.writer, string_policy)
-
- self.writer.WritePolicy(string_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleStringPolicy)"'
- ' explainText="$(string.SampleStringPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleStringPolicy"'
- ' presentation="$(presentation.SampleStringPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <text id="SampleStringPolicy" maxLength="1000000"'
- ' valueName="SampleStringPolicy"/>\n'
- ' </elements>\n'
- '</policy>')
- self.AssertXMLEquals(output, expected_output)
-
- def testIntPolicy(self):
- int_policy = {
- 'name': 'SampleIntPolicy',
- 'type': 'int',
- }
- self._initWriterForPolicy(self.writer, int_policy)
-
- self.writer.WritePolicy(int_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleIntPolicy)"'
- ' explainText="$(string.SampleIntPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleIntPolicy"'
- ' presentation="$(presentation.SampleIntPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <decimal id="SampleIntPolicy" maxValue="2000000000" '
- 'valueName="SampleIntPolicy"/>\n'
- ' </elements>\n'
- '</policy>')
- self.AssertXMLEquals(output, expected_output)
-
- def testIntEnumPolicy(self):
- enum_policy = {
- 'name': 'SampleEnumPolicy',
- 'type': 'int-enum',
- 'items': [
- {'name': 'item_1', 'value': 0},
- {'name': 'item_2', 'value': 1},
- ]
- }
-
- self._initWriterForPolicy(self.writer, enum_policy)
- self.writer.WritePolicy(enum_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleEnumPolicy)"'
- ' explainText="$(string.SampleEnumPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleEnumPolicy"'
- ' presentation="$(presentation.SampleEnumPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <enum id="SampleEnumPolicy" valueName="SampleEnumPolicy">\n'
- ' <item displayName="$(string.item_1)">\n'
- ' <value>\n'
- ' <decimal value="0"/>\n'
- ' </value>\n'
- ' </item>\n'
- ' <item displayName="$(string.item_2)">\n'
- ' <value>\n'
- ' <decimal value="1"/>\n'
- ' </value>\n'
- ' </item>\n'
- ' </enum>\n'
- ' </elements>\n'
- '</policy>')
- self.AssertXMLEquals(output, expected_output)
-
- def testStringEnumPolicy(self):
- enum_policy = {
- 'name': 'SampleEnumPolicy',
- 'type': 'string-enum',
- 'items': [
- {'name': 'item_1', 'value': 'one'},
- {'name': 'item_2', 'value': 'two'},
- ]
- }
-
- # This test is different than the others because it also tests that space
- # usage inside <string> nodes is correct.
- dom_impl = minidom.getDOMImplementation('')
- self.writer._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
- self.writer._active_policies_elem = self.writer._doc.documentElement
- self.writer._active_mandatory_policy_group_name = 'PolicyGroup'
- self.writer.WritePolicy(enum_policy)
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?>\n'
- '<policyDefinitions>\n'
- ' <policy class="TestClass" displayName="$(string.SampleEnumPolicy)"'
- ' explainText="$(string.SampleEnumPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleEnumPolicy"'
- ' presentation="$(presentation.SampleEnumPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <enum id="SampleEnumPolicy" valueName="SampleEnumPolicy">\n'
- ' <item displayName="$(string.item_1)">\n'
- ' <value>\n'
- ' <string>one</string>\n'
- ' </value>\n'
- ' </item>\n'
- ' <item displayName="$(string.item_2)">\n'
- ' <value>\n'
- ' <string>two</string>\n'
- ' </value>\n'
- ' </item>\n'
- ' </enum>\n'
- ' </elements>\n'
- ' </policy>\n'
- '</policyDefinitions>')
- self.AssertXMLEquals(output, expected_output)
-
- def testListPolicy(self):
- list_policy = {
- 'name': 'SampleListPolicy',
- 'type': 'list',
- }
- self._initWriterForPolicy(self.writer, list_policy)
- self.writer.WritePolicy(list_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleListPolicy)"'
- ' explainText="$(string.SampleListPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleListPolicy"'
- ' presentation="$(presentation.SampleListPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <list id="SampleListPolicyDesc"'
- ' key="Software\Policies\Test\SampleListPolicy" valuePrefix=""/>\n'
- ' </elements>\n'
- '</policy>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testStringEnumListPolicy(self):
- list_policy = {
- 'name': 'SampleListPolicy',
- 'type': 'string-enum-list',
- 'items': [
- {'name': 'item_1', 'value': 'one'},
- {'name': 'item_2', 'value': 'two'},
- ]
- }
- self._initWriterForPolicy(self.writer, list_policy)
- self.writer.WritePolicy(list_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.SampleListPolicy)"'
- ' explainText="$(string.SampleListPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleListPolicy"'
- ' presentation="$(presentation.SampleListPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <list id="SampleListPolicyDesc"'
- ' key="Software\Policies\Test\SampleListPolicy" valuePrefix=""/>\n'
- ' </elements>\n'
- '</policy>')
-
- self.AssertXMLEquals(output, expected_output)
-
- def testDictionaryPolicy(self):
- dict_policy = {
- 'name': 'SampleDictionaryPolicy',
- 'type': 'dict',
- }
- self._initWriterForPolicy(self.writer, dict_policy)
-
- self.writer.WritePolicy(dict_policy)
- output = self.GetXMLOfChildren(self._GetPoliciesElement(self.writer._doc))
- expected_output = (
- '<policy class="TestClass" displayName="$(string.'
- 'SampleDictionaryPolicy)"'
- ' explainText="$(string.SampleDictionaryPolicy_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleDictionaryPolicy"'
- ' presentation="$(presentation.SampleDictionaryPolicy)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <text id="SampleDictionaryPolicy" maxLength="1000000"'
- ' valueName="SampleDictionaryPolicy"/>\n'
- ' </elements>\n'
- '</policy>')
- self.AssertXMLEquals(output, expected_output)
-
- def testPlatform(self):
- # Test that the writer correctly chooses policies of platform Windows.
- self.assertTrue(self.writer.IsPolicySupported({
- 'supported_on': [
- {'platforms': ['win', 'zzz']}, {'platforms': ['aaa']}
- ]
- }))
- self.assertFalse(self.writer.IsPolicySupported({
- 'supported_on': [
- {'platforms': ['mac', 'linux']}, {'platforms': ['aaa']}
- ]
- }))
-
- def testStringEncodings(self):
- enum_policy_a = {
- 'name': 'SampleEnumPolicy.A',
- 'type': 'string-enum',
- 'items': [
- {'name': 'tls1.2', 'value': 'tls1.2'}
- ]
- }
- enum_policy_b = {
- 'name': 'SampleEnumPolicy.B',
- 'type': 'string-enum',
- 'items': [
- {'name': 'tls1.2', 'value': 'tls1.2'}
- ]
- }
-
- dom_impl = minidom.getDOMImplementation('')
- self.writer._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
- self.writer._active_policies_elem = self.writer._doc.documentElement
- self.writer._active_mandatory_policy_group_name = 'PolicyGroup'
- self.writer.WritePolicy(enum_policy_a)
- self.writer.WritePolicy(enum_policy_b)
- output = self.writer.GetTemplateText()
- expected_output = (
- '<?xml version="1.0" ?>\n'
- '<policyDefinitions>\n'
- ' <policy class="TestClass" displayName="$(string.SampleEnumPolicy_A)"'
- ' explainText="$(string.SampleEnumPolicy_A_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleEnumPolicy.A"'
- ' presentation="$(presentation.SampleEnumPolicy.A)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <enum id="SampleEnumPolicy.A" valueName="SampleEnumPolicy.A">\n'
- ' <item displayName="$(string.tls1_2)">\n'
- ' <value>\n'
- ' <string>tls1.2</string>\n'
- ' </value>\n'
- ' </item>\n'
- ' </enum>\n'
- ' </elements>\n'
- ' </policy>\n'
- ' <policy class="TestClass" displayName="$(string.SampleEnumPolicy_B)"'
- ' explainText="$(string.SampleEnumPolicy_B_Explain)"'
- ' key="Software\\Policies\\Test" name="SampleEnumPolicy.B"'
- ' presentation="$(presentation.SampleEnumPolicy.B)">\n'
- ' <parentCategory ref="PolicyGroup"/>\n'
- ' <supportedOn ref="SUPPORTED_TESTOS"/>\n'
- ' <elements>\n'
- ' <enum id="SampleEnumPolicy.B" valueName="SampleEnumPolicy.B">\n'
- ' <item displayName="$(string.tls1_2)">\n'
- ' <value>\n'
- ' <string>tls1.2</string>\n'
- ' </value>\n'
- ' </item>\n'
- ' </enum>\n'
- ' </elements>\n'
- ' </policy>\n'
- '</policyDefinitions>')
- self.AssertXMLEquals(output, expected_output)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/android_policy_writer.py b/grit/format/policy_templates/writers/android_policy_writer.py
deleted file mode 100644
index 5d8cbef..0000000
--- a/grit/format/policy_templates/writers/android_policy_writer.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-from grit.format.policy_templates.writers import xml_formatted_writer
-from xml.dom import minidom
-from xml.sax import saxutils as xml_escape
-
-
-def GetWriter(config):
- '''Factory method for creating AndroidPolicyWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return AndroidPolicyWriter(['android'], config)
-
-
-def _EscapeResource(resource):
- '''Escape the resource for usage in an Android resource XML file.
- This includes standard XML escaping as well as those specific to Android.
- '''
- if type(resource) == int:
- return str(resource)
- return xml_escape.escape(resource, {"'": "\\'", '"': '\\"', '\\': '\\\\'})
-
-
-class AndroidPolicyWriter(xml_formatted_writer.XMLFormattedWriter):
- '''Outputs localized Android Resource XML files.
- The policy strings are localized and exposed as string resources for
- consumption through Android's App restriction Schema.
- '''
-
- # DOM root node of the generated XML document.
- _doc = None
- # The resources node contains all resource 'string' and 'string-array'
- # elements.
- _resources = None
-
- def AddStringResource(self, name, string):
- '''Add a string resource of the given name.
- '''
- string_node = self._doc.createElement('string')
- string_node.setAttribute('name', name)
- string_node.appendChild(self._doc.createTextNode(_EscapeResource(string)))
- self._resources.appendChild(string_node)
-
- def AddStringArrayResource(self, name, string_items):
- '''Add a string-array resource of the given name and
- elements from string_items.
- '''
- string_array_node = self._doc.createElement('string-array')
- string_array_node.setAttribute('name', name)
- self._resources.appendChild(string_array_node)
- for item in string_items:
- string_node = self._doc.createElement('item')
- string_node.appendChild(self._doc.createTextNode(_EscapeResource(item)))
- string_array_node.appendChild(string_node)
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list)
-
- def CanBeRecommended(self, policy):
- return False
-
- def IsDeprecatedPolicySupported(self, policy):
- return True
-
- def IsFuturePolicySupported(self, policy):
- return True
-
- def WritePolicy(self, policy):
- name = policy['name']
- self.AddStringResource(name + 'Title', policy['caption'])
-
- # Get the first line of the policy description.
- description = policy['desc'].split('\n', 1)[0]
- self.AddStringResource(name + 'Desc', description)
-
- items = policy.get('items')
- if items is not None:
- entries = [ item['caption'] for item in items ]
- values = [ item['value'] for item in items ]
- self.AddStringArrayResource(name + 'Entries', entries)
- self.AddStringArrayResource(name + 'Values', values)
-
- def BeginTemplate(self):
- comment_text = 'DO NOT MODIFY THIS FILE DIRECTLY!\n' \
- 'IT IS GENERATED FROM policy_templates.json.'
- comment_node = self._doc.createComment(comment_text)
- self._doc.insertBefore(comment_node, self._resources)
-
- def Init(self):
- impl = minidom.getDOMImplementation()
- self._doc = impl.createDocument(None, 'resources', None)
- self._resources = self._doc.documentElement
-
- def GetTemplateText(self):
- return self.ToPrettyXml(self._doc)
diff --git a/grit/format/policy_templates/writers/android_policy_writer_unittest.py b/grit/format/policy_templates/writers/android_policy_writer_unittest.py
deleted file mode 100644
index 437c71a..0000000
--- a/grit/format/policy_templates/writers/android_policy_writer_unittest.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.policy_templates.writers.android_policy_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-from xml.dom import minidom
-
-from grit.format.policy_templates.writers import writer_unittest_common
-from grit.format.policy_templates.writers import android_policy_writer
-
-
-class AndroidPolicyWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests to test assumptions in Android Policy Writer'''
-
- def testPolicyWithoutItems(self):
- # Test an example policy without items.
- policy = {
- 'name': '_policy_name',
- 'caption': '_policy_caption',
- 'desc': 'This is a long policy caption. More than one sentence '
- 'in a single line because it is very important.\nIgnore this.'
- }
- writer = android_policy_writer.GetWriter({})
- writer.Init()
- writer.BeginTemplate()
- writer.WritePolicy(policy)
- self.assertEquals(
- writer._resources.toxml(),
- '<resources>'
- '<string name="_policy_nameTitle">_policy_caption</string>'
- '<string name="_policy_nameDesc">This is a long policy caption. More '
- 'than one sentence in a single line because it is very important.'
- '</string>'
- '</resources>')
-
- def testPolicyWithItems(self):
- # Test an example policy without items.
- policy = {
- 'name': '_policy_name',
- 'caption': '_policy_caption',
- 'desc': '_policy_desc_first.\n_ignored_policy_desc',
- 'items': [
- {
- 'caption':'_caption1',
- 'value':'_value1',
- },
- {
- 'caption':'_caption2',
- 'value':'_value2',
- }
- ]
- }
- writer = android_policy_writer.GetWriter({})
- writer.Init()
- writer.BeginTemplate()
- writer.WritePolicy(policy)
- self.assertEquals(
- writer._resources.toxml(),
- '<resources>'
- '<string name="_policy_nameTitle">_policy_caption</string>'
- '<string name="_policy_nameDesc">_policy_desc_first.</string>'
- '<string-array name="_policy_nameEntries">'
- '<item>_caption1</item>'
- '<item>_caption2</item>'
- '</string-array>'
- '<string-array name="_policy_nameValues">'
- '<item>_value1</item>'
- '<item>_value2</item>'
- '</string-array>'
- '</resources>')
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/doc_writer.py b/grit/format/policy_templates/writers/doc_writer.py
deleted file mode 100644
index ed6d060..0000000
--- a/grit/format/policy_templates/writers/doc_writer.py
+++ /dev/null
@@ -1,748 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-import json
-from xml.dom import minidom
-from grit import lazy_re
-from grit.format.policy_templates.writers import xml_formatted_writer
-
-
-def GetWriter(config):
- '''Factory method for creating DocWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return DocWriter(['*'], config)
-
-
-class DocWriter(xml_formatted_writer.XMLFormattedWriter):
- '''Class for generating policy templates in HTML format.
- The intended use of the generated file is to upload it on
- http://dev.chromium.org, therefore its format has some limitations:
- - No HTML and body tags.
- - Restricted set of element attributes: for example no 'class'.
- Because of the latter the output is styled using the 'style'
- attributes of HTML elements. This is supported by the dictionary
- self._STYLES[] and the method self._AddStyledElement(), they try
- to mimic the functionality of CSS classes. (But without inheritance.)
-
- This class is invoked by PolicyTemplateGenerator to create the HTML
- files.
- '''
-
- def _GetLocalizedMessage(self, msg_id):
- '''Returns a localized message for this writer.
-
- Args:
- msg_id: The identifier of the message.
-
- Returns:
- The localized message.
- '''
- return self.messages['doc_' + msg_id]['text']
-
- def _MapListToString(self, item_map, items):
- '''Creates a comma-separated list.
-
- Args:
- item_map: A dictionary containing all the elements of 'items' as
- keys.
- items: A list of arbitrary items.
-
- Returns:
- Looks up each item of 'items' in 'item_maps' and concatenates the
- resulting items into a comma-separated list.
- '''
- return ', '.join([item_map[x] for x in items])
-
- def _AddTextWithLinks(self, parent, text):
- '''Parse a string for URLs and add it to a DOM node with the URLs replaced
- with <a> HTML links.
-
- Args:
- parent: The DOM node to which the text will be added.
- text: The string to be added.
- '''
- # A simple regexp to search for URLs. It is enough for now.
- url_matcher = lazy_re.compile('(http://[^\\s]*[^\\s\\.])')
-
- # Iterate through all the URLs and replace them with links.
- while True:
- # Look for the first URL.
- res = url_matcher.search(text)
- if not res:
- break
- # Calculate positions of the substring of the URL.
- url = res.group(0)
- start = res.start(0)
- end = res.end(0)
- # Add the text prior to the URL.
- self.AddText(parent, text[:start])
- # Add a link for the URL.
- self.AddElement(parent, 'a', {'href': url}, url)
- # Drop the part of text that is added.
- text = text[end:]
- self.AddText(parent, text)
-
- def _AddParagraphs(self, parent, text):
- '''Break description into paragraphs and replace URLs with links.
-
- Args:
- parent: The DOM node to which the text will be added.
- text: The string to be added.
- '''
- # Split text into list of paragraphs.
- entries = text.split('\n\n')
- for entry in entries:
- # Create a new paragraph node.
- paragraph = self.AddElement(parent, 'p')
- # Insert text to the paragraph with processing the URLs.
- self._AddTextWithLinks(paragraph, entry)
-
- def _AddStyledElement(self, parent, name, style_ids, attrs=None, text=None):
- '''Adds an XML element to a parent, with CSS style-sheets included.
-
- Args:
- parent: The parent DOM node.
- name: Name of the element to add.
- style_ids: A list of CSS style strings from self._STYLE[].
- attrs: Dictionary of attributes for the element.
- text: Text content for the element.
- '''
- if attrs == None:
- attrs = {}
-
- style = ''.join([self._STYLE[x] for x in style_ids])
- if style != '':
- # Apply the style specified by style_ids.
- attrs['style'] = style + attrs.get('style', '')
- return self.AddElement(parent, name, attrs, text)
-
- def _AddDescription(self, parent, policy):
- '''Adds a string containing the description of the policy. URLs are
- replaced with links and the possible choices are enumerated in case
- of 'string-enum' and 'int-enum' type policies.
-
- Args:
- parent: The DOM node for which the feature list will be added.
- policy: The data structure of a policy.
- '''
- # Add description by paragraphs (URLs will be substituted by links).
- self._AddParagraphs(parent, policy['desc'])
- # Add list of enum items.
- if policy['type'] in ('string-enum', 'int-enum', 'string-enum-list'):
- ul = self.AddElement(parent, 'ul')
- for item in policy['items']:
- if policy['type'] == 'int-enum':
- value_string = str(item['value'])
- else:
- value_string = '"%s"' % item['value']
- self.AddElement(
- ul, 'li', {}, '%s = %s' % (value_string, item['caption']))
-
- def _AddFeatures(self, parent, policy):
- '''Adds a string containing the list of supported features of a policy
- to a DOM node. The text will look like as:
- Feature_X: Yes, Feature_Y: No
-
- Args:
- parent: The DOM node for which the feature list will be added.
- policy: The data structure of a policy.
- '''
- features = []
- # The sorting is to make the order well-defined for testing.
- keys = policy['features'].keys()
- keys.sort()
- for key in keys:
- key_name = self._FEATURE_MAP[key]
- if policy['features'][key]:
- value_name = self._GetLocalizedMessage('supported')
- else:
- value_name = self._GetLocalizedMessage('not_supported')
- features.append('%s: %s' % (key_name, value_name))
- self.AddText(parent, ', '.join(features))
-
- def _AddListExampleMac(self, parent, policy):
- '''Adds an example value for Mac of a 'list' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'list', for which the Mac example value
- is generated.
- '''
- example_value = policy['example_value']
- self.AddElement(parent, 'dt', {}, 'Mac:')
- mac = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
-
- mac_text = ['<array>']
- for item in example_value:
- mac_text.append(' <string>%s</string>' % item)
- mac_text.append('</array>')
- self.AddText(mac, '\n'.join(mac_text))
-
- def _AddListExampleWindows(self, parent, policy):
- '''Adds an example value for Windows of a 'list' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'list', for which the Windows example value
- is generated.
- '''
- example_value = policy['example_value']
- self.AddElement(parent, 'dt', {}, 'Windows:')
- win = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
- win_text = []
- cnt = 1
- if self.CanBeRecommended(policy) and not self.CanBeMandatory(policy):
- key_name = self.config['win_reg_recommended_key_name']
- else:
- key_name = self.config['win_reg_mandatory_key_name']
- for item in example_value:
- win_text.append(
- '%s\\%s\\%d = "%s"' %
- (key_name, policy['name'], cnt, item))
- cnt = cnt + 1
- self.AddText(win, '\n'.join(win_text))
-
- def _AddListExampleAndroidLinux(self, parent, policy):
- '''Adds an example value for Android/Linux of a 'list' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'list', for which the Android/Linux example value
- is generated.
- '''
- example_value = policy['example_value']
- self.AddElement(parent, 'dt', {}, 'Android/Linux:')
- element = self._AddStyledElement(parent, 'dd', ['.monospace'])
- text = []
- for item in example_value:
- text.append('"%s"' % item)
- self.AddText(element, '[%s]' % ', '.join(text))
-
- def _AddListExample(self, parent, policy):
- '''Adds the example value of a 'list' policy to a DOM node. Example output:
- <dl>
- <dt>Windows:</dt>
- <dd>
- Software\Policies\Chromium\DisabledPlugins\0 = "Java"
- Software\Policies\Chromium\DisabledPlugins\1 = "Shockwave Flash"
- </dd>
- <dt>Android/Linux:</dt>
- <dd>["Java", "Shockwave Flash"]</dd>
- <dt>Mac:</dt>
- <dd>
- <array>
- <string>Java</string>
- <string>Shockwave Flash</string>
- </array>
- </dd>
- </dl>
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: The data structure of a policy.
- '''
- examples = self._AddStyledElement(parent, 'dl', ['dd dl'])
- if self.IsPolicySupportedOnPlatform(policy, 'win'):
- self._AddListExampleWindows(examples, policy)
- if (self.IsPolicySupportedOnPlatform(policy, 'android') or
- self.IsPolicySupportedOnPlatform(policy, 'linux')):
- self._AddListExampleAndroidLinux(examples, policy)
- if self.IsPolicySupportedOnPlatform(policy, 'mac'):
- self._AddListExampleMac(examples, policy)
-
- def _PythonObjectToPlist(self, obj, indent=''):
- '''Converts a python object to an equivalent XML plist.
-
- Returns a list of lines.'''
- obj_type = type(obj)
- if obj_type == bool:
- return [ '%s<%s/>' % (indent, 'true' if obj else 'false') ]
- elif obj_type == int:
- return [ '%s<integer>%s</integer>' % (indent, obj) ]
- elif obj_type == str:
- return [ '%s<string>%s</string>' % (indent, obj) ]
- elif obj_type == list:
- result = [ '%s<array>' % indent ]
- for item in obj:
- result += self._PythonObjectToPlist(item, indent + ' ')
- result.append('%s</array>' % indent)
- return result
- elif obj_type == dict:
- result = [ '%s<dict>' % indent ]
- for key in sorted(obj.keys()):
- result.append('%s<key>%s</key>' % (indent + ' ', key))
- result += self._PythonObjectToPlist(obj[key], indent + ' ')
- result.append('%s</dict>' % indent)
- return result
- else:
- raise Exception('Invalid object to convert: %s' % obj)
-
- def _AddDictionaryExampleMac(self, parent, policy):
- '''Adds an example value for Mac of a 'dict' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'dict', for which the Mac example value
- is generated.
- '''
- example_value = policy['example_value']
- self.AddElement(parent, 'dt', {}, 'Mac:')
- mac = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
- mac_text = ['<key>%s</key>' % (policy['name'])]
- mac_text += self._PythonObjectToPlist(example_value)
- self.AddText(mac, '\n'.join(mac_text))
-
- def _AddDictionaryExampleWindows(self, parent, policy):
- '''Adds an example value for Windows of a 'dict' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'dict', for which the Windows example value
- is generated.
- '''
- self.AddElement(parent, 'dt', {}, 'Windows:')
- win = self._AddStyledElement(parent, 'dd', ['.monospace', '.pre'])
- if self.CanBeRecommended(policy) and not self.CanBeMandatory(policy):
- key_name = self.config['win_reg_recommended_key_name']
- else:
- key_name = self.config['win_reg_mandatory_key_name']
- example = json.dumps(policy['example_value'])
- self.AddText(win, '%s\\%s = %s' % (key_name, policy['name'], example))
-
- def _AddDictionaryExampleAndroidLinux(self, parent, policy):
- '''Adds an example value for Android/Linux of a 'dict' policy to a DOM node.
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: A policy of type 'dict', for which the Android/Linux example value
- is generated.
- '''
- self.AddElement(parent, 'dt', {}, 'Android/Linux:')
- element = self._AddStyledElement(parent, 'dd', ['.monospace'])
- example = json.dumps(policy['example_value'])
- self.AddText(element, '%s: %s' % (policy['name'], example))
-
- def _AddDictionaryExample(self, parent, policy):
- '''Adds the example value of a 'dict' policy to a DOM node. Example output:
- <dl>
- <dt>Windows:</dt>
- <dd>
- Software\Policies\Chromium\ProxySettings = "{ 'ProxyMode': 'direct' }"
- </dd>
- <dt>Android/Linux:</dt>
- <dd>"ProxySettings": {
- "ProxyMode": "direct"
- }
- </dd>
- <dt>Mac:</dt>
- <dd>
- <key>ProxySettings</key>
- <dict>
- <key>ProxyMode</key>
- <string>direct</string>
- </dict>
- </dd>
- </dl>
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: The data structure of a policy.
- '''
- examples = self._AddStyledElement(parent, 'dl', ['dd dl'])
- if self.IsPolicySupportedOnPlatform(policy, 'win'):
- self._AddDictionaryExampleWindows(examples, policy)
- if (self.IsPolicySupportedOnPlatform(policy, 'android') or
- self.IsPolicySupportedOnPlatform(policy, 'linux')):
- self._AddDictionaryExampleAndroidLinux(examples, policy)
- if self.IsPolicySupportedOnPlatform(policy, 'mac'):
- self._AddDictionaryExampleMac(examples, policy)
-
- def _AddExample(self, parent, policy):
- '''Adds the HTML DOM representation of the example value of a policy to
- a DOM node. It is simple text for boolean policies, like
- '0x00000001 (Windows), true (Linux), true (Android), <true /> (Mac)'
- in case of boolean policies, but it may also contain other HTML elements.
- (See method _AddListExample.)
-
- Args:
- parent: The DOM node for which the example will be added.
- policy: The data structure of a policy.
-
- Raises:
- Exception: If the type of the policy is unknown or the example value
- of the policy is out of its expected range.
- '''
- example_value = policy['example_value']
- policy_type = policy['type']
- if policy_type == 'main':
- pieces = []
- if self.IsPolicySupportedOnPlatform(policy, 'win'):
- value = '0x00000001' if example_value else '0x00000000'
- pieces.append(value + ' (Windows)')
- if self.IsPolicySupportedOnPlatform(policy, 'linux'):
- value = 'true' if example_value else 'false'
- pieces.append(value + ' (Linux)')
- if self.IsPolicySupportedOnPlatform(policy, 'android'):
- value = 'true' if example_value else 'false'
- pieces.append(value + ' (Android)')
- if self.IsPolicySupportedOnPlatform(policy, 'mac'):
- value = '<true />' if example_value else '<false />'
- pieces.append(value + ' (Mac)')
- self.AddText(parent, ', '.join(pieces))
- elif policy_type == 'string':
- self.AddText(parent, '"%s"' % example_value)
- elif policy_type in ('int', 'int-enum'):
- pieces = []
- if self.IsPolicySupportedOnPlatform(policy, 'win'):
- pieces.append('0x%08x (Windows)' % example_value)
- if self.IsPolicySupportedOnPlatform(policy, 'linux'):
- pieces.append('%d (Linux)' % example_value)
- if self.IsPolicySupportedOnPlatform(policy, 'android'):
- pieces.append('%d (Android)' % example_value)
- if self.IsPolicySupportedOnPlatform(policy, 'mac'):
- pieces.append('%d (Mac)' % example_value)
- self.AddText(parent, ', '.join(pieces))
- elif policy_type == 'string-enum':
- self.AddText(parent, '"%s"' % (example_value))
- elif policy_type in ('list', 'string-enum-list'):
- self._AddListExample(parent, policy)
- elif policy_type == 'dict':
- self._AddDictionaryExample(parent, policy)
- else:
- raise Exception('Unknown policy type: ' + policy_type)
-
- def _AddPolicyAttribute(self, dl, term_id,
- definition=None, definition_style=None):
- '''Adds a term-definition pair to a HTML DOM <dl> node. This method is
- used by _AddPolicyDetails. Its result will have the form of:
- <dt style="...">...</dt>
- <dd style="...">...</dd>
-
- Args:
- dl: The DOM node of the <dl> list.
- term_id: A key to self._STRINGS[] which specifies the term of the pair.
- definition: The text of the definition. (Optional.)
- definition_style: List of references to values self._STYLE[] that specify
- the CSS stylesheet of the <dd> (definition) element.
-
- Returns:
- The DOM node representing the definition <dd> element.
- '''
- # Avoid modifying the default value of definition_style.
- if definition_style == None:
- definition_style = []
- term = self._GetLocalizedMessage(term_id)
- self._AddStyledElement(dl, 'dt', ['dt'], {}, term)
- return self._AddStyledElement(dl, 'dd', definition_style, {}, definition)
-
- def _AddSupportedOnList(self, parent, supported_on_list):
- '''Creates a HTML list containing the platforms, products and versions
- that are specified in the list of supported_on.
-
- Args:
- parent: The DOM node for which the list will be added.
- supported_on_list: The list of supported products, as a list of
- dictionaries.
- '''
- ul = self._AddStyledElement(parent, 'ul', ['ul'])
- for supported_on in supported_on_list:
- text = []
- product = supported_on['product']
- platforms = supported_on['platforms']
- text.append(self._PRODUCT_MAP[product])
- text.append('(%s)' %
- self._MapListToString(self._PLATFORM_MAP, platforms))
- if supported_on['since_version']:
- since_version = self._GetLocalizedMessage('since_version')
- text.append(since_version.replace('$6', supported_on['since_version']))
- if supported_on['until_version']:
- until_version = self._GetLocalizedMessage('until_version')
- text.append(until_version.replace('$6', supported_on['until_version']))
- # Add the list element:
- self.AddElement(ul, 'li', {}, ' '.join(text))
-
- def _AddPolicyDetails(self, parent, policy):
- '''Adds the list of attributes of a policy to the HTML DOM node parent.
- It will have the form:
- <dl>
- <dt>Attribute:</dt><dd>Description</dd>
- ...
- </dl>
-
- Args:
- parent: A DOM element for which the list will be added.
- policy: The data structure of the policy.
- '''
-
- dl = self.AddElement(parent, 'dl')
- data_type = [self._TYPE_MAP[policy['type']]]
- qualified_types = []
- is_complex_policy = False
- if (self.IsPolicySupportedOnPlatform(policy, 'android') and
- self._RESTRICTION_TYPE_MAP.get(policy['type'], None)):
- qualified_types.append('Android:%s' %
- self._RESTRICTION_TYPE_MAP[policy['type']])
- if policy['type'] in ('dict', 'list'):
- is_complex_policy = True
- if (self.IsPolicySupportedOnPlatform(policy, 'win') and
- self._REG_TYPE_MAP.get(policy['type'], None)):
- qualified_types.append('Windows:%s' % self._REG_TYPE_MAP[policy['type']])
- if policy['type'] == 'dict':
- is_complex_policy = True
- if qualified_types:
- data_type.append('[%s]' % ', '.join(qualified_types))
- if is_complex_policy:
- data_type.append('(%s)' %
- self._GetLocalizedMessage('complex_policies_on_windows'))
- self._AddPolicyAttribute(dl, 'data_type', ' '.join(data_type))
- if policy['type'] != 'external':
- # All types except 'external' can be set through platform policy.
- if self.IsPolicySupportedOnPlatform(policy, 'win'):
- if self.CanBeRecommended(policy) and not self.CanBeMandatory(policy):
- key_name = self.config['win_reg_recommended_key_name']
- else:
- key_name = self.config['win_reg_mandatory_key_name']
- self._AddPolicyAttribute(
- dl,
- 'win_reg_loc',
- key_name + '\\' + policy['name'],
- ['.monospace'])
- if (self.IsPolicySupportedOnPlatform(policy, 'linux') or
- self.IsPolicySupportedOnPlatform(policy, 'mac')):
- self._AddPolicyAttribute(
- dl,
- 'mac_linux_pref_name',
- policy['name'],
- ['.monospace'])
- if self.IsPolicySupportedOnPlatform(policy, 'android'):
- self._AddPolicyAttribute(
- dl,
- 'android_restriction_name',
- policy['name'],
- ['.monospace'])
- dd = self._AddPolicyAttribute(dl, 'supported_on')
- self._AddSupportedOnList(dd, policy['supported_on'])
- dd = self._AddPolicyAttribute(dl, 'supported_features')
- self._AddFeatures(dd, policy)
- dd = self._AddPolicyAttribute(dl, 'description')
- self._AddDescription(dd, policy)
- if (self.IsPolicySupportedOnPlatform(policy, 'win') or
- self.IsPolicySupportedOnPlatform(policy, 'linux') or
- self.IsPolicySupportedOnPlatform(policy, 'android') or
- self.IsPolicySupportedOnPlatform(policy, 'mac')):
- # Don't add an example for ChromeOS-only policies.
- if policy['type'] != 'external':
- # All types except 'external' can be set through platform policy.
- dd = self._AddPolicyAttribute(dl, 'example_value')
- self._AddExample(dd, policy)
-
- def _AddPolicyNote(self, parent, policy):
- '''If a policy has an additional web page assigned with it, then add
- a link for that page.
-
- Args:
- policy: The data structure of the policy.
- '''
- if 'problem_href' not in policy:
- return
- problem_href = policy['problem_href']
- div = self._AddStyledElement(parent, 'div', ['div.note'])
- note = self._GetLocalizedMessage('note').replace('$6', problem_href)
- self._AddParagraphs(div, note)
-
- def _AddPolicyRow(self, parent, policy):
- '''Adds a row for the policy in the summary table.
-
- Args:
- parent: The DOM node of the summary table.
- policy: The data structure of the policy.
- '''
- tr = self._AddStyledElement(parent, 'tr', ['tr'])
- indent = 'padding-left: %dpx;' % (7 + self._indent_level * 14)
- if policy['type'] != 'group':
- # Normal policies get two columns with name and caption.
- name_td = self._AddStyledElement(tr, 'td', ['td', 'td.left'],
- {'style': indent})
- self.AddElement(name_td, 'a',
- {'href': '#' + policy['name']}, policy['name'])
- self._AddStyledElement(tr, 'td', ['td', 'td.right'], {},
- policy['caption'])
- else:
- # Groups get one column with caption.
- name_td = self._AddStyledElement(tr, 'td', ['td', 'td.left'],
- {'style': indent, 'colspan': '2'})
- self.AddElement(name_td, 'a', {'href': '#' + policy['name']},
- policy['caption'])
-
- def _AddPolicySection(self, parent, policy):
- '''Adds a section about the policy in the detailed policy listing.
-
- Args:
- parent: The DOM node of the <div> of the detailed policy list.
- policy: The data structure of the policy.
- '''
- # Set style according to group nesting level.
- indent = 'margin-left: %dpx' % (self._indent_level * 28)
- if policy['type'] == 'group':
- heading = 'h2'
- else:
- heading = 'h3'
- parent2 = self.AddElement(parent, 'div', {'style': indent})
-
- h2 = self.AddElement(parent2, heading)
- self.AddElement(h2, 'a', {'name': policy['name']})
- if policy['type'] != 'group':
- # Normal policies get a full description.
- policy_name_text = policy['name']
- if 'deprecated' in policy and policy['deprecated'] == True:
- policy_name_text += " ("
- policy_name_text += self._GetLocalizedMessage('deprecated') + ")"
- self.AddText(h2, policy_name_text)
- self.AddElement(parent2, 'span', {}, policy['caption'])
- self._AddPolicyNote(parent2, policy)
- self._AddPolicyDetails(parent2, policy)
- else:
- # Groups get a more compact description.
- self.AddText(h2, policy['caption'])
- self._AddStyledElement(parent2, 'div', ['div.group_desc'],
- {}, policy['desc'])
- self.AddElement(
- parent2, 'a', {'href': '#top'},
- self._GetLocalizedMessage('back_to_top'))
-
- #
- # Implementation of abstract methods of TemplateWriter:
- #
-
- def IsDeprecatedPolicySupported(self, policy):
- return True
-
- def WritePolicy(self, policy):
- self._AddPolicyRow(self._summary_tbody, policy)
- self._AddPolicySection(self._details_div, policy)
-
- def BeginPolicyGroup(self, group):
- self.WritePolicy(group)
- self._indent_level += 1
-
- def EndPolicyGroup(self):
- self._indent_level -= 1
-
- def BeginTemplate(self):
- # Add a <div> for the summary section.
- if self._GetChromiumVersionString() is not None:
- self.AddComment(self._main_div, self.config['build'] + \
- ' version: ' + self._GetChromiumVersionString())
-
- summary_div = self.AddElement(self._main_div, 'div')
- self.AddElement(summary_div, 'a', {'name': 'top'})
- self.AddElement(summary_div, 'br')
- self._AddParagraphs(
- summary_div,
- self._GetLocalizedMessage('intro'))
- self.AddElement(summary_div, 'br')
- self.AddElement(summary_div, 'br')
- self.AddElement(summary_div, 'br')
- # Add the summary table of policies.
- summary_table = self._AddStyledElement(summary_div, 'table', ['table'])
- # Add the first row.
- thead = self.AddElement(summary_table, 'thead')
- tr = self._AddStyledElement(thead, 'tr', ['tr'])
- self._AddStyledElement(
- tr, 'td', ['td', 'td.left', 'thead td'], {},
- self._GetLocalizedMessage('name_column_title'))
- self._AddStyledElement(
- tr, 'td', ['td', 'td.right', 'thead td'], {},
- self._GetLocalizedMessage('description_column_title'))
- self._summary_tbody = self.AddElement(summary_table, 'tbody')
-
- # Add a <div> for the detailed policy listing.
- self._details_div = self.AddElement(self._main_div, 'div')
-
- def Init(self):
- dom_impl = minidom.getDOMImplementation('')
- self._doc = dom_impl.createDocument(None, 'html', None)
- body = self.AddElement(self._doc.documentElement, 'body')
- self._main_div = self.AddElement(body, 'div')
- self._indent_level = 0
-
- # Human-readable names of supported platforms.
- self._PLATFORM_MAP = {
- 'win': 'Windows',
- 'mac': 'Mac',
- 'linux': 'Linux',
- 'chrome_os': self.config['os_name'],
- 'android': 'Android',
- 'ios': 'iOS',
- }
- # Human-readable names of supported products.
- self._PRODUCT_MAP = {
- 'chrome': self.config['app_name'],
- 'chrome_frame': self.config['frame_name'],
- 'chrome_os': self.config['os_name'],
- }
- # Human-readable names of supported features. Each supported feature has
- # a 'doc_feature_X' entry in |self.messages|.
- self._FEATURE_MAP = {}
- for message in self.messages:
- if message.startswith('doc_feature_'):
- self._FEATURE_MAP[message[12:]] = self.messages[message]['text']
- # Human-readable names of types.
- self._TYPE_MAP = {
- 'string': 'String',
- 'int': 'Integer',
- 'main': 'Boolean',
- 'int-enum': 'Integer',
- 'string-enum': 'String',
- 'list': 'List of strings',
- 'string-enum-list': 'List of strings',
- 'dict': 'Dictionary',
- 'external': 'External data reference',
- }
- self._REG_TYPE_MAP = {
- 'string': 'REG_SZ',
- 'int': 'REG_DWORD',
- 'main': 'REG_DWORD',
- 'int-enum': 'REG_DWORD',
- 'string-enum': 'REG_SZ',
- 'dict': 'REG_SZ',
- }
- self._RESTRICTION_TYPE_MAP = {
- 'int-enum': 'choice',
- 'string-enum': 'choice',
- 'list': 'string',
- 'string-enum-list': 'multi-select',
- 'dict': 'string',
- }
- # The CSS style-sheet used for the document. It will be used in Google
- # Sites, which strips class attributes from HTML tags. To work around this,
- # the style-sheet is a dictionary and the style attributes will be added
- # "by hand" for each element.
- self._STYLE = {
- 'table': 'border-style: none; border-collapse: collapse;',
- 'tr': 'height: 0px;',
- 'td': 'border: 1px dotted rgb(170, 170, 170); padding: 7px; '
- 'vertical-align: top; width: 236px; height: 15px;',
- 'thead td': 'font-weight: bold;',
- 'td.left': 'width: 200px;',
- 'td.right': 'width: 100%;',
- 'dt': 'font-weight: bold;',
- 'dd dl': 'margin-top: 0px; margin-bottom: 0px;',
- '.monospace': 'font-family: monospace;',
- '.pre': 'white-space: pre;',
- 'div.note': 'border: 2px solid black; padding: 5px; margin: 5px;',
- 'div.group_desc': 'margin-top: 20px; margin-bottom: 20px;',
- 'ul': 'padding-left: 0px; margin-left: 0px;'
- }
-
-
- def GetTemplateText(self):
- # Return the text representation of the main <div> tag.
- return self._main_div.toxml()
- # To get a complete HTML file, use the following.
- # return self._doc.toxml()
diff --git a/grit/format/policy_templates/writers/doc_writer_unittest.py b/grit/format/policy_templates/writers/doc_writer_unittest.py
deleted file mode 100644
index e51f9f0..0000000
--- a/grit/format/policy_templates/writers/doc_writer_unittest.py
+++ /dev/null
@@ -1,951 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.policy_templates.writers.doc_writer'''
-
-
-import json
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-from xml.dom import minidom
-
-from grit.format.policy_templates.writers import writer_unittest_common
-from grit.format.policy_templates.writers import doc_writer
-
-
-class MockMessageDictionary:
- '''A mock dictionary passed to a writer as the dictionary of
- localized messages.
- '''
-
- # Dictionary of messages.
- msg_dict = {}
-
-class DocWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for DocWriter.'''
-
- def setUp(self):
- # Create a writer for the tests.
- self.writer = doc_writer.GetWriter(
- config={
- 'app_name': 'Chrome',
- 'frame_name': 'Chrome Frame',
- 'os_name': 'Chrome OS',
- 'win_reg_mandatory_key_name': 'MockKey',
- 'win_reg_recommended_key_name': 'MockKeyRec',
- 'build': 'test_product',
- })
- self.writer.messages = {
- 'doc_back_to_top': {'text': '_test_back_to_top'},
- 'doc_complex_policies_on_windows': {'text': '_test_complex_policies_win'},
- 'doc_data_type': {'text': '_test_data_type'},
- 'doc_description': {'text': '_test_description'},
- 'doc_description_column_title': {
- 'text': '_test_description_column_title'
- },
- 'doc_example_value': {'text': '_test_example_value'},
- 'doc_feature_dynamic_refresh': {'text': '_test_feature_dynamic_refresh'},
- 'doc_feature_can_be_recommended': {'text': '_test_feature_recommended'},
- 'doc_feature_can_be_mandatory': {'text': '_test_feature_mandatory'},
- 'doc_intro': {'text': '_test_intro'},
- 'doc_mac_linux_pref_name': {'text': '_test_mac_linux_pref_name'},
- 'doc_android_restriction_name': {
- 'text': '_test_android_restriction_name'
- },
- 'doc_note': {'text': '_test_note'},
- 'doc_name_column_title': {'text': '_test_name_column_title'},
- 'doc_not_supported': {'text': '_test_not_supported'},
- 'doc_since_version': {'text': '_test_since_version'},
- 'doc_supported': {'text': '_test_supported'},
- 'doc_supported_features': {'text': '_test_supported_features'},
- 'doc_supported_on': {'text': '_test_supported_on'},
- 'doc_win_reg_loc': {'text': '_test_win_reg_loc'},
-
- 'doc_bla': {'text': '_test_bla'},
- }
- self.writer.Init()
-
- # It is not worth testing the exact content of style attributes.
- # Therefore we override them here with shorter texts.
- for key in self.writer._STYLE.keys():
- self.writer._STYLE[key] = 'style_%s;' % key
- # Add some more style attributes for additional testing.
- self.writer._STYLE['key1'] = 'style1;'
- self.writer._STYLE['key2'] = 'style2;'
-
- # Create a DOM document for the tests.
- dom_impl = minidom.getDOMImplementation('')
- self.doc = dom_impl.createDocument(None, 'root', None)
- self.doc_root = self.doc.documentElement
-
- def testSkeleton(self):
- # Test if DocWriter creates the skeleton of the document correctly.
- self.writer.BeginTemplate()
- self.assertEquals(
- self.writer._main_div.toxml(),
- '<div>'
- '<div>'
- '<a name="top"/><br/><p>_test_intro</p><br/><br/><br/>'
- '<table style="style_table;">'
- '<thead><tr style="style_tr;">'
- '<td style="style_td;style_td.left;style_thead td;">'
- '_test_name_column_title'
- '</td>'
- '<td style="style_td;style_td.right;style_thead td;">'
- '_test_description_column_title'
- '</td>'
- '</tr></thead>'
- '<tbody/>'
- '</table>'
- '</div>'
- '<div/>'
- '</div>')
-
- def testVersionAnnotation(self):
- # Test if DocWriter creates the skeleton of the document correctly.
- self.writer.config['version'] = '39.0.0.0'
- self.writer.BeginTemplate()
- self.assertEquals(
- self.writer._main_div.toxml(),
- '<div>'
- '<!--test_product version: 39.0.0.0-->'
- '<div>'
- '<a name="top"/><br/><p>_test_intro</p><br/><br/><br/>'
- '<table style="style_table;">'
- '<thead><tr style="style_tr;">'
- '<td style="style_td;style_td.left;style_thead td;">'
- '_test_name_column_title'
- '</td>'
- '<td style="style_td;style_td.right;style_thead td;">'
- '_test_description_column_title'
- '</td>'
- '</tr></thead>'
- '<tbody/>'
- '</table>'
- '</div>'
- '<div/>'
- '</div>')
-
- def testGetLocalizedMessage(self):
- # Test if localized messages are retrieved correctly.
- self.writer.messages = {
- 'doc_hello_world': {'text': 'hello, vilag!'}
- }
- self.assertEquals(
- self.writer._GetLocalizedMessage('hello_world'),
- 'hello, vilag!')
-
- def testMapListToString(self):
- # Test function DocWriter.MapListToString()
- self.assertEquals(
- self.writer._MapListToString({'a1': 'a2', 'b1': 'b2'}, ['a1', 'b1']),
- 'a2, b2')
- self.assertEquals(
- self.writer._MapListToString({'a1': 'a2', 'b1': 'b2'}, []),
- '')
- result = self.writer._MapListToString(
- {'a': '1', 'b': '2', 'c': '3', 'd': '4'}, ['b', 'd'])
- expected_result = '2, 4'
- self.assertEquals(
- result,
- expected_result)
-
- def testAddStyledElement(self):
- # Test function DocWriter.AddStyledElement()
-
- # Test the case of zero style.
- e1 = self.writer._AddStyledElement(
- self.doc_root, 'z', [], {'a': 'b'}, 'text')
- self.assertEquals(
- e1.toxml(),
- '<z a="b">text</z>')
-
- # Test the case of one style.
- e2 = self.writer._AddStyledElement(
- self.doc_root, 'z', ['key1'], {'a': 'b'}, 'text')
- self.assertEquals(
- e2.toxml(),
- '<z a="b" style="style1;">text</z>')
-
- # Test the case of two styles.
- e3 = self.writer._AddStyledElement(
- self.doc_root, 'z', ['key1', 'key2'], {'a': 'b'}, 'text')
- self.assertEquals(
- e3.toxml(),
- '<z a="b" style="style1;style2;">text</z>')
-
- def testAddDescriptionIntEnum(self):
- # Test if URLs are replaced and choices of 'int-enum' policies are listed
- # correctly.
- policy = {
- 'type': 'int-enum',
- 'items': [
- {'value': 0, 'caption': 'Disable foo'},
- {'value': 2, 'caption': 'Solve your problem'},
- {'value': 5, 'caption': 'Enable bar'},
- ],
- 'desc': '''This policy disables foo, except in case of bar.
-See http://policy-explanation.example.com for more details.
-'''
- }
- self.writer._AddDescription(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '''<root><p>This policy disables foo, except in case of bar.
-See <a href="http://policy-explanation.example.com">http://policy-explanation.example.com</a> for more details.
-</p><ul><li>0 = Disable foo</li><li>2 = Solve your problem</li><li>5 = Enable bar</li></ul></root>''')
-
- def testAddDescriptionStringEnum(self):
- # Test if URLs are replaced and choices of 'int-enum' policies are listed
- # correctly.
- policy = {
- 'type': 'string-enum',
- 'items': [
- {'value': "one", 'caption': 'Disable foo'},
- {'value': "two", 'caption': 'Solve your problem'},
- {'value': "three", 'caption': 'Enable bar'},
- ],
- 'desc': '''This policy disables foo, except in case of bar.
-See http://policy-explanation.example.com for more details.
-'''
- }
- self.writer._AddDescription(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '''<root><p>This policy disables foo, except in case of bar.
-See <a href="http://policy-explanation.example.com">http://policy-explanation.example.com</a> for more details.
-</p><ul><li>&quot;one&quot; = Disable foo</li><li>&quot;two&quot; = Solve your problem</li><li>&quot;three&quot; = Enable bar</li></ul></root>''')
-
- def testAddFeatures(self):
- # Test if the list of features of a policy is handled correctly.
- policy = {
- 'features': {
- 'spaceship_docking': False,
- 'dynamic_refresh': True,
- 'can_be_recommended': True,
- }
- }
- self.writer._FEATURE_MAP = {
- 'can_be_recommended': 'Can Be Recommended',
- 'dynamic_refresh': 'Dynamic Refresh',
- 'spaceship_docking': 'Spaceship Docking',
- }
- self.writer._AddFeatures(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- 'Can Be Recommended: _test_supported, '
- 'Dynamic Refresh: _test_supported, '
- 'Spaceship Docking: _test_not_supported'
- '</root>')
-
- def testAddListExample(self):
- policy = {
- 'name': 'PolicyName',
- 'example_value': ['Foo', 'Bar'],
- 'supported_on': [ { 'platforms': ['win', 'mac', 'linux'] } ]
- }
- self.writer._AddListExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<dl style="style_dd dl;">'
- '<dt>Windows:</dt>'
- '<dd style="style_.monospace;style_.pre;">'
- 'MockKey\\PolicyName\\1 = &quot;Foo&quot;\n'
- 'MockKey\\PolicyName\\2 = &quot;Bar&quot;'
- '</dd>'
- '<dt>Android/Linux:</dt>'
- '<dd style="style_.monospace;">'
- '[&quot;Foo&quot;, &quot;Bar&quot;]'
- '</dd>'
- '<dt>Mac:</dt>'
- '<dd style="style_.monospace;style_.pre;">'
- '&lt;array&gt;\n'
- ' &lt;string&gt;Foo&lt;/string&gt;\n'
- ' &lt;string&gt;Bar&lt;/string&gt;\n'
- '&lt;/array&gt;'
- '</dd>'
- '</dl>'
- '</root>')
-
- def testBoolExample(self):
- # Test representation of boolean example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'main',
- 'example_value': True,
- 'supported_on': [ { 'platforms': ['win', 'mac', 'linux', 'android'] } ]
- }
- e1 = self.writer.AddElement(self.doc_root, 'e1')
- self.writer._AddExample(e1, policy)
- self.assertEquals(
- e1.toxml(),
- '<e1>0x00000001 (Windows),'
- ' true (Linux), true (Android),'
- ' &lt;true /&gt; (Mac)</e1>')
-
- policy = {
- 'name': 'PolicyName',
- 'type': 'main',
- 'example_value': False,
- 'supported_on': [ { 'platforms': ['win', 'mac', 'linux', 'android'] } ]
- }
- e2 = self.writer.AddElement(self.doc_root, 'e2')
- self.writer._AddExample(e2, policy)
- self.assertEquals(
- e2.toxml(),
- '<e2>0x00000000 (Windows),'
- ' false (Linux), false (Android),'
- ' &lt;false /&gt; (Mac)</e2>')
-
- def testIntEnumExample(self):
- # Test representation of 'int-enum' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'int-enum',
- 'example_value': 16,
- 'supported_on': [ { 'platforms': ['win', 'mac', 'linux', 'android'] } ]
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>0x00000010 (Windows), 16 (Linux), 16 (Android), 16 (Mac)</root>')
-
- def testStringEnumExample(self):
- # Test representation of 'string-enum' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'string-enum',
- 'example_value': "wacky"
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>&quot;wacky&quot;</root>')
-
- def testListExample(self):
- # Test representation of 'list' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'list',
- 'example_value': ['one', 'two'],
- 'supported_on': [ { 'platforms': ['linux'] } ]
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><dl style="style_dd dl;">'
- '<dt>Android/Linux:</dt>'
- '<dd style="style_.monospace;">'
- '[&quot;one&quot;, &quot;two&quot;]'
- '</dd></dl></root>')
-
- def testStringEnumListExample(self):
- # Test representation of 'string-enum-list' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'string-enum-list',
- 'example_value': ['one', 'two'],
- 'supported_on': [ { 'platforms': ['linux'] } ]
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><dl style="style_dd dl;">'
- '<dt>Android/Linux:</dt>'
- '<dd style="style_.monospace;">'
- '[&quot;one&quot;, &quot;two&quot;]'
- '</dd></dl></root>')
-
- def testStringExample(self):
- # Test representation of 'string' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'string',
- 'example_value': 'awesome-example'
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>&quot;awesome-example&quot;</root>')
-
- def testIntExample(self):
- # Test representation of 'int' example values.
- policy = {
- 'name': 'PolicyName',
- 'type': 'int',
- 'example_value': 26,
- 'supported_on': [ { 'platforms': ['win', 'mac', 'linux', 'android'] } ]
- }
- self.writer._AddExample(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>0x0000001a (Windows), 26 (Linux), 26 (Android), 26 (Mac)</root>')
-
- def testAddPolicyAttribute(self):
- # Test creating a policy attribute term-definition pair.
- self.writer._AddPolicyAttribute(
- self.doc_root, 'bla', 'hello, world', ['key1'])
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<dt style="style_dt;">_test_bla</dt>'
- '<dd style="style1;">hello, world</dd>'
- '</root>')
-
- def testAddPolicyDetails(self):
- # Test if the definition list (<dl>) of policy details is created correctly.
- policy = {
- 'type': 'main',
- 'name': 'TestPolicyName',
- 'caption': 'TestPolicyCaption',
- 'desc': 'TestPolicyDesc',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['win', 'mac', 'linux'],
- 'since_version': '8',
- 'until_version': '',
- }, {
- 'product': 'chrome',
- 'platforms': ['android'],
- 'since_version': '30',
- 'until_version': '',
- }, {
- 'product': 'chrome',
- 'platforms': ['ios'],
- 'since_version': '34',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': False},
- 'example_value': False
- }
- self.writer.messages['doc_since_version'] = {'text': '...$6...'}
- self.writer._AddPolicyDetails(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>Boolean [Windows:REG_DWORD]</dd>'
- '<dt style="style_dt;">_test_win_reg_loc</dt>'
- '<dd style="style_.monospace;">MockKey\TestPolicyName</dd>'
- '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
- '<dd style="style_.monospace;">TestPolicyName</dd>'
- '<dt style="style_dt;">_test_android_restriction_name</dt>'
- '<dd style="style_.monospace;">TestPolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Windows, Mac, Linux) ...8...</li>'
- '<li>Chrome (Android) ...30...</li>'
- '<li>Chrome (iOS) ...34...</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt><dd><p>TestPolicyDesc</p></dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>0x00000000 (Windows), false (Linux),'
- ' false (Android), &lt;false /&gt; (Mac)</dd>'
- '</dl></root>')
-
- def testAddDictPolicyDetails(self):
- # Test if the definition list (<dl>) of policy details is created correctly
- # for 'dict' policies.
- policy = {
- 'type': 'dict',
- 'name': 'TestPolicyName',
- 'caption': 'TestPolicyCaption',
- 'desc': 'TestPolicyDesc',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['win', 'mac', 'linux'],
- 'since_version': '8',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': False},
- 'example_value': { 'foo': 123 }
- }
- self.writer.messages['doc_since_version'] = {'text': '...$6...'}
- self.writer._AddPolicyDetails(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>Dictionary [Windows:REG_SZ] (_test_complex_policies_win)</dd>'
- '<dt style="style_dt;">_test_win_reg_loc</dt>'
- '<dd style="style_.monospace;">MockKey\TestPolicyName</dd>'
- '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
- '<dd style="style_.monospace;">TestPolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Windows, Mac, Linux) ...8...</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt><dd><p>TestPolicyDesc</p></dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>'
- '<dl style="style_dd dl;">'
- '<dt>Windows:</dt>'
- '<dd style="style_.monospace;style_.pre;">MockKey\TestPolicyName = {&quot;foo&quot;: 123}</dd>'
- '<dt>Android/Linux:</dt>'
- '<dd style="style_.monospace;">TestPolicyName: {&quot;foo&quot;: 123}</dd>'
- '<dt>Mac:</dt>'
- '<dd style="style_.monospace;style_.pre;">'
- '&lt;key&gt;TestPolicyName&lt;/key&gt;\n'
- '&lt;dict&gt;\n'
- ' &lt;key&gt;foo&lt;/key&gt;\n'
- ' &lt;integer&gt;123&lt;/integer&gt;\n'
- '&lt;/dict&gt;'
- '</dd>'
- '</dl>'
- '</dd>'
- '</dl></root>')
-
- def testAddPolicyDetailsRecommendedOnly(self):
- policy = {
- 'type': 'main',
- 'name': 'TestPolicyName',
- 'caption': 'TestPolicyCaption',
- 'desc': 'TestPolicyDesc',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['win', 'mac', 'linux'],
- 'since_version': '8',
- 'until_version': '',
- }, {
- 'product': 'chrome',
- 'platforms': ['android'],
- 'since_version': '30',
- 'until_version': '',
- }, {
- 'product': 'chrome',
- 'platforms': ['ios'],
- 'since_version': '34',
- 'until_version': '',
- }],
- 'features': {
- 'dynamic_refresh': False,
- 'can_be_mandatory': False,
- 'can_be_recommended': True
- },
- 'example_value': False
- }
- self.writer.messages['doc_since_version'] = {'text': '...$6...'}
- self.writer._AddPolicyDetails(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>Boolean [Windows:REG_DWORD]</dd>'
- '<dt style="style_dt;">_test_win_reg_loc</dt>'
- '<dd style="style_.monospace;">MockKeyRec\TestPolicyName</dd>'
- '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
- '<dd style="style_.monospace;">TestPolicyName</dd>'
- '<dt style="style_dt;">_test_android_restriction_name</dt>'
- '<dd style="style_.monospace;">TestPolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Windows, Mac, Linux) ...8...</li>'
- '<li>Chrome (Android) ...30...</li>'
- '<li>Chrome (iOS) ...34...</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_mandatory: _test_not_supported,'
- ' _test_feature_recommended: _test_supported,'
- ' _test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt><dd><p>TestPolicyDesc</p></dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>0x00000000 (Windows), false (Linux),'
- ' false (Android), &lt;false /&gt; (Mac)</dd>'
- '</dl></root>')
-
- def testAddPolicyNote(self):
- # TODO(jkummerow): The functionality tested by this test is currently not
- # used for anything and will probably soon be removed.
- # Test if nodes are correctly added to policies.
- policy = {
- 'problem_href': 'http://www.example.com/5'
- }
- self.writer.messages['doc_note'] = {'text': '...$6...'}
- self.writer._AddPolicyNote(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><div style="style_div.note;"><p>...'
- '<a href="http://www.example.com/5">http://www.example.com/5</a>'
- '...</p></div></root>')
-
- def testAddPolicyRow(self):
- # Test if policies are correctly added to the summary table.
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'type': 'string',
- }
- self.writer._indent_level = 3
- self.writer._AddPolicyRow(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><tr style="style_tr;">'
- '<td style="style_td;style_td.left;padding-left: 49px;">'
- '<a href="#PolicyName">PolicyName</a>'
- '</td>'
- '<td style="style_td;style_td.right;">PolicyCaption</td>'
- '</tr></root>')
- self.setUp()
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'type': 'group',
- }
- self.writer._indent_level = 2
- self.writer._AddPolicyRow(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><tr style="style_tr;">'
- '<td colspan="2" style="style_td;style_td.left;padding-left: 35px;">'
- '<a href="#PolicyName">PolicyCaption</a>'
- '</td>'
- '</tr></root>')
-
- def testAddPolicySection(self):
- # Test if policy details are correctly added to the document.
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'desc': 'PolicyDesc',
- 'type': 'string',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['win', 'mac'],
- 'since_version': '7',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': False},
- 'example_value': 'False'
- }
- self.writer.messages['doc_since_version'] = {'text': '..$6..'}
- self.writer._AddPolicySection(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<div style="margin-left: 0px">'
- '<h3><a name="PolicyName"/>PolicyName</h3>'
- '<span>PolicyCaption</span>'
- '<dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>String [Windows:REG_SZ]</dd>'
- '<dt style="style_dt;">_test_win_reg_loc</dt>'
- '<dd style="style_.monospace;">MockKey\\PolicyName</dd>'
- '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
- '<dd style="style_.monospace;">PolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Windows, Mac) ..7..</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt>'
- '<dd><p>PolicyDesc</p></dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>&quot;False&quot;</dd>'
- '</dl>'
- '<a href="#top">_test_back_to_top</a>'
- '</div>'
- '</root>')
- # Test for groups.
- self.setUp()
- policy['type'] = 'group'
- self.writer._AddPolicySection(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<div style="margin-left: 0px">'
- '<h2><a name="PolicyName"/>PolicyCaption</h2>'
- '<div style="style_div.group_desc;">PolicyDesc</div>'
- '<a href="#top">_test_back_to_top</a>'
- '</div>'
- '</root>')
-
- def testAddPolicySectionForWindowsOnly(self):
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'desc': 'PolicyDesc',
- 'type': 'int',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['win'],
- 'since_version': '33',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': False},
- 'example_value': 123
- }
- self.writer.messages['doc_since_version'] = {'text': '..$6..'}
- self.writer._AddPolicySection(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<div style="margin-left: 0px">'
- '<h3><a name="PolicyName"/>PolicyName</h3>'
- '<span>PolicyCaption</span>'
- '<dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>Integer [Windows:REG_DWORD]</dd>'
- '<dt style="style_dt;">_test_win_reg_loc</dt>'
- '<dd style="style_.monospace;">MockKey\\PolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Windows) ..33..</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt>'
- '<dd><p>PolicyDesc</p></dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>0x0000007b (Windows)</dd>'
- '</dl>'
- '<a href="#top">_test_back_to_top</a>'
- '</div>'
- '</root>')
-
- def testAddPolicySectionForMacOnly(self):
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'desc': 'PolicyDesc',
- 'type': 'int',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['mac'],
- 'since_version': '33',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': False},
- 'example_value': 123
- }
- self.writer.messages['doc_since_version'] = {'text': '..$6..'}
- self.writer._AddPolicySection(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<div style="margin-left: 0px">'
- '<h3><a name="PolicyName"/>PolicyName</h3>'
- '<span>PolicyCaption</span>'
- '<dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>Integer</dd>'
- '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
- '<dd style="style_.monospace;">PolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Mac) ..33..</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt>'
- '<dd><p>PolicyDesc</p></dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>123 (Mac)</dd>'
- '</dl>'
- '<a href="#top">_test_back_to_top</a>'
- '</div>'
- '</root>')
-
- def testAddPolicySectionForLinuxOnly(self):
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'desc': 'PolicyDesc',
- 'type': 'int',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['linux'],
- 'since_version': '33',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': False},
- 'example_value': 123
- }
- self.writer.messages['doc_since_version'] = {'text': '..$6..'}
- self.writer._AddPolicySection(self.doc_root, policy)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<div style="margin-left: 0px">'
- '<h3><a name="PolicyName"/>PolicyName</h3>'
- '<span>PolicyCaption</span>'
- '<dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>Integer</dd>'
- '<dt style="style_dt;">_test_mac_linux_pref_name</dt>'
- '<dd style="style_.monospace;">PolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Linux) ..33..</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt>'
- '<dd><p>PolicyDesc</p></dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>123 (Linux)</dd>'
- '</dl>'
- '<a href="#top">_test_back_to_top</a>'
- '</div>'
- '</root>')
-
- def testAddPolicySectionForAndroidOnly(self):
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'desc': 'PolicyDesc',
- 'type': 'int',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['android'],
- 'since_version': '33',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': False},
- 'example_value': 123
- }
- self.writer.messages['doc_since_version'] = {'text': '..$6..'}
- self.writer._AddPolicySection(self.doc_root, policy)
- self.assertTrue(self.writer.IsPolicySupportedOnPlatform(policy, 'android'))
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<div style="margin-left: 0px">'
- '<h3><a name="PolicyName"/>PolicyName</h3>'
- '<span>PolicyCaption</span>'
- '<dl>'
- '<dt style="style_dt;">_test_data_type</dt>'
- '<dd>Integer</dd>'
- '<dt style="style_dt;">_test_android_restriction_name</dt>'
- '<dd style="style_.monospace;">PolicyName</dd>'
- '<dt style="style_dt;">_test_supported_on</dt>'
- '<dd>'
- '<ul style="style_ul;">'
- '<li>Chrome (Android) ..33..</li>'
- '</ul>'
- '</dd>'
- '<dt style="style_dt;">_test_supported_features</dt>'
- '<dd>_test_feature_dynamic_refresh: _test_not_supported</dd>'
- '<dt style="style_dt;">_test_description</dt>'
- '<dd><p>PolicyDesc</p></dd>'
- '<dt style="style_dt;">_test_example_value</dt>'
- '<dd>123 (Android)</dd>'
- '</dl>'
- '<a href="#top">_test_back_to_top</a>'
- '</div>'
- '</root>')
-
- def testAddDictionaryExample(self):
- policy = {
- 'name': 'PolicyName',
- 'caption': 'PolicyCaption',
- 'desc': 'PolicyDesc',
- 'type': 'dict',
- 'supported_on': [{
- 'product': 'chrome',
- 'platforms': ['win', 'mac', 'linux'],
- 'since_version': '7',
- 'until_version': '',
- }],
- 'features': {'dynamic_refresh': False},
- 'example_value': {
- "ProxyMode": "direct",
- "List": ["1", "2", "3"],
- "True": True,
- "False": False,
- "Integer": 123,
- "DictList": [ {
- "A": 1,
- "B": 2,
- }, {
- "C": 3,
- "D": 4,
- },
- ],
- },
- }
- self.writer._AddDictionaryExample(self.doc_root, policy)
- value = json.dumps(policy['example_value']).replace('"', '&quot;')
- self.assertEquals(
- self.doc_root.toxml(),
- '<root>'
- '<dl style="style_dd dl;">'
- '<dt>Windows:</dt>'
- '<dd style="style_.monospace;style_.pre;">MockKey\PolicyName = '
- + value +
- '</dd>'
- '<dt>Android/Linux:</dt>'
- '<dd style="style_.monospace;">PolicyName: ' + value + '</dd>'
- '<dt>Mac:</dt>'
- '<dd style="style_.monospace;style_.pre;">'
- '&lt;key&gt;PolicyName&lt;/key&gt;\n'
- '&lt;dict&gt;\n'
- ' &lt;key&gt;DictList&lt;/key&gt;\n'
- ' &lt;array&gt;\n'
- ' &lt;dict&gt;\n'
- ' &lt;key&gt;A&lt;/key&gt;\n'
- ' &lt;integer&gt;1&lt;/integer&gt;\n'
- ' &lt;key&gt;B&lt;/key&gt;\n'
- ' &lt;integer&gt;2&lt;/integer&gt;\n'
- ' &lt;/dict&gt;\n'
- ' &lt;dict&gt;\n'
- ' &lt;key&gt;C&lt;/key&gt;\n'
- ' &lt;integer&gt;3&lt;/integer&gt;\n'
- ' &lt;key&gt;D&lt;/key&gt;\n'
- ' &lt;integer&gt;4&lt;/integer&gt;\n'
- ' &lt;/dict&gt;\n'
- ' &lt;/array&gt;\n'
- ' &lt;key&gt;False&lt;/key&gt;\n'
- ' &lt;false/&gt;\n'
- ' &lt;key&gt;Integer&lt;/key&gt;\n'
- ' &lt;integer&gt;123&lt;/integer&gt;\n'
- ' &lt;key&gt;List&lt;/key&gt;\n'
- ' &lt;array&gt;\n'
- ' &lt;string&gt;1&lt;/string&gt;\n'
- ' &lt;string&gt;2&lt;/string&gt;\n'
- ' &lt;string&gt;3&lt;/string&gt;\n'
- ' &lt;/array&gt;\n'
- ' &lt;key&gt;ProxyMode&lt;/key&gt;\n'
- ' &lt;string&gt;direct&lt;/string&gt;\n'
- ' &lt;key&gt;True&lt;/key&gt;\n'
- ' &lt;true/&gt;\n'
- '&lt;/dict&gt;'
- '</dd>'
- '</dl>'
- '</root>')
-
- def testParagraphs(self):
- text = 'Paragraph 1\n\nParagraph 2\n\nParagraph 3'
- self.writer._AddParagraphs(self.doc_root, text)
- self.assertEquals(
- self.doc_root.toxml(),
- '<root><p>Paragraph 1</p><p>Paragraph 2</p><p>Paragraph 3</p></root>')
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/ios_plist_writer.py b/grit/format/policy_templates/writers/ios_plist_writer.py
deleted file mode 100644
index b726ffa..0000000
--- a/grit/format/policy_templates/writers/ios_plist_writer.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-import base64
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import plist_writer
-
-
-# This writer outputs a Property List with an example for each of the policies
-# supported on iOS. This plist can be pushed to Chrome on iOS via the MDM API
-# introduced in iOS 7.
-
-CHROME_POLICY_COMMENT = '''\
- ChromePolicy is the preferred key to configure Chrome.
- Each of the keys in this <dict> configures a Chrome policy.
- All of the Chrome policies are configured with an example
- value below.
- Note that it's not necessary to configure all of them. '''
-
-ENCODED_CHROME_POLICY_COMMENT = '''\
- EncodedChromePolicy contains a Property List file, encoded in Base64,
- which contains the same policies that can go in ChromePolicy.
- This key can be used by vendors that restrict the app configuration
- types to strings.
- The value of this string can be validated by running these
- commands in Mac OS X:
-
- # (first, copy-paste the string into a file named "policy.plist")
- # base64 -D < policy.plist > decoded_policy.plist
- # plutil -lint decoded_policy.plist
-
- plutil should indicate that decoded_policy.plist is valid,
- otherwise Chrome will reject the encoded string too.
-
- This command can be used to pretty-print the plist file:
-
- # plutil -convert xml1 decoded_policy.plist
-
- Note that <ChromePolicy> is the preferred key to configure Chrome.
- If <ChromePolicy> is present then <EncodedChromePolicy> is ignored. '''
-
-def GetWriter(config):
- '''Factory method for creating IOSPlistWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return IOSPlistWriter(['ios'], config)
-
-
-class IOSPlistWriter(plist_writer.PListWriter):
- '''Class for generating policy templates in the iOS plist format.
- It is used by PolicyTemplateGenerator to write plist files.
- '''
-
- # Overridden.
- def IsPolicySupported(self, policy):
- # Output examples only for policies that are supported on iOS.
- for support_on in policy['supported_on']:
- if ('ios' in support_on['platforms'] and
- support_on['until_version'] == '' and
- super(IOSPlistWriter, self).IsPolicySupported(policy)):
- return True
- return False
-
- def _WriteValue(self, parent, value):
- if type(value) == bool:
- self.AddElement(parent, 'true' if value else 'false')
- elif type(value) == int:
- self.AddElement(parent, 'integer', {}, str(value))
- elif type(value) == str:
- self.AddElement(parent, 'string', {}, value)
- elif type(value) == list:
- array = self.AddElement(parent, 'array')
- for element in value:
- self._WriteValue(array, element)
- elif type(value) == dict:
- dic = self.AddElement(parent, 'dict')
- for k, v in sorted(value.iteritems()):
- self.AddElement(dic, 'key', {}, k)
- self._WriteValue(dic, v)
- else:
- raise ValueError('Unsupported type in example value: ' + type(value))
-
- # Overridden.
- def WritePolicy(self, policy):
- for dict in [self._dict, self._encoded_dict]:
- self.AddElement(dict, 'key', {}, policy['name'])
- self._WriteValue(dict, policy['example_value'])
-
- # Overridden.
- # |self._plist| is created in super.Init().
- def BeginTemplate(self):
- self._plist.attributes['version'] = '1.0'
- self._root_dict = self.AddElement(self._plist, 'dict')
- self.AddComment(self._root_dict, CHROME_POLICY_COMMENT)
- if self._GetChromiumVersionString() is not None:
- self.AddComment(self._root_dict, ' ' + self.config['build'] + \
- ' version: ' + self._GetChromiumVersionString() + ' ')
- self._dict = self._AddKeyValuePair(self._root_dict, 'ChromePolicy', 'dict')
-
- self._encoded_plist.attributes['version'] = '1.0'
- self._encoded_dict = self.AddElement(self._encoded_plist, 'dict')
-
- # Overridden.
- def EndTemplate(self):
- # Add the "EncodedChromePolicy" entry.
- encoded = base64.b64encode(self._encoded_doc.toxml())
- self.AddComment(self._root_dict, ENCODED_CHROME_POLICY_COMMENT)
- self._AddStringKeyValuePair(self._root_dict, 'EncodedChromePolicy', encoded)
-
- # Overridden.
- def Init(self):
- super(IOSPlistWriter, self).Init()
- # Create a secondary DOM for the EncodedChromePolicy Plist, which will be
- # serialized and encoded in EndTemplate.
- self._encoded_doc = self.CreatePlistDocument()
- self._encoded_plist = self._encoded_doc.documentElement
-
- # Overridden.
- def GetTemplateText(self):
- return self.ToPrettyXml(self._doc, encoding='UTF-8')
diff --git a/grit/format/policy_templates/writers/ios_plist_writer_unittest.py b/grit/format/policy_templates/writers/ios_plist_writer_unittest.py
deleted file mode 100644
index 0fdecb1..0000000
--- a/grit/format/policy_templates/writers/ios_plist_writer_unittest.py
+++ /dev/null
@@ -1,240 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.policy_templates.writers.ios_plist_writer'''
-
-
-import base64
-import functools
-import os
-import plistlib
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-
-try:
- import Cocoa
-except:
- Cocoa = None
-
-from grit.format.policy_templates.writers import writer_unittest_common
-
-
-class IOSPListWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for IOSPListWriter.'''
-
- def _ParseWithPython(self, decode, text):
- '''Parses a serialized Plist, using Python's plistlib.
-
- If |decode| is true then |text| is decoded as Base64 before being
- deserialized as a Plist.'''
- if decode:
- text = base64.b64decode(text)
- return plistlib.readPlistFromString(text)
-
- def _ParseWithCocoa(self, decode, text):
- '''Parses a serialized Plist, using Cocoa's python bindings.
-
- If |decode| is true then |text| is decoded as Base64 before being
- deserialized as a Plist.'''
- if decode:
- data = Cocoa.NSData.alloc().initWithBase64EncodedString_options_(text, 0)
- else:
- data = Cocoa.NSData.alloc().initWithBytes_length_(text, len(text))
- result = Cocoa.NSPropertyListSerialization. \
- propertyListFromData_mutabilityOption_format_errorDescription_(
- data, Cocoa.NSPropertyListImmutable, None, None)
- return result[0]
-
- def _VerifyGeneratedOutputWithParsers(self,
- templates,
- expected_output,
- parse,
- decode_and_parse):
-
-
- _defines = { '_chromium': '1',
- 'mac_bundle_id': 'com.example.Test',
- 'version': '39.0.0.0' }
-
- # Generate the grit output for |templates|.
- output = self.GetOutput(
- self.PrepareTest(templates),
- 'fr',
- _defines,
- 'ios_plist',
- 'en')
-
- # Parse it as a Plist.
- plist = parse(output)
- self.assertEquals(len(plist), 2)
- self.assertTrue('ChromePolicy' in plist)
- self.assertTrue('EncodedChromePolicy' in plist)
-
- # Get the 2 expected fields.
- chrome_policy = plist['ChromePolicy']
- encoded_chrome_policy = plist['EncodedChromePolicy']
-
- # Verify the ChromePolicy.
- self.assertEquals(chrome_policy, expected_output)
-
- # Decode the EncodedChromePolicy and verify it.
- decoded_chrome_policy = decode_and_parse(encoded_chrome_policy)
- self.assertEquals(decoded_chrome_policy, expected_output)
-
- def _VerifyGeneratedOutput(self, templates, expected):
- # plistlib is available on all Python platforms.
- parse = functools.partial(self._ParseWithPython, False)
- decode_and_parse = functools.partial(self._ParseWithPython, True)
- self._VerifyGeneratedOutputWithParsers(
- templates, expected, parse, decode_and_parse)
-
- # The Cocoa bindings are available on Mac OS X only.
- if Cocoa:
- parse = functools.partial(self._ParseWithCocoa, False)
- decode_and_parse = functools.partial(self._ParseWithCocoa, True)
- self._VerifyGeneratedOutputWithParsers(
- templates, expected, parse, decode_and_parse)
-
- def _MakeTemplate(self, name, type, example, extra=''):
- return '''
- {
- 'policy_definitions': [
- {
- 'name': '%s',
- 'type': '%s',
- 'desc': '',
- 'caption': '',
- 'supported_on': ['ios:35-'],
- 'example_value': %s,
- %s
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }
- ''' % (name, type, example, extra)
-
- def testEmpty(self):
- templates = '''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {},
- }
- '''
- expected = {}
- self._VerifyGeneratedOutput(templates, expected)
-
- def testEmptyVersion(self):
- templates = '''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {},
- }
- '''
- expected = {}
- self._VerifyGeneratedOutput(templates, expected)
-
- def testBoolean(self):
- templates = self._MakeTemplate('BooleanPolicy', 'main', 'True')
- expected = {
- 'BooleanPolicy': True,
- }
- self._VerifyGeneratedOutput(templates, expected)
-
- def testString(self):
- templates = self._MakeTemplate('StringPolicy', 'string', '"Foo"')
- expected = {
- 'StringPolicy': 'Foo',
- }
- self._VerifyGeneratedOutput(templates, expected)
-
- def testStringEnum(self):
- templates = self._MakeTemplate(
- 'StringEnumPolicy', 'string-enum', '"Foo"',
- '''
- 'items': [
- { 'name': 'Foo', 'value': 'Foo', 'caption': '' },
- { 'name': 'Bar', 'value': 'Bar', 'caption': '' },
- ],
- ''')
- expected = {
- 'StringEnumPolicy': 'Foo',
- }
- self._VerifyGeneratedOutput(templates, expected)
-
- def testInt(self):
- templates = self._MakeTemplate('IntPolicy', 'int', '42')
- expected = {
- 'IntPolicy': 42,
- }
- self._VerifyGeneratedOutput(templates, expected)
-
- def testIntEnum(self):
- templates = self._MakeTemplate(
- 'IntEnumPolicy', 'int-enum', '42',
- '''
- 'items': [
- { 'name': 'Foo', 'value': 100, 'caption': '' },
- { 'name': 'Bar', 'value': 42, 'caption': '' },
- ],
- ''')
- expected = {
- 'IntEnumPolicy': 42,
- }
- self._VerifyGeneratedOutput(templates, expected)
-
- def testStringList(self):
- templates = self._MakeTemplate('StringListPolicy', 'list', '["a", "b"]')
- expected = {
- 'StringListPolicy': [ "a", "b" ],
- }
- self._VerifyGeneratedOutput(templates, expected)
-
- def testStringEnumList(self):
- templates = self._MakeTemplate('StringEnumListPolicy',
- 'string-enum-list', '["a", "b"]',
- '''
- 'items': [
- { 'name': 'Foo', 'value': 'a', 'caption': '' },
- { 'name': 'Bar', 'value': 'b', 'caption': '' },
- ],
- ''')
-
- expected = {
- 'StringEnumListPolicy': [ "a", "b" ],
- }
- self._VerifyGeneratedOutput(templates, expected)
-
- def testListOfDictionary(self):
- templates = self._MakeTemplate(
- 'ManagedBookmarks', 'dict',
- '''
- [
- {
- "name": "Google Search",
- "url": "www.google.com",
- },
- {
- "name": "Youtube",
- "url": "www.youtube.com",
- }
- ]
- ''')
- expected = {
- 'ManagedBookmarks': [
- { "name": "Google Search", "url": "www.google.com" },
- { "name": "Youtube", "url": "www.youtube.com" },
- ],
- }
- self._VerifyGeneratedOutput(templates, expected)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/json_writer.py b/grit/format/policy_templates/writers/json_writer.py
deleted file mode 100644
index 4dfd282..0000000
--- a/grit/format/policy_templates/writers/json_writer.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import json
-
-from textwrap import TextWrapper
-from grit.format.policy_templates.writers import template_writer
-
-
-TEMPLATE_HEADER="""\
-// Policy template for Linux.
-// Uncomment the policies you wish to activate and change their values to
-// something useful for your case. The provided values are for reference only
-// and do not provide meaningful defaults!
-{"""
-
-
-HEADER_DELIMETER="""\
- //-------------------------------------------------------------------------"""
-
-
-def GetWriter(config):
- '''Factory method for creating JsonWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return JsonWriter(['linux'], config)
-
-
-class JsonWriter(template_writer.TemplateWriter):
- '''Class for generating policy files in JSON format (for Linux). The
- generated files will define all the supported policies with example values
- set for them. This class is used by PolicyTemplateGenerator to write .json
- files.
- '''
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list)
-
- def WriteComment(self, comment):
- self._out.append('// ' + comment)
-
- def WritePolicy(self, policy):
- if policy['type'] == 'external':
- # This type can only be set through cloud policy.
- return
- example_value_str = json.dumps(policy['example_value'], sort_keys=True)
-
- # Add comma to the end of the previous line.
- if not self._first_written:
- self._out[-2] += ','
-
- if not self.CanBeMandatory(policy) and self.CanBeRecommended(policy):
- line = ' // Note: this policy is supported only in recommended mode.'
- self._out.append(line)
- line = ' // The JSON file should be placed in %srecommended.' % \
- self.config['linux_policy_path']
- self._out.append(line)
-
- line = ' // %s' % policy['caption']
- self._out.append(line)
- self._out.append(HEADER_DELIMETER)
- description = self._text_wrapper.wrap(policy['desc'])
- self._out += description;
- line = ' //"%s": %s' % (policy['name'], example_value_str)
- self._out.append('')
- self._out.append(line)
- self._out.append('')
-
- self._first_written = False
-
- def BeginTemplate(self):
- if self._GetChromiumVersionString() is not None:
- self.WriteComment(self.config['build'] + ''' version: ''' + \
- self._GetChromiumVersionString())
- self._out.append(TEMPLATE_HEADER)
-
- def EndTemplate(self):
- self._out.append('}')
-
- def Init(self):
- self._out = []
- # The following boolean member is true until the first policy is written.
- self._first_written = True
- # Create the TextWrapper object once.
- self._text_wrapper = TextWrapper(
- initial_indent = ' // ',
- subsequent_indent = ' // ',
- break_long_words = False,
- width = 80)
-
- def GetTemplateText(self):
- return '\n'.join(self._out)
diff --git a/grit/format/policy_templates/writers/json_writer_unittest.py b/grit/format/policy_templates/writers/json_writer_unittest.py
deleted file mode 100644
index 8f3c745..0000000
--- a/grit/format/policy_templates/writers/json_writer_unittest.py
+++ /dev/null
@@ -1,429 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.policy_templates.writers.json_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import writer_unittest_common
-
-
-TEMPLATE_HEADER="""\
-// Policy template for Linux.
-// Uncomment the policies you wish to activate and change their values to
-// something useful for your case. The provided values are for reference only
-// and do not provide meaningful defaults!
-{
-"""
-
-TEMPLATE_HEADER_WITH_VERSION="""\
-// chromium version: 39.0.0.0
-// Policy template for Linux.
-// Uncomment the policies you wish to activate and change their values to
-// something useful for your case. The provided values are for reference only
-// and do not provide meaningful defaults!
-{
-"""
-
-
-HEADER_DELIMETER="""\
- //-------------------------------------------------------------------------
-"""
-
-
-class JsonWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for JsonWriter.'''
-
- def CompareOutputs(self, output, expected_output):
- '''Compares the output of the json_writer with its expected output.
-
- Args:
- output: The output of the json writer as returned by grit.
- expected_output: The expected output.
-
- Raises:
- AssertionError: if the two strings are not equivalent.
- '''
- self.assertEquals(
- output.strip(),
- expected_output.strip())
-
- def testEmpty(self):
- # Test the handling of an empty policy list.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": [],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium': '1'}, 'json', 'en')
- expected_output = TEMPLATE_HEADER + '}'
- self.CompareOutputs(output, expected_output)
-
- def testEmptyWithVersion(self):
- # Test the handling of an empty policy list.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": [],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(
- grd, 'fr', {'_chromium': '1', 'version':'39.0.0.0'}, 'json', 'en')
- expected_output = TEMPLATE_HEADER_WITH_VERSION + '}'
- self.CompareOutputs(output, expected_output)
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "MainPolicy",'
- ' "type": "main",'
- ' "caption": "Example Main Policy",'
- ' "desc": "Example Main Policy",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": True'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Example Main Policy\n' +
- HEADER_DELIMETER +
- ' // Example Main Policy\n\n'
- ' //"MainPolicy": true\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testRecommendedOnlyPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "MainPolicy",'
- ' "type": "main",'
- ' "caption": "Example Main Policy",'
- ' "desc": "Example Main Policy",'
- ' "features": {'
- ' "can_be_recommended": True,'
- ' "can_be_mandatory": False'
- ' },'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": True'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Note: this policy is supported only in recommended mode.\n' +
- ' // The JSON file should be placed in' +
- ' /etc/opt/chrome/policies/recommended.\n' +
- ' // Example Main Policy\n' +
- HEADER_DELIMETER +
- ' // Example Main Policy\n\n'
- ' //"MainPolicy": true\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "StringPolicy",'
- ' "type": "string",'
- ' "caption": "Example String Policy",'
- ' "desc": "Example String Policy",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": "hello, world!"'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Example String Policy\n' +
- HEADER_DELIMETER +
- ' // Example String Policy\n\n'
- ' //"StringPolicy": "hello, world!"\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testIntPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "IntPolicy",'
- ' "type": "int",'
- ' "caption": "Example Int Policy",'
- ' "desc": "Example Int Policy",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": 15'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Example Int Policy\n' +
- HEADER_DELIMETER +
- ' // Example Int Policy\n\n'
- ' //"IntPolicy": 15\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "EnumPolicy",'
- ' "type": "int-enum",'
- ' "caption": "Example Int Enum",'
- ' "desc": "Example Int Enum",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": 0, "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": 1, "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": 1'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Example Int Enum\n' +
- HEADER_DELIMETER +
- ' // Example Int Enum\n\n'
- ' //"EnumPolicy": 1\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "EnumPolicy",'
- ' "type": "string-enum",'
- ' "caption": "Example String Enum",'
- ' "desc": "Example String Enum",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": "one",'
- ' "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": "two",'
- ' "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": "one"'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Example String Enum\n' +
- HEADER_DELIMETER +
- ' // Example String Enum\n\n'
- ' //"EnumPolicy": "one"\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testListPolicy(self):
- # Tests a policy group with a single policy of type 'list'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "ListPolicy",'
- ' "type": "list",'
- ' "caption": "Example List",'
- ' "desc": "Example List",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ["foo", "bar"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Example List\n' +
- HEADER_DELIMETER +
- ' // Example List\n\n'
- ' //"ListPolicy": ["foo", "bar"]\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testStringEnumListPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum-list'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "ListPolicy",'
- ' "type": "string-enum-list",'
- ' "caption": "Example List",'
- ' "desc": "Example List",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": "one",'
- ' "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": "two",'
- ' "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ["one", "two"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Example List\n' +
- HEADER_DELIMETER +
- ' // Example List\n\n'
- ' //"ListPolicy": ["one", "two"]\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testDictionaryPolicy(self):
- # Tests a policy group with a single policy of type 'dict'.
- example = {
- 'bool': True,
- 'dict': {
- 'a': 1,
- 'b': 2,
- },
- 'int': 10,
- 'list': [1, 2, 3],
- 'string': 'abc',
- }
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "DictionaryPolicy",'
- ' "type": "dict",'
- ' "caption": "Example Dictionary Policy",'
- ' "desc": "Example Dictionary Policy",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ' + str(example) +
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Example Dictionary Policy\n' +
- HEADER_DELIMETER +
- ' // Example Dictionary Policy\n\n'
- ' //"DictionaryPolicy": {"bool": true, "dict": {"a": 1, '
- '"b": 2}, "int": 10, "list": [1, 2, 3], "string": "abc"}\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Linux, so it shouldn't
- # be included in the JSON file.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "NonLinuxPolicy",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.mac:8-"],'
- ' "example_value": ["a"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = TEMPLATE_HEADER + '}'
- self.CompareOutputs(output, expected_output)
-
- def testPolicyGroup(self):
- # Tests a policy group that has more than one policies.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "Group1",'
- ' "type": "group",'
- ' "caption": "",'
- ' "desc": "",'
- ' "policies": [{'
- ' "name": "Policy1",'
- ' "type": "list",'
- ' "caption": "Policy One",'
- ' "desc": "Policy One",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ["a", "b"]'
- ' },{'
- ' "name": "Policy2",'
- ' "type": "string",'
- ' "caption": "Policy Two",'
- ' "desc": "Policy Two",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": "c"'
- ' }],'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'json', 'en')
- expected_output = (
- TEMPLATE_HEADER +
- ' // Policy One\n' +
- HEADER_DELIMETER +
- ' // Policy One\n\n'
- ' //"Policy1": ["a", "b"],\n\n'
- ' // Policy Two\n' +
- HEADER_DELIMETER +
- ' // Policy Two\n\n'
- ' //"Policy2": "c"\n\n'
- '}')
- self.CompareOutputs(output, expected_output)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/mock_writer.py b/grit/format/policy_templates/writers/mock_writer.py
deleted file mode 100644
index 3db3a54..0000000
--- a/grit/format/policy_templates/writers/mock_writer.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-from template_writer import TemplateWriter
-
-
-class MockWriter(TemplateWriter):
- '''Helper class for unit tests in policy_template_generator_unittest.py
- '''
-
- def __init__(self):
- pass
-
- def WritePolicy(self, policy):
- pass
-
- def BeginTemplate(self):
- pass
-
- def GetTemplateText(self):
- pass
-
- def IsPolicySupported(self, policy):
- return True
-
- def Test(self):
- pass
diff --git a/grit/format/policy_templates/writers/plist_helper.py b/grit/format/policy_templates/writers/plist_helper.py
deleted file mode 100644
index 0c599ca..0000000
--- a/grit/format/policy_templates/writers/plist_helper.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-'''Common functions for plist_writer and plist_strings_writer.
-'''
-
-
-def GetPlistFriendlyName(name):
- '''Transforms a string so that it will be suitable for use as
- a pfm_name in the plist manifest file.
- '''
- return name.replace(' ', '_')
diff --git a/grit/format/policy_templates/writers/plist_strings_writer.py b/grit/format/policy_templates/writers/plist_strings_writer.py
deleted file mode 100644
index 4257bf8..0000000
--- a/grit/format/policy_templates/writers/plist_strings_writer.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-from grit.format.policy_templates.writers import plist_helper
-from grit.format.policy_templates.writers import template_writer
-
-
-def GetWriter(config):
- '''Factory method for creating PListStringsWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return PListStringsWriter(['mac'], config)
-
-
-class PListStringsWriter(template_writer.TemplateWriter):
- '''Outputs localized string table files for the Mac policy file.
- These files are named Localizable.strings and they are in the
- [lang].lproj subdirectories of the manifest bundle.
- '''
-
- def WriteComment(self, comment):
- self._out.append('/* ' + comment + ' */' )
-
- def _AddToStringTable(self, item_name, caption, desc):
- '''Add a title and a description of an item to the string table.
-
- Args:
- item_name: The name of the item that will get the title and the
- description.
- title: The text of the title to add.
- desc: The text of the description to add.
- '''
- caption = caption.replace('"', '\\"')
- caption = caption.replace('\n', '\\n')
- desc = desc.replace('"', '\\"')
- desc = desc.replace('\n', '\\n')
- self._out.append('%s.pfm_title = \"%s\";' % (item_name, caption))
- self._out.append('%s.pfm_description = \"%s\";' % (item_name, desc))
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list)
-
- def WritePolicy(self, policy):
- '''Add strings to the stringtable corresponding a given policy.
-
- Args:
- policy: The policy for which the strings will be added to the
- string table.
- '''
- desc = policy['desc']
- if policy['type'] == 'external':
- # This type can only be set through cloud policy.
- return
- elif policy['type'] in ('int-enum','string-enum', 'string-enum-list'):
- # Append the captions of enum items to the description string.
- item_descs = []
- for item in policy['items']:
- item_descs.append(str(item['value']) + ' - ' + item['caption'])
- desc = '\n'.join(item_descs) + '\n' + desc
-
- self._AddToStringTable(policy['name'], policy['label'], desc)
-
- def BeginTemplate(self):
- app_name = plist_helper.GetPlistFriendlyName(self.config['app_name'])
- if self._GetChromiumVersionString() is not None:
- self.WriteComment(self.config['build'] + ''' version: ''' + \
- self._GetChromiumVersionString())
- self._AddToStringTable(
- app_name,
- self.config['app_name'],
- self.messages['mac_chrome_preferences']['text'])
-
- def Init(self):
- # A buffer for the lines of the string table being generated.
- self._out = []
-
- def GetTemplateText(self):
- return '\n'.join(self._out)
diff --git a/grit/format/policy_templates/writers/plist_strings_writer_unittest.py b/grit/format/policy_templates/writers/plist_strings_writer_unittest.py
deleted file mode 100644
index efad6f2..0000000
--- a/grit/format/policy_templates/writers/plist_strings_writer_unittest.py
+++ /dev/null
@@ -1,411 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.policy_templates.writers.plist_strings_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import writer_unittest_common
-
-
-class PListStringsWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for PListStringsWriter.'''
-
- def testEmpty(self):
- # Test PListStringsWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferen"ces',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium': '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Chromium.pfm_title = "Chromium";\n'
- 'Chromium.pfm_description = "Chromium preferen\\"ces";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testEmptyVersion(self):
- # Test PListStringsWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferen"ces',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium': '1',
- 'mac_bundle_id': 'com.example.Test',
- 'version': '39.0.0.0'},
- 'plist_strings',
- 'en')
- expected_output = (
- '/* chromium version: 39.0.0.0 */\n'
- 'Chromium.pfm_title = "Chromium";\n'
- 'Chromium.pfm_description = "Chromium preferen\\"ces";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainGroup',
- 'type': 'group',
- 'caption': 'Caption of main.',
- 'desc': 'Description of main.',
- 'policies': [{
- 'name': 'MainPolicy',
- 'type': 'main',
- 'supported_on': ['chrome.mac:8-'],
- 'caption': 'Caption of main policy.',
- 'desc': 'Description of main policy.',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': 'Preferences of $1',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Google_Chrome.pfm_title = "Google Chrome";\n'
- 'Google_Chrome.pfm_description = "Preferences of Google Chrome";\n'
- 'MainPolicy.pfm_title = "Caption of main policy.";\n'
- 'MainPolicy.pfm_description = "Description of main policy.";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'. Also test
- # inheriting group description to policy description.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'StringGroup',
- 'type': 'group',
- 'caption': 'Caption of group.',
- 'desc': """Description of group.
-With a newline.""",
- 'policies': [{
- 'name': 'StringPolicy',
- 'type': 'string',
- 'caption': 'Caption of policy.',
- 'desc': """Description of policy.
-With a newline.""",
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': 'Preferences of $1',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Chromium.pfm_title = "Chromium";\n'
- 'Chromium.pfm_description = "Preferences of Chromium";\n'
- 'StringPolicy.pfm_title = "Caption of policy.";\n'
- 'StringPolicy.pfm_description = '
- '"Description of policy.\\nWith a newline.";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringListPolicy(self):
- # Tests a policy group with a single policy of type 'list'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'ListGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'ListPolicy',
- 'type': 'list',
- 'caption': 'Caption of policy.',
- 'desc': """Description of policy.
-With a newline.""",
- 'schema': {
- 'type': 'array',
- 'items': { 'type': 'string' },
- },
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': 'Preferences of $1',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Chromium.pfm_title = "Chromium";\n'
- 'Chromium.pfm_description = "Preferences of Chromium";\n'
- 'ListPolicy.pfm_title = "Caption of policy.";\n'
- 'ListPolicy.pfm_description = '
- '"Description of policy.\\nWith a newline.";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringEnumListPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum-list'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'string-enum-list',
- 'caption': 'Caption of policy.',
- 'desc': """Description of policy.
-With a newline.""",
- 'schema': {
- 'type': 'array',
- 'items': { 'type': 'string' },
- },
- 'items': [
- {
- 'name': 'ProxyServerDisabled',
- 'value': 'one',
- 'caption': 'Option1'
- },
- {
- 'name': 'ProxyServerAutoDetect',
- 'value': 'two',
- 'caption': 'Option2'
- },
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': 'Preferences of $1',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Chromium.pfm_title = "Chromium";\n'
- 'Chromium.pfm_description = "Preferences of Chromium";\n'
- 'EnumPolicy.pfm_title = "Caption of policy.";\n'
- 'EnumPolicy.pfm_description = '
- '"one - Option1\\ntwo - Option2\\n'
- 'Description of policy.\\nWith a newline.";')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'int-enum',
- 'desc': 'Description of policy.',
- 'caption': 'Caption of policy.',
- 'items': [
- {
- 'name': 'ProxyServerDisabled',
- 'value': 0,
- 'caption': 'Option1'
- },
- {
- 'name': 'ProxyServerAutoDetect',
- 'value': 1,
- 'caption': 'Option2'
- },
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferences',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Google_Chrome.pfm_title = "Google Chrome";\n'
- 'Google_Chrome.pfm_description = "Google Chrome preferences";\n'
- 'EnumPolicy.pfm_title = "Caption of policy.";\n'
- 'EnumPolicy.pfm_description = '
- '"0 - Option1\\n1 - Option2\\nDescription of policy.";\n')
-
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'string-enum',
- 'desc': 'Description of policy.',
- 'caption': 'Caption of policy.',
- 'items': [
- {
- 'name': 'ProxyServerDisabled',
- 'value': 'one',
- 'caption': 'Option1'
- },
- {
- 'name': 'ProxyServerAutoDetect',
- 'value': 'two',
- 'caption': 'Option2'
- },
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferences',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Google_Chrome.pfm_title = "Google Chrome";\n'
- 'Google_Chrome.pfm_description = "Google Chrome preferences";\n'
- 'EnumPolicy.pfm_title = "Caption of policy.";\n'
- 'EnumPolicy.pfm_description = '
- '"one - Option1\\ntwo - Option2\\nDescription of policy.";\n')
-
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Mac, so its strings shouldn't
- # be included in the plist string table.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'NonMacGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'NonMacPolicy',
- 'type': 'string',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome_os:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {
- 'mac_chrome_preferences': {
- 'text': '$1 preferences',
- 'desc': 'blah'
- }
- }
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist_strings',
- 'en')
- expected_output = (
- 'Google_Chrome.pfm_title = "Google Chrome";\n'
- 'Google_Chrome.pfm_description = "Google Chrome preferences";')
- self.assertEquals(output.strip(), expected_output.strip())
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/plist_writer.py b/grit/format/policy_templates/writers/plist_writer.py
deleted file mode 100644
index cae6844..0000000
--- a/grit/format/policy_templates/writers/plist_writer.py
+++ /dev/null
@@ -1,149 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-from xml.dom import minidom
-from grit.format.policy_templates.writers import plist_helper
-from grit.format.policy_templates.writers import xml_formatted_writer
-
-
-# This writer outputs a Preferences Manifest file as documented at
-# https://developer.apple.com/library/mac/documentation/MacOSXServer/Conceptual/Preference_Manifest_Files
-
-
-def GetWriter(config):
- '''Factory method for creating PListWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return PListWriter(['mac'], config)
-
-
-class PListWriter(xml_formatted_writer.XMLFormattedWriter):
- '''Class for generating policy templates in Mac plist format.
- It is used by PolicyTemplateGenerator to write plist files.
- '''
-
- STRING_TABLE = 'Localizable.strings'
- TYPE_TO_INPUT = {
- 'string': 'string',
- 'int': 'integer',
- 'int-enum': 'integer',
- 'string-enum': 'string',
- 'string-enum-list': 'array',
- 'main': 'boolean',
- 'list': 'array',
- 'dict': 'dictionary',
- }
-
- def _AddKeyValuePair(self, parent, key_string, value_tag):
- '''Adds a plist key-value pair to a parent XML element.
-
- A key-value pair in plist consists of two XML elements next two each other:
- <key>key_string</key>
- <value_tag>...</value_tag>
-
- Args:
- key_string: The content of the key tag.
- value_tag: The name of the value element.
-
- Returns:
- The XML element of the value tag.
- '''
- self.AddElement(parent, 'key', {}, key_string)
- return self.AddElement(parent, value_tag)
-
- def _AddStringKeyValuePair(self, parent, key_string, value_string):
- '''Adds a plist key-value pair to a parent XML element, where the
- value element contains a string. The name of the value element will be
- <string>.
-
- Args:
- key_string: The content of the key tag.
- value_string: The content of the value tag.
- '''
- self.AddElement(parent, 'key', {}, key_string)
- self.AddElement(parent, 'string', {}, value_string)
-
- def _AddTargets(self, parent, policy):
- '''Adds the following XML snippet to an XML element:
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
-
- Args:
- parent: The parent XML element where the snippet will be added.
- '''
- array = self._AddKeyValuePair(parent, 'pfm_targets', 'array')
- if self.CanBeRecommended(policy):
- self.AddElement(array, 'string', {}, 'user')
- if self.CanBeMandatory(policy):
- self.AddElement(array, 'string', {}, 'user-managed')
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list)
-
- def WritePolicy(self, policy):
- policy_name = policy['name']
- policy_type = policy['type']
- if policy_type == 'external':
- # This type can only be set through cloud policy.
- return
-
- dict = self.AddElement(self._array, 'dict')
- self._AddStringKeyValuePair(dict, 'pfm_name', policy_name)
- # Set empty strings for title and description. They will be taken by the
- # OSX Workgroup Manager from the string table in a Localizable.strings file.
- # Those files are generated by plist_strings_writer.
- self._AddStringKeyValuePair(dict, 'pfm_description', '')
- self._AddStringKeyValuePair(dict, 'pfm_title', '')
- self._AddTargets(dict, policy)
- self._AddStringKeyValuePair(dict, 'pfm_type',
- self.TYPE_TO_INPUT[policy_type])
- if policy_type in ('int-enum', 'string-enum'):
- range_list = self._AddKeyValuePair(dict, 'pfm_range_list', 'array')
- for item in policy['items']:
- if policy_type == 'int-enum':
- element_type = 'integer'
- else:
- element_type = 'string'
- self.AddElement(range_list, element_type, {}, str(item['value']))
- elif policy_type in ('list', 'string-enum-list'):
- subkeys = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array')
- subkeys_dict = self.AddElement(subkeys, 'dict')
- subkeys_type = self._AddKeyValuePair(subkeys_dict, 'pfm_type', 'string')
- self.AddText(subkeys_type, 'string')
-
- def BeginTemplate(self):
- self._plist.attributes['version'] = '1'
- dict = self.AddElement(self._plist, 'dict')
- if self._GetChromiumVersionString() is not None:
- self.AddComment(self._plist, self.config['build'] + ' version: ' + \
- self._GetChromiumVersionString())
- app_name = plist_helper.GetPlistFriendlyName(self.config['app_name'])
- self._AddStringKeyValuePair(dict, 'pfm_name', app_name)
- self._AddStringKeyValuePair(dict, 'pfm_description', '')
- self._AddStringKeyValuePair(dict, 'pfm_title', '')
- self._AddStringKeyValuePair(dict, 'pfm_version', '1')
- self._AddStringKeyValuePair(dict, 'pfm_domain',
- self.config['mac_bundle_id'])
-
- self._array = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array')
-
- def CreatePlistDocument(self):
- dom_impl = minidom.getDOMImplementation('')
- doctype = dom_impl.createDocumentType(
- 'plist',
- '-//Apple//DTD PLIST 1.0//EN',
- 'http://www.apple.com/DTDs/PropertyList-1.0.dtd')
- return dom_impl.createDocument(None, 'plist', doctype)
-
- def Init(self):
- self._doc = self.CreatePlistDocument()
- self._plist = self._doc.documentElement
-
- def GetTemplateText(self):
- return self.ToPrettyXml(self._doc)
diff --git a/grit/format/policy_templates/writers/plist_writer_unittest.py b/grit/format/policy_templates/writers/plist_writer_unittest.py
deleted file mode 100644
index 6186c15..0000000
--- a/grit/format/policy_templates/writers/plist_writer_unittest.py
+++ /dev/null
@@ -1,691 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.policy_templates.writers.plist_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import writer_unittest_common
-
-
-class PListWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for PListWriter.'''
-
- def _GetExpectedOutputs(self, product_name, bundle_id, policies):
- '''Substitutes the variable parts into a plist template. The result
- of this function can be used as an expected result to test the output
- of PListWriter.
-
- Args:
- product_name: The name of the product, normally Chromium or Google Chrome.
- bundle_id: The mac bundle id of the product.
- policies: The list of policies.
-
- Returns:
- The text of a plist template with the variable parts substituted.
- '''
- return '''
-<?xml version="1.0" ?>
-<!DOCTYPE plist PUBLIC '-//Apple//DTD PLIST 1.0//EN' 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
-<plist version="1">
- <dict>
- <key>pfm_name</key>
- <string>%s</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_version</key>
- <string>1</string>
- <key>pfm_domain</key>
- <string>%s</string>
- <key>pfm_subkeys</key>
- %s
- </dict>
-</plist>''' % (product_name, bundle_id, policies)
-
- def _GetExpectedOutputsWithVersion(self, product_name, bundle_id, policies,
- version):
- '''Substitutes the variable parts into a plist template. The result
- of this function can be used as an expected result to test the output
- of PListWriter.
-
- Args:
- product_name: The name of the product, normally Chromium or Google Chrome.
- bundle_id: The mac bundle id of the product.
- policies: The list of policies.
-
- Returns:
- The text of a plist template with the variable parts substituted.
- '''
- return '''
-<?xml version="1.0" ?>
-<!DOCTYPE plist PUBLIC '-//Apple//DTD PLIST 1.0//EN' 'http://www.apple.com/DTDs/PropertyList-1.0.dtd'>
-<plist version="1">
- <dict>
- <key>pfm_name</key>
- <string>%s</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_version</key>
- <string>1</string>
- <key>pfm_domain</key>
- <string>%s</string>
- <key>pfm_subkeys</key>
- %s
- </dict>
- <!--%s-->
-</plist>''' % (product_name, bundle_id, policies, version)
-
- def testEmpty(self):
- # Test PListWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {},
- }''')
-
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium': '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '<array/>')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testEmptyVersion(self):
- # Test PListWriter in case of empty polices.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [],
- 'placeholders': [],
- 'messages': {},
- }''')
-
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium': '1',
- 'mac_bundle_id': 'com.example.Test',
- 'version': '39.0.0.0'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputsWithVersion(
- 'Chromium',
- 'com.example.Test',
- '<array/>',
- 'chromium version: 39.0.0.0')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainGroup',
- 'type': 'group',
- 'policies': [{
- 'name': 'MainPolicy',
- 'type': 'main',
- 'desc': '',
- 'caption': '',
- 'supported_on': ['chrome.mac:8-'],
- }],
- 'desc': '',
- 'caption': '',
- },
- ],
- 'placeholders': [],
- 'messages': {}
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>MainPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>boolean</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testRecommendedPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainGroup',
- 'type': 'group',
- 'policies': [{
- 'name': 'MainPolicy',
- 'type': 'main',
- 'desc': '',
- 'caption': '',
- 'features': {
- 'can_be_recommended' : True
- },
- 'supported_on': ['chrome.mac:8-'],
- }],
- 'desc': '',
- 'caption': '',
- },
- ],
- 'placeholders': [],
- 'messages': {}
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>MainPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user</string>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>boolean</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testRecommendedOnlyPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'MainGroup',
- 'type': 'group',
- 'policies': [{
- 'name': 'MainPolicy',
- 'type': 'main',
- 'desc': '',
- 'caption': '',
- 'features': {
- 'can_be_recommended' : True,
- 'can_be_mandatory' : False
- },
- 'supported_on': ['chrome.mac:8-'],
- }],
- 'desc': '',
- 'caption': '',
- },
- ],
- 'placeholders': [],
- 'messages': {}
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>MainPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user</string>
- </array>
- <key>pfm_type</key>
- <string>boolean</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'StringGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'StringPolicy',
- 'type': 'string',
- 'supported_on': ['chrome.mac:8-'],
- 'desc': '',
- 'caption': '',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>StringPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>string</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testListPolicy(self):
- # Tests a policy group with a single policy of type 'list'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'ListGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'ListPolicy',
- 'type': 'list',
- 'schema': {
- 'type': 'array',
- 'items': { 'type': 'string' },
- },
- 'supported_on': ['chrome.mac:8-'],
- 'desc': '',
- 'caption': '',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>ListPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>array</string>
- <key>pfm_subkeys</key>
- <array>
- <dict>
- <key>pfm_type</key>
- <string>string</string>
- </dict>
- </array>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringEnumListPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum-list'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'ListGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'ListPolicy',
- 'type': 'string-enum-list',
- 'schema': {
- 'type': 'array',
- 'items': { 'type': 'string' },
- },
- 'items': [
- {'name': 'ProxyServerDisabled', 'value': 'one', 'caption': ''},
- {'name': 'ProxyServerAutoDetect', 'value': 'two', 'caption': ''},
- ],
- 'supported_on': ['chrome.mac:8-'],
- 'supported_on': ['chrome.mac:8-'],
- 'desc': '',
- 'caption': '',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>ListPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>array</string>
- <key>pfm_subkeys</key>
- <array>
- <dict>
- <key>pfm_type</key>
- <string>string</string>
- </dict>
- </array>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testIntPolicy(self):
- # Tests a policy group with a single policy of type 'int'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'IntGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'IntPolicy',
- 'type': 'int',
- 'caption': '',
- 'desc': '',
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>IntPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>integer</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'int-enum',
- 'desc': '',
- 'caption': '',
- 'items': [
- {'name': 'ProxyServerDisabled', 'value': 0, 'caption': ''},
- {'name': 'ProxyServerAutoDetect', 'value': 1, 'caption': ''},
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Google_Chrome', 'com.example.Test2', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>EnumPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>integer</string>
- <key>pfm_range_list</key>
- <array>
- <integer>0</integer>
- <integer>1</integer>
- </array>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'EnumGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'EnumPolicy',
- 'type': 'string-enum',
- 'desc': '',
- 'caption': '',
- 'items': [
- {'name': 'ProxyServerDisabled', 'value': 'one', 'caption': ''},
- {'name': 'ProxyServerAutoDetect', 'value': 'two', 'caption': ''},
- ],
- 'supported_on': ['chrome.mac:8-'],
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Google_Chrome', 'com.example.Test2', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>EnumPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>string</string>
- <key>pfm_range_list</key>
- <array>
- <string>one</string>
- <string>two</string>
- </array>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testDictionaryPolicy(self):
- # Tests a policy group with a single policy of type 'dict'.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'DictionaryGroup',
- 'type': 'group',
- 'desc': '',
- 'caption': '',
- 'policies': [{
- 'name': 'DictionaryPolicy',
- 'type': 'dict',
- 'supported_on': ['chrome.mac:8-'],
- 'desc': '',
- 'caption': '',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Chromium', 'com.example.Test', '''<array>
- <dict>
- <key>pfm_name</key>
- <string>DictionaryPolicy</string>
- <key>pfm_description</key>
- <string/>
- <key>pfm_title</key>
- <string/>
- <key>pfm_targets</key>
- <array>
- <string>user-managed</string>
- </array>
- <key>pfm_type</key>
- <string>dictionary</string>
- </dict>
- </array>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Mac, so it shouldn't
- # be included in the plist file.
- grd = self.PrepareTest('''
- {
- 'policy_definitions': [
- {
- 'name': 'NonMacGroup',
- 'type': 'group',
- 'caption': '',
- 'desc': '',
- 'policies': [{
- 'name': 'NonMacPolicy',
- 'type': 'string',
- 'supported_on': ['chrome.linux:8-', 'chrome.win:7-'],
- 'caption': '',
- 'desc': '',
- }],
- },
- ],
- 'placeholders': [],
- 'messages': {},
- }''')
- output = self.GetOutput(
- grd,
- 'fr',
- {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'},
- 'plist',
- 'en')
- expected_output = self._GetExpectedOutputs(
- 'Google_Chrome', 'com.example.Test2', '''<array/>''')
- self.assertEquals(output.strip(), expected_output.strip())
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/reg_writer.py b/grit/format/policy_templates/writers/reg_writer.py
deleted file mode 100644
index 70c87a3..0000000
--- a/grit/format/policy_templates/writers/reg_writer.py
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-import json
-
-from grit.format.policy_templates.writers import template_writer
-
-
-def GetWriter(config):
- '''Factory method for creating RegWriter objects.
- See the constructor of TemplateWriter for description of
- arguments.
- '''
- return RegWriter(['win'], config)
-
-
-class RegWriter(template_writer.TemplateWriter):
- '''Class for generating policy example files in .reg format (for Windows).
- The generated files will define all the supported policies with example
- values set for them. This class is used by PolicyTemplateGenerator to
- write .reg files.
- '''
-
- NEWLINE = '\r\n'
-
- def _EscapeRegString(self, string):
- return string.replace('\\', '\\\\').replace('\"', '\\\"')
-
- def _StartBlock(self, key, suffix, list):
- key = 'HKEY_LOCAL_MACHINE\\' + key
- if suffix:
- key = key + '\\' + suffix
- if key != self._last_key.get(id(list), None):
- list.append('')
- list.append('[%s]' % key)
- self._last_key[id(list)] = key
-
- def PreprocessPolicies(self, policy_list):
- return self.FlattenGroupsAndSortPolicies(policy_list,
- self.GetPolicySortingKey)
-
- def GetPolicySortingKey(self, policy):
- '''Extracts a sorting key from a policy. These keys can be used for
- list.sort() methods to sort policies.
- See TemplateWriter.SortPoliciesGroupsFirst for usage.
- '''
- is_list = policy['type'] in ('list', 'string-enum-list')
- # Lists come after regular policies.
- return (is_list, policy['name'])
-
- def _WritePolicy(self, policy, key, list):
- example_value = policy['example_value']
-
- if policy['type'] == 'external':
- # This type can only be set through cloud policy.
- return
- elif policy['type'] in ('list', 'string-enum-list'):
- self._StartBlock(key, policy['name'], list)
- i = 1
- for item in example_value:
- escaped_str = self._EscapeRegString(item)
- list.append('"%d"="%s"' % (i, escaped_str))
- i = i + 1
- else:
- self._StartBlock(key, None, list)
- if policy['type'] in ('string', 'string-enum', 'dict'):
- example_value_str = json.dumps(example_value, sort_keys=True)
- if policy['type'] == 'dict':
- example_value_str = '"%s"' % example_value_str
- elif policy['type'] == 'main':
- if example_value == True:
- example_value_str = 'dword:00000001'
- else:
- example_value_str = 'dword:00000000'
- elif policy['type'] in ('int', 'int-enum'):
- example_value_str = 'dword:%08x' % example_value
- else:
- raise Exception('unknown policy type %s:' % policy['type'])
-
- list.append('"%s"=%s' % (policy['name'], example_value_str))
-
- def WriteComment(self, comment):
- self._prefix.append('; ' + comment)
-
- def WritePolicy(self, policy):
- if self.CanBeMandatory(policy):
- self._WritePolicy(policy,
- self.config['win_reg_mandatory_key_name'],
- self._mandatory)
-
- def WriteRecommendedPolicy(self, policy):
- self._WritePolicy(policy,
- self.config['win_reg_recommended_key_name'],
- self._recommended)
-
- def BeginTemplate(self):
- pass
-
- def EndTemplate(self):
- pass
-
- def Init(self):
- self._mandatory = []
- self._recommended = []
- self._last_key = {}
- self._prefix = []
-
- def GetTemplateText(self):
- self._prefix.append('Windows Registry Editor Version 5.00')
- if self._GetChromiumVersionString() is not None:
- self.WriteComment(self.config['build'] + ' version: ' + \
- self._GetChromiumVersionString())
- all = self._prefix + self._mandatory + self._recommended
- return self.NEWLINE.join(all)
diff --git a/grit/format/policy_templates/writers/reg_writer_unittest.py b/grit/format/policy_templates/writers/reg_writer_unittest.py
deleted file mode 100644
index 2851a8b..0000000
--- a/grit/format/policy_templates/writers/reg_writer_unittest.py
+++ /dev/null
@@ -1,392 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-'''Unit tests for grit.format.policy_templates.writers.reg_writer'''
-
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import writer_unittest_common
-
-
-class RegWriterUnittest(writer_unittest_common.WriterUnittestCommon):
- '''Unit tests for RegWriter.'''
-
- NEWLINE = '\r\n'
-
- def CompareOutputs(self, output, expected_output):
- '''Compares the output of the reg_writer with its expected output.
-
- Args:
- output: The output of the reg writer as returned by grit.
- expected_output: The expected output.
-
- Raises:
- AssertionError: if the two strings are not equivalent.
- '''
- self.assertEquals(
- output.strip(),
- expected_output.strip())
-
- def testEmpty(self):
- # Test the handling of an empty policy list.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": [],'
- ' "placeholders": [],'
- ' "messages": {}'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium': '1', }, 'reg', 'en')
- expected_output = 'Windows Registry Editor Version 5.00'
- self.CompareOutputs(output, expected_output)
-
- def testEmptyVersion(self):
- # Test the handling of an empty policy list.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": [],'
- ' "placeholders": [],'
- ' "messages": {}'
- '}')
- output = self.GetOutput(
- grd, 'fr', {'_chromium': '1', 'version': '39.0.0.0' }, 'reg', 'en')
- expected_output = ('Windows Registry Editor Version 5.00\r\n'
- '; chromium version: 39.0.0.0\r\n')
- self.CompareOutputs(output, expected_output)
-
- def testMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "MainPolicy",'
- ' "type": "main",'
- ' "features": { "can_be_recommended": True },'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": True'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
- '"MainPolicy"=dword:00000001',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome\\Recommended]',
- '"MainPolicy"=dword:00000001'])
- self.CompareOutputs(output, expected_output)
-
- def testRecommendedMainPolicy(self):
- # Tests a policy group with a single policy of type 'main'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "MainPolicy",'
- ' "type": "main",'
- ' "features": {'
- ' "can_be_recommended": True,'
- ' "can_be_mandatory": False '
- ' },'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": True'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome\\Recommended]',
- '"MainPolicy"=dword:00000001'])
- self.CompareOutputs(output, expected_output)
-
- def testStringPolicy(self):
- # Tests a policy group with a single policy of type 'string'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "StringPolicy",'
- ' "type": "string",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": "hello, world! \\\" \\\\"'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
- '"StringPolicy"="hello, world! \\\" \\\\"'])
- self.CompareOutputs(output, expected_output)
-
- def testIntPolicy(self):
- # Tests a policy group with a single policy of type 'int'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "IntPolicy",'
- ' "type": "int",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": 26'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
- '"IntPolicy"=dword:0000001a'])
- self.CompareOutputs(output, expected_output)
-
- def testIntEnumPolicy(self):
- # Tests a policy group with a single policy of type 'int-enum'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "EnumPolicy",'
- ' "type": "int-enum",'
- ' "caption": "",'
- ' "desc": "",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": 0, "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": 1, "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": 1'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
- '"EnumPolicy"=dword:00000001'])
- self.CompareOutputs(output, expected_output)
-
- def testStringEnumPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "EnumPolicy",'
- ' "type": "string-enum",'
- ' "caption": "",'
- ' "desc": "",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": "one",'
- ' "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": "two",'
- ' "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": "two"'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_google_chrome': '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Google\\Chrome]',
- '"EnumPolicy"="two"'])
- self.CompareOutputs(output, expected_output)
-
- def testListPolicy(self):
- # Tests a policy group with a single policy of type 'list'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "ListPolicy",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ["foo", "bar"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium\\ListPolicy]',
- '"1"="foo"',
- '"2"="bar"'])
-
- def testStringEnumListPolicy(self):
- # Tests a policy group with a single policy of type 'string-enum-list'.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "ListPolicy",'
- ' "type": "string-enum-list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "items": ['
- ' {"name": "ProxyServerDisabled", "value": "foo",'
- ' "caption": ""},'
- ' {"name": "ProxyServerAutoDetect", "value": "bar",'
- ' "caption": ""},'
- ' ],'
- ' "supported_on": ["chrome.linux:8-"],'
- ' "example_value": ["foo", "bar"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium\\ListPolicy]',
- '"1"="foo"',
- '"2"="bar"'])
-
- def testDictionaryPolicy(self):
- # Tests a policy group with a single policy of type 'dict'.
- example = {
- 'bool': True,
- 'dict': {
- 'a': 1,
- 'b': 2,
- },
- 'int': 10,
- 'list': [1, 2, 3],
- 'string': 'abc',
- }
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "DictionaryPolicy",'
- ' "type": "dict",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": ' + str(example) +
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
- '"DictionaryPolicy"="{"bool": true, "dict": {"a": 1, '
- '"b": 2}, "int": 10, "list": [1, 2, 3], "string": "abc"}"'])
- self.CompareOutputs(output, expected_output)
-
- def testNonSupportedPolicy(self):
- # Tests a policy that is not supported on Windows, so it shouldn't
- # be included in the .REG file.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "NonWindowsPolicy",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.mac:8-"],'
- ' "example_value": ["a"]'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00'])
- self.CompareOutputs(output, expected_output)
-
- def testPolicyGroup(self):
- # Tests a policy group that has more than one policies.
- grd = self.PrepareTest(
- '{'
- ' "policy_definitions": ['
- ' {'
- ' "name": "Group1",'
- ' "type": "group",'
- ' "caption": "",'
- ' "desc": "",'
- ' "policies": [{'
- ' "name": "Policy1",'
- ' "type": "list",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": ["a", "b"]'
- ' },{'
- ' "name": "Policy2",'
- ' "type": "string",'
- ' "caption": "",'
- ' "desc": "",'
- ' "supported_on": ["chrome.win:8-"],'
- ' "example_value": "c"'
- ' }],'
- ' },'
- ' ],'
- ' "placeholders": [],'
- ' "messages": {},'
- '}')
- output = self.GetOutput(grd, 'fr', {'_chromium' : '1'}, 'reg', 'en')
- expected_output = self.NEWLINE.join([
- 'Windows Registry Editor Version 5.00',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium]',
- '"Policy2"="c"',
- '',
- '[HKEY_LOCAL_MACHINE\\Software\\Policies\\Chromium\\Policy1]',
- '"1"="a"',
- '"2"="b"'])
- self.CompareOutputs(output, expected_output)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/template_writer.py b/grit/format/policy_templates/writers/template_writer.py
deleted file mode 100644
index d489d64..0000000
--- a/grit/format/policy_templates/writers/template_writer.py
+++ /dev/null
@@ -1,318 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-class TemplateWriter(object):
- '''Abstract base class for writing policy templates in various formats.
- The methods of this class will be called by PolicyTemplateGenerator.
- '''
-
- def __init__(self, platforms, config):
- '''Initializes a TemplateWriter object.
-
- Args:
- platforms: List of platforms for which this writer can write policies.
- config: A dictionary of information required to generate the template.
- It contains some key-value pairs, including the following examples:
- 'build': 'chrome' or 'chromium'
- 'branding': 'Google Chrome' or 'Chromium'
- 'mac_bundle_id': The Mac bundle id of Chrome. (Only set when building
- for Mac.)
- messages: List of all the message strings from the grd file. Most of them
- are also present in the policy data structures that are passed to
- methods. That is the preferred way of accessing them, this should only
- be used in exceptional cases. An example for its use is the
- IDS_POLICY_WIN_SUPPORTED_WINXPSP2 message in ADM files, because that
- cannot be associated with any policy or group.
- '''
- self.platforms = platforms
- self.config = config
-
- def IsDeprecatedPolicySupported(self, policy):
- '''Checks if the given deprecated policy is supported by the writer.
-
- Args:
- policy: The dictionary of the policy.
-
- Returns:
- True if the writer chooses to include the deprecated 'policy' in its
- output.
- '''
- return False
-
- def IsFuturePolicySupported(self, policy):
- '''Checks if the given future policy is supported by the writer.
-
- Args:
- policy: The dictionary of the policy.
-
- Returns:
- True if the writer chooses to include the deprecated 'policy' in its
- output.
- '''
- return False
-
- def IsPolicySupported(self, policy):
- '''Checks if the given policy is supported by the writer.
- In other words, the set of platforms supported by the writer
- has a common subset with the set of platforms that support
- the policy.
-
- Args:
- policy: The dictionary of the policy.
-
- Returns:
- True if the writer chooses to include 'policy' in its output.
- '''
- if ('deprecated' in policy and policy['deprecated'] is True and
- not self.IsDeprecatedPolicySupported(policy)):
- return False
-
- if ('future' in policy and policy['future'] is True and
- not self.IsFuturePolicySupported(policy)):
- return False
-
- if '*' in self.platforms:
- # Currently chrome_os is only catched here.
- return True
- for supported_on in policy['supported_on']:
- for supported_on_platform in supported_on['platforms']:
- if supported_on_platform in self.platforms:
- return True
- return False
-
- def CanBeRecommended(self, policy):
- '''Checks if the given policy can be recommended.'''
- return policy.get('features', {}).get('can_be_recommended', False)
-
- def CanBeMandatory(self, policy):
- '''Checks if the given policy can be mandatory.'''
- return policy.get('features', {}).get('can_be_mandatory', True)
-
- def IsPolicySupportedOnPlatform(self, policy, platform):
- '''Checks if |policy| is supported on |platform|.
-
- Args:
- policy: The dictionary of the policy.
- platform: The platform to check; one of 'win', 'mac', 'linux' or
- 'chrome_os'.
- '''
- is_supported = lambda x: platform in x['platforms']
- return any(filter(is_supported, policy['supported_on']))
-
- def _GetChromiumVersionString(self):
- '''Returns the Chromium version string stored in the environment variable
- version (if it is set).
-
- Returns: The Chromium version string or None if it has not been set.'''
-
- if 'version' in self.config:
- return self.config['version']
-
- def _GetPoliciesForWriter(self, group):
- '''Filters the list of policies in the passed group that are supported by
- the writer.
-
- Args:
- group: The dictionary of the policy group.
-
- Returns: The list of policies of the policy group that are compatible
- with the writer.
- '''
- if not 'policies' in group:
- return []
- result = []
- for policy in group['policies']:
- if self.IsPolicySupported(policy):
- result.append(policy)
- return result
-
- def Init(self):
- '''Initializes the writer. If the WriteTemplate method is overridden, then
- this method must be called as first step of each template generation
- process.
- '''
- pass
-
- def WriteTemplate(self, template):
- '''Writes the given template definition.
-
- Args:
- template: Template definition to write.
-
- Returns:
- Generated output for the passed template definition.
- '''
- self.messages = template['messages']
- self.Init()
- template['policy_definitions'] = \
- self.PreprocessPolicies(template['policy_definitions'])
- self.BeginTemplate()
- for policy in template['policy_definitions']:
- if policy['type'] == 'group':
- child_policies = self._GetPoliciesForWriter(policy)
- child_recommended_policies = filter(self.CanBeRecommended,
- child_policies)
- if child_policies:
- # Only write nonempty groups.
- self.BeginPolicyGroup(policy)
- for child_policy in child_policies:
- # Nesting of groups is currently not supported.
- self.WritePolicy(child_policy)
- self.EndPolicyGroup()
- if child_recommended_policies:
- self.BeginRecommendedPolicyGroup(policy)
- for child_policy in child_recommended_policies:
- self.WriteRecommendedPolicy(child_policy)
- self.EndRecommendedPolicyGroup()
- elif self.IsPolicySupported(policy):
- self.WritePolicy(policy)
- if self.CanBeRecommended(policy):
- self.WriteRecommendedPolicy(policy)
- self.EndTemplate()
-
- return self.GetTemplateText()
-
- def PreprocessPolicies(self, policy_list):
- '''Preprocesses a list of policies according to a given writer's needs.
- Preprocessing steps include sorting policies and stripping unneeded
- information such as groups (for writers that ignore them).
- Subclasses are encouraged to override this method, overriding
- implementations may call one of the provided specialized implementations.
- The default behaviour is to use SortPoliciesGroupsFirst().
-
- Args:
- policy_list: A list containing the policies to sort.
-
- Returns:
- The sorted policy list.
- '''
- return self.SortPoliciesGroupsFirst(policy_list)
-
- def WritePolicy(self, policy):
- '''Appends the template text corresponding to a policy into the
- internal buffer.
-
- Args:
- policy: The policy as it is found in the JSON file.
- '''
- raise NotImplementedError()
-
- def WriteComment(self, comment):
- '''Appends the comment to the internal buffer.
-
- comment: The comment to be added.
- '''
- raise NotImplementedError()
-
- def WriteRecommendedPolicy(self, policy):
- '''Appends the template text corresponding to a recommended policy into the
- internal buffer.
-
- Args:
- policy: The recommended policy as it is found in the JSON file.
- '''
- # TODO
- #raise NotImplementedError()
- pass
-
- def BeginPolicyGroup(self, group):
- '''Appends the template text corresponding to the beginning of a
- policy group into the internal buffer.
-
- Args:
- group: The policy group as it is found in the JSON file.
- '''
- pass
-
- def EndPolicyGroup(self):
- '''Appends the template text corresponding to the end of a
- policy group into the internal buffer.
- '''
- pass
-
- def BeginRecommendedPolicyGroup(self, group):
- '''Appends the template text corresponding to the beginning of a recommended
- policy group into the internal buffer.
-
- Args:
- group: The recommended policy group as it is found in the JSON file.
- '''
- pass
-
- def EndRecommendedPolicyGroup(self):
- '''Appends the template text corresponding to the end of a recommended
- policy group into the internal buffer.
- '''
- pass
-
- def BeginTemplate(self):
- '''Appends the text corresponding to the beginning of the whole
- template into the internal buffer.
- '''
- raise NotImplementedError()
-
- def EndTemplate(self):
- '''Appends the text corresponding to the end of the whole
- template into the internal buffer.
- '''
- pass
-
- def GetTemplateText(self):
- '''Gets the content of the internal template buffer.
-
- Returns:
- The generated template from the the internal buffer as a string.
- '''
- raise NotImplementedError()
-
- def SortPoliciesGroupsFirst(self, policy_list):
- '''Sorts a list of policies alphabetically. The order is the
- following: first groups alphabetically by caption, then other policies
- alphabetically by name. The order of policies inside groups is unchanged.
-
- Args:
- policy_list: The list of policies to sort. Sub-lists in groups will not
- be sorted.
- '''
- policy_list.sort(key=self.GetPolicySortingKeyGroupsFirst)
- return policy_list
-
- def FlattenGroupsAndSortPolicies(self, policy_list, sorting_key=None):
- '''Sorts a list of policies according to |sorting_key|, defaulting
- to alphabetical sorting if no key is given. If |policy_list| contains
- policies with type="group", it is flattened first, i.e. any groups' contents
- are inserted into the list as first-class elements and the groups are then
- removed.
- '''
- new_list = []
- for policy in policy_list:
- if policy['type'] == 'group':
- for grouped_policy in policy['policies']:
- new_list.append(grouped_policy)
- else:
- new_list.append(policy)
- if sorting_key == None:
- sorting_key = self.GetPolicySortingKeyName
- new_list.sort(key=sorting_key)
- return new_list
-
- def GetPolicySortingKeyName(self, policy):
- return policy['name']
-
- def GetPolicySortingKeyGroupsFirst(self, policy):
- '''Extracts a sorting key from a policy. These keys can be used for
- list.sort() methods to sort policies.
- See TemplateWriter.SortPolicies for usage.
- '''
- is_group = policy['type'] == 'group'
- if is_group:
- # Groups are sorted by caption.
- str_key = policy['caption']
- else:
- # Regular policies are sorted by name.
- str_key = policy['name']
- # Groups come before regular policies.
- return (not is_group, str_key)
diff --git a/grit/format/policy_templates/writers/template_writer_unittest.py b/grit/format/policy_templates/writers/template_writer_unittest.py
deleted file mode 100644
index 172e292..0000000
--- a/grit/format/policy_templates/writers/template_writer_unittest.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.policy_templates.writers.template_writer'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../../../..'))
-
-import unittest
-
-from grit.format.policy_templates.writers import template_writer
-
-
-POLICY_DEFS = [
- {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
- {
- 'type': 'group',
- 'caption': 'z_group1_caption',
- 'name': 'group1',
- 'policies': [
- {'name': 'z0', 'type': 'string', 'supported_on': []},
- {'name': 'a0', 'type': 'string', 'supported_on': []}
- ]
- },
- {
- 'type': 'group',
- 'caption': 'b_group2_caption',
- 'name': 'group2',
- 'policies': [{'name': 'q', 'type': 'string', 'supported_on': []}],
- },
- {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []}
-]
-
-
-GROUP_FIRST_SORTED_POLICY_DEFS = [
- {
- 'type': 'group',
- 'caption': 'b_group2_caption',
- 'name': 'group2',
- 'policies': [{'name': 'q', 'type': 'string', 'supported_on': []}],
- },
- {
- 'type': 'group',
- 'caption': 'z_group1_caption',
- 'name': 'group1',
- 'policies': [
- {'name': 'z0', 'type': 'string', 'supported_on': []},
- {'name': 'a0', 'type': 'string', 'supported_on': []}
- ]
- },
- {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []},
- {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
-]
-
-
-IGNORE_GROUPS_SORTED_POLICY_DEFS = [
- {'name': 'a0', 'type': 'string', 'supported_on': []},
- {'name': 'ap', 'type': 'string', 'caption': 'a2', 'supported_on': []},
- {'name': 'q', 'type': 'string', 'supported_on': []},
- {'name': 'z0', 'type': 'string', 'supported_on': []},
- {'name': 'zp', 'type': 'string', 'caption': 'a1', 'supported_on': []},
-]
-
-
-class TemplateWriterUnittests(unittest.TestCase):
- '''Unit tests for templater_writer.py.'''
-
- def testSortingGroupsFirst(self):
- tw = template_writer.TemplateWriter(None, None)
- sorted_list = tw.SortPoliciesGroupsFirst(POLICY_DEFS)
- self.assertEqual(sorted_list, GROUP_FIRST_SORTED_POLICY_DEFS)
-
- def testSortingIgnoreGroups(self):
- tw = template_writer.TemplateWriter(None, None)
- sorted_list = tw.FlattenGroupsAndSortPolicies(POLICY_DEFS)
- self.assertEqual(sorted_list, IGNORE_GROUPS_SORTED_POLICY_DEFS)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/policy_templates/writers/writer_unittest_common.py b/grit/format/policy_templates/writers/writer_unittest_common.py
deleted file mode 100644
index f75c391..0000000
--- a/grit/format/policy_templates/writers/writer_unittest_common.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Common tools for unit-testing writers.'''
-
-
-import os
-import tempfile
-import unittest
-import StringIO
-
-from grit import grd_reader
-from grit import util
-from grit.tool import build
-
-
-class DummyOutput(object):
- def __init__(self, type, language, file = 'hello.gif'):
- self.type = type
- self.language = language
- self.file = file
- def GetType(self):
- return self.type
- def GetLanguage(self):
- return self.language
- def GetOutputFilename(self):
- return self.file
-
-
-class WriterUnittestCommon(unittest.TestCase):
- '''Common class for unittesting writers.'''
-
- def PrepareTest(self, policy_json):
- '''Prepares and parses a grit tree along with a data structure of policies.
-
- Args:
- policy_json: The policy data structure in JSON format.
- '''
- # First create a temporary file that contains the JSON policy list.
- tmp_file_name = 'test.json'
- tmp_dir_name = tempfile.gettempdir()
- json_file_path = tmp_dir_name + '/' + tmp_file_name
- with open(json_file_path, 'w') as f:
- f.write(policy_json.strip())
- # Then assemble the grit tree.
- grd_text = '''
- <grit base_dir="." latest_public_release="0" current_release="1" source_lang_id="en">
- <release seq="1">
- <structures>
- <structure name="IDD_POLICY_SOURCE_FILE" file="%s" type="policy_template_metafile" />
- </structures>
- </release>
- </grit>''' % json_file_path
- grd_string_io = StringIO.StringIO(grd_text)
- # Parse the grit tree and load the policies' JSON with a gatherer.
- grd = grd_reader.Parse(grd_string_io, dir=tmp_dir_name)
- grd.SetOutputLanguage('en')
- grd.RunGatherers()
- # Remove the policies' JSON.
- os.unlink(json_file_path)
- return grd
-
- def GetOutput(self, grd, env_lang, env_defs, out_type, out_lang):
- '''Generates an output of a writer.
-
- Args:
- grd: The root of the grit tree.
- env_lang: The environment language.
- env_defs: Environment definitions.
- out_type: Type of the output node for which output will be generated.
- This selects the writer.
- out_lang: Language of the output node for which output will be generated.
-
- Returns:
- The string of the template created by the writer.
- '''
- grd.SetOutputLanguage(env_lang)
- grd.SetDefines(env_defs)
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(grd, DummyOutput(out_type, out_lang), buf)
- return buf.getvalue()
diff --git a/grit/format/policy_templates/writers/xml_formatted_writer.py b/grit/format/policy_templates/writers/xml_formatted_writer.py
deleted file mode 100644
index 5917fb4..0000000
--- a/grit/format/policy_templates/writers/xml_formatted_writer.py
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-from grit.format.policy_templates.writers import template_writer
-
-
-class XMLFormattedWriter(template_writer.TemplateWriter):
- '''Helper class for generating XML-based templates.
- '''
-
- def AddElement(self, parent, name, attrs=None, text=None):
- '''
- Adds a new XML Element as a child to an existing element or the Document.
-
- Args:
- parent: An XML element or the document, where the new element will be
- added.
- name: The name of the new element.
- attrs: A dictionary of the attributes' names and values for the new
- element.
- text: Text content for the new element.
-
- Returns:
- The created new element.
- '''
- if attrs == None:
- attrs = {}
-
- doc = parent.ownerDocument
- element = doc.createElement(name)
- for key, value in sorted(attrs.iteritems()):
- element.setAttribute(key, value)
- if text:
- element.appendChild(doc.createTextNode(text))
- parent.appendChild(element)
- return element
-
- def AddText(self, parent, text):
- '''Adds text to a parent node.
- '''
- doc = parent.ownerDocument
- parent.appendChild(doc.createTextNode(text))
-
- def AddAttribute(self, parent, name, value):
- '''Adds a new attribute to the parent Element. If an attribute with the
- given name already exists then it will be replaced.
- '''
- doc = parent.ownerDocument
- attribute = doc.createAttribute(name)
- attribute.value = value
- parent.setAttributeNode(attribute)
-
- def AddComment(self, parent, comment):
- '''Adds a comment node.'''
- parent.appendChild(parent.ownerDocument.createComment(comment))
-
- def ToPrettyXml(self, doc, **kwargs):
- # return doc.toprettyxml(indent=' ')
- # The above pretty-printer does not print the doctype and adds spaces
- # around texts, e.g.:
- # <string>
- # value of the string
- # </string>
- # This is problematic both for the OSX Workgroup Manager (plist files) and
- # the Windows Group Policy Editor (admx files). What they need instead:
- # <string>value of string</string>
- # So we use the poor man's pretty printer here. It assumes that there are
- # no mixed-content nodes.
- # Get all the XML content in a one-line string.
- xml = doc.toxml(**kwargs)
- # Determine where the line breaks will be. (They will only be between tags.)
- lines = xml[1:len(xml) - 1].split('><')
- indent = ''
- res = ''
- # Determine indent for each line.
- for i, line in enumerate(lines):
- if line[0] == '/':
- # If the current line starts with a closing tag, decrease indent before
- # printing.
- indent = indent[2:]
- lines[i] = indent + '<' + line + '>'
- if (line[0] not in ['/', '?', '!'] and '</' not in line and
- line[len(line) - 1] != '/'):
- # If the current line starts with an opening tag and does not conatin a
- # closing tag, increase indent after the line is printed.
- indent += ' '
- # Reconstruct XML text from the lines.
- return '\n'.join(lines)
diff --git a/grit/format/policy_templates/writers/xml_writer_base_unittest.py b/grit/format/policy_templates/writers/xml_writer_base_unittest.py
deleted file mode 100644
index cfa5dc2..0000000
--- a/grit/format/policy_templates/writers/xml_writer_base_unittest.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-
-"""Unittests for grit.format.policy_templates.writers.admx_writer."""
-
-
-import re
-import unittest
-
-
-class XmlWriterBaseTest(unittest.TestCase):
- '''Base class for XML writer unit-tests.
- '''
-
- def GetXMLOfChildren(self, parent):
- '''Returns the XML of all child nodes of the given parent node.
- Args:
- parent: The XML of the children of this node will be returned.
-
- Return: XML of the chrildren of the parent node.
- '''
- raw_pretty_xml = ''.join(
- child.toprettyxml(indent=' ') for child in parent.childNodes)
- # Python 2.6.5 which is present in Lucid has bug in its pretty print
- # function which produces new lines around string literals. This has been
- # fixed in Precise which has Python 2.7.3 but we have to keep compatibility
- # with both for now.
- text_re = re.compile('>\n\s+([^<>\s].*?)\n\s*</', re.DOTALL)
- return text_re.sub('>\g<1></', raw_pretty_xml)
-
- def AssertXMLEquals(self, output, expected_output):
- '''Asserts if the passed XML arguements are equal.
- Args:
- output: Actual XML text.
- expected_output: Expected XML text.
- '''
- self.assertEquals(output.strip(), expected_output.strip())
diff --git a/grit/format/rc.py b/grit/format/rc.py
deleted file mode 100644
index eb8efac..0000000
--- a/grit/format/rc.py
+++ /dev/null
@@ -1,481 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Support for formatting an RC file for compilation.
-'''
-
-import os
-import types
-import re
-from functools import partial
-
-from grit import util
-from grit.node import misc
-
-
-def Format(root, lang='en', output_dir='.'):
- from grit.node import empty, include, message, structure
-
- yield _FormatHeader(root, lang, output_dir)
-
- for item in root.ActiveDescendants():
- if isinstance(item, empty.MessagesNode):
- # Write one STRINGTABLE per <messages> container.
- # This is hacky: it iterates over the children twice.
- yield 'STRINGTABLE\nBEGIN\n'
- for subitem in item.ActiveDescendants():
- if isinstance(subitem, message.MessageNode):
- with subitem:
- yield FormatMessage(subitem, lang)
- yield 'END\n\n'
- elif isinstance(item, include.IncludeNode):
- with item:
- yield FormatInclude(item, lang, output_dir)
- elif isinstance(item, structure.StructureNode):
- with item:
- yield FormatStructure(item, lang, output_dir)
-
-
-'''
-This dictionary defines the language charset pair lookup table, which is used
-for replacing the GRIT expand variables for language info in Product Version
-resource. The key is the language ISO country code, and the value
-is the language and character-set pair, which is a hexadecimal string
-consisting of the concatenation of the language and character-set identifiers.
-The first 4 digit of the value is the hex value of LCID, the remaining
-4 digits is the hex value of character-set id(code page)of the language.
-
-LCID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
-Codepage resource: http://www.science.co.il/language/locale-codes.asp
-
-We have defined three GRIT expand_variables to be used in the version resource
-file to set the language info. Here is an example how they should be used in
-the VS_VERSION_INFO section of the resource file to allow GRIT to localize
-the language info correctly according to product locale.
-
-VS_VERSION_INFO VERSIONINFO
-...
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "[GRITVERLANGCHARSETHEX]"
- BEGIN
- ...
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", [GRITVERLANGID], [GRITVERCHARSETID]
- END
-END
-
-'''
-
-_LANGUAGE_CHARSET_PAIR = {
- # Language neutral LCID, unicode(1200) code page.
- 'neutral' : '000004b0',
- # LANG_USER_DEFAULT LCID, unicode(1200) code page.
- 'userdefault' : '040004b0',
- 'ar' : '040104e8',
- 'fi' : '040b04e4',
- 'ko' : '041203b5',
- 'es' : '0c0a04e4',
- 'bg' : '040204e3',
- # No codepage for filipino, use unicode(1200).
- 'fil' : '046404e4',
- 'fr' : '040c04e4',
- 'lv' : '042604e9',
- 'sv' : '041d04e4',
- 'ca' : '040304e4',
- 'de' : '040704e4',
- 'lt' : '042704e9',
- # Do not use! This is only around for backwards
- # compatibility and will be removed - use fil instead
- 'tl' : '0c0004b0',
- 'zh-CN' : '080403a8',
- 'zh-TW' : '040403b6',
- 'zh-HK' : '0c0403b6',
- 'el' : '040804e5',
- 'no' : '001404e4',
- 'nb' : '041404e4',
- 'nn' : '081404e4',
- 'th' : '041e036a',
- 'he' : '040d04e7',
- 'iw' : '040d04e7',
- 'pl' : '041504e2',
- 'tr' : '041f04e6',
- 'hr' : '041a04e4',
- # No codepage for Hindi, use unicode(1200).
- 'hi' : '043904b0',
- 'pt-PT' : '081604e4',
- 'pt-BR' : '041604e4',
- 'uk' : '042204e3',
- 'cs' : '040504e2',
- 'hu' : '040e04e2',
- 'ro' : '041804e2',
- # No codepage for Urdu, use unicode(1200).
- 'ur' : '042004b0',
- 'da' : '040604e4',
- 'is' : '040f04e4',
- 'ru' : '041904e3',
- 'vi' : '042a04ea',
- 'nl' : '041304e4',
- 'id' : '042104e4',
- 'sr' : '081a04e2',
- 'en-GB' : '0809040e',
- 'it' : '041004e4',
- 'sk' : '041b04e2',
- 'et' : '042504e9',
- 'ja' : '041103a4',
- 'sl' : '042404e2',
- 'en' : '040904b0',
- # LCID for Mexico; Windows does not support L.A. LCID.
- 'es-419' : '080a04e4',
- # No codepage for Bengali, use unicode(1200).
- 'bn' : '044504b0',
- 'fa' : '042904e8',
- # No codepage for Gujarati, use unicode(1200).
- 'gu' : '044704b0',
- # No codepage for Kannada, use unicode(1200).
- 'kn' : '044b04b0',
- # Malay (Malaysia) [ms-MY]
- 'ms' : '043e04e4',
- # No codepage for Malayalam, use unicode(1200).
- 'ml' : '044c04b0',
- # No codepage for Marathi, use unicode(1200).
- 'mr' : '044e04b0',
- # No codepage for Oriya , use unicode(1200).
- 'or' : '044804b0',
- # No codepage for Tamil, use unicode(1200).
- 'ta' : '044904b0',
- # No codepage for Telugu, use unicode(1200).
- 'te' : '044a04b0',
- # No codepage for Amharic, use unicode(1200). >= Vista.
- 'am' : '045e04b0',
- 'sw' : '044104e4',
- 'af' : '043604e4',
- 'eu' : '042d04e4',
- 'fr-CA' : '0c0c04e4',
- 'gl' : '045604e4',
- # No codepage for Zulu, use unicode(1200).
- 'zu' : '043504b0',
- 'fake-bidi' : '040d04e7',
-}
-
-# Language ID resource: http://msdn.microsoft.com/en-us/library/ms776294.aspx
-#
-# There is no appropriate sublang for Spanish (Latin America) [es-419], so we
-# use Mexico. SUBLANG_DEFAULT would incorrectly map to Spain. Unlike other
-# Latin American countries, Mexican Spanish is supported by VERSIONINFO:
-# http://msdn.microsoft.com/en-us/library/aa381058.aspx
-
-_LANGUAGE_DIRECTIVE_PAIR = {
- 'neutral' : 'LANG_NEUTRAL, SUBLANG_NEUTRAL',
- 'userdefault' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
- 'ar' : 'LANG_ARABIC, SUBLANG_DEFAULT',
- 'fi' : 'LANG_FINNISH, SUBLANG_DEFAULT',
- 'ko' : 'LANG_KOREAN, SUBLANG_KOREAN',
- 'es' : 'LANG_SPANISH, SUBLANG_SPANISH_MODERN',
- 'bg' : 'LANG_BULGARIAN, SUBLANG_DEFAULT',
- # LANG_FILIPINO (100) not in VC 7 winnt.h.
- 'fil' : '100, SUBLANG_DEFAULT',
- 'fr' : 'LANG_FRENCH, SUBLANG_FRENCH',
- 'lv' : 'LANG_LATVIAN, SUBLANG_DEFAULT',
- 'sv' : 'LANG_SWEDISH, SUBLANG_SWEDISH',
- 'ca' : 'LANG_CATALAN, SUBLANG_DEFAULT',
- 'de' : 'LANG_GERMAN, SUBLANG_GERMAN',
- 'lt' : 'LANG_LITHUANIAN, SUBLANG_LITHUANIAN',
- # Do not use! See above.
- 'tl' : 'LANG_NEUTRAL, SUBLANG_DEFAULT',
- 'zh-CN' : 'LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED',
- 'zh-TW' : 'LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL',
- 'zh-HK' : 'LANG_CHINESE, SUBLANG_CHINESE_HONGKONG',
- 'el' : 'LANG_GREEK, SUBLANG_DEFAULT',
- 'no' : 'LANG_NORWEGIAN, SUBLANG_DEFAULT',
- 'nb' : 'LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL',
- 'nn' : 'LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK',
- 'th' : 'LANG_THAI, SUBLANG_DEFAULT',
- 'he' : 'LANG_HEBREW, SUBLANG_DEFAULT',
- 'iw' : 'LANG_HEBREW, SUBLANG_DEFAULT',
- 'pl' : 'LANG_POLISH, SUBLANG_DEFAULT',
- 'tr' : 'LANG_TURKISH, SUBLANG_DEFAULT',
- 'hr' : 'LANG_CROATIAN, SUBLANG_DEFAULT',
- 'hi' : 'LANG_HINDI, SUBLANG_DEFAULT',
- 'pt-PT' : 'LANG_PORTUGUESE, SUBLANG_PORTUGUESE',
- 'pt-BR' : 'LANG_PORTUGUESE, SUBLANG_DEFAULT',
- 'uk' : 'LANG_UKRAINIAN, SUBLANG_DEFAULT',
- 'cs' : 'LANG_CZECH, SUBLANG_DEFAULT',
- 'hu' : 'LANG_HUNGARIAN, SUBLANG_DEFAULT',
- 'ro' : 'LANG_ROMANIAN, SUBLANG_DEFAULT',
- 'ur' : 'LANG_URDU, SUBLANG_DEFAULT',
- 'da' : 'LANG_DANISH, SUBLANG_DEFAULT',
- 'is' : 'LANG_ICELANDIC, SUBLANG_DEFAULT',
- 'ru' : 'LANG_RUSSIAN, SUBLANG_DEFAULT',
- 'vi' : 'LANG_VIETNAMESE, SUBLANG_DEFAULT',
- 'nl' : 'LANG_DUTCH, SUBLANG_DEFAULT',
- 'id' : 'LANG_INDONESIAN, SUBLANG_DEFAULT',
- 'sr' : 'LANG_SERBIAN, SUBLANG_SERBIAN_LATIN',
- 'en-GB' : 'LANG_ENGLISH, SUBLANG_ENGLISH_UK',
- 'it' : 'LANG_ITALIAN, SUBLANG_DEFAULT',
- 'sk' : 'LANG_SLOVAK, SUBLANG_DEFAULT',
- 'et' : 'LANG_ESTONIAN, SUBLANG_DEFAULT',
- 'ja' : 'LANG_JAPANESE, SUBLANG_DEFAULT',
- 'sl' : 'LANG_SLOVENIAN, SUBLANG_DEFAULT',
- 'en' : 'LANG_ENGLISH, SUBLANG_ENGLISH_US',
- # No L.A. sublang exists.
- 'es-419' : 'LANG_SPANISH, SUBLANG_SPANISH_MEXICAN',
- 'bn' : 'LANG_BENGALI, SUBLANG_DEFAULT',
- 'fa' : 'LANG_PERSIAN, SUBLANG_DEFAULT',
- 'gu' : 'LANG_GUJARATI, SUBLANG_DEFAULT',
- 'kn' : 'LANG_KANNADA, SUBLANG_DEFAULT',
- 'ms' : 'LANG_MALAY, SUBLANG_DEFAULT',
- 'ml' : 'LANG_MALAYALAM, SUBLANG_DEFAULT',
- 'mr' : 'LANG_MARATHI, SUBLANG_DEFAULT',
- 'or' : 'LANG_ORIYA, SUBLANG_DEFAULT',
- 'ta' : 'LANG_TAMIL, SUBLANG_DEFAULT',
- 'te' : 'LANG_TELUGU, SUBLANG_DEFAULT',
- 'am' : 'LANG_AMHARIC, SUBLANG_DEFAULT',
- 'sw' : 'LANG_SWAHILI, SUBLANG_DEFAULT',
- 'af' : 'LANG_AFRIKAANS, SUBLANG_DEFAULT',
- 'eu' : 'LANG_BASQUE, SUBLANG_DEFAULT',
- 'fr-CA' : 'LANG_FRENCH, SUBLANG_FRENCH_CANADIAN',
- 'gl' : 'LANG_GALICIAN, SUBLANG_DEFAULT',
- 'zu' : 'LANG_ZULU, SUBLANG_DEFAULT',
- 'pa' : 'LANG_PUNJABI, SUBLANG_PUNJABI_INDIA',
- 'sa' : 'LANG_SANSKRIT, SUBLANG_SANSKRIT_INDIA',
- 'si' : 'LANG_SINHALESE, SUBLANG_SINHALESE_SRI_LANKA',
- 'ne' : 'LANG_NEPALI, SUBLANG_NEPALI_NEPAL',
- 'ti' : 'LANG_TIGRIGNA, SUBLANG_TIGRIGNA_ERITREA',
- 'fake-bidi' : 'LANG_HEBREW, SUBLANG_DEFAULT',
-}
-
-# A note on 'no-specific-language' in the following few functions:
-# Some build systems may wish to call GRIT to scan for dependencies in
-# a language-agnostic way, and can then specify this fake language as
-# the output context. It should never be used when output is actually
-# being generated.
-
-def GetLangCharsetPair(language):
- if _LANGUAGE_CHARSET_PAIR.has_key(language):
- return _LANGUAGE_CHARSET_PAIR[language]
- elif language == 'no-specific-language':
- return ''
- else:
- print 'Warning:GetLangCharsetPair() found undefined language %s' %(language)
- return ''
-
-def GetLangDirectivePair(language):
- if _LANGUAGE_DIRECTIVE_PAIR.has_key(language):
- return _LANGUAGE_DIRECTIVE_PAIR[language]
- else:
- # We don't check for 'no-specific-language' here because this
- # function should only get called when output is being formatted,
- # and at that point we would not want to get
- # 'no-specific-language' passed as the language.
- print ('Warning:GetLangDirectivePair() found undefined language %s' %
- language)
- return 'unknown language: see tools/grit/format/rc.py'
-
-def GetLangIdHex(language):
- if _LANGUAGE_CHARSET_PAIR.has_key(language):
- langcharset = _LANGUAGE_CHARSET_PAIR[language]
- lang_id = '0x' + langcharset[0:4]
- return lang_id
- elif language == 'no-specific-language':
- return ''
- else:
- print 'Warning:GetLangIdHex() found undefined language %s' %(language)
- return ''
-
-
-def GetCharsetIdDecimal(language):
- if _LANGUAGE_CHARSET_PAIR.has_key(language):
- langcharset = _LANGUAGE_CHARSET_PAIR[language]
- charset_decimal = int(langcharset[4:], 16)
- return str(charset_decimal)
- elif language == 'no-specific-language':
- return ''
- else:
- print 'Warning:GetCharsetIdDecimal() found undefined language %s' % language
- return ''
-
-
-def GetUnifiedLangCode(language) :
- r = re.compile('([a-z]{1,2})_([a-z]{1,2})')
- if r.match(language) :
- underscore = language.find('_')
- return language[0:underscore] + '-' + language[underscore + 1:].upper()
- else :
- return language
-
-
-def RcSubstitutions(substituter, lang):
- '''Add language-based substitutions for Rc files to the substitutor.'''
- unified_lang_code = GetUnifiedLangCode(lang)
- substituter.AddSubstitutions({
- 'GRITVERLANGCHARSETHEX': GetLangCharsetPair(unified_lang_code),
- 'GRITVERLANGID': GetLangIdHex(unified_lang_code),
- 'GRITVERCHARSETID': GetCharsetIdDecimal(unified_lang_code)})
-
-
-def _FormatHeader(root, lang, output_dir):
- '''Returns the required preamble for RC files.'''
- assert isinstance(lang, types.StringTypes)
- assert isinstance(root, misc.GritNode)
- # Find the location of the resource header file, so that we can include
- # it.
- resource_header = 'resource.h' # fall back to this
- language_directive = ''
- for output in root.GetOutputFiles():
- if output.attrs['type'] == 'rc_header':
- resource_header = os.path.abspath(output.GetOutputFilename())
- resource_header = util.MakeRelativePath(output_dir, resource_header)
- if output.attrs['lang'] != lang:
- continue
- if output.attrs['language_section'] == '':
- # If no language_section is requested, no directive is added
- # (Used when the generated rc will be included from another rc
- # file that will have the appropriate language directive)
- language_directive = ''
- elif output.attrs['language_section'] == 'neutral':
- # If a neutral language section is requested (default), add a
- # neutral language directive
- language_directive = 'LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL'
- elif output.attrs['language_section'] == 'lang':
- language_directive = 'LANGUAGE %s' % GetLangDirectivePair(lang)
- resource_header = resource_header.replace('\\', '\\\\')
- return '''// This file is automatically generated by GRIT. Do not edit.
-
-#include "%s"
-#include <winresrc.h>
-#ifdef IDC_STATIC
-#undef IDC_STATIC
-#endif
-#define IDC_STATIC (-1)
-
-%s
-
-
-''' % (resource_header, language_directive)
-# end _FormatHeader() function
-
-
-def FormatMessage(item, lang):
- '''Returns a single message of a string table.'''
- message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
- # Escape quotation marks (RC format uses doubling-up
- message = message.replace('"', '""')
- # Replace linebreaks with a \n escape
- message = util.LINEBREAKS.sub(r'\\n', message)
- if hasattr(item.GetRoot(), 'GetSubstituter'):
- substituter = item.GetRoot().GetSubstituter()
- message = substituter.Substitute(message)
-
- name_attr = item.GetTextualIds()[0]
-
- return ' %-15s "%s"\n' % (name_attr, message)
-
-
-def _FormatSection(item, lang, output_dir):
- '''Writes out an .rc file section.'''
- assert isinstance(lang, types.StringTypes)
- from grit.node import structure
- assert isinstance(item, structure.StructureNode)
-
- if item.IsExcludedFromRc():
- return ''
- else:
- text = item.gatherer.Translate(
- lang, skeleton_gatherer=item.GetSkeletonGatherer(),
- pseudo_if_not_available=item.PseudoIsAllowed(),
- fallback_to_english=item.ShouldFallbackToEnglish()) + '\n\n'
-
- # Replace the language expand_variables in version rc info.
- if item.ExpandVariables() and hasattr(item.GetRoot(), 'GetSubstituter'):
- substituter = item.GetRoot().GetSubstituter()
- text = substituter.Substitute(text)
-
- return text
-
-
-def FormatInclude(item, lang, output_dir, type=None, process_html=False):
- '''Formats an item that is included in an .rc file (e.g. an ICON).
-
- Args:
- item: an IncludeNode or StructureNode
- lang, output_dir: standard formatter parameters
- type: .rc file resource type, e.g. 'ICON' (ignored unless item is a
- StructureNode)
- process_html: False/True (ignored unless item is a StructureNode)
- '''
- assert isinstance(lang, types.StringTypes)
- from grit.node import structure
- from grit.node import include
- assert isinstance(item, (structure.StructureNode, include.IncludeNode))
-
- if isinstance(item, include.IncludeNode):
- type = item.attrs['type'].upper()
- process_html = item.attrs['flattenhtml'] == 'true'
- filename_only = item.attrs['filenameonly'] == 'true'
- relative_path = item.attrs['relativepath'] == 'true'
- else:
- assert (isinstance(item, structure.StructureNode) and item.attrs['type'] in
- ['admin_template', 'chrome_html', 'chrome_scaled_image', 'igoogle',
- 'muppet', 'tr_html', 'txt'])
- filename_only = False
- relative_path = False
-
- # By default, we use relative pathnames to included resources so that
- # sharing the resulting .rc files is possible.
- #
- # The FileForLanguage() Function has the side effect of generating the file
- # if needed (e.g. if it is an HTML file include).
- file_for_lang = item.FileForLanguage(lang, output_dir)
- if file_for_lang is None:
- return ''
-
- filename = os.path.abspath(file_for_lang)
- if process_html:
- filename = item.Process(output_dir)
- elif filename_only:
- filename = os.path.basename(filename)
- elif relative_path:
- filename = util.MakeRelativePath(output_dir, filename)
-
- filename = filename.replace('\\', '\\\\') # escape for the RC format
-
- if isinstance(item, structure.StructureNode) and item.IsExcludedFromRc():
- return ''
- else:
- return '%-18s %-18s "%s"\n' % (item.attrs['name'], type, filename)
-
-
-def _DoNotFormat(item, lang, output_dir):
- return ''
-
-
-# Formatter instance to use for each type attribute
-# when formatting Structure nodes.
-_STRUCTURE_FORMATTERS = {
- 'accelerators' : _FormatSection,
- 'dialog' : _FormatSection,
- 'menu' : _FormatSection,
- 'rcdata' : _FormatSection,
- 'version' : _FormatSection,
- 'admin_template' : partial(FormatInclude, type='ADM'),
- 'chrome_html' : partial(FormatInclude, type='BINDATA',
- process_html=True),
- 'chrome_scaled_image' : partial(FormatInclude, type='BINDATA'),
- 'igoogle' : partial(FormatInclude, type='XML'),
- 'muppet' : partial(FormatInclude, type='XML'),
- 'tr_html' : partial(FormatInclude, type='HTML'),
- 'txt' : partial(FormatInclude, type='TXT'),
- 'policy_template_metafile': _DoNotFormat,
-}
-
-
-def FormatStructure(item, lang, output_dir):
- formatter = _STRUCTURE_FORMATTERS[item.attrs['type']]
- return formatter(item, lang, output_dir)
diff --git a/grit/format/rc_header.py b/grit/format/rc_header.py
deleted file mode 100644
index 74e7127..0000000
--- a/grit/format/rc_header.py
+++ /dev/null
@@ -1,204 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Item formatters for RC headers.
-'''
-
-from grit import exception
-from grit import util
-from grit.extern import FP
-
-
-def Format(root, lang='en', output_dir='.'):
- yield '''\
-// This file is automatically generated by GRIT. Do not edit.
-
-#pragma once
-'''
- # Check for emit nodes under the rc_header. If any emit node
- # is present, we assume it means the GRD file wants to override
- # the default header, with no includes.
- default_includes = ['#include <atlres.h>', '']
- emit_lines = []
- for output_node in root.GetOutputFiles():
- if output_node.GetType() == 'rc_header':
- for child in output_node.children:
- if child.name == 'emit' and child.attrs['emit_type'] == 'prepend':
- emit_lines.append(child.GetCdata())
- for line in emit_lines or default_includes:
- yield line + '\n'
-
- for line in FormatDefines(root, root.ShouldOutputAllResourceDefines(),
- root.GetRcHeaderFormat()):
- yield line
-
-
-def FormatDefines(root, output_all_resource_defines=True,
- rc_header_format=None):
- '''Yields #define SYMBOL 1234 lines.
-
- Args:
- root: A GritNode.
- output_all_resource_defines: If False, output only the symbols used in the
- current output configuration.
- '''
- from grit.node import message
- tids = GetIds(root)
-
- if output_all_resource_defines:
- items = root.Preorder()
- else:
- items = root.ActiveDescendants()
-
- if not rc_header_format:
- rc_header_format = "#define {textual_id} {numeric_id}"
- rc_header_format += "\n"
- seen = set()
- for item in items:
- if not isinstance(item, message.MessageNode):
- with item:
- for tid in item.GetTextualIds():
- if tid in tids and tid not in seen:
- seen.add(tid)
- yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid])
-
- # Temporarily mimic old behavior: MessageNodes were only output if active,
- # even with output_all_resource_defines set. TODO(benrg): Remove this after
- # fixing problems in the Chrome tree.
- for item in root.ActiveDescendants():
- if isinstance(item, message.MessageNode):
- with item:
- for tid in item.GetTextualIds():
- if tid in tids and tid not in seen:
- seen.add(tid)
- yield rc_header_format.format(textual_id=tid,numeric_id=tids[tid])
-
-
-_cached_ids = {}
-
-
-def GetIds(root):
- '''Return a dictionary mapping textual ids to numeric ids for the given tree.
-
- Args:
- root: A GritNode.
- '''
- # TODO(benrg): Since other formatters use this, it might make sense to move it
- # and _ComputeIds to GritNode and store the cached ids as an attribute. On the
- # other hand, GritNode has too much random stuff already.
- if root not in _cached_ids:
- _cached_ids[root] = _ComputeIds(root)
- return _cached_ids[root]
-
-
-def _ComputeIds(root):
- from grit.node import empty, include, message, misc, structure
-
- ids = {} # Maps numeric id to textual id
- tids = {} # Maps textual id to numeric id
- id_reasons = {} # Maps numeric id to text id and a human-readable explanation
- group = None
- last_id = None
-
- for item in root:
- if isinstance(item, empty.GroupingNode):
- # Note: this won't work if any GroupingNode can be contained inside
- # another.
- group = item
- last_id = None
- continue
-
- assert not item.GetTextualIds() or isinstance(item,
- (include.IncludeNode, message.MessageNode,
- misc.IdentifierNode, structure.StructureNode))
-
- # Resources that use the RES protocol don't need
- # any numerical ids generated, so we skip them altogether.
- # This is accomplished by setting the flag 'generateid' to false
- # in the GRD file.
- if item.attrs.get('generateid', 'true') == 'false':
- continue
-
- for tid in item.GetTextualIds():
- if util.SYSTEM_IDENTIFIERS.match(tid):
- # Don't emit a new ID for predefined IDs
- continue
-
- if tid in tids:
- continue
-
- # Some identifier nodes can provide their own id,
- # and we use that id in the generated header in that case.
- if hasattr(item, 'GetId') and item.GetId():
- id = long(item.GetId())
- reason = 'returned by GetId() method'
-
- elif ('offset' in item.attrs and group and
- group.attrs.get('first_id', '') != ''):
- offset_text = item.attrs['offset']
- parent_text = group.attrs['first_id']
-
- try:
- offset_id = long(offset_text)
- except ValueError:
- offset_id = tids[offset_text]
-
- try:
- parent_id = long(parent_text)
- except ValueError:
- parent_id = tids[parent_text]
-
- id = parent_id + offset_id
- reason = 'first_id %d + offset %d' % (parent_id, offset_id)
-
- # We try to allocate IDs sequentially for blocks of items that might
- # be related, for instance strings in a stringtable (as their IDs might be
- # used e.g. as IDs for some radio buttons, in which case the IDs must
- # be sequential).
- #
- # We do this by having the first item in a section store its computed ID
- # (computed from a fingerprint) in its parent object. Subsequent children
- # of the same parent will then try to get IDs that sequentially follow
- # the currently stored ID (on the parent) and increment it.
- elif last_id is None:
- # First check if the starting ID is explicitly specified by the parent.
- if group and group.attrs.get('first_id', '') != '':
- id = long(group.attrs['first_id'])
- reason = "from parent's first_id attribute"
- else:
- # Automatically generate the ID based on the first clique from the
- # first child of the first child node of our parent (i.e. when we
- # first get to this location in the code).
-
- # According to
- # http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
- # the safe usable range for resource IDs in Windows is from decimal
- # 101 to 0x7FFF.
-
- id = FP.UnsignedFingerPrint(tid)
- id = id % (0x7FFF - 101) + 101
- reason = 'chosen by random fingerprint -- use first_id to override'
-
- last_id = id
- else:
- id = last_id = last_id + 1
- reason = 'sequentially assigned'
-
- reason = "%s (%s)" % (tid, reason)
- # Don't fail when 'offset' is specified, as the base and the 0th
- # offset will have the same ID.
- if id in id_reasons and not 'offset' in item.attrs:
- raise exception.IdRangeOverlap('ID %d was assigned to both %s and %s.'
- % (id, id_reasons[id], reason))
-
- if id < 101:
- print ('WARNING: Numeric resource IDs should be greater than 100 to\n'
- 'avoid conflicts with system-defined resource IDs.')
-
- ids[id] = tid
- tids[tid] = id
- id_reasons[id] = reason
-
- return tids
diff --git a/grit/format/rc_header_unittest.py b/grit/format/rc_header_unittest.py
deleted file mode 100644
index 5d780e3..0000000
--- a/grit/format/rc_header_unittest.py
+++ /dev/null
@@ -1,193 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for the rc_header formatter'''
-
-# GRD samples exceed the 80 character limit.
-# pylint: disable-msg=C6310
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import StringIO
-import unittest
-
-from grit import exception
-from grit import grd_reader
-from grit import util
-from grit.format import rc_header
-
-
-class RcHeaderFormatterUnittest(unittest.TestCase):
- def FormatAll(self, grd):
- output = rc_header.FormatDefines(grd, grd.ShouldOutputAllResourceDefines())
- return ''.join(output).replace(' ', '')
-
- def testFormatter(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
- <release seq="3">
- <includes first_id="300" comment="bingo">
- <include type="gif" name="ID_LOGO" file="images/logo.gif" />
- </includes>
- <messages first_id="10000">
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="IDS_BONGO">
- Bongo!
- </message>
- </messages>
- <structures>
- <structure type="dialog" name="IDD_NARROW_DIALOG" file="rc_files/dialogs.rc" />
- <structure type="version" name="VS_VERSION_INFO" file="rc_files/version.rc" />
- </structures>
- </release>
- </grit>'''), '.')
- output = self.FormatAll(grd)
- self.failUnless(output.count('IDS_GREETING10000'))
- self.failUnless(output.count('ID_LOGO300'))
-
- def testOnlyDefineResourcesThatSatisfyOutputCondition(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3"
- base_dir="." output_all_resource_defines="false">
- <release seq="3">
- <includes first_id="300" comment="bingo">
- <include type="gif" name="ID_LOGO" file="images/logo.gif" />
- </includes>
- <messages first_id="10000">
- <message name="IDS_FIRSTPRESENTSTRING" desc="Present in .rc file.">
- I will appear in the .rc file.
- </message>
- <if expr="False"> <!--Do not include in the .rc files until used.-->
- <message name="IDS_MISSINGSTRING" desc="Not present in .rc file.">
- I will not appear in the .rc file.
- </message>
- </if>
- <if expr="lang != 'es'">
- <message name="IDS_LANGUAGESPECIFICSTRING" desc="Present in .rc file.">
- Hello.
- </message>
- </if>
- <if expr="lang == 'es'">
- <message name="IDS_LANGUAGESPECIFICSTRING" desc="Present in .rc file.">
- Hola.
- </message>
- </if>
- <message name="IDS_THIRDPRESENTSTRING" desc="Present in .rc file.">
- I will also appear in the .rc file.
- </message>
- </messages>
- </release>
- </grit>'''), '.')
- output = self.FormatAll(grd)
- self.failUnless(output.count('IDS_FIRSTPRESENTSTRING10000'))
- self.failIf(output.count('IDS_MISSINGSTRING'))
- self.failIf(output.count('10001')) # IDS_MISSINGSTRING should get this ID
- self.failUnless(output.count('IDS_LANGUAGESPECIFICSTRING10002'))
- self.failUnless(output.count('IDS_THIRDPRESENTSTRING10003'))
-
- def testExplicitFirstIdOverlaps(self):
- # second first_id will overlap preexisting range
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
- <release seq="3">
- <includes first_id="300" comment="bingo">
- <include type="gif" name="ID_LOGO" file="images/logo.gif" />
- <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
- </includes>
- <messages first_id="301">
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="IDS_SMURFGEBURF">Frubegfrums</message>
- </messages>
- </release>
- </grit>'''), '.')
- self.assertRaises(exception.IdRangeOverlap, self.FormatAll, grd)
-
- def testImplicitOverlapsPreexisting(self):
- # second message in <messages> will overlap preexisting range
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
- <release seq="3">
- <includes first_id="301" comment="bingo">
- <include type="gif" name="ID_LOGO" file="images/logo.gif" />
- <include type="gif" name="ID_LOGO2" file="images/logo2.gif" />
- </includes>
- <messages first_id="300">
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="IDS_SMURFGEBURF">Frubegfrums</message>
- </messages>
- </release>
- </grit>'''), '.')
- self.assertRaises(exception.IdRangeOverlap, self.FormatAll, grd)
-
- def testEmit(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
- <outputs>
- <output type="rc_all" filename="dummy">
- <emit emit_type="prepend">Wrong</emit>
- </output>
- <if expr="False">
- <output type="rc_header" filename="dummy">
- <emit emit_type="prepend">No</emit>
- </output>
- </if>
- <output type="rc_header" filename="dummy">
- <emit emit_type="append">Error</emit>
- </output>
- <output type="rc_header" filename="dummy">
- <emit emit_type="prepend">Bingo</emit>
- </output>
- </outputs>
- </grit>'''), '.')
- output = ''.join(rc_header.Format(grd, 'en', '.'))
- output = util.StripBlankLinesAndComments(output)
- self.assertEqual('#pragma once\nBingo', output)
-
- def testRcHeaderFormat(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3" base_dir=".">
- <release seq="3">
- <includes first_id="300" comment="bingo">
- <include type="gif" name="IDR_LOGO" file="images/logo.gif" />
- </includes>
- <messages first_id="10000">
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="IDS_BONGO">
- Bongo!
- </message>
- </messages>
- </release>
- </grit>'''), '.')
-
- # Using the default rc_header format string.
- output = rc_header.FormatDefines(grd, grd.ShouldOutputAllResourceDefines(),
- grd.GetRcHeaderFormat())
- self.assertEqual(('#define IDR_LOGO 300\n'
- '#define IDS_GREETING 10000\n'
- '#define IDS_BONGO 10001\n'), ''.join(output))
-
- # Using a custom rc_header format string.
- grd.AssignRcHeaderFormat(
- '#define {textual_id} _Pragma("{textual_id}") {numeric_id}')
- output = rc_header.FormatDefines(grd, grd.ShouldOutputAllResourceDefines(),
- grd.GetRcHeaderFormat())
- self.assertEqual(('#define IDR_LOGO _Pragma("IDR_LOGO") 300\n'
- '#define IDS_GREETING _Pragma("IDS_GREETING") 10000\n'
- '#define IDS_BONGO _Pragma("IDS_BONGO") 10001\n'),
- ''.join(output))
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/rc_unittest.py b/grit/format/rc_unittest.py
deleted file mode 100644
index a38001b..0000000
--- a/grit/format/rc_unittest.py
+++ /dev/null
@@ -1,409 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.rc'''
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import tempfile
-import unittest
-import StringIO
-
-from grit import grd_reader
-from grit import util
-from grit.node import structure
-from grit.tool import build
-
-
-_PREAMBLE = '''\
-#include "resource.h"
-#include <winresrc.h>
-#ifdef IDC_STATIC
-#undef IDC_STATIC
-#endif
-#define IDC_STATIC (-1)
-'''
-
-
-class DummyOutput(object):
- def __init__(self, type, language, file = 'hello.gif'):
- self.type = type
- self.language = language
- self.file = file
- def GetType(self):
- return self.type
- def GetLanguage(self):
- return self.language
- def GetOutputFilename(self):
- return self.file
-
-class FormatRcUnittest(unittest.TestCase):
- def testMessages(self):
- root = util.ParseGrdForUnittest('''
- <messages>
- <message name="IDS_BTN_GO" desc="Button text" meaning="verb">Go!</message>
- <message name="IDS_GREETING" desc="Printed to greet the currently logged in user">
- Hello <ph name="USERNAME">%s<ex>Joi</ex></ph>, how are you doing today?
- </message>
- <message name="BONGO" desc="Flippo nippo">
- Howdie "Mr. Elephant", how are you doing? \'\'\'
- </message>
- <message name="IDS_WITH_LINEBREAKS">
-Good day sir,
-I am a bee
-Sting sting
- </message>
- </messages>
- ''')
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- self.assertEqual(_PREAMBLE + u'''\
-STRINGTABLE
-BEGIN
- IDS_BTN_GO "Go!"
- IDS_GREETING "Hello %s, how are you doing today?"
- BONGO "Howdie ""Mr. Elephant"", how are you doing? "
- IDS_WITH_LINEBREAKS "Good day sir,\\nI am a bee\\nSting sting"
-END''', output)
-
-
- def testRcSection(self):
- root = util.ParseGrdForUnittest('''
- <structures>
- <structure type="menu" name="IDC_KLONKMENU" file="grit\\testdata\klonk.rc" encoding="utf-16" />
- <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\testdata\klonk.rc" encoding="utf-16" />
- <structure type="version" name="VS_VERSION_INFO" file="grit\\testdata\klonk.rc" encoding="utf-16" />
- </structures>''')
- root.SetOutputLanguage('en')
- root.RunGatherers()
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- expected = _PREAMBLE + u'''\
-IDC_KLONKMENU MENU
-BEGIN
- POPUP "&File"
- BEGIN
- MENUITEM "E&xit", IDM_EXIT
- MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
- POPUP "gonk"
- BEGIN
- MENUITEM "Klonk && is [good]", ID_GONK_KLONKIS
- END
- END
- POPUP "&Help"
- BEGIN
- MENUITEM "&About ...", IDM_ABOUT
- END
-END
-
-IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "About"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- ICON IDI_KLONK,IDC_MYICON,14,9,20,20
- LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
- SS_NOPREFIX
- LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
- DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
- CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
- BS_AUTORADIOBUTTON,46,51,84,10
-END
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,1
- PRODUCTVERSION 1,0,0,1
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "FileDescription", "klonk Application"
- VALUE "FileVersion", "1, 0, 0, 1"
- VALUE "InternalName", "klonk"
- VALUE "LegalCopyright", "Copyright (C) 2005"
- VALUE "OriginalFilename", "klonk.exe"
- VALUE "ProductName", " klonk Application"
- VALUE "ProductVersion", "1, 0, 0, 1"
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END'''.strip()
- for expected_line, output_line in zip(expected.split(), output.split()):
- self.assertEqual(expected_line, output_line)
-
- def testRcIncludeStructure(self):
- root = util.ParseGrdForUnittest('''
- <structures>
- <structure type="tr_html" name="IDR_HTML" file="bingo.html"/>
- <structure type="tr_html" name="IDR_HTML2" file="bingo2.html"/>
- </structures>''', base_dir = '/temp')
- # We do not run gatherers as it is not needed and wouldn't find the file
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- expected = (_PREAMBLE +
- u'IDR_HTML HTML "%s"\n'
- u'IDR_HTML2 HTML "%s"'
- % (util.normpath('/temp/bingo.html').replace('\\', '\\\\'),
- util.normpath('/temp/bingo2.html').replace('\\', '\\\\')))
- # hackety hack to work on win32&lin
- output = re.sub('"[c-zC-Z]:', '"', output)
- self.assertEqual(expected, output)
-
- def testRcIncludeFile(self):
- root = util.ParseGrdForUnittest('''
- <includes>
- <include type="TXT" name="TEXT_ONE" file="bingo.txt"/>
- <include type="TXT" name="TEXT_TWO" file="bingo2.txt" filenameonly="true" />
- </includes>''', base_dir = '/temp')
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- expected = (_PREAMBLE +
- u'TEXT_ONE TXT "%s"\n'
- u'TEXT_TWO TXT "%s"'
- % (util.normpath('/temp/bingo.txt').replace('\\', '\\\\'),
- 'bingo2.txt'))
- # hackety hack to work on win32&lin
- output = re.sub('"[c-zC-Z]:', '"', output)
- self.assertEqual(expected, output)
-
- def testRcIncludeFlattenedHtmlFile(self):
- input_file = util.PathFromRoot('grit/testdata/include_test.html')
- output_file = '%s/HTML_FILE1_include_test.html' % tempfile.gettempdir()
- root = util.ParseGrdForUnittest('''
- <includes>
- <include name="HTML_FILE1" flattenhtml="true" file="%s" type="BINDATA" />
- </includes>''' % input_file)
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
- buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
-
- expected = (_PREAMBLE +
- u'HTML_FILE1 BINDATA "HTML_FILE1_include_test.html"')
- # hackety hack to work on win32&lin
- output = re.sub('"[c-zC-Z]:', '"', output)
- self.assertEqual(expected, output)
-
- file_contents = util.ReadFile(output_file, util.RAW_TEXT)
-
- # Check for the content added by the <include> tag.
- self.failUnless(file_contents.find('Hello Include!') != -1)
- # Check for the content that was removed by if tag.
- self.failUnless(file_contents.find('should be removed') == -1)
- # Check for the content that was kept in place by if.
- self.failUnless(file_contents.find('should be kept') != -1)
- self.failUnless(file_contents.find('in the middle...') != -1)
- self.failUnless(file_contents.find('at the end...') != -1)
- # Check for nested content that was kept
- self.failUnless(file_contents.find('nested true should be kept') != -1)
- self.failUnless(file_contents.find('silbing true should be kept') != -1)
- # Check for removed "<if>" and "</if>" tags.
- self.failUnless(file_contents.find('<if expr=') == -1)
- self.failUnless(file_contents.find('</if>') == -1)
-
-
- def testStructureNodeOutputfile(self):
- input_file = util.PathFromRoot('grit/testdata/simple.html')
- root = util.ParseGrdForUnittest('''\
- <structures>
- <structure type="tr_html" name="IDR_HTML" file="%s" />
- </structures>''' % input_file)
- struct, = root.GetChildrenOfType(structure.StructureNode)
- # We must run the gatherer since we'll be wanting the translation of the
- # file. The file exists in the location pointed to.
- root.SetOutputLanguage('en')
- root.RunGatherers()
-
- output_dir = tempfile.gettempdir()
- en_file = struct.FileForLanguage('en', output_dir)
- self.failUnless(en_file == input_file)
- fr_file = struct.FileForLanguage('fr', output_dir)
- self.failUnless(fr_file == os.path.join(output_dir, 'fr_simple.html'))
-
- contents = util.ReadFile(fr_file, util.RAW_TEXT)
-
- self.failUnless(contents.find('<p>') != -1) # should contain the markup
- self.failUnless(contents.find('Hello!') == -1) # should be translated
-
-
- def testChromeHtmlNodeOutputfile(self):
- input_file = util.PathFromRoot('grit/testdata/chrome_html.html')
- output_file = '%s/HTML_FILE1_chrome_html.html' % tempfile.gettempdir()
- root = util.ParseGrdForUnittest('''\
- <structures>
- <structure type="chrome_html" name="HTML_FILE1" file="%s" flattenhtml="true" />
- </structures>''' % input_file)
- struct, = root.GetChildrenOfType(structure.StructureNode)
- struct.gatherer.SetDefines({'scale_factors': '2x'})
- # We must run the gatherers since we'll be wanting the chrome_html output.
- # The file exists in the location pointed to.
- root.SetOutputLanguage('en')
- root.RunGatherers()
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en', output_file),
- buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- expected = (_PREAMBLE +
- u'HTML_FILE1 BINDATA "HTML_FILE1_chrome_html.html"')
- # hackety hack to work on win32&lin
- output = re.sub('"[c-zC-Z]:', '"', output)
- self.assertEqual(expected, output)
-
- file_contents = util.ReadFile(output_file, util.RAW_TEXT)
-
- # Check for the content added by the <include> tag.
- self.failUnless(file_contents.find('Hello Include!') != -1)
- # Check for inserted -webkit-image-set.
- self.failUnless(file_contents.find('content: -webkit-image-set') != -1)
-
-
- def testSubstitutionHtml(self):
- input_file = util.PathFromRoot('grit/testdata/toolbar_about.html')
- root = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3" base_dir=".">
- <release seq="1" allow_pseudo="False">
- <structures fallback_to_english="True">
- <structure type="tr_html" name="IDR_HTML" file="%s" expand_variables="true"/>
- </structures>
- </release>
- </grit>
- ''' % input_file), util.PathFromRoot('.'))
- root.SetOutputLanguage('ar')
- # We must run the gatherers since we'll be wanting the translation of the
- # file. The file exists in the location pointed to.
- root.RunGatherers()
-
- output_dir = tempfile.gettempdir()
- struct, = root.GetChildrenOfType(structure.StructureNode)
- ar_file = struct.FileForLanguage('ar', output_dir)
- self.failUnless(ar_file == os.path.join(output_dir,
- 'ar_toolbar_about.html'))
-
- contents = util.ReadFile(ar_file, util.RAW_TEXT)
-
- self.failUnless(contents.find('dir="RTL"') != -1)
-
-
- def testFallbackToEnglish(self):
- root = util.ParseGrdForUnittest('''\
- <structures fallback_to_english="True">
- <structure type="dialog" name="IDD_ABOUTBOX" file="grit\\testdata\klonk.rc" encoding="utf-16" />
- </structures>''', base_dir=util.PathFromRoot('.'))
- root.SetOutputLanguage('en')
- root.RunGatherers()
-
- buf = StringIO.StringIO()
- formatter = build.RcBuilder.ProcessNode(
- root, DummyOutput('rc_all', 'bingobongo'), buf)
- output = util.StripBlankLinesAndComments(buf.getvalue())
- self.assertEqual(_PREAMBLE + '''\
-IDD_ABOUTBOX DIALOGEX 22, 17, 230, 75
-STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
-CAPTION "About"
-FONT 8, "System", 0, 0, 0x0
-BEGIN
- ICON IDI_KLONK,IDC_MYICON,14,9,20,20
- LTEXT "klonk Version ""yibbee"" 1.0",IDC_STATIC,49,10,119,8,
- SS_NOPREFIX
- LTEXT "Copyright (C) 2005",IDC_STATIC,49,20,119,8
- DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP
- CONTROL "Jack ""Black"" Daniels",IDC_RADIO1,"Button",
- BS_AUTORADIOBUTTON,46,51,84,10
-END''', output)
-
-
- def testSubstitutionRc(self):
- root = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3"
- base_dir=".">
- <outputs>
- <output lang="en" type="rc_all" filename="grit\\testdata\klonk_resources.rc"/>
- </outputs>
- <release seq="1" allow_pseudo="False">
- <structures>
- <structure type="menu" name="IDC_KLONKMENU"
- file="grit\\testdata\klonk.rc" encoding="utf-16"
- expand_variables="true" />
- </structures>
- <messages>
- <message name="good" sub_variable="true">
- excellent
- </message>
- </messages>
- </release>
- </grit>
- '''), util.PathFromRoot('.'))
- root.SetOutputLanguage('en')
- root.RunGatherers()
-
- buf = StringIO.StringIO()
- build.RcBuilder.ProcessNode(root, DummyOutput('rc_all', 'en'), buf)
- output = buf.getvalue()
- self.assertEqual('''
-// This file is automatically generated by GRIT. Do not edit.
-
-#include "resource.h"
-#include <winresrc.h>
-#ifdef IDC_STATIC
-#undef IDC_STATIC
-#endif
-#define IDC_STATIC (-1)
-
-LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
-
-
-IDC_KLONKMENU MENU
-BEGIN
- POPUP "&File"
- BEGIN
- MENUITEM "E&xit", IDM_EXIT
- MENUITEM "This be ""Klonk"" me like", ID_FILE_THISBE
- POPUP "gonk"
- BEGIN
- MENUITEM "Klonk && is excellent", ID_GONK_KLONKIS
- END
- END
- POPUP "&Help"
- BEGIN
- MENUITEM "&About ...", IDM_ABOUT
- END
-END
-
-STRINGTABLE
-BEGIN
- good "excellent"
-END
-'''.strip(), output.strip())
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/format/repack.py b/grit/format/repack.py
deleted file mode 100755
index 337b7af..0000000
--- a/grit/format/repack.py
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
-A simple utility function to merge data pack files into a single data pack. See
-http://dev.chromium.org/developers/design-documents/linuxresourcesandlocalizedstrings
-for details about the file format.
-"""
-
-import optparse
-import os
-import sys
-
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import grit.format.data_pack
-
-
-def main(argv):
- parser = optparse.OptionParser('usage: %prog [options] <output_filename>'
- '<input_file1> [input_file2] ...')
- parser.add_option('--whitelist', action='store', dest='whitelist',
- default=None, help='Full path to the whitelist used to'
- 'filter output pak file resource IDs')
- options, file_paths = parser.parse_args(argv)
-
- if len(file_paths) < 2:
- parser.error('Please specify output and at least one input filenames')
-
- grit.format.data_pack.RePack(file_paths[0], file_paths[1:],
- whitelist_file=options.whitelist)
-
-if '__main__' == __name__:
- main(sys.argv[1:])
diff --git a/grit/format/resource_map.py b/grit/format/resource_map.py
deleted file mode 100644
index 37ac54a..0000000
--- a/grit/format/resource_map.py
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''This file contains item formatters for resource_map_header and
-resource_map_source files. A resource map is a mapping between resource names
-(string) and the internal resource ID.'''
-
-import os
-from functools import partial
-
-from grit import util
-
-
-def GetFormatter(type):
- if type == 'resource_map_header':
- return _FormatHeader
- elif type == 'resource_map_source':
- return partial(_FormatSource, _GetItemName)
- elif type == 'resource_file_map_source':
- return partial(_FormatSource, _GetItemPath)
-
-
-def GetMapName(root):
- '''Get the name of the resource map based on the header file name. E.g.,
- if our header filename is theme_resources.h, we name our resource map
- kThemeResourcesMap.
-
- |root| is the grd file root.'''
- outputs = root.GetOutputFiles()
- rc_header_file = None
- for output in outputs:
- if 'rc_header' == output.GetType():
- rc_header_file = output.GetFilename()
- if not rc_header_file:
- raise Exception('unable to find resource header filename')
- filename = os.path.splitext(os.path.split(rc_header_file)[1])[0]
- filename = filename[0].upper() + filename[1:]
- while filename.find('_') != -1:
- pos = filename.find('_')
- if pos >= len(filename):
- break
- filename = filename[:pos] + filename[pos + 1].upper() + filename[pos + 2:]
- return 'k' + filename
-
-
-def _FormatHeader(root, lang='en', output_dir='.'):
- '''Create the header file for the resource mapping. This file just declares
- an array of name/value pairs.'''
- return '''\
-// This file is automatically generated by GRIT. Do not edit.
-
-#include <stddef.h>
-
-#ifndef GRIT_RESOURCE_MAP_STRUCT_
-#define GRIT_RESOURCE_MAP_STRUCT_
-struct GritResourceMap {
- const char* const name;
- int value;
-};
-#endif // GRIT_RESOURCE_MAP_STRUCT_
-
-extern const GritResourceMap %(map_name)s[];
-extern const size_t %(map_name)sSize;
-''' % { 'map_name': GetMapName(root) }
-
-
-def _FormatSourceHeader(root):
- '''Create the header of the C++ source file for the resource mapping.'''
- rc_header_file = None
- map_header_file = None
- for output in root.GetOutputFiles():
- if 'rc_header' == output.GetType():
- rc_header_file = output.GetFilename()
- elif 'resource_map_header' == output.GetType():
- map_header_file = output.GetFilename()
- if not rc_header_file or not map_header_file:
- raise Exception('resource_map_source output type requires '
- 'resource_map_header and rc_header outputs')
- return '''\
-// This file is automatically generated by GRIT. Do not edit.
-
-#include "%(map_header_file)s"
-
-#include "base/basictypes.h"
-#include "%(rc_header_file)s"
-
-const GritResourceMap %(map_name)s[] = {
-''' % { 'map_header_file': map_header_file,
- 'rc_header_file': rc_header_file,
- 'map_name': GetMapName(root),
- }
-
-
-def _FormatSourceFooter(root):
- # Return the footer text.
- return '''\
-};
-
-const size_t %(map_name)sSize = arraysize(%(map_name)s);
-''' % { 'map_name': GetMapName(root) }
-
-
-def _FormatSource(get_key, root, lang, output_dir):
- from grit.format import rc_header
- from grit.node import include, structure, message
- yield _FormatSourceHeader(root)
- tids = rc_header.GetIds(root)
- seen = set()
- active_descendants = [item for item in root.ActiveDescendants()]
- output_all_resource_defines = root.ShouldOutputAllResourceDefines()
- for item in root:
- if not item.IsResourceMapSource():
- continue
- key = get_key(item)
- tid = item.attrs['name']
- if tid not in tids or key in seen:
- continue
- seen.add(key)
- if item.GeneratesResourceMapEntry(output_all_resource_defines,
- item in active_descendants):
- yield ' {"%s", %s},\n' % (key, tid)
- yield _FormatSourceFooter(root)
-
-
-def _GetItemName(item):
- return item.attrs['name']
-
-
-def _GetItemPath(item):
- return item.GetInputPath().replace("\\", "/")
diff --git a/grit/format/resource_map_unittest.py b/grit/format/resource_map_unittest.py
deleted file mode 100644
index 55de504..0000000
--- a/grit/format/resource_map_unittest.py
+++ /dev/null
@@ -1,279 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.format.resource_map'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import StringIO
-import unittest
-
-from grit import grd_reader
-from grit import util
-from grit.format import resource_map
-
-
-class FormatResourceMapUnittest(unittest.TestCase):
- def testFormatResourceMap(self):
- grd = grd_reader.Parse(StringIO.StringIO(
- '''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3"
- base_dir=".">
- <outputs>
- <output type="rc_header" filename="the_rc_header.h" />
- <output type="resource_map_header"
- filename="the_resource_map_header.h" />
- </outputs>
- <release seq="3">
- <structures first_id="300">
- <structure type="menu" name="IDC_KLONKMENU"
- file="grit\\testdata\\klonk.rc" encoding="utf-16" />
- </structures>
- <includes first_id="10000">
- <include type="foo" file="abc" name="IDS_FIRSTPRESENT" />
- <if expr="False">
- <include type="foo" file="def" name="IDS_MISSING" />
- </if>
- <if expr="lang != 'es'">
- <include type="foo" file="ghi" name="IDS_LANGUAGESPECIFIC" />
- </if>
- <if expr="lang == 'es'">
- <include type="foo" file="jkl" name="IDS_LANGUAGESPECIFIC" />
- </if>
- <include type="foo" file="mno" name="IDS_THIRDPRESENT" />
- </includes>
- </release>
- </grit>'''), util.PathFromRoot('.'))
- grd.SetOutputLanguage('en')
- grd.RunGatherers()
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
- self.assertEqual('''\
-#include <stddef.h>
-#ifndef GRIT_RESOURCE_MAP_STRUCT_
-#define GRIT_RESOURCE_MAP_STRUCT_
-struct GritResourceMap {
- const char* const name;
- int value;
-};
-#endif // GRIT_RESOURCE_MAP_STRUCT_
-extern const GritResourceMap kTheRcHeader[];
-extern const size_t kTheRcHeaderSize;''', output)
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
- self.assertEqual('''\
-#include "the_resource_map_header.h"
-#include "base/basictypes.h"
-#include "the_rc_header.h"
-const GritResourceMap kTheRcHeader[] = {
- {"IDC_KLONKMENU", IDC_KLONKMENU},
- {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT},
- {"IDS_MISSING", IDS_MISSING},
- {"IDS_LANGUAGESPECIFIC", IDS_LANGUAGESPECIFIC},
- {"IDS_THIRDPRESENT", IDS_THIRDPRESENT},
-};
-const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_file_map_source')(grd, 'en', '.')))
- self.assertEqual('''\
-#include "the_resource_map_header.h"
-#include "base/basictypes.h"
-#include "the_rc_header.h"
-const GritResourceMap kTheRcHeader[] = {
- {"grit/testdata/klonk.rc", IDC_KLONKMENU},
- {"abc", IDS_FIRSTPRESENT},
- {"def", IDS_MISSING},
- {"ghi", IDS_LANGUAGESPECIFIC},
- {"jkl", IDS_LANGUAGESPECIFIC},
- {"mno", IDS_THIRDPRESENT},
-};
-const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
-
- def testFormatResourceMapWithOutputAllEqualsFalseForStructures(self):
- grd = grd_reader.Parse(StringIO.StringIO(
- '''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3"
- base_dir="." output_all_resource_defines="false">
- <outputs>
- <output type="rc_header" filename="the_rc_header.h" />
- <output type="resource_map_header"
- filename="the_resource_map_header.h" />
- <output type="resource_map_source"
- filename="the_resource_map_header.cc" />
- </outputs>
- <release seq="3">
- <structures first_id="300">
- <structure type="chrome_scaled_image" name="IDR_KLONKMENU"
- file="foo.png" />
- <if expr="False">
- <structure type="chrome_scaled_image" name="IDR_MISSING"
- file="bar.png" />
- </if>
- </structures>
- </release>
- </grit>'''), util.PathFromRoot('.'))
- grd.SetOutputLanguage('en')
- grd.RunGatherers()
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
- self.assertEqual('''\
-#include <stddef.h>
-#ifndef GRIT_RESOURCE_MAP_STRUCT_
-#define GRIT_RESOURCE_MAP_STRUCT_
-struct GritResourceMap {
- const char* const name;
- int value;
-};
-#endif // GRIT_RESOURCE_MAP_STRUCT_
-extern const GritResourceMap kTheRcHeader[];
-extern const size_t kTheRcHeaderSize;''', output)
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
- self.assertEqual('''\
-#include "the_resource_map_header.h"
-#include "base/basictypes.h"
-#include "the_rc_header.h"
-const GritResourceMap kTheRcHeader[] = {
- {"IDR_KLONKMENU", IDR_KLONKMENU},
-};
-const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
- self.assertEqual('''\
-#include "the_resource_map_header.h"
-#include "base/basictypes.h"
-#include "the_rc_header.h"
-const GritResourceMap kTheRcHeader[] = {
- {"IDR_KLONKMENU", IDR_KLONKMENU},
-};
-const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
-
- def testFormatResourceMapWithOutputAllEqualsFalseForIncludes(self):
- grd = grd_reader.Parse(StringIO.StringIO(
- '''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3"
- base_dir="." output_all_resource_defines="false">
- <outputs>
- <output type="rc_header" filename="the_rc_header.h" />
- <output type="resource_map_header"
- filename="the_resource_map_header.h" />
- </outputs>
- <release seq="3">
- <structures first_id="300">
- <structure type="menu" name="IDC_KLONKMENU"
- file="grit\\testdata\\klonk.rc" encoding="utf-16" />
- </structures>
- <includes first_id="10000">
- <include type="foo" file="abc" name="IDS_FIRSTPRESENT" />
- <if expr="False">
- <include type="foo" file="def" name="IDS_MISSING" />
- </if>
- <include type="foo" file="mno" name="IDS_THIRDPRESENT" />
- </includes>
- </release>
- </grit>'''), util.PathFromRoot('.'))
- grd.SetOutputLanguage('en')
- grd.RunGatherers()
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
- self.assertEqual('''\
-#include <stddef.h>
-#ifndef GRIT_RESOURCE_MAP_STRUCT_
-#define GRIT_RESOURCE_MAP_STRUCT_
-struct GritResourceMap {
- const char* const name;
- int value;
-};
-#endif // GRIT_RESOURCE_MAP_STRUCT_
-extern const GritResourceMap kTheRcHeader[];
-extern const size_t kTheRcHeaderSize;''', output)
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
- self.assertEqual('''\
-#include "the_resource_map_header.h"
-#include "base/basictypes.h"
-#include "the_rc_header.h"
-const GritResourceMap kTheRcHeader[] = {
- {"IDC_KLONKMENU", IDC_KLONKMENU},
- {"IDS_FIRSTPRESENT", IDS_FIRSTPRESENT},
- {"IDS_THIRDPRESENT", IDS_THIRDPRESENT},
-};
-const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_file_map_source')(grd, 'en', '.')))
- self.assertEqual('''\
-#include "the_resource_map_header.h"
-#include "base/basictypes.h"
-#include "the_rc_header.h"
-const GritResourceMap kTheRcHeader[] = {
- {"grit/testdata/klonk.rc", IDC_KLONKMENU},
- {"abc", IDS_FIRSTPRESENT},
- {"mno", IDS_THIRDPRESENT},
-};
-const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
-
- def testFormatStringResourceMap(self):
- grd = grd_reader.Parse(StringIO.StringIO(
- '''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en" current_release="3"
- base_dir=".">
- <outputs>
- <output type="rc_header" filename="the_rc_header.h" />
- <output type="resource_map_header" filename="the_rc_map_header.h" />
- <output type="resource_map_source" filename="the_rc_map_source.cc" />
- </outputs>
- <release seq="1" allow_pseudo="false">
- <messages fallback_to_english="true">
- <message name="IDS_PRODUCT_NAME" desc="The application name">
- Application
- </message>
- <if expr="True">
- <message name="IDS_DEFAULT_TAB_TITLE_TITLE_CASE"
- desc="In Title Case: The default title in a tab.">
- New Tab
- </message>
- </if>
- <if expr="False">
- <message name="IDS_DEFAULT_TAB_TITLE"
- desc="The default title in a tab.">
- New tab
- </message>
- </if>
- </messages>
- </release>
- </grit>'''), util.PathFromRoot('.'))
- grd.SetOutputLanguage('en')
- grd.RunGatherers()
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_header')(grd, 'en', '.')))
- self.assertEqual('''\
-#include <stddef.h>
-#ifndef GRIT_RESOURCE_MAP_STRUCT_
-#define GRIT_RESOURCE_MAP_STRUCT_
-struct GritResourceMap {
- const char* const name;
- int value;
-};
-#endif // GRIT_RESOURCE_MAP_STRUCT_
-extern const GritResourceMap kTheRcHeader[];
-extern const size_t kTheRcHeaderSize;''', output)
- output = util.StripBlankLinesAndComments(''.join(
- resource_map.GetFormatter('resource_map_source')(grd, 'en', '.')))
- self.assertEqual('''\
-#include "the_rc_map_header.h"
-#include "base/basictypes.h"
-#include "the_rc_header.h"
-const GritResourceMap kTheRcHeader[] = {
- {"IDS_PRODUCT_NAME", IDS_PRODUCT_NAME},
- {"IDS_DEFAULT_TAB_TITLE_TITLE_CASE", IDS_DEFAULT_TAB_TITLE_TITLE_CASE},
-};
-const size_t kTheRcHeaderSize = arraysize(kTheRcHeader);''', output)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/gather/__init__.py b/grit/gather/__init__.py
deleted file mode 100644
index e52734a..0000000
--- a/grit/gather/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Module grit.gather
-'''
-
-pass
diff --git a/grit/gather/admin_template.py b/grit/gather/admin_template.py
deleted file mode 100644
index edf783b..0000000
--- a/grit/gather/admin_template.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Gatherer for administrative template files.
-'''
-
-import re
-
-from grit.gather import regexp
-from grit import exception
-from grit import lazy_re
-
-
-class MalformedAdminTemplateException(exception.Base):
- '''This file doesn't look like a .adm file to me.'''
- pass
-
-
-class AdmGatherer(regexp.RegexpGatherer):
- '''Gatherer for the translateable portions of an admin template.
-
- This gatherer currently makes the following assumptions:
- - there is only one [strings] section and it is always the last section
- of the file
- - translateable strings do not need to be escaped.
- '''
-
- # Finds the strings section as the group named 'strings'
- _STRINGS_SECTION = lazy_re.compile(
- '(?P<first_part>.+^\[strings\])(?P<strings>.+)\Z',
- re.MULTILINE | re.DOTALL)
-
- # Finds the translateable sections from within the [strings] section.
- _TRANSLATEABLES = lazy_re.compile(
- '^\s*[A-Za-z0-9_]+\s*=\s*"(?P<text>.+)"\s*$',
- re.MULTILINE)
-
- def Escape(self, text):
- return text.replace('\n', '\\n')
-
- def UnEscape(self, text):
- return text.replace('\\n', '\n')
-
- def Parse(self):
- if self.have_parsed_:
- return
- self.have_parsed_ = True
-
- self.text_ = self._LoadInputFile().strip()
- m = self._STRINGS_SECTION.match(self.text_)
- if not m:
- raise MalformedAdminTemplateException()
- # Add the first part, which is all nontranslateable, to the skeleton
- self._AddNontranslateableChunk(m.group('first_part'))
- # Then parse the rest using the _TRANSLATEABLES regexp.
- self._RegExpParse(self._TRANSLATEABLES, m.group('strings'))
-
- def GetTextualIds(self):
- return [self.extkey]
diff --git a/grit/gather/admin_template_unittest.py b/grit/gather/admin_template_unittest.py
deleted file mode 100644
index 6c7e56b..0000000
--- a/grit/gather/admin_template_unittest.py
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for the admin template gatherer.'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import StringIO
-import tempfile
-import unittest
-
-from grit.gather import admin_template
-from grit import util
-from grit import grd_reader
-from grit import grit_runner
-from grit.tool import build
-
-
-class AdmGathererUnittest(unittest.TestCase):
- def testParsingAndTranslating(self):
- pseudofile = StringIO.StringIO(
- 'bingo bongo\n'
- 'ding dong\n'
- '[strings] \n'
- 'whatcha="bingo bongo"\n'
- 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
- gatherer = admin_template.AdmGatherer(pseudofile)
- gatherer.Parse()
- self.failUnless(len(gatherer.GetCliques()) == 2)
- self.failUnless(gatherer.GetCliques()[1].GetMessage().GetRealContent() ==
- 'bingolabongola "the wise" fingulafongula')
-
- translation = gatherer.Translate('en')
- self.failUnless(translation == gatherer.GetText().strip())
-
- def testErrorHandling(self):
- pseudofile = StringIO.StringIO(
- 'bingo bongo\n'
- 'ding dong\n'
- 'whatcha="bingo bongo"\n'
- 'gotcha = "bingolabongola "the wise" fingulafongula" \n')
- gatherer = admin_template.AdmGatherer(pseudofile)
- self.assertRaises(admin_template.MalformedAdminTemplateException,
- gatherer.Parse)
-
- _TRANSLATABLES_FROM_FILE = (
- 'Google', 'Google Desktop', 'Preferences',
- 'Controls Google Desktop preferences',
- 'Indexing and Capture Control',
- 'Controls what files, web pages, and other content will be indexed by Google Desktop.',
- 'Prevent indexing of email',
- # there are lots more but we don't check any further
- )
-
- def VerifyCliquesFromAdmFile(self, cliques):
- self.failUnless(len(cliques) > 20)
- for clique, expected in zip(cliques, self._TRANSLATABLES_FROM_FILE):
- text = clique.GetMessage().GetRealContent()
- self.failUnless(text == expected)
-
- def testFromFile(self):
- fname = util.PathFromRoot('grit/testdata/GoogleDesktop.adm')
- gatherer = admin_template.AdmGatherer(fname)
- gatherer.Parse()
- cliques = gatherer.GetCliques()
- self.VerifyCliquesFromAdmFile(cliques)
-
- def MakeGrd(self):
- grd = grd_reader.Parse(StringIO.StringIO('''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="2" source_lang_id="en-US" current_release="3">
- <release seq="3">
- <structures>
- <structure type="admin_template" name="IDAT_GOOGLE_DESKTOP_SEARCH"
- file="GoogleDesktop.adm" exclude_from_rc="true" />
- <structure type="txt" name="BINGOBONGO"
- file="README.txt" exclude_from_rc="true" />
- </structures>
- </release>
- <outputs>
- <output filename="de_res.rc" type="rc_all" lang="de" />
- </outputs>
- </grit>'''), util.PathFromRoot('grit/testdata'))
- grd.SetOutputLanguage('en')
- grd.RunGatherers()
- return grd
-
- def testInGrd(self):
- grd = self.MakeGrd()
- cliques = grd.children[0].children[0].children[0].GetCliques()
- self.VerifyCliquesFromAdmFile(cliques)
-
- def testFileIsOutput(self):
- grd = self.MakeGrd()
- dirname = tempfile.mkdtemp()
- try:
- tool = build.RcBuilder()
- tool.o = grit_runner.Options()
- tool.output_directory = dirname
- tool.res = grd
- tool.Process()
-
- self.failUnless(os.path.isfile(
- os.path.join(dirname, 'de_GoogleDesktop.adm')))
- self.failUnless(os.path.isfile(
- os.path.join(dirname, 'de_README.txt')))
- finally:
- for f in os.listdir(dirname):
- os.unlink(os.path.join(dirname, f))
- os.rmdir(dirname)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/gather/chrome_html.py b/grit/gather/chrome_html.py
deleted file mode 100644
index e7469bf..0000000
--- a/grit/gather/chrome_html.py
+++ /dev/null
@@ -1,360 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Prepares a Chrome HTML file by inlining resources and adding references to
-high DPI resources and removing references to unsupported scale factors.
-
-This is a small gatherer that takes a HTML file, looks for src attributes
-and inlines the specified file, producing one HTML file with no external
-dependencies. It recursively inlines the included files. When inlining CSS
-image files this script also checks for the existence of high DPI versions
-of the inlined file including those on relevant platforms. Unsupported scale
-factors are also removed from existing image sets to support explicitly
-referencing all available images.
-"""
-
-import os
-import re
-
-from grit import lazy_re
-from grit import util
-from grit.format import html_inline
-from grit.gather import interface
-
-
-# Distribution string to replace with distribution.
-DIST_SUBSTR = '%DISTRIBUTION%'
-
-
-# Matches a chrome theme source URL.
-_THEME_SOURCE = lazy_re.compile(
- '(?P<baseurl>chrome://theme/IDR_[A-Z0-9_]*)(?P<query>\?.*)?')
-# Pattern for matching CSS url() function.
-_CSS_URL_PATTERN = 'url\((?P<quote>"|\'|)(?P<filename>[^"\'()]*)(?P=quote)\)'
-# Matches CSS url() functions with the capture group 'filename'.
-_CSS_URL = lazy_re.compile(_CSS_URL_PATTERN)
-# Matches one or more CSS image urls used in given properties.
-_CSS_IMAGE_URLS = lazy_re.compile(
- '(?P<attribute>content|background|[\w-]*-image):\s*' +
- '(?P<urls>(' + _CSS_URL_PATTERN + '\s*,?\s*)+)')
-# Matches CSS image sets.
-_CSS_IMAGE_SETS = lazy_re.compile(
- '(?P<attribute>content|background|[\w-]*-image):[ ]*' +
- '-webkit-image-set\((?P<images>' +
- '(\s*,?\s*url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*[0-9.]*x)*)\)',
- re.MULTILINE)
-# Matches a single image in a CSS image set with the capture group scale.
-_CSS_IMAGE_SET_IMAGE = lazy_re.compile('\s*,?\s*' +
- 'url\((?P<quote>"|\'|)[^"\'()]*(?P=quote)\)[ ]*(?P<scale>[0-9.]*x)',
- re.MULTILINE)
-_HTML_IMAGE_SRC = lazy_re.compile(
- '<img[^>]+src=\"(?P<filename>[^">]*)\"[^>]*>')
-
-def GetImageList(
- base_path, filename, scale_factors, distribution,
- filename_expansion_function=None):
- """Generate the list of images which match the provided scale factors.
-
- Takes an image filename and checks for files of the same name in folders
- corresponding to the supported scale factors. If the file is from a
- chrome://theme/ source, inserts supported @Nx scale factors as high DPI
- versions.
-
- Args:
- base_path: path to look for relative file paths in
- filename: name of the base image file
- scale_factors: a list of the supported scale factors (i.e. ['2x'])
- distribution: string that should replace %DISTRIBUTION%
-
- Returns:
- array of tuples containing scale factor and image (i.e.
- [('1x', 'image.png'), ('2x', '2x/image.png')]).
- """
- # Any matches for which a chrome URL handler will serve all scale factors
- # can simply request all scale factors.
- theme_match = _THEME_SOURCE.match(filename)
- if theme_match:
- images = [('1x', filename)]
- for scale_factor in scale_factors:
- scale_filename = "%s@%s" % (theme_match.group('baseurl'), scale_factor)
- if theme_match.group('query'):
- scale_filename += theme_match.group('query')
- images.append((scale_factor, scale_filename))
- return images
-
- if filename.find(':') != -1:
- # filename is probably a URL, only return filename itself.
- return [('1x', filename)]
-
- filename = filename.replace(DIST_SUBSTR, distribution)
- if filename_expansion_function:
- filename = filename_expansion_function(filename)
- filepath = os.path.join(base_path, filename)
- images = [('1x', filename)]
-
- for scale_factor in scale_factors:
- # Check for existence of file and add to image set.
- scale_path = os.path.split(os.path.join(base_path, filename))
- scale_image_path = os.path.join(scale_path[0], scale_factor, scale_path[1])
- if os.path.isfile(scale_image_path):
- # HTML/CSS always uses forward slashed paths.
- scale_image_name = re.sub('(?P<path>(.*/)?)(?P<file>[^/]*)',
- '\\g<path>' + scale_factor + '/\\g<file>',
- filename)
- images.append((scale_factor, scale_image_name))
- return images
-
-
-def GenerateImageSet(images, quote):
- """Generates a -webkit-image-set for the provided list of images.
-
- Args:
- images: an array of tuples giving scale factor and file path
- (i.e. [('1x', 'image.png'), ('2x', '2x/image.png')]).
- quote: a string giving the quotation character to use (i.e. "'")
-
- Returns:
- string giving a -webkit-image-set rule referencing the provided images.
- (i.e. '-webkit-image-set(url('image.png') 1x, url('2x/image.png') 2x)')
- """
- imageset = []
- for (scale_factor, filename) in images:
- imageset.append("url(%s%s%s) %s" % (quote, filename, quote, scale_factor))
- return "-webkit-image-set(%s)" % (', '.join(imageset))
-
-
-def UrlToImageSet(
- src_match, base_path, scale_factors, distribution,
- filename_expansion_function=None):
- """Regex replace function which replaces url() with -webkit-image-set.
-
- Takes a regex match for url('path'). If the file is local, checks for
- files of the same name in folders corresponding to the supported scale
- factors. If the file is from a chrome://theme/ source, inserts the
- supported @Nx scale factor request. In either case inserts a
- -webkit-image-set rule to fetch the appropriate image for the current
- scale factor.
-
- Args:
- src_match: regex match object from _CSS_URLS
- base_path: path to look for relative file paths in
- scale_factors: a list of the supported scale factors (i.e. ['2x'])
- distribution: string that should replace %DISTRIBUTION%.
-
- Returns:
- string
- """
- quote = src_match.group('quote')
- filename = src_match.group('filename')
- image_list = GetImageList(
- base_path, filename, scale_factors, distribution,
- filename_expansion_function=filename_expansion_function)
-
- # Don't modify the source if there is only one image.
- if len(image_list) == 1:
- return src_match.group(0)
-
- return GenerateImageSet(image_list, quote)
-
-
-def InsertImageSet(
- src_match, base_path, scale_factors, distribution,
- filename_expansion_function=None):
- """Regex replace function which inserts -webkit-image-set rules.
-
- Takes a regex match for `property: url('path')[, url('path')]+`.
- Replaces one or more occurances of the match with image set rules.
-
- Args:
- src_match: regex match object from _CSS_IMAGE_URLS
- base_path: path to look for relative file paths in
- scale_factors: a list of the supported scale factors (i.e. ['2x'])
- distribution: string that should replace %DISTRIBUTION%.
-
- Returns:
- string
- """
- attr = src_match.group('attribute')
- urls = _CSS_URL.sub(
- lambda m: UrlToImageSet(m, base_path, scale_factors, distribution,
- filename_expansion_function),
- src_match.group('urls'))
-
- return "%s: %s" % (attr, urls)
-
-
-def InsertImageStyle(
- src_match, base_path, scale_factors, distribution,
- filename_expansion_function=None):
- """Regex replace function which adds a content style to an <img>.
-
- Takes a regex match from _HTML_IMAGE_SRC and replaces the attribute with a CSS
- style which defines the image set.
- """
- filename = src_match.group('filename')
- image_list = GetImageList(
- base_path, filename, scale_factors, distribution,
- filename_expansion_function=filename_expansion_function)
-
- # Don't modify the source if there is only one image or image already defines
- # a style.
- if src_match.group(0).find(" style=\"") != -1 or len(image_list) == 1:
- return src_match.group(0)
-
- return "%s style=\"content: %s;\">" % (src_match.group(0)[:-1],
- GenerateImageSet(image_list, "'"))
-
-
-def InsertImageSets(
- filepath, text, scale_factors, distribution,
- filename_expansion_function=None):
- """Helper function that adds references to external images available in any of
- scale_factors in CSS backgrounds.
- """
- # Add high DPI urls for css attributes: content, background,
- # or *-image or <img src="foo">.
- return _CSS_IMAGE_URLS.sub(
- lambda m: InsertImageSet(
- m, filepath, scale_factors, distribution,
- filename_expansion_function=filename_expansion_function),
- _HTML_IMAGE_SRC.sub(
- lambda m: InsertImageStyle(
- m, filepath, scale_factors, distribution,
- filename_expansion_function=filename_expansion_function),
- text)).decode('utf-8').encode('utf-8')
-
-
-def RemoveImagesNotIn(scale_factors, src_match):
- """Regex replace function which removes images for scale factors not in
- scale_factors.
-
- Takes a regex match for _CSS_IMAGE_SETS. For each image in the group images,
- checks if this scale factor is in scale_factors and if not, removes it.
-
- Args:
- scale_factors: a list of the supported scale factors (i.e. ['1x', '2x'])
- src_match: regex match object from _CSS_IMAGE_SETS
-
- Returns:
- string
- """
- attr = src_match.group('attribute')
- images = _CSS_IMAGE_SET_IMAGE.sub(
- lambda m: m.group(0) if m.group('scale') in scale_factors else '',
- src_match.group('images'))
- return "%s: -webkit-image-set(%s)" % (attr, images)
-
-
-def RemoveImageSetImages(text, scale_factors):
- """Helper function which removes images in image sets not in the list of
- supported scale_factors.
- """
- return _CSS_IMAGE_SETS.sub(
- lambda m: RemoveImagesNotIn(scale_factors, m), text)
-
-
-def ProcessImageSets(
- filepath, text, scale_factors, distribution,
- filename_expansion_function=None):
- """Helper function that adds references to external images available in other
- scale_factors and removes images from image-sets in unsupported scale_factors.
- """
- # Explicitly add 1x to supported scale factors so that it is not removed.
- supported_scale_factors = ['1x']
- supported_scale_factors.extend(scale_factors)
- return InsertImageSets(
- filepath,
- RemoveImageSetImages(text, supported_scale_factors),
- scale_factors,
- distribution,
- filename_expansion_function=filename_expansion_function)
-
-
-class ChromeHtml(interface.GathererBase):
- """Represents an HTML document processed for Chrome WebUI.
-
- HTML documents used in Chrome WebUI have local resources inlined and
- automatically insert references to high DPI assets used in CSS properties
- with the use of the -webkit-image-set value. References to unsupported scale
- factors in image sets are also removed. This does not generate any
- translateable messages and instead generates a single DataPack resource.
- """
-
- def __init__(self, *args, **kwargs):
- super(ChromeHtml, self).__init__(*args, **kwargs)
- self.allow_external_script_ = False
- self.flatten_html_ = False
- # 1x resources are implicitly already in the source and do not need to be
- # added.
- self.scale_factors_ = []
- self.filename_expansion_function = None
-
- def SetAttributes(self, attrs):
- self.allow_external_script_ = ('allowexternalscript' in attrs and
- attrs['allowexternalscript'] == 'true')
- self.flatten_html_ = ('flattenhtml' in attrs and
- attrs['flattenhtml'] == 'true')
-
- def SetDefines(self, defines):
- if 'scale_factors' in defines:
- self.scale_factors_ = defines['scale_factors'].split(',')
-
- def GetText(self):
- """Returns inlined text of the HTML document."""
- return self.inlined_text_
-
- def GetTextualIds(self):
- return [self.extkey]
-
- def GetData(self, lang, encoding):
- """Returns inlined text of the HTML document."""
- return self.inlined_text_
-
- def GetHtmlResourceFilenames(self):
- """Returns a set of all filenames inlined by this file."""
- if self.flatten_html_:
- return html_inline.GetResourceFilenames(
- self.grd_node.ToRealPath(self.GetInputPath()),
- allow_external_script=self.allow_external_script_,
- rewrite_function=lambda fp, t, d: ProcessImageSets(
- fp, t, self.scale_factors_, d,
- filename_expansion_function=self.filename_expansion_function),
- filename_expansion_function=self.filename_expansion_function)
- return []
-
- def Translate(self, lang, pseudo_if_not_available=True,
- skeleton_gatherer=None, fallback_to_english=False):
- """Returns this document translated."""
- return self.inlined_text_
-
- def SetFilenameExpansionFunction(self, fn):
- self.filename_expansion_function = fn
-
- def Parse(self):
- """Parses and inlines the represented file."""
-
- filename = self.GetInputPath()
- if self.filename_expansion_function:
- filename = self.filename_expansion_function(filename)
- # Hack: some unit tests supply an absolute path and no root node.
- if not os.path.isabs(filename):
- filename = self.grd_node.ToRealPath(filename)
- if self.flatten_html_:
- self.inlined_text_ = html_inline.InlineToString(
- filename,
- self.grd_node,
- allow_external_script = self.allow_external_script_,
- rewrite_function=lambda fp, t, d: ProcessImageSets(
- fp, t, self.scale_factors_, d,
- filename_expansion_function=self.filename_expansion_function),
- filename_expansion_function=self.filename_expansion_function)
- else:
- distribution = html_inline.GetDistribution()
- self.inlined_text_ = ProcessImageSets(
- os.path.dirname(filename),
- util.ReadFile(filename, 'utf-8'),
- self.scale_factors_,
- distribution,
- filename_expansion_function=self.filename_expansion_function)
diff --git a/grit/gather/chrome_html_unittest.py b/grit/gather/chrome_html_unittest.py
deleted file mode 100644
index 9b17c11..0000000
--- a/grit/gather/chrome_html_unittest.py
+++ /dev/null
@@ -1,523 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.gather.chrome_html'''
-
-
-import os
-import re
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import unittest
-
-from grit import lazy_re
-from grit import util
-from grit.gather import chrome_html
-
-
-_NEW_LINE = lazy_re.compile('(\r\n|\r|\n)', re.MULTILINE)
-
-
-def StandardizeHtml(text):
- '''Standardizes the newline format and png mime type in Html text.'''
- return _NEW_LINE.sub('\n', text).replace('data:image/x-png;',
- 'data:image/png;')
-
-
-class ChromeHtmlUnittest(unittest.TestCase):
- '''Unit tests for ChromeHtml.'''
-
- def testFileResources(self):
- '''Tests inlined image file resources with available high DPI assets.'''
-
- tmp_dir = util.TempDir({
- 'index.html': '''
- <!DOCTYPE HTML>
- <html>
- <head>
- <link rel="stylesheet" href="test.css">
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- ''',
-
- 'test.css': '''
- .image {
- background: url('test.png');
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- '1.4x/test.png': '1.4x PNG DATA',
-
- '1.8x/test.png': '1.8x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
- html.SetDefines({'scale_factors': '1.4x,1.8x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- <!DOCTYPE HTML>
- <html>
- <head>
- <style>
- .image {
- background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
- }
- </style>
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesImageTag(self):
- '''Tests inlined image file resources with available high DPI assets on
- an image tag.'''
-
- tmp_dir = util.TempDir({
- 'index.html': '''
- <!DOCTYPE HTML>
- <html>
- <body>
- <img id="foo" src="test.png">
- </body>
- </html>
- ''',
-
- 'test.png': 'PNG DATA',
-
- '2x/test.png': '2x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- <!DOCTYPE HTML>
- <html>
- <body>
- <img id="foo" src="data:image/png;base64,UE5HIERBVEE=" style="content: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MnggUE5HIERBVEE=') 2x);">
- </body>
- </html>
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesNoFlatten(self):
- '''Tests non-inlined image file resources with available high DPI assets.'''
-
- tmp_dir = util.TempDir({
- 'test.css': '''
- .image {
- background: url('test.png');
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- '1.4x/test.png': '1.4x PNG DATA',
-
- '1.8x/test.png': '1.8x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
- html.SetDefines({'scale_factors': '1.4x,1.8x'})
- html.SetAttributes({'flattenhtml': 'false'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- .image {
- background: -webkit-image-set(url('test.png') 1x, url('1.4x/test.png') 1.4x, url('1.8x/test.png') 1.8x);
- }
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesDoubleQuotes(self):
- '''Tests inlined image file resources if url() filename is double quoted.'''
-
- tmp_dir = util.TempDir({
- 'test.css': '''
- .image {
- background: url("test.png");
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- '2x/test.png': '2x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- .image {
- background: -webkit-image-set(url("data:image/png;base64,UE5HIERBVEE=") 1x, url("data:image/png;base64,MnggUE5HIERBVEE=") 2x);
- }
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesNoQuotes(self):
- '''Tests inlined image file resources when url() filename is unquoted.'''
-
- tmp_dir = util.TempDir({
- 'test.css': '''
- .image {
- background: url(test.png);
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- '2x/test.png': '2x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- .image {
- background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
- }
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesNoFile(self):
- '''Tests inlined image file resources without available high DPI assets.'''
-
- tmp_dir = util.TempDir({
- 'index.html': '''
- <!DOCTYPE HTML>
- <html>
- <head>
- <link rel="stylesheet" href="test.css">
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- ''',
-
- 'test.css': '''
- .image {
- background: url('test.png');
- }
- ''',
-
- 'test.png': 'PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- <!DOCTYPE HTML>
- <html>
- <head>
- <style>
- .image {
- background: url('data:image/png;base64,UE5HIERBVEE=');
- }
- </style>
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesMultipleBackgrounds(self):
- '''Tests inlined image file resources with two url()s.'''
-
- tmp_dir = util.TempDir({
- 'test.css': '''
- .image {
- background: url(test.png), url(test.png);
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- '2x/test.png': '2x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- .image {
- background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x), -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
- }
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesMultipleBackgroundsWithNewline1(self):
- '''Tests inlined image file resources with line break after first url().'''
-
- tmp_dir = util.TempDir({
- 'test.css': '''
- .image {
- background: url(test.png),
- url(test.png);
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- '2x/test.png': '2x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- .image {
- background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x),
- -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
- }
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesMultipleBackgroundsWithNewline2(self):
- '''Tests inlined image file resources with line break before first url()
- and before second url().'''
-
- tmp_dir = util.TempDir({
- 'test.css': '''
- .image {
- background:
- url(test.png),
- url(test.png);
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- '2x/test.png': '2x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- .image {
- background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x),
- -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
- }
- '''))
- tmp_dir.CleanUp()
-
- def testFileResourcesCRLF(self):
- '''Tests inlined image file resource when url() is preceded by a Windows
- style line break.'''
-
- tmp_dir = util.TempDir({
- 'test.css': '''
- .image {
- background:\r\nurl(test.png);
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- '2x/test.png': '2x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('test.css'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- .image {
- background: -webkit-image-set(url(data:image/png;base64,UE5HIERBVEE=) 1x, url(data:image/png;base64,MnggUE5HIERBVEE=) 2x);
- }
- '''))
- tmp_dir.CleanUp()
-
- def testThemeResources(self):
- '''Tests inserting high DPI chrome://theme references.'''
-
- tmp_dir = util.TempDir({
- 'index.html': '''
- <!DOCTYPE HTML>
- <html>
- <head>
- <link rel="stylesheet" href="test.css">
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- ''',
-
- 'test.css': '''
- .image {
- background: url('chrome://theme/IDR_RESOURCE_NAME');
- content: url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q?$1');
- }
- ''',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
- html.SetDefines({'scale_factors': '2x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- <!DOCTYPE HTML>
- <html>
- <head>
- <style>
- .image {
- background: -webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME') 1x, url('chrome://theme/IDR_RESOURCE_NAME@2x') 2x);
- content: -webkit-image-set(url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q?$1') 1x, url('chrome://theme/IDR_RESOURCE_NAME_WITH_Q@2x?$1') 2x);
- }
- </style>
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- '''))
- tmp_dir.CleanUp()
-
- def testRemoveUnsupportedScale(self):
- '''Tests removing an unsupported scale factor from an explicit image-set.'''
-
- tmp_dir = util.TempDir({
- 'index.html': '''
- <!DOCTYPE HTML>
- <html>
- <head>
- <link rel="stylesheet" href="test.css">
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- ''',
-
- 'test.css': '''
- .image {
- background: -webkit-image-set(url('test.png') 1x,
- url('test1.4.png') 1.4x,
- url('test1.8.png') 1.8x);
- }
- ''',
-
- 'test.png': 'PNG DATA',
-
- 'test1.4.png': '1.4x PNG DATA',
-
- 'test1.8.png': '1.8x PNG DATA',
- })
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
- html.SetDefines({'scale_factors': '1.8x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- <!DOCTYPE HTML>
- <html>
- <head>
- <style>
- .image {
- background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x,
- url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
- }
- </style>
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- '''))
- tmp_dir.CleanUp()
-
- def testExpandVariablesInFilename(self):
- '''
- Tests variable substitution in filenames while flattening images
- with multiple scale factors.
- '''
-
- tmp_dir = util.TempDir({
- 'index.html': '''
- <!DOCTYPE HTML>
- <html>
- <head>
- <link rel="stylesheet" href="test.css">
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- ''',
-
- 'test.css': '''
- .image {
- background: url('test[WHICH].png');
- }
- ''',
-
- 'test1.png': 'PNG DATA',
- '1.4x/test1.png': '1.4x PNG DATA',
- '1.8x/test1.png': '1.8x PNG DATA',
- })
-
- def replacer(var, repl):
- return lambda filename: filename.replace('[%s]' % var, repl)
-
- html = chrome_html.ChromeHtml(tmp_dir.GetPath('index.html'))
- html.SetDefines({'scale_factors': '1.4x,1.8x'})
- html.SetAttributes({'flattenhtml': 'true'})
- html.SetFilenameExpansionFunction(replacer('WHICH', '1'));
- html.Parse()
- self.failUnlessEqual(StandardizeHtml(html.GetData('en', 'utf-8')),
- StandardizeHtml('''
- <!DOCTYPE HTML>
- <html>
- <head>
- <style>
- .image {
- background: -webkit-image-set(url('data:image/png;base64,UE5HIERBVEE=') 1x, url('data:image/png;base64,MS40eCBQTkcgREFUQQ==') 1.4x, url('data:image/png;base64,MS44eCBQTkcgREFUQQ==') 1.8x);
- }
- </style>
- </head>
- <body>
- <!-- Don't need a body. -->
- </body>
- </html>
- '''))
- tmp_dir.CleanUp()
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/gather/chrome_scaled_image.py b/grit/gather/chrome_scaled_image.py
deleted file mode 100644
index 864c9bd..0000000
--- a/grit/gather/chrome_scaled_image.py
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Gatherer for <structure type="chrome_scaled_image">.
-'''
-
-import os
-import struct
-
-from grit import exception
-from grit import lazy_re
-from grit import util
-from grit.gather import interface
-
-
-_PNG_SCALE_CHUNK = '\0\0\0\0csCl\xc1\x30\x60\x4d'
-
-
-def _RescaleImage(data, from_scale, to_scale):
- if from_scale != to_scale:
- assert from_scale == 100
- # Rather than rescaling the image we add a custom chunk directing Chrome to
- # rescale it on load. Just append it to the PNG data since
- # _MoveSpecialChunksToFront will move it later anyway.
- data += _PNG_SCALE_CHUNK
- return data
-
-
-_PNG_MAGIC = '\x89PNG\r\n\x1a\n'
-
-'''Mandatory first chunk in order for the png to be valid.'''
-_FIRST_CHUNK = 'IHDR'
-
-'''Special chunks to move immediately after the IHDR chunk. (so that the PNG
-remains valid.)
-'''
-_SPECIAL_CHUNKS = frozenset('csCl npTc'.split())
-
-'''Any ancillary chunk not in this list is deleted from the PNG.'''
-_ANCILLARY_CHUNKS_TO_LEAVE = frozenset(
- 'bKGD cHRM gAMA iCCP pHYs sBIT sRGB tRNS'.split())
-
-
-def _MoveSpecialChunksToFront(data):
- '''Move special chunks immediately after the IHDR chunk (so that the PNG
- remains valid). Also delete ancillary chunks that are not on our whitelist.
- '''
- first = [_PNG_MAGIC]
- special_chunks = []
- rest = []
- for chunk in _ChunkifyPNG(data):
- type = chunk[4:8]
- critical = type < 'a'
- if type == _FIRST_CHUNK:
- first.append(chunk)
- elif type in _SPECIAL_CHUNKS:
- special_chunks.append(chunk)
- elif critical or type in _ANCILLARY_CHUNKS_TO_LEAVE:
- rest.append(chunk)
- return ''.join(first + special_chunks + rest)
-
-
-def _ChunkifyPNG(data):
- '''Given a PNG image, yield its chunks in order.'''
- assert data.startswith(_PNG_MAGIC)
- pos = 8
- while pos != len(data):
- length = 12 + struct.unpack_from('>I', data, pos)[0]
- assert 12 <= length <= len(data) - pos
- yield data[pos:pos+length]
- pos += length
-
-
-def _MakeBraceGlob(strings):
- '''Given ['foo', 'bar'], return '{foo,bar}', for error reporting.
- '''
- if len(strings) == 1:
- return strings[0]
- else:
- return '{' + ','.join(strings) + '}'
-
-
-class ChromeScaledImage(interface.GathererBase):
- '''Represents an image that exists in multiple layout variants
- (e.g. "default", "touch") and multiple scale variants
- (e.g. "100_percent", "200_percent").
- '''
-
- split_context_re_ = lazy_re.compile(r'(.+)_(\d+)_percent\Z')
-
- def _FindInputFile(self):
- output_context = self.grd_node.GetRoot().output_context
- match = self.split_context_re_.match(output_context)
- if not match:
- raise exception.MissingMandatoryAttribute(
- 'All <output> nodes must have an appropriate context attribute'
- ' (e.g. context="touch_200_percent")')
- req_layout, req_scale = match.group(1), int(match.group(2))
-
- layouts = [req_layout]
- try_default_layout = self.grd_node.GetRoot().fallback_to_default_layout
- if try_default_layout and 'default' not in layouts:
- layouts.append('default')
-
- # TODO(tdanderson): Search in descending order of all image scales
- # instead of immediately falling back to 100.
- # See crbug.com/503643.
- scales = [req_scale]
- try_low_res = self.grd_node.FindBooleanAttribute(
- 'fallback_to_low_resolution', default=False, skip_self=False)
- if try_low_res and 100 not in scales:
- scales.append(100)
-
- for layout in layouts:
- for scale in scales:
- dir = '%s_%s_percent' % (layout, scale)
- path = os.path.join(dir, self.rc_file)
- if os.path.exists(self.grd_node.ToRealPath(path)):
- return path, scale, req_scale
-
- if not try_default_layout:
- # The file was not found in the specified output context and it was
- # explicitly indicated that the default context should not be searched
- # as a fallback, so return an empty path.
- return None, 100, req_scale
-
- # The file was found in neither the specified context nor the default
- # context, so raise an exception.
- dir = "%s_%s_percent" % (_MakeBraceGlob(layouts),
- _MakeBraceGlob(map(str, scales)))
- raise exception.FileNotFound(
- 'Tried ' + self.grd_node.ToRealPath(os.path.join(dir, self.rc_file)))
-
- def GetInputPath(self):
- path, scale, req_scale = self._FindInputFile()
- return path
-
- def Parse(self):
- pass
-
- def GetTextualIds(self):
- return [self.extkey]
-
- def GetData(self, *args):
- path, scale, req_scale = self._FindInputFile()
- if path is None:
- return None
-
- data = util.ReadFile(self.grd_node.ToRealPath(path), util.BINARY)
- data = _RescaleImage(data, scale, req_scale)
- data = _MoveSpecialChunksToFront(data)
- return data
-
- def Translate(self, *args, **kwargs):
- return self.GetData()
diff --git a/grit/gather/chrome_scaled_image_unittest.py b/grit/gather/chrome_scaled_image_unittest.py
deleted file mode 100644
index 4b0bbfc..0000000
--- a/grit/gather/chrome_scaled_image_unittest.py
+++ /dev/null
@@ -1,193 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for ChromeScaledImage.'''
-
-
-import re
-import struct
-import unittest
-import zlib
-
-from grit import exception
-from grit import util
-from grit.format import data_pack
-from grit.tool import build
-
-
-_OUTFILETYPES = [
- ('.h', 'rc_header'),
- ('_map.cc', 'resource_map_source'),
- ('_map.h', 'resource_map_header'),
- ('.pak', 'data_package'),
- ('.rc', 'rc_all'),
-]
-
-
-_PNG_HEADER = (
- '\x89\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52'
- '\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90\x77\x53'
- '\xde')
-_PNG_FOOTER = (
- '\x00\x00\x00\x0c\x49\x44\x41\x54\x18\x57\x63\xf8\xff\xff\x3f\x00'
- '\x05\xfe\x02\xfe\xa7\x35\x81\x84\x00\x00\x00\x00\x49\x45\x4e\x44'
- '\xae\x42\x60\x82')
-
-
-def _MakePNG(chunks):
- pack_int32 = struct.Struct('>i').pack
- chunks = [pack_int32(len(payload)) + type + payload + pack_int32(zlib.crc32(type + payload))
- for type, payload in chunks]
- return _PNG_HEADER + ''.join(chunks) + _PNG_FOOTER
-
-
-def _GetFilesInPak(pakname):
- '''Get a set of the files that were actually included in the .pak output.
- '''
- return set(data_pack.DataPack.ReadDataPack(pakname).resources.values())
-
-
-def _GetFilesInRc(rcname, tmp_dir, contents):
- '''Get a set of the files that were actually included in the .rc output.
- '''
- data = util.ReadFile(rcname, util.BINARY).decode('utf-16')
- contents = dict((tmp_dir.GetPath(k), v) for k, v in contents.items())
- return set(contents[m.group(1)]
- for m in re.finditer(ur'(?m)^\w+\s+BINDATA\s+"([^"]+)"$', data))
-
-
-def _MakeFallbackAttr(fallback):
- if fallback is None:
- return ''
- else:
- return ' fallback_to_low_resolution="%s"' % ('false', 'true')[fallback]
-
-
-def _Structures(fallback, *body):
- return '<structures%s>\n%s\n</structures>' % (
- _MakeFallbackAttr(fallback), '\n'.join(body))
-
-
-def _Structure(name, file, fallback=None):
- return '<structure name="%s" file="%s" type="chrome_scaled_image"%s />' % (
- name, file, _MakeFallbackAttr(fallback))
-
-
-def _If(expr, *body):
- return '<if expr="%s">\n%s\n</if>' % (expr, '\n'.join(body))
-
-
-def _RunBuildTest(self, structures, inputs, expected_outputs, skip_rc=False, layout_fallback=''):
- outputs = '\n'.join('<output filename="out/%s%s" type="%s" context="%s"%s />'
- % (context, ext, type, context, layout_fallback)
- for ext, type in _OUTFILETYPES
- for context in expected_outputs)
-
- infiles = {
- 'in/in.grd': '''<?xml version="1.0" encoding="UTF-8"?>
- <grit latest_public_release="0" current_release="1">
- <outputs>
- %s
- </outputs>
- <release seq="1">
- %s
- </release>
- </grit>
- ''' % (outputs, structures),
- }
- for pngpath, pngdata in inputs.items():
- infiles['in/' + pngpath] = pngdata
- class Options(object):
- pass
- with util.TempDir(infiles) as tmp_dir:
- with tmp_dir.AsCurrentDir():
- options = Options()
- options.input = tmp_dir.GetPath('in/in.grd')
- options.verbose = False
- options.extra_verbose = False
- build.RcBuilder().Run(options, [])
- for context, expected_data in expected_outputs.items():
- self.assertEquals(expected_data,
- _GetFilesInPak(tmp_dir.GetPath('out/%s.pak' % context)))
- if not skip_rc:
- self.assertEquals(expected_data,
- _GetFilesInRc(tmp_dir.GetPath('out/%s.rc' % context),
- tmp_dir, infiles))
-
-
-class ChromeScaledImageUnittest(unittest.TestCase):
- def testNormalFallback(self):
- d123a = _MakePNG([('AbCd', '')])
- t123a = _MakePNG([('EfGh', '')])
- d123b = _MakePNG([('IjKl', '')])
- _RunBuildTest(self,
- _Structures(None,
- _Structure('IDR_A', 'a.png'),
- _Structure('IDR_B', 'b.png'),
- ),
- {'default_123_percent/a.png': d123a,
- 'tactile_123_percent/a.png': t123a,
- 'default_123_percent/b.png': d123b,
- },
- {'default_123_percent': set([d123a, d123b]),
- 'tactile_123_percent': set([t123a, d123b]),
- })
-
- def testNormalFallbackFailure(self):
- self.assertRaises(exception.FileNotFound,
- _RunBuildTest, self,
- _Structures(None,
- _Structure('IDR_A', 'a.png'),
- ),
- {'default_100_percent/a.png': _MakePNG([('AbCd', '')]),
- 'tactile_100_percent/a.png': _MakePNG([('EfGh', '')]),
- },
- {'tactile_123_percent': 'should fail before using this'})
-
- def testLowresFallback(self):
- png = _MakePNG([('Abcd', '')])
- png_with_csCl = _MakePNG([('csCl', ''),('Abcd', '')])
- for outer in (None, False, True):
- for inner in (None, False, True):
- args = (
- self,
- _Structures(outer,
- _Structure('IDR_A', 'a.png', inner),
- ),
- {'default_100_percent/a.png': png},
- {'tactile_200_percent': set([png_with_csCl])})
- if inner or (inner is None and outer):
- # should fall back to 100%
- _RunBuildTest(*args, skip_rc=True)
- else:
- # shouldn't fall back
- self.assertRaises(exception.FileNotFound, _RunBuildTest, *args)
-
- # Test fallback failure with fallback_to_low_resolution=True
- self.assertRaises(exception.FileNotFound,
- _RunBuildTest, self,
- _Structures(True,
- _Structure('IDR_A', 'a.png'),
- ),
- {}, # no files
- {'tactile_123_percent': 'should fail before using this'})
-
- def testNoFallbackToDefaultLayout(self):
- d123a = _MakePNG([('AbCd', '')])
- t123a = _MakePNG([('EfGh', '')])
- d123b = _MakePNG([('IjKl', '')])
- _RunBuildTest(self,
- _Structures(None,
- _Structure('IDR_A', 'a.png'),
- _Structure('IDR_B', 'b.png'),
- ),
- {'default_123_percent/a.png': d123a,
- 'tactile_123_percent/a.png': t123a,
- 'default_123_percent/b.png': d123b,
- },
- {'default_123_percent': set([d123a, d123b]),
- 'tactile_123_percent': set([t123a]),
- },
- layout_fallback=' fallback_to_default_layout="false"')
diff --git a/grit/gather/igoogle_strings.py b/grit/gather/igoogle_strings.py
deleted file mode 100644
index 79ed839..0000000
--- a/grit/gather/igoogle_strings.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Support for ALL_ALL.xml format used by Igoogle plug-ins in Google Desktop.'''
-
-import StringIO
-import re
-import xml.sax
-import xml.sax.handler
-import xml.sax.saxutils
-
-from grit.gather import regexp
-from grit import util
-from grit import tclib
-
-# Placeholders can be defined in strings.xml files by putting the name of the
-# placeholder between [![ and ]!] e.g. <MSG>Hello [![USER]!] how are you<MSG>
-PLACEHOLDER_RE = re.compile('(\[!\[|\]!\])')
-
-
-class IgoogleStringsContentHandler(xml.sax.handler.ContentHandler):
- '''A very dumb parser for splitting the strings.xml file into translateable
- and nontranslateable chunks.'''
-
- def __init__(self, parent):
- self.curr_elem = ''
- self.curr_text = ''
- self.parent = parent
- self.resource_name = ''
- self.meaning = ''
- self.translateable = True
-
- def startElement(self, name, attrs):
- if (name != 'messagebundle'):
- self.curr_elem = name
-
- attr_names = attrs.getQNames()
- if 'name' in attr_names:
- self.resource_name = attrs.getValueByQName('name')
-
- att_text = []
- for attr_name in attr_names:
- att_text.append(' ')
- att_text.append(attr_name)
- att_text.append('=')
- att_text.append(
- xml.sax.saxutils.quoteattr(attrs.getValueByQName(attr_name)))
-
- self.parent._AddNontranslateableChunk("<%s%s>" %
- (name, ''.join(att_text)))
-
- def characters(self, content):
- if self.curr_elem != '':
- self.curr_text += content
-
- def endElement(self, name):
- if name != 'messagebundle':
- self.parent.AddMessage(self.curr_text, self.resource_name,
- self.meaning, self.translateable)
- self.parent._AddNontranslateableChunk("</%s>\n" % name)
- self.curr_elem = ''
- self.curr_text = ''
- self.resource_name = ''
- self.meaning = ''
- self.translateable = True
-
- def ignorableWhitespace(self, whitespace):
- pass
-
-
-class IgoogleStrings(regexp.RegexpGatherer):
- '''Supports the ALL_ALL.xml format used by Igoogle gadgets.'''
-
- def AddMessage(self, msgtext, description, meaning, translateable):
- if msgtext == '':
- return
-
- msg = tclib.Message(description=description, meaning=meaning)
-
- unescaped_text = self.UnEscape(msgtext)
- parts = PLACEHOLDER_RE.split(unescaped_text)
- in_placeholder = False
- for part in parts:
- if part == '':
- continue
- elif part == '[![':
- in_placeholder = True
- elif part == ']!]':
- in_placeholder = False
- else:
- if in_placeholder:
- msg.AppendPlaceholder(tclib.Placeholder(part, '[![%s]!]' % part,
- '(placeholder)'))
- else:
- msg.AppendText(part)
-
- self.skeleton_.append(
- self.uberclique.MakeClique(msg, translateable=translateable))
-
- # if statement needed because this is supposed to be idempotent (so never
- # set back to false)
- if translateable:
- self.translatable_chunk_ = True
-
- # Although we use the RegexpGatherer base class, we do not use the
- # _RegExpParse method of that class to implement Parse(). Instead, we
- # parse using a SAX parser.
- def Parse(self):
- if self.have_parsed_:
- return
- self.have_parsed_ = True
-
- self.text_ = self._LoadInputFile().strip()
- self._AddNontranslateableChunk(u'<messagebundle>\n')
- stream = StringIO.StringIO(self.text_)
- handler = IgoogleStringsContentHandler(self)
- xml.sax.parse(stream, handler)
- self._AddNontranslateableChunk(u'</messagebundle>\n')
-
- def Escape(self, text):
- return util.EncodeCdata(text)
diff --git a/grit/gather/igoogle_strings_unittest.py b/grit/gather/igoogle_strings_unittest.py
deleted file mode 100644
index 3a4488c..0000000
--- a/grit/gather/igoogle_strings_unittest.py
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Unit tests for grit.gather.igoogle_strings'''
-
-import os
-import sys
-if __name__ == '__main__':
- sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
-
-import unittest
-import StringIO
-
-from grit.gather import igoogle_strings
-
-class IgoogleStringsUnittest(unittest.TestCase):
- def testParsing(self):
- original = '''<messagebundle><msg test="hello_world">Hello World</msg></messagebundle>'''
- gatherer = igoogle_strings.IgoogleStrings(StringIO.StringIO(original))
- gatherer.Parse()
- print len(gatherer.GetCliques())
- print gatherer.GetCliques()[0].GetMessage().GetRealContent()
- self.failUnless(len(gatherer.GetCliques()) == 1)
- self.failUnless(gatherer.Translate('en').replace('\n', '') == original)
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/grit/gather/interface.py b/grit/gather/interface.py
deleted file mode 100644
index c277d37..0000000
--- a/grit/gather/interface.py
+++ /dev/null
@@ -1,171 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-'''Interface for all gatherers.
-'''
-
-
-import os.path
-import types
-
-from grit import clique