5555try :
5656 import collections .abc as compat_collections_abc
5757except ImportError :
58- import collections as compat_collections_abc
58+ compat_collections_abc = collections
5959
6060
6161# compat_urllib_request
@@ -3452,13 +3452,18 @@ def unpack(self, string):
34523452 except ImportError :
34533453 compat_map = map
34543454
3455+
3456+ # compat_filter, compat_filter_fns
34553457try :
34563458 from future_builtins import filter as compat_filter
34573459except ImportError :
34583460 try :
34593461 from itertools import ifilter as compat_filter
34603462 except ImportError :
34613463 compat_filter = filter
3464+ # "Is this function one or maybe the other filter()?"
3465+ compat_filter_fns = tuple (set ((filter , compat_filter )))
3466+
34623467
34633468# compat_zip
34643469try :
@@ -3478,6 +3483,40 @@ def unpack(self, string):
34783483 from itertools import izip_longest as compat_itertools_zip_longest
34793484
34803485
3486+ # compat_abc_ABC
3487+ try :
3488+ from abc import ABC as compat_abc_ABC
3489+ except ImportError :
3490+ # Py < 3.4
3491+ from abc import ABCMeta as _ABCMeta
3492+ compat_abc_ABC = _ABCMeta (str ('ABC' ), (object ,), {})
3493+
3494+
3495+ # dict mixin used here
3496+ # like UserDict.DictMixin, without methods created by MutableMapping
3497+ class _DictMixin (compat_abc_ABC ):
3498+ def has_key (self , key ):
3499+ return key in self
3500+
3501+ # get(), clear(), setdefault() in MM
3502+
3503+ def iterkeys (self ):
3504+ return (k for k in self )
3505+
3506+ def itervalues (self ):
3507+ return (self [k ] for k in self )
3508+
3509+ def iteritems (self ):
3510+ return ((k , self [k ]) for k in self )
3511+
3512+ # pop(), popitem() in MM
3513+
3514+ def copy (self ):
3515+ return type (self )(self )
3516+
3517+ # update() in MM
3518+
3519+
34813520# compat_collections_chain_map
34823521# collections.ChainMap: new class
34833522try :
@@ -3632,6 +3671,129 @@ def compat_datetime_timedelta_total_seconds(td):
36323671 compat_zstandard = None
36333672
36343673
3674+ # compat_thread
3675+ try :
3676+ import _thread as compat_thread
3677+ except ImportError :
3678+ try :
3679+ import thread as compat_thread
3680+ except ImportError :
3681+ import dummy_thread as compat_thread
3682+
3683+
3684+ # compat_dict
3685+ # compat_builtins_dict
3686+ # compat_dict_items
3687+ if sys .version_info >= (3 , 6 ):
3688+ compat_dict = compat_builtins_dict = dict
3689+ compat_dict_items = dict .items
3690+ else :
3691+ _get_ident = compat_thread .get_ident
3692+
3693+ class compat_dict (compat_collections_abc .MutableMapping , _DictMixin , dict ):
3694+ """`dict` that preserves insertion order with interface like Py3.7+"""
3695+
3696+ _order = [] # default that should never be used
3697+
3698+ def __init__ (self , * mappings_or_iterables , ** kwargs ):
3699+ # order an unordered dict using a list of keys: actual Py 2.7+
3700+ # OrderedDict uses a doubly linked list for better performance
3701+ self ._order = []
3702+ for arg in mappings_or_iterables :
3703+ self .__update (arg )
3704+ if kwargs :
3705+ self .__update (kwargs )
3706+
3707+ def __getitem__ (self , key ):
3708+ return dict .__getitem__ (self , key )
3709+
3710+ def __setitem__ (self , key , value ):
3711+ try :
3712+ if key not in self ._order :
3713+ self ._order .append (key )
3714+ dict .__setitem__ (self , key , value )
3715+ except Exception :
3716+ if key in self ._order [- 1 :] and key not in self :
3717+ del self ._order [- 1 ]
3718+ raise
3719+
3720+ def __len__ (self ):
3721+ return dict .__len__ (self )
3722+
3723+ def __delitem__ (self , key ):
3724+ dict .__delitem__ (self , key )
3725+ try :
3726+ # expected case, O(len(self)), but who dels anyway?
3727+ self ._order .remove (key )
3728+ except ValueError :
3729+ pass
3730+
3731+ def __iter__ (self ):
3732+ for from_ in self ._order :
3733+ if from_ in self :
3734+ yield from_
3735+
3736+ def __del__ (self ):
3737+ for attr in ('_order' ,):
3738+ try :
3739+ delattr (self , attr )
3740+ except Exception :
3741+ pass
3742+
3743+ def __repr__ (self , _repr_running = {}):
3744+ # skip recursive items ...
3745+ call_key = id (self ), _get_ident ()
3746+ if _repr_running .get (call_key ):
3747+ return '...'
3748+ _repr_running [call_key ] = True
3749+ try :
3750+ return '%s({%s})' % (
3751+ type (self ).__name__ ,
3752+ ',' .join ('%r: %r' % k_v for k_v in self .items ()))
3753+ finally :
3754+ del _repr_running [call_key ]
3755+
3756+ # merge/update (PEP 584)
3757+
3758+ def __or__ (self , other ):
3759+ if not isinstance (other , compat_collections_abc .Mapping ):
3760+ return NotImplemented
3761+ new = type (self )(self )
3762+ new .update (other )
3763+ return new
3764+
3765+ def __ror__ (self , other ):
3766+ if not isinstance (other , compat_collections_abc .Mapping ):
3767+ return NotImplemented
3768+ new = type (other )(other )
3769+ new .update (self )
3770+ return new
3771+
3772+ def __ior__ (self , other ):
3773+ self .update (other )
3774+ return self
3775+
3776+ # optimisations
3777+
3778+ def __reversed__ (self ):
3779+ for from_ in reversed (self ._order ):
3780+ if from_ in self :
3781+ yield from_
3782+
3783+ def __contains__ (self , item ):
3784+ return dict .__contains__ (self , item )
3785+
3786+ # allow overriding update without breaking __init__
3787+ def __update (self , * args , ** kwargs ):
3788+ super (compat_dict , self ).update (* args , ** kwargs )
3789+
3790+ compat_builtins_dict = dict
3791+ # Using the object's method, not dict's:
3792+ # an ordered dict's items can be returned unstably by unordered
3793+ # dict.items as if the method was not ((k, self[k]) for k in self)
3794+ compat_dict_items = lambda d : d .items ()
3795+
3796+
36353797legacy = [
36363798 'compat_HTMLParseError' ,
36373799 'compat_HTMLParser' ,
@@ -3662,19 +3824,24 @@ def compat_datetime_timedelta_total_seconds(td):
36623824
36633825__all__ = [
36643826 'compat_Struct' ,
3827+ 'compat_abc_ABC' ,
36653828 'compat_base64_b64decode' ,
36663829 'compat_basestring' ,
36673830 'compat_brotli' ,
3831+ 'compat_builtins_dict' ,
36683832 'compat_casefold' ,
36693833 'compat_chr' ,
36703834 'compat_collections_abc' ,
36713835 'compat_collections_chain_map' ,
36723836 'compat_contextlib_suppress' ,
36733837 'compat_ctypes_WINFUNCTYPE' ,
36743838 'compat_datetime_timedelta_total_seconds' ,
3839+ 'compat_dict' ,
3840+ 'compat_dict_items' ,
36753841 'compat_etree_fromstring' ,
36763842 'compat_etree_iterfind' ,
36773843 'compat_filter' ,
3844+ 'compat_filter_fns' ,
36783845 'compat_get_terminal_size' ,
36793846 'compat_getenv' ,
36803847 'compat_getpass_getpass' ,
@@ -3716,6 +3883,7 @@ def compat_datetime_timedelta_total_seconds(td):
37163883 'compat_struct_unpack' ,
37173884 'compat_subprocess_get_DEVNULL' ,
37183885 'compat_subprocess_Popen' ,
3886+ 'compat_thread' ,
37193887 'compat_tokenize_tokenize' ,
37203888 'compat_urllib_error' ,
37213889 'compat_urllib_parse' ,
0 commit comments