# Copyright 2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import io import re import subprocess import sys try: from configparser import Error as ConfigParserError, RawConfigParser except ImportError: from ConfigParser import Error as ConfigParserError, RawConfigParser from portage import _encodings, _unicode_encode, _unicode_decode from portage.util import writemsg def parse_desktop_entry(path): """ Parse the given file with RawConfigParser and return the result. This may raise an IOError from io.open(), or a ParsingError from RawConfigParser. """ parser = RawConfigParser() # use read_file/readfp in order to control decoding of unicode try: # Python >=3.2 read_file = parser.read_file except AttributeError: read_file = parser.readfp with io.open(_unicode_encode(path, encoding=_encodings['fs'], errors='strict'), mode='r', encoding=_encodings['repo.content'], errors='replace') as f: content = f.read() # In Python 3.2, read_file does not support bytes in file names # (see bug #429544), so use StringIO to hide the file name. read_file(io.StringIO(content)) return parser _trivial_warnings = re.compile(r' looks redundant with value ') _ignore_kde_key_re = re.compile(r'^\s*(configurationType\s*=|Type\s*=\s*Service)') _ignore_kde_types = frozenset( ["AkonadiAgent", "AkonadiResource", "Service", "ServiceType"]) # kdebase-data installs files with [Currency Code] sections # in /usr/share/locale/currency # kdepim-runtime installs files with [Plugin] and [Wizard] # sections in /usr/share/apps/akonadi/{plugins,accountwizard} _ignore_kde_sections = ("Currency Code", "Plugin", "Wizard") def validate_desktop_entry(path): args = ["desktop-file-validate", path] if sys.hexversion < 0x3000000 or sys.hexversion >= 0x3020000: # Python 3.1 does not support bytes in Popen args. args = [_unicode_encode(x, errors='strict') for x in args] proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) output_lines = _unicode_decode(proc.communicate()[0]).splitlines() proc.wait() if output_lines: # Ignore kde extensions for bug #414125 and bug #432862. try: desktop_entry = parse_desktop_entry(path) except ConfigParserError: with io.open(_unicode_encode(path, encoding=_encodings['fs'], errors='strict'), mode='r', encoding=_encodings['repo.content'], errors='replace') as f: for line in f: if _ignore_kde_key_re.match(line): # Ignore kde extensions for bug #432862. del output_lines[:] break else: if desktop_entry.has_section("Desktop Entry"): try: entry_type = desktop_entry.get("Desktop Entry", "Type") except ConfigParserError: pass else: if entry_type in _ignore_kde_types: del output_lines[:] try: desktop_entry.get("Desktop Entry", "Hidden") except ConfigParserError: pass else: # The "Hidden" key appears to be unique to special kde # service files (which don't validate well), installed # in /usr/share/kde4/services/ by packages like # nepomuk-core and kurifilter-plugins. del output_lines[:] for section in _ignore_kde_sections: if desktop_entry.has_section(section): del output_lines[:] if output_lines: output_lines = [line for line in output_lines if _trivial_warnings.search(line) is None] return output_lines if __name__ == "__main__": for arg in sys.argv[1:]: for line in validate_desktop_entry(arg): writemsg(line + "\n", noiselevel=-1)