22
33from types import ModuleType
44
5+ try :
6+ from collections .abc import Mapping
7+ except ImportError :
8+ from collections import Mapping
9+
510from six import text_type
611
712try :
@@ -47,9 +52,6 @@ class MethodDispatcher(dict):
4752 """
4853
4954 def __init__ (self , items = ()):
50- # Using _dictEntries instead of directly assigning to self is about
51- # twice as fast. Please do careful performance testing before changing
52- # anything here.
5355 _dictEntries = []
5456 for name , value in items :
5557 if isinstance (name , (list , tuple , frozenset , set )):
@@ -64,6 +66,36 @@ def __init__(self, items=()):
6466 def __getitem__ (self , key ):
6567 return dict .get (self , key , self .default )
6668
69+ def __get__ (self , instance , owner = None ):
70+ return BoundMethodDispatcher (instance , self )
71+
72+
73+ class BoundMethodDispatcher (Mapping ):
74+ """Wraps a MethodDispatcher, binding its return values to `instance`"""
75+ def __init__ (self , instance , dispatcher ):
76+ self .instance = instance
77+ self .dispatcher = dispatcher
78+
79+ def __getitem__ (self , key ):
80+ # see https://docs.python.org/3/reference/datamodel.html#object.__get__
81+ # on a function, __get__ is used to bind a function to an instance as a bound method
82+ return self .dispatcher [key ].__get__ (self .instance )
83+
84+ def get (self , key , default ):
85+ if key in self .dispatcher :
86+ return self [key ]
87+ else :
88+ return default
89+
90+ def __iter__ (self ):
91+ return iter (self .dispatcher )
92+
93+ def __len__ (self ):
94+ return len (self .dispatcher )
95+
96+ def __contains__ (self , key ):
97+ return key in self .dispatcher
98+
6799
68100# Some utility functions to deal with weirdness around UCS2 vs UCS4
69101# python builds
0 commit comments