main.py
import os
import psycopg2
import gunicorn
from flask import Flask
from app.routes.universities_routes import app_universities_routes
from app.routes.degrees_routes import app_degrees_routes
from app.routes.curriculum_ratings_routes import app_curriculum_ratings_routes
from app.routes.departments_route import app_departments_routes
from app.routes.user_route import app_users_routes
from app.routes.history_route import app_history_routes
from app.routes.curriculums_route import app_curriculum_routes
from app.routes.courses_route import app_course_routes
from flask_cors import CORS, cross_origin
app = Flask(__name__)
CORS(app)
app.register_blueprint(app_universities_routes)
app.register_blueprint(app_degrees_routes)
app.register_blueprint(app_curriculum_ratings_routes)
app.register_blueprint(app_departments_routes)
app.register_blueprint(app_users_routes)
app.register_blueprint(app_history_routes)
app.register_blueprint(app_curriculum_routes)
app.register_blueprint(app_course_routes)
#app.route('/')
def hello():
return 'Hello, Class Track!'
...
test_routes.py
import pytest
from flask import current_app as app
#pytest.fixture
def app():
app.testing = True
yield app
#pytest.fixture
def client(app):
return app.test_client()
#pytest.fixture
def runner(app):
return app.test_cli_runner()
def test_hello(client):
response = client.get('/')
assert response.status_code == 200
File Structure
backend
app
routes
models
tests
test_routes.py
main.py
I'm trying to run the most simple test for routes, but for some reason this doesn't work and throws this error:
app = <function app at 0x000001FD18A0EF80>
#pytest.fixture
def client(app):
> return app.test_client()
E AttributeError: 'function' object has no attribute 'test_client'
backend\app\tests\test_routes.py:24: AttributeError
I run this through VSCode and through the terminal with the 'pytest' command
Is there a way to make this work without changing the code in main.py
Related
Writting UniTTest For Flask Application
I have a simple Flask Application below , flask application will work perfectly fine without any issues
import sys , os , os.path , time , datetime , json , logging, warnings
from os import listdir
from os.path import isfile, join
from flask_wtf.csrf import CSRFProtect
from flask import Flask
from flask import render_template
from flask import request
from datetime import datetime
from logging import FileHandler
from logging import Formatter
# --> Required Host and Env
_cloudhost='dev.net'
_cloudenv='dev'
_portNumber=4444
#CRF Compliant / (.)
app = Flask(__name__)
csrf = CSRFProtect()
csrf.init_app(app)
#app.route('/')
#app.route('/index')
def index():
project = "CFTP - TBRP & TBLP "
framework = "Publish Framework"
version = '0.1'
hostname = os.popen("echo $(hostname)").read().split('\n')[0]
return render_template('index.html', title=project , description=f'{project} : {framework} v - {version}' , hostname=hostname , logFile=readlogs(), get_env=_cloudenv)
app.run(host=_cloudhost, port=_portNumber)
UnitTest Function . I am struggling to understand on how i can create unit test cases for flask application. Inside my unittest file which i created , i was wondering if i am doing this right .
1 -> To test the csrf if that i included above and also on how i can test my index page can result as pass
test_flask.py
import unittest , sys , tempfile, os , json , shutil
from unittest import mock
from subprocess import Popen, PIPE
import logging
with mock.patch.dict(os.environ, {'PROJECT_FOLDER':'CitiFTP Reports','RPM_ENVIRONMENT': 'DEV', 'HOST_NAME': 'sd-nzvp-czog.nam.nsroot.net', 'USER': 'citiftptabhyper','TABLEAU_PUBLISH_TYPE':'TABCMD','TABCMD_PATH':'/home/citiftptabhyper/tabcmd','CYBERARK_TYPE':'DYNAMIC','JOB_TYPE':'workbook_TP','JOB_FILE':'publish_workbook_TP','RESTAPI_LOG_TYPE':'TP'}):
sys.path.insert(2, 'C:/Users/mm13854/Desktop/FileCopy_Dec_122/cftp_tableau_filecopy/deploy/src')
sys.path.insert(1, 'C:/Users/mm13854/Desktop/FileCopy_Dec_122/cftp_tableau_filecopy/deploy/app')
import env_conf as conf
import run_flask as flk_app
from run_flask import app
class test_tbrp_case(unittest.TestCase):
def setUp(self):
self.ctx = app.app_context()
self.ctx.push()
self.client = app.test_client()
def tearDown(self):
self.ctx.pop()
def test_home(self): ## Fail
response = self.client.post("/index", data={"title": "CFTP - TBRP & TBLP "})
assert response.status_code == 200
## test flask port used -- PASS
def test_port(self):
self.assertEqual(flk_app._portNumber,4444)
## Test host is returning the same value -- PASS
def test_host(self):
self.assertEqual(flk_app._cloudhost,conf.FLASK_CONFIGURATION.get('ENV_URL'))
def test_csrf(self):
pass
if __name__=='__main__':
unittest.main()
I am trying to use pytest to test a flask app and failing at instantiating the app. I am getting the following error when running pytest tests/. The flask --app main run works fine.
ImportError while importing test module '****/tests/test_eventlist.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/opt/homebrew/Cellar/python#3.10/3.10.6_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py:126: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
tests/test_eventlist.py:2: in <module>
from app import create_app
app/__init__.py:1: in <module>
from flask import Flask
E ModuleNotFoundError: No module named 'flask'
Here is my project structure.
Here is the code for test_eventlist.py file and my main.py
import pytest
from app import create_app
#pytest.fixture()
def app():
app = create_app()
app.config.update({
"TESTING": True,
})
yield app
#pytest.fixture()
def client(app):
return app.test_client()
def test_eventlist_post(client):
response = client.post("/", data={"filename": "sample1.txt",
"from": "2000-01-01T17:25:49Z", "to": "2000-01-10T16:55:01Z"})
assert len(response) == 5
from flask import Flask
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
How can I make #celery.task available on user resources package?
I'm new to python and confused about the "circular imports error" can somebody explain how it works? and how to handle this kind of errors in flask application. This is the part where I always get stuck.
This is my project current folder structure
code
|_resources
| |_user.py
|
|_utils
| |_flask_celery.py
|
|_flask_app.py
--- SOURCE CODE ---
flask_app.py
from flask import Flask
from flask_cors import CORS
from flask_restful import Api
from util.flask_celery import make_celery
from routes.endpoint import urls
from resources.user import Users
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "*"}})
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql:///username:StrongPassword#localhost:3306/db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['CELERY_BROKER_URL'] = 'amqp//admin:StrongPassword#localhost:5672'
app.config['CELERY_RESULT_BACKEND'] = 'db+mysql:///username:StrongPassword#localhost:3306/db'
app.config['PROPAGATE_EXCEPTIONS'] = True
api = Api(app)
celery = make_celery(app)
url = urls()
api.add_resource(Users, url.get('users'))
if __name__ == "__main__":
# sqlalchemy
from db import db
db.__init__(app)
app.run(host='0.0.0.0', debug=True, port=5000)
flask_celery.py
from celery import Celery
def make_celery(celery_app):
celery = Celery(
celery_app.import_name,
backend=celery_app.config['CELERY_RESULT_BACKEND'],
broker=celery_app.config['CELERY_BROKER_URL']
)
celery.conf.update(celery_app.config)
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with celery_app.app_context():
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery
user.py
from flask_restful import Resource, reqparse
from app import celery # <-- this cause the error
from util.zk_connector import zk_connect
from util.zk_error import error
class Users(Resource):
def post(self, ip, comkey):
zk = zk_connect(ip=ip, password=int(comkey))
try:
session = zk.connect()
session.disable_device()
users = session.get_users()
print(users)
session.enable_device()
session.disconnect()
return {'message': 'success'}, 200
except Exception as e:
return error(e)
#celery.task(name='user.reverse')
def reverse(string):
return string[::-1]
Error:
Traceback (most recent call last):
File ".\flask_app.py", line 6, in <module>
from resources.user import User
File "C:\Users\Gelo\Documents\Brand new clean arch pyzk\code\resources\user.py", line 2, in <module>
from flask_app import celery
File "C:\Users\Gelo\Documents\Brand new clean arch pyzk\code\flask_app.py", line 6, in <module>
from resources.user import User
ImportError: cannot import name 'User' from partially initialized module 'resources.user' (most likely due to a circular import) (C:\Users\Gelo\Documents\Brand new clean arch pyzk\code\resources\user.py)
I have a question regarding the flask_track_usage module.
All my blueprints should have the Trackusage function included.
Unfortunately i didn't find a way to solve my problem.
Why isn't it possible to simply use the flask.current_app?
route.py
import datetime
from uuid import uuid4
from flask import Blueprint, session, render_template, url_for, flash, redirect, current_app, request, jsonify
from flask_template.main.utils import my_func
import os
import json
from flask_track_usage import TrackUsage
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter
main = Blueprint('main', __name__)
t = TrackUsage(current_app, [
PrintWriter(),
OutputWriter(transform=lambda s: "OUTPUT: " + str(s))
])
#t.include
#main.before_request
def session_management():
now = datetime.datetime.now()
session_lifetime = current_app.config['SESSION_DURATION']
# Create session, if not already existing
if session.get('session_ID') is None:
# Initiate session, set a random UUID as Session ID
session['session_ID'] = str(uuid4())
session.permanent = True # will expire after 30 minutes of inactivity
session['timeout'] = False
print(f'Initated session with ID:', session.get('session_ID'))
return redirect(url_for('main.index'))
else:
try:
last_active = session.get('last_active')
delta = now - last_active
if delta.seconds > 1740:
print(f'Note: Session lifetime less than one minute. Expires in:',
session_lifetime - delta.seconds, 'sec')
if delta.seconds > session_lifetime:
session['last_active'] = now
session['timeout'] = True
print(f'Your session has expired after 30 minutes, you have been logged out (files are deleted).')
return redirect(url_for('main.logout'))
except:
pass
try:
session['last_active'] = now
except:
pass
#main.route('/')
def index():
return redirect(url_for('main.home'))
#main.route('/home')
def home():
return render_template('home.html', title='home', subheader='Template Main Page')
__init__.py
from flask import Flask
from flask_template.config import Config
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
from flask_template.sample_extension.routes import sample_extension
from flask_template.main.routes import main
from flask_template.errors.handlers import errors
app.register_blueprint(sample_extension)
app.register_blueprint(main)
app.register_blueprint(errors)
return app
Config
import os
import json
from datetime import timedelta
with open(os.path.join(os.getcwd(), 'etc', 'app_config.json')) as config_file:
config = json.load(config_file)
class Config:
SECRET_KEY = config.get('SECRET_KEY')
SESSION_DURATION = 1800 # 30 minutes for delete function
PERMANENT_SESSION_LIFETIME = timedelta(minutes=30) # session lifetime
root_dir = os.path.join(os.path.realpath('.'), 'flask_template')
# Path to template to illustrate download functionality
TEMPLATE_FOLDER = os.path.join(root_dir, 'sample_extension', 'assets', 'template')
TRACK_USAGE_USE_FREEGEOIP = False
TRACK_USAGE_INCLUDE_OR_EXCLUDE_VIEWS = 'include'
run.py
from flask_template import create_app
from flask_track_usage import TrackUsage
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter
app = create_app()
if __name__ == '__main__':
app.run(ssl_context=('******'),
host='0.0.0.0',
port=5000,
debug=True)
error
RuntimeError: Working outside of application context.
There are several global Flask variables such as current_app and g that can be accessed only while the application is running (more about them in the Flask Application Context documentation entry). Using them outside the application context raises RuntimeError.
You can instantiate TrackUsage without parameters in your routes.py module:
track_usage = TrackUsage()
#track_usage.include
#main.before_request
def session_management():
...
And then you can import it in your __init__.py module and apply to your application instance:
from flask import Flask
from flask_template.config import Config
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter
def create_app(config_class=Config):
app = Flask(__name__)
app.config.from_object(Config)
from flask_template.sample_extension.routes import sample_extension, track_usage
from flask_template.main.routes import main
from flask_template.errors.handlers import errors
track_usage.init_app(app, [
PrintWriter(),
OutputWriter(transform=lambda s: "OUTPUT: " + str(s)),
])
app.register_blueprint(sample_extension)
app.register_blueprint(main)
app.register_blueprint(errors)
return app
I have not found this solution in the Flask-Track-Usage documentation but it is a common interface for Flask extentions. It allows to instantiate an extension in one module and connect it to Flask application in main module.
I struggle with the implementation of the Flask-MQTT lib to my app. SQLAlchemy etc works fine, but
flask-mqtt throws the error AttributeError: module 'app.mqtt' has no attribute 'init_app'.
In the offical documentatio of Flask-MQTT they build up the create_app() Method the same way
( https://flask-mqtt.readthedocs.io/en/latest/usage.html )
Would be greate if someone can help me! Thank you very much
__init__.py
from flask import Flask
from flask_restful import Api
from flask_mqtt import Mqtt
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_jwt_extended import JWTManager
mqtt = Mqtt()
api = Api()
db = SQLAlchemy()
ma = Marshmallow()
jwt = JWTManager()
def create_app(config):
app = Flask(__name__)
app.config.from_object(config.DevelopmentConfig)
mqtt.init_app(app)
db.init_app(app)
api.init_app(app)
ma.init_app(app)
jwt.init_app(app)
return app
from app.mqtt import mqttclient
run.py
from app import create_app
import config
from flask_migrate import Migrate
app = create_app(config)
migrate = Migrate(app, db)
app.config['MQTT_BROKER_URL'] = 'hivemq'
app.config['MQTT_BROKER_PORT'] = 1883
app.config['MQTT_USERNAME'] = ''
app.config['MQTT_PASSWORD'] = ''
app.config['MQTT_KEEPALIVE'] = 5
app.config['MQTT_TLS_ENABLED'] = False
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5003, threaded=True)
ERROR:
mqttservice | Traceback (most recent call last):
mqttservice | File "run.py", line 5, in <module>
mqttservice | app = create_app(config)
mqttservice | File "/code/app/__init__.py", line 18, in create_app
mqttservice | mqtt.init_app(app)
mqttservice | AttributeError: module 'app.mqtt' has no attribute 'init_app'
In that code fragment, mqtt has two meanings. The first is the variable assigned in
mqtt = Mqtt()
The second is a namespace (module)
from app.mqtt import mqttclient
The tell is in the error
AttributeError: module 'app.mqtt' has no attribute 'init_app'
which is happening because the import is overwriting the initial value, so by the time of that .init_app(), mqtt isn't what you expected.
You're going to have to change one of those names.