how to make a python-mysqldb template? - python

I've learn some basics about python-mysqldb ,when I want to define anther function for query,I have to write (connect ,cursor...try ..) repeatedly
so I want to design a template like jdbcTemplate (Java EE, Spring)
my code is:
def DBV():
def templateFN(fn):
logging.basicConfig(level=logging.INFO)
log = logging.getLogger('DB')
conn = MySQLdb.connect(user='root',passwd='247326',db='lucky',charset="utf8",cursorclass=MySQLdb.cursors.DictCursor);
cursor = conn.cursor()
def wrap(data=None):
try:
return fn(cursor=cursor,data=data)
#conn.commit()
except Exception ,e:
conn.rollback()
log.error('%s, transaction rollback',e)
finally:
cursor.close()
conn.close()
return wrap
class DB():
#templateFN
def insertTest(self,cursor,data=None):
data = {
'field':'this is a test',
'name':'this is a name'
}
return cursor.execute('insert into test(field,name) values(%(field)s,%(name)s)',data)
return DB()
db = DBV()
print 'return value',db.insertTest(data="ok")
Traceback (most recent call last):
File "D:\WorkSpaces\Aptana Studio 3 Workspace\VLuck\src\com\test.py", line 164, in
print 'return value',db.insertTest(data="ok")
TypeError: wrap() got multiple values for keyword argument 'data'
but failed,how should I do it right

Here's a solution I came up with, inspired by another answer:
def connect_mysql(func):
# Assign value of 'self' to be default func
func.func_defaults = func.func_defaults[:-1] + (func,)
func._cnx = mysql.connector.connect(**CONFIG)
func._cursor = func._cnx.cursor()
return func
#connect_mysql
def test(data, self=None):
self._cursor.execute("SELECT %(c1)s", data)
print(self._cursor.fetchall())
test({'c1': 1})

Related

Flask current_user is None type

My code that was previously working is now causing my main flask app to not run.
The error is coming from my forms.py file.
class selectClass(FlaskForm):
a = current_user.database
conn = sqlite3.connect("C:\\Users\\Lenovo\\PycharmProjects\\spacedonline\\"+a)
c = conn.cursor()
c.execute("SELECT Class FROM Students ")
data = c.fetchall()
listofclasses = []
for clas in data:
if clas[0] not in listofclasses:
listofclasses.append(clas[0])
finallist = []
for clas in listofclasses:
finallist.append((clas, clas))
nameofclass=SelectField(u"Name of Class", choices=finallist)
submit= SubmitField("Select")
On trying to launch the main.py file I get the message:
Traceback (most recent call last):
File "C:/Users/Lenovo/PycharmProjects/spacedonline/forms.py", line 102, in <module>
class selectClass(FlaskForm):
File "C:/Users/Lenovo/PycharmProjects/spacedonline/forms.py", line 104, in selectClass
a = current_user.database
File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python36-32\lib\site-packages\werkzeug\local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
AttributeError: 'NoneType' object has no attribute 'database'
As I said, it was not returning this error before, I am at a loss.
you are probably not logged in. so current_user is NoneType. Try:
if current_user: # or current_user.is_active:
a = current_user.database
...
else:
return redirect('/login')
I have been logged in and when the problem code is commented out it, my page shows me as logged on.
I have worked around the problem by creating a function which creates the class:
'''
def selectclassform():
class SelectClass(FlaskForm):
a = current_user.database
conn = sqlite3.connect("C:\\Users\\Lenovo\\PycharmProjects\\spacedonline\\"+a)
c = conn.cursor()
c.execute("SELECT Class FROM Students ")
data = c.fetchall()
listofclasses = []
for clas in data:
if clas[0] not in listofclasses:
listofclasses.append(clas[0])
finallist = []
for clas in listofclasses:
finallist.append((clas, clas))
nameofclass=SelectField(u"Name of Class", choices=finallist)
submit= SubmitField("Select")
return (SelectClass)
'''
And then calling the function in the main apps.py file:
'''
#app.route("/select", methods=["GET", "POST"])
def selectclass():
if current_user.is_authenticated:
form = selectclassform()()
print(form)
if form.validate_on_submit():
print("valid")
session ["nameofclass"]=form.nameofclass.data
#return printtable(form.nameofclass.data, current_user.database)
return redirect(url_for("validate"))
else:
print("bye")
return render_template("select.html", form=form)
else:
return redirect(url_for("login"))
'''
I've had the same issue, and this was actually due to the security keys.
I have set different app security keys and it works now.
app.config['SECRET_KEY'] = 'new key 1'
app.config['SECURITY_PASSWORD_SALT'] = 'new key 2'
It is probably due to a security control that fails when creating a new instance.

