AttributeError: 'str' object has no attribute 'client' - python

I have a code where, I am establishing connection with MongoDB. This code is
ConnectMongoDB.py:
import pymongo
from pymongo import MongoClient
from flask import Flask, render_template, request,redirect,url_for
app = Flask(__name__)
# Connection to MongoDB
class ConnectMdb:
#staticmethod
def connect2mongodb():
global client
try:
client = pymongo.MongoClient("mongodb") # modified to avoid showing actual string. Kindly ignore this part.
print("Connected to Avengers MongoClient Successfully!!!")
print (type(client))
print(client)
except:
print("Connection to MongoClient Failed!!!")
#db = client.avengers_hack_db
return("Connection established")
if __name__ == '__main__':
ConnectMdb.connect2mongodb()
I import this script in another program which has some business logic. Here is some part of the code which is relevant to this issue:
ProcessData.py:
import pymongo
from pymongo import MongoClient
import datetime
import sys
from flask import Flask, render_template, request
#import ProcessTaskData
#import werkzeug
import ConnectMongoDB as cDB
app = Flask(__name__)
CMdb = cDB.ConnectMdb.connect2mongodb()
db = CMdb.client.avengers_hack_db
#app.route('/')
def index():
return render_template('index.html')
#app.route('/Avengers',methods = ['POST'])
def Avengers():
ip = request.remote_addr
Project_ID = request.form['pid']
Name = request.form['pname']
Resource_Names = request.form['rsrc']
db.ppm_master_db_collection.insert_many([
{"Org_Id":"",
"Name": Name,
"last_modified": datetime.datetime.utcnow()}
])
return render_template('ptasks.html', user_ip=ip)
#app.route('/ProjectTasks',methods = ['POST'])
def ProjectTask():
ip = request.remote_addr
Task_ID = request.form['tid']
TAlert = request.form['talrt']
TResource_Names = request.form['trsrc']
db.ppm_tasks_data_collection.insert_many([
{"Task_ID": Task_ID,
"Resource_Names": TResource_Names,
"last_modified": datetime.datetime.utcnow()}
])
return render_template('ptasks.html', user_ip=ip)
if __name__ == '__main__':
app.run(debug = True)
If I put the code from ConnectMongoDB.py directly in the ProcessData.py rather than importing, it works good. But from separate file it errors.
Also, client is of type:
<class 'pymongo.mongo_client.MongoClient'>
Ideally it is expected to behave normally (establish connection to db as well) like when the code is in the ProcessData.py. Not sure where am I missing.

Changing
db = CMdb.client.avengers_hack_db
to
db = cDB.client.avengers_hack_db
should make your error go away, you are referencing the wrong thing. The return value of your staticmethod is a string, and it has no client attribute.
A bit better approach would be if your connect2mongodb method would return client:
class ConnectMdb:
#staticmethod
def connect2mongodb():
try:
client = pymongo.MongoClient("mongodb") # modified to avoid showing actual string. Kindly ignore this part.
print("Connected to Avengers MongoClient Successfully!!!")
print (type(client))
print(client)
except:
raise Exception("Connection to MongoClient Failed!!!")
return client
This way db = CMdb.client.avengers_hack_db would work.

Related

Using data from python Web-socket inside flask application

I came across a problem where I want to consume data from a python Websocket named truedata-ws inside my flask application, I had tried different ways but, I am not able to succeed. Please help me out for the same below are my main script file and the file for the connection to the Websocket
Main.py file
import sqlalchemy
from flask import Flask, url_for
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
from flask_mail import Mail
from flask_restful import Api
from flask_sock import Sock
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine
from ryj_bhav.Config import Config
from truedata_ws.websocket.TD import TD
import logging
bcrypt = Bcrypt()
login_manager = LoginManager()
login_manager.login_view = 'users.login'
login_manager.login_message_category = 'info'
db = SQLAlchemy()
mail = Mail()
api = Api()
sock = Sock()
Gold_Onn = 55000
Silver_Onn = 65000
#sock.route('/echo')
def echo():
while True:
username = 'test'
password = 'test'
realtime_port = 8084
url = 'push.truedata.in'
symbols = ["SYMBOL-I", "SYMBOL-II"]
td_obj = TD(username, password, live_port=realtime_port, url=url, log_level=logging.DEBUG,
log_format="%(message)s")
#td_obj.trade_callback
def strategy_callback(symbol_id, tick_data):
print(f'Trade update > {tick_data}')
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
bcrypt.init_app(app)
login_manager.init_app(app)
db.init_app(app)
mail.init_app(app)
sock.init_app(app)
from ryj_bhav.routes import routes
from ryj_bhav.routes import LiveRateAPI
api.add_resource(LiveRateAPI, '/live-bhav')
api.init_app(app)
app.register_blueprint(routes)
return app
true-data-ws.py (websocket file)
from truedata_ws.websocket.TD import TD
import time
import logging
from datetime import date
username = 'test'
password = 'test'
realtime_port = 8084
url = 'push.truedata.in'
symbols = ["SYMBOL-I", "SYMBOL-II"]
print('About To Start')
td_obj = TD(username, password, live_port=realtime_port, url=url, log_level=logging.DEBUG, log_format="%(message)s")
# td_obj = TD(username, password, live_port=realtime_port, url=url, historical_api=False)
print('\n')
print('Starting Real Time Feed....')
req_ids = td_obj.start_live_data(symbols)
live_data_objs = {}
time.sleep(2)
for req_id in req_ids:
print('my req ids', req_id)
print(f'touchlinedata -> {td_obj.touchline_data[req_id]}')
#td_obj.trade_callback
def strategy_callback(symbol_id, tick_data):
print('My Symbol id',tick_data.get('ltp'))
# print(f'Trade update > {tick_data}')
# #td_obj.bidask_callback
# def new_bidask(symbol_id, tick_data):
# print(f"BidAsk update > {tick_data}")
while True:
time.sleep(120)
I had tried this solution and also tried to run it from my main file
run.py
from ryj_bhav import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
I had also tried multithreading but did not got succeed in any of the above tried solution.

