From 4b5c6803038d5f334282218fb0a53716d94b1e98 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 18 Apr 2025 23:11:55 -0400 Subject: [PATCH 1/3] Add new config for ruff linting and formatting --- pyproject.toml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 pyproject.toml diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..ff5275ea --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,11 @@ +[tool.ruff] +line-length = 88 +fix = true + +[tool.ruff.lint] +select = ["I", "F", "E"] + +[tool.ruff.format] +quote-style = "double" +indent-style = "space" +line-ending = "lf" From e5fd8552c944e0ed08364ff0a95d600479e1c645 Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 18 Apr 2025 23:12:09 -0400 Subject: [PATCH 2/3] remove unused routes --- labconnect/main/discover_routes.py | 69 ------------------------------ 1 file changed, 69 deletions(-) delete mode 100644 labconnect/main/discover_routes.py diff --git a/labconnect/main/discover_routes.py b/labconnect/main/discover_routes.py deleted file mode 100644 index f6be865f..00000000 --- a/labconnect/main/discover_routes.py +++ /dev/null @@ -1,69 +0,0 @@ -from labconnect import db -from labconnect.models import ( - ClassYears, - LabManager, - Leads, - Majors, - Opportunities, - RecommendsClassYears, - RecommendsMajors, - User, - UserMajors, -) -from labconnect.serializers import serialize_opportunity - -from . import main_blueprint - - -@main_blueprint.get("/discover") -def discover(): - # result = discover_data(get_jwt_identity(), 5) - result = discover_data(None, 5) - return result - - -def discover_data(jwt_identity, limit): - data = [] - if jwt_identity is not None: - user = db.select(User).where(User.email == jwt_identity).first() - query = ( - db.select( - Opportunities.id, - Opportunities.name, - Opportunities.semester, - Opportunities.location, - LabManager.id.label("lab_manager_id"), - ) - .where(Opportunities.active) - .join( - RecommendsClassYears, - Opportunities.id == RecommendsClassYears.class_year, - ) - .join(ClassYears, RecommendsClassYears.class_year == ClassYears.class_year) - .where(ClassYears.class_year == user.class_year) - .join(Leads, Opportunities.id == Leads.opportunity_id) - .join(LabManager, Leads.lab_manager_id == LabManager.id) - .limit(limit) - .order_by(Opportunities.last_updated.desc()) - ) - - majors = [ - Majors.code == user_major.major_code - for user_major in db.select(UserMajors) - .where(UserMajors.user_id == user.id) - .scalars() - ] - query = query.join(Majors, RecommendsMajors.major_code == Majors.code) - query = query.where(db.or_(*majors)) - - data = db.session.execute(query).scalars() - if jwt_identity is None or data is None: - data = db.session.execute( - db.select(Opportunities) - .where(Opportunities.active) - .limit(limit) - .order_by(Opportunities.last_updated.desc()) - ).scalars() - - result = [serialize_opportunity(opportunity) for opportunity in data] - return result From 5714f334f734b5c19f44cd21c617d0fdf18859ed Mon Sep 17 00:00:00 2001 From: Rafael Cenzano <32753063+RafaelCenzano@users.noreply.github.com> Date: Fri, 18 Apr 2025 23:12:43 -0400 Subject: [PATCH 3/3] Fix linting issues and sorting --- config.py | 2 +- db_init.py | 11 ++++++----- labconnect/__init__.py | 6 +----- labconnect/main/auth_routes.py | 10 +++++----- labconnect/main/opportunity_routes.py | 25 +++++++++++++++---------- labconnect/main/routes.py | 8 ++++---- labconnect/models.py | 2 +- labconnect/serializers.py | 2 +- migrations/env.py | 3 +-- migrations/versions/0e1d1657b500_.py | 17 +++++++++++++---- tests/conftest.py | 5 ++++- tests/test_courses.py | 2 +- tests/test_departments.py | 2 +- tests/test_errors.py | 2 +- tests/test_general.py | 2 +- tests/test_lab_manager.py | 5 +++-- tests/test_majors.py | 2 +- tests/test_opportunity.py | 4 +++- tests/test_user.py | 3 ++- 19 files changed, 65 insertions(+), 48 deletions(-) diff --git a/config.py b/config.py index b2716f9a..85103cae 100644 --- a/config.py +++ b/config.py @@ -1,6 +1,6 @@ # Import os -from os import getenv, path from datetime import timedelta +from os import getenv, path from dotenv import load_dotenv diff --git a/db_init.py b/db_init.py index ec9f5041..3c08aed1 100644 --- a/db_init.py +++ b/db_init.py @@ -6,18 +6,18 @@ Then pass an Executable into Session.execute() """ -import sys -import requests import re - +import sys from datetime import date, datetime +import requests + from labconnect import create_app, db from labconnect.helpers import LocationEnum, SemesterEnum -from labconnect.models import LabManager # Professors and Grad students from labconnect.models import ( ClassYears, Courses, + LabManager, # Professors and Grad students Leads, Majors, Opportunities, @@ -395,7 +395,8 @@ def main() -> None: ), ( "Data Science Research", - "Work with a team of researchers to analyze large datasets and extract meaningful insights.", + "Work with a team of researchers to analyze large datasets and " + "extract meaningful insights.", "Python, Machine Learning, Data Analysis", 20.0, True, diff --git a/labconnect/__init__.py b/labconnect/__init__.py index 07e64ea9..2e477e95 100644 --- a/labconnect/__init__.py +++ b/labconnect/__init__.py @@ -1,13 +1,9 @@ import json import os from datetime import datetime, timedelta, timezone - -import sentry_sdk - -# Import logging from logging.config import dictConfig -# Import Flask modules +import sentry_sdk from flask import Flask from flask_cors import CORS from flask_jwt_extended import ( diff --git a/labconnect/main/auth_routes.py b/labconnect/main/auth_routes.py index 6092b720..96c6e043 100644 --- a/labconnect/main/auth_routes.py +++ b/labconnect/main/auth_routes.py @@ -1,15 +1,15 @@ from datetime import datetime, timedelta from uuid import uuid4 -from flask import current_app, make_response, redirect, request, abort +from flask import abort, current_app, make_response, redirect, request from flask_jwt_extended import ( - get_jwt_identity, create_access_token, create_refresh_token, + get_jwt_identity, + jwt_required, set_access_cookies, set_refresh_cookies, unset_jwt_cookies, - jwt_required, ) from onelogin.saml2.auth import OneLogin_Saml2_Auth from werkzeug.wrappers.response import Response @@ -17,12 +17,12 @@ from labconnect import db from labconnect.helpers import prepare_flask_request from labconnect.models import ( + Codes, + ManagementPermissions, User, UserCourses, UserDepartments, UserMajors, - ManagementPermissions, - Codes, ) from . import main_blueprint diff --git a/labconnect/main/opportunity_routes.py b/labconnect/main/opportunity_routes.py index f2bae121..d38379f1 100644 --- a/labconnect/main/opportunity_routes.py +++ b/labconnect/main/opportunity_routes.py @@ -2,24 +2,24 @@ from flask import abort, request from flask_jwt_extended import get_jwt_identity, jwt_required -from sqlalchemy import func, case +from sqlalchemy import case, func from labconnect import db from labconnect.helpers import ( LocationEnum, SemesterEnum, - format_credits, convert_to_enum, + format_credits, ) from labconnect.models import ( + Courses, LabManager, Leads, Opportunities, - RecommendsClassYears, - User, - Courses, Participates, + RecommendsClassYears, RecommendsMajors, + User, UserSavedOpportunities, ) from labconnect.serializers import serialize_opportunity @@ -149,7 +149,8 @@ def getOpportunity(opp_id: int): query = db.session.execute( db.select( Opportunities, - # Creates an array for all of the recommended class years for the opportunity labeled recommended_years + # Creates an array for all of the recommended class years for the + # opportunity labeled recommended_years func.array_agg(RecommendsClassYears.class_year).label("recommended_years"), ) .join( @@ -317,7 +318,8 @@ def filterOpportunities(): opportunity[0], lab_managers=", ".join( [ - f"{name.get('preferred_name', None) or name.get('first_name')} {name.get('last_name')}" + f"{name.get('preferred_name', None) or name.get('first_name')} " + f"{name.get('last_name')}" for name in opportunity[1] ] ), @@ -404,7 +406,8 @@ def getProfileOpportunities(rcs_id: str) -> list[dict[str, str]]: # function to search for lab managers @main_blueprint.get("/searchLabManagers/") def searchLabManagers(query: str): - # Perform a search on User table by first name, last name, or email using ILIKE for exact partial matches + # Perform a search on User table by first name, last name, or email using ILIKE + # for exact partial matches stmt = ( db.select(User) .join(LabManager, User.lab_manager_id == LabManager.id) @@ -444,7 +447,9 @@ def searchLabManagers(query: str): @main_blueprint.get("/searchCourses/") def searchCourses(query: str): - # Perform a search on Courses table by code and name using ILIKE for exact partial matches + # Perform a search on Courses table by code and + # name using ILIKE for exact partial matches + # TODO: merge into filtering stmt = ( db.select(Courses) .distinct() @@ -880,7 +885,7 @@ def allSavedUserOportunities(): return saved_opportunities_list, 200 -# Create route to allow for multiple pages to be unsaved given a list of opp_ids delete them +# Create route to allow for multiple pages to be unsaved given a list of opp_ids @main_blueprint.delete("/UnsaveMultiplePages/") @jwt_required() # Delete id that appear on delete_ids list diff --git a/labconnect/main/routes.py b/labconnect/main/routes.py index b16dab68..8160d65d 100644 --- a/labconnect/main/routes.py +++ b/labconnect/main/routes.py @@ -1,17 +1,18 @@ from typing import NoReturn + from flask import abort, request from flask_jwt_extended import get_jwt_identity, jwt_required from labconnect import db from labconnect.models import ( + ClassYears, + Courses, LabManager, + Majors, Opportunities, RPIDepartments, User, - ClassYears, UserDepartments, - Majors, - Courses, ) from labconnect.serializers import serialize_course @@ -186,7 +187,6 @@ def changeActiveStatus() -> dict[str, bool]: if opportunity.active != setStatus: abort(500) - # if match is found, change the opportunities active status to true or false based on setStatus return {"activeStatus": opportunity} diff --git a/labconnect/models.py b/labconnect/models.py index 80d52537..d84809a8 100644 --- a/labconnect/models.py +++ b/labconnect/models.py @@ -3,9 +3,9 @@ from labconnect import db from labconnect.helpers import ( + LabManagerTypeEnum, LocationEnum, SemesterEnum, - LabManagerTypeEnum, ) # DD - Entities diff --git a/labconnect/serializers.py b/labconnect/serializers.py index c404463a..0a7b28a2 100644 --- a/labconnect/serializers.py +++ b/labconnect/serializers.py @@ -1,5 +1,5 @@ -from labconnect.models import Courses, Opportunities from labconnect.helpers import format_credits +from labconnect.models import Courses, Opportunities def serialize_course(course: Courses) -> str: diff --git a/migrations/env.py b/migrations/env.py index d004741b..54a60716 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -1,9 +1,8 @@ import logging from logging.config import fileConfig -from flask import current_app - from alembic import context +from flask import current_app # this is the Alembic Config object, which provides # access to the values within the .ini file in use. diff --git a/migrations/versions/0e1d1657b500_.py b/migrations/versions/0e1d1657b500_.py index f87c5a0c..b7b41061 100644 --- a/migrations/versions/0e1d1657b500_.py +++ b/migrations/versions/0e1d1657b500_.py @@ -6,9 +6,8 @@ """ -from alembic import op import sqlalchemy as sa - +from alembic import op # revision identifiers, used by Alembic. revision = "0e1d1657b500" @@ -23,8 +22,18 @@ def upgrade(): op.execute(""" DO $$ BEGIN - IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'labmanagertypeenum') THEN - CREATE TYPE labmanagertypeenum AS ENUM ('PI', 'CO_PI', 'LAB_MANAGER', 'POST_DOC', 'GRAD_STUDENT'); + IF NOT EXISTS ( + SELECT 1 + FROM pg_type + WHERE typname = 'labmanagertypeenum' + ) THEN + CREATE TYPE labmanagertypeenum AS ENUM ( + 'PI', + 'CO_PI', + 'LAB_MANAGER', + 'POST_DOC', + 'GRAD_STUDENT' + ); END IF; END$$; """) diff --git a/tests/conftest.py b/tests/conftest.py index 403ec2fd..6106dd40 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -63,7 +63,10 @@ def test_client(): # @pytest.fixture(scope="function") # def log_in_default_user(test_client): # test_client.post( -# "/login", data={"email": "patkennedy79@gmail.com", "password": "FlaskIsAwesome"} +# "/login", data={ +# "email": "patkennedy79@gmail.com", +# "password": "FlaskIsAwesome" +# } # ) # yield # this is where the testing happens! diff --git a/tests/test_courses.py b/tests/test_courses.py index cb2fd309..c661aba4 100644 --- a/tests/test_courses.py +++ b/tests/test_courses.py @@ -2,9 +2,9 @@ Test courses routes """ +import pytest from flask import json from flask.testing import FlaskClient -import pytest @pytest.mark.parametrize( diff --git a/tests/test_departments.py b/tests/test_departments.py index fbeb88a8..a8397be1 100644 --- a/tests/test_departments.py +++ b/tests/test_departments.py @@ -2,9 +2,9 @@ Test department routes """ +import pytest from flask import json from flask.testing import FlaskClient -import pytest @pytest.mark.parametrize( diff --git a/tests/test_errors.py b/tests/test_errors.py index d09edc6e..049e006c 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -2,9 +2,9 @@ Test errors """ +import pytest from flask import json from flask.testing import FlaskClient -import pytest @pytest.mark.parametrize( diff --git a/tests/test_general.py b/tests/test_general.py index 71d19ee0..e712e647 100644 --- a/tests/test_general.py +++ b/tests/test_general.py @@ -2,9 +2,9 @@ Test general routes """ +import pytest from flask import json from flask.testing import FlaskClient -import pytest def test_home_page(test_client: FlaskClient) -> None: diff --git a/tests/test_lab_manager.py b/tests/test_lab_manager.py index 5d54c2cd..c053c643 100644 --- a/tests/test_lab_manager.py +++ b/tests/test_lab_manager.py @@ -56,7 +56,7 @@ def test_lab_manager_opportunity_cards( ) -> None: """ GIVEN a Flask application configured for testing - WHEN the '/lab_manager/opportunities' page is requested (GET) with different JSON inputs + WHEN the '/lab_manager/opportunities' page is requested (GET) with different inputs THEN check that the response matches the expected status code """ response = test_client.get("/lab_manager/opportunities", json=input_json) @@ -77,7 +77,8 @@ def test_lab_manager_opportunity_cards( { "name": "Iphone 15 durability test", "description": "Scratching the Iphone, drop testing etc.", - "recommended_experience": "Experienced in getting angry and throwing temper tantrum", + "recommended_experience": "Experienced in getting angry and throwing" + " temper tantrum", "pay": None, "semester": "Spring", "year": 2024, diff --git a/tests/test_majors.py b/tests/test_majors.py index d7d6df87..96eeca9e 100644 --- a/tests/test_majors.py +++ b/tests/test_majors.py @@ -2,9 +2,9 @@ Test majors routes """ +import pytest from flask import json from flask.testing import FlaskClient -import pytest @pytest.mark.parametrize( diff --git a/tests/test_opportunity.py b/tests/test_opportunity.py index bd0e9da4..dcc567b4 100644 --- a/tests/test_opportunity.py +++ b/tests/test_opportunity.py @@ -1,4 +1,5 @@ import json + import pytest from flask.testing import FlaskClient @@ -31,7 +32,8 @@ def test_get_opportunity_parametrized(test_client: FlaskClient): { "name": "Iphone 15 durability test", "description": "Scratching the Iphone, drop testing etc.", - "recommended_experience": "Experienced in getting angry and throwing temper tantrum", + "recommended_experience": "Experienced in getting angry and throwing" + " temper tantrum", "pay": None, "one_credit": True, "two_credits": True, diff --git a/tests/test_user.py b/tests/test_user.py index 2b6744e1..f5f68fe6 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -93,7 +93,8 @@ def test_user_route( { "name": "Iphone 15 durability test", "description": "Scratching the Iphone, drop testing etc.", - "recommended_experience": "Experienced in getting angry and throwing temper tantrum", + "recommended_experience": "Experienced in getting angry and " + "throwing temper tantrum", "pay": None, "semester": "Spring", "year": 2024,