@@ -2327,3 +2327,265 @@ def get_instancemethod(self):
2327
2327
else :
2328
2328
def _putmask (a , mask , values ):
2329
2329
return np .copyto (a , values , where = mask )
2330
+
2331
+ # TODO Remove when the following code when we no longer support python-2.6
2332
+ # Code taken from http://code.activestate.com/recipes/576693/ referenced from
2333
+ # https://docs.python.org/2/library/collections.html#collections.OrderedDict
2334
+ # Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
2335
+ # Passes Python2.7's test suite and incorporates all the latest updates.
2336
+
2337
+ try :
2338
+ from thread import get_ident as _get_ident
2339
+ except ImportError :
2340
+ from dummy_thread import get_ident as _get_ident
2341
+
2342
+ try :
2343
+ from _abcoll import KeysView , ValuesView , ItemsView
2344
+ except ImportError :
2345
+ pass
2346
+
2347
+
2348
+ class OrderedDict (dict ):
2349
+ 'Dictionary that remembers insertion order'
2350
+ # An inherited dict maps keys to values.
2351
+ # The inherited dict provides __getitem__, __len__, __contains__, and get.
2352
+ # The remaining methods are order-aware.
2353
+ # Big-O running times for all methods are the same as for regular dictionaries.
2354
+
2355
+ # The internal self.__map dictionary maps keys to links in a doubly linked list.
2356
+ # The circular doubly linked list starts and ends with a sentinel element.
2357
+ # The sentinel element never gets deleted (this simplifies the algorithm).
2358
+ # Each link is stored as a list of length three: [PREV, NEXT, KEY].
2359
+
2360
+ def __init__ (self , * args , ** kwds ):
2361
+ '''Initialize an ordered dictionary. Signature is the same as for
2362
+ regular dictionaries, but keyword arguments are not recommended
2363
+ because their insertion order is arbitrary.
2364
+
2365
+ '''
2366
+ if len (args ) > 1 :
2367
+ raise TypeError ('expected at most 1 arguments, got %d' % len (args ))
2368
+ try :
2369
+ self .__root
2370
+ except AttributeError :
2371
+ self .__root = root = [] # sentinel node
2372
+ root [:] = [root , root , None ]
2373
+ self .__map = {}
2374
+ self .__update (* args , ** kwds )
2375
+
2376
+ def __setitem__ (self , key , value , dict_setitem = dict .__setitem__ ):
2377
+ 'od.__setitem__(i, y) <==> od[i]=y'
2378
+ # Setting a new item creates a new link which goes at the end of the linked
2379
+ # list, and the inherited dictionary is updated with the new key/value pair.
2380
+ if key not in self :
2381
+ root = self .__root
2382
+ last = root [0 ]
2383
+ last [1 ] = root [0 ] = self .__map [key ] = [last , root , key ]
2384
+ dict_setitem (self , key , value )
2385
+
2386
+ def __delitem__ (self , key , dict_delitem = dict .__delitem__ ):
2387
+ 'od.__delitem__(y) <==> del od[y]'
2388
+ # Deleting an existing item uses self.__map to find the link which is
2389
+ # then removed by updating the links in the predecessor and successor nodes.
2390
+ dict_delitem (self , key )
2391
+ link_prev , link_next , key = self .__map .pop (key )
2392
+ link_prev [1 ] = link_next
2393
+ link_next [0 ] = link_prev
2394
+
2395
+ def __iter__ (self ):
2396
+ 'od.__iter__() <==> iter(od)'
2397
+ root = self .__root
2398
+ curr = root [1 ]
2399
+ while curr is not root :
2400
+ yield curr [2 ]
2401
+ curr = curr [1 ]
2402
+
2403
+ def __reversed__ (self ):
2404
+ 'od.__reversed__() <==> reversed(od)'
2405
+ root = self .__root
2406
+ curr = root [0 ]
2407
+ while curr is not root :
2408
+ yield curr [2 ]
2409
+ curr = curr [0 ]
2410
+
2411
+ def clear (self ):
2412
+ 'od.clear() -> None. Remove all items from od.'
2413
+ try :
2414
+ for node in self .__map .itervalues ():
2415
+ del node [:]
2416
+ root = self .__root
2417
+ root [:] = [root , root , None ]
2418
+ self .__map .clear ()
2419
+ except AttributeError :
2420
+ pass
2421
+ dict .clear (self )
2422
+
2423
+ def popitem (self , last = True ):
2424
+ '''od.popitem() -> (k, v), return and remove a (key, value) pair.
2425
+ Pairs are returned in LIFO order if last is true or FIFO order if false.
2426
+
2427
+ '''
2428
+ if not self :
2429
+ raise KeyError ('dictionary is empty' )
2430
+ root = self .__root
2431
+ if last :
2432
+ link = root [0 ]
2433
+ link_prev = link [0 ]
2434
+ link_prev [1 ] = root
2435
+ root [0 ] = link_prev
2436
+ else :
2437
+ link = root [1 ]
2438
+ link_next = link [1 ]
2439
+ root [1 ] = link_next
2440
+ link_next [0 ] = root
2441
+ key = link [2 ]
2442
+ del self .__map [key ]
2443
+ value = dict .pop (self , key )
2444
+ return key , value
2445
+
2446
+ # -- the following methods do not depend on the internal structure --
2447
+
2448
+ def keys (self ):
2449
+ 'od.keys() -> list of keys in od'
2450
+ return list (self )
2451
+
2452
+ def values (self ):
2453
+ 'od.values() -> list of values in od'
2454
+ return [self [key ] for key in self ]
2455
+
2456
+ def items (self ):
2457
+ 'od.items() -> list of (key, value) pairs in od'
2458
+ return [(key , self [key ]) for key in self ]
2459
+
2460
+ def iterkeys (self ):
2461
+ 'od.iterkeys() -> an iterator over the keys in od'
2462
+ return iter (self )
2463
+
2464
+ def itervalues (self ):
2465
+ 'od.itervalues -> an iterator over the values in od'
2466
+ for k in self :
2467
+ yield self [k ]
2468
+
2469
+ def iteritems (self ):
2470
+ 'od.iteritems -> an iterator over the (key, value) items in od'
2471
+ for k in self :
2472
+ yield (k , self [k ])
2473
+
2474
+ def update (* args , ** kwds ):
2475
+ '''od.update(E, **F) -> None. Update od from dict/iterable E and F.
2476
+
2477
+ If E is a dict instance, does: for k in E: od[k] = E[k]
2478
+ If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
2479
+ Or if E is an iterable of items, does: for k, v in E: od[k] = v
2480
+ In either case, this is followed by: for k, v in F.items(): od[k] = v
2481
+
2482
+ '''
2483
+ if len (args ) > 2 :
2484
+ raise TypeError ('update() takes at most 2 positional '
2485
+ 'arguments (%d given)' % (len (args ),))
2486
+ elif not args :
2487
+ raise TypeError ('update() takes at least 1 argument (0 given)' )
2488
+ self = args [0 ]
2489
+ # Make progressively weaker assumptions about "other"
2490
+ other = ()
2491
+ if len (args ) == 2 :
2492
+ other = args [1 ]
2493
+ if isinstance (other , dict ):
2494
+ for key in other :
2495
+ self [key ] = other [key ]
2496
+ elif hasattr (other , 'keys' ):
2497
+ for key in other .keys ():
2498
+ self [key ] = other [key ]
2499
+ else :
2500
+ for key , value in other :
2501
+ self [key ] = value
2502
+ for key , value in kwds .items ():
2503
+ self [key ] = value
2504
+
2505
+ __update = update # let subclasses override update without breaking __init__
2506
+
2507
+ __marker = object ()
2508
+
2509
+ def pop (self , key , default = __marker ):
2510
+ '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
2511
+ If key is not found, d is returned if given, otherwise KeyError is raised.
2512
+
2513
+ '''
2514
+ if key in self :
2515
+ result = self [key ]
2516
+ del self [key ]
2517
+ return result
2518
+ if default is self .__marker :
2519
+ raise KeyError (key )
2520
+ return default
2521
+
2522
+ def setdefault (self , key , default = None ):
2523
+ 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
2524
+ if key in self :
2525
+ return self [key ]
2526
+ self [key ] = default
2527
+ return default
2528
+
2529
+ def __repr__ (self , _repr_running = {}):
2530
+ 'od.__repr__() <==> repr(od)'
2531
+ call_key = id (self ), _get_ident ()
2532
+ if call_key in _repr_running :
2533
+ return '...'
2534
+ _repr_running [call_key ] = 1
2535
+ try :
2536
+ if not self :
2537
+ return '%s()' % (self .__class__ .__name__ ,)
2538
+ return '%s(%r)' % (self .__class__ .__name__ , self .items ())
2539
+ finally :
2540
+ del _repr_running [call_key ]
2541
+
2542
+ def __reduce__ (self ):
2543
+ 'Return state information for pickling'
2544
+ items = [[k , self [k ]] for k in self ]
2545
+ inst_dict = vars (self ).copy ()
2546
+ for k in vars (OrderedDict ()):
2547
+ inst_dict .pop (k , None )
2548
+ if inst_dict :
2549
+ return (self .__class__ , (items ,), inst_dict )
2550
+ return self .__class__ , (items ,)
2551
+
2552
+ def copy (self ):
2553
+ 'od.copy() -> a shallow copy of od'
2554
+ return self .__class__ (self )
2555
+
2556
+ @classmethod
2557
+ def fromkeys (cls , iterable , value = None ):
2558
+ '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
2559
+ and values equal to v (which defaults to None).
2560
+
2561
+ '''
2562
+ d = cls ()
2563
+ for key in iterable :
2564
+ d [key ] = value
2565
+ return d
2566
+
2567
+ def __eq__ (self , other ):
2568
+ '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
2569
+ while comparison to a regular mapping is order-insensitive.
2570
+
2571
+ '''
2572
+ if isinstance (other , OrderedDict ):
2573
+ return len (self )== len (other ) and self .items () == other .items ()
2574
+ return dict .__eq__ (self , other )
2575
+
2576
+ def __ne__ (self , other ):
2577
+ return not self == other
2578
+
2579
+ # -- the following methods are only used in Python 2.7 --
2580
+
2581
+ def viewkeys (self ):
2582
+ "od.viewkeys() -> a set-like object providing a view on od's keys"
2583
+ return KeysView (self )
2584
+
2585
+ def viewvalues (self ):
2586
+ "od.viewvalues() -> an object providing a view on od's values"
2587
+ return ValuesView (self )
2588
+
2589
+ def viewitems (self ):
2590
+ "od.viewitems() -> a set-like object providing a view on od's items"
2591
+ return ItemsView (self )
0 commit comments