Package param :: Module external
[hide private]
[frames] | no frames]

Source Code for Module param.external

   1  """ 
   2  External code required for param/tkinter interface. 
   3   
   4  * odict: an ordered dictionary 
   5  * tilewrapper: a wrapper for Tile/ttk widgets 
   6   
   7  Note that an ordered dictionary and a wrapper for ttk widgets are both 
   8  available in Python 2.7. 
   9  """ 
  10   
  11  from __future__ import generators 
  12   
  13  # odict.py 
  14  # An Ordered Dictionary object 
  15  # Copyright (C) 2005 Nicola Larosa, Michael Foord 
  16  # E-mail: nico AT tekNico DOT net, fuzzyman AT voidspace DOT org DOT uk 
  17   
  18  # This software is licensed under the terms of the BSD license. 
  19  # http://www.voidspace.org.uk/python/license.shtml 
  20  # Basically you're free to copy, modify, distribute and relicense it, 
  21  # So long as you keep a copy of the license with it. 
  22   
  23  # Documentation at http://www.voidspace.org.uk/python/odict.html 
  24  # For information about bugfixes, updates and support, please join the 
  25  # Pythonutils mailing list: 
  26  # http://groups.google.com/group/pythonutils/ 
  27  # Comments, suggestions and bug reports welcome. 
  28   
  29  """A dict that keeps keys in insertion order""" 
  30   
  31   
  32  __author__ = ('Nicola Larosa <nico-NoSp@m-tekNico.net>,' 
  33      'Michael Foord <fuzzyman AT voidspace DOT org DOT uk>') 
  34   
  35  __docformat__ = "restructuredtext en" 
  36   
  37  __revision__ = '$Id: external.py 11264 2010-07-21 18:12:49Z ceball $' 
  38   
  39  __version__ = '0.2.2' 
  40   
  41  __all__ = ['OrderedDict', 'SequenceOrderedDict'] 
  42   
  43  import sys 
  44  INTP_VER = sys.version_info[:2] 
  45  if INTP_VER < (2, 2): 
  46      raise RuntimeError("Python v.2.2 or later required") 
  47   
  48  import types, warnings 
  49   
