~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_export_pot.py

(gz) Add _ModuleContext to track location in source and other refactorings
 in export_pot (Martin Packman)

Show diffs side-by-side

added added

removed removed

Lines of Context:
67
67
        self.assertEqual(export_pot._normalize(s), e)
68
68
 
69
69
 
 
70
class TestParseSource(tests.TestCase):
 
71
    """Check mappings to line numbers generated from python source"""
 
72
 
 
73
    def test_classes(self):
 
74
        src = '''
 
75
class Ancient:
 
76
    """Old style class"""
 
77
 
 
78
class Modern(object):
 
79
    """New style class"""
 
80
'''
 
81
        cls_lines, _ = export_pot._parse_source(src)
 
82
        self.assertEqual(cls_lines,
 
83
            {"Ancient": 2, "Modern": 5})
 
84
 
 
85
    def test_classes_nested(self):
 
86
        src = '''
 
87
class Matroska(object):
 
88
    class Smaller(object):
 
89
        class Smallest(object):
 
90
            pass
 
91
'''
 
92
        cls_lines, _ = export_pot._parse_source(src)
 
93
        self.assertEqual(cls_lines,
 
94
            {"Matroska": 2, "Smaller": 3, "Smallest":4})
 
95
 
 
96
    def test_strings_docstrings(self):
 
97
        src = '''\
 
98
"""Module"""
 
99
 
 
100
def function():
 
101
    """Function"""
 
102
 
 
103
class Class(object):
 
104
    """Class"""
 
105
 
 
106
    def method(self):
 
107
        """Method"""
 
108
'''
 
109
        _, str_lines = export_pot._parse_source(src)
 
110
        self.assertEqual(str_lines,
 
111
            {"Module": 1, "Function": 4, "Class": 7, "Method": 10})
 
112
 
 
113
    def test_strings_literals(self):
 
114
        src = '''\
 
115
s = "One"
 
116
t = (2, "Two")
 
117
f = dict(key="Three")
 
118
'''
 
119
        _, str_lines = export_pot._parse_source(src)
 
120
        self.assertEqual(str_lines,
 
121
            {"One": 1, "Two": 2, "Three": 3})
 
122
 
 
123
    def test_strings_multiline(self):
 
124
        src = '''\
 
125
"""Start
 
126
 
 
127
End
 
128
"""
 
129
t = (
 
130
    "A"
 
131
    "B"
 
132
    "C"
 
133
    )
 
134
'''
 
135
        _, str_lines = export_pot._parse_source(src)
 
136
        self.assertEqual(str_lines,
 
137
            {"Start\n\nEnd\n": 1, "ABC": 6})
 
138
 
 
139
    def test_strings_multiline_escapes(self):
 
140
        src = '''\
 
141
s = "Escaped\\n"
 
142
r = r"Raw\\n"
 
143
t = (
 
144
    "A\\n\\n"
 
145
    "B\\n\\n"
 
146
    "C\\n\\n"
 
147
    )
 
148
'''
 
149
        _, str_lines = export_pot._parse_source(src)
 
150
        self.expectFailure("Escaped newlines confuses the multiline handling",
 
151
            self.assertNotEqual, str_lines,
 
152
            {"Escaped\n": 0, "Raw\\n": 2, "A\n\nB\n\nC\n\n": -2})
 
153
        self.assertEqual(str_lines,
 
154
            {"Escaped\n": 1, "Raw\\n": 2, "A\n\nB\n\nC\n\n": 4})
 
155
 
 
156
 
 
157
class TestModuleContext(tests.TestCase):
 
158
    """Checks for source context tracking objects"""
 
159
 
 
160
    def check_context(self, context, path, lineno):
 
161
        self.assertEquals((context.path, context.lineno), (path, lineno))
 
162
 
 
163
    def test___init__(self):
 
164
        context = export_pot._ModuleContext("one.py")
 
165
        self.check_context(context, "one.py", 1)
 
166
        context = export_pot._ModuleContext("two.py", 5)
 
167
        self.check_context(context, "two.py", 5)
 
168
 
 
169
    def test_from_class(self):
 
170
        """New context returned with lineno updated from class"""
 
171
        path = "cls.py"
 
172
        class A(object): pass
 
173
        class B(object): pass
 
174
        cls_lines = {"A": 5, "B": 7}
 
175
        context = export_pot._ModuleContext(path, _source_info=(cls_lines, {}))
 
176
        contextA = context.from_class(A)
 
177
        self.check_context(contextA, path, 5)
 
178
        contextB1 = context.from_class(B)
 
179
        self.check_context(contextB1, path, 7)
 
180
        contextB2 = contextA.from_class(B)
 
181
        self.check_context(contextB2, path, 7)
 
182
        self.check_context(context, path, 1)
 
183
        self.assertEquals("", self.get_log())
 
184
 
 
185
    def test_from_class_missing(self):
 
186
        """When class has no lineno the old context details are returned"""
 
187
        path = "cls_missing.py"
 
188
        class A(object): pass
 
189
        class M(object): pass
 
190
        context = export_pot._ModuleContext(path, 3, ({"A": 15}, {}))
 
191
        contextA = context.from_class(A)
 
192
        contextM1 = context.from_class(M)
 
193
        self.check_context(contextM1, path, 3)
 
194
        contextM2 = contextA.from_class(M)
 
195
        self.check_context(contextM2, path, 15)
 
196
        self.assertContainsRe(self.get_log(), "Definition of <.*M'> not found")
 
197
 
 
198
    def test_from_string(self):
 
199
        """New context returned with lineno updated from string"""
 
200
        path = "str.py"
 
201
        str_lines = {"one": 14, "two": 42}
 
202
        context = export_pot._ModuleContext(path, _source_info=({}, str_lines))
 
203
        context1 = context.from_string("one")
 
204
        self.check_context(context1, path, 14)
 
205
        context2A = context.from_string("two")
 
206
        self.check_context(context2A, path, 42)
 
207
        context2B = context1.from_string("two")
 
208
        self.check_context(context2B, path, 42)
 
209
        self.check_context(context, path, 1)
 
210
        self.assertEquals("", self.get_log())
 
211
 
 
212
    def test_from_string_missing(self):
 
213
        """When string has no lineno the old context details are returned"""
 
214
        path = "str_missing.py"
 
215
        context = export_pot._ModuleContext(path, 4, ({}, {"line\n": 21}))
 
216
        context1 = context.from_string("line\n")
 
217
        context2A = context.from_string("not there")
 
218
        self.check_context(context2A, path, 4)
 
219
        context2B = context1.from_string("not there")
 
220
        self.check_context(context2B, path, 21)
 
221
        self.assertContainsRe(self.get_log(), "String 'not there' not found")
 
222
 
 
223
 
70
224
class PoEntryTestCase(tests.TestCase):
71
225
 
72
226
    def setUp(self):
79
233
                textwrap.dedent(expected)
80
234
                )
81
235
 
 
236
 
82
237
class TestPoEntry(PoEntryTestCase):
83
238
 
84
239
    def test_simple(self):