Python MySQLdb execute return int - python

I'm using python 3.5.2 for my project. I installed MySQLdb via pip for Mysql connection.
Code:
import MySQLdb
class DB:
def __init__(self):
self.con = MySQLdb.connect(host="127.0.0.1", user="*", passwd="*", db="*")
self.cur = self.con.cursor()
def query(self, q):
r = self.cur.execute(q)
return r
def test():
db = DB()
result = db.query('SELECT id, name FROM test')
return print(result)
def test1():
db = DB()
result = db.query('SELECT id, name FROM test').fetchall()
for res in result:
id, name = res
print(id, name)
test()
test1()
#test output >>> '3'
#test1 output >>> AttributeError: 'int' object has no attribute 'fetchall'
Test table:
id | name
1 | 'test'
2 | 'test2'
3 | 'test3'

Please read this link:http://mysql-python.sourceforge.net/MySQLdb.html
At this point your query has been executed and you need to get the
results. You have two options:
r=db.store_result()
...or... r=db.use_result() Both methods return a result object. What's the difference? store_result() returns the entire result set to
the client immediately. If your result set is really large, this could
be a problem. One way around this is to add a LIMIT clause to your
query, to limit the number of rows returned. The other is to use
use_result(), which keeps the result set in the server and sends it
row-by-row when you fetch. This does, however, tie up server
resources, and it ties up the connection: You cannot do any more
queries until you have fetched all the rows. Generally I recommend
using store_result() unless your result set is really huge and you
can't use LIMIT for some reason.
def test1():
db = DB()
db.query('SELECT id, name FROM test')
result = db.cur.fetchall()
for res in result:
id, name = res
print(id, name)

cursor.execute() will return the number of rows modified or retrieved, just like in PHP. Have you tried to return the fetchall() like so?
def query(self, q):
r = self.cur.execute(q).fetchall()
return r
See here for more documentation: https://ianhowson.com/blog/a-quick-guide-to-using-mysql-in-python/

Related

AttributeError: 'str' object has no attribute 'cursor'

This Python class is supposed to query an SQLite database:
import sqlite3
class Database:
def __init__(self):
self.connection = sqlite3.connect('devel.db')
self.cursor = self.connection.cursor()
self.connection.commit()
def query(self, query, params=()):
if params == ():
self.cursor.execute(query)
else:
self.cursor.execute(query, params)
self.connection.commit()
return True
def select(self, query, params=()):
if params == ():
self.cursor.execute(query)
else:
self.cursor.execute(query, params)
return self.cursor.fetchall()
id = 1
Database.select("SELECT * FROM users WHERE id = ?", (id,))
It gives :
AttributeError: 'str' object has no attribute 'cursor'
I also tried self.connection.cursor() instead of self.cursor.
To call the query method, you need to first create an instance of the Database class.
Basically, by calling the query method without an object, you are passing the query string as the self parameter, so it tries to access the cursor() method in a string and not the class itself.
So instead of executing this code:
Database.select("SELECT * FROM users WHERE id = ?", (id,))
You need to do something like this:
db = Database()
db.select("SELECT * FROM users WHERE id = ?", (id,))

How do I mock an internally used python function with pytest_mock? [duplicate]

