Dear all,

I cannot currently wrap my head around why I am seeing this:

        2020-09-23 23:30:23 gmConnectionPool.py::<module>() #87): psycopg2 
module version: 2.8.5 (dt dec pq3 ext)
        2020-09-23 23:30:23 gmConnectionPool.py::<module>() #88): PostgreSQL 
via DB-API module "<module 'psycopg2' from 
'/usr/lib/python3/dist-packages/psycopg2/__init__.py'>": API level 2.0, thread 
safety 2, parameter style "pyformat"
        2020-09-23 23:30:23 gmConnectionPool.py::<module>() #89): libpq version 
(compiled in): 120002
        2020-09-23 23:30:23 gmConnectionPool.py::<module>() #90): libpq version 
(loaded now) : 120004
        ...
        2020-09-23 23:30:28 gmConnectionPool.py::__log_on_first_contact() 
#445): heed Prime Directive
        2020-09-23 23:30:28 gmConnectionPool.py::__log_on_first_contact() 
#457): PostgreSQL version (numeric): 11.7
        ...
        2020-09-23 23:31:02 gmMacro.py::_get_variant_diagnoses() #2442): [[260, 
'L: Bewegungsapparat', False, 'B', 'clin.health_issue'], [260, 'K: aHT/HI', 
False, 'B', 'clin.health_issue'], [260, 'D: Verdauung', False, None, 
'clin.health_issue']]
        2020-09-23 23:31:02 gmMacro.py::_get_variant_diagnoses() #2443): <class 
'psycopg2.extras.DictRow'>
        2020-09-23 23:31:02 gmMacro.py::_escape_dict() #2851): 260
        2020-09-23 23:31:02 gmMacro.py::__getitem__() #880): placeholder 
handling error: diagnoses::            \item %(diagnosis)s::
        Traceback (most recent call last):
          File 
"/home/ncq/Projekte/gm/git/gnumed/gnumed/Gnumed/wxpython/gmMacro.py", line 869, 
in __getitem__
            val = handler(data = options)
          File 
"/home/ncq/Projekte/gm/git/gnumed/gnumed/Gnumed/wxpython/gmMacro.py", line 
2445, in _get_variant_diagnoses
            return '\n'.join(template % self._escape_dict(dx, none_string = 
'?', bool_strings = [_('yes'), _('no')]) for dx in selected)
          File 
"/home/ncq/Projekte/gm/git/gnumed/gnumed/Gnumed/wxpython/gmMacro.py", line 
2445, in <genexpr>
            return '\n'.join(template % self._escape_dict(dx, none_string = 
'?', bool_strings = [_('yes'), _('no')]) for dx in selected)
          File 
"/home/ncq/Projekte/gm/git/gnumed/gnumed/Gnumed/wxpython/gmMacro.py", line 
2852, in _escape_dict
            val = the_dict[field]
          File "/usr/lib/python3/dist-packages/psycopg2/extras.py", line 169, 
in __getitem__
            return super(DictRow, self).__getitem__(x)
        IndexError: list index out of range

This line logs a list of DictRow's:

        2020-09-23 23:31:02 gmMacro.py::_get_variant_diagnoses() #2442): [[260, 
'L: Bewegungsapparat', False, 'B', 'clin.health_issue'], [260, 'K: aHT/HI', 
False, 'B', 'clin.health_issue'], [260, 'D: Verdauung', False, None, 
'clin.health_issue']]

as evidenced here:

        2020-09-23 23:31:02 gmMacro.py::_get_variant_diagnoses() #2443): <class 
'psycopg2.extras.DictRow'>

The logging code:

        _log.debug('%s', selected)
        _log.debug('%s', type(selected[0]))

and then iterates over the list of DictRow's as per list
comprehension like so:

        return '\n'.join(template % self._escape_dict(dx, none_string = '?', 
bool_strings = [_('yes'), _('no')]) for dx in selected)

where _escape_dict() does this:

        def _escape_dict(self, the_dict=None, date_format='%Y %b %d  %H:%M', 
none_string='', bool_strings=None):
                data = {}
                for field in the_dict:
                        _log.debug('%s', field)
                        val = the_dict[field]
                        if val is None:
                                ...
                        if isinstance(val, bool):
                                ...
                        if isinstance(val, datetime.datetime):
                                ...
                        if self.__esc_style in ['latex', 'tex']:
                                ...
                        elif self.__esc_style in ['xetex', 'xelatex']:
                                ...
                return data

Iterating over the_dict should work for lists (produces
values) OR dicts (produces keys, under py3). It seems as if
the line

        for field in the_dict:                  # I hoped to iterate over the 
keys = column names

somehow "decides": "currently we are treating the_dict as a
list (after all, it is a DictRow, which _can_ be treated as a
list) which then "turns" the dict-style access in

        val = the_dict[field]

into a list access.

Somehow I have a feeling that due to the type of "field"
-- it being integer (namely, a primary key) -- forces

        the_dict[field]

to attempt a list-style index based access (which fails, due
to there not being 260 columns in the SQL query result :-)

Solutions that come to mind:

        _Must_ I use RealDictCursor() to safely avoid this trap ?

        (or else dict()ify DictRow's as needed)

Any insights to be had ?

Thanks,
Karsten
--
GPG  40BE 5B0E C98E 1713 AFA6  5BC0 3BEA AC80 7D4F C89B


Reply via email to