50 -class OrderedDict(dict):
51 """ 52 A class of dictionary that keeps the insertion order of keys. 53 54 All appropriate methods return keys, items, or values in an ordered way. 55 56 All normal dictionary methods are available. Update and comparison is 57 restricted to other OrderedDict objects. 58 59 Various sequence methods are available, including the ability to explicitly 60 mutate the key ordering. 61 62 __contains__ tests: 63 64 >>> d = OrderedDict(((1, 3),)) 65 >>> 1 in d 66 1 67 >>> 4 in d 68 0 69 70 __getitem__ tests: 71 72 >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[2] 73 1 74 >>> OrderedDict(((1, 3), (3, 2), (2, 1)))[4] 75 Traceback (most recent call last): 76 KeyError: 4 77 78 __len__ tests: 79 80 >>> len(OrderedDict()) 81 0 82 >>> len(OrderedDict(((1, 3), (3, 2), (2, 1)))) 83 3 84 85 get tests: 86 87 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 88 >>> d.get(1) 89 3 90 >>> d.get(4) is None 91 1 92 >>> d.get(4, 5) 93 5 94 >>> d 95 OrderedDict([(1, 3), (3, 2), (2, 1)]) 96 97 has_key tests: 98 99 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 100 >>> d.has_key(1) 101 1 102 >>> d.has_key(4) 103 0 104 """ 105
106 - def __init__(self, init_val=(), strict=False):
107 """ 108 Create a new ordered dictionary. Cannot init from a normal dict, 109 nor from kwargs, since items order is undefined in those cases. 110 111 If the ``strict`` keyword argument is ``True`` (``False`` is the 112 default) then when doing slice assignment - the ``OrderedDict`` you are 113 assigning from *must not* contain any keys in the remaining dict. 114 115 >>> OrderedDict() 116 OrderedDict([]) 117 >>> OrderedDict({1: 1}) 118 Traceback (most recent call last): 119 TypeError: undefined order, cannot get items from dict 120 >>> OrderedDict({1: 1}.items()) 121 OrderedDict([(1, 1)]) 122 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 123 >>> d 124 OrderedDict([(1, 3), (3, 2), (2, 1)]) 125 >>> OrderedDict(d) 126 OrderedDict([(1, 3), (3, 2), (2, 1)]) 127 """ 128 self.strict = strict 129 dict.__init__(self) 130 if isinstance(init_val, OrderedDict): 131 self._sequence = init_val.keys() 132 dict.update(self, init_val) 133 elif isinstance(init_val, dict): 134 # we lose compatibility with other ordered dict types this way 135 raise TypeError('undefined order, cannot get items from dict') 136 else: 137 self._sequence = [] 138 self.update(init_val)
139 140 ### Special methods ### 141
142 - def __delitem__(self, key):
143 """ 144 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 145 >>> del d[3] 146 >>> d 147 OrderedDict([(1, 3), (2, 1)]) 148 >>> del d[3] 149 Traceback (most recent call last): 150 KeyError: 3 151 >>> d[3] = 2 152 >>> d 153 OrderedDict([(1, 3), (2, 1), (3, 2)]) 154 >>> del d[0:1] 155 >>> d 156 OrderedDict([(2, 1), (3, 2)]) 157 """ 158 if isinstance(key, types.SliceType): 159 # FIXME: efficiency? 160 keys = self._sequence[key] 161 for entry in keys: 162 dict.__delitem__(self, entry) 163 del self._sequence[key] 164 else: 165 # do the dict.__delitem__ *first* as it raises 166 # the more appropriate error 167 dict.__delitem__(self, key) 168 self._sequence.remove(key)
169
170 - def __eq__(self, other):
171 """ 172 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 173 >>> d == OrderedDict(d) 174 True 175 >>> d == OrderedDict(((1, 3), (2, 1), (3, 2))) 176 False 177 >>> d == OrderedDict(((1, 0), (3, 2), (2, 1))) 178 False 179 >>> d == OrderedDict(((0, 3), (3, 2), (2, 1))) 180 False 181 >>> d == dict(d) 182 False 183 >>> d == False 184 False 185 """ 186 if isinstance(other, OrderedDict): 187 # FIXME: efficiency? 188 # Generate both item lists for each compare 189 return (self.items() == other.items()) 190 else: 191 return False
192
193 - def __lt__(self, other):
194 """ 195 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 196 >>> c = OrderedDict(((0, 3), (3, 2), (2, 1))) 197 >>> c < d 198 True 199 >>> d < c 200 False 201 >>> d < dict(c) 202 Traceback (most recent call last): 203 TypeError: Can only compare with other OrderedDicts 204 """ 205 if not isinstance(other, OrderedDict): 206 raise TypeError('Can only compare with other OrderedDicts') 207 # FIXME: efficiency? 208 # Generate both item lists for each compare 209 return (self.items() < other.items())
210
211 - def __le__(self, other):
212 """ 213 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 214 >>> c = OrderedDict(((0, 3), (3, 2), (2, 1))) 215 >>> e = OrderedDict(d) 216 >>> c <= d 217 True 218 >>> d <= c 219 False 220 >>> d <= dict(c) 221 Traceback (most recent call last): 222 TypeError: Can only compare with other OrderedDicts 223 >>> d <= e 224 True 225 """ 226 if not isinstance(other, OrderedDict): 227 raise TypeError('Can only compare with other OrderedDicts') 228 # FIXME: efficiency? 229 # Generate both item lists for each compare 230 return (self.items() <= other.items())
231
232 - def __ne__(self, other):
233 """ 234 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 235 >>> d != OrderedDict(d) 236 False 237 >>> d != OrderedDict(((1, 3), (2, 1), (3, 2))) 238 True 239 >>> d != OrderedDict(((1, 0), (3, 2), (2, 1))) 240 True 241 >>> d == OrderedDict(((0, 3), (3, 2), (2, 1))) 242 False 243 >>> d != dict(d) 244 True 245 >>> d != False 246 True 247 """ 248 if isinstance(other, OrderedDict): 249 # FIXME: efficiency? 250 # Generate both item lists for each compare 251 return not (self.items() == other.items()) 252 else: 253 return True
254
255 - def __gt__(self, other):
256 """ 257 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 258 >>> c = OrderedDict(((0, 3), (3, 2), (2, 1))) 259 >>> d > c 260 True 261 >>> c > d 262 False 263 >>> d > dict(c) 264 Traceback (most recent call last): 265 TypeError: Can only compare with other OrderedDicts 266 """ 267 if not isinstance(other, OrderedDict): 268 raise TypeError('Can only compare with other OrderedDicts') 269 # FIXME: efficiency? 270 # Generate both item lists for each compare 271 return (self.items() > other.items())
272
273 - def __ge__(self, other):
274 """ 275 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 276 >>> c = OrderedDict(((0, 3), (3, 2), (2, 1))) 277 >>> e = OrderedDict(d) 278 >>> c >= d 279 False 280 >>> d >= c 281 True 282 >>> d >= dict(c) 283 Traceback (most recent call last): 284 TypeError: Can only compare with other OrderedDicts 285 >>> e >= d 286 True 287 """ 288 if not isinstance(other, OrderedDict): 289 raise TypeError('Can only compare with other OrderedDicts') 290 # FIXME: efficiency? 291 # Generate both item lists for each compare 292 return (self.items() >= other.items())
293
294 - def __repr__(self):
295 """ 296 Used for __repr__ and __str__ 297 298 >>> r1 = repr(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f')))) 299 >>> r1 300 "OrderedDict([('a', 'b'), ('c', 'd'), ('e', 'f')])" 301 >>> r2 = repr(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd')))) 302 >>> r2 303 "OrderedDict([('a', 'b'), ('e', 'f'), ('c', 'd')])" 304 >>> r1 == str(OrderedDict((('a', 'b'), ('c', 'd'), ('e', 'f')))) 305 True 306 >>> r2 == str(OrderedDict((('a', 'b'), ('e', 'f'), ('c', 'd')))) 307 True 308 """ 309 return '%s([%s])' % (self.__class__.__name__, ', '.join( 310 ['(%r, %r)' % (key, self[key]) for key in self._sequence]))
311
312 - def __setitem__(self, key, val):
313 """ 314 Allows slice assignment, so long as the slice is an OrderedDict 315 >>> d = OrderedDict() 316 >>> d['a'] = 'b' 317 >>> d['b'] = 'a' 318 >>> d[3] = 12 319 >>> d 320 OrderedDict([('a', 'b'), ('b', 'a'), (3, 12)]) 321 >>> d[:] = OrderedDict(((1, 2), (2, 3), (3, 4))) 322 >>> d 323 OrderedDict([(1, 2), (2, 3), (3, 4)]) 324 >>> d[::2] = OrderedDict(((7, 8), (9, 10))) 325 >>> d 326 OrderedDict([(7, 8), (2, 3), (9, 10)]) 327 >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4))) 328 >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8))) 329 >>> d 330 OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)]) 331 >>> d = OrderedDict(((0, 1), (1, 2), (2, 3), (3, 4)), strict=True) 332 >>> d[1:3] = OrderedDict(((1, 2), (5, 6), (7, 8))) 333 >>> d 334 OrderedDict([(0, 1), (1, 2), (5, 6), (7, 8), (3, 4)]) 335 336 >>> a = OrderedDict(((0, 1), (1, 2), (2, 3)), strict=True) 337 >>> a[3] = 4 338 >>> a 339 OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 340 >>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 341 >>> a 342 OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 343 >>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]) 344 Traceback (most recent call last): 345 ValueError: slice assignment must be from unique keys 346 >>> a = OrderedDict(((0, 1), (1, 2), (2, 3))) 347 >>> a[3] = 4 348 >>> a 349 OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 350 >>> a[::1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 351 >>> a 352 OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 353 >>> a[:2] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 354 >>> a 355 OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 356 >>> a[::-1] = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 357 >>> a 358 OrderedDict([(3, 4), (2, 3), (1, 2), (0, 1)]) 359 360 >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 361 >>> d[:1] = 3 362 Traceback (most recent call last): 363 TypeError: slice assignment requires an OrderedDict 364 365 >>> d = OrderedDict([(0, 1), (1, 2), (2, 3), (3, 4)]) 366 >>> d[:1] = OrderedDict([(9, 8)]) 367 >>> d 368 OrderedDict([(9, 8), (1, 2), (2, 3), (3, 4)]) 369 """ 370 if isinstance(key, types.SliceType): 371 if not isinstance(val, OrderedDict): 372 # FIXME: allow a list of tuples? 373 raise TypeError('slice assignment requires an OrderedDict') 374 keys = self._sequence[key] 375 # NOTE: Could use ``range(*key.indices(len(self._sequence)))`` 376 indexes = range(len(self._sequence))[key] 377 if key.step is None: 378 # NOTE: new slice may not be the same size as the one being 379 # overwritten ! 380 # NOTE: What is the algorithm for an impossible slice? 381 # e.g. d[5:3] 382 pos = key.start or 0 383 del self[key] 384 newkeys = val.keys() 385 for k in newkeys: 386 if k in self: 387 if self.strict: 388 raise ValueError('slice assignment must be from ' 389 'unique keys') 390 else: 391 # NOTE: This removes duplicate keys *first* 392 # so start position might have changed? 393 del self[k] 394 self._sequence = (self._sequence[:pos] + newkeys + 395 self._sequence[pos:]) 396 dict.update(self, val) 397 else: 398 # extended slice - length of new slice must be the same 399 # as the one being replaced 400 if len(keys) != len(val): 401 raise ValueError('attempt to assign sequence of size %s ' 402 'to extended slice of size %s' % (len(val), len(keys))) 403 # FIXME: efficiency? 404 del self[key] 405 item_list = zip(indexes, val.items()) 406 # smallest indexes first - higher indexes not guaranteed to 407 # exist 408 item_list.sort() 409 for pos, (newkey, newval) in item_list: 410 if self.strict and newkey in self: 411 raise ValueError('slice assignment must be from unique' 412 ' keys') 413 self.insert(pos, newkey, newval) 414 else: 415 if key not in self: 416 self._sequence.append(key) 417 dict.__setitem__(self, key, val)
418
419 - def __getitem__(self, key):
420 """ 421 Allows slicing. Returns an OrderedDict if you slice. 422 >>> b = OrderedDict([(7, 0), (6, 1), (5, 2), (4, 3), (3, 4), (2, 5), (1, 6)]) 423 >>> b[::-1] 424 OrderedDict([(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1), (7, 0)]) 425 >>> b[2:5] 426 OrderedDict([(5, 2), (4, 3), (3, 4)]) 427 >>> type(b[2:4]) 428 <class '__main__.OrderedDict'> 429 """ 430 if isinstance(key, types.SliceType): 431 # FIXME: does this raise the error we want? 432 keys = self._sequence[key] 433 # FIXME: efficiency? 434 return OrderedDict([(entry, self[entry]) for entry in keys]) 435 else: 436 return dict.__getitem__(self, key)
437 438 __str__ = __repr__ 439
440 - def __setattr__(self, name, value):
441 """ 442 Implemented so that accesses to ``sequence`` raise a warning and are 443 diverted to the new ``setkeys`` method. 444 """ 445 if name == 'sequence': 446 warnings.warn('Use of the sequence attribute is deprecated.' 447 ' Use the keys method instead.', DeprecationWarning) 448 # NOTE: doesn't return anything 449 self.setkeys(value) 450 else: 451 # FIXME: do we want to allow arbitrary setting of attributes? 452 # Or do we want to manage it? 453 object.__setattr__(self, name, value)
454
455 - def __getattr__(self, name):
456 """ 457 Implemented so that access to ``sequence`` raises a warning. 458 459 >>> d = OrderedDict() 460 >>> d.sequence 461 [] 462 """ 463 if name == 'sequence': 464 warnings.warn('Use of the sequence attribute is deprecated.' 465 ' Use the keys method instead.', DeprecationWarning) 466 # NOTE: Still (currently) returns a direct reference. Need to 467 # because code that uses sequence will expect to be able to 468 # mutate it in place. 469 return self._sequence 470 else: 471 # raise the appropriate error 472 raise AttributeError("OrderedDict has no '%s' attribute" % name)
473
474 - def __deepcopy__(self, memo):
475 """ 476 To allow deepcopy to work with OrderedDict. 477 478 >>> from copy import deepcopy 479 >>> a = OrderedDict([(1, 1), (2, 2), (3, 3)]) 480 >>> a['test'] = {} 481 >>> b = deepcopy(a) 482 >>> b == a 483 True 484 >>> b is a 485 False 486 >>> a['test'] is b['test'] 487 False 488 """ 489 from copy import deepcopy 490 return self.__class__(deepcopy(self.items(), memo), self.strict)
491 492 493 ### Read-only methods ### 494
495 - def copy(self):
496 """ 497 >>> OrderedDict(((1, 3), (3, 2), (2, 1))).copy() 498 OrderedDict([(1, 3), (3, 2), (2, 1)]) 499 """ 500 return OrderedDict(self)
501
502 - def items(self):
503 """ 504 ``items`` returns a list of tuples representing all the 505 ``(key, value)`` pairs in the dictionary. 506 507 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 508 >>> d.items() 509 [(1, 3), (3, 2), (2, 1)] 510 >>> d.clear() 511 >>> d.items() 512 [] 513 """ 514 return zip(self._sequence, self.values())
515
516 - def keys(self):
517 """ 518 Return a list of keys in the ``OrderedDict``. 519 520 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 521 >>> d.keys() 522 [1, 3, 2] 523 """ 524 return self._sequence[:]
525
526 - def values(self, values=None):
527 """ 528 Return a list of all the values in the OrderedDict. 529 530 Optionally you can pass in a list of values, which will replace the 531 current list. The value list must be the same len as the OrderedDict. 532 533 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 534 >>> d.values() 535 [3, 2, 1] 536 """ 537 return [self[key] for key in self._sequence]
538
539 - def iteritems(self):
540 """ 541 >>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iteritems() 542 >>> ii.next() 543 (1, 3) 544 >>> ii.next() 545 (3, 2) 546 >>> ii.next() 547 (2, 1) 548 >>> ii.next() 549 Traceback (most recent call last): 550 StopIteration 551 """ 552 def make_iter(self=self): 553 keys = self.iterkeys() 554 while True: 555 key = keys.next() 556 yield (key, self[key])
557 return make_iter()
558
559 - def iterkeys(self):
560 """ 561 >>> ii = OrderedDict(((1, 3), (3, 2), (2, 1))).iterkeys() 562 >>> ii.next() 563 1 564 >>> ii.next() 565 3 566 >>> ii.next() 567 2 568 >>> ii.next() 569 Traceback (most recent call last): 570 StopIteration 571 """ 572 return iter(self._sequence)
573 574 __iter__ = iterkeys 575
576 - def itervalues(self):
577 """ 578 >>> iv = OrderedDict(((1, 3), (3, 2), (2, 1))).itervalues() 579 >>> iv.next() 580 3 581 >>> iv.next() 582 2 583 >>> iv.next() 584 1 585 >>> iv.next() 586 Traceback (most recent call last): 587 StopIteration 588 """ 589 def make_iter(self=self): 590 keys = self.iterkeys() 591 while True: 592 yield self[keys.next()]
593 return make_iter() 594 595 ### Read-write methods ### 596
597 - def clear(self):
598 """ 599 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 600 >>> d.clear() 601 >>> d 602 OrderedDict([]) 603 """ 604 dict.clear(self) 605 self._sequence = []
606
607 - def pop(self, key, *args):
608 """ 609 No dict.pop in Python 2.2, gotta reimplement it 610 611 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 612 >>> d.pop(3) 613 2 614 >>> d 615 OrderedDict([(1, 3), (2, 1)]) 616 >>> d.pop(4) 617 Traceback (most recent call last): 618 KeyError: 4 619 >>> d.pop(4, 0) 620 0 621 >>> d.pop(4, 0, 1) 622 Traceback (most recent call last): 623 TypeError: pop expected at most 2 arguments, got 3 624 """ 625 if len(args) > 1: 626 raise TypeError, ('pop expected at most 2 arguments, got %s' % 627 (len(args) + 1)) 628 if key in self: 629 val = self[key] 630 del self[key] 631 else: 632 try: 633 val = args[0] 634 except IndexError: 635 raise KeyError(key) 636 return val
637
638 - def popitem(self, i=-1):
639 """ 640 Delete and return an item specified by index, not a random one as in 641 dict. The index is -1 by default (the last item). 642 643 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 644 >>> d.popitem() 645 (2, 1) 646 >>> d 647 OrderedDict([(1, 3), (3, 2)]) 648 >>> d.popitem(0) 649 (1, 3) 650 >>> OrderedDict().popitem() 651 Traceback (most recent call last): 652 KeyError: 'popitem(): dictionary is empty' 653 >>> d.popitem(2) 654 Traceback (most recent call last): 655 IndexError: popitem(): index 2 not valid 656 """ 657 if not self._sequence: 658 raise KeyError('popitem(): dictionary is empty') 659 try: 660 key = self._sequence[i] 661 except IndexError: 662 raise IndexError('popitem(): index %s not valid' % i) 663 return (key, self.pop(key))
664
665 - def setdefault(self, key, defval = None):
666 """ 667 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 668 >>> d.setdefault(1) 669 3 670 >>> d.setdefault(4) is None 671 True 672 >>> d 673 OrderedDict([(1, 3), (3, 2), (2, 1), (4, None)]) 674 >>> d.setdefault(5, 0) 675 0 676 >>> d 677 OrderedDict([(1, 3), (3, 2), (2, 1), (4, None), (5, 0)]) 678 """ 679 if key in self: 680 return self[key] 681 else: 682 self[key] = defval 683 return defval
684
685 - def update(self, from_od):
686 """ 687 Update from another OrderedDict or sequence of (key, value) pairs 688 689 >>> d = OrderedDict(((1, 0), (0, 1))) 690 >>> d.update(OrderedDict(((1, 3), (3, 2), (2, 1)))) 691 >>> d 692 OrderedDict([(1, 3), (0, 1), (3, 2), (2, 1)]) 693 >>> d.update({4: 4}) 694 Traceback (most recent call last): 695 TypeError: undefined order, cannot get items from dict 696 >>> d.update((4, 4)) 697 Traceback (most recent call last): 698 TypeError: cannot convert dictionary update sequence element "4" to a 2-item sequence 699 """ 700 if isinstance(from_od, OrderedDict): 701 for key, val in from_od.items(): 702 self[key] = val 703 elif isinstance(from_od, dict): 704 # we lose compatibility with other ordered dict types this way 705 raise TypeError('undefined order, cannot get items from dict') 706 else: 707 # FIXME: efficiency? 708 # sequence of 2-item sequences, or error 709 for item in from_od: 710 try: 711 key, val = item 712 except TypeError: 713 raise TypeError('cannot convert dictionary update' 714 ' sequence element "%s" to a 2-item sequence' % item) 715 self[key] = val
716
717 - def rename(self, old_key, new_key):
718 """ 719 Rename the key for a given value, without modifying sequence order. 720 721 For the case where new_key already exists this raise an exception, 722 since if new_key exists, it is ambiguous as to what happens to the 723 associated values, and the position of new_key in the sequence. 724 725 >>> od = OrderedDict() 726 >>> od['a'] = 1 727 >>> od['b'] = 2 728 >>> od.items() 729 [('a', 1), ('b', 2)] 730 >>> od.rename('b', 'c') 731 >>> od.items() 732 [('a', 1), ('c', 2)] 733 >>> od.rename('c', 'a') 734 Traceback (most recent call last): 735 ValueError: New key already exists: 'a' 736 >>> od.rename('d', 'b') 737 Traceback (most recent call last): 738 KeyError: 'd' 739 """ 740 if new_key == old_key: 741 # no-op 742 return 743 if new_key in self: 744 raise ValueError("New key already exists: %r" % new_key) 745 # rename sequence entry 746 value = self[old_key] 747 old_idx = self._sequence.index(old_key) 748 self._sequence[old_idx] = new_key 749 # rename internal dict entry 750 dict.__delitem__(self, old_key) 751 dict.__setitem__(self, new_key, value)
752
753 - def setitems(self, items):
754 """ 755 This method allows you to set the items in the dict. 756 757 It takes a list of tuples - of the same sort returned by the ``items`` 758 method. 759 760 >>> d = OrderedDict() 761 >>> d.setitems(((3, 1), (2, 3), (1, 2))) 762 >>> d 763 OrderedDict([(3, 1), (2, 3), (1, 2)]) 764 """ 765 self.clear() 766 # FIXME: this allows you to pass in an OrderedDict as well :-) 767 self.update(items)
768
769 - def setkeys(self, keys):
770 """ 771 ``setkeys`` all ows you to pass in a new list of keys which will 772 replace the current set. This must contain the same set of keys, but 773 need not be in the same order. 774 775 If you pass in new keys that don't match, a ``KeyError`` will be 776 raised. 777 778 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 779 >>> d.keys() 780 [1, 3, 2] 781 >>> d.setkeys((1, 2, 3)) 782 >>> d 783 OrderedDict([(1, 3), (2, 1), (3, 2)]) 784 >>> d.setkeys(['a', 'b', 'c']) 785 Traceback (most recent call last): 786 KeyError: 'Keylist is not the same as current keylist.' 787 """ 788 # FIXME: Efficiency? (use set for Python 2.4 :-) 789 # NOTE: list(keys) rather than keys[:] because keys[:] returns 790 # a tuple, if keys is a tuple. 791 kcopy = list(keys) 792 kcopy.sort() 793 self._sequence.sort() 794 if kcopy != self._sequence: 795 raise KeyError('Keylist is not the same as current keylist.') 796 # NOTE: This makes the _sequence attribute a new object, instead 797 # of changing it in place. 798 # FIXME: efficiency? 799 self._sequence = list(keys)
800
801 - def setvalues(self, values):
802 """ 803 You can pass in a list of values, which will replace the 804 current list. The value list must be the same len as the OrderedDict. 805 806 (Or a ``ValueError`` is raised.) 807 808 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 809 >>> d.setvalues((1, 2, 3)) 810 >>> d 811 OrderedDict([(1, 1), (3, 2), (2, 3)]) 812 >>> d.setvalues([6]) 813 Traceback (most recent call last): 814 ValueError: Value list is not the same length as the OrderedDict. 815 """ 816 if len(values) != len(self): 817 # FIXME: correct error to raise? 818 raise ValueError('Value list is not the same length as the ' 819 'OrderedDict.') 820 self.update(zip(self, values))
821 822 ### Sequence Methods ### 823
824 - def index(self, key):
825 """ 826 Return the position of the specified key in the OrderedDict. 827 828 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 829 >>> d.index(3) 830 1 831 >>> d.index(4) 832 Traceback (most recent call last): 833 ValueError: list.index(x): x not in list 834 """ 835 return self._sequence.index(key)
836
837 - def insert(self, index, key, value):
838 """ 839 Takes ``index``, ``key``, and ``value`` as arguments. 840 841 Sets ``key`` to ``value``, so that ``key`` is at position ``index`` in 842 the OrderedDict. 843 844 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 845 >>> d.insert(0, 4, 0) 846 >>> d 847 OrderedDict([(4, 0), (1, 3), (3, 2), (2, 1)]) 848 >>> d.insert(0, 2, 1) 849 >>> d 850 OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2)]) 851 >>> d.insert(8, 8, 1) 852 >>> d 853 OrderedDict([(2, 1), (4, 0), (1, 3), (3, 2), (8, 1)]) 854 """ 855 if key in self: 856 # FIXME: efficiency? 857 del self[key] 858 self._sequence.insert(index, key) 859 dict.__setitem__(self, key, value)
860
861 - def reverse(self):
862 """ 863 Reverse the order of the OrderedDict. 864 865 >>> d = OrderedDict(((1, 3), (3, 2), (2, 1))) 866 >>> d.reverse() 867 >>> d 868 OrderedDict([(2, 1), (3, 2), (1, 3)]) 869 """ 870 self._sequence.reverse()
871
872 - def sort(self, *args, **kwargs):
873 """ 874 Sort the key order in the OrderedDict. 875 876 This method takes the same arguments as the ``list.sort`` method on 877 your version of Python. 878 879 >>> d = OrderedDict(((4, 1), (2, 2), (3, 3), (1, 4))) 880 >>> d.sort() 881 >>> d 882 OrderedDict([(1, 4), (2, 2), (3, 3), (4, 1)]) 883 """ 884 self._sequence.sort(*args, **kwargs)
885
886 -class Keys(object):
887 # FIXME: should this object be a subclass of list? 888 """ 889 Custom object for accessing the keys of an OrderedDict. 890 891 Can be called like the normal ``OrderedDict.keys`` method, but also 892 supports indexing and sequence methods. 893 """ 894
895 - def __init__(self, main):
896 self._main = main
897
898 - def __call__(self):
899 """Pretend to be the keys method.""" 900 return self._main._keys()
901
902 - def __getitem__(self, index):
903 """Fetch the key at position i.""" 904 # NOTE: this automatically supports slicing :-) 905 return self._main._sequence[index]
906
907 - def __setitem__(self, index, name):
908 """ 909 You cannot assign to keys, but you can do slice assignment to re-order 910 them. 911 912 You can only do slice assignment if the new set of keys is a reordering 913 of the original set. 914 """ 915 if isinstance(index, types.SliceType): 916 # FIXME: efficiency? 917 # check length is the same 918 indexes = range(len(self._main._sequence))[index] 919 if len(indexes) != len(name): 920 raise ValueError('attempt to assign sequence of size %s ' 921 'to slice of size %s' % (len(name), len(indexes))) 922 # check they are the same keys 923 # FIXME: Use set 924 old_keys = self._main._sequence[index] 925 new_keys = list(name) 926 old_keys.sort() 927 new_keys.sort() 928 if old_keys != new_keys: 929 raise KeyError('Keylist is not the same as current keylist.') 930 orig_vals = [self._main[k] for k in name] 931 del self._main[index] 932 vals = zip(indexes, name, orig_vals) 933 vals.sort() 934 for i, k, v in vals: 935 if self._main.strict and k in self._main: 936 raise ValueError('slice assignment must be from ' 937 'unique keys') 938 self._main.insert(i, k, v) 939 else: 940 raise ValueError('Cannot assign to keys')
941 942 ### following methods pinched from UserList and adapted ###
943 - def __repr__(self): return repr(self._main._sequence)
944 945 # FIXME: do we need to check if we are comparing with another ``Keys`` 946 # object? (like the __cast method of UserList)
947 - def __lt__(self, other): return self._main._sequence < other
948 - def __le__(self, other): return self._main._sequence <= other
949 - def __eq__(self, other): return self._main._sequence == other
950 - def __ne__(self, other): return self._main._sequence != other
951 - def __gt__(self, other): return self._main._sequence > other
952 - def __ge__(self, other): return self._main._sequence >= other
953 # FIXME: do we need __cmp__ as well as rich comparisons?
954 - def __cmp__(self, other): return cmp(self._main._sequence, other)
955
956 - def __contains__(self, item): return item in self._main._sequence
957 - def __len__(self): return len(self._main._sequence)
958 - def __iter__(self): return self._main.iterkeys()
959 - def count(self, item): return self._main._sequence.count(item)
960 - def index(self, item, *args): return self._main._sequence.index(item, *args)
961 - def reverse(self): self._main._sequence.reverse()
962 - def sort(self, *args, **kwds): self._main._sequence.sort(*args, **kwds)
963 - def __mul__(self, n): return self._main._sequence*n
964 __rmul__ = __mul__
965 - def __add__(self, other): return self._main._sequence + other
966 - def __radd__(self, other): return other + self._main._sequence
967 968 ## following methods not implemented for keys ##
969 - def __delitem__(self, i): raise TypeError('Can\'t delete items from keys')
970 - def __iadd__(self, other): raise TypeError('Can\'t add in place to keys')
971 - def __imul__(self, n): raise TypeError('Can\'t multiply keys in place')
972 - def append(self, item): raise TypeError('Can\'t append items to keys')
973 - def insert(self, i, item): raise TypeError('Can\'t insert items into keys')
974 - def pop(self, i=-1): raise TypeError('Can\'t pop items from keys')
975 - def remove(self, item): raise TypeError('Can\'t remove items from keys')
976 - def extend(self, other): raise TypeError('Can\'t extend keys')
977
978 -class Items(object):
979 """ 980 Custom object for accessing the items of an OrderedDict. 981 982 Can be called like the normal ``OrderedDict.items`` method, but also 983 supports indexing and sequence methods. 984 """ 985
986 - def __init__(self, main):
987 self._main = main
988
989 - def __call__(self):
990 """Pretend to be the items method.""" 991 return self._main._items()
992
993 - def __getitem__(self, index):
994 """Fetch the item at position i.""" 995 if isinstance(index, types.SliceType): 996 # fetching a slice returns an OrderedDict 997 return self._main[index].items() 998 key = self._main._sequence[index] 999 return (key, self._main[key])
1000
1001 - def __setitem__(self, index, item):
1002 """Set item at position i to item.""" 1003 if isinstance(index, types.SliceType): 1004 # NOTE: item must be an iterable (list of tuples) 1005 self._main[index] = OrderedDict(item) 1006 else: 1007 # FIXME: Does this raise a sensible error? 1008 orig = self._main.keys[index] 1009 key, value = item 1010 if self._main.strict and key in self and (key != orig): 1011 raise ValueError('slice assignment must be from ' 1012 'unique keys') 1013 # delete the current one 1014 del self._main[self._main._sequence[index]] 1015 self._main.insert(index, key, value)
1016
1017 - def __delitem__(self, i):
1018 """Delete the item at position i.""" 1019 key = self._main._sequence[i] 1020 if isinstance(i, types.SliceType): 1021 for k in key: 1022 # FIXME: efficiency? 1023 del self._main[k] 1024 else: 1025 del self._main[key]
1026 1027 ### following methods pinched from UserList and adapted ###
1028 - def __repr__(self): return repr(self._main.items())
1029 1030 # FIXME: do we need to check if we are comparing with another ``Items`` 1031 # object? (like the __cast method of UserList)
1032 - def __lt__(self, other): return self._main.items() < other
1033 - def __le__(self, other): return self._main.items() <= other
1034 - def __eq__(self, other): return self._main.items() == other
1035 - def __ne__(self, other): return self._main.items() != other
1036 - def __gt__(self, other): return self._main.items() > other
1037 - def __ge__(self, other): return self._main.items() >= other
1038 - def __cmp__(self, other): return cmp(self._main.items(), other)
1039
1040 - def __contains__(self, item): return item in self._main.items()
1041 - def __len__(self): return len(self._main._sequence) # easier :-)
1042 - def __iter__(self): return self._main.iteritems()
1043 - def count(self, item): return self._main.items().count(item)
1044 - def index(self, item, *args): return self._main.items().index(item, *args)
1045 - def reverse(self): self._main.reverse()
1046 - def sort(self, *args, **kwds): self._main.sort(*args, **kwds)
1047 - def __mul__(self, n): return self._main.items()*n
1048 __rmul__ = __mul__
1049 - def __add__(self, other): return self._main.items() + other
1050 - def __radd__(self, other): return other + self._main.items()
1051
1052 - def append(self, item):
1053 """Add an item to the end.""" 1054 # FIXME: this is only append if the key isn't already present 1055 key, value = item 1056 self._main[key] = value
1057
1058 - def insert(self, i, item):
1059 key, value = item 1060 self._main.insert(i, key, value)
1061
1062 - def pop(self, i=-1):
1063 key = self._main._sequence[i] 1064 return (key, self._main.pop(key))
1065
1066 - def remove(self, item):
1067 key, value = item 1068 try: 1069 assert value == self._main[key] 1070 except (KeyError, AssertionError): 1071 raise ValueError('ValueError: list.remove(x): x not in list') 1072 else: 1073 del self._main[key]
1074
1075 - def extend(self, other):
1076 # FIXME: is only a true extend if none of the keys already present 1077 for item in other: 1078 key, value = item 1079 self._main[key] = value
1080
1081 - def __iadd__(self, other):
1082 self.extend(other)
1083 1084 ## following methods not implemented for items ## 1085
1086 - def __imul__(self, n): raise TypeError('Can\'t multiply items in place')
1087
1088 -class Values(object):
1089 """ 1090 Custom object for accessing the values of an OrderedDict. 1091 1092 Can be called like the normal ``OrderedDict.values`` method, but also 1093 supports indexing and sequence methods. 1094 """ 1095
1096 - def __init__(self, main):
1097 self._main = main
1098
1099 - def __call__(self):
1100 """Pretend to be the values method.""" 1101 return self._main._values()
1102
1103 - def __getitem__(self, index):
1104 """Fetch the value at position i.""" 1105 if isinstance(index, types.SliceType): 1106 return [self._main[key] for key in self._main._sequence[index]] 1107 else: 1108 return self._main[self._main._sequence[index]]
1109
1110 - def __setitem__(self, index, value):
1111 """ 1112 Set the value at position i to value. 1113 1114 You can only do slice assignment to values if you supply a sequence of 1115 equal length to the slice you are replacing. 1116 """ 1117 if isinstance(index, types.SliceType): 1118 keys = self._main._sequence[index] 1119 if len(keys) != len(value): 1120 raise ValueError('attempt to assign sequence of size %s ' 1121 'to slice of size %s' % (len(name), len(keys))) 1122 # FIXME: efficiency? Would be better to calculate the indexes 1123 # directly from the slice object 1124 # NOTE: the new keys can collide with existing keys (or even 1125 # contain duplicates) - these will overwrite 1126 for key, val in zip(keys, value): 1127 self._main[key] = val 1128 else: 1129 self._main[self._main._sequence[index]] = value
1130 1131 ### following methods pinched from UserList and adapted ###
1132 - def __repr__(self): return repr(self._main.values())
1133 1134 # FIXME: do we need to check if we are comparing with another ``Values`` 1135 # object? (like the __cast method of UserList)
1136 - def __lt__(self, other): return self._main.values() < other
1137 - def __le__(self, other): return self._main.values() <= other
1138 - def __eq__(self, other): return self._main.values() == other
1139 - def __ne__(self, other): return self._main.values() != other
1140 - def __gt__(self, other): return self._main.values() > other
1141 - def __ge__(self, other): return self._main.values() >= other
1142 - def __cmp__(self, other): return cmp(self._main.values(), other)
1143
1144 - def __contains__(self, item): return item in self._main.values()
1145 - def __len__(self): return len(self._main._sequence) # easier :-)
1146 - def __iter__(self): return self._main.itervalues()
1147 - def count(self, item): return self._main.values().count(item)
1148 - def index(self, item, *args): return self._main.values().index(item, *args)
1149
1150 - def reverse(self):
1151 """Reverse the values""" 1152 vals = self._main.values() 1153 vals.reverse() 1154 # FIXME: efficiency 1155 self[:] = vals
1156
1157 - def sort(self, *args, **kwds):
1158 """Sort the values.""" 1159 vals = self._main.values() 1160 vals.sort(*args, **kwds) 1161 self[:] = vals
1162
1163 - def __mul__(self, n): return self._main.values()*n
1164 __rmul__ = __mul__
1165 - def __add__(self, other): return self._main.values() + other
1166 - def __radd__(self, other): return other + self._main.values()
1167 1168 ## following methods not implemented for values ##
1169 - def __delitem__(self, i): raise TypeError('Can\'t delete items from values')
1170 - def __iadd__(self, other): raise TypeError('Can\'t add in place to values')
1171 - def __imul__(self, n): raise TypeError('Can\'t multiply values in place')
1172 - def append(self, item): raise TypeError('Can\'t append items to values')
1173 - def insert(self, i, item): raise TypeError('Can\'t insert items into values')
1174 - def pop(self, i=-1): raise TypeError('Can\'t pop items from values')
1175 - def remove(self, item): raise TypeError('Can\'t remove items from values')
1176 - def extend(self, other): raise TypeError('Can\'t extend values')
1177
1178 -class SequenceOrderedDict(OrderedDict):
1179 """ 1180 Experimental version of OrderedDict that has a custom object for ``keys``, 1181 ``values``, and ``items``. 1182 1183 These are callable sequence objects that work as methods, or can be 1184 manipulated directly as sequences. 1185 1186 Test for ``keys``, ``items`` and ``values``. 1187 1188 >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) 1189 >>> d 1190 SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) 1191 >>> d.keys 1192 [1, 2, 3] 1193 >>> d.keys() 1194 [1, 2, 3] 1195 >>> d.setkeys((3, 2, 1)) 1196 >>> d 1197 SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) 1198 >>> d.setkeys((1, 2, 3)) 1199 >>> d.keys[0] 1200 1 1201 >>> d.keys[:] 1202 [1, 2, 3] 1203 >>> d.keys[-1] 1204 3 1205 >>> d.keys[-2] 1206 2 1207 >>> d.keys[0:2] = [2, 1] 1208 >>> d 1209 SequenceOrderedDict([(2, 3), (1, 2), (3, 4)]) 1210 >>> d.keys.reverse() 1211 >>> d.keys 1212 [3, 1, 2] 1213 >>> d.keys = [1, 2, 3] 1214 >>> d 1215 SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) 1216 >>> d.keys = [3, 1, 2] 1217 >>> d 1218 SequenceOrderedDict([(3, 4), (1, 2), (2, 3)]) 1219 >>> a = SequenceOrderedDict() 1220 >>> b = SequenceOrderedDict() 1221 >>> a.keys == b.keys 1222 1 1223 >>> a['a'] = 3 1224 >>> a.keys == b.keys 1225 0 1226 >>> b['a'] = 3 1227 >>> a.keys == b.keys 1228 1 1229 >>> b['b'] = 3 1230 >>> a.keys == b.keys 1231 0 1232 >>> a.keys > b.keys 1233 0 1234 >>> a.keys < b.keys 1235 1 1236 >>> 'a' in a.keys 1237 1 1238 >>> len(b.keys) 1239 2 1240 >>> 'c' in d.keys 1241 0 1242 >>> 1 in d.keys 1243 1 1244 >>> [v for v in d.keys] 1245 [3, 1, 2] 1246 >>> d.keys.sort() 1247 >>> d.keys 1248 [1, 2, 3] 1249 >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4)), strict=True) 1250 >>> d.keys[::-1] = [1, 2, 3] 1251 >>> d 1252 SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) 1253 >>> d.keys[:2] 1254 [3, 2] 1255 >>> d.keys[:2] = [1, 3] 1256 Traceback (most recent call last): 1257 KeyError: 'Keylist is not the same as current keylist.' 1258 1259 >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) 1260 >>> d 1261 SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) 1262 >>> d.values 1263 [2, 3, 4] 1264 >>> d.values() 1265 [2, 3, 4] 1266 >>> d.setvalues((4, 3, 2)) 1267 >>> d 1268 SequenceOrderedDict([(1, 4), (2, 3), (3, 2)]) 1269 >>> d.values[::-1] 1270 [2, 3, 4] 1271 >>> d.values[0] 1272 4 1273 >>> d.values[-2] 1274 3 1275 >>> del d.values[0] 1276 Traceback (most recent call last): 1277 TypeError: Can't delete items from values 1278 >>> d.values[::2] = [2, 4] 1279 >>> d 1280 SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) 1281 >>> 7 in d.values 1282 0 1283 >>> len(d.values) 1284 3 1285 >>> [val for val in d.values] 1286 [2, 3, 4] 1287 >>> d.values[-1] = 2 1288 >>> d.values.count(2) 1289 2 1290 >>> d.values.index(2) 1291 0 1292 >>> d.values[-1] = 7 1293 >>> d.values 1294 [2, 3, 7] 1295 >>> d.values.reverse() 1296 >>> d.values 1297 [7, 3, 2] 1298 >>> d.values.sort() 1299 >>> d.values 1300 [2, 3, 7] 1301 >>> d.values.append('anything') 1302 Traceback (most recent call last): 1303 TypeError: Can't append items to values 1304 >>> d.values = (1, 2, 3) 1305 >>> d 1306 SequenceOrderedDict([(1, 1), (2, 2), (3, 3)]) 1307 1308 >>> d = SequenceOrderedDict(((1, 2), (2, 3), (3, 4))) 1309 >>> d 1310 SequenceOrderedDict([(1, 2), (2, 3), (3, 4)]) 1311 >>> d.items() 1312 [(1, 2), (2, 3), (3, 4)] 1313 >>> d.setitems([(3, 4), (2 ,3), (1, 2)]) 1314 >>> d 1315 SequenceOrderedDict([(3, 4), (2, 3), (1, 2)]) 1316 >>> d.items[0] 1317 (3, 4) 1318 >>> d.items[:-1] 1319 [(3, 4), (2, 3)] 1320 >>> d.items[1] = (6, 3) 1321 >>> d.items 1322 [(3, 4), (6, 3), (1, 2)] 1323 >>> d.items[1:2] = [(9, 9)] 1324 >>> d 1325 SequenceOrderedDict([(3, 4), (9, 9), (1, 2)]) 1326 >>> del d.items[1:2] 1327 >>> d 1328 SequenceOrderedDict([(3, 4), (1, 2)]) 1329 >>> (3, 4) in d.items 1330 1 1331 >>> (4, 3) in d.items 1332 0 1333 >>> len(d.items) 1334 2 1335 >>> [v for v in d.items] 1336 [(3, 4), (1, 2)] 1337 >>> d.items.count((3, 4)) 1338 1 1339 >>> d.items.index((1, 2)) 1340 1 1341 >>> d.items.index((2, 1)) 1342 Traceback (most recent call last): 1343 ValueError: list.index(x): x not in list 1344 >>> d.items.reverse() 1345 >>> d.items 1346 [(1, 2), (3, 4)] 1347 >>> d.items.reverse() 1348 >>> d.items.sort() 1349 >>> d.items 1350 [(1, 2), (3, 4)] 1351 >>> d.items.append((5, 6)) 1352 >>> d.items 1353 [(1, 2), (3, 4), (5, 6)] 1354 >>> d.items.insert(0, (0, 0)) 1355 >>> d.items 1356 [(0, 0), (1, 2), (3, 4), (5, 6)] 1357 >>> d.items.insert(-1, (7, 8)) 1358 >>> d.items 1359 [(0, 0), (1, 2), (3, 4), (7, 8), (5, 6)] 1360 >>> d.items.pop() 1361 (5, 6) 1362 >>> d.items 1363 [(0, 0), (1, 2), (3, 4), (7, 8)] 1364 >>> d.items.remove((1, 2)) 1365 >>> d.items 1366 [(0, 0), (3, 4), (7, 8)] 1367 >>> d.items.extend([(1, 2), (5, 6)]) 1368 >>> d.items 1369 [(0, 0), (3, 4), (7, 8), (1, 2), (5, 6)] 1370 """ 1371
1372 - def __init__(self, init_val=(), strict=True):
1373 OrderedDict.__init__(self, init_val, strict=strict) 1374 self._keys = self.keys 1375 self._values = self.values 1376 self._items = self.items 1377 self.keys = Keys(self) 1378 self.values = Values(self) 1379 self.items = Items(self) 1380 self._att_dict = { 1381 'keys': self.setkeys, 1382 'items': self.setitems, 1383 'values': self.setvalues, 1384 }
1385
1386 - def __setattr__(self, name, value):
1387 """Protect keys, items, and values.""" 1388 if not '_att_dict' in self.__dict__: 1389 object.__setattr__(self, name, value) 1390 else: 1391 try: 1392 fun = self._att_dict[name] 1393 except KeyError: 1394 OrderedDict.__setattr__(self, name, value) 1395 else: 1396 fun(value)
1397 1398 1399 1400 # Tile wrapping copied from http://tkinter.unpythonic.net/wiki/TileWrapper. 1401 # Will be able to replace with ttk from Python 2.7, eventually. 1402 1403 # only create these gui classes if Tkinter is available (so param does 1404 # not depend on Tkinter). 1405 try: 1406 import Tkinter 1407 from Tkconstants import * # CB: should get the specific imports and move to section below 1408 Tkinter_imported = True 1409 except ImportError: 1410 Tkinter_imported = False 1411 1412 if Tkinter_imported: 1413 1414 if Tkinter.TkVersion >= 8.5: 1415
1416 - class Style:
1417 - def default(self, style, **kw):
1418 """Sets the default value of the specified option(s) in style""" 1419 pass
1420
1421 - def map_style(self, **kw):
1422 """Sets dynamic values of the specified option(s) in style. See 1423 "STATE MAPS", below.""" 1424 pass
1425
1426 - def layout(self, style, layoutSpec):
1427 """Define the widget layout for style style. See "LAYOUTS" below 1428 for the format of layoutSpec. If layoutSpec is omitted, return the 1429 layout specification for style style. """ 1430 pass
1431
1432 - def element_create(self, name, type, *args):
1433 """Creates a new element in the current theme of type type. The 1434 only built-in element type is image (see image(n)), although 1435 themes may define other element types (see 1436 Ttk_RegisterElementFactory). 1437 """ 1438 pass
1439
1440 - def element_names(self):
1441 """Returns a list of all elements defined in the current theme. """ 1442 pass
1443
1444 - def theme_create(self, name, parent=None, basedon=None):
1445 """Creates a new theme. It is an error if themeName already exists. 1446 If -parent is specified, the new theme will inherit styles, elements, 1447 and layouts from the parent theme basedon. If -settings is present, 1448 script is evaluated in the context of the new theme as per style theme 1449 settings. 1450 """ 1451 pass
1452
1453 - def theme_settings(self, name, script):
1454 """Temporarily sets the current theme to themeName, evaluate script, 1455 then restore the previous theme. Typically script simply defines styles 1456 and elements, though arbitrary Tcl code may appear. 1457 """ 1458 pass
1459
1460 - def theme_names(self):
1461 """Returns a list of the available themes. """ 1462 return self.tk.call("style", "theme", "names")
1463
1464 - def theme_use(self, theme):
1465 """Sets the current theme to themeName, and refreshes all widgets.""" 1466 return self.tk.call("style", "theme", "use", theme)
1467
1468 - class Widget(Tkinter.Widget, Style):
1469 - def __init__(self, master, widgetName=None, cnf={}, kw={}, extra=()):
1470 if not widgetName: 1471 ## why you would ever want to create a Tile Widget is behond me! 1472 widgetName="ttk::widget" 1473 Tkinter.Widget.__init__(self, master, widgetName, cnf, kw)
1474
1475 - def instate(self, spec=None, script=None):
1476 """Test the widget's state. If script is not specified, returns 1 1477 if the widget state matches statespec and 0 otherwise. If script 1478 is specified, equivalent to if {[pathName instate stateSpec]} 1479 script. 1480 """ 1481 return self.tk.call(self._w, "instate", spec, script)
1482
1483 - def state(self, spec=None):
1484 """Modify or inquire widget state. If stateSpec is present, sets 1485 the widget state: for each flag in stateSpec, sets the corresponding 1486 flag or clears it if prefixed by an exclamation point. Returns a new 1487 state spec indicating which flags were changed: ''set changes 1488 [pathName state spec] ; pathName state $changes'' will restore 1489 pathName to the original state. If stateSpec is not specified, 1490 returns a list of the currently-enabled state flags. 1491 """ 1492 return self.tk.call(self._w, "state", spec)
1493
1494 - class Button(Widget, Tkinter.Button):
1495 - def __init__(self, master=None, cnf={}, **kw):
1496 Widget.__init__(self, master, "ttk::button", cnf, kw)
1497 1498 ###add frame support here--KWs
1499 - class Frame(Widget, Tkinter.Frame):
1500 - def __init__(self, master=None, cnf={}, **kw):
1501 Widget.__init__(self, master, "ttk::frame", cnf, kw)
1502
1503 - class Checkbutton(Widget, Tkinter.Checkbutton):
1504 - def __init__(self, master=None, cnf={}, **kw):
1505 Widget.__init__(self, master, "ttk::checkbutton", cnf, kw)
1506
1507 - class Combobox(Widget, Tkinter.Entry):
1508 - def __init__(self, master=None, cnf={}, **kw):
1509 1510 # HACK to work around strange parsing of list 1511 if 'values' in kw: 1512 values = kw['values'] 1513 if isinstance(values,list): 1514 kw['values'] = tuple(values) 1515 1516 Widget.__init__(self, master, "ttk::combobox", cnf, kw)
1517
1518 - def current(self, index=None):
1519 """If index is supplied, sets the combobox value to the element 1520 at position newIndex in the list of -values. Otherwise, returns 1521 the index of the current value in the list of -values or -1 if 1522 the current value does not appear in the list. 1523 """ 1524 return self.tk.call(self._w, "current", index)
1525
1526 - class Entry(Widget, Tkinter.Entry):
1527 - def __init__(self, master=None, cnf={}, **kw):
1528 Widget.__init__(self, master, "ttk::entry", cnf, kw)
1529
1530 - def validate(self):
1531 """Force revalidation, independent of the conditions specified by 1532 the -validate option. Returns 0 if the -validatecommand returns a 1533 false value, or 1 if it returns a true value or is not specified. 1534 """ 1535 return self.tk.call(self._w, "validate")
1536
1537 - class Label(Widget, Tkinter.Label):
1538 - def __init__(self, master=None, cnf={}, **kw):
1539 Widget.__init__(self, master, "ttk::label", cnf, kw)
1540 1541 ###add LabelFrame class here--KW
1542 - class LabelFrame(Widget, Tkinter.Label):
1543 - def __init__(self, master=None, cnf={}, **kw):
1544 Widget.__init__(self, master, "ttk::labelframe", cnf, kw)
1545 1549
1550 - class Notebook(Widget):
1551 - def __init__(self, master=None, cnf={}, **kw):
1552 Widget.__init__(self, master, "ttk::notebook", cnf, kw)
1553
1554 - def add(self, child, cnf=(), **kw):
1555 """Adds a new tab to the notebook. When the tab is selected, the 1556 child window will be displayed. child must be a direct child of 1557 the notebook window. See TAB OPTIONS for the list of available 1558 options. 1559 """ 1560 1561 return self.tk.call((self._w, "add", child) + self._options(cnf, kw))
1562
1563 - def forget(self, index):
1564 """Removes the tab specified by index, unmaps and unmanages the 1565 associated child window. 1566 """ 1567 return self.tk.call(self._w, "forget", index)
1568
1569 - def index(self, index):
1570 """Returns the numeric index of the tab specified by index, or 1571 the total number of tabs if index is the string "end". 1572 """ 1573 return self.tk.call(self._w, "index")
1574
1575 - def select(self, index):
1576 """Selects the specified tab; the associated child pane will 1577 be displayed, and the previously-selected pane (if different) 1578 is unmapped. 1579 """ 1580 return self.tk.call(self._w, "select", index)
1581 1582
1583 - def tab(self, index, **kw):
1584 """Query or modify the options of the specific tab. If no 1585 -option is specified, returns a dictionary of the tab option 1586 values. If one -option is specified, returns the value of tha 1587 t option. Otherwise, sets the -options to the corresponding 1588 values. See TAB OPTIONS for the available options. 1589 """ 1590 return self.tk.call((self._w, "tab", index) + self._options(kw))
1591
1592 - def tabs(self):
1593 """Returns a list of all pane windows managed by the widget.""" 1594 return self.tk.call(self._w, "tabs")
1595
1596 - class Paned(Widget):
1597 """ 1598 WIDGET OPTIONS 1599 Name Database name Database class 1600 -orient orient Orient 1601 Specifies the orientation of the window. If vertical, subpanes 1602 are stacked top-to-bottom; if horizontal, subpanes are stacked 1603 left-to-right. 1604 1605 PANE OPTIONS 1606 The following options may be specified for each pane: 1607 Name Database name Database class 1608 -weight weight Weight 1609 An integer specifying the relative stretchability of the pane. 1610 When the paned window is resized, the extra space is added or 1611 subracted to each pane proportionally to its -weight 1612 """
1613 - def __init__(self, master=None, cnf={}, **kw):
1614 Widget.__init__(self, master, "ttk::panedwindow", cnf, kw)
1615
1616 - def add(self, subwindow, **kw):
1617 """Adds a new pane to the window. subwindow must be a direct child of 1618 the paned window pathname. See PANE OPTIONS for the list of available 1619 options. 1620 """ 1621 return self.tk.call((self._w, "add", subwindow) + self._options(kw))
1622
1623 - def forget(self, pane):
1624 """Removes the specified subpane from the widget. pane is either an 1625 integer index or the name of a managed subwindow. 1626 """ 1627 self.tk.call(self._w, "forget", pane)
1628
1629 - def insert(self, pos, subwindow, **kw):
1630 """Inserts a pane at the specified position. pos is either the string 1631 end, an integer index, or the name of a managed subwindow. If subwindow 1632 is already managed by the paned window, moves it to the specified 1633 position. See PANE OPTIONS for the list of available options. 1634 """ 1635 return self.tk.call((self._w, "insert", pos, subwindow) + self._options(kw))
1636
1637 - def pane(self, pane, **kw):
1638 """Query or modify the options of the specified pane, where pane is 1639 either an integer index or the name of a managed subwindow. If no 1640 -option is specified, returns a dictionary of the pane option values. 1641 If one -option is specified, returns the value of that option. 1642 Otherwise, sets the -options to the corresponding values. 1643 """ 1644 return self.tk.call((self._w, "pane", pane) + self._options(kw))
1645 1646
1647 - class Progressbar(Widget):
1648 - def __init__(self, master=None, cnf={}, **kw):
1649 Widget.__init__(self, master, "ttk::progressbar", cnf, kw)
1650
1651 - def step(self, amount=1.0):
1652 """Increments the -value by amount. amount defaults to 1.0 1653 if omitted. """ 1654 return self.tk.call(self._w, "step", amount)
1655
1656 - def start(self):
1657 self.tk.call("ttk::progressbar::start", self._w)
1658
1659 - def stop(self):
1660 self.tk.call("ttk::progressbar::stop", self._w)
1661 1662 1663
1664 - class Radiobutton(Widget, Tkinter.Radiobutton):
1665 - def __init__(self, master=None, cnf={}, **kw):
1666 Widget.__init__(self, master, "ttk::radiobutton", cnf, kw)
1667
1668 - class Scrollbar(Widget, Tkinter.Scrollbar):
1669 - def __init__(self, master=None, cnf={}, **kw):
1670 Widget.__init__(self, master, "ttk::scrollbar", cnf, kw)
1671
1672 - class Separator(Widget):
1673 - def __init__(self, master=None, cnf={}, **kw):
1674 Widget.__init__(self, master, "ttk::separator", cnf, kw)
1675
1676 - class Treeview(Widget, Tkinter.Listbox):
1677 - def __init__(self, master=None, cnf={}, **kw):
1678 Widget.__init__(self, master, 'ttk::treeview', cnf, kw)
1679
1680 - def children(self, item, newchildren=None):
1681 """If newchildren is not specified, returns the list of 1682 children belonging to item. 1683 1684 If newchildren is specified, replaces item's child list 1685 with newchildren. Items in the old child list not present 1686 in the new child list are detached from the tree. None of 1687 the items in newchildren may be an ancestor of item. 1688 """ 1689 return self.tk.call(self._w, "children", item, newchildren)
1690
1691 - def column(self, column, **kw):
1692 """Query or modify the options for the specified column. 1693 If no options are specified, returns a dictionary of 1694 option/value pairs. If a single option is specified, 1695 returns the value of that option. Otherwise, the options 1696 are updated with the specified values. The following 1697 options may be set on each column: 1698 1699 -id name 1700 The column name. This is a read-only option. For example, 1701 [$pathname column #n -id] returns the data column 1702 associated with data column #n. 1703 -anchor 1704 Specifies how the text in this column should be aligned 1705 with respect to the cell. One of n, ne, e, se, s, sw, w, 1706 nw, or center. 1707 -width w 1708 The width of the column in pixels. Default is something 1709 reasonable, probably 200 or so. 1710 """ 1711 pass
1712
1713 - def delete(self, items):
1714 """Deletes each of the items and all of their descendants. 1715 The root item may not be deleted. See also: detach. 1716 """ 1717 return self.tk.call(self._w, "delete", items)
1718
1719 - def detach(self, items):
1720 """Unlinks all of the specified items from the tree. The 1721 items and all of their descendants are still present and 1722 may be reinserted at another point in the tree but will 1723 not be displayed. The root item may not be detached. See 1724 also: delete. 1725 """ 1726 return self.tk.call(self._w, "detach", items)
1727
1728 - def exists(self, item):
1729 """Returns 1 if the specified item is present in the 1730 tree, 0 otherwise. 1731 """ 1732 return self.tk.call(self._w, "exists", item)
1733
1734 - def focus(self, item=None):
1735 """If item is specified, sets the focus item to item. 1736 Otherwise, returns the current focus item, or {} if there 1737 is none. 1738 """ 1739 return self.tk.call(self._w, "focus", item)
1740
1741 - def heading(self, column, **kw):
1742 """Query or modify the heading options for the specified 1743 column. Valid options are: 1744 1745 -text text 1746 The text to display in the column heading. 1747 -image imageName 1748 Specifies an image to display to the right of the column heading. 1749 -command script 1750 A script to evaluate when the heading label is pressed. 1751 """ 1752 pass
1753
1754 - def identify(self, x, y):
1755 """Returns a description of the widget component under the point given 1756 by x and y. The return value is a list with one of the following forms: 1757 1758 heading #n 1759 The column heading for display column #n. 1760 separator #n 1761 The border to the right of display column #n. 1762 cell itemid #n 1763 The data value for item itemid in display column #n. 1764 item itemid element 1765 The tree label for item itemid; element is one of text, image, or 1766 indicator, or another element name depending on the style. 1767 row itemid 1768 The y position is over the item but x does not identify any element 1769 or displayed data value. 1770 nothing 1771 The coordinates are not over any identifiable object. 1772 1773 See COLUMN IDENTIFIERS for a discussion of display columns and data 1774 columns. 1775 """ 1776 pass
1777
1778 - def index(self, item):
1779 """Returns the integer index of item within its parent's list of 1780 children. 1781 """ 1782 pass
1783
1784 - def insert(self, parent, index, id=None, **kw):
1785 """Creates a new item. parent is the item ID of the parent item, or 1786 the empty string {} to create a new top-level item. index is an 1787 integer, or the value end, specifying where in the list of parent's 1788 children to insert the new item. If index is less than or equal to 1789 zero, the new node is inserted at the beginning; if index is greater 1790 than or equal to the current number of children, it is inserted at the 1791 end. If -id is specified, it is used as the item identifier; id must 1792 not already exist in the tree. Otherwise, a new unique identifier is 1793 generated. 1794 returns the item identifier of the newly created item. See ITEM 1795 OPTIONS for the list of available options. 1796 """ 1797 pass
1798 1799
1800 - def item(item, **kw):
1801 """Query or modify the options for the specified item. If no -option 1802 is specified, returns a dictionary of option/value pairs. If a single 1803 -option is specified, returns the value of that option. Otherwise, the 1804 item's options are updated with the specified values. See ITEM OPTIONS 1805 for the list of available options. 1806 """ 1807 pass
1808
1809 - def move(self, item, parent, index):
1810 """Moves item to position index in parent's list of children. It is 1811 illegal to move an item under one of its descendants. 1812 1813 If index is less than or equal to zero, item is moved to the 1814 beginning; if greater than or equal to the number of children, it's 1815 moved to the end. 1816 """ 1817 pass
1818
1819 - def next(self, item):
1820 """Returns the identifier of item's next sibling, or {} if item is the 1821 last child of its parent. 1822 """ 1823 pass
1824
1825 - def parent(self, item):
1826 """Returns the ID of the parent of item, or {} if item is at the top 1827 level of the hierarchy. 1828 """ 1829 pass
1830
1831 - def prev(self, item):
1832 """Returns the identifier of item's previous sibling, or {} if item is 1833 the first child of its parent. 1834 """ 1835 pass
1836 1837
1838 - def selection(self):
1839 """Returns the list of selected items""" 1840 pass
1841
1842 - def selection_set(self, items):
1843 """items becomes the new selection. """ 1844 pass
1845
1846 - def selection_add(self, items):
1847 """Add items to the selection """ 1848 pass
1849
1850 - def selection_remove(self, items):
1851 """Remove items from the selection """ 1852 pass
1853
1854 - def selection_toggle(self, items):
1855 """Toggle the selection state of each item in items. """ 1856 pass
1857
1858 - def set(self, item, column, value=None):
1859 """If value is specified, sets the value of column column in item item, 1860 otherwise returns the current value. See COLUMN IDENTIFIERS. 1861 """ 1862 pass
1863 1864 else: 1865 1866 print "GUI: tcl/tk version is older than 8.5; using simple back-up widgets." 1867 1868 # In the future, could add more fake tile widgets (or handle more methods of 1869 # existing ones) if required. 1870
1871 - class FakeCombobox(Tkinter.OptionMenu):
1872 - def __init__(self, master=None, textvariable=None,values=None,state=None,**kw):
1873 # missing state=readonly 1874 # missing current() 1875 Tkinter.OptionMenu.__init__(self,master,textvariable,*values)
1876 1877 Combobox = FakeCombobox 1878 1879
1880 - class FakeProgressbar(Tkinter.Frame):
1881 - def __init__(self,master=None,cnf={},**kw):
1882 Tkinter.Frame.__init__(self,master)
1883 - def step(self,amount=1.0):
1884 pass
1885 - def start(self):
1886 pass
1887 - def stop(self):
1888 pass
1889 1890 Progressbar = FakeProgressbar 1891 1892 1893 # CB: tix has Notebook, Combobox, and Meter, but I wouldn't 1894 # want to rely on Tix being present (even though it is 1895 # supposed to be part of Python's standard library). 1896