How to mock sqlalchemy.engine.cursor.LegacyCursorResult? - pytest

I have the following class that makes connection to MSSQL Server instance in my project,
"""MSSql Connection class."""
import logging
import logging.config
import sqlalchemy
class MSSQLConnection:
_connection = None
_engine = None
def __init__(self, host, database, username, password):
connection_string = self.build_connection_string(
host, database, username, password)
self._engine = sqlalchemy.create_engine(
connection_string, fast_executemany=True,
isolation_level="READ COMMITTED")
def connect(self):
self._connection = self._engine.connect()
def get_result_tuple(self, table):
logger = logging.getLogger()
metadata = sqlalchemy.MetaData()
db_table = sqlalchemy.Table(
table, metadata, autoload=True, autoload_with=self._engine)
query = sqlalchemy.select([db_table])
transaction_id = self.get_transaction_id()
result_proxy = self._connection.execute(query)
return transaction_id, result_proxy
def get_transaction_id(self):
"""Get the transaction id."""
connection = self._connection
sql_query = sqlalchemy.text("SELECT CURRENT_TRANSACTION_ID()")
result = connection.execute(sql_query)
row = result.fetchone()
return row[0]
def build_connection_string(self, host, database, username, password):
connection_string = ('mssql+pyodbc://' + username + ':'
+ password + '#' + host + '/' + database
+ '?driver=ODBC+Driver+17+for+SQL+Server')
return connection_string
I would like to mock the method
get_result_tuple
that returns ´transaction_id´ and instance of sqlalchemy.engine.cursor.LegacyCursorResult.
How to mock sqlalchemy.engine.cursor.LegacyCursorResult and return some dummy data on the ResultProxy object?
The caller has the following code,
mssql_connection = MSSQLConnection(
host, database, username, password)
mssql_connection.connect()
result_tuple = mssql_connection.get_result_tuple(table)
transaction_id, result_proxy = result_tuple
logger.info(f'Transaction id = {transaction_id}')
current_date = date.today().strftime("%Y_%m_%d")
while True:
partial_results = result_proxy.fetchmany(rows_fetch_limit)
results_count = len(partial_results)
if (partial_results == [] or results_count == 0):
return
else:
// other logic
Please advise.

Related

MongoDB not connecting to the server

Every time I try to connect to my mongodb atlas via my app, I keep getting this error.
ERROR 'f len([h for h in host if "/" in h]) > 1: TypeError: 'Flask' object is not iterable'
from turtle import turtlesize
from flask import Flask, redirect, render_template, request, url_for
from pymongo import MongoClient
app = Flask(__name__)
#app.config['SECRET KEY'] = ''
app.config['MONGO_URI'] = 'mongodb+srv:// admin:admin#sunbeam.cb2bg.mongodb.net/?retryWrites=true&w=majority'
mongodb_client = MongoClient(app)
db = mongodb_client.db
cluster = db['Studentsdb']
collection = cluster['students']
#app.route('/', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'admin':
error = 'Invalid Credentials. Please try again.'
else:
return redirect(url_for('student_forms'))
return render_template('login.html', error=error)
#app.route("/")
def products():
#return "<p>This is a proejcts page</p>"
return render_template('index.html')
#app.route("/student_forms", methods = ['GET','POST'])
def student_forms():
if request.method == 'POST':
name = request.form['name']
gender = request.form['gender']
class_admit = request.form['class']
dob = request.form['birthdate']
collection.insert_one({'name':name, 'gender':gender, 'class': class_admit, 'dob': dob})
return redirect(url_for('student_forms'))
return render_template('studentform.html', form=student_forms)
if __name__ == '__main__':
app.run(debug=True, port=8000)
You may have a number of issues but the first is your connection string should not have a space:
app.config['MONGO_URI'] = 'mongodb+srv:// admin:admin#sunbeam.cb2bg.mongodb.net/?retryWrites=true&w=majority'
->
app.config['MONGO_URI'] = 'mongodb+srv://admin:admin#sunbeam.cb2bg.mongodb.net/?retryWrites=true&w=majority'

how to store bcrypt hashpw result in db correctly?

