File: tests.py

package info (click to toggle)
python-titlecase 2.4.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 112 kB
  • sloc: python: 547; makefile: 4
file content (434 lines) | stat: -rw-r--r-- 13,652 bytes parent folder | download | duplicates (2)
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Tests for titlecase"""

import os
import sys
import tempfile
import unittest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../'))
from titlecase import titlecase, set_small_word_list, create_wordlist_filter_from_file


# (executed by `test_input_output` below)
TEST_DATA = (
    (
        "",
        ""
    ),
    (
        "word/word",
        "Word/Word"
    ),
    (
        "a title and/or string",
        "A Title and/or String"
    ),
    (
        "dance with me/let’s face the music and dance",
        "Dance With Me/Let’s Face the Music and Dance"
    ),
    (
        "a-b end-to-end two-not-three/three-by-four/five-and",
        "A-B End-to-End Two-Not-Three/Three-by-Four/Five-And"
    ),
    (
        "34th 3rd 2nd",
        "34th 3rd 2nd"
    ),
    (
        "Q&A with steve jobs: 'that's what happens in technology'",
        "Q&A With Steve Jobs: 'That's What Happens in Technology'"
    ),
    (
        "What is AT&T's problem?",
        "What Is AT&T's Problem?"
    ),
    (
        "Apple deal with AT&T falls through",
        "Apple Deal With AT&T Falls Through"
    ),
    (
        "Words with all consonants like cnn are acronyms",
        "Words With All Consonants Like CNN Are Acronyms"
    ),
    (
        "this v that",
        "This v That"
    ),
    (
        "this v. that",
        "This v. That"
    ),
    (
        "this vs that",
        "This vs That"
    ),
    (
        "this vs. that",
        "This vs. That"
    ),
    (
        "The SEC's Apple probe: what you need to know",
        "The SEC's Apple Probe: What You Need to Know"
    ),
    (
        "'by the Way, small word at the start but within quotes.'",
        "'By the Way, Small Word at the Start but Within Quotes.'"
    ),
    (
        "Small word at end is nothing to be afraid of",
        "Small Word at End Is Nothing to Be Afraid Of"
    ),
    (
        "Starting Sub-Phrase With a Small Word: a Trick, Perhaps?",
        "Starting Sub-Phrase With a Small Word: A Trick, Perhaps?"
    ),
    (
        "Sub-Phrase With a Small Word in Quotes: 'a Trick, Perhaps?'",
        "Sub-Phrase With a Small Word in Quotes: 'A Trick, Perhaps?'"
    ),
    (
        'sub-phrase with a small word in quotes: "a trick, perhaps?"',
        'Sub-Phrase With a Small Word in Quotes: "A Trick, Perhaps?"'
    ),
    (
        "Starting a Hyphen Delimited Sub-Phrase With a Small Word - a Trick, Perhaps?",
        "Starting a Hyphen Delimited Sub-Phrase With a Small Word - A Trick, Perhaps?"
    ),
    (
        "Hyphen Delimited Sub-Phrase With a Small Word in Quotes - 'a Trick, Perhaps?'",
        "Hyphen Delimited Sub-Phrase With a Small Word in Quotes - 'A Trick, Perhaps?'"
    ),
    (
        'Hyphen Delimited sub-phrase with a small word in quotes - "a trick, perhaps?"',
        'Hyphen Delimited Sub-Phrase With a Small Word in Quotes - "A Trick, Perhaps?"'
    ),
    (
        "Snakes on a Plane - The TV Edit - The Famous Line",
        "Snakes on a Plane - The TV Edit - The Famous Line"
    ),
    (
        "Starting an Em Dash Delimited Sub-Phrase With a Small Word — a Trick, Perhaps?",
        "Starting an Em Dash Delimited Sub-Phrase With a Small Word — A Trick, Perhaps?"
    ),
    (
        "Em Dash Delimited Sub-Phrase With a Small Word in Quotes — 'a Trick, Perhaps?'",
        "Em Dash Delimited Sub-Phrase With a Small Word in Quotes — 'A Trick, Perhaps?'"
    ),
    (
        'Em Dash Delimited sub-phrase with a small word in quotes — "a trick, perhaps?"',
        'Em Dash Delimited Sub-Phrase With a Small Word in Quotes — "A Trick, Perhaps?"'
    ),
    (
        "Snakes on a Plane — The TV Edit — The Famous Line",
        "Snakes on a Plane — The TV Edit — The Famous Line"
    ),
    (
        "EPISODE 7 — THE FORCE AWAKENS",
        "Episode 7 — The Force Awakens"
    ),
    (
        "episode 7 – The force awakens",
        "Episode 7 – The Force Awakens"
    ),
    (
        "THE CASE OF X ≤ 7",
        "The Case of X ≤ 7"
    ),
    (
        "the case of X ≤ 7",
        "The Case of X ≤ 7"
    ),
    (
        '"Nothing to Be Afraid of?"',
        '"Nothing to Be Afraid Of?"'
    ),
    (
        '"Nothing to be Afraid Of?"',
        '"Nothing to Be Afraid Of?"'
    ),
    (
        'a thing',
        'A Thing'
    ),
    (
        "2lmc Spool: 'gruber on OmniFocus and vapo(u)rware'",
        "2lmc Spool: 'Gruber on OmniFocus and Vapo(u)rware'"
    ),
    (
        'this is just an example.com',
        'This Is Just an example.com'
    ),
    (
        'this is something listed on del.icio.us',
        'This Is Something Listed on del.icio.us'
    ),
    (
        'iTunes should be unmolested',
        'iTunes Should Be Unmolested'
    ),
    (
        'reading between the lines of steve jobs’s ‘thoughts on music’',
        'Reading Between the Lines of Steve Jobs’s ‘Thoughts on Music’'
    ),
    (
        'seriously, ‘repair permissions’ is voodoo',
        'Seriously, ‘Repair Permissions’ Is Voodoo'
    ),
    (
        'generalissimo francisco franco: still dead; kieren McCarthy: still a jackass',
        'Generalissimo Francisco Franco: Still Dead; Kieren McCarthy: Still a Jackass'
    ),
    (
        "O'Reilly should be untouched",
        "O'Reilly Should Be Untouched"
    ),
    (
        "my name is o'reilly",
        "My Name Is O'Reilly"
    ),
    (
        "WASHINGTON, D.C. SHOULD BE FIXED BUT MIGHT BE A PROBLEM",
        "Washington, D.C. Should Be Fixed but Might Be a Problem"
    ),
    (
        "THIS IS ALL CAPS AND SHOULD BE ADDRESSED",
        "This Is All Caps and Should Be Addressed"
    ),
    (
        "Mr McTavish went to MacDonalds",
        "Mr McTavish Went to MacDonalds"
    ),
    (
        "this shouldn't\nget mangled",
        "This Shouldn't\nGet Mangled"
    ),
    (
        "this is http://foo.com",
        "This Is http://foo.com"
    ),
    (
        "mac mc MAC MC machine",
        "Mac Mc MAC MC Machine",
    ),
    (
        "FOO BAR 5TH ST",
        "Foo Bar 5th St",
    ),
    (
        "foo bar 5th st",
        "Foo Bar 5th St",
    ),
    (
        "l'grange l'grange l'Grange l'Grange",
        "l'Grange l'Grange l'Grange l'Grange",
    ),
    (
        "L'grange L'grange L'Grange L'Grange",
        "l'Grange l'Grange l'Grange l'Grange",
    ),
    (
        "l'GranGe",
        "l'GranGe",
    ),
    (
        "o'grange O'grange o'Grange O'Grange",
        "O'Grange O'Grange O'Grange O'Grange",
    ),
    (
        "o'grange's O'grange's o'Grange's O'Grange's",
        "O'Grange's O'Grange's O'Grange's O'Grange's",
    ),
    (
        "O'GranGe",
        "O'GranGe",
    ),
    (
        "o'melveny/o'doyle o'Melveny/o'doyle O'melveny/o'doyle o'melveny/o'Doyle o'melveny/O'doyle",
        "O'Melveny/O'Doyle O'Melveny/O'Doyle O'Melveny/O'Doyle O'Melveny/O'Doyle O'Melveny/O'Doyle",
    ),
    # These 'Mc' cases aim to ensure more consistent/predictable behavior.
    # The examples here are somewhat contrived, and are subject to change
    # if there is a compelling argument for updating their behavior.
    # See https://github.com/ppannuto/python-titlecase/issues/64
    (
        "mccay-mcbut-mcdo mcdonalds/mcby",
        "McCay-McBut-McDo McDonalds/McBy"
    ),
    (
        "oblon, spivak, mcclelland, maier & neustadt",
        "Oblon, Spivak, McClelland, Maier & Neustadt",
    ),
    (
        "Mcoblon, spivak, mcclelland, mcmaier, & mcneustadt",
        "McOblon, Spivak, McClelland, McMaier, & McNeustadt",
    ),
    (
        "mcfoo-bar, MCFOO-BAR, McFoo-bar, McFoo-Bar, mcfoo-mcbar, foo-mcbar",
        "McFoo-Bar, McFoo-Bar, McFoo-Bar, McFoo-Bar, McFoo-McBar, Foo-McBar",
    ),
    (
        "'QUOTE' A GREAT",
        "'Quote' a Great",
    ),
    (
        "‘QUOTE’ A GREAT",
        "‘Quote’ a Great",
    ),
    (
        "“YOUNG AND RESTLESS”",
        "“Young and Restless”",
    ),
    (
        "EL NIÑO A ARRIVÉ HIER",
        "El Niño a Arrivé Hier",
    ),
    (
        "YEA NO",
        "Yea No",
    ),
    (
        "ÝÆ ÑØ",
        "Ýæ Ñø",
    ),
    (
        "yea no",
        "Yea No",
    ),
    (
        "ýæ ñø",
        "Ýæ Ñø",
    ),
    # https://github.com/ppannuto/python-titlecase/pull/67
    (
        "Mr mr Mrs Ms Mss Dr dr , Mr. and Mrs. Person",
        "Mr Mr Mrs Ms MSS Dr Dr , Mr. And Mrs. Person",
    ),
)


class TestStringSuite(unittest.TestCase):
    """Generated tests from strings"""

    def test_specific_string(self):
        for data in TEST_DATA:
            with self.subTest():
                self.assertEqual(titlecase(data[0]), data[1])


class TestInitialsRegex(unittest.TestCase):
    def test_initials_regex(self):
        """Test - uppercase initials regex with A.B"""
        from titlecase import UC_INITIALS
        #assert bool(UC_INITIALS.match('A.B')) is True
        self.assertRegex('A.B', UC_INITIALS)

    def test_initials_regex_2(self):
        """Test - uppercase initials regex with A.B."""
        from titlecase import UC_INITIALS
        #assert bool(UC_INITIALS.match('A.B.')) is True
        self.assertRegex('A.B.', UC_INITIALS)

    def test_initials_regex_3(self):
        """Test - uppercase initials regex with ABCD"""
        from titlecase import UC_INITIALS
        #assert bool(UC_INITIALS.match('ABCD')) is False
        self.assertNotRegex('ABCD', UC_INITIALS)


class TestSymbols(unittest.TestCase):
    @staticmethod
    def at_n_t(word, **kwargs):
        if word.upper() == "AT&T":
            return word.upper()

    def test_at_n_t(self):
        self.assertEqual(titlecase("at&t", callback=TestSymbols.at_n_t), "AT&T")


class TestCallback(unittest.TestCase):
    @staticmethod
    def abbreviation(word, **kwargs):
        if word.upper() in ('TCP', 'UDP'):
            return word.upper()

    def test_callback(self):
        s = 'a simple tcp and udp wrapper'
        # Note: this library is able to guess that all-consonant words are acronyms, so TCP
        # works naturally, but others will require the custom list
        self.assertEqual(titlecase(s),
                'A Simple TCP and Udp Wrapper')
        self.assertEqual(titlecase(s, callback=TestCallback.abbreviation),
                'A Simple TCP and UDP Wrapper')
        self.assertEqual(titlecase(s.upper(), callback=TestCallback.abbreviation),
                'A Simple TCP and UDP Wrapper')
        self.assertEqual(titlecase(u'crème brûlée', callback=lambda x, **kw: x.upper()),
                u'CRÈME BRÛLÉE')


# It looks like set_small_word_list uses different regexs that the original
# setup code path :/. It really should be the case that one could call
# titlecase.set_small_word_list() and reset to the original behavior (it
# _really_ should be the case that there aren't all these ugly globals around).
#
# It seems that `nose` ran every test in isolation, or just in a different
# order, so the global state bug wasn't caught before. This should be fixed,
# but one thingg at a time.
@unittest.skip("FIXME: Converting to unittest exposed a bug")
class TestSmallWordList(unittest.TestCase):
    def test_set_small_word_list(self):
        self.assertEqual(titlecase('playing the game "words with friends"'),
                'Playing the Game "Words With Friends"')
        set_small_word_list('a|an|the|with')
        self.assertEqual(titlecase('playing the game "words with friends"'),
                'Playing the Game "Words with Friends"')


class TestCustomAbbreviations(unittest.TestCase):
    def setUp(self):
        # Do not delete on close, instead do manually for Windows (see #86).
        self.f = tempfile.NamedTemporaryFile(mode='w', delete=False)
        self.f.write('UDP\nPPPoE\n')
        self.f.flush()

    def tearDown(self):
        self.f.close()  # manually close
        os.unlink(self.f.name)  # manually delete

    def test_technical_acronyms(self):
        # This works without a wordlist, because it begins mixed case
        self.assertEqual(titlecase('sending UDP packets over PPPoE works great'),
            'Sending UDP Packets Over PPPoE Works Great')
        # Without a wordlist, this will do the "wrong" thing for the context
        self.assertEqual(titlecase('SENDING UDP PACKETS OVER PPPOE WORKS GREAT'),
            'Sending Udp Packets Over Pppoe Works Great')
        # A wordlist can provide custom acronyms
        self.assertEqual(titlecase(
            'sending UDP packets over PPPoE works great',
            callback=create_wordlist_filter_from_file(self.f.name)),
            'Sending UDP Packets Over PPPoE Works Great')


class TestBlankLines(unittest.TestCase):
    # Really, it's a bit odd that the default behavior is to delete blank lines,
    # but that's what it was from day one, so we're kind of stuck with that.
    # This ensures folks can opt-out of that behavior if they want.

    def test_one_blank(self):
        s = 'Line number one\n\nand Line three\n'
        self.assertEqual(titlecase(s), 'Line Number One\nAnd Line Three\n')
        self.assertEqual(titlecase(s, preserve_blank_lines=True), 'Line Number One\n\nAnd Line Three\n')

    def test_complex_blanks(self):
        s = '\n\nLeading blank\n\n\nMulti-blank\n\n\n\n\nTrailing Blank\n\n'
        self.assertEqual(titlecase(s),
                '\nLeading Blank\nMulti-Blank\nTrailing Blank\n')
        self.assertEqual(titlecase(s, preserve_blank_lines=True),
                '\n\nLeading Blank\n\n\nMulti-Blank\n\n\n\n\nTrailing Blank\n\n')


if __name__ == '__main__':
    unittest.main()