Merge lp:~niedbalski/charm-helpers/fix-lp-1311979 into lp:charm-helpers

Proposed by Jorge Niedbalski
Status: Merged
Merged at revision: 142
Proposed branch: lp:~niedbalski/charm-helpers/fix-lp-1311979
Merge into: lp:charm-helpers
Diff against target: 278 lines (+255/-0)
4 files modified
charmhelpers/contrib/python/packages.py (+76/-0)
charmhelpers/contrib/python/version.py (+18/-0)
tests/contrib/python/test_packages.py (+134/-0)
tests/contrib/python/test_version.py (+27/-0)
To merge this branch: bzr merge lp:~niedbalski/charm-helpers/fix-lp-1311979
Reviewer Review Type Date Requested Status
Marco Ceppi Approve
charmers Pending
Review via email: mp+216975@code.launchpad.net

Description of the change

- Added a new module under contrib/python for keeping common python tasks.
 - Added contrib/python/packages, exposing pip_install/pip_uninstall/pip_list/pip_install_from_requirements
 - Added contrib/python/version, exposing current_version/current_version_string

Test status:
-----------

charmhelpers.contrib.python 0 0 100%
charmhelpers.contrib.python.packages 42 3 93% 11-13
charmhelpers.contrib.python.version 6 0 100%

Also

    - Added the fetch.is_package_installed method for
      check if a package or a list of are already installed into the system
     - Added unit tests

    Tests output:
    -------------

    tests.fetch.test_fetch.FetchTest.test_is_package_installed ... ok
    tests.fetch.test_fetch.FetchTest.test_is_package_installed_not_available ... ok

To post a comment you must log in.
Revision history for this message
Marco Ceppi (marcoceppi) wrote :