I am trying to write a test case test_is_user_present() which calls another function execute_redshift_sql() from redshift_util.py script
I set the expected return value from the function execute_redshift_sql() to 1 . But I never get this value returned from result after the function is called ! I also printed some values for debugging purpose
You can take a look at test case below
from mock import patch, Mock, MagicMock
from cia_admin_operations.redshift_util import execute_redshift_sql
#patch('cia_admin_operations.redshift_util.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
print(mock_execute_redshift_sql())
result = execute_redshift_sql(mock_out, user_check_sql)
print(result)
print(result())
> assert result() == 1
E AssertionError: assert <Mock name='m...749067684720'> == 1
E -<Mock name='mock.query().getresult()()' id='139749067684720'>
E +1
test/test_cia_admin_operations.py:51: AssertionError
----------------------------- Captured stdout call -----------------------------
1
<Mock name='mock.query().getresult()' id='139749067684776'>
<Mock name='mock.query().getresult()()' id='139749067684720'>
redshift_util.py
def execute_redshift_sql(connection, sqlQuery):
"""Executes redshift query"""
logger.info("Executing following SQL query :\n %s" % sqlQuery)
try:
result = connection.query(sqlQuery)
logger.info("Redshift query is successfully executed.")
except Exception as e:
logger.error("Query not executed : %s" % e)
return None
# return only if the result has some data
if result:
logger.info("Query result :\n %s" % result)
return result.getresult()
else:
return 0
You have to patch the function as it is imported. One possibility to fix this is to use:
from mock import patch, Mock
import cia_admin_operations.redshift_util
#patch('cia_admin_operations.redshift_util.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
result = cia_admin_operations.redshift_util.execute_redshift_sql(mock_out, user_check_sql)
print(result)
In your case, you had mocked the function from the package, but used a locally imported module. You always have to check where to patch.
Above, I adapted the import, you can also adapt the patching:
from mock import patch, Mock
from cia_admin_operations.redshift_util import execute_redshift_sql
#patch('redshift_test.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
result = execute_redshift_sql(mock_out, user_check_sql)
print(result)
(you have to substitute redshift_test for the name of your test module in the patch decorator)

#patch mock to mysqldb connection is not working

