Best Python code snippet using pyatom_python
generate_extension_admx.py
Source:generate_extension_admx.py  
1#!/usr/bin/env python2# Copyright 2017 The Chromium Authors. All rights reserved.3# Use of this source code is governed by a BSD-style license that can be4# found in the LICENSE file.5'''Creates a ADMX group policy template file from an extension schema.json file.6generate_extension_admx.py --name <name> --id <id> --schema <schema_file>7                           --admx <admx_file> --adml <adml_file>8<name> is the human-readable name of the extension.9<id> is the 32-character extension ID.10<schema_file> is the file path of the input schema.json file.11<admx_file> is the file path of the output ADMX file.12<adml_file> is the file path of the output ADML language file (e.g. in en-US).13Example:14  Download the managed bookmarks extension from15    http://developer.chrome.com/extensions/examples/extensions/managed_bookmarks.zip16  to obtain the schema.json file.17  generate_extension_admx.py --name 'Managed Bookmarks'18                             --id 'gihmafigllmhbppdfjnfecimiohcljba'19                             --schema '/path/to/schema.json'20                             --admx '/path/to/managed_bookmarks.admx'21                             --adml '/path/to/en-US/managed_bookmarks.adml'22'''23import re24import sys25from argparse import ArgumentParser26from xml.dom import minidom27class AdmxGenerator(object):28  '''Generates ADMX and ADML templates'''29  def __init__(self, extension_name, extension_id, schema):30    self._extension_name = extension_name31    self._extension_id = extension_id32    self._schema = schema33    self._schema_map = {}34    self._strings_seen = {}35    self._admx_doc = None36    self._adml_doc = None37    self._policies_elem = None38    self._string_table_elem = None39    self._presentation_table_elem = None40    # Registry key for policies. Treat all policies as mandatory. Recommended41    # policies would use 'Recommended' instead of 'Policy'.42    self._REGISTRY_KEY = \43        'Software\\Policies\\Google\\Chrome\\3rdparty\\extensions\\' + \44        extension_id + '\\Policy'45  def CreateTemplateXml(self):46    '''47    Creates ADMX and ADML templates.48    @return (ADMX xml, ADML xml) tuple.49    '''50    # ADML must be first as ADMX uses the ADML doc to write strings.51    self._BeginAdmlTemplate()52    self._BeginAdmxTemplate()53    root_category_name = 'extension'54    # Add a category element for the root55    self._AddCategory(self._extension_name, root_category_name,56                      'Google:Cat_Google')57    properties = self._schema['properties']58    for policy_name, policy_schema in properties.items():59      self._AddPolicy(policy_name, policy_schema, root_category_name,60                      self._REGISTRY_KEY)61    return self._ToPrettyXml(self._admx_doc.toxml()), self._ToPrettyXml(62        self._adml_doc.toxml())63  def _AddElement(self, parent, name):64    '''65    Adds an element named |name| as child of |parent|.66    @return The new XML element.67    '''68    doc = parent.ownerDocument69    element = doc.createElement(name)70    parent.appendChild(element)71    return element72  def _SetAttribute(self, elem, name, value, string_id=None):73    '''74    Sets the attribute |name| = |value| on the element |elem|. If |string_id|75    is given, a new string with that ID is added to the strings table in the76    ADML file.77    '''78    string_id = self._ToId(string_id)79    if (string_id):80      elem.setAttribute(name, '$(string.%s)' % string_id)81      self._AddString(string_id, value)82    else:83      elem.setAttribute(name, value)84  def _ToId(self, id_str):85    '''86    Replaces all non-alphanumeric characters by underscores.87    '''88    return re.sub('[^0-9a-zA-Z]+', '_', id_str) if id_str else None89  def _AddString(self, string_id, text):90    '''91    Adds a string with ID |string_id| to the strings table in the ADML doc or92    reuses an existing string.93    '''94    string_id = self._ToId(string_id)95    if string_id in self._strings_seen:96      assert text == self._strings_seen[string_id]97    else:98      self._strings_seen[string_id] = text99      string_elem = self._AddElement(self._string_table_elem, 'string')100      self._SetAttribute(string_elem, 'id', string_id)101      string_elem.appendChild(self._adml_doc.createTextNode(text))102  def _AddNamespace(self, namespaces_elem, elem_name, namespace, prefix):103    '''104    Adds an ADMX namespace node.105    '''106    namespace_elem = self._AddElement(namespaces_elem, elem_name)107    self._SetAttribute(namespace_elem, 'namespace', namespace)108    self._SetAttribute(namespace_elem, 'prefix', prefix)109  def _AddCategory(self, display_name, category_full_name,110                   parent_category_full_name):111    '''112    Adds an ADMX category.113    Args:114      display_name: The human-readable name of the category.115      category_full_name:116        A unique name for the category.117        This is used in 'name' attributes, which may only contain lowercase118        letters, uppercase letters, digits and the underscore character.119      parent_category_full_name: The unique 'full name' of the parent category.120    '''121    category_elem = self._AddElement(self.categories_elem_, 'category')122    self._SetAttribute(category_elem, 'displayName', display_name,123                       category_full_name)124    self._SetAttribute(category_elem, 'name', category_full_name)125    parent_category_elem = self._AddElement(category_elem, 'parentCategory')126    self._SetAttribute(parent_category_elem, 'ref', parent_category_full_name)127  def _BeginAdmlTemplate(self):128    '''129    Writes the header of the ADML doc.130    '''131    dom_impl = minidom.getDOMImplementation('')132    self._adml_doc = dom_impl.createDocument(None, 'policyDefinitionResources',133                                             None)134    root_elem = self._adml_doc.documentElement135    self._SetAttribute(root_elem, 'revision', '1.0')136    self._SetAttribute(root_elem, 'schemaVersion', '1.0')137    self._AddElement(root_elem, 'displayName')138    self._AddElement(root_elem, 'description')139    resources_elem = self._AddElement(root_elem, 'resources')140    self._string_table_elem = self._AddElement(resources_elem, 'stringTable')141    self._presentation_table_elem = self._AddElement(resources_elem,142                                                     'presentationTable')143  def _BeginAdmxTemplate(self):144    '''145    Writes the header of the ADMX doc.146    '''147    dom_impl = minidom.getDOMImplementation('')148    self._admx_doc = dom_impl.createDocument(None, 'policyDefinitions', None)149    root_elem = self._admx_doc.documentElement150    self._SetAttribute(root_elem, 'revision', '1.0')151    self._SetAttribute(root_elem, 'schemaVersion', '1.0')152    namespaces_elem = self._AddElement(root_elem, 'policyNamespaces')153    self._AddNamespace(namespaces_elem, 'target',154                       'Google.Policies.ThirdParty.' + self._extension_id,155                       'extension')156    self._AddNamespace(namespaces_elem, 'using', 'Google.Policies', 'Google')157    self._AddNamespace(namespaces_elem, 'using', 'Microsoft.Policies.Windows',158                       'windows')159    resources_elem = self._AddElement(root_elem, 'resources')160    self._SetAttribute(resources_elem, 'minRequiredRevision', '1.0')161    supported_on_elem = self._AddElement(root_elem, 'supportedOn')162    definitions_elem = self._AddElement(supported_on_elem, 'definitions')163    definition_elem = self._AddElement(definitions_elem, 'definition')164    self._SetAttribute(definition_elem, 'displayName',165                       'Microsoft Windows 7 or later', 'SUPPORTED_WIN7')166    self._SetAttribute(definition_elem, 'name', 'SUPPORTED_WIN7')167    self.categories_elem_ = self._AddElement(root_elem, 'categories')168    self._policies_elem = self._AddElement(root_elem, 'policies')169  def _AddPolicy(self, policy_name, policy_schema, parent_category_full_name,170                 parent_key):171    '''172    Adds a policy with name |policy_name| and schema data |policy_schema| to173    the ADMX/ADML docs.174    Args:175      policy_name: The name of the policy.176      policy_schema: Schema data of the policy.177      parent_category_full_name:178        The unique 'full name' of the category this policy should be placed179        under.180        This is used in 'name' attributes, which may only contain lowercase181        letters, uppercase letters, digits and the underscore character.182      parenty_key: The registry key of the parent.183    '''184    policy_id = self._ToId(policy_name)185    full_name = parent_category_full_name + '_' + policy_id186    policy_title = policy_schema.get('title', policy_name)187    if 'id' in policy_schema:188      # Keep id map for referenced schema.189      self._schema_map[policy_schema['id']] = policy_schema190    elif ('$ref' in policy_schema):191      # Instantiate referenced schema.192      referenced_schema = self._schema_map[policy_schema['$ref']]193      for key, value in referenced_schema.iteritems():194        if not key in policy_schema:195          policy_schema[key] = value196    # For 'object' type items create a new category (folder) and add children.197    if (policy_schema['type'] == 'object'):198      self._AddCategory(policy_title, full_name, parent_category_full_name)199      properties = policy_schema['properties']200      for child_policy_name, child_policy_schema in properties.items():201        self._AddPolicy(child_policy_name, child_policy_schema, full_name,202                        parent_key + '\\' + policy_name)203    else:204      policy_elem = self._AddElement(self._policies_elem, 'policy')205      policy_desc = policy_schema.get('description', None)206      self._SetAttribute(policy_elem, 'name', full_name)207      self._SetAttribute(policy_elem, 'class', 'Both')208      self._SetAttribute(policy_elem, 'displayName', policy_title, full_name)209      if policy_desc:210        self._SetAttribute(policy_elem, 'explainText', policy_desc,211                           full_name + '_Explain')212      self._SetAttribute(policy_elem, 'presentation',213                         '$(presentation.%s)' % full_name)214      self._SetAttribute(policy_elem, 'key', parent_key)215      parent_category_elem = self._AddElement(policy_elem, 'parentCategory')216      self._SetAttribute(parent_category_elem, 'ref', parent_category_full_name)217      supported_on_elem = self._AddElement(policy_elem, 'supportedOn')218      self._SetAttribute(supported_on_elem, 'ref', 'SUPPORTED_WIN7')219      desc_id = full_name + '_Part'220      presentation_elem = self._AddElement(self._presentation_table_elem,221                                           'presentation')222      self._SetAttribute(presentation_elem, 'id', full_name)223      if policy_schema['type'] == 'boolean':224        self._SetAttribute(policy_elem, 'valueName', policy_id)225        enabled_value_elem = self._AddElement(policy_elem, 'enabledValue')226        decimal_elem = self._AddElement(enabled_value_elem, 'decimal')227        self._SetAttribute(decimal_elem, 'value', '1')228        disabled_value_elem = self._AddElement(policy_elem, 'disabledValue')229        decimal_elem = self._AddElement(disabled_value_elem, 'decimal')230        self._SetAttribute(decimal_elem, 'value', '0')231      elif policy_schema['type'] == 'integer':232        elements_elem = self._AddElement(policy_elem, 'elements')233        decimal_elem = self._AddElement(elements_elem, 'decimal')234        self._SetAttribute(decimal_elem, 'id', desc_id)235        self._SetAttribute(decimal_elem, 'valueName', policy_id)236        textbox_elem = self._AddElement(presentation_elem, 'decimalTextBox')237        self._SetAttribute(textbox_elem, 'refId', desc_id)238        textbox_elem.appendChild(self._adml_doc.createTextNode(policy_title))239      elif (policy_schema['type'] == 'string' or240            policy_schema['type'] == 'number'):241        # Note: 'number' are doubles, but ADMX only supports integers242        # (decimal), thus use 'string' and rely on string-to-double243        # conversion in RegistryDict.244        elements_elem = self._AddElement(policy_elem, 'elements')245        text_elem = self._AddElement(elements_elem, 'text')246        self._SetAttribute(text_elem, 'id', desc_id)247        self._SetAttribute(text_elem, 'valueName', policy_id)248        textbox_elem = self._AddElement(presentation_elem, 'textBox')249        self._SetAttribute(textbox_elem, 'refId', desc_id)250        label_elem = self._AddElement(textbox_elem, 'label')251        label_elem.appendChild(self._adml_doc.createTextNode(policy_title))252      elif policy_schema['type'] == 'array':253        elements_elem = self._AddElement(policy_elem, 'elements')254        list_elem = self._AddElement(elements_elem, 'list')255        self._SetAttribute(list_elem, 'id', desc_id)256        self._SetAttribute(list_elem, 'key', parent_key + '\\' + policy_name)257        self._SetAttribute(list_elem, 'valuePrefix', None)258        listbox_elem = self._AddElement(presentation_elem, 'listBox')259        self._SetAttribute(listbox_elem, 'refId', desc_id)260        listbox_elem.appendChild(self._adml_doc.createTextNode(policy_title))261      else:262        raise Exception('Unhandled schema type "%s"' % policy_schema['type'])263  def _ToPrettyXml(self, xml):264    # return doc.toprettyxml(indent='  ')265    # The above pretty-printer does not print the doctype and adds spaces266    # around texts, e.g.:267    #  <string>268    #    value of the string269    #  </string>270    # This is problematic both for the OSX Workgroup Manager (plist files) and271    # the Windows Group Policy Editor (admx files). What they need instead:272    #  <string>value of string</string>273    # So we use a hacky pretty printer here. It assumes that there are no274    # mixed-content nodes.275    # Get all the XML content in a one-line string.276    # Determine where the line breaks will be. (They will only be between tags.)277    lines = xml[1:len(xml) - 1].split('><')278    indent = ''279    # Determine indent for each line.280    for i, line in enumerate(lines):281      if line[0] == '/':282        # If the current line starts with a closing tag, decrease indent before283        # printing.284        indent = indent[2:]285      lines[i] = indent + '<' + line + '>'286      if (line[0] not in ['/', '?', '!'] and '</' not in line and287          line[len(line) - 1] != '/'):288        # If the current line starts with an opening tag and does not conatin a289        # closing tag, increase indent after the line is printed.290        indent += '  '291    # Reconstruct XML text from the lines.292    return '\n'.join(lines)293def ConvertJsonToAdmx(extension_id, extension_name, schema_file, admx_file,294                      adml_file):295  '''296  Loads the schema.json file |schema_file|, generates the ADMX and ADML docs and297  saves them to |admx_file| and |adml_file|, respectively. The name of the298  template and the registry keys are determined from the |extension_name| and299  the 32-byte |extension_id|, respectively.300  '''301  # Load that schema.302  with open(schema_file, 'r') as f:303    schema = eval(f.read())304  admx_generator = AdmxGenerator(extension_id, extension_name, schema)305  admx, adml = admx_generator.CreateTemplateXml()306  with open(admx_file, 'w') as f:307    f.write(admx)308  with open(adml_file, 'w') as f:309    f.write(adml)310def main():311  '''Main function, usage see top of file.'''312  parser = ArgumentParser(usage=__doc__)313  parser.add_argument(314      '--name',315      dest='extension_name',316      help='extension name (e.g. Managed Bookmarks)')317  parser.add_argument(318      '--id',319      dest='extension_id',320      help='extension id (e.g. gihmafigllmhbppdfjnfecimiohcljba)')321  parser.add_argument(322      '--schema',323      dest='schema_file',324      help='Input schema.json file for the extension',325      metavar='FILE')326  parser.add_argument(327      '--admx', dest='admx_file', help='Output ADMX file', metavar='FILE')328  parser.add_argument(329      '--adml', dest='adml_file', help='Output ADML file', metavar='FILE')330  args = parser.parse_args()331  if (not args.extension_name or not args.extension_id or332      not args.schema_file or not args.admx_file or not args.adml_file):333    parser.print_help()334    return 1335  ConvertJsonToAdmx(args.extension_name, args.extension_id, args.schema_file,336                    args.admx_file, args.adml_file)337  return 0338if __name__ == '__main__':...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
