~divmod-dev/divmod.org/trunk

« back to all changes in this revision

Viewing changes to Epsilon/epsilon/caseless.py

  • Committer: Jean-Paul Calderone
  • Date: 2014-06-29 20:33:04 UTC
  • mfrom: (2749.1.1 remove-epsilon-1325289)
  • Revision ID: exarkun@twistedmatrix.com-20140629203304-gdkmbwl1suei4m97
mergeĀ lp:~exarkun/divmod.org/remove-epsilon-1325289

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- test-case-name: epsilon.test.test_caseless -*-
2
 
"""
3
 
Helpers for case-insensitive string handling.
4
 
"""
5
 
 
6
 
class Caseless(object):
7
 
    """
8
 
    Case-insensitive string wrapper type.
9
 
    
10
 
    This wrapper is intended for use with strings that have case-insensitive
11
 
    semantics, such as HTTP/MIME header values.  It implements comparison-based
12
 
    operations case-insensitively, avoiding the need to manually call C{lower}
13
 
    where appropriate, or keep track of which strings are case-insensitive
14
 
    throughout various function calls.
15
 
 
16
 
    Example usage:
17
 
 
18
 
        >>> Caseless('Spam') == Caseless('spam')
19
 
        True
20
 
        >>> 'spam' in Caseless('Eggs and Spam')
21
 
        True
22
 
 
23
 
        >>> sorted(['FOO', 'bar'], key=Caseless)
24
 
        ['bar', 'FOO']
25
 
 
26
 
        >>> d = {Caseless('Content-type'): Caseless('Text/Plain')}
27
 
        >>> d[Caseless('Content-Type')].startswith('text/')
28
 
        True
29
 
 
30
 
    Note:  String methods that return modified strings (such as
31
 
    C{decode}/C{encode}, C{join}, C{partition}, C{replace}, C{strip}/C{split})
32
 
    don't have an unambiguous return types with regards to case sensitivity, so
33
 
    they are not implemented by L{Caseless}.  They should be accessed on the
34
 
    underlying cased string instead.  (Excepted are methods like
35
 
    C{lower}/C{upper}, whose return case is unambiguous.)
36
 
 
37
 
    @ivar cased:  the wrapped string-like object
38
 
    """
39
 
 
40
 
    def __init__(self, cased):
41
 
        if isinstance(cased, Caseless):
42
 
            cased = cased.cased
43
 
        self.cased = cased
44
 
 
45
 
 
46
 
    def __repr__(self):
47
 
        return '%s(%r)' % (type(self).__name__, self.cased)
48
 
 
49
 
 
50
 
    # Methods delegated to cased
51
 
 
52
 
    def __str__(self):
53
 
        return str(self.cased)
54
 
 
55
 
 
56
 
    def __unicode__(self):
57
 
        return unicode(self.cased)
58
 
 
59
 
 
60
 
    def __len__(self):
61
 
        return len(self.cased)
62
 
 
63
 
 
64
 
    def __getitem__(self, key):
65
 
        return self.cased[key]
66
 
 
67
 
 
68
 
    def __iter__(self):
69
 
        return iter(self.cased)
70
 
 
71
 
 
72
 
    def lower(self):
73
 
        return self.cased.lower()
74
 
 
75
 
 
76
 
    def upper(self):
77
 
        return self.cased.upper()
78
 
 
79
 
 
80
 
    def title(self):
81
 
        return self.cased.title()
82
 
 
83
 
 
84
 
    def swapcase(self):
85
 
        return self.cased.swapcase()
86
 
 
87
 
 
88
 
    # Methods delegated to lower()
89
 
 
90
 
    def __cmp__(self, other):
91
 
        return cmp(self.lower(), other.lower())
92
 
 
93
 
 
94
 
    def __hash__(self):
95
 
        return hash(self.lower())
96
 
 
97
 
 
98
 
    def __contains__(self, substring):
99
 
        return substring.lower() in self.lower()
100
 
 
101
 
 
102
 
    def startswith(self, prefix, *rest):
103
 
        if isinstance(prefix, tuple):
104
 
            lprefix = tuple(s.lower() for s in prefix)
105
 
        else:
106
 
            lprefix = prefix.lower()
107
 
        return self.lower().startswith(lprefix, *rest)
108
 
 
109
 
 
110
 
    def endswith(self, suffix, *rest):
111
 
        if isinstance(suffix, tuple):
112
 
            lsuffix = tuple(s.lower() for s in suffix)
113
 
        else:
114
 
            lsuffix = suffix.lower()
115
 
        return self.lower().endswith(lsuffix, *rest)
116
 
 
117
 
 
118
 
    def count(self, substring, *rest):
119
 
        return self.lower().count(substring.lower(), *rest)
120
 
 
121
 
 
122
 
    def find(self, substring, *rest):
123
 
        return self.lower().find(substring.lower(), *rest)
124
 
 
125
 
 
126
 
    def index(self, substring, *rest):
127
 
        return self.lower().index(substring.lower(), *rest)
128
 
 
129
 
 
130
 
    def rfind(self, substring, *rest):
131
 
        return self.lower().rfind(substring.lower(), *rest)
132
 
 
133
 
 
134
 
    def rindex(self, substring, *rest):
135
 
        return self.lower().rindex(substring.lower(), *rest)