Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NamedTupleRow broken #99

Open
bkline opened this issue Aug 25, 2019 · 1 comment
Open

NamedTupleRow broken #99

bkline opened this issue Aug 25, 2019 · 1 comment

Comments

@bkline
Copy link

bkline commented Aug 25, 2019

Summary

Setting row_type_callable to NamedTupleRow causes data retrieval to fail in the constructor for the local Row class inside the global NamedTupleRow function.

Repro

Here's my repro case (tweak as necessary to adjust to your environment):

#!/usr/bin/env python

"""Repro case for pypyodbc.NamedTupleRow bug
"""

from argparse import ArgumentParser
from pypyodbc import connect, NamedTupleRow

parser = ArgumentParser()
parser.add_argument("--host", required=True)
parser.add_argument("--port", required=True)
parser.add_argument("--database", required=True)
parser.add_argument("--driver", required=True)
opts = parser.parse_args()
parms = dict(
    Driver=opts.driver,
    Server="{},{}".format(opts.host, opts.port),
    Database=opts.database,
    Trusted_Connection="yes",
)
parms = ";".join(["{}={}".format(*p) for p in parms.items()])
conn = connect(parms)
cursor = conn.cursor(row_type_callable=NamedTupleRow)
cursor.execute("CREATE TABLE #t (i INT)")
cursor.execute("INSERT INTO #t (i) VALUES (42)")
cursor.execute("SELECT * FROM #t")
row = cursor.fetchone()
print(row.i)

Output

And here's what happens:

$ python repro.py --host test-host --port 52300 --database test-db \
>                  --driver "{ODBC Driver 17 for SQL Server}"
Traceback (most recent call last):
  File "repro.py", line 27, in <module>
    row = cursor.fetchone()
  File "D:\Python\lib\site-packages\pypyodbc.py", line 1930, in fetchone
    return self._row_type(value_list)
  File "D:\Python\lib\site-packages\pypyodbc.py", line 1079, in __new__
    return super(Row, cls).__new__(cls, *iterable)
TypeError: __new__() takes 1 positional argument but 2 were given

Environment

Reproducible with Python 3.7.4 as well as 2.7.13 with pypyodbc-1.3.5 on various flavors of Windows Server.

@bkline
Copy link
Author

bkline commented Aug 25, 2019

Unit test using free data source

In case you don't have access to SQL Server (and to nudge the project in the direction of using real unit tests):

#!/usr/bin/env python

"""Tests for pypyodbc package
"""

from unittest import TestCase, main
from pypyodbc import connect, NamedTupleRow

class Tests(TestCase):
    """Base class for unit tests"""
    CONNECTION_STRING = "Driver=SQLite3 ODBC Driver;Database=:memory:"

class CursorTests(Tests):
    """Tests of the cursor object"""

    def test_dictionary_rows(self):
        """Ensure that the cursor can provide rows indexable by column name"""
        conn = connect(self.CONNECTION_STRING)
        cursor = conn.cursor(row_type_callable=None)
        cursor.execute("CREATE TABLE t (i INT)")
        cursor.execute("INSERT INTO t (i) VALUES (42)")
        cursor.execute("SELECT * FROM t")
        row = cursor.fetchone()
        cursor.execute("DROP TABLE t")
        self.assertEqual(row["i"], 42)

    def test_named_tuple_rows(self):
        """Ensure that the cursor can provide rows with column attributes"""
        conn = connect(self.CONNECTION_STRING)
        cursor = conn.cursor(row_type_callable=NamedTupleRow)
        cursor.execute("CREATE TABLE t (i INT)")
        cursor.execute("INSERT INTO t (i) VALUES (42)")
        cursor.execute("SELECT * FROM t")
        row = cursor.fetchone()
        cursor.execute("DROP TABLE t")
        self.assertEqual(row.i, 42)


if __name__ == "__main__":
    main()

Test results

$ python tests/pypyodbc_tests.py -v
test_dictionary_rows (__main__.CursorTests)
Ensure that the cursor can provide rows indexable by column name ... ok
test_named_tuple_rows (__main__.CursorTests)
Ensure that the cursor can provide rows with column attributes ... ERROR

======================================================================
ERROR: test_named_tuple_rows (__main__.CursorTests)
Ensure that the cursor can provide rows with column attributes
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/pypyodbc_tests.py", line 34, in test_named_tuple_rows
    row = cursor.fetchone()
  File "D:\Python\lib\site-packages\pypyodbc.py", line 1930, in fetchone
    return self._row_type(value_list)
  File "D:\Python\lib\site-packages\pypyodbc.py", line 1079, in __new__
    return super(Row, cls).__new__(cls, *iterable)
TypeError: __new__() takes 1 positional argument but 2 were given

----------------------------------------------------------------------
Ran 2 tests in 0.026s

FAILED (errors=1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant