This repository provides User Manual for setting up a Docker environment tailored for testing DGTD code.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

384 lines
9.3 KiB

# Copyright (c) 2006-2021 Andrey Golovizin
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""Miscellaneous small utils."""
from __future__ import print_function, unicode_literals
import itertools
from collections import OrderedDict, deque
from functools import wraps
from types import GeneratorType
try:
from collections.abc import MutableMapping, MutableSet, Sequence
except ImportError:
from collections import MutableMapping, MutableSet, Sequence
from six.moves import zip_longest
from .py3compat import fix_unicode_literals_in_doctest
def deprecated(since, reason=None):
def decorator(f):
@wraps(f)
def new_f(*args, **kwargs):
import warnings
message = u'{0}() is deprecated since {1}'.format(f.__name__, since)
if reason:
message += ': {0}'.format(reason)
warnings.warn(message, DeprecationWarning, stacklevel=2)
return f(*args, **kwargs)
return new_f
return decorator
def memoize(f, capacity=1024):
memory = {}
history = deque()
@wraps(f)
def new_f(*args):
if args not in memory:
if len(history) >= capacity:
del memory[history.popleft()]
memory[args] = f(*args)
history.append(args)
return memory[args]
return new_f
def collect_iterable(f):
@wraps(f)
def new_f(*args, **kwargs):
return list(f(*args, **kwargs))
return new_f
def pairwise(iterable):
a, b = itertools.tee(iterable)
next(b, None)
return zip_longest(a, b)
@fix_unicode_literals_in_doctest
class CaseInsensitiveDict(MutableMapping):
"""A dict with case-insensitive lookup.
>>> d = CaseInsensitiveDict(TesT='passed')
>>> d
CaseInsensitiveDict({'TesT': u'passed'})
>>> d.lower()
CaseInsensitiveDict({'test': u'passed'})
>>> print(d['TesT'])
passed
>>> print(d['test'])
passed
>>> print(d['Test'])
passed
>>> print(d.get('test'))
passed
>>> print(d.get('Test'))
passed
>>> d['Test'] = 'passed again'
>>> print(d['test'])
passed again
>>> 'test' in d
True
>>> 'Test' in d
True
>>> list(d.keys())
[u'Test']
>>> for key in d:
... print(key)
Test
>>> for key, value in d.items():
... print(key, value)
Test passed again
>>> bool(d)
True
>>> len(d)
1
>>> del d['test']
>>> len(d)
0
>>> bool(d)
False
>>> 'test' in d
False
>>> 'Test' in d
False
>>> print(d.get('test'))
None
>>> print(d.get('Test'))
None
>>> print(d.get('Test', 'failed'))
failed
>>> CaseInsensitiveDict(
... (key, value) for key, value in [('a', 'b')]
... )
CaseInsensitiveDict({u'a': u'b'})
"""
def __init__(self, *args, **kwargs):
initial = dict(*args, **kwargs)
self._dict = dict((key.lower(), value) for key, value in initial.items())
self._keys = dict((key.lower(), key) for key in initial)
def __len__(self):
return len(self._dict)
def __iter__(self):
return iter(self._keys.values())
def __setitem__(self, key, value):
"""To implement lowercase keys."""
key_lower = key.lower()
self._dict[key_lower] = value
self._keys[key_lower] = key
def __getitem__(self, key):
return self._dict[key.lower()]
def __delitem__(self, key):
key_lower = key.lower()
del self._dict[key_lower]
del self._keys[key_lower]
def __contains__(self, key):
return key.lower() in self._dict
def __repr__(self):
"""A caselessDict version of __repr__ """
dct = dict((key, self[key]) for key in self)
return '{0}({1})'.format(
type(self).__name__, repr(dct),
)
def items_lower(self):
return ((key.lower(), value) for key, value in self.items())
def lower(self):
return type(self)(self.items_lower())
class CaseInsensitiveDefaultDict(CaseInsensitiveDict):
"""CaseInseisitiveDict with default factory, like collections.defaultdict
>>> d = CaseInsensitiveDefaultDict(int)
>>> d['a']
0
>>> d['a'] += 1
>>> d['a']
1
>>> d['A']
1
>>> d['a'] = 3
>>> d['a']
3
>>> d['B'] += 10
>>> d['b']
10
"""
def __init__(self, default_factory):
super(CaseInsensitiveDefaultDict, self).__init__()
self.default_factory = default_factory
def __getitem__(self, key):
try:
return super(CaseInsensitiveDefaultDict, self).__getitem__(key)
except KeyError:
return self.default_factory()
@fix_unicode_literals_in_doctest
class OrderedCaseInsensitiveDict(CaseInsensitiveDict):
""" An (incomplete) ordered case-insensitive dict.
>>> d = OrderedCaseInsensitiveDict([
... ('Uno', 1),
... ('Dos', 2),
... ('Tres', 3),
... ])
>>> d
OrderedCaseInsensitiveDict([(u'Uno', 1), (u'Dos', 2), (u'Tres', 3)])
>>> d.lower()
OrderedCaseInsensitiveDict([(u'uno', 1), (u'dos', 2), (u'tres', 3)])
>>> list(d.keys())
[u'Uno', u'Dos', u'Tres']
>>> list(d.items())
[(u'Uno', 1), (u'Dos', 2), (u'Tres', 3)]
>>> list(d.values())
[1, 2, 3]
>>> d['Cuatro'] = 4
>>> list(d.keys())
[u'Uno', u'Dos', u'Tres', u'Cuatro']
>>> list(d.items())
[(u'Uno', 1), (u'Dos', 2), (u'Tres', 3), (u'Cuatro', 4)]
>>> list(d.values())
[1, 2, 3, 4]
>>> list(d)
[u'Uno', u'Dos', u'Tres', u'Cuatro']
>>> 'Uno' in d
True
>>> 'uno' in d
True
>>> d['Uno']
1
>>> d['uno']
1
>>> d['UNO']
1
>>> 'Cuatro' in d
True
>>> 'CUATRO' in d
True
>>> d['Cuatro']
4
>>> d['cuatro']
4
>>> d['UNO'] = 'one'
>>> d['uno']
u'one'
>>> d['Uno']
u'one'
>>> list(d.keys())
[u'UNO', u'Dos', u'Tres', u'Cuatro']
>>> d['cuatro'] = 'four'
>>> d['Cuatro']
u'four'
>>> d['cuatro']
u'four'
>>> list(d.keys())
[u'UNO', u'Dos', u'Tres', u'cuatro']
>>> list(d.values())
[u'one', 2, 3, u'four']
>>> del d['dos']
>>> list(d.keys())
[u'UNO', u'Tres', u'cuatro']
>>> list(d.values())
[u'one', 3, u'four']
"""
def __init__(self, *args, **kwargs):
initial = OrderedDict(*args, **kwargs)
self._dict = dict((key.lower(), value) for key, value in initial.items())
self._keys = OrderedDict((key.lower(), key) for key in initial)
def __repr__(self):
return '{0}({1})'.format(
type(self).__name__, list(self.items()),
)
@fix_unicode_literals_in_doctest
class CaseInsensitiveSet(MutableSet):
"""A very basic case-insensitive set.
>>> s = CaseInsensitiveSet()
>>> len(s)
0
>>> 'a' in s
False
>>> list(CaseInsensitiveSet(['aaa', 'Aaa', 'AAA']))
[u'aaa']
>>> s = CaseInsensitiveSet(['Aaa', 'Bbb'])
>>> s
CaseInsensitiveSet([u'Aaa', u'Bbb'])
>>> s.lower()
CaseInsensitiveSet([u'aaa', u'bbb'])
>>> len(s)
2
>>> 'aaa' in s
True
>>> 'Aaa' in s
True
>>> 'AAA' in s
True
>>> 'bbb' in s
True
>>> 'Bbb' in s
True
>>> 'abc' in s
False
>>> s.add('ccc')
>>> len(s)
3
>>> 'aaa' in s
True
>>> 'ccc' in s
True
>>> s.remove('AAA')
>>> len(s)
2
>>> 'aaa' in s
False
>>> bool(CaseInsensitiveSet(['a']))
True
>>> bool(CaseInsensitiveSet([]))
False
>>> bool(CaseInsensitiveSet())
False
"""
def __init__(self, iterable=()):
self._set = set()
self._keys = dict()
for item in iterable:
self.add(item)
def __contains__(self, key):
return key.lower() in self._set
def __iter__(self):
return iter(self._set)
def __len__(self):
return len(self._set)
def __repr__(self):
"""A caselessDict version of __repr__ """
return '{0}({1})'.format(
type(self).__name__, repr(sorted(self._keys.values()))
)
def add(self, key):
key_lower = key.lower()
self._set.add(key_lower)
self._keys[key_lower] = key
def discard(self, key):
key_lower = key.lower()
self._set.discard(key_lower)
self._keys.pop(key_lower, None)
def get_canonical_key(self, key):
return self._keys[key.lower()]
def lower(self):
return type(self)(self._set)