How to convert python dict to DictRow object

Viewed 584

Hi I am writing unittest using pytest. But I am not able to mock few db functions. We are using psycopg2 for db connections and executions. Response of query returned from psycopg2 is of the type DictRow which can be accessed either by key or by index. Ex:

response = ['prajwal', '23', 'engineer'] #Response of a query "select name, age , job from users"

>>>response[0]
   'prajwal'
    
>>>response['name']
   'prajwal'

I want to know is there any way by which we can covert dict/list to above mentioned type.

1 Answers

Looking at the source for psycopg2, creating a DictRow requires passing in a DictCursor object. However the only thing it uses from DictCursor appears to be an index and description attribute.

# found in lib\site-packages\psycopg2.extras.py
class DictRow(list):
    """A row object that allow by-column-name access to data."""

    __slots__ = ('_index',)

    def __init__(self, cursor):
        self._index = cursor.index
        self[:] = [None] * len(cursor.description)

The index looks like a dict with a mapping a key to an index. e.g.response['name'] = 0 The description looks like your dict that you want to convert.

If you're feeling hacky you could take advantage of duck typing and pretend you're passing in a cursor when you're just satisfying the requirements.

The only caveat is after we instantiate the DictRow, we need to populate it. Our fake cursor hack will take care of the rest.

from psycopg2.extras import DictRow

class DictRowHack:
    def __init__(self, my_dict):
        # we need to set these 2 attributes so that
        # it auto populates our indexes
        self.index = {key: i for i, key in enumerate(my_dict)}
        self.description = my_dict

def dictrow_from_dict(my_dict):
    # this is just a little helper function
    # so you don't always need to go through
    # the steps to recreate a DictRow
    fake_cursor = DictRowHack(my_dict)

    my_dictrow = DictRow(fake_cursor)

    for k, v in my_dict.items():
        my_dictrow[k] = v
    
    return my_dictrow

response = {'name': 'prajwal', 'age': '23', 'job': 'engineer'}

my_dictrow = dictrow_from_dict(response)

print(my_dictrow[1])
print(my_dictrow['name'])
print(type(my_dictrow))
Related