I am writing Unit test for Python app that connects to Mysql using MySQLdb .
There is a function that connects to Mysql db and returns the connection object.
def connect_to_database():
conn = MySQLdb.connect(host=db_pb2['mysql_host'],
user=db_pb2['mysql_user'],
passwd=db_pb2['mysql_password'],
db=db_pb2['mysql_db'])
return conn
There is one more function that executes the query using the above connection
def execute_query():
cur = connect_to_database().cursor()
a = cur.execute("query")
if a > 0:
result = cur.fetchall()
return result
I have written #patch to mock the return value from the cur.fetchall() and cur.execute() methods
#patch('application.module1.data_adapters.connect_to_database')
def test_daily_test_failures(self, db_connection):
db_connection.cursor().execute.return_value = 1
db_connection.cursor().fetchall. \
return_value = ((1,5,6),)
self.assertEqual((execute_query(),
((1,5,6),))
I get the following error:
if a > 0:
TypeError: '<=' not supported between instances of 'MagicMock' and 'int'
Seems like the return value in patch function is not working as expected
Your patching requires a bit more effort.
#patch('application.module1.data_adapters.connect_to_database')
def test_daily_test_failures(self, connect_to_database):
db_connection = MagicMock()
connect_to_database.return_value = db_connection # 1.
mock_cursor = MagicMock()
db_connection.cursor.return_value = mock_cursor # 2.
mock_cursor.fetchall.return_value = ((1,5,6),)
self.assertEqual((execute_query(),
((1,5,6),))
You're patching the symbol connect_to_database - that does not mock the call to the function. You need to specify that "when that symbol is called, do this"
When mocking function calls, you can't do it like this: db_connection.cursor(). - you need to make db_connection.cursor return a mock, & then specify the .return_value for that mock object

python unit test patch mock method not returning the return values

I am trying to write a test case test_is_user_present() which calls another function execute_redshift_sql() from redshift_util.py script
I set the expected return value from the function execute_redshift_sql() to 1 . But I never get this value returned from result after the function is called ! I also printed some values for debugging purpose
You can take a look at test case below
from mock import patch, Mock, MagicMock
from cia_admin_operations.redshift_util import execute_redshift_sql
#patch('cia_admin_operations.redshift_util.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
print(mock_execute_redshift_sql())
result = execute_redshift_sql(mock_out, user_check_sql)
print(result)
print(result())
> assert result() == 1
E AssertionError: assert <Mock name='m...749067684720'> == 1
E -<Mock name='mock.query().getresult()()' id='139749067684720'>
E +1
test/test_cia_admin_operations.py:51: AssertionError
----------------------------- Captured stdout call -----------------------------
1
<Mock name='mock.query().getresult()' id='139749067684776'>
<Mock name='mock.query().getresult()()' id='139749067684720'>
redshift_util.py
def execute_redshift_sql(connection, sqlQuery):
"""Executes redshift query"""
logger.info("Executing following SQL query :\n %s" % sqlQuery)
try:
result = connection.query(sqlQuery)
logger.info("Redshift query is successfully executed.")
except Exception as e:
logger.error("Query not executed : %s" % e)
return None
# return only if the result has some data
if result:
logger.info("Query result :\n %s" % result)
return result.getresult()
else:
return 0
You have to patch the function as it is imported. One possibility to fix this is to use:
from mock import patch, Mock
import cia_admin_operations.redshift_util
#patch('cia_admin_operations.redshift_util.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
result = cia_admin_operations.redshift_util.execute_redshift_sql(mock_out, user_check_sql)
print(result)
In your case, you had mocked the function from the package, but used a locally imported module. You always have to check where to patch.
Above, I adapted the import, you can also adapt the patching:
from mock import patch, Mock
from cia_admin_operations.redshift_util import execute_redshift_sql
#patch('redshift_test.execute_redshift_sql')
def test_is_user_present(mock_execute_redshift_sql):
ldap_user = "dummy_user"
mock_out = Mock()
user_check_sql = "SELECT COUNT(1) FROM pg_user WHERE usename = '{}';".format(ldap_user)
mock_execute_redshift_sql.return_value = 1
result = execute_redshift_sql(mock_out, user_check_sql)
print(result)
(you have to substitute redshift_test for the name of your test module in the patch decorator)

programming error with pyodbc

I am attempting to query a SQL Server 2012 database using the following code:
import pyodbc
class sqlserverConnector:
def __init__(self, connectionString):
"""
this is a typical connection string using windows authentication and the DSN manager:
'DSN=python;Trusted_Connection=yes'
"""
self._conn = pyodbc.connect(connectionString)
self._curs = self._conn.cursor()
self.fetchall = self._curs.fetchall
self.description = self._curs.description
self.columns = dict()
def __del__(self):
self._conn.close()
def __iter__(self):
return self._curs.__iter__()
# executes SQL statements
def execute(self, statement, **params):
if params is None:
self._curs.execute(statement)
else:
self._curs.execute(statement,params)
# creates a dictionary of column names and positions
if self._curs.description != None:
self.columns = dict((field[0], pos) for pos, field in enumerate(self._curs.description))
else:
None
And:
from sqlutil import *
sqlcnxn = sqlserverConnector('DSN=python;Trusted_Connection=yes')
rows = sqlcnxn.execute("select * from demographics", params=None)
for row in rows:
print row
break
The goal is to print out a single row (the table has 80k+ rows). However I always get this error message:
pyodbc.ProgrammingError: ('The SQL contains 0 parameter markers, but 1 parameters were supplied', 'HY000')
I have googled around and it seems like this pops up for different people for different reasons and none of the solutions I have found fit my error. I think what is happening is that the execute method is defaulting to the first else statement instead of the first if statement.
When you use the **params notation, then params is always a dictionary.
Calling that function with params=None means you now have a dictionary with:
>>> def func(**params):
... print params
...
>>> func()
{}
>>> func(params=None)
{'params': None}
>>> func(foo='bar')
{'foo': 'bar'}
The syntax is meant to accept arbitrary keyword parameters, illustrated by the foo keyword argument above.
Either remove the ** or test for an empty dictionary, and don't set params=None when calling .execute():
def execute(self, statement, **params):
if not params:
self._curs.execute(statement)
else:
self._curs.execute(statement, params)
# ...
and:
rows = sqlcnxn.execute("select * from demographics")
Note that your execute() function has no return statement, which means that rows will be set to None (the default return value for functions). Add return self if you meant to return the connection object so that it can be iterated over.

Categories