22from collections import Counter
33
44if sys .version_info [0 ] >= 3 :
5+ _iter_values = 'values'
56 _range = range
6- string_type = str
7+ _string_type = str
78 import collections as _c
89 class _kView (_c .KeysView ):
910 def __iter__ (self ):
@@ -15,8 +16,9 @@ class _iView(_c.ItemsView):
1516 def __iter__ (self ):
1617 return self ._mapping .iteritems ()
1718else :
19+ _iter_values = 'itervalues'
1820 _range = xrange
19- string_type = basestring
21+ _string_type = basestring
2022 _kView = lambda x : list (x .iterkeys ())
2123 _vView = lambda x : list (x .itervalues ())
2224 _iView = lambda x : list (x .iteritems ())
@@ -56,11 +58,11 @@ def _verify_key_tuple(self, key):
5658 raise ValueError ("Expected key tuple length to be 2, got %d" % len (key ))
5759 if not isinstance (key [0 ], int ):
5860 raise TypeError ("Key index should be an int" )
59- if not isinstance (key [1 ], string_type ):
61+ if not isinstance (key [1 ], _string_type ):
6062 raise TypeError ("Key value should be a str" )
6163
6264 def _normalize_key (self , key ):
63- if isinstance (key , string_type ):
65+ if isinstance (key , _string_type ):
6466 key = (0 , key )
6567 elif isinstance (key , tuple ):
6668 self ._verify_key_tuple (key )
@@ -69,7 +71,7 @@ def _normalize_key(self, key):
6971 return key
7072
7173 def __setitem__ (self , key , value ):
72- if isinstance (key , string_type ):
74+ if isinstance (key , _string_type ):
7375 key = (self .__kcount [key ], key )
7476 self .__omap .append (key )
7577 elif isinstance (key , tuple ):
@@ -183,13 +185,13 @@ def items(self):
183185
184186 def get_all_for (self , key ):
185187 """ Returns all values of the given key """
186- if not isinstance (key , string_type ):
188+ if not isinstance (key , _string_type ):
187189 raise TypeError ("Key needs to be a string." )
188190 return [self [(idx , key )] for idx in _range (self .__kcount [key ])]
189191
190192 def remove_all_for (self , key ):
191193 """ Removes all items with the given key """
192- if not isinstance (key , string_type ):
194+ if not isinstance (key , _string_type ):
193195 raise TypeError ("Key need to be a string." )
194196
195197 for idx in _range (self .__kcount [key ]):
@@ -198,3 +200,22 @@ def remove_all_for(self, key):
198200 self .__omap = list (filter (lambda x : x [1 ] != key , self .__omap ))
199201
200202 del self .__kcount [key ]
203+
204+ def has_duplicates (self ):
205+ """
206+ Returns ``True`` if the dict contains keys with duplicates.
207+ Recurses through any all keys with value that is ``VDFDict``.
208+ """
209+ for n in getattr (self .__kcount , _iter_values )():
210+ if n != 1 :
211+ return True
212+
213+ def dict_recurse (obj ):
214+ for v in getattr (obj , _iter_values )():
215+ if isinstance (v , VDFDict ) and v .has_duplicates ():
216+ return True
217+ elif isinstance (v , dict ):
218+ return dict_recurse (v )
219+ return False
220+
221+ return dict_recurse (self )
0 commit comments