From f9704c131849929022d112a2a403838d5ba58d70 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sun, 16 Jun 2024 03:20:41 -0700 Subject: [PATCH 1/3] Fix all mypy errors --- pittapi/course.py | 27 ++++- pittapi/dining.py | 56 ++++----- pittapi/laundry.py | 4 +- pittapi/library.py | 22 ++-- pittapi/shuttle.py | 33 +++--- tests/course_test.py | 12 +- tests/dining_test.py | 10 +- tests/laundry_test.py | 6 +- tests/mocks/course_mocks.py | 29 ++++- tests/people_test.py | 111 +++--------------- tests/samples/people_none_mock_response.html | 21 ++++ .../samples/people_ramirez_mock_response.html | 43 +++++++ .../people_too_many_mock_response.html | 11 ++ tests/shuttle_test.py | 10 +- 14 files changed, 205 insertions(+), 190 deletions(-) create mode 100644 tests/samples/people_none_mock_response.html create mode 100644 tests/samples/people_ramirez_mock_response.html create mode 100644 tests/samples/people_too_many_mock_response.html diff --git a/pittapi/course.py b/pittapi/course.py index b40f195..a2cfa18 100644 --- a/pittapi/course.py +++ b/pittapi/course.py @@ -24,11 +24,28 @@ from typing import NamedTuple # https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/WEBLIB_HCX_CM.H_CLASS_SEARCH.FieldFormula.IScript_ClassSearch?institution=UPITT&term=2244&date_from=&date_thru=&subject=CS&subject_like=&catalog_nbr=&time_range=&days=&campus=PIT&location=&x_acad_career=UGRD&acad_group=&rqmnt_designtn=&instruction_mode=&keyword=&class_nbr=&acad_org=&enrl_stat=O&crse_attr=&crse_attr_value=&instructor_name=&instr_first_name=&session_code=&units=&trigger_search=&page=1 -SUBJECTS_API = "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/WEBLIB_HCX_CM.H_COURSE_CATALOG.FieldFormula.IScript_CatalogSubjects?institution=UPITT" -SUBJECT_COURSES_API = "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/WEBLIB_HCX_CM.H_COURSE_CATALOG.FieldFormula.IScript_SubjectCourses?institution=UPITT&subject={subject}" -COURSE_DETAIL_API = "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/WEBLIB_HCX_CM.H_COURSE_CATALOG.FieldFormula.IScript_CatalogCourseDetails?institution=UPITT&course_id={id}&effdt=2018-06-30&crse_offer_nbr=1&use_catalog_print=Y" -COURSE_SECTIONS_API = "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/WEBLIB_HCX_CM.H_BROWSE_CLASSES.FieldFormula.IScript_BrowseSections?institution=UPITT&campus=&location=&course_id={id}&institution=UPITT&term={term}&crse_offer_nbr=1" -SECTION_DETAILS_API = "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/WEBLIB_HCX_CM.H_CLASS_SEARCH.FieldFormula.IScript_ClassDetails?institution=UPITT&term={term}&class_nbr={id}" +SUBJECTS_API = ( + "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/" + "WEBLIB_HCX_CM.H_COURSE_CATALOG.FieldFormula.IScript_CatalogSubjects?institution=UPITT" +) +SUBJECT_COURSES_API = ( + "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/" + "WEBLIB_HCX_CM.H_COURSE_CATALOG.FieldFormula.IScript_SubjectCourses?institution=UPITT&subject={subject}" +) +COURSE_DETAIL_API = ( + "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/" + "WEBLIB_HCX_CM.H_COURSE_CATALOG.FieldFormula.IScript_CatalogCourseDetails?institution=UPITT&course_id={id}" + "&effdt=2018-06-30&crse_offer_nbr=1&use_catalog_print=Y" +) +COURSE_SECTIONS_API = ( + "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/" + "WEBLIB_HCX_CM.H_BROWSE_CLASSES.FieldFormula.IScript_BrowseSections?institution=UPITT&campus=&location=&course_id={id}" + "&institution=UPITT&term={term}&crse_offer_nbr=1" +) +SECTION_DETAILS_API = ( + "https://pitcsprd.csps.pitt.edu/psc/pitcsprd/EMPLOYEE/SA/s/" + "WEBLIB_HCX_CM.H_CLASS_SEARCH.FieldFormula.IScript_ClassDetails?institution=UPITT&term={term}&class_nbr={id}" +) # id -> unique course ID, not to be confused with course code (for instance, CS 0007 has code 105611) # career -> for example, UGRD (undergraduate) diff --git a/pittapi/dining.py b/pittapi/dining.py index 531fd49..982035c 100644 --- a/pittapi/dining.py +++ b/pittapi/dining.py @@ -62,19 +62,16 @@ "CAFE 1923", } +LOCATIONS_URL = "https://api.dineoncampus.com/v1/locations/status?site_id=5e6fcc641ca48e0cacd93b04&platform=" +HOURS_URL = "https://api.dineoncampus.com/v1/locations/weekly_schedule?site_id=5e6fcc641ca48e0cacd93b04&date=%22{date_str}%22" +PERIODS_URL = "https://api.dineoncampus.com/v1/location/{location_id}/periods?platform=0&date={date_str}" +MENU_URL = "https://api.dineoncampus.com/v1/location/{location_id}/periods/{period_id}?platform=0&date={date_str}" + def get_locations() -> dict[str, Any]: """Gets data about all dining locations""" - - url = "https://api.dineoncampus.com/v1/locations/status?site_id=5e6fcc641ca48e0cacd93b04&platform=" - - resp = requests.get( - url, - headers=REQUEST_HEADERS, - ) - + resp = requests.get(LOCATIONS_URL, headers=REQUEST_HEADERS) locations = json.loads(resp.content)["locations"] - dining_locations = {location["name"].upper(): location for location in locations} return dining_locations @@ -87,17 +84,17 @@ def get_location_hours(location_name: str, date: datetime) -> dict[str, Any]: - date must be in YYYY,MM,DD format, will return data on current day if None """ - if location_name != None and location_name.upper() not in LOCATIONS: + if location_name is not None and location_name.upper() not in LOCATIONS: raise ValueError("Invalid Dining Location") - if date == None: + if date is None: date = datetime.now() date_str = date.strftime("%Y-%m-%d") - - url = f"https://api.dineoncampus.com/v1/locations/weekly_schedule?site_id=5e6fcc641ca48e0cacd93b04&date=%22{date_str}%22" - - resp = requests.get(url, headers=REQUEST_HEADERS) + resp = requests.get( + HOURS_URL.format(date_str=date_str), + headers=REQUEST_HEADERS, + ) if resp.status_code == 502: raise ValueError("Invalid Date") @@ -106,7 +103,7 @@ def get_location_hours(location_name: str, date: datetime) -> dict[str, Any]: hours = {} - if location_name == None: + if location_name is None: for location in locations: for day in location["week"]: if day["date"] == date_str: @@ -124,39 +121,38 @@ def get_location_hours(location_name: str, date: datetime) -> dict[str, Any]: def get_location_menu(location: str, date: datetime, period_name: str): """Returns menu data for given dining location on given day/period - -period_name used for locations with different serving periods(i.e. 'Breakfast','Lunch','Dinner','Late Night') - - None -> Returns menu for first(or only) period at location""" + - period_name used for locations with different serving periods(i.e. 'Breakfast','Lunch','Dinner','Late Night') + - None -> Returns menu for first(or only) period at location + """ if location.upper() not in LOCATIONS: raise ValueError("Invalid Dining Location") - if date == None: + if date is None: date = datetime.today() date_str = date.strftime("%y-%m-%d") - location_id = get_locations()[location.upper()]["id"] - - periods_url = f"https://api.dineoncampus.com/v1/location/{location_id}/periods?platform=0&date={date_str}" - - periods_resp = requests.get(periods_url, headers=REQUEST_HEADERS) + periods_resp = requests.get( + PERIODS_URL.format(location_id=location_id, date_str=date_str), + headers=REQUEST_HEADERS, + ) if periods_resp.status_code == 502: raise ValueError("Invalid Date") periods = json.loads(periods_resp.content)["periods"] - - if period_name == None or len(periods) == 1: + if period_name is None or len(periods) == 1: period_id = periods[0]["id"] else: for period in periods: if period["name"].lower() == period_name.lower(): period_id = period["id"] - menu_url = f"https://api.dineoncampus.com/v1/location/{location_id}/periods/{period_id}?platform=0&date={date_str}" - - menu_resp = requests.get(menu_url, headers=REQUEST_HEADERS) - + menu_resp = requests.get( + MENU_URL.format(location_id=location_id, period_id=period_id, date_str=date_str), + headers=REQUEST_HEADERS, + ) menu = json.loads(menu_resp.content)["menu"] return menu diff --git a/pittapi/laundry.py b/pittapi/laundry.py index 230267e..bbbca6a 100644 --- a/pittapi/laundry.py +++ b/pittapi/laundry.py @@ -23,7 +23,7 @@ from typing import Any -BASE_URL = "https://www.laundryview.com/api/currentRoomData?school_desc_key=197&location={}" +BASE_URL = "https://www.laundryview.com/api/currentRoomData?school_desc_key=197&location={location}" LOCATION_LOOKUP = { "TOWERS": "2430136", @@ -40,7 +40,7 @@ def _get_laundry_info(building_name: str) -> Any: """Returns JSON object of laundry view webpage""" building_name = building_name.upper() - url = BASE_URL.format(LOCATION_LOOKUP[building_name]) + url = BASE_URL.format(location=LOCATION_LOOKUP[building_name]) response = requests.get(url) info = response.json() return info diff --git a/pittapi/library.py b/pittapi/library.py index 0692e13..001c0c9 100644 --- a/pittapi/library.py +++ b/pittapi/library.py @@ -25,16 +25,18 @@ LIBRARY_URL = ( "https://pitt.primo.exlibrisgroup.com/primaws/rest/pub/pnxs" - "?acTriggered=false&blendFacetsSeparately=false" - "&citationTrailFilterByAvailability=true&disableCache=false&getMore=0" - "&inst=01PITT_INST&isCDSearch=false&lang=en&limit=10&newspapersActive=false" - "&newspapersSearch=false&offset=0&otbRanking=false&pcAvailability=false" - "&qExclude=&qInclude=&rapido=false&refEntryActive=false&rtaLinks=true" - "&scope=MyInst_and_CI&searchInFulltextUserSelection=false&skipDelivery=Y" - "&sort=rank&tab=Everything&vid=01PITT_INST:01PITT_INST" + "?acTriggered=false&blendFacetsSeparately=false&citationTrailFilterByAvailability=true&disableCache=false&getMore=0" + "&inst=01PITT_INST&isCDSearch=false&lang=en&limit=10&newspapersActive=false&newspapersSearch=false&offset=0" + "&otbRanking=false&pcAvailability=false&qExclude=&qInclude=&rapido=false&refEntryActive=false&rtaLinks=true" + "&scope=MyInst_and_CI&searchInFulltextUserSelection=false&skipDelivery=Y&sort=rank&tab=Everything" + "&vid=01PITT_INST:01PITT_INST" ) -STUDY_ROOMS_URL = "https://pitt.libcal.com/spaces/bookings/search?lid=917&gid=1558&eid=0&seat=0&d=1&customDate=&q=&daily=0&draw=1&order%5B0%5D%5Bcolumn%5D=1&order%5B0%5D%5Bdir%5D=asc&start=0&length=25&search%5Bvalue%5D=&_=1717907260661" +STUDY_ROOMS_URL = ( + "https://pitt.libcal.com/spaces/bookings/search" + "?lid=917&gid=1558&eid=0&seat=0&d=1&customDate=&q=&daily=0&draw=1&order%5B0%5D%5Bcolumn%5D=1&order%5B0%5D%5Bdir%5D=asc" + "&start=0&length=25&search%5Bvalue%5D=&_=1717907260661" +) QUERY_START = "&q=any,contains," @@ -148,7 +150,7 @@ def hillman_total_reserved() -> dict[str, int]: def reserved_hillman_times() -> list[dict[str, str | list[str]]]: - """Returns a list of dictionaries of reserved rooms of the Hillman with their respective times""" + """Returns a list of dictionaries of reserved rooms in Hillman with their respective times""" resp = requests.get(STUDY_ROOMS_URL) resp = resp.json() data = resp["data"] @@ -156,7 +158,7 @@ def reserved_hillman_times() -> list[dict[str, str | list[str]]]: if data is None: return [] - # Note: there can be multiple reservations in the same room, hence why we must use a list of maps, and cannot just use a singular map + # Note: there can be multiple reservations in the same room, so we must use a list of maps and not a singular map bookings = [ { "Room": reservation["itemName"], diff --git a/pittapi/shuttle.py b/pittapi/shuttle.py index e5fa05d..54943fa 100644 --- a/pittapi/shuttle.py +++ b/pittapi/shuttle.py @@ -20,44 +20,39 @@ import requests from typing import Any + +API_KEY = "8882812681" +VEHICLE_POINTS_URL = "http://www.pittshuttle.com/Services/JSONPRelay.svc/GetMapVehiclePoints" +ARRIVAL_TIMES_URL = "http://www.pittshuttle.com/Services/JSONPRelay.svc/GetRouteStopArrivals" +STOP_ESTIMATES_URL = "http://www.pittshuttle.com/Services/JSONPRelay.svc/GetVehicleRouteStopEstimates" +ROUTES_URL = "http://www.pittshuttle.com/Services/JSONPRelay.svc/GetRoutesForMap" + sess = requests.session() -def get_map_vehicle_points(api_key: str = "8882812681") -> dict[str, Any]: +def get_map_vehicle_points(api_key: str = API_KEY) -> dict[str, Any]: """Return the map location for all active vehicles.""" payload = {"ApiKey": api_key} - response = sess.get( - "http://www.pittshuttle.com/Services/JSONPRelay.svc/GetMapVehiclePoints", - params=payload, - ) + response = sess.get(VEHICLE_POINTS_URL, params=payload) return response.json() -def get_route_stop_arrivals(api_key: str = "8882812681", times_per_stop: int = 1) -> dict[str, Any]: +def get_route_stop_arrivals(api_key: str = API_KEY, times_per_stop: int = 1) -> dict[str, Any]: """Return stop arrival times for all vehicles.""" payload = {"ApiKey": api_key, "TimesPerStopString": times_per_stop} - response = sess.get( - "http://www.pittshuttle.com/Services/JSONPRelay.svc/GetRouteStopArrivals", - params=payload, - ) + response = sess.get(ARRIVAL_TIMES_URL, params=payload) return response.json() def get_vehicle_route_stop_estimates(vehicle_id: str, quantity: int = 2) -> dict[str, Any]: """Return {quantity} stop estimates for all active vehicles.""" payload = {"vehicleIdStrings": vehicle_id, "quantity": str(quantity)} - response = sess.get( - "http://www.pittshuttle.com/Services/JSONPRelay.svc/GetVehicleRouteStopEstimates", - params=payload, - ) + response = sess.get(STOP_ESTIMATES_URL, params=payload) return response.json() -def get_routes(api_key: str = "8882812681") -> dict[str, Any]: +def get_routes(api_key: str = API_KEY) -> dict[str, Any]: """Return the routes with Vehicle Route Name, Vehicle ID, and all stops, etc.""" payload = {"ApiKey": api_key} - response = sess.get( - "http://www.pittshuttle.com/Services/JSONPRelay.svc/GetRoutesForMap", - params=payload, - ) + response = sess.get(ROUTES_URL, params=payload) return response.json() diff --git a/tests/course_test.py b/tests/course_test.py index 7743713..d96ef99 100644 --- a/tests/course_test.py +++ b/tests/course_test.py @@ -22,17 +22,7 @@ from pittapi import course -from pittapi.course import ( - Attribute, - Component, - Course, - CourseDetails, - Instructor, - Meeting, - Section, - SectionDetails, - Subject, -) +from pittapi.course import Attribute, Course, CourseDetails, Instructor, Meeting, Section, SectionDetails, Subject from tests.mocks.course_mocks import ( mocked_subject_data, diff --git a/tests/dining_test.py b/tests/dining_test.py index e6b96c4..9c945b4 100644 --- a/tests/dining_test.py +++ b/tests/dining_test.py @@ -45,7 +45,7 @@ def __init__(self, *args, **kwargs): def test_get_locations(self): responses.add( responses.GET, - "https://api.dineoncampus.com/v1/locations/status?site_id=5e6fcc641ca48e0cacd93b04&platform=", + dining.LOCATIONS_URL, json=self.dining_locations_data, status=200, ) @@ -55,7 +55,7 @@ def test_get_locations(self): def test_get_location_hours(self): responses.add( responses.GET, - "https://api.dineoncampus.com/v1/locations/weekly_schedule?site_id=5e6fcc641ca48e0cacd93b04&date=%222024-04-12%22", + dining.HOURS_URL.format(date_str="2024-04-12"), json=self.dining_schedule_data, status=200, ) @@ -69,19 +69,19 @@ def test_get_location_hours(self): def test_get_location_menu(self): responses.add( responses.GET, - "https://api.dineoncampus.com/v1/locations/status?site_id=5e6fcc641ca48e0cacd93b04&platform=", + dining.LOCATIONS_URL, json=self.dining_locations_data, status=200, ) responses.add( responses.GET, - "https://api.dineoncampus.com/v1/location/610b1f78e82971147c9f8ba5/periods?platform=0&date=24-04-12", + dining.PERIODS_URL.format(location_id="610b1f78e82971147c9f8ba5", date_str="24-04-12"), json=self.dining_menu_data, status=200, ) responses.add( responses.GET, - "https://api.dineoncampus.com/v1/location/610b1f78e82971147c9f8ba5/periods/659daa4d351d53068df67835?platform=0&date=24-04-12", + dining.MENU_URL.format("610b1f78e82971147c9f8ba5", period_id="659daa4d351d53068df67835", date_str="24-04-12"), json=self.dining_menu_data, status=200, ) diff --git a/tests/laundry_test.py b/tests/laundry_test.py index 28fe61d..e708c75 100644 --- a/tests/laundry_test.py +++ b/tests/laundry_test.py @@ -39,8 +39,7 @@ def __init__(self, *args, **kwargs): def test_get_status_simple(self): responses.add( responses.GET, - "https://www.laundryview.com/api/currentRoomData?school_desc_key=197&location=" - + laundry.LOCATION_LOOKUP[TEST_BUILDING], + laundry.BASE_URL.format(location=laundry.LOCATION_LOOKUP[TEST_BUILDING]), json=self.mock_data, status=200, ) @@ -56,8 +55,7 @@ def test_get_status_simple(self): def test_get_status_detailed(self): responses.add( responses.GET, - "https://www.laundryview.com/api/currentRoomData?school_desc_key=197&location=" - + laundry.LOCATION_LOOKUP[TEST_BUILDING], + laundry.BASE_URL.format(location=laundry.LOCATION_LOOKUP[TEST_BUILDING]), json=self.mock_data, status=200, ) diff --git a/tests/mocks/course_mocks.py b/tests/mocks/course_mocks.py index 9e0d4be..cd0f486 100644 --- a/tests/mocks/course_mocks.py +++ b/tests/mocks/course_mocks.py @@ -13,7 +13,14 @@ mocked_course_info_data = { "course_details": { - "descrlong": "This is a first course in computer science programming. It is recommended for those students intending to major in computer science who do not have the required background for cs 0401. It may also be of interest to students majoring in one of the social sciences or humanities. The focus of the course is on problem analysis and the development of algorithms and computer programs in a modern high-level language.", + "descrlong": ( + "This is a first course in computer science programming. " + "It is recommended for those students intending to major in computer science who do not have the required " + "background for cs 0401. " + "It may also be of interest to students majoring in one of the social sciences or humanities. " + "The focus of the course is on problem analysis and the development of algorithms and computer programs in a " + "modern high-level language." + ), "units_minimum": 3, "units_maximum": 3, "units_inc": 1, @@ -179,7 +186,11 @@ "drop_consent": "", "enroll_requirements": "", "requirement_desig": "", - "class_attributes": "DSAS Algebra General Ed. Requirement \rDSAS Quant.-Formal Reason General Ed. Requirement \rAsian Studies", + "class_attributes": ( + "DSAS Algebra General Ed. Requirement \r" + "DSAS Quant.-Formal Reason General Ed. Requirement \r" + "Asian Studies" + ), }, "class_availability": { "class_capacity": "28", @@ -192,7 +203,14 @@ "is_combined": False, "notes": {"class_notes": "", "subject_notes": ""}, "catalog_descr": { - "crse_catalog_description": "This is a first course in computer science programming. It is recommended for those students intending to major in computer science who do not have the required background for cs 0401. It may also be of interest to students majoring in one of the social sciences or humanities. The focus of the course is on problem analysis and the development of algorithms and computer programs in a modern high-level language." + "crse_catalog_description": ( + "This is a first course in computer science programming. " + "It is recommended for those students intending to major in computer science who do not have the required " + "background for cs 0401. " + "It may also be of interest to students majoring in one of the social sciences or humanities. " + "The focus of the course is on problem analysis and the development of algorithms and computer programs in a " + "modern high-level language." + ) }, "materials": { "txb_none": "N", @@ -241,7 +259,10 @@ "messages": { "shareLink": "Copy link to share the class with friends.", "shareSocial": "Or share on social media networks.", - "reserveInfo": "Seats in this class have been reserved for students for the specified programs, majors or groups listed below. Reserved seats are subject to change without notice.", + "reserveInfo": ( + "Seats in this class have been reserved for students for the specified programs, majors or groups listed below. " + "Reserved seats are subject to change without notice." + ), "noMeetingInfo": "No meeting info found", }, } diff --git a/tests/people_test.py b/tests/people_test.py index 45621fe..f34ac84 100644 --- a/tests/people_test.py +++ b/tests/people_test.py @@ -19,97 +19,28 @@ import unittest import responses -from pittapi import people -RAMIREZ_TEST_DATA = """ -
-
-
-
-
- - Ramirez, John C - -
-
-
- Employee Information - Faculty, SCI-Computer Science -
-
- Emailramirez@cs.pitt.edu -
-
Office Phone(412) 624-8441
-
Office Mailing Address6125 Sennott Square -
- -
-
- -
- - """ +from pathlib import Path + +from pittapi import people -TOO_MANY_TEST_DATA = """ -
-
- Too many people matched your criteria. Please try searching by username, phone, email, or by enclosing your - search in quotation marks. -
- -
- - """ -NONE_FOUND_TEST_DATA = """ -
- -
- - """ +SAMPLE_PATH = Path() / "tests" / "samples" class PeopleTest(unittest.TestCase): + def __init__(self, *args, **kwargs): + unittest.TestCase.__init__(self, *args, **kwargs) + with open(SAMPLE_PATH / "people_ramirez_mock_response.html") as f: + self.ramirez_test_data = f.read() + with open(SAMPLE_PATH / "people_too_many_mock_response.html") as f: + self.too_many_test_data = f.read() + with open(SAMPLE_PATH / "people_none_mock_response.html") as f: + self.none_found_test_data = f.read() + @responses.activate def test_people_get_person(self): - responses.add(responses.POST, people.PEOPLE_SEARCH_URL, body=RAMIREZ_TEST_DATA, status=200) + responses.add(responses.POST, people.PEOPLE_SEARCH_URL, body=self.ramirez_test_data, status=200) ans = people.get_person("John C Ramirez") self.assertIsInstance(ans, list) self.assertTrue(ans[0]["name"] == "Ramirez, John C") @@ -117,24 +48,14 @@ def test_people_get_person(self): @responses.activate def test_people_get_person_too_many(self): - responses.add( - responses.POST, - people.PEOPLE_SEARCH_URL, - body=TOO_MANY_TEST_DATA, - status=200, - ) + responses.add(responses.POST, people.PEOPLE_SEARCH_URL, body=self.too_many_test_data, status=200) ans = people.get_person("Smith") self.assertIsInstance(ans, list) self.assertEqual(ans, [{"ERROR": "Too many people matched your criteria."}]) @responses.activate def test_people_get_person_none(self): - responses.add( - responses.POST, - people.PEOPLE_SEARCH_URL, - body=NONE_FOUND_TEST_DATA, - status=200, - ) + responses.add(responses.POST, people.PEOPLE_SEARCH_URL, body=self.none_found_test_data, status=200) ans = people.get_person("Lebron Iverson James Jordan Kobe") self.assertIsInstance(ans, list) self.assertEqual(ans, [{"ERROR": "No one found."}]) diff --git a/tests/samples/people_none_mock_response.html b/tests/samples/people_none_mock_response.html new file mode 100644 index 0000000..8e2ba6c --- /dev/null +++ b/tests/samples/people_none_mock_response.html @@ -0,0 +1,21 @@ +
+ +
+ diff --git a/tests/samples/people_ramirez_mock_response.html b/tests/samples/people_ramirez_mock_response.html new file mode 100644 index 0000000..3a9b602 --- /dev/null +++ b/tests/samples/people_ramirez_mock_response.html @@ -0,0 +1,43 @@ +
+
+
+
+
+ + Ramirez, John C + +
+
+
+ Employee Information + Faculty, SCI-Computer Science +
+
+ Emailramirez@cs.pitt.edu +
+
Office Phone(412) 624-8441
+
Office Mailing Address6125 Sennott Square +
+ +
+
+ +
+ diff --git a/tests/samples/people_too_many_mock_response.html b/tests/samples/people_too_many_mock_response.html new file mode 100644 index 0000000..89b290c --- /dev/null +++ b/tests/samples/people_too_many_mock_response.html @@ -0,0 +1,11 @@ +
+
+ Too many people matched your criteria. Please try searching by username, phone, email, or by enclosing your + search in quotation marks. +
+ +
+ diff --git a/tests/shuttle_test.py b/tests/shuttle_test.py index e8a0855..e116a33 100644 --- a/tests/shuttle_test.py +++ b/tests/shuttle_test.py @@ -28,7 +28,7 @@ class ShuttleTest(unittest.TestCase): def test_get_map_vehicle_points(self): responses.add( method=responses.GET, - url="http://www.pittshuttle.com/Services/JSONPRelay.svc/GetMapVehiclePoints?ApiKey=8882812681", + url=f"{shuttle.VEHICLE_POINTS_URL}?ApiKey={shuttle.API_KEY}", json=[{}, {}, {}], status=200, ) @@ -38,7 +38,7 @@ def test_get_map_vehicle_points(self): def test_get_route_stop_arrivals(self): responses.add( method=responses.GET, - url="http://www.pittshuttle.com/Services/JSONPRelay.svc/GetRouteStopArrivals?ApiKey=8882812681&TimesPerStopString=1", + url=f"{shuttle.STOP_ESTIMATES_URL}?ApiKey={shuttle.API_KEY}&TimesPerStopString=1", json=[{}, {}, {}], status=200, ) @@ -48,11 +48,11 @@ def test_get_route_stop_arrivals(self): def test_vehicle_route_stop_estimates(self): responses.add( method=responses.GET, - url="http://www.pittshuttle.com/Services/JSONPRelay.svc/GetVehicleRouteStopEstimates?vehicleIdStrings=25&quantity=4", + url=f"{shuttle.STOP_ESTIMATES_URL}?vehicleIdStrings=25&quantity=4", json=[{"Estimates": [{}, {}, {}, {}]}], status=200, ) - stop_estimates = shuttle.get_vehicle_route_stop_estimates(25, 4) + stop_estimates = shuttle.get_vehicle_route_stop_estimates("25", 4) self.assertIsInstance(stop_estimates, list) self.assertEqual(len(stop_estimates[0]["Estimates"]), 4) @@ -60,7 +60,7 @@ def test_vehicle_route_stop_estimates(self): def test_get_routes(self): responses.add( method=responses.GET, - url="http://www.pittshuttle.com/Services/JSONPRelay.svc/GetRoutesForMap?ApiKey=8882812681", + url=f"{shuttle.ROUTES_URL}?ApiKey={shuttle.API_KEY}", json=[{}, {}, {}], status=200, ) From fb24e3a078f18c2b6e78b12249c7b65c8c7a5e80 Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sun, 16 Jun 2024 03:42:28 -0700 Subject: [PATCH 2/3] Fix flake8 complexity errors --- pittapi/course.py | 57 ++++++++++++++++++++++------------------------- pittapi/dining.py | 26 +++++++++------------ 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/pittapi/course.py b/pittapi/course.py index a2cfa18..9f8e84c 100644 --- a/pittapi/course.py +++ b/pittapi/course.py @@ -168,27 +168,25 @@ def get_course_details(term: str | int, subject: str, course: str | int) -> Cour components = None if "components" in json_response and len(json_response["components"]) != 0: - components = [] - for component in json_response["components"]: - components.append( - Component( - component=component["descr"], - required=True if component["optional"] == "N" else False, - ) + components = [ + Component( + component=component["descr"], + required=True if component["optional"] == "N" else False, ) + for component in json_response["components"] + ] attributes = None if "attributes" in json_response and len(json_response["attributes"]) != 0: - attributes = [] - for attribute in json_response["attributes"]: - attributes.append( - Attribute( - attribute=attribute["crse_attribute"], - attribute_description=attribute["crse_attribute_descr"], - value=attribute["crse_attribute_value"], - value_description=attribute["crse_attribute_value_descr"], - ) + attributes = [ + Attribute( + attribute=attribute["crse_attribute"], + attribute_description=attribute["crse_attribute_descr"], + value=attribute["crse_attribute_value"], + value_description=attribute["crse_attribute_value_descr"], ) + for attribute in json_response["attributes"] + ] sections = [] for section in json_response_details["sections"]: @@ -200,24 +198,23 @@ def get_course_details(term: str | int, subject: str, course: str | int) -> Cour instructors = None if len(section["instructors"]) != 0 and section["instructors"][0] != "To be Announced": - instructors = [] - for instructor in section["instructors"]: - instructors.append(Instructor(name=instructor["name"], email=instructor["email"])) + instructors = [ + Instructor(name=instructor["name"], email=instructor["email"]) for instructor in section["instructors"] + ] meetings = None if len(section["meetings"]) != 0: - meetings = [] - for meeting in section["meetings"]: - meetings.append( - Meeting( - days=meeting["days"], - start_time=meeting["start_time"], - end_time=meeting["end_time"], - start_date=meeting["start_dt"], - end_date=meeting["end_dt"], - instructors=[Instructor(name=meeting["instructor"])], - ) + meetings = [ + Meeting( + days=meeting["days"], + start_time=meeting["start_time"], + end_time=meeting["end_time"], + start_date=meeting["start_dt"], + end_date=meeting["end_dt"], + instructors=[Instructor(name=meeting["instructor"])], ) + for meeting in section["meetings"] + ] sections.append( Section( diff --git a/pittapi/dining.py b/pittapi/dining.py index 982035c..910dee4 100644 --- a/pittapi/dining.py +++ b/pittapi/dining.py @@ -101,22 +101,18 @@ def get_location_hours(location_name: str, date: datetime) -> dict[str, Any]: locations = json.loads(resp.content)["the_locations"] - hours = {} - if location_name is None: - for location in locations: - for day in location["week"]: - if day["date"] == date_str: - hours[location["name"]] = day["hours"] - else: - for location in locations: - if location["name"].upper() == location_name.upper(): - for day in location["week"]: - if day["date"] == date_str: - hours[location["name"]] = day["hours"] - break - - return hours + hours = { + location["name"]: day["hours"] for location in locations for day in location["week"] if day["date"] == date_str + } + return hours + + for location in locations: + if location["name"].upper() == location_name.upper(): + hours = {location["name"]: day["hours"] for day in location["week"] if day["date"] == date_str} + return hours + + return {} def get_location_menu(location: str, date: datetime, period_name: str): From 1f24c04284c9d731ea558b96dc7cfed4ad5fae9e Mon Sep 17 00:00:00 2001 From: Tianyi Zheng Date: Sun, 16 Jun 2024 03:49:50 -0700 Subject: [PATCH 3/3] Fix typos in tests --- tests/dining_test.py | 6 +++++- tests/shuttle_test.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/dining_test.py b/tests/dining_test.py index 9c945b4..80b9dbf 100644 --- a/tests/dining_test.py +++ b/tests/dining_test.py @@ -81,7 +81,11 @@ def test_get_location_menu(self): ) responses.add( responses.GET, - dining.MENU_URL.format("610b1f78e82971147c9f8ba5", period_id="659daa4d351d53068df67835", date_str="24-04-12"), + dining.MENU_URL.format( + location_id="610b1f78e82971147c9f8ba5", + period_id="659daa4d351d53068df67835", + date_str="24-04-12", + ), json=self.dining_menu_data, status=200, ) diff --git a/tests/shuttle_test.py b/tests/shuttle_test.py index e116a33..a40723e 100644 --- a/tests/shuttle_test.py +++ b/tests/shuttle_test.py @@ -38,7 +38,7 @@ def test_get_map_vehicle_points(self): def test_get_route_stop_arrivals(self): responses.add( method=responses.GET, - url=f"{shuttle.STOP_ESTIMATES_URL}?ApiKey={shuttle.API_KEY}&TimesPerStopString=1", + url=f"{shuttle.ARRIVAL_TIMES_URL}?ApiKey={shuttle.API_KEY}&TimesPerStopString=1", json=[{}, {}, {}], status=200, )