Python flattening my tuple structure
Question: I am trying to have a python hierarchical data structure with a map and the
value will be a tuple. In some cases the tuple will be of length 1. Python
intelligently flattens the structure whenever the tuple is of length 1.
Observe the example below which can be run in a python interpreter. In the
"another_scenario" I expected the length to be 1 but it has drilled one level
below and got the underlying steps. This totally screws up my tests because I
rely on that being a tuple with the command, function_list, function list.

Question - Why does this happen? How do I ask python to not flatten it?

    
    
    import os
    
    def run():
        my_scenario = {
                "scenario_name" : 
                (   # Each scenario is a List of (command, function_list, function_list)
                    # function_list = one function OR tuple of functions
                    (
                        "command1",
                        (
                            os.path,
                            os.path.exists
                        ),
                        None
                    ),
                    (
                        "command2",
                        (
                            os.path,
                            os.path.exists
                        ),
                        None
                    )
                )
            } 
        another_scenario = {
                "scenario_name" : 
                (
                    (
                        "command1",
                        (
                            os.path,
                            os.path.exists
                        ),
                        None
                    )
                )
        }
        for name in my_scenario:
            print "Full Scenario is %s" % str(my_scenario[name])
            print "Length should be 2 -> %s" % len(my_scenario[name])
        for name in another_scenario:
            print "Full Scenario is %s" % str(another_scenario[name])
            print "Length should be 1 -> %s" % len(another_scenario[name]) #Prints 3 as it drills one level down
    
    
    if __name__ == "__main__":
        run()    
    


Answer: You need to add a comma:

    
    
    another_scenario = {
            "scenario_name": 
            (
                (
                    "command1",
                    (
                        os.path,
                        os.path.exists
                    ),
                    None
                ),  # <- Note this comma
            )
    }
    

to make that a tuple, otherwise it is just an expression. 1-element tuples can
only be distinguished from expressions by the presence of a comma:

    
    
    >>> (1)
    1
    >>> (1,)
    (1,)
    >>> type((1))
    <type 'int'>
    >>> type((1,))
    <type 'tuple'>
    

In fact, it's the _comma_ that defines tuples, not the parenthesis:

    
    
    >>> 1,
    (1,)
    >>> 1, 2
    (1, 2)
    

The parenthesis are only needed when you need to define an _empty_ tuple:

    
    
    >>> ()
    ()
    

