From 5ffc82ebeeb434ecffc9f015b5ea8cbeee0bf2e2 Mon Sep 17 00:00:00 2001 From: Gbayi Date: Fri, 27 Feb 2026 13:30:28 -0500 Subject: [PATCH 1/3] Replaced cx_Oracle with oracledb and upgraded library versions to work with Python 3.12 - 3.14 --- app/__init__.py | 5 ++ app/logic/banner.py | 4 +- database/demo_data.py | 41 ++++++----- requirements.txt | 155 +++++++++++++++++++++++------------------- setup.sh | 2 +- 5 files changed, 116 insertions(+), 91 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 206a5fc7b..11c90a0a9 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,3 +1,5 @@ +import os + from flask import Flask from flask_restful import Api from flask_bootstrap import Bootstrap @@ -8,8 +10,11 @@ bootstrap = Bootstrap(app) api = Api(app) +app.env = os.environ.get('APP_ENV', 'production') from app.config.loadConfig import get_secret_cfg app.config.update(get_secret_cfg()) +print (" * Environment:", app.env) +app.config['ENV'] = app.env app.secret_key = app.config["secret_key"] diff --git a/app/logic/banner.py b/app/logic/banner.py index 7c6daac03..57e12f666 100644 --- a/app/logic/banner.py +++ b/app/logic/banner.py @@ -1,6 +1,6 @@ # Relying on https://www.oracle.com/technical-resources/articles/database/python-with-database-11g.html -import cx_Oracle +import oracledb from app import app class Banner(): @@ -12,7 +12,7 @@ def __init__(self): if app.config['use_banner']: self.database_exists = True try: - self.conn = cx_Oracle.connect( + self.conn = python-oracledb.connect( app.config["banner"]["user"], app.config["banner"]["password"], "{url}:{port}/{sid}".format(**app.config["banner"])) diff --git a/database/demo_data.py b/database/demo_data.py index 3bee9c07b..0557c9361 100644 --- a/database/demo_data.py +++ b/database/demo_data.py @@ -3,6 +3,8 @@ This file will need to be changed if the format of models changes (new fields, dropping fields, renaming...)''' from datetime import * +from app import app + from app.models.Tracy import db from app.models.Tracy.studata import STUDATA from app.models.Tracy.stuposn import STUPOSN @@ -150,9 +152,10 @@ ] # Add students to Tracy db -for student in (tracyStudents + bothStudents): - db.session.add(STUDATA(**student)) - db.session.commit() +with app.app_context(): + for student in (tracyStudents + bothStudents): + db.session.add(STUDATA(**student)) + db.session.commit() # Add the Student records students = [] @@ -254,9 +257,10 @@ ] # Add to Tracy db -for position in positions: - db.session.add(STUPOSN(**position)) - db.session.commit() +with app.app_context(): + for position in positions: + db.session.add(STUPOSN(**position)) + db.session.commit() print(" * positions (TRACY) added") @@ -351,18 +355,19 @@ ] # Add to Tracy db -for staff in staffs: - db.session.add(STUSTAFF(**staff)) - db.session.commit() - - staff['legal_name'] = staff['FIRST_NAME'].strip() - del staff['FIRST_NAME'] - Supervisor.get_or_create(**staff) - -# Add non Supervisor staffs to Tracy db -for staff in non_supervisor_staffs: - db.session.add(STUSTAFF(**staff)) - db.session.commit() +with app.app_context(): + for staff in staffs: + db.session.add(STUSTAFF(**staff)) + db.session.commit() + + staff['legal_name'] = staff['FIRST_NAME'].strip() + del staff['FIRST_NAME'] + Supervisor.get_or_create(**staff) + + # Add non Supervisor staffs to Tracy db + for staff in non_supervisor_staffs: + db.session.add(STUSTAFF(**staff)) + db.session.commit() print(" * staff added") diff --git a/requirements.txt b/requirements.txt index 5f9acfb5e..0549a2235 100755 --- a/requirements.txt +++ b/requirements.txt @@ -1,79 +1,94 @@ -alembic==1.0.11 -aniso8601==9.0.1 -asn1crypto==1.3.0 -attrs==19.3.0 -blinker==1.4 -certifi==2020.6.20 -cffi==1.15.1 -chardet==3.0.4 -clg==2.0.0 -click==8.1.3 -colorama==0.4.3 -configparser==5.0.0 -crayons==0.3.1 -cryptography==2.7 -cx-Oracle==7.3.0 -dnspython==1.16.0 +alembic==1.18.4 +aniso8601==10.0.1 +asn1crypto==1.5.1 +attrs==25.4.0 +blinker==1.9.0 +certifi==2026.2.25 +cffi==2.0.0 +chardet==6.0.0.post1 +charset-normalizer==3.4.4 +clg==3.3.0 +click==8.3.1 +colorama==0.4.6 +configparser==7.2.0 +crayons==0.4.0 +cryptography==46.0.5 +dnspython==2.8.0 docopt==0.6.2 -dominate==2.3.5 -email-validator==1.0.4 -enum34==1.1.6 -exceptiongroup==1.0.3 -Flask==2.0.3 -Flask-Admin==1.5.3 +dominate==2.9.1 +email-validator==2.3.0 +enum34==1.1.10 +exceptiongroup==1.3.1 +Flask==3.1.3 +Flask-Admin==2.0.2 Flask-Bootstrap==3.3.7.1 -Flask-Login==0.4.1 -Flask-Mail==0.9.1 -Flask-Migrate==2.5.2 -Flask-MySQL==1.4.0 +Flask-Login==0.6.3 +Flask-Mail==0.10.0 +Flask-Migrate==4.1.0 +Flask-MySQL==1.6.0 Flask-RESTful==0.3.10 -Flask-SQLAlchemy==2.4.3 -Flask-WTF==1.0.1 +Flask-SQLAlchemy==3.1.1 +Flask-WTF==1.2.2 fpdf==1.7.2 -idna==2.8 -importlib-metadata==1.7.0 -iniconfig==1.1.1 -itsdangerous==2.1.2 -Jinja2==3.0.3 +h11==0.16.0 +idna==3.11 +importlib_metadata==8.7.1 +iniconfig==2.3.0 +itsdangerous==2.2.0 +Jinja2==3.1.6 ldap3==2.9.1 -Mako==1.0.13 -MarkupSafe==2.1.1 -migrant==1.3.1 -more-itertools==8.4.0 -packaging==20.4 -pathtools==0.1.2 -peewee==3.9.6 -peewee-migrations==0.3.18 -pluggy==0.13.1 +Mako==1.3.10 +MarkupSafe==3.0.3 +migrant==1.6.1 +more-itertools==10.8.0 +oracledb==3.4.2 +outcome==1.3.0.post0 +packaging==26.0 +peewee==4.0.0 +peewee-migrations==0.3.32 +pluggy==1.6.0 py==1.11.0 -pyasn1==0.4.8 -pycparser==2.19 -PyMySQL==0.9.3 -pyodbc==4.0.39 -pyparsing==2.4.7 -pytest==7.4.0 -pytest-base-url==1.4.2 -pytest-html==2.1.1 -pytest-metadata==1.10.0 -pytest-selenium==1.17.0 -pytest-variables==1.9.0 +pyasn1==0.6.2 +pycparser==3.0 +Pygments==2.19.2 +PyMySQL==1.1.2 +pyodbc==5.3.0 +pyparsing==3.3.2 +PySocks==1.7.1 +pytest==9.0.2 +pytest-base-url==2.1.0 +pytest-html==4.2.0 +pytest-metadata==3.1.1 +pytest-selenium==4.1.0 +pytest-variables==3.1.0 pytest-watch==4.2.0 -python-dateutil==2.8.0 +python-dateutil==2.9.0.post0 +python-dotenv==1.2.1 python-editor==1.0.4 -pytz==2023.3.post1 -PyYAML==5.3 -requests==2.24.0 -selenium==3.141.0 -six==1.14.0 -SQLAlchemy==1.3.18 -termcolor==1.1.0 -tomli==2.0.1 -urllib3==1.25.9 +pytz==2025.2 +PyYAML==6.0.3 +requests==2.32.5 +selenium==4.41.0 +setuptools==82.0.0 +six==1.17.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +SQLAlchemy==2.0.47 +tenacity==9.1.4 +termcolor==3.3.0 +tomli==2.4.0 +trio==0.33.0 +trio-websocket==0.12.2 +typing_extensions==4.15.0 +urllib3==2.6.3 visitor==0.1.3 -watchdog==2.1.9 -wcwidth==0.2.5 -webdriver-manager==3.2.1 -Werkzeug==2.0.3 -WTForms==3.0.0 -XlsxWriter==1.1.8 -zipp==3.1.0 +watchdog==6.0.0 +wcwidth==0.6.0 +webdriver-manager==4.0.2 +websocket-client==1.9.0 +Werkzeug==3.1.6 +wheel==0.46.3 +wsproto==1.3.2 +WTForms==3.2.1 +xlsxwriter==3.2.9 +zipp==3.23.0 diff --git a/setup.sh b/setup.sh index 3bcaf9dac..895e43b98 100755 --- a/setup.sh +++ b/setup.sh @@ -36,6 +36,6 @@ if [[ ! -e app/config/secret_config.yaml ]]; then fi export FLASK_APP=app.py # app entry point -export FLASK_ENV=development # default +export APP_ENV=development # default export FLASK_RUN_PORT=8080 # For consistency (python app.py vs flask run) export FLASK_RUN_HOST=0.0.0.0 # To allow external routing to the application From 94872a72720475269ed48e5058333ac161b4fd81 Mon Sep 17 00:00:00 2001 From: Gbayi Date: Wed, 4 Mar 2026 11:12:23 -0500 Subject: [PATCH 2/3] Internal functions for '.contains()' have changed to only accept strings, so params must be casted to strings before use. --- app/controllers/admin_routes/termManagement.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin_routes/termManagement.py b/app/controllers/admin_routes/termManagement.py index 69c6373d4..8a17d169f 100644 --- a/app/controllers/admin_routes/termManagement.py +++ b/app/controllers/admin_routes/termManagement.py @@ -25,7 +25,7 @@ def term_Management(): termsByYear ={} for termYear in range(today.year-2, today.year+3): createTerms(termYear) - termsByYear[termYear] = list(Term.select().where(Term.termCode.cast('char').contains(termYear))) + termsByYear[termYear] = list(Term.select().where(Term.termCode.cast('char').contains(str(termYear)))) return render_template( 'admin/termManagement.html', title='Term Management', From d1acfbf5eead5e0d609b3811e8c2a8d02947bf1f Mon Sep 17 00:00:00 2001 From: Gbayi Date: Wed, 4 Mar 2026 12:46:27 -0500 Subject: [PATCH 3/3] Fixed oracledb call in banner.py --- app/logic/banner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/logic/banner.py b/app/logic/banner.py index 57e12f666..44e60d39b 100644 --- a/app/logic/banner.py +++ b/app/logic/banner.py @@ -12,7 +12,7 @@ def __init__(self): if app.config['use_banner']: self.database_exists = True try: - self.conn = python-oracledb.connect( + self.conn = oracledb.connect( app.config["banner"]["user"], app.config["banner"]["password"], "{url}:{port}/{sid}".format(**app.config["banner"]))