I defined the below slots based class to satisfy my "mutable namedtuple with default None values" requirement:
class Row:
__slots__ = tuple(fields)
def __init__(self):
for attr in self.__slots__:
setattr(self, attr, None)
def __setitem__(self, name, value):
setattr(name, value)
def __getitem__(self, i):
return getattr(self, self.__slots__[i])
But when I use its instance for generating query string using cur.mogrify
I get
SystemError: ../Objects/tupleobject.c:85: bad argument to internal function
Complete code:
import psycopg2 as pg2
def define_row(fields):
class Row:
pass # as mentioned above
return Row
fields = ("age", "gender")
row = define_row(fields)()
row.age = 33
row.gender = "m"
rows = [row]
cur = pg2.connect(dbname="playground", user="postgres").cursor()
placeholders = "({})".format(",".join(["%s"] * len(fields)))
args_str = ",".join(
cur.mogrify(placeholders, r).decode("utf-8") for r in rows
) # Exception on this line
qry = f"INSERT INTO playground({','.join(fields)}) VALUES "
cur.execute(qry + args_str)
mogrify
docs do not explicitly mention what the datatype of parameters
should be.
The Row
class needs to implement a __len__
method:
class Row:
...
def __len__(self):
return len(self.__slots__)
cursor.mogrify
expects its second argument to be a sequence or mapping, and Python sequences are expected to define __len__
.