Mocking a module selectively in Python 3.7

I am trying to write unit test for one of my module using pymysql as follows:
def execute(self, query):
try:
conn = pymysql.connect(host='localhost', port=3306, user='root', passwd='',
db='mysql')
cur = conn.cursor()
cur.execute(query)
except pymysql.Error as e:
raise
except Exception as e:
raise
While writing unit test for the above function, I am mocking pysql as follows #patch(my_package.my_module.pymysql). As a result pymysql.erroris also becoming mocked. So while testing the failure scenario as follows:
#patch('my_package.my_module.pymysql')
def test_execute_with_failure(self, mock_pymysql):
...
self.my_obj.cur.execute.side_effect = pymysql.Error
with self.assertRaises(pymysql.Error) as context:
_ = self.my_obj.execute(query="SELECT FOO FROM BAR")
I am getting the below error:
TypeError: catching classes that do not inherit from BaseException is not allowed
In this regard I have gone through this: Can't catch mocked exception because it doesn't inherit BaseException. But I am not getting how to make this work for pymysql.
EDIT 1: As suggested, I have tried to mock only pymysql.connect as follows:
#patch('my_package.my_module.pymysql.connect')
def test_execute_with_failure(self, mock_pymysql_conn):
cursor = MagicMock()
mock_pymysql_conn.return_value.cursor = cursor
self.my_obj.cur = cursor
self.my_obj.cur.execute.side_effect = pymysql.Error
with self.assertRaises(pymysql.Error) as context:
_ = self.my_obj.execute(query="SELECT FOO FROM BAR")
But, I am getting here, as follows:
E AttributeError: <module 'pymysql' from '/my_project/venv/lib/python3.7/site-packages/pymysql/__init__.py'> does not have the attribute ''
EDIT 2: I have tried with below approach as well:
#patch('my_package.my_module.pymysql')
def test_execute_with_failure(self, mock_pymysql):
conn = Mock()
mock_pymysql.connect.return_value = conn
cursor = MagicMock()
conn.return_value.cursor = cursor
self.my_obj.cur = cursor
mock_pymysql.Error = type('PymysqlError', (Exception,), {})
self.my_obj.cur.execute.side_effect = mock_pymysql.Error
with self.assertRaises(mock_pymysql.Error) as context:
_ = self.my_obj.execute(query="SELECT * FROM TEST")
Still the same error as Edit 1.

Python "cx_Oracle.InterfaceError: not a query" for Oracle Function return type cursor

Please help me to understand what I am doing wrong because with same value if I execute procedure which gives multiple lines of response but in python which is failing and giving exception in cursor call to function.
-----Oracle Function----------
FUNCTION get_details (id IN VARCHAR2, actNo IN VARCHAR2, code IN VARCHAR2)
RETURN SYS_REFCURSOR
----Oracle Function Logic----------
OPEN cur_msg_dtls FOR SELECT NAME,VALUE,CODE FROM TABLE
returns cur_msg_dtls
----Python Code--------
import cx_Oracle
if __name__ == '__main__':
con = cx_Oracle.connect('username/pass#host.com:1521/schema')
cur_var = con.cursor()
actNo = 'actNo';
code ='Code';
Id ='Id';
try:
cur_var.callfunc('SCHEMA.PKG.GET_DETAILS',cx_Oracle.CURSOR, (Id,actNo, actCd))
print ("hello")
print(cur_var)
print(type(cur_var))
for row in cur_var:
print(row)
except cx_Oracle.DatabaseError as e:
print (e)
finally:
cur_var.close()
con.close()
pass
----Error--------------
hello
<cx_Oracle.Cursor on <cx_Oracle.Connection to username/pass#host.com:1521/schema>>
<class 'cx_Oracle.Cursor'>
Traceback (most recent call last):
File "C:\Users\TestDBPRoc.py", line 26, in <module>
for row in cur_var:
cx_Oracle.InterfaceError: not a query

Python class database constructor

I am trying to convert my script into a class, Since I will be using the connect method everytime,
I want to place it in the constructor, and then call it in the other functions.
I am new classes in Python, This is a
from datetime import date
import pymssql
import sys
class PHQuery:
def __init__(self):
self.conn = self.conn()
def get_stock_by_sku(self, sku):
if self.conn["code"] < 0:
return {"code":-1,"error":conn["error"]}
cursor = self.conn.cursor(as_dict=True)
try:
cursor.execute('''
SELECT NUMBER, UNITS, LOW, UNCOST, PRICE1, ONORDER
FROM STOCK
WHERE NUMBER=%s''', sku)
return {"code":1,"data":cursor.fetchone()}
except Exception as e:
return {"code":-2,"error":e}
def conn(self):
try:
conn = pymssql.connect(server='server', user='user', password='pwd', database='db', timeout=0, login_timeout=60, charset='UTF-8', as_dict=False, port='1433')
return {"code":1,"data":conn}
except Exception as e:
return {"code":-1,"error":e}
OUTPUT ERRORS:
File "test.py", line 3, in
print testObject.get_stock_by_sku('BK31')
TypeError: unbound method get_stock_by_sku() must be called with PHQuery instance as first argument (got str instance instead)
THIS IS THE CALL TO THE METHOD
from query import PHQuery
testObject = PHQuery
print testObject.get_stock_by_sku('BK31')
Here is my goal
data = {"stock_id" : "12345"}
qobject = PHQuery()
qobject.get_stock_by_sku(data["stock_id"])
and return the same data my script returns:
The script below is working perfectly fine, I just need to make it a class.
THANK YOU IN ADVANCE.
WORKING CODE:
import time
from datetime import date
import pymssql
import sys
def conn():
try:
conn = pymssql.connect(server='', user='', password='', database='', timeout=0, login_timeout=60, charset='UTF-8', as_dict=False, port='1433')
return {"code":1,"data":conn}
except Exception as e:
return {"code":-1,"error":e}
conn = conn()
def get_stock_by_sku(conn,sku):
""" Returns stock information when passing a sku"""
if conn["code"] < 0:
return {"code":-1,"error":conn["error"]}
cursor = conn["data"].cursor(as_dict=True)
try:
cursor.execute('''
SELECT NUMBER, UNITS, LOW, UNCOST, PRICE1, ONORDER
FROM STOCK
WHERE NUMBER=%s''', sku)
return {"code":1,"data":cursor.fetchone()}
except Exception as e:
return {"code":-2,"error":e}

Phyton3 error >> global name 'self' is not defined

I don't know why I am having this error. Please enlighten me. Here's my code:
filename: sqlfunc.py
from sqlalchemy import create_engine
class SQL:
def __init__(self):
self.connection_string = ''
self.sql = ''
def exec_nonquery(connection_string, sql):
self.connection_string = connection_string
self.sql = sql
self.__connection = self.__mydb(self.connection_string)
self.__transaction = self.__connection.begin()
try:
self.__connection.execute(self.sql).fetchall()
self.__transaction.commit()
except:
self.__transaction.rollback()
raise
_connection.close()
def exec_query(self, connection_string, sql):
self.connection_string = connection_string
self.sql = sql
self.__connection = self.__mydb(self.connection_string)
self.__result = None
self.query_result = []
try:
self.__result = self.__connection.execute(sql)
self.query_result = list(self.__result)
except:
raise
self.__connection.close()
return self.query_result
Now, I tried:
from sqlfunc import SQL
SQL.exec_nonquery('mssql+pyodbc://scott:tiger#mydsn','select * from table1')
and I got this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./sqlfunc.py", line 25, in exec_nonquery
self.connection_string = connection_string
NameError: global name 'self' is not defined
Is there anything I did wrong or missing?
I changed exec_nonquery to
def exec_nonquery(self, connection_string, sql)
But it leads me to this error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: exec_nonquery() missing 1 required positional argument: 'sql'
"Is there anything I did wrong or missing?" - yes, you failed to include self as the first positional argument to your method:
def exec_nonquery(connection_string, sql):
should be
def exec_nonquery(self, connection_string, sql):
# ^ see here
You are also trying to call this instance method on the class. The minimal fix is:
sql = SQL() # create instance
sql.exec_nonquery('mssql+pyodbc://scott:tiger#mydsn',
'select * from table1') # call method
but as Martijn points out you really should refactor the class to make the most of OOP.

Categories

Resources