Skip to content

Commit

Permalink
Added Study Room Functions to to Library Module (#177)
Browse files Browse the repository at this point in the history
* Added a couple Hillman library features

Tells the user how many reservations are in the Hillman library, and also tells the user what rooms and times are reserved in the Hillman library.

* fixed a bug with reservations pulling; moved reservations functions to library module

* revert lab back

* revert lab

* Update lab.py

* revert lab again

* Ran black to format correctly

* Update pittapi/course.py

Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>

* Delete black

* Update course_test.py

* Update dining_test.py

* Update library_test.py

* Update course_mocks.py

* Update people_test.py

* Update sports_test.py

* Update status_test.py

* Update textbook_test.py

* Update textbook_test.py

* Update course_mocks.py

* Update dining_test.py

* Update course_test.py

* Update textbook_test.py

* Update course_mocks.py

* Fix black errors

* Update library.py

Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>

* Added type hints for new functions

* Polished up formatting in library file

- Added space at end of file
- Enforced 2 spaces between functions

* Added unit tests for library module update

I added unit tests for both of the new functions and updated the sample path variable.

For some reason I was having issues with the original sample path, so I updated it so the testing works good for all functions in the library_test file now.

* changed spacing for a line

* Update tests/library_test.py

Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>

* Update tests/library_test.py

Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>

* Update tests/library_test.py

Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>

* Update type hints

---------

Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>
  • Loading branch information
ghosteau and tianyizheng02 authored Jun 13, 2024
1 parent f991030 commit 5f7ad48
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 33 deletions.
7 changes: 6 additions & 1 deletion pittapi/course.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,12 @@ def get_course_details(term: str | int, subject: str, course: str | int) -> Cour
)

