1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2013-2017 Vinay Sajip.
4# Licensed to the Python Software Foundation under a contributor agreement.
5# See LICENSE.txt and CONTRIBUTORS.txt.
6#
7from __future__ import absolute_import
8
9import os
10import re
11import sys
12
13try:
14    import ssl
15except ImportError:  # pragma: no cover
16    ssl = None
17
18if sys.version_info[0] < 3:  # pragma: no cover
19    from StringIO import StringIO
20    string_types = basestring,
21    text_type = unicode
22    from types import FileType as file_type
23    import __builtin__ as builtins
24    import ConfigParser as configparser
25    from ._backport import shutil
26    from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit
27    from urllib import (urlretrieve, quote as _quote, unquote, url2pathname,
28                        pathname2url, ContentTooShortError, splittype)
29
30    def quote(s):
31        if isinstance(s, unicode):
32            s = s.encode('utf-8')
33        return _quote(s)
34
35    import urllib2
36    from urllib2 import (Request, urlopen, URLError, HTTPError,
37                         HTTPBasicAuthHandler, HTTPPasswordMgr,
38                         HTTPHandler, HTTPRedirectHandler,
39                         build_opener)
40    if ssl:
41        from urllib2 import HTTPSHandler
42    import httplib
43    import xmlrpclib
44    import Queue as queue
45    from HTMLParser import HTMLParser
46    import htmlentitydefs
47    raw_input = raw_input
48    from itertools import ifilter as filter
49    from itertools import ifilterfalse as filterfalse
50
51    _userprog = None
52    def splituser(host):
53        """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'."""
54        global _userprog
55        if _userprog is None:
56            import re
57            _userprog = re.compile('^(.*)@(.*)$')
58
59        match = _userprog.match(host)
60        if match: return match.group(1, 2)
61        return None, host
62
63else:  # pragma: no cover
64    from io import StringIO
65    string_types = str,
66    text_type = str
67    from io import TextIOWrapper as file_type
68    import builtins
69    import configparser
70    import shutil
71    from urllib.parse import (urlparse, urlunparse, urljoin, splituser, quote,
72                              unquote, urlsplit, urlunsplit, splittype)
73    from urllib.request import (urlopen, urlretrieve, Request, url2pathname,
74                                pathname2url,
75                                HTTPBasicAuthHandler, HTTPPasswordMgr,
76                                HTTPHandler, HTTPRedirectHandler,
77                                build_opener)
78    if ssl:
79        from urllib.request import HTTPSHandler
80    from urllib.error import HTTPError, URLError, ContentTooShortError
81    import http.client as httplib
82    import urllib.request as urllib2
83    import xmlrpc.client as xmlrpclib
84    import queue
85    from html.parser import HTMLParser
86    import html.entities as htmlentitydefs
87    raw_input = input
88    from itertools import filterfalse
89    filter = filter
90
91try:
92    from ssl import match_hostname, CertificateError
93except ImportError: # pragma: no cover
94    class CertificateError(ValueError):
95        pass
96
97
98    def _dnsname_match(dn, hostname, max_wildcards=1):
99        """Matching according to RFC 6125, section 6.4.3
100
101        http://tools.ietf.org/html/rfc6125#section-6.4.3
102        """
103        pats = []
104        if not dn:
105            return False
106
107        parts = dn.split('.')
108        leftmost, remainder = parts[0], parts[1:]
109
110        wildcards = leftmost.count('*')
111        if wildcards > max_wildcards:
112            # Issue #17980: avoid denials of service by refusing more
113            # than one wildcard per fragment.  A survey of established
114            # policy among SSL implementations showed it to be a
115            # reasonable choice.
116            raise CertificateError(
117                "too many wildcards in certificate DNS name: " + repr(dn))
118
119        # speed up common case w/o wildcards
120        if not wildcards:
121            return dn.lower() == hostname.lower()
122
123        # RFC 6125, section 6.4.3, subitem 1.
124        # The client SHOULD NOT attempt to match a presented identifier in which
125        # the wildcard character comprises a label other than the left-most label.
126        if leftmost == '*':
127            # When '*' is a fragment by itself, it matches a non-empty dotless
128            # fragment.
129            pats.append('[^.]+')
130        elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
131            # RFC 6125, section 6.4.3, subitem 3.
132            # The client SHOULD NOT attempt to match a presented identifier
133            # where the wildcard character is embedded within an A-label or
134            # U-label of an internationalized domain name.
135            pats.append(re.escape(leftmost))
136        else:
137            # Otherwise, '*' matches any dotless string, e.g. www*
138            pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
139
140        # add the remaining fragments, ignore any wildcards
141        for frag in remainder:
142            pats.append(re.escape(frag))
143
144        pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
145        return pat.match(hostname)
146
147
148    def match_hostname(cert, hostname):
149        """Verify that *cert* (in decoded format as returned by
150        SSLSocket.getpeercert()) matches the *hostname*.  RFC 2818 and RFC 6125
151        rules are followed, but IP addresses are not accepted for *hostname*.
152
153        CertificateError is raised on failure. On success, the function
154        returns nothing.
155        """
156        if not cert:
157            raise ValueError("empty or no certificate, match_hostname needs a "
158                             "SSL socket or SSL context with either "
159                             "CERT_OPTIONAL or CERT_REQUIRED")
160        dnsnames = []
161        san = cert.get('subjectAltName', ())
162        for key, value in san:
163            if key == 'DNS':
164                if _dnsname_match(value, hostname):
165                    return
166                dnsnames.append(value)
167        if not dnsnames:
168            # The subject is only checked when there is no dNSName entry
169            # in subjectAltName
170            for sub in cert.get('subject', ()):
171                for key, value in sub:
172                    # XXX according to RFC 2818, the most specific Common Name
173                    # must be used.
174                    if key == 'commonName':
175                        if _dnsname_match(value, hostname):
176                            return
177                        dnsnames.append(value)
178        if len(dnsnames) > 1:
179            raise CertificateError("hostname %r "
180                "doesn't match either of %s"
181                % (hostname, ', '.join(map(repr, dnsnames))))
182        elif len(dnsnames) == 1:
183            raise CertificateError("hostname %r "
184                "doesn't match %r"
185                % (hostname, dnsnames[0]))
186        else:
187            raise CertificateError("no appropriate commonName or "
188                "subjectAltName fields were found")
189
190
191try:
192    from types import SimpleNamespace as Container
193except ImportError:  # pragma: no cover
194    class Container(object):
195        """
196        A generic container for when multiple values need to be returned
197        """
198        def __init__(self, **kwargs):
199            self.__dict__.update(kwargs)
200
201
202try:
203    from shutil import which
204except ImportError:  # pragma: no cover
205    # Implementation from Python 3.3
206    def which(cmd, mode=os.F_OK | os.X_OK, path=None):
207        """Given a command, mode, and a PATH string, return the path which
208        conforms to the given mode on the PATH, or None if there is no such
209        file.
210
211        `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result
212        of os.environ.get("PATH"), or can be overridden with a custom search
213        path.
214
215        """
216        # Check that a given file can be accessed with the correct mode.
217        # Additionally check that `file` is not a directory, as on Windows
218        # directories pass the os.access check.
219        def _access_check(fn, mode):
220            return (os.path.exists(fn) and os.access(fn, mode)
221                    and not os.path.isdir(fn))
222
223        # If we're given a path with a directory part, look it up directly rather
224        # than referring to PATH directories. This includes checking relative to the
225        # current directory, e.g. ./script
226        if os.path.dirname(cmd):
227            if _access_check(cmd, mode):
228                return cmd
229            return None
230
231        if path is None:
232            path = os.environ.get("PATH", os.defpath)
233        if not path:
234            return None
235        path = path.split(os.pathsep)
236
237        if sys.platform == "win32":
238            # The current directory takes precedence on Windows.
239            if not os.curdir in path:
240                path.insert(0, os.curdir)
241
242            # PATHEXT is necessary to check on Windows.
243            pathext = os.environ.get("PATHEXT", "").split(os.pathsep)
244            # See if the given file matches any of the expected path extensions.
245            # This will allow us to short circuit when given "python.exe".
246            # If it does match, only test that one, otherwise we have to try
247            # others.
248            if any(cmd.lower().endswith(ext.lower()) for ext in pathext):
249                files = [cmd]
250            else:
251                files = [cmd + ext for ext in pathext]
252        else:
253            # On other platforms you don't have things like PATHEXT to tell you
254            # what file suffixes are executable, so just pass on cmd as-is.
255            files = [cmd]
256
257        seen = set()
258        for dir in path:
259            normdir = os.path.normcase(dir)
260            if not normdir in seen:
261                seen.add(normdir)
262                for thefile in files:
263                    name = os.path.join(dir, thefile)
264                    if _access_check(name, mode):
265                        return name
266        return None
267
268
269# ZipFile is a context manager in 2.7, but not in 2.6
270
271from zipfile import ZipFile as BaseZipFile
272
273if hasattr(BaseZipFile, '__enter__'):  # pragma: no cover
274    ZipFile = BaseZipFile
275else:  # pragma: no cover
276    from zipfile import ZipExtFile as BaseZipExtFile
277
278    class ZipExtFile(BaseZipExtFile):
279        def __init__(self, base):
280            self.__dict__.update(base.__dict__)
281
282        def __enter__(self):
283            return self
284
285        def __exit__(self, *exc_info):
286            self.close()
287            # return None, so if an exception occurred, it will propagate
288
289    class ZipFile(BaseZipFile):
290        def __enter__(self):
291            return self
292
293        def __exit__(self, *exc_info):
294            self.close()
295            # return None, so if an exception occurred, it will propagate
296
297        def open(self, *args, **kwargs):
298            base = BaseZipFile.open(self, *args, **kwargs)
299            return ZipExtFile(base)
300
301try:
302    from platform import python_implementation
303except ImportError: # pragma: no cover
304    def python_implementation():
305        """Return a string identifying the Python implementation."""
306        if 'PyPy' in sys.version:
307            return 'PyPy'
308        if os.name == 'java':
309            return 'Jython'
310        if sys.version.startswith('IronPython'):
311            return 'IronPython'
312        return 'CPython'
313
314try:
315    import sysconfig
316except ImportError: # pragma: no cover
317    from ._backport import sysconfig
318
319try:
320    callable = callable
321except NameError:   # pragma: no cover
322    from collections.abc import Callable
323
324    def callable(obj):
325        return isinstance(obj, Callable)
326
327
328try:
329    fsencode = os.fsencode
330    fsdecode = os.fsdecode
331except AttributeError:  # pragma: no cover
332    # Issue #99: on some systems (e.g. containerised),
333    # sys.getfilesystemencoding() returns None, and we need a real value,
334    # so fall back to utf-8. From the CPython 2.7 docs relating to Unix and
335    # sys.getfilesystemencoding(): the return value is "the user’s preference
336    # according to the result of nl_langinfo(CODESET), or None if the
337    # nl_langinfo(CODESET) failed."
338    _fsencoding = sys.getfilesystemencoding() or 'utf-8'
339    if _fsencoding == 'mbcs':
340        _fserrors = 'strict'
341    else:
342        _fserrors = 'surrogateescape'
343
344    def fsencode(filename):
345        if isinstance(filename, bytes):
346            return filename
347        elif isinstance(filename, text_type):
348            return filename.encode(_fsencoding, _fserrors)
349        else:
350            raise TypeError("expect bytes or str, not %s" %
351                            type(filename).__name__)
352
353    def fsdecode(filename):
354        if isinstance(filename, text_type):
355            return filename
356        elif isinstance(filename, bytes):
357            return filename.decode(_fsencoding, _fserrors)
358        else:
359            raise TypeError("expect bytes or str, not %s" %
360                            type(filename).__name__)
361
362try:
363    from tokenize import detect_encoding
364except ImportError: # pragma: no cover
365    from codecs import BOM_UTF8, lookup
366    import re
367
368    cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)")
369
370    def _get_normal_name(orig_enc):
371        """Imitates get_normal_name in tokenizer.c."""
372        # Only care about the first 12 characters.
373        enc = orig_enc[:12].lower().replace("_", "-")
374        if enc == "utf-8" or enc.startswith("utf-8-"):
375            return "utf-8"
376        if enc in ("latin-1", "iso-8859-1", "iso-latin-1") or \
377           enc.startswith(("latin-1-", "iso-8859-1-", "iso-latin-1-")):
378            return "iso-8859-1"
379        return orig_enc
380
381    def detect_encoding(readline):
382        """
383        The detect_encoding() function is used to detect the encoding that should
384        be used to decode a Python source file.  It requires one argument, readline,
385        in the same way as the tokenize() generator.
386
387        It will call readline a maximum of twice, and return the encoding used
388        (as a string) and a list of any lines (left as bytes) it has read in.
389
390        It detects the encoding from the presence of a utf-8 bom or an encoding
391        cookie as specified in pep-0263.  If both a bom and a cookie are present,
392        but disagree, a SyntaxError will be raised.  If the encoding cookie is an
393        invalid charset, raise a SyntaxError.  Note that if a utf-8 bom is found,
394        'utf-8-sig' is returned.
395
396        If no encoding is specified, then the default of 'utf-8' will be returned.
397        """
398        try:
399            filename = readline.__self__.name
400        except AttributeError:
401            filename = None
402        bom_found = False
403        encoding = None
404        default = 'utf-8'
405        def read_or_stop():
406            try:
407                return readline()
408            except StopIteration:
409                return b''
410
411        def find_cookie(line):
412            try:
413                # Decode as UTF-8. Either the line is an encoding declaration,
414                # in which case it should be pure ASCII, or it must be UTF-8
415                # per default encoding.
416                line_string = line.decode('utf-8')
417            except UnicodeDecodeError:
418                msg = "invalid or missing encoding declaration"
419                if filename is not None:
420                    msg = '{} for {!r}'.format(msg, filename)
421                raise SyntaxError(msg)
422
423            matches = cookie_re.findall(line_string)
424            if not matches:
425                return None
426            encoding = _get_normal_name(matches[0])
427            try:
428                codec = lookup(encoding)
429            except LookupError:
430                # This behaviour mimics the Python interpreter
431                if filename is None:
432                    msg = "unknown encoding: " + encoding
433                else:
434                    msg = "unknown encoding for {!r}: {}".format(filename,
435                            encoding)
436                raise SyntaxError(msg)
437
438            if bom_found:
439                if codec.name != 'utf-8':
440                    # This behaviour mimics the Python interpreter
441                    if filename is None:
442                        msg = 'encoding problem: utf-8'
443                    else:
444                        msg = 'encoding problem for {!r}: utf-8'.format(filename)
445                    raise SyntaxError(msg)
446                encoding += '-sig'
447            return encoding
448
449        first = read_or_stop()
450        if first.startswith(BOM_UTF8):
451            bom_found = True
452            first = first[3:]
453            default = 'utf-8-sig'
454        if not first:
455            return default, []
456
457        encoding = find_cookie(first)
458        if encoding:
459            return encoding, [first]
460
461        second = read_or_stop()
462        if not second:
463            return default, [first]
464
465        encoding = find_cookie(second)
466        if encoding:
467            return encoding, [first, second]
468
469        return default, [first, second]
470
471# For converting & <-> &amp; etc.
472try:
473    from html import escape
474except ImportError:
475    from cgi import escape
476if sys.version_info[:2] < (3, 4):
477    unescape = HTMLParser().unescape
478else:
479    from html import unescape
480
481try:
482    from collections import ChainMap
483except ImportError: # pragma: no cover
484    from collections import MutableMapping
485
486    try:
487        from reprlib import recursive_repr as _recursive_repr
488    except ImportError:
489        def _recursive_repr(fillvalue='...'):
490            '''
491            Decorator to make a repr function return fillvalue for a recursive
492            call
493            '''
494
495            def decorating_function(user_function):
496                repr_running = set()
497
498                def wrapper(self):
499                    key = id(self), get_ident()
500                    if key in repr_running:
501                        return fillvalue
502                    repr_running.add(key)
503                    try:
504                        result = user_function(self)
505                    finally:
506                        repr_running.discard(key)
507                    return result
508
509                # Can't use functools.wraps() here because of bootstrap issues
510                wrapper.__module__ = getattr(user_function, '__module__')
511                wrapper.__doc__ = getattr(user_function, '__doc__')
512                wrapper.__name__ = getattr(user_function, '__name__')
513                wrapper.__annotations__ = getattr(user_function, '__annotations__', {})
514                return wrapper
515
516            return decorating_function
517
518    class ChainMap(MutableMapping):
519        ''' A ChainMap groups multiple dicts (or other mappings) together
520        to create a single, updateable view.
521
522        The underlying mappings are stored in a list.  That list is public and can
523        accessed or updated using the *maps* attribute.  There is no other state.
524
525        Lookups search the underlying mappings successively until a key is found.
526        In contrast, writes, updates, and deletions only operate on the first
527        mapping.
528
529        '''
530
531        def __init__(self, *maps):
532            '''Initialize a ChainMap by setting *maps* to the given mappings.
533            If no mappings are provided, a single empty dictionary is used.
534
535            '''
536            self.maps = list(maps) or [{}]          # always at least one map
537
538        def __missing__(self, key):
539            raise KeyError(key)
540
541        def __getitem__(self, key):
542            for mapping in self.maps:
543                try:
544                    return mapping[key]             # can't use 'key in mapping' with defaultdict
545                except KeyError:
546                    pass
547            return self.__missing__(key)            # support subclasses that define __missing__
548
549        def get(self, key, default=None):
550            return self[key] if key in self else default
551
552        def __len__(self):
553            return len(set().union(*self.maps))     # reuses stored hash values if possible
554
555        def __iter__(self):
556            return iter(set().union(*self.maps))
557
558        def __contains__(self, key):
559            return any(key in m for m in self.maps)
560
561        def __bool__(self):
562            return any(self.maps)
563
564        @_recursive_repr()
565        def __repr__(self):
566            return '{0.__class__.__name__}({1})'.format(
567                self, ', '.join(map(repr, self.maps)))
568
569        @classmethod
570        def fromkeys(cls, iterable, *args):
571            'Create a ChainMap with a single dict created from the iterable.'
572            return cls(dict.fromkeys(iterable, *args))
573
574        def copy(self):
575            'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]'
576            return self.__class__(self.maps[0].copy(), *self.maps[1:])
577
578        __copy__ = copy
579
580        def new_child(self):                        # like Django's Context.push()
581            'New ChainMap with a new dict followed by all previous maps.'
582            return self.__class__({}, *self.maps)
583
584        @property
585        def parents(self):                          # like Django's Context.pop()
586            'New ChainMap from maps[1:].'
587            return self.__class__(*self.maps[1:])
588
589        def __setitem__(self, key, value):
590            self.maps[0][key] = value
591
592        def __delitem__(self, key):
593            try:
594                del self.maps[0][key]
595            except KeyError:
596                raise KeyError('Key not found in the first mapping: {!r}'.format(key))
597
598        def popitem(self):
599            'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.'
600            try:
601                return self.maps[0].popitem()
602            except KeyError:
603                raise KeyError('No keys found in the first mapping.')
604
605        def pop(self, key, *args):
606            'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].'
607            try:
608                return self.maps[0].pop(key, *args)
609            except KeyError:
610                raise KeyError('Key not found in the first mapping: {!r}'.format(key))
611
612        def clear(self):
613            'Clear maps[0], leaving maps[1:] intact.'
614            self.maps[0].clear()
615
616try:
617    from importlib.util import cache_from_source  # Python >= 3.4
618except ImportError:  # pragma: no cover
619    try:
620        from imp import cache_from_source
621    except ImportError:  # pragma: no cover
622        def cache_from_source(path, debug_override=None):
623            assert path.endswith('.py')
624            if debug_override is None:
625                debug_override = __debug__
626            if debug_override:
627                suffix = 'c'
628            else:
629                suffix = 'o'
630            return path + suffix
631
632try:
633    from collections import OrderedDict
634except ImportError: # pragma: no cover
635## {{{ http://code.activestate.com/recipes/576693/ (r9)
636# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
637# Passes Python2.7's test suite and incorporates all the latest updates.
638    try:
639        from thread import get_ident as _get_ident
640    except ImportError:
641        from dummy_thread import get_ident as _get_ident
642
643    try:
644        from _abcoll import KeysView, ValuesView, ItemsView
645    except ImportError:
646        pass
647
648
649    class OrderedDict(dict):
650        'Dictionary that remembers insertion order'
651        # An inherited dict maps keys to values.
652        # The inherited dict provides __getitem__, __len__, __contains__, and get.
653        # The remaining methods are order-aware.
654        # Big-O running times for all methods are the same as for regular dictionaries.
655
656        # The internal self.__map dictionary maps keys to links in a doubly linked list.
657        # The circular doubly linked list starts and ends with a sentinel element.
658        # The sentinel element never gets deleted (this simplifies the algorithm).
659        # Each link is stored as a list of length three:  [PREV, NEXT, KEY].
660
661        def __init__(self, *args, **kwds):
662            '''Initialize an ordered dictionary.  Signature is the same as for
663            regular dictionaries, but keyword arguments are not recommended
664            because their insertion order is arbitrary.
665
666            '''
667            if len(args) > 1:
668                raise TypeError('expected at most 1 arguments, got %d' % len(args))
669            try:
670                self.__root
671            except AttributeError:
672                self.__root = root = []                     # sentinel node
673                root[:] = [root, root, None]
674                self.__map = {}
675            self.__update(*args, **kwds)
676
677        def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
678            'od.__setitem__(i, y) <==> od[i]=y'
679            # Setting a new item creates a new link which goes at the end of the linked
680            # list, and the inherited dictionary is updated with the new key/value pair.
681            if key not in self:
682                root = self.__root
683                last = root[0]
684                last[1] = root[0] = self.__map[key] = [last, root, key]
685            dict_setitem(self, key, value)
686
687        def __delitem__(self, key, dict_delitem=dict.__delitem__):
688            'od.__delitem__(y) <==> del od[y]'
689            # Deleting an existing item uses self.__map to find the link which is
690            # then removed by updating the links in the predecessor and successor nodes.
691            dict_delitem(self, key)
692            link_prev, link_next, key = self.__map.pop(key)
693            link_prev[1] = link_next
694            link_next[0] = link_prev
695
696        def __iter__(self):
697            'od.__iter__() <==> iter(od)'
698            root = self.__root
699            curr = root[1]
700            while curr is not root:
701                yield curr[2]
702                curr = curr[1]
703
704        def __reversed__(self):
705            'od.__reversed__() <==> reversed(od)'
706            root = self.__root
707            curr = root[0]
708            while curr is not root:
709                yield curr[2]
710                curr = curr[0]
711
712        def clear(self):
713            'od.clear() -> None.  Remove all items from od.'
714            try:
715                for node in self.__map.itervalues():
716                    del node[:]
717                root = self.__root
718                root[:] = [root, root, None]
719                self.__map.clear()
720            except AttributeError:
721                pass
722            dict.clear(self)
723
724        def popitem(self, last=True):
725            '''od.popitem() -> (k, v), return and remove a (key, value) pair.
726            Pairs are returned in LIFO order if last is true or FIFO order if false.
727
728            '''
729            if not self:
730                raise KeyError('dictionary is empty')
731            root = self.__root
732            if last:
733                link = root[0]
734                link_prev = link[0]
735                link_prev[1] = root
736                root[0] = link_prev
737            else:
738                link = root[1]
739                link_next = link[1]
740                root[1] = link_next
741                link_next[0] = root
742            key = link[2]
743            del self.__map[key]
744            value = dict.pop(self, key)
745            return key, value
746
747        # -- the following methods do not depend on the internal structure --
748
749        def keys(self):
750            'od.keys() -> list of keys in od'
751            return list(self)
752
753        def values(self):
754            'od.values() -> list of values in od'
755            return [self[key] for key in self]
756
757        def items(self):
758            'od.items() -> list of (key, value) pairs in od'
759            return [(key, self[key]) for key in self]
760
761        def iterkeys(self):
762            'od.iterkeys() -> an iterator over the keys in od'
763            return iter(self)
764
765        def itervalues(self):
766            'od.itervalues -> an iterator over the values in od'
767            for k in self:
768                yield self[k]
769
770        def iteritems(self):
771            'od.iteritems -> an iterator over the (key, value) items in od'
772            for k in self:
773                yield (k, self[k])
774
775        def update(*args, **kwds):
776            '''od.update(E, **F) -> None.  Update od from dict/iterable E and F.
777
778            If E is a dict instance, does:           for k in E: od[k] = E[k]
779            If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
780            Or if E is an iterable of items, does:   for k, v in E: od[k] = v
781            In either case, this is followed by:     for k, v in F.items(): od[k] = v
782
783            '''
784            if len(args) > 2:
785                raise TypeError('update() takes at most 2 positional '
786                                'arguments (%d given)' % (len(args),))
787            elif not args:
788                raise TypeError('update() takes at least 1 argument (0 given)')
789            self = args[0]
790            # Make progressively weaker assumptions about "other"
791            other = ()
792            if len(args) == 2:
793                other = args[1]
794            if isinstance(other, dict):
795                for key in other:
796                    self[key] = other[key]
797            elif hasattr(other, 'keys'):
798                for key in other.keys():
799                    self[key] = other[key]
800            else:
801                for key, value in other:
802                    self[key] = value
803            for key, value in kwds.items():
804                self[key] = value
805
806        __update = update  # let subclasses override update without breaking __init__
807
808        __marker = object()
809
810        def pop(self, key, default=__marker):
811            '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
812            If key is not found, d is returned if given, otherwise KeyError is raised.
813
814            '''
815            if key in self:
816                result = self[key]
817                del self[key]
818                return result
819            if default is self.__marker:
820                raise KeyError(key)
821            return default
822
823        def setdefault(self, key, default=None):
824            'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
825            if key in self:
826                return self[key]
827            self[key] = default
828            return default
829
830        def __repr__(self, _repr_running=None):
831            'od.__repr__() <==> repr(od)'
832            if not _repr_running: _repr_running = {}
833            call_key = id(self), _get_ident()
834            if call_key in _repr_running:
835                return '...'
836            _repr_running[call_key] = 1
837            try:
838                if not self:
839                    return '%s()' % (self.__class__.__name__,)
840                return '%s(%r)' % (self.__class__.__name__, self.items())
841            finally:
842                del _repr_running[call_key]
843
844        def __reduce__(self):
845            'Return state information for pickling'
846            items = [[k, self[k]] for k in self]
847            inst_dict = vars(self).copy()
848            for k in vars(OrderedDict()):
849                inst_dict.pop(k, None)
850            if inst_dict:
851                return (self.__class__, (items,), inst_dict)
852            return self.__class__, (items,)
853
854        def copy(self):
855            'od.copy() -> a shallow copy of od'
856            return self.__class__(self)
857
858        @classmethod
859        def fromkeys(cls, iterable, value=None):
860            '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
861            and values equal to v (which defaults to None).
862
863            '''
864            d = cls()
865            for key in iterable:
866                d[key] = value
867            return d
868
869        def __eq__(self, other):
870            '''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
871            while comparison to a regular mapping is order-insensitive.
872
873            '''
874            if isinstance(other, OrderedDict):
875                return len(self)==len(other) and self.items() == other.items()
876            return dict.__eq__(self, other)
877
878        def __ne__(self, other):
879            return not self == other
880
881        # -- the following methods are only used in Python 2.7 --
882
883        def viewkeys(self):
884            "od.viewkeys() -> a set-like object providing a view on od's keys"
885            return KeysView(self)
886
887        def viewvalues(self):
888            "od.viewvalues() -> an object providing a view on od's values"
889            return ValuesView(self)
890
891        def viewitems(self):
892            "od.viewitems() -> a set-like object providing a view on od's items"
893            return ItemsView(self)
894
895try:
896    from logging.config import BaseConfigurator, valid_ident
897except ImportError: # pragma: no cover
898    IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I)
899
900
901    def valid_ident(s):
902        m = IDENTIFIER.match(s)
903        if not m:
904            raise ValueError('Not a valid Python identifier: %r' % s)
905        return True
906
907
908    # The ConvertingXXX classes are wrappers around standard Python containers,
909    # and they serve to convert any suitable values in the container. The
910    # conversion converts base dicts, lists and tuples to their wrapped
911    # equivalents, whereas strings which match a conversion format are converted
912    # appropriately.
913    #
914    # Each wrapper should have a configurator attribute holding the actual
915    # configurator to use for conversion.
916
917    class ConvertingDict(dict):
918        """A converting dictionary wrapper."""
919
920        def __getitem__(self, key):
921            value = dict.__getitem__(self, key)
922            result = self.configurator.convert(value)
923            #If the converted value is different, save for next time
924            if value is not result:
925                self[key] = result
926                if type(result) in (ConvertingDict, ConvertingList,
927                                    ConvertingTuple):
928                    result.parent = self
929                    result.key = key
930            return result
931
932        def get(self, key, default=None):
933            value = dict.get(self, key, default)
934            result = self.configurator.convert(value)
935            #If the converted value is different, save for next time
936            if value is not result:
937                self[key] = result
938                if type(result) in (ConvertingDict, ConvertingList,
939                                    ConvertingTuple):
940                    result.parent = self
941                    result.key = key
942            return result
943
944    def pop(self, key, default=None):
945        value = dict.pop(self, key, default)
946        result = self.configurator.convert(value)
947        if value is not result:
948            if type(result) in (ConvertingDict, ConvertingList,
949                                ConvertingTuple):
950                result.parent = self
951                result.key = key
952        return result
953
954    class ConvertingList(list):
955        """A converting list wrapper."""
956        def __getitem__(self, key):
957            value = list.__getitem__(self, key)
958            result = self.configurator.convert(value)
959            #If the converted value is different, save for next time
960            if value is not result:
961                self[key] = result
962                if type(result) in (ConvertingDict, ConvertingList,
963                                    ConvertingTuple):
964                    result.parent = self
965                    result.key = key
966            return result
967
968        def pop(self, idx=-1):
969            value = list.pop(self, idx)
970            result = self.configurator.convert(value)
971            if value is not result:
972                if type(result) in (ConvertingDict, ConvertingList,
973                                    ConvertingTuple):
974                    result.parent = self
975            return result
976
977    class ConvertingTuple(tuple):
978        """A converting tuple wrapper."""
979        def __getitem__(self, key):
980            value = tuple.__getitem__(self, key)
981            result = self.configurator.convert(value)
982            if value is not result:
983                if type(result) in (ConvertingDict, ConvertingList,
984                                    ConvertingTuple):
985                    result.parent = self
986                    result.key = key
987            return result
988
989    class BaseConfigurator(object):
990        """
991        The configurator base class which defines some useful defaults.
992        """
993
994        CONVERT_PATTERN = re.compile(r'^(?P<prefix>[a-z]+)://(?P<suffix>.*)$')
995
996        WORD_PATTERN = re.compile(r'^\s*(\w+)\s*')
997        DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*')
998        INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*')
999        DIGIT_PATTERN = re.compile(r'^\d+$')
1000
1001        value_converters = {
1002            'ext' : 'ext_convert',
1003            'cfg' : 'cfg_convert',
1004        }
1005
1006        # We might want to use a different one, e.g. importlib
1007        importer = staticmethod(__import__)
1008
1009        def __init__(self, config):
1010            self.config = ConvertingDict(config)
1011            self.config.configurator = self
1012
1013        def resolve(self, s):
1014            """
1015            Resolve strings to objects using standard import and attribute
1016            syntax.
1017            """
1018            name = s.split('.')
1019            used = name.pop(0)
1020            try:
1021                found = self.importer(used)
1022                for frag in name:
1023                    used += '.' + frag
1024                    try:
1025                        found = getattr(found, frag)
1026                    except AttributeError:
1027                        self.importer(used)
1028                        found = getattr(found, frag)
1029                return found
1030            except ImportError:
1031                e, tb = sys.exc_info()[1:]
1032                v = ValueError('Cannot resolve %r: %s' % (s, e))
1033                v.__cause__, v.__traceback__ = e, tb
1034                raise v
1035
1036        def ext_convert(self, value):
1037            """Default converter for the ext:// protocol."""
1038            return self.resolve(value)
1039
1040        def cfg_convert(self, value):
1041            """Default converter for the cfg:// protocol."""
1042            rest = value
1043            m = self.WORD_PATTERN.match(rest)
1044            if m is None:
1045                raise ValueError("Unable to convert %r" % value)
1046            else:
1047                rest = rest[m.end():]
1048                d = self.config[m.groups()[0]]
1049                #print d, rest
1050                while rest:
1051                    m = self.DOT_PATTERN.match(rest)
1052                    if m:
1053                        d = d[m.groups()[0]]
1054                    else:
1055                        m = self.INDEX_PATTERN.match(rest)
1056                        if m:
1057                            idx = m.groups()[0]
1058                            if not self.DIGIT_PATTERN.match(idx):
1059                                d = d[idx]
1060                            else:
1061                                try:
1062                                    n = int(idx) # try as number first (most likely)
1063                                    d = d[n]
1064                                except TypeError:
1065                                    d = d[idx]
1066                    if m:
1067                        rest = rest[m.end():]
1068                    else:
1069                        raise ValueError('Unable to convert '
1070                                         '%r at %r' % (value, rest))
1071            #rest should be empty
1072            return d
1073
1074        def convert(self, value):
1075            """
1076            Convert values to an appropriate type. dicts, lists and tuples are
1077            replaced by their converting alternatives. Strings are checked to
1078            see if they have a conversion format and are converted if they do.
1079            """
1080            if not isinstance(value, ConvertingDict) and isinstance(value, dict):
1081                value = ConvertingDict(value)
1082                value.configurator = self
1083            elif not isinstance(value, ConvertingList) and isinstance(value, list):
1084                value = ConvertingList(value)
1085                value.configurator = self
1086            elif not isinstance(value, ConvertingTuple) and\
1087                     isinstance(value, tuple):
1088                value = ConvertingTuple(value)
1089                value.configurator = self
1090            elif isinstance(value, string_types):
1091                m = self.CONVERT_PATTERN.match(value)
1092                if m:
1093                    d = m.groupdict()
1094                    prefix = d['prefix']
1095                    converter = self.value_converters.get(prefix, None)
1096                    if converter:
1097                        suffix = d['suffix']
1098                        converter = getattr(self, converter)
1099                        value = converter(suffix)
1100            return value
1101
1102        def configure_custom(self, config):
1103            """Configure an object with a user-supplied factory."""
1104            c = config.pop('()')
1105            if not callable(c):
1106                c = self.resolve(c)
1107            props = config.pop('.', None)
1108            # Check for valid identifiers
1109            kwargs = dict([(k, config[k]) for k in config if valid_ident(k)])
1110            result = c(**kwargs)
1111            if props:
1112                for name, value in props.items():
1113                    setattr(result, name, value)
1114            return result
1115
1116        def as_tuple(self, value):
1117            """Utility function which converts lists to tuples."""
1118            if isinstance(value, list):
1119                value = tuple(value)
1120            return value
1121