def check_glade_file(glade_file_path, po_map=None): glade_success = True with open(glade_file_path) as glade_file: # Parse the XML glade_tree = etree.parse(glade_file) # Search for label properties on objects that have use_markup set to True for label in glade_tree.xpath( ".//property[@name='label' and ../property[@name='use_markup']/text() = 'True']" ): if po_map: try: label_texts = po_map.get(label.text, label.get("context")) except KeyError: continue lang_str = " for language %s" % po_map.metadata['Language'] else: label_texts = (label.text, ) lang_str = "" # Wrap the label text in <markup> tags and parse the tree for label_text in label_texts: try: # pylint: disable=unescaped-markup pango_tree = etree.fromstring("<markup>%s</markup>" % label_text) _validate_pango_markup(pango_tree) # Check if the markup is necessary if not markup_necessary(pango_tree): print("Markup could be expressed as attributes at %s%s:%d" % \ (glade_file_path, lang_str, label.sourceline)) glade_success = False except etree.XMLSyntaxError: print("Unable to parse pango markup at %s%s:%d" % \ (glade_file_path, lang_str, label.sourceline)) glade_success = False except PangoElementException as px: print("Invalid pango element %s at %s%s:%d" % \ (px.element, glade_file_path, lang_str, label.sourceline)) glade_success = False else: if po_map: # Check that translated markup has the same elements and attributes if not markup_match(label.text, label_text): print("Translated markup does not contain the same elements and attributes at %s%s:%d" % \ (glade_file_path, lang_str, label.sourceline)) glade_success = False return glade_success
def check_glade_file(glade_file_path, po_map=None): glade_success = True with open(glade_file_path) as glade_file: # Parse the XML glade_tree = etree.parse(glade_file) # Search for label properties on objects that have use_markup set to True for label in glade_tree.xpath(".//property[@name='label' and ../property[@name='use_markup']/text() = 'True']"): if po_map: try: label_texts = po_map.get(label.text, label.get("context")) except KeyError: continue lang_str = " for language %s" % po_map.metadata['Language'] else: label_texts = (label.text,) lang_str = "" # Wrap the label text in <markup> tags and parse the tree for label_text in label_texts: try: # pylint: disable=unescaped-markup pango_tree = etree.fromstring("<markup>%s</markup>" % label_text) _validate_pango_markup(pango_tree) # Check if the markup is necessary if not markup_necessary(pango_tree): print("Markup could be expressed as attributes at %s%s:%d" % \ (glade_file_path, lang_str, label.sourceline)) glade_success = False except etree.XMLSyntaxError: print("Unable to parse pango markup at %s%s:%d" % \ (glade_file_path, lang_str, label.sourceline)) glade_success = False except PangoElementException as px: print("Invalid pango element %s at %s%s:%d" % \ (px.element, glade_file_path, lang_str, label.sourceline)) glade_success = False else: if po_map: # Check that translated markup has the same elements and attributes if not markup_match(label.text, label_text): print("Translated markup does not contain the same elements and attributes at %s%s:%d" % \ (glade_file_path, lang_str, label.sourceline)) glade_success = False return glade_success
def visit_const(self, node): if not isinstance(node.value, types.StringType) and not isinstance(node.value, types.UnicodeType): return if not is_markup(node.value): return self._validate_pango_markup_string(node, node.value) # Check translated versions of the string if requested if self.config.translate_markup: global podicts # Check if this is a translatable string curr = node i18nFunc = None while curr.parent: if isinstance(curr.parent, astroid.CallFunc) and \ getattr(curr.parent.func, "name", "") in i18n_funcs: i18nFunc = curr.parent break curr = curr.parent if i18nFunc: # If not done already, import polib and read the translations if not podicts: try: from translatepo import translate_all except ImportError: print("Unable to load po translation module") sys.exit(99) else: podicts = translate_all(os.path.join(os.environ.get('top_srcdir', '.'), 'po')) if i18nFunc.func.name in i18n_ctxt_funcs: msgctxt = i18nFunc.args[0].value else: msgctxt = None # Loop over all translations for the string for podict in podicts.values(): try: node_values = podict.get(node.value, msgctxt) except KeyError: continue for value in node_values: self._validate_pango_markup_string(node, value, podict.metadata['Language']) # Check that the markup matches, roughly if not markup_match(node.value, value): self.add_message("W9925", node=node, args=(podict.metadata['Language'],)) # Check if this the left side of a % operation curr = node formatOp = None while curr.parent: if isinstance(curr.parent, astroid.BinOp) and curr.parent.op == "%" and \ curr.parent.left == curr: formatOp = curr.parent break curr = curr.parent # Check whether the right side of the % operation is escaped if formatOp: if isinstance(formatOp.right, astroid.CallFunc): if getattr(formatOp.right.func, "name", "") not in escapeMethods: self.add_message("W9922", node=formatOp.right) # If a tuple, each item in the tuple must be escaped elif isinstance(formatOp.right, astroid.Tuple): for elt in formatOp.right.elts: if not isinstance(elt, astroid.CallFunc) or\ getattr(elt.func, "name", "") not in escapeMethods: self.add_message("W9922", node=elt) # If a dictionary, each value must be escaped elif isinstance(formatOp.right, astroid.Dict): for item in formatOp.right.items: if not isinstance(item[1], astroid.CallFunc) or\ getattr(item[1].func, "name", "") not in escapeMethods: self.add_message("W9922", node=item[1]) else: self.add_message("W9922", node=formatOp)
def visit_const(self, node): if type(node.value) not in (types.StringType, types.UnicodeType): return if not is_markup(node.value): return self._validate_pango_markup_string(node, node.value) # Check translated versions of the string if requested if self.config.translate_markup: global podicts # Check if this is a translatable string curr = node i18nFunc = None while curr.parent: if isinstance(curr.parent, astroid.CallFunc) and \ getattr(curr.parent.func, "name", "") in i18n_funcs: i18nFunc = curr.parent break curr = curr.parent if i18nFunc: # If not done already, import polib and read the translations if not podicts: try: from translatepo import translate_all except ImportError: print("Unable to load po translation module") sys.exit(99) else: podicts = translate_all( os.path.join(os.environ.get('top_srcdir', '.'), 'po')) if i18nFunc.func.name in i18n_ctxt_funcs: msgctxt = i18nFunc.args[0].value else: msgctxt = None # Loop over all translations for the string for podict in podicts.values(): try: node_values = podict.get(node.value, msgctxt) except KeyError: continue for value in node_values: self._validate_pango_markup_string( node, value, podict.metadata['Language']) # Check that the markup matches, roughly if not markup_match(node.value, value): self.add_message( "W9925", node=node, args=(podict.metadata['Language'], )) # Check if this the left side of a % operation curr = node formatOp = None while curr.parent: if isinstance(curr.parent, astroid.BinOp) and curr.parent.op == "%" and \ curr.parent.left == curr: formatOp = curr.parent break curr = curr.parent # Check whether the right side of the % operation is escaped if formatOp: if isinstance(formatOp.right, astroid.CallFunc): if getattr(formatOp.right.func, "name", "") not in escapeMethods: self.add_message("W9922", node=formatOp.right) # If a tuple, each item in the tuple must be escaped elif isinstance(formatOp.right, astroid.Tuple): for elt in formatOp.right.elts: if not isinstance(elt, astroid.CallFunc) or\ getattr(elt.func, "name", "") not in escapeMethods: self.add_message("W9922", node=elt) # If a dictionary, each value must be escaped elif isinstance(formatOp.right, astroid.Dict): for item in formatOp.right.items: if not isinstance(item[1], astroid.CallFunc) or\ getattr(item[1].func, "name", "") not in escapeMethods: self.add_message("W9922", node=item[1]) else: self.add_message("W9922", node=formatOp)