~ci-train-bot/ubuntu-system-image/system-image-ubuntu-xenial-landing-023

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# Copyright (C) 2013-2016 Canonical Ltd.
# Author: Barry Warsaw <barry@ubuntu.com>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Test the Bag class."""

__all__ = [
    'TestBag',
    ]


import pickle
import unittest

from operator import setitem
from systemimage.bag import Bag


class TestBag(unittest.TestCase):
    def test_simple(self):
        # Initialize a bag; its attributes are the keywords of the ctor.
        bag = Bag(a=1, b=2, c=3)
        self.assertEqual(bag.a, 1)
        self.assertEqual(bag.b, 2)
        self.assertEqual(bag.c, 3)

    def test_dash_translation(self):
        # Dashes in keys get turned into underscore in attributes.
        bag = Bag(**{'a-b': 1, 'c-d': 2, 'e-f': 3})
        self.assertEqual(bag.a_b, 1)
        self.assertEqual(bag.c_d, 2)
        self.assertEqual(bag.e_f, 3)

    def test_dash_literal_access(self):
        # For keys with dashes, the original name is preserved in getitem.
        bag = Bag(**{'a-b': 1, 'c-d': 2, 'e-f': 3})
        self.assertEqual(bag['a-b'], 1)
        self.assertEqual(bag['c-d'], 2)
        self.assertEqual(bag['e-f'], 3)

    def test_keyword_translation(self):
        # Python keywords get a trailing underscore.
        bag = Bag(**{'global': 1, 'with': 2, 'import': 3})
        self.assertEqual(bag.global_, 1)
        self.assertEqual(bag.with_, 2)
        self.assertEqual(bag.import_, 3)

    def test_repr(self):
        # The repr of a bag includes its translated keys.
        bag = Bag(**{'a-b': 1, 'global': 2, 'foo': 3})
        self.assertEqual(repr(bag), '<Bag: a_b, foo, global_>')

    def test_original(self):
        # There's a magical attribute containing the original ctor arguments.
        source = {'a-b': 1, 'global': 2, 'foo': 3}
        bag = Bag(**source)
        self.assertEqual(bag.__original__, source)

    def test_add_key(self):
        # We can add new keys/attributes via setitem.
        bag = Bag(a=1, b=2, c=3)
        bag['d'] = bag.b + bag.c
        self.assertEqual(bag.d, 5)

    def test_add_existing_key(self):
        # A key set in the original ctor cannot be changed.
        bag = Bag(a=1, b=2, c=3)
        self.assertRaises(ValueError, setitem, bag, 'b', 5)
        self.assertEqual(bag.b, 2)

    def test_add_new_key(self):
        # A key added by setitem can be changed.
        bag = Bag(a=1, b=2, c=3)
        bag['d'] = 4
        bag['d'] = 5
        self.assertEqual(bag.d, 5)

    def test_pickle(self):
        # Bags can be pickled and unpickled.
        bag = Bag(a=1, b=2, c=3)
        pck = pickle.dumps(bag)
        new_bag = pickle.loads(pck)
        self.assertEqual(new_bag.a, 1)
        self.assertEqual(new_bag.b, 2)
        self.assertEqual(new_bag.c, 3)

    def test_update(self):
        # Bags can be updated, similar to dicts.
        bag = Bag(a=1, b=2, c=3)
        bag.update(b=7, d=9)
        self.assertEqual(bag.a, 1)
        self.assertEqual(bag.b, 7)
        self.assertEqual(bag.c, 3)
        self.assertEqual(bag.d, 9)

    def test_converters(self):
        # The Bag ctor accepts a mapping of type converter functions.
        bag = Bag(converters=dict(a=int, b=int),
                  a='1', b='2', c='3')
        self.assertEqual(bag.a, 1)
        self.assertEqual(bag.b, 2)
        self.assertEqual(bag.c, '3')

    def test_converters_error(self):
        # Type converter function errors get propagated.
        converters = dict(a=int, b=int)
        keywords = dict(a='1', b='foo', c=3)
        self.assertRaises(ValueError, Bag, converters=converters, **keywords)

    def test_update_converters(self):
        # The update method also accepts converters.
        bag = Bag(a=1, b=2, c=3)
        bag.update(converters=dict(d=int),
                   d='4', e='5')
        self.assertEqual(bag.d, 4)
        self.assertEqual(bag.e, '5')

    def test_update_converter_overrides(self):
        # Converters in the update method permanently override ctor converters.
        converters = dict(a=int, b=int)
        bag = Bag(converters=converters, a='1', b='2')
        self.assertEqual(bag.a, 1)
        self.assertEqual(bag.b, 2)
        new_converters = dict(a=str)
        bag.update(converters=new_converters, a='3', b='4')
        self.assertEqual(bag.a, '3')
        self.assertEqual(bag.b, 4)
        bag.update(a='5', b='6')
        self.assertEqual(bag.a, '5')
        self.assertEqual(bag.b, 6)


    def test_keys(self):
        bag = Bag(c=1, b=2, a=3)
        self.assertEqual(sorted(bag.keys()), ['a', 'b', 'c'])

    def test_iter(self):
        # Iteration is over the available keys.
        bag = Bag(c=1, b=2, a=3)
        self.assertEqual(sorted(bag, reverse=True), ['c', 'b', 'a'])

    def test_get(self):
        # You can get a single key.  If missing, None or a supplied default is
        # returned.
        bag = Bag(c=1, b=2, a=3)
        self.assertEqual(bag.get('b'), 2)
        self.assertIsNone(bag.get('missing'))
        missing = object()
        self.assertIs(bag.get('missing', missing), missing)