I am in the process of creating a login system.
I use python flask and as database the Prostgresql.
I think I just store the hash value wrong.
I have saved it as vachar 255 so far
My code:
from flask import Flask, render_template, redirect, request, url_for, session
from flask_sqlalchemy import SQLAlchemy
import bcrypt
import psycopg2
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:PostGreSQL_13#localhost/test'
sql = SQLAlchemy(app)
#app.route('/')
def home():
return render_template("home.html")
#app.route('/register', methods=["GET","POST"])
def register():
if request.method == "GET":
return render_template("register.html")
else:
name = request.form['name']
email = request.form['email']
password = request.form['password'].encode('utf-8')
hash_password = bcrypt.hashpw(password, bcrypt.gensalt())
t_host = 'localhost'
t_port = "5432"
t_dbname = "test"
t_user = "postgres"
t_pw = "password"
db_conn = psycopg2.connect(host=t_host, port=t_port, dbname=t_dbname, user=t_user, password=t_pw)
db_cursor = db_conn.cursor()
db_cursor.execute("INSERT INTO users (UserName,UserEmail,UserPassword) VALUES (%s,%s,%s)",(name,email,hash_password,))
db_conn.commit()
session['name'] = name
session['email'] = email
return redirect(url_for("home"))
#app.route('/login', methods=["GET","POST"])
def login():
if request.method == "POST":
email = request.form['email']
password = request.form['password'].encode('utf-8')
t_host = 'localhost'
t_port = "5432"
t_dbname = "test"
t_user = "postgres"
t_pw = "password"
db_conn = psycopg2.connect(host=t_host, port=t_port, dbname=t_dbname, user=t_user, password=t_pw)
db_cursor = db_conn.cursor()
db_cursor.execute("SELECT username, useremail, userpassword FROM users WHERE useremail=%s",(email,))
user = db_cursor.fetchone()
db_conn.close()
if len(user) > 0:
name = user[0]
if bcrypt.hashpw(password, user[2].encode('utf-8')) == user[2].encode('utf-8'):
session['name'] = user[0]
session['email'] = user[1]
return render_template("home.html")
else:
return "Versuch es doch Nochmal"
else:
return render_template("login.html")
#app.route('/logout')
def logout():
session.clear()
return render_template("home.html")
if __name__ == '__main__':
app.secret_key = '012#!ApaAjaBoleh)(*^%'
app.run(debug=True)
the procedure I got from the Youtube video. see attachment.
I need a login system and this was recommended to me, it works pretty good.
The last one has to work somehow and if it works I would be very happy.
Can anyone tell me what I'm doing wrong or if my appendix with the database is right or wrong?
I know nothing about this language you're using, but any bcrypt implementation will output a string similar to:
$2a$12$ieXy2Rj/TEGqVRx0JihGFesujNFCdmlQWpUaTNvwQ0XuB3lzOcTWK
Yes, you should store that varchar string in your database.

Flask BCrypt check_password_hash return False after saving via MongoEngine

I run into a weird situation, which is similar to this . This is my model:
class User(db.Document):
email = db.EmailField(required=True, unique=True)
username = db.StringField(max_length=50, required=True, unique=True )
password = db.StringField(required=True)
first_name = db.StringField(max_length=100, required=False)
last_name = db.StringField(max_length=100, required=False)
role = db.IntField(required = True, choices = role_choices, default = 5)
status = db.IntField(required = True, choices = status_choices, default = 1)
last_login = db.DateTimeField(required=False)
#property
def is_authenticated(self):
return True
#property
def is_active(self):
return True
#property
def is_anonymous(self):
return False
def __unicode__(self):
return self.username
def set_password(self, password):
self.password = bcrypt.generate_password_hash(password)
def __init__(self, *args, **kwargs):
username = kwargs.pop('username', None)
password = kwargs.pop('password', None)
email = kwargs.pop('email', None)
super(User, self).__init__(*args, **kwargs)
self.username = username
self.set_password(password)
self.email = email
meta = {
'allow_inheritance': False,
'indexes': ['-username'],
'ordering': ['-username']
}
def check_password(self, password):
return bcrypt.check_password_hash(self.password, password)
When I first create an instance of this User class, everything works as expected:
an = User(username="annguyen", first_name="An", last_name="Nguyen", password="janet78", email="an#gmail.com")
>>> an.password
'$2b$12$Ho9Q0/n4FPERytHKxA3szu8gzRZE4J9FxuZots8FFxJUKP6ULmqpe'
>>> an.save()
<User: annguyen>
>>> len(an.password)
60
>>> an.check_password('janet78')
True
However, when I retrieve this user from the database, the check_password method always return False.
>>> an_new = User.objects.get(username='annguyen')
>>> an_new.password
'$2b$12$j9VfNiySMKN19cYIEjuAseiamREUmGbB2ZFM4faoLJySB6uZfaCj2'
>>> len(an.password)
60
>>> len(an_new.password)
60
>>> an_new.check_password('janet78')
False
It is very clear that the password retrieved from the database is very different from what it was before being saved to the database, and therefore it always returns False. I spent a whole day trying to figure out what's wrong but couldn't come up with any clue. Can someone help point out how I can fix it.
I am developing on Windows 10 with Python 2.7, Flask 0.10.1, MongoDB 3.2, flask-mongoengine==0.7.5, mongoengine==0.10.6
Thanks a lot.

