• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import re
2
3from ._functools import method_cache
4
5
6# from jaraco.text 3.5
7class FoldedCase(str):
8    """
9    A case insensitive string class; behaves just like str
10    except compares equal when the only variation is case.
11
12    >>> s = FoldedCase('hello world')
13
14    >>> s == 'Hello World'
15    True
16
17    >>> 'Hello World' == s
18    True
19
20    >>> s != 'Hello World'
21    False
22
23    >>> s.index('O')
24    4
25
26    >>> s.split('O')
27    ['hell', ' w', 'rld']
28
29    >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta']))
30    ['alpha', 'Beta', 'GAMMA']
31
32    Sequence membership is straightforward.
33
34    >>> "Hello World" in [s]
35    True
36    >>> s in ["Hello World"]
37    True
38
39    You may test for set inclusion, but candidate and elements
40    must both be folded.
41
42    >>> FoldedCase("Hello World") in {s}
43    True
44    >>> s in {FoldedCase("Hello World")}
45    True
46
47    String inclusion works as long as the FoldedCase object
48    is on the right.
49
50    >>> "hello" in FoldedCase("Hello World")
51    True
52
53    But not if the FoldedCase object is on the left:
54
55    >>> FoldedCase('hello') in 'Hello World'
56    False
57
58    In that case, use in_:
59
60    >>> FoldedCase('hello').in_('Hello World')
61    True
62
63    >>> FoldedCase('hello') > FoldedCase('Hello')
64    False
65    """
66
67    def __lt__(self, other):
68        return self.lower() < other.lower()
69
70    def __gt__(self, other):
71        return self.lower() > other.lower()
72
73    def __eq__(self, other):
74        return self.lower() == other.lower()
75
76    def __ne__(self, other):
77        return self.lower() != other.lower()
78
79    def __hash__(self):
80        return hash(self.lower())
81
82    def __contains__(self, other):
83        return super(FoldedCase, self).lower().__contains__(other.lower())
84
85    def in_(self, other):
86        "Does self appear in other?"
87        return self in FoldedCase(other)
88
89    # cache lower since it's likely to be called frequently.
90    @method_cache
91    def lower(self):
92        return super(FoldedCase, self).lower()
93
94    def index(self, sub):
95        return self.lower().index(sub.lower())
96
97    def split(self, splitter=' ', maxsplit=0):
98        pattern = re.compile(re.escape(splitter), re.I)
99        return pattern.split(self, maxsplit)
100