f20217fdc6cdbfd0f9668310eda537539018b507
[yardstick.git] / yardstick / common / packages.py
1 # Copyright (c) 2018 Intel Corporation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 import logging
16 import re
17
18 import pip
19 from pip import exceptions as pip_exceptions
20 from pip.operations import freeze
21
22 from yardstick.common import privsep
23
24
25 LOG = logging.getLogger(__name__)
26
27 ACTION_INSTALL = 'install'
28 ACTION_UNINSTALL = 'uninstall'
29
30
31 @privsep.yardstick_root.entrypoint
32 def _pip_main(package, action, target=None):
33     if action == ACTION_UNINSTALL:
34         cmd = [action, package, '-y']
35     elif action == ACTION_INSTALL:
36         cmd = [action, package, '--upgrade']
37         if target:
38             cmd.append('--target=%s' % target)
39     return pip.main(cmd)
40
41
42 def _pip_execute_action(package, action=ACTION_INSTALL, target=None):
43     """Execute an action with a PIP package.
44
45     According to [1], a package could be a URL, a local directory, a local dist
46     file or a requirements file.
47
48     [1] https://pip.pypa.io/en/stable/reference/pip_install/#argument-handling
49     """
50     try:
51         status = _pip_main(package, action, target)
52     except pip_exceptions.PipError:
53         status = 1
54
55     if not status:
56         LOG.info('Action "%s" executed, package %s', package, action)
57     else:
58         LOG.info('Error executing action "%s", package %s', package, action)
59     return status
60
61
62 def pip_remove(package):
63     """Remove an installed PIP package"""
64     return _pip_execute_action(package, action=ACTION_UNINSTALL)
65
66
67 def pip_install(package, target=None):
68     """Install a PIP package"""
69     return _pip_execute_action(package, action=ACTION_INSTALL, target=target)
70
71
72 def pip_list(pkg_name=None):
73     """Dict of installed PIP packages with version.
74
75     If 'pkg_name' is not None, will return only those packages matching the
76     name."""
77     pip_regex = re.compile(r"(?P<name>.*)==(?P<version>[\w\.]+)")
78     git_regex = re.compile(r".*@(?P<version>[\w]+)#egg=(?P<name>[\w]+)")
79
80     pkg_dict = {}
81     for _pkg in freeze.freeze(local_only=True):
82         match = pip_regex.match(_pkg) or git_regex.match(_pkg)
83         if match and (not pkg_name or (
84                 pkg_name and match.group('name').find(pkg_name) != -1)):
85             pkg_dict[match.group('name')] = match.group('version')
86
87     return pkg_dict