Robot Framework
normalizing.py
Go to the documentation of this file.
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 
16 from collections.abc import MutableMapping
17 import re
18 
19 from .robottypes import is_dict_like, is_string
20 
21 
22 
27 def normalize(string, ignore=(), caseless=True, spaceless=True):
28  empty = '' if is_string(string) else b''
29  if isinstance(ignore, bytes):
30  # Iterating bytes in Python3 yields integers.
31  ignore = [bytes([i]) for i in ignore]
32  if spaceless:
33  string = empty.join(string.split())
34  if caseless:
35  string = string.lower()
36  ignore = [i.lower() for i in ignore]
37  # both if statements below enhance performance a little
38  if ignore:
39  for ign in ignore:
40  if ign in string:
41  string = string.replace(ign, empty)
42  return string
43 
44 
46  return re.sub(r'\s', ' ', string, flags=re.UNICODE)
47 
48 
49 
50 class NormalizedDict(MutableMapping):
51 
52 
60  def __init__(self, initial=None, ignore=(), caseless=True, spaceless=True):
61  self._data_data = {}
62  self._keys_keys = {}
63  self._normalize_normalize = lambda s: normalize(s, ignore, caseless, spaceless)
64  if initial:
65  self._add_initial_add_initial(initial)
66 
67  def _add_initial(self, initial):
68  items = initial.items() if hasattr(initial, 'items') else initial
69  for key, value in items:
70  self[key] = value
71 
72  def __getitem__(self, key):
73  return self._data_data[self._normalize_normalize(key)]
74 
75  def __setitem__(self, key, value):
76  norm_key = self._normalize_normalize(key)
77  self._data_data[norm_key] = value
78  self._keys_keys.setdefault(norm_key, key)
79 
80  def __delitem__(self, key):
81  norm_key = self._normalize_normalize(key)
82  del self._data_data[norm_key]
83  del self._keys_keys[norm_key]
84 
85  def __iter__(self):
86  return (self._keys_keys[norm_key] for norm_key in sorted(self._keys_keys))
87 
88  def __len__(self):
89  return len(self._data_data)
90 
91  def __str__(self):
92  return '{%s}' % ', '.join('%r: %r' % (key, self[key]) for key in self)
93 
94  def __eq__(self, other):
95  if not is_dict_like(other):
96  return False
97  if not isinstance(other, NormalizedDict):
98  other = NormalizedDict(other)
99  return self._data_data == other._data
100 
101  def copy(self):
102  copy = NormalizedDict()
103  copy._data = self._data_data.copy()
104  copy._keys = self._keys_keys.copy()
105  copy._normalize = self._normalize_normalize
106  return copy
107 
108  # Speed-ups. Following methods are faster than default implementations.
109 
110  def __contains__(self, key):
111  return self._normalize_normalize(key) in self._data_data
112 
113  def clear(self):
114  self._data_data.clear()
115  self._keys_keys.clear()
Custom dictionary implementation automatically normalizing keys.
Definition: normalizing.py:50
def __setitem__(self, key, value)
Definition: normalizing.py:75
def __init__(self, initial=None, ignore=(), caseless=True, spaceless=True)
Initialized with possible initial value and normalizing spec.
Definition: normalizing.py:60
def normalize_whitespace(string)
Definition: normalizing.py:45
def normalize(string, ignore=(), caseless=True, spaceless=True)
Normalizes given string according to given spec.
Definition: normalizing.py:27
def is_dict_like(item)
Definition: robottypes.py:72