return CourseDetails(
course=Course(subject_code=subject, course_number=course, course_id=internal_course_id, course_title=course_title),
course=Course(
subject_code=subject,
course_number=course,
course_id=internal_course_id,
course_title=course_title,
),
course_description=course_description,
credit_range=credit_range,
requisites=requisites,
Expand Down
10 changes: 9 additions & 1 deletion pittapi/lab.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,13 @@ def get_status():
if key["name"] in labs:
total = key["total"]
in_use = key["active"]
statuses.append({"location": key["name"], "isOpen": labs[key["name"]], "total": total, "in_use": in_use})
statuses.append(
{
"location": key["name"],
"isOpen": labs[key["name"]],
"total": total,
"in_use": in_use,
}
)

return statuses
38 changes: 38 additions & 0 deletions pittapi/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""

from __future__ import annotations

import requests
from html.parser import HTMLParser
from typing import Any
Expand All @@ -32,6 +34,9 @@
"&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"


QUERY_START = "&q=any,contains,"

sess = requests.session()
Expand Down Expand Up @@ -127,3 +132,36 @@ def _extract_facets(facet_fields: list[dict[str, Any]]) -> dict[str, list[dict[s
facets[facet["display_name"]].append({"value": count["value"], "count": count["count"]})

return facets


def hillman_total_reserved() -> dict[str, int]:
"""Returns a simple count dictionary of the total amount of reserved rooms appointments"""
count = {}
resp = requests.get(STUDY_ROOMS_URL)
resp = resp.json()
# Total records is kept track of by default in the JSON
total_records = resp["recordsTotal"]

# Note: this must align with the amount of entries in reserved times function; renamed for further clarification
count["Total Hillman Reservations"] = total_records
return count


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"""
resp = requests.get(STUDY_ROOMS_URL)
resp = resp.json()
data = resp["data"]

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
bookings = [
{
"Room": reservation["itemName"],
"Reserved": [reservation["from"], reservation["to"]],
}
for reservation in data
]
return bookings
15 changes: 13 additions & 2 deletions tests/course_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,19 @@
from unittest.mock import MagicMock

from pittapi import course
from pittapi.course import Attribute, Course, CourseDetails, Instructor, Meeting, Section, SectionDetails, Subject

from pittapi.course import (
Attribute,
Component,
Course,
CourseDetails,
Instructor,
Meeting,
Section,
SectionDetails,
Subject,
)

from tests.mocks.course_mocks import (
mocked_subject_data,
mocked_courses_data,
Expand Down Expand Up @@ -112,7 +124,6 @@ def test_get_course_details(self):
self.assertEqual(test_attribute.attribute, "DSGE")
self.assertEqual(test_attribute.attribute_description, "*DSAS General Ed. Requirements")
self.assertEqual(test_attribute.value, "ALG")

self.assertEqual(test_attribute.value_description, "Algebra")
test_section = course_sections.sections[0]
self.assertTrue(isinstance(test_section, Section))
Expand Down
5 changes: 4 additions & 1 deletion tests/dining_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ def test_get_location_hours(self):
status=200,
)

self.assertIsInstance(dining.get_location_hours("The Eatery", datetime.datetime(2024, 4, 12)), dict)
self.assertIsInstance(
dining.get_location_hours("The Eatery", datetime.datetime(2024, 4, 12)),
dict,
)

@responses.activate
def test_get_location_menu(self):
Expand Down
54 changes: 52 additions & 2 deletions tests/library_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

from pittapi import library

SAMPLE_PATH = Path() / "tests" / "samples"
SAMPLE_PATH = Path(__file__).parent / "samples"


class LibraryTest(unittest.TestCase):
Expand All @@ -36,8 +36,58 @@ def __init__(self, *args, **kwargs):

@responses.activate
def test_get_documents(self):
responses.add(responses.GET, library.LIBRARY_URL + library.QUERY_START + "water", json=self.library_query, status=200)
responses.add(
responses.GET,
library.LIBRARY_URL + library.QUERY_START + "water",
json=self.library_query,
status=200,
)
query_result = library.get_documents("water")
self.assertIsInstance(query_result, dict)
self.assertEqual(query_result["pages"], 10)
self.assertEqual(len(query_result["docs"]), 10)


class StudyRoomTest(unittest.TestCase):
def __init__(self, *args, **kwargs):
unittest.TestCase.__init__(self, *args, **kwargs)
with (SAMPLE_PATH / "hillman_study_room_mock_response.json").open() as f:
self.hillman_query = json.load(f)

@responses.activate
def test_hillman_total_reserved(self):
responses.add(
responses.GET,
library.STUDY_ROOMS_URL,
json=self.hillman_query,
status=200,
)
self.assertEqual(library.hillman_total_reserved(), {"Total Hillman Reservations": 4})

@responses.activate
def test_reserved_hillman_times(self):
responses.add(
responses.GET,
library.STUDY_ROOMS_URL,
json=self.hillman_query,
status=200,
)
mock_answer = [
{
"Room": "408 HL (Max. 5 persons) (Enclosed Room)",
"Reserved": ["2024-06-12 17:30:00", "2024-06-12 20:30:00"],
},
{
"Room": "409 HL (Max. 5 persons) (Enclosed Room)",
"Reserved": ["2024-06-12 18:00:00", "2024-06-12 21:00:00"],
},
{
"Room": "303 HL (Max. 5 persons) (Enclosed Room)",
"Reserved": ["2024-06-12 18:30:00", "2024-06-12 21:30:00"],
},
{
"Room": "217 HL (Max. 10 persons) (Enclosed Room)",
"Reserved": ["2024-06-12 19:00:00", "2024-06-12 22:30:00"],
},
]
self.assertEqual(mock_answer, library.reserved_hillman_times())
38 changes: 31 additions & 7 deletions tests/mocks/course_mocks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
mocked_subject_data = {"subjects": [{"subject": "CS", "descr": "Computer Science"}]}

mocked_courses_data = {
"courses": [{"catalog_nbr": "0007", "descr": "INTRODUCTION TO COMPUTER PROGRAMMING", "crse_id": "105611"}]
"courses": [
{
"catalog_nbr": "0007",
"descr": "INTRODUCTION TO COMPUTER PROGRAMMING",
"crse_id": "105611",
}
]
}

mocked_courses_data_invalid = {}
Expand All @@ -17,7 +22,10 @@
"course_title": "INTRODUCTION TO COMPUTER PROGRAMMING",
"rqmnt_designtn": "",
"effdt": "2018-06-30",
"components": [{"descr": "Lecture", "optional": "N"}, {"descr": "Recitation", "optional": "N"}],
"components": [
{"descr": "Lecture", "optional": "N"},
{"descr": "Recitation", "optional": "N"},
],
"attributes": [
{
"crse_attribute": "DSGE",
Expand Down Expand Up @@ -45,11 +53,27 @@
"req_group": "",
"planner_message": "You have no active career, so you can not add this course to a planner.",
"open_terms": [
{"strm": "2224", "descr": "Spring Term 2021-2022", "default_term": False},
{"strm": "2227", "descr": "Summer Term 2021-2022", "default_term": False},
{"strm": "2231", "descr": "Fall Term 2022-2023", "default_term": True},
{
"strm": "2224",
"descr": "Spring Term 2021-2022",
"default_term": False,
},
{
"strm": "2227",
"descr": "Summer Term 2021-2022",
"default_term": False,
},
{
"strm": "2231",
"descr": "Fall Term 2022-2023",
"default_term": True,
},
],
"enrollable_terms": [
{"strm": "2224"},
{"strm": "2227"},
{"strm": "2231"},
],
"enrollable_terms": [{"strm": "2224"}, {"strm": "2227"}, {"strm": "2231"}],
}
],
}
Expand Down
17 changes: 12 additions & 5 deletions tests/people_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,24 +110,31 @@ class PeopleTest(unittest.TestCase):
@responses.activate
def test_people_get_person(self):
responses.add(responses.POST, people.PEOPLE_SEARCH_URL, body=RAMIREZ_TEST_DATA, status=200)

ans = people.get_person("John C Ramirez")
self.assertIsInstance(ans, list)
self.assertTrue(ans[0]["name"] == "Ramirez, John C")
self.assertTrue(ans[0]["office_phone"] == "(412) 624-8441")

@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=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=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."}])
55 changes: 55 additions & 0 deletions tests/samples/hillman_study_room_mock_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"data": [
{
"from": "2024-06-12 17:30:00",
"to": "2024-06-12 20:30:00",
"nickname": "H2P CLUB",
"itemId": 31053,
"itemName": "408 HL (Max. 5 persons) (Enclosed Room)",
"itemHasMoreInfo": true,
"categoryName": "Group Study Spaces",
"categoryUrl": "/spaces?lid=917&gid=1558",
"locationName": "Hillman Library",
"seatName": ""
},
{
"from": "2024-06-12 18:00:00",
"to": "2024-06-12 21:00:00",
"nickname": "ria",
"itemId": 31055,
"itemName": "409 HL (Max. 5 persons) (Enclosed Room)",
"itemHasMoreInfo": true,
"categoryName": "Group Study Spaces",
"categoryUrl": "/spaces?lid=917&gid=1558",
"locationName": "Hillman Library",
"seatName": ""
},
{
"from": "2024-06-12 18:30:00",
"to": "2024-06-12 21:30:00",
"nickname": "Leyla",
"itemId": 60964,
"itemName": "303 HL (Max. 5 persons) (Enclosed Room)",
"itemHasMoreInfo": true,
"categoryName": "Group Study Spaces",
"categoryUrl": "/spaces?lid=917&gid=1558",
"locationName": "Hillman Library",
"seatName": ""
},
{
"from": "2024-06-12 19:00:00",
"to": "2024-06-12 22:30:00",
"nickname": "John 117",
"itemId": 146782,
"itemName": "217 HL (Max. 10 persons) (Enclosed Room)",
"itemHasMoreInfo": true,
"categoryName": "Group Study Spaces",
"categoryUrl": "/spaces?lid=917&gid=1558",
"locationName": "Hillman Library",
"seatName": ""
}
],
"draw": 1,
"recordsTotal": 4,
"recordsFiltered": 4
}
17 changes: 14 additions & 3 deletions tests/sports_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ def setUp(self):
"id": "221",
"record": {
"items": [
{"description": "Overall Record", "type": "total", "summary": "11-21"},
{
"description": "Overall Record",
"type": "total",
"summary": "11-21",
},
{
"description": "Home Record",
"type": "home",
Expand All @@ -40,7 +44,10 @@ def setUp(self):
"date": "2022-03-08T19:00Z",
"competitions": [
{
"venue": {"fullName": "Barclays Center", "address": {"city": "Brooklyn", "state": "NY"}},
"venue": {
"fullName": "Barclays Center",
"address": {"city": "Brooklyn", "state": "NY"},
},
"competitors": [
{
"id": "221",
Expand Down Expand Up @@ -79,7 +86,11 @@ def setUp(self):
"name": "Pittsburgh",
"record": {
"items": [
{"description": "Overall Record", "type": "total", "summary": "10-2"},
{
"description": "Overall Record",
"type": "total",
"summary": "10-2",
},
{
"description": "Home Record",
"type": "home",
Expand Down
7 changes: 6 additions & 1 deletion tests/status_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,10 @@ def __init__(self, *args, **kwargs):

@responses.activate
def test_get_status(self):
responses.add(responses.GET, "https://status.pitt.edu/index.json", json=self.status_data, status=200)
responses.add(
responses.GET,
"https://status.pitt.edu/index.json",
json=self.status_data,
status=200,
)
self.assertIsInstance(status.get_status(), dict)
Loading

0 comments on commit 5f7ad48

Please sign in to comment.