Search code examples
pythonfunctiondictionarynose

nosetest error: ValueError: dictionary update sequence element #0 has length 4; 2 is required


I am very much a noob and this is w/r/t python 2.7 and an exercise I'm working through on Learn Python the Hard Way (link to ex47) - The file below is named ex47_tests.py and the error I get is related to running nosetests to the directory I'm working in.

According to nosetests, the error is from the test_map() function at the line west.add_paths({'east', start}) and it states: ValueError: dictionary update sequence at element #0 has length 4; 2 is required but I cannot understand what the problem is... here's the test file:

from nose.tools import *
from ex47.game import Room


def test_room():
    gold = Room("GoldRoom", 
                """This room has gold in it you can grab. There's a
                door to the north.""")
    assert_equal(gold.name, "GoldRoom")
    assert_equal(gold.paths, {})

def test_room_paths():
    center = Room("Center", "Test room in the center.")
    north = Room("North", "Test room in the north.")
    south = Room("South", "Test room in the south.")

    center.add_paths({'north': north, 'south':south})
    assert_equal(center.go('north'), north)
    assert_equal(center.go('south'), south)

def test_map():
    start = Room("Start", "You can go west and down a hole.")
    west = Room("Trees", "There are trees here, you can go east.")
    down = Room("Dungeon", "It's dark down here, you can go up.")

    start.add_paths({'west': west, 'down': down})
    west.add_paths({'east', start})
    down.add_paths({'up': start})

    assert_equal(start.go('west'), west)
    assert_equal(start.go('west').go('east'), start)
    assert_equal(start.go('down').go('up'), start)

For reference, the game.py file contains the Room class that has the add_paths function (method?):

class Room(object):

    def __init__(self, name, description):
        self.name = name
        self.description = description
        self.paths = {}

    def go(self, direction):
        return self.paths.get(direction, None)

    def add_paths(self, paths):
        self.paths.update(paths)

I've reviewed this several times and I have successfully run the code for west.add_paths({'east', start}) within the game.py file but when I run the nosetestsI keep getting the same error. At the point in the code where the error occurs, my interpretation is that west contains an empty {} which should update without issue, no? Can someone provide some insight as to why this isn't working and where the error comes from?

Thank you so much.


Solution

  • The bug in the code is coming from this call:

    west.add_paths({'east', start})
    

    The correction to be made with this, is that you want to update with a dictionary, not a set:

    west.add_paths({'east': start})
    

    This error is reproducible with the following example when you try to update a dictionary with a set:

    >>> d = {}
    >>> d.update({'east','start'})
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: dictionary update sequence element #0 has length 5; 2 is required
    

    To provide more clarity on the bug, if you go to your interpreter and check the type of this:

    Notice the comma between 'east' and 'start'

    >>> print(type({'east', 'start'}))
    <type 'set'>
    

    Notice the colon between 'east' and 'start'

    >>> print(type({'east': 'start'}))
    <type 'dict'>