AutoRollback doesn't rollback

After I run the following spec, the table exists. I expected it to never be present as it should only exist within the eventually rolled-back transaction.
import org.specs2.mutable.Specification
import scalikejdbc.{DB, NamedDB}
import scalikejdbc.specs2.mutable.AutoRollback
class MyQuerySpec extends Specification with ArbitraryInput {
sequential
DBs.setup('myDB)
"creating the table" in new AutoRollback {
override def db(): DB = NamedDB('myDB).toDB()
private val tableName = s"test_${UUID.randomUUID().toString.replaceAll("-", "_")}"
private val query = new MyQuery(tableName)
query.createTable
ok
}
}
The line DBs.setup('myDB) is not part of the examples. But if I remove it I get the exception java.lang.IllegalStateException: Connection pool is not yet initialized.(name:'myDB)
The source of MyQuery.create:
SQL(s"DROP TABLE IF EXISTS $tableName").execute().apply()
SQL(s"""
|CREATE TABLE $tableName (
| id bigint PRIMARY KEY
|)""".stripMargin).execute().apply()
Config:
db {
myDB {
driver = "org.postgresql.Driver"
url = "****"
user = "****"
password = "****"
poolInitialSize = 1
poolMaxSize = 300
poolConnectionTimeoutMillis = 120000
poolValidationQuery = "select 1 as one"
poolFactoryName = "commons-dbcp2"
}
}
ScalikeJDBC v2.2.9
The MyQuery#createTable must accept implicit parameter like this:
def createTable(implicit session: DBSession)

Momoko, Jinja2 and Tornado

there is something fundamentally wrong with my code. These are my
tornado handlers with basic authentication and jinja2 as template
engine. The following works without the momoko db parts.
class BaseHandler(tornado.web.RequestHandler):
#property
def db(self):
return self.application.db
def get_current_user(self):
return self.get_secure_cookie("user")
class TemplateHandler(BaseHandler):
"""Request handler for writing HTML templates."""
def render(self, template_name, **kwargs):
"""Renders a Jinja2 template."""
kwargs['options'] = options.as_dict()
template = templates.environment.get_template(template_name)
html = template.render(kwargs)
self.write(html)
class AuthLoginHandler(TemplateHandler):
def get(self):
try:
errormessage = self.get_argument("error")
except:
errormessage = ""
self.render("login.html", errormessage = errormessage)
def check_permission(self, password, username):
if username == "admin" and password == "admin":
return True
return False
def post(self):
username = self.get_argument("username", "")
password = self.get_argument("password", "")
auth = self.check_permission(password, username)
if auth:
self.set_current_user(username)
self.redirect(self.get_argument("next", u"/"))
else:
error_msg = u"?error=" + tornado.escape.url_escape("Login incorrect")
self.redirect(u"/auth/login/" + error_msg)
def set_current_user(self, user):
if user:
self.set_secure_cookie("user", tornado.escape.json_encode(user))
else:
self.clear_cookie("user")
class AuthLogoutHandler(TemplateHandler):
def get(self):
self.clear_cookie("user")
self.redirect(self.get_argument("next", "/"))
class MainHandler(TemplateHandler):
#gen.engine
def get(self):
username = tornado.escape.xhtml_escape(self.current_user)
try:
cursor = yield momoko.Op(self.db.execute, 'SELECT * FROM products;')
except Exception as error:
self.write(str(error))
res = 'Query results: '+''.join(str(cursor.fetchall()))
self.render("index.html", username = username, cip = self.request.remote_ip, res = res)
For the logged in client, this code should execute a basic query and then print the result to the defined location ( {{ res }} ) within the jinja template. When I try to start the server, I get this:
line 22, in render
kwargs['options'] = options.as_dict()
AttributeError: 'module' object has no attribute 'as_dict'
We'll need to see your "import" statements to know what's wrong for certain. I suspect you have:
from tornado import options
But you need:
from tornado.options import options