Remove python-2.6 StringIO.StringIO fallback.
[portage.git] / pym / portage / package / ebuild / _ipc / QueryCommand.py
1 # Copyright 2010-2011 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 import io
5
6 import portage
7 from portage import os
8 from portage import _encodings
9 from portage import _unicode_decode
10 from portage.dep import Atom
11 from portage.elog import messages as elog_messages
12 from portage.exception import InvalidAtom
13 from portage.package.ebuild._ipc.IpcCommand import IpcCommand
14 from portage.util import normalize_path
15 from portage.versions import best
16
17 class QueryCommand(IpcCommand):
18
19         __slots__ = ('phase', 'settings',)
20
21         _db = None
22
23         def __init__(self, settings, phase):
24                 IpcCommand.__init__(self)
25                 self.settings = settings
26                 self.phase = phase
27
28         def __call__(self, argv):
29                 """
30                 @returns: tuple of (stdout, stderr, returncode)
31                 """
32
33                 cmd, root, atom_str = argv
34
35                 try:
36                         atom = Atom(atom_str)
37                 except InvalidAtom:
38                         return ('', 'invalid atom: %s\n' % atom_str, 2)
39
40                 warnings = []
41                 try:
42                         atom = Atom(atom_str, eapi=self.settings.get('EAPI'))
43                 except InvalidAtom as e:
44                         warnings.append(_unicode_decode("QA Notice: %s: %s") % (cmd, e))
45
46                 use = self.settings.get('PORTAGE_BUILT_USE')
47                 if use is None:
48                         use = self.settings['PORTAGE_USE']
49
50                 use = frozenset(use.split())
51                 atom = atom.evaluate_conditionals(use)
52
53                 db = self._db
54                 if db is None:
55                         db = portage.db
56
57                 warnings_str = ''
58                 if warnings:
59                         warnings_str = self._elog('eqawarn', warnings)
60
61                 root = normalize_path(root).rstrip(os.path.sep) + os.path.sep
62                 if root not in db:
63                         return ('', 'invalid ROOT: %s\n' % root, 2)
64
65                 vardb = db[root]["vartree"].dbapi
66
67                 if cmd == 'has_version':
68                         if vardb.match(atom):
69                                 returncode = 0
70                         else:
71                                 returncode = 1
72                         return ('', warnings_str, returncode)
73                 elif cmd == 'best_version':
74                         m = best(vardb.match(atom))
75                         return ('%s\n' % m, warnings_str, 0)
76                 else:
77                         return ('', 'invalid command: %s\n' % cmd, 2)
78
79         def _elog(self, elog_funcname, lines):
80                 """
81                 This returns a string, to be returned via ipc and displayed at the
82                 appropriate place in the build output. We wouldn't want to open the
83                 log here since it is already opened by AbstractEbuildProcess and we
84                 don't want to corrupt it, especially if it is being written with
85                 compression.
86                 """
87                 out = io.StringIO()
88                 phase = self.phase
89                 elog_func = getattr(elog_messages, elog_funcname)
90                 global_havecolor = portage.output.havecolor
91                 try:
92                         portage.output.havecolor = \
93                                 self.settings.get('NOCOLOR', 'false').lower() in ('no', 'false')
94                         for line in lines:
95                                 elog_func(line, phase=phase, key=self.settings.mycpv, out=out)
96                 finally:
97                         portage.output.havecolor = global_havecolor
98                 msg = _unicode_decode(out.getvalue(),
99                         encoding=_encodings['content'], errors='replace')
100                 return msg