From 1203ac23e8b172743527074f46eac66c74eee74c Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Sat, 15 Mar 2025 23:50:39 -0400 Subject: [PATCH 01/10] Created function to add courses from json endpoint to database --- db_init.py | 123 +++++++++++++++++++++++++++++++++++++++-- labconnect/__init__.py | 5 ++ 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/db_init.py b/db_init.py index 0cb2225c..80393bb1 100644 --- a/db_init.py +++ b/db_init.py @@ -1,3 +1,4 @@ +# db_init.py """ https://docs.sqlalchemy.org/en/20/orm/queryguide/select.html https://docs.sqlalchemy.org/en/20/core/selectable.html#sqlalchemy.sql.expression.Executable @@ -7,6 +8,16 @@ """ import sys +import requests +import os + +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +# from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import declarative_base +from sqlalchemy import inspect + + from datetime import date, datetime from labconnect import create_app, db @@ -28,10 +39,69 @@ UserCourses, UserDepartments, UserMajors, - UserSavedOpportunities, - Codes, + Codes ) +from labconnect.models import Courses + +Base = declarative_base() + +basedir = os.path.abspath(os.path.dirname(__file__)) + +# from sqlalchemy.inspect import inspect + +# inspector = inspect(engine) +# if 'courses' not in inspector.get_table_names(): +# print("Error: 'courses' table does not exist. Make sure metadata is created.") + + +def fetch_json_data(json_url): + response = requests.get(json_url) + + print("Response Status Code:", response.status_code) + print("Response Headers:", response.headers) + print("Response Content (first 500 chars):", response.text[:500]) # Prevent flooding output + + if response.status_code != 200: + raise ValueError(f"Error: Received status code {response.status_code}") + + try: + return response.json() + except requests.exceptions.JSONDecodeError: + raise ValueError("Error: Received invalid JSON response") + + # if response.status_code == 200: + # # print("Response Status Code:", response.status_code) + # # print("Response Content:", response.text) # Add this line + # data = response.json() + # return data + # else: + # print( + # f"Failed to fetch JSON data from {json_url}. Status code: {response.status_code}" + # ) + # return None + + +def insert_courses_from_json(session, courses_data): + for course_code, course_info in courses_data.items(): + course_name = course_info.get("name") + + existing_course = session.query(Courses).filter_by(code=course_code).first() + if existing_course: + if existing_course.name != course_name: + existing_course.name = course_name + session.commit() + print(f"Course '{course_code}' name updated.") + else: + new_course = Courses() + new_course.code = course_code + new_course.name = course_name + session.add(new_course) + session.commit() + print(f"Course '{course_code}' inserted into the database.") + + + app = create_app() if len(sys.argv) < 2: @@ -42,7 +112,7 @@ if db.inspect(db.engine).get_table_names(): print("Tables already exist.") # clear the codes table - db.session.query(Codes).delete() + db.session.delete(Codes) db.session.commit() sys.exit() db.create_all() @@ -50,6 +120,51 @@ elif sys.argv[1] == "clear": with app.app_context(): db.drop_all() + +elif sys.argv[1] == "addCourses": + with app.app_context(): + db.create_all() + + # data = db.session.execute.select(db.select(Courses)).scalars().all() + data = db.session.execute(db.select(Courses)).scalars().all() + existing_course_codes = [courses.code for courses in data] # fill this up + + + # get the json data from the internet + json_data = [] + + # for each json data item if the course code is NOT in existing_course_codes list then just add to the database + for course in json_data: + row = Courses() + course.code = '' + course.name = '' + db.session.add(row) + db.session.commit() + + + # engine = create_engine(f"sqlite:///{os.path.join(basedir, 'database.db')}") + # # TODO: fix this + # print("Creating tables...") + # # Base.metadata.create_all(engine) + + # # Verify table creation + # inspector = inspect(engine) + # tables = inspector.get_table_names() + # print("Tables in database:", tables) # This should list ['courses'] + + # Session = sessionmaker(bind=engine) + # session = Session() + # # Base = declarative_base(metadata=metadata_obj) + + # json_url = "https://github.com/quacs/quacs-data/blob/master/semester_data/202409/catalog.json" + json_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/catalog.json" + + courses_data = fetch_json_data(json_url) + if not courses_data: + sys.exit("Failed to fetch courses data. Exiting...") + + insert_courses_from_json(db.session, courses_data) + db.session.close() elif sys.argv[1] == "create": with app.app_context(): @@ -443,10 +558,10 @@ UserCourses, UserDepartments, UserMajors, - UserSavedOpportunities, ] for table in tables: + stmt = db.select(table) result = db.session.execute(stmt).scalars() diff --git a/labconnect/__init__.py b/labconnect/__init__.py index f1f32704..b375c985 100644 --- a/labconnect/__init__.py +++ b/labconnect/__init__.py @@ -27,6 +27,11 @@ def create_app() -> Flask: # Create flask app object + + ### + ### ADD APP LOGGER HERE + ### + app = Flask(__name__) app.config.from_object(os.environ.get("CONFIG", "config.TestingConfig")) From 5a1e7b8aba40d6aba1f65fc88548439ebac4922a Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Sat, 22 Mar 2025 23:48:53 -0400 Subject: [PATCH 02/10] fixed bug issue to ensure course_code is of size String(8), with a single exception --- db_init.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/db_init.py b/db_init.py index 80393bb1..221974f5 100644 --- a/db_init.py +++ b/db_init.py @@ -13,7 +13,6 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker -# from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import declarative_base from sqlalchemy import inspect @@ -48,19 +47,13 @@ basedir = os.path.abspath(os.path.dirname(__file__)) -# from sqlalchemy.inspect import inspect - -# inspector = inspect(engine) -# if 'courses' not in inspector.get_table_names(): -# print("Error: 'courses' table does not exist. Make sure metadata is created.") - def fetch_json_data(json_url): response = requests.get(json_url) - print("Response Status Code:", response.status_code) - print("Response Headers:", response.headers) - print("Response Content (first 500 chars):", response.text[:500]) # Prevent flooding output + # print("Response Status Code:", response.status_code) + # print("Response Headers:", response.headers) + # print("Response Content (first 500 chars):", response.text[:500]) # Prevent flooding output if response.status_code != 200: raise ValueError(f"Error: Received status code {response.status_code}") @@ -83,8 +76,10 @@ def fetch_json_data(json_url): def insert_courses_from_json(session, courses_data): - for course_code, course_info in courses_data.items(): + for course, course_info in courses_data.items(): course_name = course_info.get("name") + course_code = course_info.get('subj') + course_info.get('crse') + existing_course = session.query(Courses).filter_by(code=course_code).first() if existing_course: @@ -93,12 +88,18 @@ def insert_courses_from_json(session, courses_data): session.commit() print(f"Course '{course_code}' name updated.") else: + # if (len(course_code)>8): + # print(course_code) + # else: new_course = Courses() new_course.code = course_code new_course.name = course_name session.add(new_course) session.commit() print(f"Course '{course_code}' inserted into the database.") + + # Change length requiremetn from 8 to 10 + #[parameters: {'code': 'USNA29401', 'name': 'Indep Study Naval Science'}] From ea63cd8a6c63d20bc853fa16163dd7c1f3031740 Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Fri, 28 Mar 2025 22:46:19 -0400 Subject: [PATCH 03/10] Simplfied and cleaned up code. Course_code only accepts string of length 8. --- db_init.py | 92 +++++++++--------------------------------------------- 1 file changed, 15 insertions(+), 77 deletions(-) diff --git a/db_init.py b/db_init.py index 221974f5..e03f8c7c 100644 --- a/db_init.py +++ b/db_init.py @@ -1,4 +1,3 @@ -# db_init.py """ https://docs.sqlalchemy.org/en/20/orm/queryguide/select.html https://docs.sqlalchemy.org/en/20/core/selectable.html#sqlalchemy.sql.expression.Executable @@ -9,13 +8,8 @@ import sys import requests -import os from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker -from sqlalchemy.orm import declarative_base -from sqlalchemy import inspect - from datetime import date, datetime @@ -41,70 +35,45 @@ Codes ) -from labconnect.models import Courses - -Base = declarative_base() - -basedir = os.path.abspath(os.path.dirname(__file__)) - def fetch_json_data(json_url): response = requests.get(json_url) - # print("Response Status Code:", response.status_code) - # print("Response Headers:", response.headers) - # print("Response Content (first 500 chars):", response.text[:500]) # Prevent flooding output - if response.status_code != 200: raise ValueError(f"Error: Received status code {response.status_code}") - try: return response.json() except requests.exceptions.JSONDecodeError: raise ValueError("Error: Received invalid JSON response") - - # if response.status_code == 200: - # # print("Response Status Code:", response.status_code) - # # print("Response Content:", response.text) # Add this line - # data = response.json() - # return data - # else: - # print( - # f"Failed to fetch JSON data from {json_url}. Status code: {response.status_code}" - # ) - # return None def insert_courses_from_json(session, courses_data): + # Fetch existing courses to avoid multiple queries + existing_courses = {course.code: course for course in session.query(Courses).all()} + new_courses = [] + for course, course_info in courses_data.items(): course_name = course_info.get("name") course_code = course_info.get('subj') + course_info.get('crse') - - existing_course = session.query(Courses).filter_by(code=course_code).first() - if existing_course: + if len(course_code) != 8: + continue + if course_code in existing_courses: + # Update name if changed + existing_course = existing_courses[course_code] if existing_course.name != course_name: existing_course.name = course_name - session.commit() - print(f"Course '{course_code}' name updated.") else: - # if (len(course_code)>8): - # print(course_code) - # else: - new_course = Courses() - new_course.code = course_code - new_course.name = course_name - session.add(new_course) - session.commit() - print(f"Course '{course_code}' inserted into the database.") - - # Change length requiremetn from 8 to 10 - #[parameters: {'code': 'USNA29401', 'name': 'Indep Study Naval Science'}] + new_courses.append(Courses(code=course_code, name=course_name)) + if new_courses: + session.add_all(new_courses) + session.commit() app = create_app() + if len(sys.argv) < 2: sys.exit("No argument or exsisting argument found") @@ -126,38 +95,6 @@ def insert_courses_from_json(session, courses_data): with app.app_context(): db.create_all() - # data = db.session.execute.select(db.select(Courses)).scalars().all() - data = db.session.execute(db.select(Courses)).scalars().all() - existing_course_codes = [courses.code for courses in data] # fill this up - - - # get the json data from the internet - json_data = [] - - # for each json data item if the course code is NOT in existing_course_codes list then just add to the database - for course in json_data: - row = Courses() - course.code = '' - course.name = '' - db.session.add(row) - db.session.commit() - - - # engine = create_engine(f"sqlite:///{os.path.join(basedir, 'database.db')}") - # # TODO: fix this - # print("Creating tables...") - # # Base.metadata.create_all(engine) - - # # Verify table creation - # inspector = inspect(engine) - # tables = inspector.get_table_names() - # print("Tables in database:", tables) # This should list ['courses'] - - # Session = sessionmaker(bind=engine) - # session = Session() - # # Base = declarative_base(metadata=metadata_obj) - - # json_url = "https://github.com/quacs/quacs-data/blob/master/semester_data/202409/catalog.json" json_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/catalog.json" courses_data = fetch_json_data(json_url) @@ -165,6 +102,7 @@ def insert_courses_from_json(session, courses_data): sys.exit("Failed to fetch courses data. Exiting...") insert_courses_from_json(db.session, courses_data) + db.session.close() elif sys.argv[1] == "create": From 0ebdfc07f144b8fe20aed2c2e017d0c68dcd15c9 Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Fri, 4 Apr 2025 17:11:52 -0400 Subject: [PATCH 04/10] Added logging with app.logger that logs information for functions --- labconnect/__init__.py | 43 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/labconnect/__init__.py b/labconnect/__init__.py index b375c985..ad0bcb69 100644 --- a/labconnect/__init__.py +++ b/labconnect/__init__.py @@ -4,6 +4,9 @@ import sentry_sdk +# Import logging +from logging.config import dictConfig + # Import Flask modules from flask import Flask from flask_cors import CORS @@ -27,15 +30,35 @@ def create_app() -> Flask: # Create flask app object - - ### - ### ADD APP LOGGER HERE - ### - + app = Flask(__name__) app.config.from_object(os.environ.get("CONFIG", "config.TestingConfig")) + # Logging configuration + dictConfig({ + 'version': 1, + 'formatters': { + 'default': { + 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', + } + }, + 'handlers': { + 'wsgi': { + 'class': 'logging.StreamHandler', + 'stream': 'ext://flask.logging.wsgi_errors_stream', + 'formatter': 'default' + } + }, + 'root': { + 'level': 'INFO', + 'handlers': ['wsgi'] + } + }) + + app.logger.info("App logger initialized.") + + # Sentry sentry_sdk.init( dsn=app.config["SENTRY_DSN"], integrations=[FlaskIntegration()], @@ -48,6 +71,8 @@ def create_app() -> Flask: initialize_extensions(app) register_blueprints(app) + app.logger.info("Returning App") + return app @@ -64,8 +89,11 @@ def initialize_extensions(app) -> None: jwt.init_app(app) app.json = OrJSONProvider(app) + app.logger.info("Extensions initialized.") + with app.app_context(): db.create_all() + app.logger.info("Database tables created.") @app.after_request def refresh_expiring_jwts(response): @@ -79,9 +107,11 @@ def refresh_expiring_jwts(response): if type(data) is dict: data["access_token"] = access_token response.data = json.dumps(data) + app.logger.info("Access token refreshed for user.") return response except (RuntimeError, KeyError): # Case where there is not a valid JWT. Just return the original respone + app.logger.debug("No valid JWT found; skipping refresh.") return response @@ -92,4 +122,7 @@ def register_blueprints(app) -> None: from labconnect.main import main_blueprint app.register_blueprint(main_blueprint) + app.logger.info("Main blueprint registered.") + app.register_blueprint(error_blueprint) + app.logger.info("Error blueprint registered.") From 416a6ec06dd9e145ce73d9617b88546fd44388fc Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Tue, 8 Apr 2025 16:55:52 -0400 Subject: [PATCH 05/10] Updated function to intake URL as argument & checks if URL is valid. Ran ruff format. --- db_init.py | 31 +++++++++++--------- labconnect/__init__.py | 41 +++++++++++++-------------- labconnect/main/opportunity_routes.py | 32 ++++++++++----------- labconnect/models.py | 17 +++++------ migrations/env.py | 31 +++++++++----------- 5 files changed, 75 insertions(+), 77 deletions(-) diff --git a/db_init.py b/db_init.py index e03f8c7c..4d485ecb 100644 --- a/db_init.py +++ b/db_init.py @@ -8,8 +8,7 @@ import sys import requests - -from sqlalchemy import create_engine +import validators from datetime import date, datetime @@ -32,13 +31,13 @@ UserCourses, UserDepartments, UserMajors, - Codes + Codes, ) def fetch_json_data(json_url): response = requests.get(json_url) - + if response.status_code != 200: raise ValueError(f"Error: Received status code {response.status_code}") try: @@ -51,10 +50,10 @@ def insert_courses_from_json(session, courses_data): # Fetch existing courses to avoid multiple queries existing_courses = {course.code: course for course in session.query(Courses).all()} new_courses = [] - + for course, course_info in courses_data.items(): course_name = course_info.get("name") - course_code = course_info.get('subj') + course_info.get('crse') + course_code = course_info.get("subj") + course_info.get("crse") if len(course_code) != 8: continue @@ -68,14 +67,14 @@ def insert_courses_from_json(session, courses_data): if new_courses: session.add_all(new_courses) - session.commit() + session.commit() app = create_app() if len(sys.argv) < 2: - sys.exit("No argument or exsisting argument found") + sys.exit("No argument or existing argument found") if sys.argv[1] == "start": with app.app_context(): @@ -90,19 +89,26 @@ def insert_courses_from_json(session, courses_data): elif sys.argv[1] == "clear": with app.app_context(): db.drop_all() - + elif sys.argv[1] == "addCourses": + if len(sys.argv) < 3: + sys.exit("Error: No URL argument provided.") + + json_url = sys.argv[2] + + # Validate that json_url is a valid URL + if not validators.url(json_url): + sys.exit("Error: Invalid URL provided.") + with app.app_context(): db.create_all() - json_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/catalog.json" - courses_data = fetch_json_data(json_url) if not courses_data: sys.exit("Failed to fetch courses data. Exiting...") insert_courses_from_json(db.session, courses_data) - + db.session.close() elif sys.argv[1] == "create": @@ -500,7 +506,6 @@ def insert_courses_from_json(session, courses_data): ] for table in tables: - stmt = db.select(table) result = db.session.execute(stmt).scalars() diff --git a/labconnect/__init__.py b/labconnect/__init__.py index ad0bcb69..07e64ea9 100644 --- a/labconnect/__init__.py +++ b/labconnect/__init__.py @@ -36,28 +36,27 @@ def create_app() -> Flask: app.config.from_object(os.environ.get("CONFIG", "config.TestingConfig")) # Logging configuration - dictConfig({ - 'version': 1, - 'formatters': { - 'default': { - 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s', - } - }, - 'handlers': { - 'wsgi': { - 'class': 'logging.StreamHandler', - 'stream': 'ext://flask.logging.wsgi_errors_stream', - 'formatter': 'default' - } - }, - 'root': { - 'level': 'INFO', - 'handlers': ['wsgi'] + dictConfig( + { + "version": 1, + "formatters": { + "default": { + "format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s", + } + }, + "handlers": { + "wsgi": { + "class": "logging.StreamHandler", + "stream": "ext://flask.logging.wsgi_errors_stream", + "formatter": "default", + } + }, + "root": {"level": "INFO", "handlers": ["wsgi"]}, } - }) + ) app.logger.info("App logger initialized.") - + # Sentry sentry_sdk.init( dsn=app.config["SENTRY_DSN"], @@ -72,7 +71,7 @@ def create_app() -> Flask: register_blueprints(app) app.logger.info("Returning App") - + return app @@ -123,6 +122,6 @@ def register_blueprints(app) -> None: app.register_blueprint(main_blueprint) app.logger.info("Main blueprint registered.") - + app.register_blueprint(error_blueprint) app.logger.info("Error blueprint registered.") diff --git a/labconnect/main/opportunity_routes.py b/labconnect/main/opportunity_routes.py index 078b43c2..74bf115c 100644 --- a/labconnect/main/opportunity_routes.py +++ b/labconnect/main/opportunity_routes.py @@ -210,8 +210,7 @@ def getOpportunity(opp_id: int): Opportunities.id == RecommendsClassYears.opportunity_id, ) .where(Opportunities.id == opp_id) - .group_by(Opportunities.id) - + .group_by(Opportunities.id) ) data = query.all() @@ -756,8 +755,8 @@ def editOpportunity_get(opportunity_id): if credit ] - years = [str(year.class_year) for year in years_data] - #if years_data else [] + years = [str(year.class_year) for year in years_data] + # if years_data else [] # Format opportunity data as JSON opportunity_data = { @@ -896,7 +895,6 @@ def editOpportunity(opportunity_id): # ) # db.session.add(new_lead) - # Atttempt to fix by replacing data with request_data # Add the updated list of managers if "lab_manager_ids" in request_data: @@ -908,10 +906,8 @@ def editOpportunity(opportunity_id): db.session.commit() # Commit all changes - # db.session.commit() # Commit all changes - return {"data": "Opportunity Updated"}, 200 @@ -949,10 +945,12 @@ def deleteOpportunity(opportunity_id): return {"data": "Opportunity Deleted"} -#//////////////////////////////////////////////// + +# //////////////////////////////////////////////// # Store opportunities saved by a user # ***Specificaly storing a individual users saved opportunities*** + # Save User Opportunity @main_blueprint.post("/saveUserOpportunity/") @jwt_required() @@ -964,14 +962,14 @@ def saveUserOpportunity(opportunity_id): save_opp_opportunity_id = db.session.get(Opportunities, opportunity_id) if not save_opp_opportunity_id: return {"error": "Opportunity not found"}, 404 - + save_opp_user_id = get_jwt_identity() # Check if the opportunity already exists in saved opportunities find_opp = db.session.execute( db.select(UserSavedOpportunities).where( - (UserSavedOpportunities.user_id == save_opp_user_id) & - (UserSavedOpportunities.opportunity_id == save_opp_opportunity_id) + (UserSavedOpportunities.user_id == save_opp_user_id) + & (UserSavedOpportunities.opportunity_id == save_opp_opportunity_id) ) ).scalar_one_or_none() @@ -980,14 +978,14 @@ def saveUserOpportunity(opportunity_id): # Save the new opportunity new_opp = UserSavedOpportunities( - user_id = save_opp_user_id, - opportunity_id = save_opp_opportunity_id + user_id=save_opp_user_id, opportunity_id=save_opp_opportunity_id ) db.session.add(new_opp) db.session.commit() return {"message": "Opportunity saved successfully"}, 201 + # Delete an opportunitiy saved by a user @main_blueprint.delete("/deleteUserOpportunity/") @jwt_required() @@ -1004,16 +1002,16 @@ def deleteUserOpportunity(opportunity_id): # Find the saved opportunity get_saved_opp_info = db.session.execute( db.select(UserSavedOpportunities).where( - (UserSavedOpportunities.user_id == save_opp_user_id) & - (UserSavedOpportunities.opportunity_id == save_opp_opportunity_id) + (UserSavedOpportunities.user_id == save_opp_user_id) + & (UserSavedOpportunities.opportunity_id == save_opp_opportunity_id) ) ).scalar_one_or_none() if not get_saved_opp_info: return {"message": "Opportunity not found"}, 404 - # Delete the opportunity + # Delete the opportunity db.session.delete(get_saved_opp_info) db.session.commit() - return {"message": "Opportunity deleted"}, 200 \ No newline at end of file + return {"message": "Opportunity deleted"}, 200 diff --git a/labconnect/models.py b/labconnect/models.py index 8c3d4282..5d333119 100644 --- a/labconnect/models.py +++ b/labconnect/models.py @@ -303,18 +303,19 @@ class UserSavedOpportunities(db.Model): ) user = db.relationship("User", back_populates="saved_opportunities") - #user = db.relationship("User", back_populates="opportunities") + # user = db.relationship("User", back_populates="opportunities") opportunity = db.relationship("Opportunities", back_populates="saved_opportunities") - #__tablename__ = "participates" + # __tablename__ = "participates" - #user_id = db.Column(db.String(9), db.ForeignKey("user.id"), primary_key=True) - #opportunity_id = db.Column( - #db.Integer, db.ForeignKey("opportunities.id"), primary_key=True - #) + # user_id = db.Column(db.String(9), db.ForeignKey("user.id"), primary_key=True) + # opportunity_id = db.Column( + # db.Integer, db.ForeignKey("opportunities.id"), primary_key=True + # ) + + # user = db.relationship("User", back_populates="opportunities") + # opportunity = db.relationship("Opportunities", back_populates="users") - #user = db.relationship("User", back_populates="opportunities") - #opportunity = db.relationship("Opportunities", back_populates="users") class Leads(db.Model): __tablename__ = "leads" diff --git a/migrations/env.py b/migrations/env.py index 4c970927..d004741b 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -12,32 +12,31 @@ # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') +logger = logging.getLogger("alembic.env") def get_engine(): try: # this works with Flask-SQLAlchemy<3 and Alchemical - return current_app.extensions['migrate'].db.get_engine() + return current_app.extensions["migrate"].db.get_engine() except (TypeError, AttributeError): # this works with Flask-SQLAlchemy>=3 - return current_app.extensions['migrate'].db.engine + return current_app.extensions["migrate"].db.engine def get_engine_url(): try: - return get_engine().url.render_as_string(hide_password=False).replace( - '%', '%%') + return get_engine().url.render_as_string(hide_password=False).replace("%", "%%") except AttributeError: - return str(get_engine().url).replace('%', '%%') + return str(get_engine().url).replace("%", "%%") # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata -config.set_main_option('sqlalchemy.url', get_engine_url()) -target_db = current_app.extensions['migrate'].db +config.set_main_option("sqlalchemy.url", get_engine_url()) +target_db = current_app.extensions["migrate"].db # other values from the config, defined by the needs of env.py, # can be acquired: @@ -46,7 +45,7 @@ def get_engine_url(): def get_metadata(): - if hasattr(target_db, 'metadatas'): + if hasattr(target_db, "metadatas"): return target_db.metadatas[None] return target_db.metadata @@ -64,9 +63,7 @@ def run_migrations_offline(): """ url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, target_metadata=get_metadata(), literal_binds=True - ) + context.configure(url=url, target_metadata=get_metadata(), literal_binds=True) with context.begin_transaction(): context.run_migrations() @@ -84,13 +81,13 @@ def run_migrations_online(): # when there are no changes to the schema # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): + if getattr(config.cmd_opts, "autogenerate", False): script = directives[0] if script.upgrade_ops.is_empty(): directives[:] = [] - logger.info('No changes in schema detected.') + logger.info("No changes in schema detected.") - conf_args = current_app.extensions['migrate'].configure_args + conf_args = current_app.extensions["migrate"].configure_args if conf_args.get("process_revision_directives") is None: conf_args["process_revision_directives"] = process_revision_directives @@ -98,9 +95,7 @@ def process_revision_directives(context, revision, directives): with connectable.connect() as connection: context.configure( - connection=connection, - target_metadata=get_metadata(), - **conf_args + connection=connection, target_metadata=get_metadata(), **conf_args ) with context.begin_transaction(): From 73a7cf3af4d767d3aab3611cee6b25dbafc31dd0 Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Tue, 8 Apr 2025 17:46:28 -0400 Subject: [PATCH 06/10] Created function to process department data from QUACS data and push to the db --- db_init.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/db_init.py b/db_init.py index 4d485ecb..da72a565 100644 --- a/db_init.py +++ b/db_init.py @@ -68,8 +68,35 @@ def insert_courses_from_json(session, courses_data): if new_courses: session.add_all(new_courses) session.commit() + +def insert_schools_and_departments(session, schools_data): + for school_data in schools_data: + school_name = school_data.get("name") + school_description = "" + school = RPISchools() + school.name = school_name + school.description = school_description + session.add(school) + session.commit() + print(f"School '{school_name}' inserted into the database.") + + for department_data in school_data.get("depts", []): + department_id = department_data.get("code") + department_name = department_data.get("name") + department_description = "" + + department = RPIDepartments() + department.id = department_id + department.name = department_name + department.description = department_description + department.school_id = school_name + session.add(department) + session.commit() + print(f"Department '{department_name}' inserted into the database.") + + app = create_app() @@ -111,6 +138,37 @@ def insert_courses_from_json(session, courses_data): db.session.close() +elif sys.argv[1] == "addDept": + + json_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/schools.json" + + with app.app_context(): + db.create_all() + + schools_data = fetch_json_data(json_url) + if not schools_data: + sys.exit("Failed to fetch schools data. Exiting...") + + insert_schools_and_departments(db.session, schools_data) + + db.session.close() + + ### PREVIOUS + # engine = create_engine(f"sqlite:///{os.path.join(basedir, 'database.db')}") + # Base.metadata.create_all(engine) + # Session = sessionmaker(bind=engine) + # session = Session() + + # schools_data = load_json_data(JSON_FILE_PATH) + # if not schools_data: + # print("Failed to load JSON data. Exiting...") + # return + + # insert_schools_and_departments(session, schools_data) + + # session.close() + + elif sys.argv[1] == "create": with app.app_context(): db.create_all() From cb8520eeec217a3562434a5a69ed64d5956078f6 Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Fri, 11 Apr 2025 17:01:35 -0400 Subject: [PATCH 07/10] Addressed deepsource major errors, added main function --- db_init.py | 944 +++++++++++++++++++++++++++-------------------------- 1 file changed, 476 insertions(+), 468 deletions(-) diff --git a/db_init.py b/db_init.py index da72a565..21c7b865 100644 --- a/db_init.py +++ b/db_init.py @@ -68,7 +68,7 @@ def insert_courses_from_json(session, courses_data): if new_courses: session.add_all(new_courses) session.commit() - + def insert_schools_and_departments(session, schools_data): for school_data in schools_data: @@ -96,484 +96,492 @@ def insert_schools_and_departments(session, schools_data): session.commit() print(f"Department '{department_name}' inserted into the database.") - -app = create_app() - - -if len(sys.argv) < 2: - sys.exit("No argument or existing argument found") - -if sys.argv[1] == "start": - with app.app_context(): - if db.inspect(db.engine).get_table_names(): - print("Tables already exist.") - # clear the codes table - db.session.delete(Codes) - db.session.commit() - sys.exit() - db.create_all() - -elif sys.argv[1] == "clear": - with app.app_context(): - db.drop_all() - -elif sys.argv[1] == "addCourses": - if len(sys.argv) < 3: - sys.exit("Error: No URL argument provided.") - - json_url = sys.argv[2] - - # Validate that json_url is a valid URL - if not validators.url(json_url): - sys.exit("Error: Invalid URL provided.") - - with app.app_context(): - db.create_all() - - courses_data = fetch_json_data(json_url) - if not courses_data: - sys.exit("Failed to fetch courses data. Exiting...") - - insert_courses_from_json(db.session, courses_data) - - db.session.close() - -elif sys.argv[1] == "addDept": - - json_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/schools.json" - - with app.app_context(): - db.create_all() - - schools_data = fetch_json_data(json_url) - if not schools_data: - sys.exit("Failed to fetch schools data. Exiting...") - - insert_schools_and_departments(db.session, schools_data) - - db.session.close() - - ### PREVIOUS - # engine = create_engine(f"sqlite:///{os.path.join(basedir, 'database.db')}") - # Base.metadata.create_all(engine) - # Session = sessionmaker(bind=engine) - # session = Session() - - # schools_data = load_json_data(JSON_FILE_PATH) - # if not schools_data: - # print("Failed to load JSON data. Exiting...") - # return - - # insert_schools_and_departments(session, schools_data) - # session.close() +def main(): + app = create_app() - -elif sys.argv[1] == "create": - with app.app_context(): - db.create_all() - - rpi_schools_rows = ( - ("School of Science", "the coolest of them all"), - ("School of Engineering", "also pretty cool"), - ) - - for row_tuple in rpi_schools_rows: - row = RPISchools() - row.name = row_tuple[0] - row.description = row_tuple[1] - - db.session.add(row) - db.session.commit() - - rpi_departments_rows = ( - ("Computer Science", "DS is rough", "School of Science", "CSCI"), - ("Biology", "life science", "School of Science", "BIOL"), - ( - "Materials Engineering", - "also pretty cool", - "School of Engineering", - "MTLE", - ), - ( - "Environmental Engineering", - "water stuff", - "School of Engineering", - "ENVE", - ), - ("Math", "quick maths", "School of Science", "MATH"), - ( - "Mechanical, Aerospace, and Nuclear Engineering", - "space, the final frontier", - "School of Engineering", - "MANE", - ), - ) - - for row_tuple in rpi_departments_rows: - row = RPIDepartments() - row.name = row_tuple[0] - row.description = row_tuple[1] - row.school_id = row_tuple[2] - row.id = row_tuple[3] - row.image = "https://cdn-icons-png.flaticon.com/512/5310/5310672.png" - row.website = "https://www.rpi.edu" - - db.session.add(row) - db.session.commit() - - class_years_rows = (2025, 2026, 2027, 2028, 2029, 2030, 2031) - - for row_item in class_years_rows: - row = ClassYears() - row.class_year = row_item - row.active = True - - db.session.add(row) - db.session.commit() - - lab_manager_rows = ( - ("led", "Duy", "Le", "CSCI", "database database database"), - ( - "turner", - "Wes", - "Turner", - "CSCI", - "open source stuff is cool", - ), - ( - "kuzmin", - "Konstantine", - "Kuzmin", + if len(sys.argv) < 2: + sys.exit("No argument or existing argument found") + + if sys.argv[1] == "start": + with app.app_context(): + if db.inspect(db.engine).get_table_names(): + print("Tables already exist.") + # clear the codes table + db.session.delete(Codes) + db.session.commit() + sys.exit() + db.create_all() + + elif sys.argv[1] == "clear": + with app.app_context(): + db.drop_all() + + elif sys.argv[1] == "addCourses": + if len(sys.argv) < 3: + sys.exit("Error: No URL argument provided.") + + j_url = sys.argv[2] + + # Validate that j_url is a valid URL + if not validators.url(j_url): + sys.exit("Error: Invalid URL provided.") + + with app.app_context(): + db.create_all() + + data = fetch_json_data(j_url) + if not data: + sys.exit("Failed to fetch courses data. Exiting...") + + insert_courses_from_json(db.session, data) + + db.session.close() + + elif sys.argv[1] == "addDept": + j_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/schools.json" + + with app.app_context(): + db.create_all() + + data = fetch_json_data(j_url) + if not data: + sys.exit("Failed to fetch schools data. Exiting...") + + insert_schools_and_departments(db.session, data) + + db.session.close() + + ### PREVIOUS + # engine = create_engine(f"sqlite:///{os.path.join(basedir, 'database.db')}") + # Base.metadata.create_all(engine) + # Session = sessionmaker(bind=engine) + # session = Session() + + # schools_data = load_json_data(JSON_FILE_PATH) + # if not schools_data: + # print("Failed to load JSON data. Exiting...") + # return + + # insert_schools_and_departments(session, schools_data) + + # session.close() + + elif sys.argv[1] == "create": + with app.app_context(): + db.create_all() + + rpi_schools_rows = ( + ("School of Science", "the coolest of them all"), + ("School of Engineering", "also pretty cool"), + ) + + for row_tuple in rpi_schools_rows: + row = RPISchools() + row.name = row_tuple[0] + row.description = row_tuple[1] + + db.session.add(row) + db.session.commit() + + rpi_departments_rows = ( + ("Computer Science", "DS is rough", "School of Science", "CSCI"), + ("Biology", "life science", "School of Science", "BIOL"), + ( + "Materials Engineering", + "also pretty cool", + "School of Engineering", + "MTLE", + ), + ( + "Environmental Engineering", + "water stuff", + "School of Engineering", + "ENVE", + ), + ("Math", "quick maths", "School of Science", "MATH"), + ( + "Mechanical, Aerospace, and Nuclear Engineering", + "space, the final frontier", + "School of Engineering", + "MANE", + ), + ) + + for row_tuple in rpi_departments_rows: + row = RPIDepartments() + row.name = row_tuple[0] + row.description = row_tuple[1] + row.school_id = row_tuple[2] + row.id = row_tuple[3] + row.image = "https://cdn-icons-png.flaticon.com/512/5310/5310672.png" + row.website = "https://www.rpi.edu" + + db.session.add(row) + db.session.commit() + + class_years_rows = (2025, 2026, 2027, 2028, 2029, 2030, 2031) + + for row_item in class_years_rows: + row = ClassYears() + row.class_year = row_item + row.active = True + + db.session.add(row) + db.session.commit() + + lab_manager_rows = ( + ("led", "Duy", "Le", "CSCI", "database database database"), + ( + "turner", + "Wes", + "Turner", + "CSCI", + "open source stuff is cool", + ), + ( + "kuzmin", + "Konstantine", + "Kuzmin", + "CSCI", + "java, psoft, etc.", + ), + ("goldd", "David", "Goldschmidt", "CSCI", "VIM master"), + ("rami", "Rami", "Rami", "MTLE", "cubes are cool"), + ("holm", "Mark", "Holmes", "MATH", "all about that math"), + ("test", "RCOS", "RCOS", "CSCI", "first test"), + ("test2", "RCOS", "RCOS", "CSCI", "Second test"), + ("test3", "RCOS", "RCOS", "CSCI", "Third test"), + ) + + raf_test_user = ( + "cenzar", + "Rafael", + "Cenzano", + "Raf", + 2025, "CSCI", - "java, psoft, etc.", - ), - ("goldd", "David", "Goldschmidt", "CSCI", "VIM master"), - ("rami", "Rami", "Rami", "MTLE", "cubes are cool"), - ("holm", "Mark", "Holmes", "MATH", "all about that math"), - ("test", "RCOS", "RCOS", "CSCI", "first test"), - ("test2", "RCOS", "RCOS", "CSCI", "Second test"), - ("test3", "RCOS", "RCOS", "CSCI", "Third test"), - ) - - raf_test_user = ( - "cenzar", - "Rafael", - "Cenzano", - "Raf", - 2025, - "CSCI", - "labconnect is the best RCOS project", - "https://rafael.sirv.com/Images/rafael.jpeg?thumbnail=350&format=webp&q=90", - "https://rafaelcenzano.com", - ) - - lab_manager = LabManager() - lab_manager.department_id = raf_test_user[5] - - db.session.add(lab_manager) - db.session.commit() - - user = User() - user.id = raf_test_user[0] - user.email = raf_test_user[0] + "@rpi.edu" - user.first_name = raf_test_user[1] - user.last_name = raf_test_user[2] - user.preferred_name = raf_test_user[3] - user.class_year = raf_test_user[4] - user.lab_manager_id = lab_manager.id - user.description = raf_test_user[6] - user.profile_picture = raf_test_user[7] - user.website = raf_test_user[8] - - db.session.add(user) - db.session.commit() - - for row_tuple in lab_manager_rows: + "labconnect is the best RCOS project", + "https://rafael.sirv.com/Images/rafael.jpeg?thumbnail=350&format=webp&q=90", + "https://rafaelcenzano.com", + ) + lab_manager = LabManager() - lab_manager.department_id = row_tuple[3] + lab_manager.department_id = raf_test_user[5] db.session.add(lab_manager) db.session.commit() user = User() - user.id = row_tuple[0] - user.email = row_tuple[0] + "@rpi.edu" - user.first_name = row_tuple[1] - user.last_name = row_tuple[2] + user.id = raf_test_user[0] + user.email = raf_test_user[0] + "@rpi.edu" + user.first_name = raf_test_user[1] + user.last_name = raf_test_user[2] + user.preferred_name = raf_test_user[3] + user.class_year = raf_test_user[4] user.lab_manager_id = lab_manager.id - user.description = row_tuple[4] - user.profile_picture = "https://www.svgrepo.com/show/206842/professor.svg" + user.description = raf_test_user[6] + user.profile_picture = raf_test_user[7] + user.website = raf_test_user[8] db.session.add(user) db.session.commit() - opportunities_rows = ( - ( - "Automated Cooling System", - "Energy efficient AC system", - "Thermodynamics", - 15.0, - False, - False, - False, - True, - SemesterEnum.SPRING, - 2025, - date.today(), - True, - datetime.now(), - LocationEnum.REMOTE, - ), - ( - "Iphone 15 durability test", - "Scratching the Iphone, drop testing etc.", - "Experienced in getting angry and throwing temper tantrum", - None, - True, - True, - True, - True, - SemesterEnum.SPRING, - 2025, - date.today(), - True, - datetime.now(), - LocationEnum.LALLY, - ), - ( - "Checking out cubes", - "Material Sciences", - "Experienced in materials.", - None, - True, - True, - True, - True, - SemesterEnum.FALL, - 2025, - date.today(), - True, - datetime.now(), - LocationEnum.MRC, - ), - ( - "Test the water", - "Testing the quality of water in Troy pipes", - "Understanding of lead poisioning", - None, - False, - False, - True, - True, - SemesterEnum.SUMMER, - 2025, - date.today(), - True, - datetime.now(), - LocationEnum.JEC, - ), - ( - "Data Science Research", - "Work with a team of researchers to analyze large datasets and extract meaningful insights.", - "Python, Machine Learning, Data Analysis", - 20.0, - True, - False, - True, - False, - SemesterEnum.FALL, - 2025, - "2025-10-31", - True, - "2025-10-10T10:30:00", - LocationEnum.JROWL, - ), - ) - - for row_tuple in opportunities_rows: - row = Opportunities() - row.name = row_tuple[0] - row.description = row_tuple[1] - row.recommended_experience = row_tuple[2] - row.pay = row_tuple[3] - row.one_credit = row_tuple[4] - row.two_credits = row_tuple[5] - row.three_credits = row_tuple[6] - row.four_credits = row_tuple[7] - row.semester = row_tuple[8] - row.year = row_tuple[9] - row.application_due = row_tuple[10] - row.active = row_tuple[11] - row.last_updated = row_tuple[12] - row.location = row_tuple[13] - - db.session.add(row) - db.session.commit() - - courses_rows = ( - ("CSCI2300", "Introduction to Algorithms"), - ("CSCI4430", "Programming Languages"), - ("CSCI2961", "Rensselaer Center for Open Source"), - ("CSCI4390", "Data Mining"), - ) - - for row_tuple in courses_rows: - row = Courses() - row.code = row_tuple[0] - row.name = row_tuple[1] - - db.session.add(row) - db.session.commit() - - majors_rows = ( - ("CSCI", "Computer Science"), - ("ECSE", "Electrical, Computer, and Systems Engineering"), - ("BIOL", "Biological Science"), - ("MATH", "Mathematics"), - ("COGS", "Cognitive Science"), - ("PHYS", "Physics"), - ) - - for row_tuple in majors_rows: - row = Majors() - row.code = row_tuple[0] - row.name = row_tuple[1] - - db.session.add(row) - db.session.commit() - - # https://www.geeksforgeeks.org/datetime-timezone-in-sqlalchemy/ - # https://www.tutorialspoint.com/handling-timezone-in-python - - leads_rows = ( - (2, 1), - (1, 1), - (2, 2), - (1, 3), - (4, 4), - (8, 5), - ) - - for r in leads_rows: - row = Leads() - row.lab_manager_id = r[0] - row.opportunity_id = r[1] - - db.session.add(row) - db.session.commit() - - recommends_courses_rows = ((1, "CSCI4430"), (1, "CSCI2961"), (2, "CSCI4390")) - - for r in recommends_courses_rows: - row = RecommendsCourses() - row.opportunity_id = r[0] - row.course_code = r[1] - - db.session.add(row) - db.session.commit() - - recommends_majors_rows = ((1, "CSCI"), (1, "PHYS"), (2, "BIOL")) - - for r in recommends_majors_rows: - row = RecommendsMajors() - row.opportunity_id = r[0] - row.major_code = r[1] - - db.session.add(row) - db.session.commit() - - recommends_class_years_rows = ((3, 2025), (2, 2025), (2, 2026), (1, 2027)) - - for r in recommends_class_years_rows: - row = RecommendsClassYears() - row.opportunity_id = r[0] - row.class_year = r[1] - - db.session.add(row) - db.session.commit() - - user_majors = ( - ("cenzar", "MATH"), - ("cenzar", "CSCI"), - ("test", "CSCI"), - ) - - for r in user_majors: - row = UserMajors() - row.user_id = r[0] - row.major_code = r[1] - - db.session.add(row) - db.session.commit() - - for r in user_majors: - row = UserDepartments() - row.user_id = r[0] - row.department_id = r[1] - - db.session.add(row) - db.session.commit() - - user_courses = ( - ("cenzar", "CSCI2300", False), - ("cenzar", "CSCI4430", True), - ("test", "CSCI2300", False), - ) - - for r in user_courses: - row = UserCourses() - row.user_id = r[0] - row.course_code = r[1] - row.in_progress = r[2] - - db.session.add(row) - db.session.commit() - - participates_rows = ( - ("cenzar", 1), - ("cenzar", 2), - ("test", 3), - ("test", 4), - ) - - for r in participates_rows: - row = Participates() - row.user_id = r[0] - row.opportunity_id = r[1] - - db.session.add(row) - db.session.commit() - - tables = [ - ClassYears, - Courses, - Leads, - Majors, - Opportunities, - Participates, - RecommendsClassYears, - RecommendsCourses, - RecommendsMajors, - RPIDepartments, - RPISchools, - User, - UserCourses, - UserDepartments, - UserMajors, - ] - - for table in tables: - stmt = db.select(table) - result = db.session.execute(stmt).scalars() - - inst = db.inspect(table) - attr_names = [c_attr.key for c_attr in inst.mapper.column_attrs] - - print(f"{table.__tablename__}") - print(attr_names) - for row in result: - print(row) - print() - - print("Number of tables:", len(tables)) + for row_tuple in lab_manager_rows: + lab_manager = LabManager() + lab_manager.department_id = row_tuple[3] + + db.session.add(lab_manager) + db.session.commit() + + user = User() + user.id = row_tuple[0] + user.email = row_tuple[0] + "@rpi.edu" + user.first_name = row_tuple[1] + user.last_name = row_tuple[2] + user.lab_manager_id = lab_manager.id + user.description = row_tuple[4] + user.profile_picture = ( + "https://www.svgrepo.com/show/206842/professor.svg" + ) + + db.session.add(user) + db.session.commit() + + opportunities_rows = ( + ( + "Automated Cooling System", + "Energy efficient AC system", + "Thermodynamics", + 15.0, + False, + False, + False, + True, + SemesterEnum.SPRING, + 2025, + date.today(), + True, + datetime.now(), + LocationEnum.REMOTE, + ), + ( + "Iphone 15 durability test", + "Scratching the Iphone, drop testing etc.", + "Experienced in getting angry and throwing temper tantrum", + None, + True, + True, + True, + True, + SemesterEnum.SPRING, + 2025, + date.today(), + True, + datetime.now(), + LocationEnum.LALLY, + ), + ( + "Checking out cubes", + "Material Sciences", + "Experienced in materials.", + None, + True, + True, + True, + True, + SemesterEnum.FALL, + 2025, + date.today(), + True, + datetime.now(), + LocationEnum.MRC, + ), + ( + "Test the water", + "Testing the quality of water in Troy pipes", + "Understanding of lead poisioning", + None, + False, + False, + True, + True, + SemesterEnum.SUMMER, + 2025, + date.today(), + True, + datetime.now(), + LocationEnum.JEC, + ), + ( + "Data Science Research", + "Work with a team of researchers to analyze large datasets and extract meaningful insights.", + "Python, Machine Learning, Data Analysis", + 20.0, + True, + False, + True, + False, + SemesterEnum.FALL, + 2025, + "2025-10-31", + True, + "2025-10-10T10:30:00", + LocationEnum.JROWL, + ), + ) + + for row_tuple in opportunities_rows: + row = Opportunities() + row.name = row_tuple[0] + row.description = row_tuple[1] + row.recommended_experience = row_tuple[2] + row.pay = row_tuple[3] + row.one_credit = row_tuple[4] + row.two_credits = row_tuple[5] + row.three_credits = row_tuple[6] + row.four_credits = row_tuple[7] + row.semester = row_tuple[8] + row.year = row_tuple[9] + row.application_due = row_tuple[10] + row.active = row_tuple[11] + row.last_updated = row_tuple[12] + row.location = row_tuple[13] + + db.session.add(row) + db.session.commit() + + courses_rows = ( + ("CSCI2300", "Introduction to Algorithms"), + ("CSCI4430", "Programming Languages"), + ("CSCI2961", "Rensselaer Center for Open Source"), + ("CSCI4390", "Data Mining"), + ) + + for row_tuple in courses_rows: + row = Courses() + row.code = row_tuple[0] + row.name = row_tuple[1] + + db.session.add(row) + db.session.commit() + + majors_rows = ( + ("CSCI", "Computer Science"), + ("ECSE", "Electrical, Computer, and Systems Engineering"), + ("BIOL", "Biological Science"), + ("MATH", "Mathematics"), + ("COGS", "Cognitive Science"), + ("PHYS", "Physics"), + ) + + for row_tuple in majors_rows: + row = Majors() + row.code = row_tuple[0] + row.name = row_tuple[1] + + db.session.add(row) + db.session.commit() + + # https://www.geeksforgeeks.org/datetime-timezone-in-sqlalchemy/ + # https://www.tutorialspoint.com/handling-timezone-in-python + + leads_rows = ( + (2, 1), + (1, 1), + (2, 2), + (1, 3), + (4, 4), + (8, 5), + ) + + for r in leads_rows: + row = Leads() + row.lab_manager_id = r[0] + row.opportunity_id = r[1] + + db.session.add(row) + db.session.commit() + + recommends_courses_rows = ( + (1, "CSCI4430"), + (1, "CSCI2961"), + (2, "CSCI4390"), + ) + + for r in recommends_courses_rows: + row = RecommendsCourses() + row.opportunity_id = r[0] + row.course_code = r[1] + + db.session.add(row) + db.session.commit() + + recommends_majors_rows = ((1, "CSCI"), (1, "PHYS"), (2, "BIOL")) + + for r in recommends_majors_rows: + row = RecommendsMajors() + row.opportunity_id = r[0] + row.major_code = r[1] + + db.session.add(row) + db.session.commit() + + recommends_class_years_rows = ((3, 2025), (2, 2025), (2, 2026), (1, 2027)) + + for r in recommends_class_years_rows: + row = RecommendsClassYears() + row.opportunity_id = r[0] + row.class_year = r[1] + + db.session.add(row) + db.session.commit() + + user_majors = ( + ("cenzar", "MATH"), + ("cenzar", "CSCI"), + ("test", "CSCI"), + ) + + for r in user_majors: + row = UserMajors() + row.user_id = r[0] + row.major_code = r[1] + + db.session.add(row) + db.session.commit() + + for r in user_majors: + row = UserDepartments() + row.user_id = r[0] + row.department_id = r[1] + + db.session.add(row) + db.session.commit() + + user_courses = ( + ("cenzar", "CSCI2300", False), + ("cenzar", "CSCI4430", True), + ("test", "CSCI2300", False), + ) + + for r in user_courses: + row = UserCourses() + row.user_id = r[0] + row.course_code = r[1] + row.in_progress = r[2] + + db.session.add(row) + db.session.commit() + + participates_rows = ( + ("cenzar", 1), + ("cenzar", 2), + ("test", 3), + ("test", 4), + ) + + for r in participates_rows: + row = Participates() + row.user_id = r[0] + row.opportunity_id = r[1] + + db.session.add(row) + db.session.commit() + + tables = [ + ClassYears, + Courses, + Leads, + Majors, + Opportunities, + Participates, + RecommendsClassYears, + RecommendsCourses, + RecommendsMajors, + RPIDepartments, + RPISchools, + User, + UserCourses, + UserDepartments, + UserMajors, + ] + + for table in tables: + stmt = db.select(table) + result = db.session.execute(stmt).scalars() + + inst = db.inspect(table) + attr_names = [c_attr.key for c_attr in inst.mapper.column_attrs] + + print(f"{table.__tablename__}") + print(attr_names) + for row in result: + print(row) + print() + + print("Number of tables:", len(tables)) + + +if __name__ == "__main__": + main() From b29287ee5a12129bcb9118ee8b45b5e9221eb78c Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Fri, 11 Apr 2025 17:07:47 -0400 Subject: [PATCH 08/10] Updated merged code --- db_init.py | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/db_init.py b/db_init.py index 21c7b865..e56f8bc2 100644 --- a/db_init.py +++ b/db_init.py @@ -68,7 +68,7 @@ def insert_courses_from_json(session, courses_data): if new_courses: session.add_all(new_courses) session.commit() - + def insert_schools_and_departments(session, schools_data): for school_data in schools_data: @@ -139,8 +139,9 @@ def main(): db.session.close() elif sys.argv[1] == "addDept": - j_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/schools.json" + j_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/schools.json" + with app.app_context(): db.create_all() @@ -152,21 +153,6 @@ def main(): db.session.close() - ### PREVIOUS - # engine = create_engine(f"sqlite:///{os.path.join(basedir, 'database.db')}") - # Base.metadata.create_all(engine) - # Session = sessionmaker(bind=engine) - # session = Session() - - # schools_data = load_json_data(JSON_FILE_PATH) - # if not schools_data: - # print("Failed to load JSON data. Exiting...") - # return - - # insert_schools_and_departments(session, schools_data) - - # session.close() - elif sys.argv[1] == "create": with app.app_context(): db.create_all() @@ -301,9 +287,7 @@ def main(): user.last_name = row_tuple[2] user.lab_manager_id = lab_manager.id user.description = row_tuple[4] - user.profile_picture = ( - "https://www.svgrepo.com/show/206842/professor.svg" - ) + user.profile_picture = "https://www.svgrepo.com/show/206842/professor.svg" db.session.add(user) db.session.commit() @@ -463,11 +447,7 @@ def main(): db.session.add(row) db.session.commit() - recommends_courses_rows = ( - (1, "CSCI4430"), - (1, "CSCI2961"), - (2, "CSCI4390"), - ) + recommends_courses_rows = ((1, "CSCI4430"), (1, "CSCI2961"), (2, "CSCI4390")) for r in recommends_courses_rows: row = RecommendsCourses() @@ -583,5 +563,5 @@ def main(): print("Number of tables:", len(tables)) -if __name__ == "__main__": - main() +if __name__ == '__main__': + main() \ No newline at end of file From 1e3fb35a479d97220981b83b86226bddd3960334 Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Sun, 13 Apr 2025 16:24:15 -0400 Subject: [PATCH 09/10] Updated addDept to only add school/dept if not exisiting in DB --- db_init.py | 89 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 74 insertions(+), 15 deletions(-) diff --git a/db_init.py b/db_init.py index e56f8bc2..83836963 100644 --- a/db_init.py +++ b/db_init.py @@ -58,8 +58,8 @@ def insert_courses_from_json(session, courses_data): if len(course_code) != 8: continue if course_code in existing_courses: - # Update name if changed existing_course = existing_courses[course_code] + # Update name if changed if existing_course.name != course_name: existing_course.name = course_name else: @@ -71,30 +71,89 @@ def insert_courses_from_json(session, courses_data): def insert_schools_and_departments(session, schools_data): + # Fetch existing schools and departments once + existing_schools = {school.name: school for school in session.query(RPISchools).all()} + existing_departments = {dept.id: dept for dept in session.query(RPIDepartments).all()} + new_schools = [] + new_depts = [] + for school_data in schools_data: school_name = school_data.get("name") school_description = "" - school = RPISchools() - school.name = school_name - school.description = school_description - session.add(school) - session.commit() - print(f"School '{school_name}' inserted into the database.") + if school_name in existing_schools: + school = existing_schools[school_name] + # Update description if changed + if school.description != school_description: + school.description = school_description + else: + # school = RPISchools(name=school_name, description=school_description) + # session.add(school) + # session.flush() # Get ID if needed + new_schools.append(RPISchools(name=school_name, description=school_description)) + print(f"School '{school_name}' added.") + + print(f"School '{school_name}' processed.") for department_data in school_data.get("depts", []): department_id = department_data.get("code") department_name = department_data.get("name") department_description = "" - department = RPIDepartments() - department.id = department_id - department.name = department_name - department.description = department_description - department.school_id = school_name - session.add(department) - session.commit() - print(f"Department '{department_name}' inserted into the database.") + if department_id in existing_departments: + department = existing_departments[department_id] + # Update name or description if changed + if department.name != department_name: + department.name = department_name + if department.description != department_description: + department.description = department_description + if department.school_id != school_name: + department.school_id = school_name + else: + # department = RPIDepartments( + # id=department_id, + # name=department_name, + # description=department_description, + # school_id=school.name + # ) + # new_depts.append(department) + + new_depts.append(RPIDepartments(id=department_id, name=department_name, + description=department_description, school_id=school_name)) + print(f"Department '{department_name}' added.") + + print(f"Department '{department_name}' processed.") + + if new_schools or new_depts: + session.add_all(new_schools + new_depts) + session.commit() + + +# def insert_schools_and_departments(session, schools_data): +# for school_data in schools_data: +# school_name = school_data.get("name") +# school_description = "" + +# school = RPISchools() +# school.name = school_name +# school.description = school_description +# session.add(school) +# session.commit() +# print(f"School '{school_name}' inserted into the database.") + +# for department_data in school_data.get("depts", []): +# department_id = department_data.get("code") +# department_name = department_data.get("name") +# department_description = "" + +# department = RPIDepartments() +# department.id = department_id +# department.name = department_name +# department.description = department_description +# department.school_id = school_name +# session.add(department) +# session.commit() +# print(f"Department '{department_name}' inserted into the database.") def main(): From 7cb030001841022b1a91e09bb4ece4dcf240db39 Mon Sep 17 00:00:00 2001 From: MasterFardeen15 <148890501+MasterFardeen15@users.noreply.github.com> Date: Sun, 13 Apr 2025 16:46:41 -0400 Subject: [PATCH 10/10] Updated addDept function to intake URL as argument & checks if URL is valid. Ran ruff format. --- db_init.py | 94 +++++++++++++++++--------------------------- labconnect/models.py | 1 + 2 files changed, 38 insertions(+), 57 deletions(-) diff --git a/db_init.py b/db_init.py index 83836963..01af2ba1 100644 --- a/db_init.py +++ b/db_init.py @@ -68,15 +68,19 @@ def insert_courses_from_json(session, courses_data): if new_courses: session.add_all(new_courses) session.commit() - + def insert_schools_and_departments(session, schools_data): # Fetch existing schools and departments once - existing_schools = {school.name: school for school in session.query(RPISchools).all()} - existing_departments = {dept.id: dept for dept in session.query(RPIDepartments).all()} + existing_schools = { + school.name: school for school in session.query(RPISchools).all() + } + existing_departments = { + dept.id: dept for dept in session.query(RPIDepartments).all() + } new_schools = [] new_depts = [] - + for school_data in schools_data: school_name = school_data.get("name") school_description = "" @@ -87,13 +91,9 @@ def insert_schools_and_departments(session, schools_data): if school.description != school_description: school.description = school_description else: - # school = RPISchools(name=school_name, description=school_description) - # session.add(school) - # session.flush() # Get ID if needed - new_schools.append(RPISchools(name=school_name, description=school_description)) - print(f"School '{school_name}' added.") - - print(f"School '{school_name}' processed.") + new_schools.append( + RPISchools(name=school_name, description=school_description) + ) for department_data in school_data.get("depts", []): department_id = department_data.get("code") @@ -110,52 +110,20 @@ def insert_schools_and_departments(session, schools_data): if department.school_id != school_name: department.school_id = school_name else: - # department = RPIDepartments( - # id=department_id, - # name=department_name, - # description=department_description, - # school_id=school.name - # ) - # new_depts.append(department) - - new_depts.append(RPIDepartments(id=department_id, name=department_name, - description=department_description, school_id=school_name)) - print(f"Department '{department_name}' added.") - - print(f"Department '{department_name}' processed.") + new_depts.append( + RPIDepartments( + id=department_id, + name=department_name, + description=department_description, + school_id=school_name, + ) + ) if new_schools or new_depts: session.add_all(new_schools + new_depts) session.commit() -# def insert_schools_and_departments(session, schools_data): -# for school_data in schools_data: -# school_name = school_data.get("name") -# school_description = "" - -# school = RPISchools() -# school.name = school_name -# school.description = school_description -# session.add(school) -# session.commit() -# print(f"School '{school_name}' inserted into the database.") - -# for department_data in school_data.get("depts", []): -# department_id = department_data.get("code") -# department_name = department_data.get("name") -# department_description = "" - -# department = RPIDepartments() -# department.id = department_id -# department.name = department_name -# department.description = department_description -# department.school_id = school_name -# session.add(department) -# session.commit() -# print(f"Department '{department_name}' inserted into the database.") - - def main(): app = create_app() @@ -198,9 +166,15 @@ def main(): db.session.close() elif sys.argv[1] == "addDept": + if len(sys.argv) < 3: + sys.exit("Error: No URL argument provided.") + + j_url = sys.argv[2] + + # Validate that j_url is a valid URL + if not validators.url(j_url): + sys.exit("Error: Invalid URL provided.") - j_url = "https://raw.githubusercontent.com/quacs/quacs-data/master/semester_data/202409/schools.json" - with app.app_context(): db.create_all() @@ -346,7 +320,9 @@ def main(): user.last_name = row_tuple[2] user.lab_manager_id = lab_manager.id user.description = row_tuple[4] - user.profile_picture = "https://www.svgrepo.com/show/206842/professor.svg" + user.profile_picture = ( + "https://www.svgrepo.com/show/206842/professor.svg" + ) db.session.add(user) db.session.commit() @@ -506,7 +482,11 @@ def main(): db.session.add(row) db.session.commit() - recommends_courses_rows = ((1, "CSCI4430"), (1, "CSCI2961"), (2, "CSCI4390")) + recommends_courses_rows = ( + (1, "CSCI4430"), + (1, "CSCI2961"), + (2, "CSCI4390"), + ) for r in recommends_courses_rows: row = RecommendsCourses() @@ -622,5 +602,5 @@ def main(): print("Number of tables:", len(tables)) -if __name__ == '__main__': - main() \ No newline at end of file +if __name__ == "__main__": + main() diff --git a/labconnect/models.py b/labconnect/models.py index 3563a799..80d52537 100644 --- a/labconnect/models.py +++ b/labconnect/models.py @@ -254,6 +254,7 @@ class UserSavedOpportunities(db.Model): user = db.relationship("User", back_populates="saved_opportunities") opportunity = db.relationship("Opportunities", back_populates="saved_opportunities") + class Leads(db.Model): __tablename__ = "leads"