Skip to content

Commit 1281710

Browse files
committed
workaround missing dictproxy methods Fixes benjaminp#295
1 parent 4309e80 commit 1281710

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

six.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,8 @@ def iterlists(d, **kw):
597597

598598
viewitems = operator.methodcaller("items")
599599
else:
600+
import collections as _collections
601+
600602
def iterkeys(d, **kw):
601603
return d.iterkeys(**kw)
602604

@@ -609,11 +611,27 @@ def iteritems(d, **kw):
609611
def iterlists(d, **kw):
610612
return d.iterlists(**kw)
611613

612-
viewkeys = operator.methodcaller("viewkeys")
613-
614-
viewvalues = operator.methodcaller("viewvalues")
614+
def viewkeys(d):
615+
return (
616+
_collections.KeysView(d)
617+
if isinstance(d, types.DictProxyType)
618+
else d.viewkeys()
619+
)
620+
621+
def viewvalues(d):
622+
return (
623+
_collections.ValuesView(d)
624+
if isinstance(d, types.DictProxyType)
625+
else d.viewvalues()
626+
)
627+
628+
def viewitems(d):
629+
return (
630+
_collections.ItemsView(d)
631+
if isinstance(d, types.DictProxyType)
632+
else d.viewitems()
633+
)
615634

616-
viewitems = operator.methodcaller("viewitems")
617635

618636
_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
619637
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")

test_six.py

+26
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,32 @@ def stock_method_name(viewwhat):
434434
view = meth(d)
435435
assert set(view) == set(getattr(d, name)())
436436

437+
@pytest.mark.skipif("sys.version_info[:2] < (2, 7)",
438+
reason="view methods on dictionaries only available on 2.7+")
439+
def test_dictproxy_views():
440+
class Ham(object):
441+
pass
442+
443+
dictproxy = vars(Ham)
444+
dictcopy = dict(dp)
445+
446+
keysview = six.viewkeys(dictproxy)
447+
valuesview = six.viewvalues(dictproxy)
448+
itemsview = six.viewitems(dictproxy)
449+
450+
# test dictproxy six.view*s work the same as per a regular dict
451+
assert keysview == six.viewvalues(dictcopy)
452+
assert valuesview == six.viewvalues(dictcopy)
453+
assert itemsview == six.viewitems(dictcopy)
454+
455+
# test that dictproxy mutations are also exposed on the relevent
456+
# six.view*s results
457+
eggs = object()
458+
setattr(Ham, "spam", eggs)
459+
assert "spam" in keysview
460+
assert eggs in valuesview
461+
assert ("spam", eggs) in itemsview
462+
437463

438464
def test_advance_iterator():
439465
assert six.next is six.advance_iterator

0 commit comments

Comments
 (0)