LGTM +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'charmhelpers/contrib/python'
=== added file 'charmhelpers/contrib/python/__init__.py'
=== added file 'charmhelpers/contrib/python/packages.py'
--- charmhelpers/contrib/python/packages.py 1970-01-01 00:00:00 +0000
+++ charmhelpers/contrib/python/packages.py 2014-04-24 04:23:58 +0000
@@ -0,0 +1,76 @@
1#!/usr/bin/env python
2# coding: utf-8
3
4__author__ = "Jorge Niedbalski <jorge.niedbalski@canonical.com>"
5
6from charmhelpers.fetch import apt_install
7from charmhelpers.core.hookenv import log
8
9try:
10 from pip import main as pip_execute
11except ImportError:
12 apt_install('python-pip')
13 from pip import main as pip_execute
14
15
16def parse_options(given, available):
17 """Given a set of options, check if available"""
18 for key, value in given.items():
19 if key in available:
20 yield "--{0}={1}".format(key, value)
21
22
23def pip_install_requirements(requirements, **options):
24 """Install a requirements file """
25 command = ["install"]
26
27 available_options = ('proxy', 'src', 'log', )
28 for option in parse_options(options, available_options):
29 command.append(option)
30
31 command.append("-r {0}".format(requirements))
32 log("Installing from file: {} with options: {}".format(requirements,
33 command))
34 pip_execute(command)
35
36
37def pip_install(package, fatal=False, **options):
38 """Install a python package"""
39 command = ["install"]
40
41 available_options = ('proxy', 'src', 'log', "index-url", )
42 for option in parse_options(options, available_options):
43 command.append(option)
44
45 if isinstance(package, list):
46 command.extend(package)
47 else:
48 command.append(package)
49
50 log("Installing {} package with options: {}".format(package,
51 command))
52 pip_execute(command)
53
54
55def pip_uninstall(package, **options):
56 """Uninstall a python package"""
57 command = ["uninstall", "-q", "-y"]
58
59 available_options = ('proxy', 'log', )
60 for option in parse_options(options, available_options):
61 command.append(option)
62
63 if isinstance(package, list):
64 command.extend(package)
65 else:
66 command.append(package)
67
68 log("Uninstalling {} package with options: {}".format(package,
69 command))
70 pip_execute(command)
71
72
73def pip_list():
74 """Returns the list of current python installed packages
75 """
76 return pip_execute(["list"])
077
=== added file 'charmhelpers/contrib/python/version.py'
--- charmhelpers/contrib/python/version.py 1970-01-01 00:00:00 +0000
+++ charmhelpers/contrib/python/version.py 2014-04-24 04:23:58 +0000
@@ -0,0 +1,18 @@
1#!/usr/bin/env python
2# coding: utf-8
3
4__author__ = "Jorge Niedbalski <jorge.niedbalski@canonical.com>"
5
6import sys
7
8
9def current_version():
10 """Current system python version"""
11 return sys.version_info
12
13
14def current_version_string():
15 """Current system python version as string major.minor.micro"""
16 return "{0}.{1}.{2}".format(sys.version_info.major,
17 sys.version_info.minor,
18 sys.version_info.micro)
019
=== added directory 'tests/contrib/python'
=== added file 'tests/contrib/python/__init__.py'
=== added file 'tests/contrib/python/test_packages.py'
--- tests/contrib/python/test_packages.py 1970-01-01 00:00:00 +0000
+++ tests/contrib/python/test_packages.py 2014-04-24 04:23:58 +0000
@@ -0,0 +1,134 @@
1#!/usr/bin/env python
2# coding: utf-8
3
4__author__ = "Jorge Niedbalski <jorge.niedbalski@canonical.com>"
5
6from unittest import TestCase
7from charmhelpers.contrib.python import packages
8
9import mock
10
11TO_PATCH = [
12 "apt_install",
13 "log",
14 "pip_execute"
15]
16
17
18class PipTestCase(TestCase):
19
20 def setUp(self):
21 TestCase.setUp(self)
22 self.patch_all()
23
24 self.log.return_value = True
25 self.apt_install.return_value = True
26
27 def patch(self, method):
28 _m = mock.patch.object(packages, method)
29 _mock = _m.start()
30 self.addCleanup(_m.stop)
31 return _mock
32
33 def patch_all(self):
34 for method in TO_PATCH:
35 setattr(self, method, self.patch(method))
36
37 def test_pip_install_requirements(self):
38 """
39 Check if pip_install_requirements works correctly
40 """
41 packages.pip_install_requirements("test_requirements.txt")
42 self.pip_execute.assert_called_with(["install",
43 "-r test_requirements.txt"])
44
45 packages.pip_install_requirements("test_requirements.txt",
46 proxy="proxy_addr:8080")
47
48 self.pip_execute.assert_called_with(["install",
49 "--proxy=proxy_addr:8080",
50 "-r test_requirements.txt"])
51
52 packages.pip_install_requirements("test_requirements.txt",
53 log="output.log",
54 proxy="proxy_addr:8080")
55
56 self.pip_execute.assert_called_with(["install",
57 "--log=output.log",
58 "--proxy=proxy_addr:8080",
59 "-r test_requirements.txt"])
60
61 def test_pip_install(self):
62 """
63 Check if pip_install works correctly with a single package
64 """
65 packages.pip_install("mock")
66 self.pip_execute.assert_called_with(["install",
67 "mock"])
68 packages.pip_install("mock",
69 proxy="proxy_addr:8080")
70
71 self.pip_execute.assert_called_with(["install",
72 "--proxy=proxy_addr:8080",
73 "mock"])
74 packages.pip_install("mock",
75 log="output.log",
76 proxy="proxy_addr:8080")
77
78 self.pip_execute.assert_called_with(["install",
79 "--log=output.log",
80 "--proxy=proxy_addr:8080",
81 "mock"])
82
83 def test_pip_install_multiple(self):
84 """
85 Check if pip_install works correctly with multiple packages
86 """
87 packages.pip_install(["mock", "nose"])
88 self.pip_execute.assert_called_with(["install",
89 "mock", "nose"])
90
91 def test_pip_uninstall(self):
92 """
93 Check if pip_uninstall works correctly with a single package
94 """
95 packages.pip_uninstall("mock")
96 self.pip_execute.assert_called_with(["uninstall",
97 "-q",
98 "-y",
99 "mock"])
100 packages.pip_uninstall("mock",
101 proxy="proxy_addr:8080")
102
103 self.pip_execute.assert_called_with(["uninstall",
104 "-q",
105 "-y",
106 "--proxy=proxy_addr:8080",
107 "mock"])
108 packages.pip_uninstall("mock",
109 log="output.log",
110 proxy="proxy_addr:8080")
111
112 self.pip_execute.assert_called_with(["uninstall",
113 "-q",
114 "-y",
115 "--log=output.log",
116 "--proxy=proxy_addr:8080",
117 "mock"])
118
119 def test_pip_uninstall_multiple(self):
120 """
121 Check if pip_uninstall works correctly with multiple packages
122 """
123 packages.pip_uninstall(["mock", "nose"])
124 self.pip_execute.assert_called_with(["uninstall",
125 "-q",
126 "-y",
127 "mock", "nose"])
128
129 def test_pip_list(self):
130 """
131 Checks if pip_list works correctly
132 """
133 packages.pip_list()
134 self.pip_execute.assert_called_with(["list"])
0135
=== added file 'tests/contrib/python/test_version.py'
--- tests/contrib/python/test_version.py 1970-01-01 00:00:00 +0000
+++ tests/contrib/python/test_version.py 2014-04-24 04:23:58 +0000
@@ -0,0 +1,27 @@
1#!/usr/bin/env python
2# coding: utf-8
3
4__author__ = "Jorge Niedbalski <jorge.niedbalski@canonical.com>"
5
6from unittest import TestCase
7from charmhelpers.contrib.python import version
8
9import sys
10
11
12class VersionTestCase(TestCase):
13
14 def setUp(self):
15 TestCase.setUp(self)
16
17 def test_current_version(self):
18 """
19 Check if version.current_version and version.current_version_string
20 works correctly
21 """
22 self.assertEquals(version.current_version(),
23 sys.version_info)
24 self.assertEquals(version.current_version_string(),
25 "{0}.{1}.{2}".format(sys.version_info.major,
26 sys.version_info.minor,
27 sys.version_info.micro))

Subscribers

People subscribed via source and target branches