fast api depends SQL connection

I'm new in fast api. I'm trying to get user from my table but getting this error:
user = await db.query(User).filter(User.login == data['login']).first()
AttributeError: 'Depends' object has no attribute 'query'
here is my server/database.py
import os
from sqlmodel import SQLModel, Session
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
DATABASE_URL = os.environ.get("DATABASE_URL")
engine = create_async_engine(DATABASE_URL, echo = True, future = True)
async def init_db():
async with engine.begin() as conn:
# await conn.run_sync(SQLModel.metadata.drop_all)
await conn.run_sync(SQLModel.metadata.create_all) # init is ok, db table working
pass
async def get_session() -> AsyncSession:
async_session = sessionmaker(
engine, class_ = AsyncSession,
expire_on_commit = False
)
async with async_session() as session:
yield session
here is server/web_server.py
from fastapi import Depends, FastAPI
from sqlalchemy.future import select
from fastapi_socketio import SocketManager
from fastapi_login import LoginManager
import json
from database import get_session, init_db
from models import User, File
app = FastAPI()
sio = SocketManager(app = app)
#app.on_event("startup")
async def on_startup():
await init_db() # is ok
#app.sio.on('connect')
async def handle_connect(sid, connection_data):
await app.sio.emit('connect', 'User joined') # is ok
#app.sio.on('authorize')
async def authorize(sid, message, db = Depends(get_session)):
data = json.loads(message) # is ok
user = await db.query(User).filter(User.login == data['login']).first() # error in this line
print(user)
if __name__ == '__main__':
import uvicorn
uvicorn.run("web_server:app", host = '0.0.0.0', port = 8000, reload = True, debug = False)
I'm using socketio for my app, socketio.on('authorize') message contains data = {'login' : '...', 'password' : '...'} and I want to use this to find user in my postgresql table to check password and authorize it. So having problems with 'get_session', query, execute and commit not working with it, getting the same error AttributeError: 'Depends' object has no attribute ...

Using Pytest to monkeypatch an initialized redis connection in a flask application

I've been struggling with this for awhile now. I Have a flask app that is executed in my app.py file. In this file I have a bunch of endpoints that call different functions from other files. In another file, extensions.py, I've instantiated a class that contains a redis connection. See the file structure below.
#app.py
from flask import Flask
from extensions import redis_obj
app = Flask(__name__)
#app.route('/flush-cache', methods=['POST'])
def flush_redis():
result = redis_obj.flush_redis_cache()
return result
# extensions.py
from redis_class import CloudRedis
redis_obj = CloudRedis()
# redis_class
import redis
class CloudRedis:
def __init__(self):
self.conn = redis.Redis(connection_pool=redis.ConnectionPool.from_url('REDIS_URL',
ssl_cert_reqs=None))
def flush_redis_cache(self):
try:
self.conn.flushdb()
return 'OK'
except:
return 'redis flush failed'
I've been attempting to use monkeypatching in a test patch flush_redis_cache, so when I run flush_redis() the call to redis_obj.flush_redis_cache() will just return "Ok", since I've already tested the CloudRedis class in other pytests. However, no matter what I've tried I haven't been able to successfully patch this. This is what I have below.
from extensions import redis_obj
from app import app
#pytest.fixture()
def client():
yield app.test_client()
def test_flush_redis_when_redis_flushed(client, monkeypatch):
# setup
def get_mock_flush_redis_cache():
return 'OK'
monkeypatch.setattr(cloud_reids, 'flush_redis_cache', get_mock_flush_redis_cache)
cloud_redis.flush_redis = get_mock_flush_redis_cache
# act
res = client.post('/flush-cache')
result = flush_redis()
Does anyone have any ideas on how this can be done?

