From a47f69daa745d15b8c831329569137c43d5175ef Mon Sep 17 00:00:00 2001 From: "gfeher@chromium.org" Date: Wed, 25 Aug 2010 09:35:55 +0000 Subject: Add Mac output for policy template generator Writer for plist manifest and string table files, and custom strings for the Mac templates. BUG=49316 TEST=plist_writer_unittest.*, plist_strings_writer_unittest.* (grit) Review URL: http://codereview.chromium.org/3116027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57307 0039d316-1c4b-4281-b951-d872f2087c98 --- .../format/policy_templates/template_formatter.py | 17 +- .../format/policy_templates/writers/adm_writer.py | 8 +- .../writers/plist_strings_writer.py | 93 ++++++++ .../writers/plist_strings_writer_unittest.py | 190 +++++++++++++++ .../policy_templates/writers/plist_writer.py | 148 ++++++++++++ .../writers/plist_writer_unittest.py | 255 +++++++++++++++++++++ .../writers/writer_unittest_common.py | 74 ++++++ tools/grit/grit/node/misc.py | 2 +- tools/grit/grit/test_suite_all.py | 5 + tools/grit/grit/tool/build.py | 2 +- 10 files changed, 785 insertions(+), 9 deletions(-) create mode 100644 tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py create mode 100644 tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py create mode 100644 tools/grit/grit/format/policy_templates/writers/plist_writer.py create mode 100644 tools/grit/grit/format/policy_templates/writers/plist_writer_unittest.py create mode 100644 tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py (limited to 'tools/grit') diff --git a/tools/grit/grit/format/policy_templates/template_formatter.py b/tools/grit/grit/format/policy_templates/template_formatter.py index 2e5633a..ddbb0cce 100644 --- a/tools/grit/grit/format/policy_templates/template_formatter.py +++ b/tools/grit/grit/format/policy_templates/template_formatter.py @@ -59,7 +59,7 @@ class TemplateFormatter(interface.ItemFormatter): self._lang = lang self._GetFlags(item) - self._policy_groups = None + self._policy_data = None self._messages = {} self._ParseGritNodes(item) return self._GetOutput() @@ -72,8 +72,9 @@ class TemplateFormatter(interface.ItemFormatter): The text of the policy template based on the parameters passed to __init__() and Format(). ''' - policy_generator = \ - PolicyTemplateGenerator(self._messages, self._policy_groups) + policy_generator = PolicyTemplateGenerator( + self._messages, + self._policy_data['policy_groups']) writer = self._writer_module.GetWriter(self._info, self._messages) str = policy_generator.GetTemplateText(writer) return str @@ -107,8 +108,14 @@ class TemplateFormatter(interface.ItemFormatter): message: A node in the grit tree. ''' msg_name = message.GetTextualIds()[0] + # Get translation of message. msg_txt = message.Translate(self._lang) + # Replace the placeholder of app name. msg_txt = msg_txt.replace('$1', self._info['app_name']) + # Replace other placeholders. + for placeholder in self._policy_data['placeholders']: + msg_txt = msg_txt.replace(placeholder['key'], placeholder['value']) + # Strip spaces and escape newlines. lines = msg_txt.split('\n') lines = [line.strip() for line in lines] msg_txt = "\\n".join(lines) @@ -126,8 +133,8 @@ class TemplateFormatter(interface.ItemFormatter): return if (isinstance(item, structure.StructureNode) and item.attrs['type'] == 'policy_template_metafile'): - assert self._policy_groups == None - self._policy_groups = item.gatherer.GetData() + assert self._policy_data == None + self._policy_data = item.gatherer.GetData() elif (isinstance(item, message.MessageNode)): self._ImportMessage(item) for child in item.children: diff --git a/tools/grit/grit/format/policy_templates/writers/adm_writer.py b/tools/grit/grit/format/policy_templates/writers/adm_writer.py index 51dea06..76b8b60 100644 --- a/tools/grit/grit/format/policy_templates/writers/adm_writer.py +++ b/tools/grit/grit/format/policy_templates/writers/adm_writer.py @@ -3,14 +3,18 @@ # found in the LICENSE file. -from template_writer import TemplateWriter +from grit.format.policy_templates.writers import template_writer def GetWriter(info, messages): + '''Factory method for creating AdmWriter objects. + See the constructor of TemplateWriter for description of + arguments. + ''' return AdmWriter(info, messages) -class AdmWriter(TemplateWriter): +class AdmWriter(template_writer.TemplateWriter): '''Class for generating policy templates in Windows ADM format. It is used by PolicyTemplateGenerator to write ADM files. ''' diff --git a/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py b/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py new file mode 100644 index 0000000..ce1da45 --- /dev/null +++ b/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py @@ -0,0 +1,93 @@ +# Copyright (c) 2010 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 + + +def GetWriter(info, messages): + '''Factory method for creating PListStringsWriter objects. + See the constructor of TemplateWriter for description of + arguments. + ''' + return PListStringsWriter(info, messages) + + +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 _GetLocalizedPolicyMessage(self, policy, msg_id): + '''Looks up localized caption or description for a policy. + If the policy does not have the required message, then it is + inherited from the group. + + Args: + policy: The data structure of the policy. + msg_id: Either 'caption' or 'desc'. + + Returns: + The corresponding message for the policy. + ''' + if msg_id in policy: + msg = policy[msg_id] + else: + msg = self._policy_group[msg_id] + return msg + + def _AddToStringTable(self, item_name, title, 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. + ''' + title = title.replace('"', '\\"') + desc = desc.replace('"', '\\"') + self._out.append('%s.pfm_title = \"%s\";' % (item_name, title)) + self._out.append('%s.pfm_description = \"%s\";' % (item_name, desc)) + + 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 = self._GetLocalizedPolicyMessage(policy, 'desc') + caption = self._GetLocalizedPolicyMessage(policy, 'caption') + if (policy['type'] == 'enum'): + # Append the captions of enum items to the description string. + item_descs = [] + for item in policy['items']: + item_descs.append( item['value'] + ' - ' + item['caption'] ) + desc = '\\n'.join(item_descs) + '\\n' + desc + + self._AddToStringTable(policy['name'], caption, desc) + + def BeginPolicyGroup(self, group): + self._policy_group = group + + def EndPolicyGroup(self): + self._policy_group = None + + def BeginTemplate(self): + self._AddToStringTable( + self.info['app_name'], + self.info['app_name'], + self.messages['IDS_POLICY_MAC_CHROME_PREFERENCES']) + + def EndTemplate(self): + pass + + def Prepare(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/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py b/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py new file mode 100644 index 0000000..635b55f --- /dev/null +++ b/tools/grit/grit/format/policy_templates/writers/plist_strings_writer_unittest.py @@ -0,0 +1,190 @@ +#!/usr/bin/python2.4 +# Copyright (c) 2010 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(sys.argv[0]), '../../../..')) + +import tempfile +import unittest +import StringIO + +from grit.format.policy_templates.writers import writer_unittest_common +from grit import grd_reader +from grit import util +from grit.tool import build + + +class PListStringsWriterUnittest(writer_unittest_common.WriterUnittestCommon): + '''Unit tests for PListWriter.''' + + def testEmpty(self): + # Test PListWriter in case of empty polices. + grd = self.prepareTest(''' + { + 'policy_groups': [], + 'placeholders': [], + }''', ''' + + + + + + + $1 preferen"ces + + + + ''' ) + + self.CompareResult( + grd, + 'fr', + {'_chromium': '1', 'mac_bundle_id': 'com.example.Test'}, + 'plist_strings', + 'en', + '''Chromium.pfm_title = "Chromium"; +Chromium.pfm_description = "Chromium preferen\\"ces"; + ''') + + def testMainPolicy(self): + # Tests a policy group with a single policy of type 'main'. + grd = self.prepareTest(''' + { + 'policy_groups': [ + { + 'name': 'MainGroup', + 'policies': [{ + 'name': 'MainPolicy', + 'type': 'main', + }], + }, + ], + 'placeholders': [], + }''', ''' + + + + + + + Caption of main. + Title of main. + Preferences of $1 + + + + ''' ) + self.CompareResult( + grd, + 'fr', + {'_google_chrome' : '1', 'mac_bundle_id': 'com.example.Test'}, + 'plist_strings', + 'en', + '''Google Chrome.pfm_title = "Google Chrome"; +Google Chrome.pfm_description = "Preferences of Google Chrome"; +MainPolicy.pfm_title = "Caption of main."; +MainPolicy.pfm_description = "Title of main."; +''') + + 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_groups': [ + { + 'name': 'StringGroup', + 'policies': [{ + 'name': 'StringPolicy', + 'type': 'string', + }], + }, + ], + 'placeholders': [], + }''', ''' + + + + + + + Caption of group. + Description of group. +With a newline. + Caption of policy. + Preferences Of $1 + + + + ''' ) + self.CompareResult( + grd, + 'fr', + {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'}, + 'plist_strings', + 'en', + '''Chromium.pfm_title = "Chromium"; +Chromium.pfm_description = "Preferences Of Chromium"; +StringPolicy.pfm_title = "Caption of policy."; +StringPolicy.pfm_description = "Description of group.\\nWith a newline."; + ''') + + def testEnumPolicy(self): + # Tests a policy group with a single policy of type 'enum'. + grd = self.prepareTest(''' + { + 'policy_groups': [ + { + 'name': 'EnumGroup', + 'policies': [{ + 'name': 'EnumPolicy', + 'type': 'enum', + 'items': [ + {'name': 'ProxyServerDisabled', 'value': '0'}, + {'name': 'ProxyServerAutoDetect', 'value': '1'}, + ] + }], + }, + ], + 'placeholders': [], + }''', ''' + + + + + + + Caption of group. + Description of group. + Caption of policy. + Description of policy. + Option1 + Option2 + $1 preferences + + + + ''' ) + self.CompareResult( + grd, + 'fr', + {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'}, + 'plist_strings', + 'en', + '''Google Chrome.pfm_title = "Google Chrome"; +Google Chrome.pfm_description = "Google Chrome preferences"; +EnumPolicy.pfm_title = "Caption of policy."; +EnumPolicy.pfm_description = "0 - Option1\\n1 - Option2\\nDescription of policy."; + ''') + + +if __name__ == '__main__': + unittest.main() + diff --git a/tools/grit/grit/format/policy_templates/writers/plist_writer.py b/tools/grit/grit/format/policy_templates/writers/plist_writer.py new file mode 100644 index 0000000..3399fcee --- /dev/null +++ b/tools/grit/grit/format/policy_templates/writers/plist_writer.py @@ -0,0 +1,148 @@ +# Copyright (c) 2010 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(info, messages): + '''Factory method for creating PListWriter objects. + See the constructor of TemplateWriter for description of + arguments. + ''' + return PListWriter(info, messages) + + +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', + 'enum': 'integer', + 'main': 'boolean', + 'list': 'array', + } + + 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_string + ... + + 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 + . + + 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): + '''Adds the following XML snippet to an XML element: + pfm_targets + + user-managed + + + Args: + parent: The parent XML element where the snippet will be added. + ''' + array = self._AddKeyValuePair(parent, 'pfm_targets', 'array') + self.AddElement(array, 'string', {}, 'user-managed') + + def WritePolicy(self, policy): + policy_name = policy['name'] + policy_type = policy['type'] + + 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) + self._AddStringKeyValuePair(dict, 'pfm_type', + self.TYPE_TO_INPUT[policy_type]) + if (policy_type == 'enum'): + range_list = self._AddKeyValuePair(dict, 'pfm_range_list', 'array') + for item in policy['items']: + self.AddElement(range_list, 'integer', {}, item['value']) + + def BeginPolicyGroup(self, group): + pass + + def EndPolicyGroup(self): + pass + + def BeginTemplate(self): + self._plist.attributes['version'] = '1' + dict = self.AddElement(self._plist, 'dict') + + self._AddStringKeyValuePair(dict, 'pfm_name', self.info['app_name']) + self._AddStringKeyValuePair(dict, 'pfm_description', '') + self._AddStringKeyValuePair(dict, 'pfm_title', '') + self._AddStringKeyValuePair(dict, 'pfm_version', '1') + self._AddStringKeyValuePair(dict, 'pfm_domain', self.info['mac_bundle_id']) + + self._array = self._AddKeyValuePair(dict, 'pfm_subkeys', 'array') + + def EndTemplate(self): + pass + + def Prepare(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') + self._doc = dom_impl.createDocument(None, 'plist', doctype) + self._plist = self._doc.documentElement + + def GetTemplateText(self): + # return self.plist_doc.toprettyxml(indent=' ') + # The above pretty-printer does not print the doctype and adds spaces + # around texts, which the OSX Workgroup Manager does not like. So we use + # the poor man's pretty printer. It assumes that there are no mixed-content + # nodes. + # Get all the XML content in a one-line string. + xml = self._doc.toxml() + # 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 in range(len(lines)): + line = lines[i] + 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 ' + + + + pfm_name + %s + pfm_description + + pfm_title + + pfm_version + 1 + pfm_domain + %s + pfm_subkeys + %s + +''' % (product_name, bundle_id, policies) + + def testEmpty(self): + # Test PListWriter in case of empty polices. + grd = self.prepareTest(''' + { + 'policy_groups': [], + 'placeholders': [], + }''', ''' + + + + + + + + + ''' ) + + self.CompareResult( + grd, + 'fr', + {'_chromium': '1', 'mac_bundle_id': 'com.example.Test'}, + 'plist', + 'en', + self._GetExpectedResults('Chromium', 'com.example.Test', '')) + + def testMainPolicy(self): + # Tests a policy group with a single policy of type 'main'. + grd = self.prepareTest(''' + { + 'policy_groups': [ + { + 'name': 'MainGroup', + 'policies': [{ + 'name': 'MainPolicy', + 'type': 'main', + }], + }, + ], + 'placeholders': [], + }''', ''' + + + + + + + This is not tested here. + This is not tested here. + + + + ''' ) + self.CompareResult( + grd, + 'fr', + {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'}, + 'plist', + 'en', + self._GetExpectedResults('Chromium', 'com.example.Test', ''' + + pfm_name + MainPolicy + pfm_description + + pfm_title + + pfm_targets + + user-managed + + pfm_type + boolean + + ''')) + + def testStringPolicy(self): + # Tests a policy group with a single policy of type 'string'. + grd = self.prepareTest(''' + { + 'policy_groups': [ + { + 'name': 'StringGroup', + 'policies': [{ + 'name': 'StringPolicy', + 'type': 'string', + }], + }, + ], + 'placeholders': [], + }''', ''' + + + + + + + This is not tested here. + This is not tested here. + This is not tested here. + This is not tested here. + + + + ''' ) + self.CompareResult( + grd, + 'fr', + {'_chromium' : '1', 'mac_bundle_id': 'com.example.Test'}, + 'plist', + 'en', + self._GetExpectedResults('Chromium', 'com.example.Test', ''' + + pfm_name + StringPolicy + pfm_description + + pfm_title + + pfm_targets + + user-managed + + pfm_type + string + + ''')) + + def testEnumPolicy(self): + # Tests a policy group with a single policy of type 'enum'. + grd = self.prepareTest(''' + { + 'policy_groups': [ + { + 'name': 'EnumGroup', + 'policies': [{ + 'name': 'EnumPolicy', + 'type': 'enum', + 'items': [ + {'name': 'ProxyServerDisabled', 'value': '0'}, + {'name': 'ProxyServerAutoDetect', 'value': '1'}, + ] + }], + }, + ], + 'placeholders': [], + }''', ''' + + + + + + + This is not tested here. + This is not tested here. + This is not tested here. + This is not tested here. + This is not tested here. + This is not tested here. + + + + ''' ) + self.CompareResult( + grd, + 'fr', + {'_google_chrome': '1', 'mac_bundle_id': 'com.example.Test2'}, + 'plist', + 'en', + self._GetExpectedResults('Google Chrome', 'com.example.Test2', ''' + + pfm_name + EnumPolicy + pfm_description + + pfm_title + + pfm_targets + + user-managed + + pfm_type + integer + pfm_range_list + + 0 + 1 + + + ''')) + + +if __name__ == '__main__': + unittest.main() + diff --git a/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py b/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py new file mode 100644 index 0000000..ff7d8f5 --- /dev/null +++ b/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py @@ -0,0 +1,74 @@ +# Copyright (c) 2010 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 sys +if __name__ == '__main__': + sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '../../../..')) + +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, grd_text): + '''Parses a grit tree along with a data structure of policies. + + Args: + policy_json: The policy data structure in JSON format. + grd_text: The grit tree in text form. + ''' + tmp_file_name = 'test.json' + tmp_dir_name = tempfile.gettempdir() + json_file_path = tmp_dir_name + '/' + tmp_file_name + f = open(json_file_path, 'w') + f.write(policy_json.strip()) + f.close() + grd = grd_reader.Parse( + StringIO.StringIO(grd_text % json_file_path), dir=tmp_dir_name) + grd.RunGatherers(recursive=True) + os.unlink(json_file_path) + return grd + + def CompareResult(self, grd, env_lang, env_defs, out_type, out_lang, + expected_output): + '''Generates an output of the writer and compares it with the expected + result. Fails if they differ. + + 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. + out_lang: Language of the output node for which output will be generated. + expected_output: The expected output of the writer. + ''' + grd.SetOutputContext(env_lang, env_defs) + buf = StringIO.StringIO() + build.RcBuilder.ProcessNode(grd, DummyOutput(out_type, out_lang), buf) + output = buf.getvalue() + self.assertEquals(output.strip(), expected_output.strip()) diff --git a/tools/grit/grit/node/misc.py b/tools/grit/grit/node/misc.py index b906ec2..2ba2ff1 100644 --- a/tools/grit/grit/node/misc.py +++ b/tools/grit/grit/node/misc.py @@ -250,7 +250,7 @@ class GritNode(base.Node): elif t == 'js_map_format': from grit.format import js_map_format return js_map_format.TopLevel() - elif t == 'adm': + elif t in ['adm', 'plist', 'plist_strings']: from grit.format.policy_templates import template_formatter return template_formatter.TemplateFormatter(t) else: diff --git a/tools/grit/grit/test_suite_all.py b/tools/grit/grit/test_suite_all.py index 98b9d0d..0a427a2 100644 --- a/tools/grit/grit/test_suite_all.py +++ b/tools/grit/grit/test_suite_all.py @@ -47,6 +47,9 @@ class TestSuiteAll(unittest.TestSuite): from grit.node.custom import filename_unittest import grit.format.js_map_format_unittest from grit.format.policy_templates import policy_template_generator_unittest + from grit.format.policy_templates.writers import plist_writer_unittest + from grit.format.policy_templates.writers \ + import plist_strings_writer_unittest test_classes = [ base_unittest.NodeUnittest, @@ -77,6 +80,8 @@ class TestSuiteAll(unittest.TestSuite): filename_unittest.WindowsFilenameUnittest, grit.format.js_map_format_unittest.JsMapFormatUnittest, policy_template_generator_unittest.PolicyTemplateGeneratorUnittest, + plist_writer_unittest.PListWriterUnittest, + plist_strings_writer_unittest.PListStringsWriterUnittest, # add test classes here... ] diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py index 9d1c6bc1..2882c95 100644 --- a/tools/grit/grit/tool/build.py +++ b/tools/grit/grit/tool/build.py @@ -182,7 +182,7 @@ are exported to translation interchange files (e.g. XMB files), etc. if output.GetType() in ('rc_header', 'resource_map_header', 'resource_map_source', 'resource_file_map_source'): encoding = 'cp1252' - elif output.GetType() == 'js_map_format': + elif output.GetType() in ['js_map_format', 'plist', 'plist_strings']: encoding = 'utf_8' else: # TODO(gfeher) modify here to set utf-8 encoding for admx/adml -- cgit v1.1