1#  Copyright 2008-2015 Nokia Networks
2#  Copyright 2016-     Robot Framework Foundation
3#
4#  Licensed under the Apache License, Version 2.0 (the "License");
5#  you may not use this file except in compliance with the License.
6#  You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10#  Unless required by applicable law or agreed to in writing, software
11#  distributed under the License is distributed on an "AS IS" BASIS,
12#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13#  See the License for the specific language governing permissions and
14#  limitations under the License.
15
16import re
17import fnmatch
18from functools import partial
19
20from .compat import py2to3
21from .normalizing import normalize
22from .platform import IRONPYTHON, PY3
23from .robottypes import is_string
24
25
26def eq(str1, str2, ignore=(), caseless=True, spaceless=True):
27    str1 = normalize(str1, ignore, caseless, spaceless)
28    str2 = normalize(str2, ignore, caseless, spaceless)
29    return str1 == str2
30
31
32@py2to3
33class Matcher(object):
34
35    def __init__(self, pattern, ignore=(), caseless=True, spaceless=True,
36                 regexp=False):
37        if PY3 and isinstance(pattern, bytes):
38            raise TypeError('Matching bytes is not supported on Python 3.')
39        self.pattern = pattern
40        self._normalize = partial(normalize, ignore=ignore, caseless=caseless,
41                                  spaceless=spaceless)
42        self._regexp = self._compile(self._normalize(pattern), regexp=regexp)
43
44    def _compile(self, pattern, regexp=False):
45        if not regexp:
46            pattern = fnmatch.translate(pattern)
47            # https://github.com/IronLanguages/ironpython2/issues/515
48            if IRONPYTHON and "\\'" in pattern:
49                pattern = pattern.replace("\\'", "'")
50        return re.compile(pattern, re.DOTALL)
51
52    def match(self, string):
53        return self._regexp.match(self._normalize(string)) is not None
54
55    def match_any(self, strings):
56        return any(self.match(s) for s in strings)
57
58    def __nonzero__(self):
59        return bool(self._normalize(self.pattern))
60
61
62class MultiMatcher(object):
63
64    def __init__(self, patterns=None, ignore=(), caseless=True, spaceless=True,
65                 match_if_no_patterns=False, regexp=False):
66        self._matchers = [Matcher(pattern, ignore, caseless, spaceless, regexp)
67                          for pattern in self._ensure_list(patterns)]
68        self._match_if_no_patterns = match_if_no_patterns
69
70    def _ensure_list(self, patterns):
71        if patterns is None:
72            return []
73        if is_string(patterns):
74            return [patterns]
75        return patterns
76
77    def match(self, string):
78        if self._matchers:
79            return any(m.match(string) for m in self._matchers)
80        return self._match_if_no_patterns
81
82    def match_any(self, strings):
83        return any(self.match(s) for s in strings)
84
85    def __len__(self):
86        return len(self._matchers)
87
88    def __iter__(self):
89        for matcher in self._matchers:
90            yield matcher.pattern
91