connecting mongodb server via seperate class

I am using flask to create simple api. The api simply returns values from mongoDB. Everything works great if i do the connection within same function. I am not doing connection simply at start of file because i am using uwsgi and nginx server on ubuntu. If i do that then there will be a problem of fork.
However, I have to use this connection with other api so thought to make a seperate class for connection and each api will simply call it . I m using this functionality to make codes manageable. However when i try the these codes it always shows internal server error. I tried making this function static too , still the error exists.
Note - I have replaced mongodb address with xxx as i am using mongodbatlas account here
from flask import Flask
from flask import request, jsonify
from flask_pymongo import pymongo
from pymongo import MongoClient
from flask_restful import Resource, Api, reqparse
app = Flask(__name__)
api = Api(app)
#client = MongoClient("xxx")
#db = client.get_database('restdb')
#records = db.stars
class dbConnect():
def connect(self):
client = MongoClient("xxx")
db = client.get_database('restdb')
records = db.stars
return records
class Order(Resource):
def get(self):
#client = MongoClient("xxx")
#db = client.get_database('restdb')
#records = db.stars
#star = records
star = dbConnect.connect
output = []
for s in star.find():
output.append({'name' : s['name'], 'distance' : s['distance']})
return jsonify({'result' : output})
api.add_resource(Order, '/')
if __name__ == "__main__":
app.run(host='0.0.0.0')
ERROR {"message": "Internal Server Error"}
Preliminary investigation suggests that you haven't instantiated your dbConnect class. Also, you haven't called the method connect properly.
class Order(Resource):
def get(self):
db = dbConnect() # This was missing
star = db.connect() # This is how you make method call properly.
output = []
for s in star.find():
output.append({'name' : s['name'], 'distance' : s['distance']})
return jsonify({'result' : output})
Also class dbConnect() should be declared as class dbConnect:.

Flask RESTful API: Issue with db connection pool

I'm trying to create REST API endpoints using flask framework. This is my fully working script:
from flask import Flask, jsonify
from flask_restful import Resource, Api
from flask_restful import reqparse
from sqlalchemy import create_engine
from flask.ext.httpauth import HTTPBasicAuth
from flask.ext.cors import CORS
conn_string = "mssql+pyodbc://x:x#x:1433/x?driver=SQL Server"
auth = HTTPBasicAuth()
#auth.get_password
def get_password(username):
if username == 'x':
return 'x'
return None
app = Flask(__name__)
cors = CORS(app)
api = Api(app)
class Report(Resource):
decorators = [auth.login_required]
def get(self):
parser = reqparse.RequestParser()
parser.add_argument('start', type = str)
parser.add_argument('end', type = str)
args = parser.parse_args()
e = create_engine(conn_string)
conn = e.connect()
stat = """
select x from report
"""
query = conn.execute(stat)
json_dict = []
for i in query.cursor.fetchall():
res = {'x': i[0], 'xx': i[1]}
json_dict.append(res)
conn.close()
e.dispose()
return jsonify(results=json_dict)
api.add_resource(Report, '/report')
if __name__ == '__main__':
app.run(host='0.0.0.0')
The issue is that I get results when I call this API only for a day or so after which I stop getting results unless I restart my script (or sometimes even my VM) after which I get results again. I reckon there is some issue with the database connection pool or something but I'm closing the connection and disposing it as well. I have no idea why the API gives me results only for some time being because of which I have to restart my VM every single day. Any ideas?
Per my experience, the issue was caused by coding create_engine(conn_string) to create db pool inside the Class Report so that always do the create & destory operations of db pool for per restful request. It's not correct way for using SQLAlchemy ORM, and be cause IO resouce clash related to DB connection, see the engine.dispose() function description below at http://docs.sqlalchemy.org/en/rel_1_0/core/connections.html#sqlalchemy.engine.Engine:
To resolve the issue, you just need to move e = create_engine(conn_string) to the below of the code conn_string = "mssql+pyodbc://x:x#x:1433/x?driver=SQL Server" and remove the code e.dispose() both in the Class Report, see below.
conn_string = "mssql+pyodbc://x:x#x:1433/x?driver=SQL Server"
e = create_engine(conn_string) # To here
In the def get(delf) function:
args = parser.parse_args()
# Move: e = create_engine(conn_string)
conn = e.connect()
and
conn.close()
# Remove: e.dispose()
return jsonify(results=json_dict)

Categories

Resources