-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Gym module created * Update gym.py * Updated Gym Module and created Unit tests for them * updated issued for the GYM Module * updated variable name * updated gym module * udpated unit testing for Gym module * Apply suggestions from code review * Apply suggestions from code review * Fix from_text return type to support 3.9 and 3.10 --------- Co-authored-by: Tianyi Zheng <[email protected]>
- Loading branch information
1 parent
61f69b6
commit 966b603
Showing
3 changed files
with
269 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
""" | ||
The Pitt API, to access workable data of the University of Pittsburgh | ||
Copyright (C) 2015 Ritwik Gupta | ||
This program is free software; you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation; either version 2 of the License, or | ||
(at your option) any later version. | ||
This program is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
You should have received a copy of the GNU General Public License along | ||
with this program; if not, write to the Free Software Foundation, Inc., | ||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
""" | ||
|
||
from __future__ import annotations | ||
|
||
from bs4 import BeautifulSoup | ||
import requests | ||
from typing import NamedTuple | ||
|
||
GYM_URL = "https://connect2concepts.com/connect2/?type=bar&key=17c2cbcb-ec92-4178-a5f5-c4860330aea0" | ||
|
||
GYM_NAMES = [ | ||
"Baierl Rec Center", | ||
"Bellefield Hall: Fitness Center & Weight Room", | ||
"Bellefield Hall: Court & Dance Studio", | ||
"Trees Hall: Fitness Center", | ||
"Trees Hall: Courts", | ||
"Trees Hall: Racquetball Courts & Multipurpose Room", | ||
"William Pitt Union", | ||
"Pitt Sports Dome", | ||
] | ||
|
||
|
||
class Gym(NamedTuple): | ||
name: str | ||
date: str | ||
count: int | ||
percentage: int | ||
|
||
@classmethod | ||
def from_text(cls, text: str) -> Gym: | ||
info = text.split("|") | ||
name = info[0] | ||
if len(info) < 4: | ||
return cls(name=name, date=None, count=None, percentage=None) | ||
count = int(info[2][12:]) | ||
date = info[3][9:] | ||
try: | ||
percentage = int(info[4].rstrip("%")) | ||
except ValueError: | ||
percentage = 0 | ||
|
||
return cls(name=name, date=date, count=count, percentage=percentage) | ||
|
||
|
||
def get_all_gyms_info() -> list[Gym]: | ||
"""Fetches list of Gym named tuples with all gym information""" | ||
# Was getting a Mod Security Error | ||
# Fix: https://stackoverflow.com/questions/61968521/python-web-scraping-request-errormod-security | ||
headers = { | ||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:55.0) Gecko/20100101 Firefox/55.0", | ||
} | ||
|
||
page = requests.get(GYM_URL, headers=headers) | ||
soup = BeautifulSoup(page.text, "html.parser") | ||
gym_info_list = soup.find_all("div", class_="barChart") | ||
|
||
# Iterate through list and add to dictionary | ||
gyms = [Gym.from_text(gym.get_text("|", strip=True)) for gym in gym_info_list] | ||
return gyms | ||
|
||
|
||
def get_gym_info(gym_name: str) -> Gym | None: | ||
"""Fetches the information of a singular gym as a tuple""" | ||
info = get_all_gyms_info() | ||
if gym_name in GYM_NAMES: | ||
for gym in info: | ||
if gym.name == gym_name and gym.date and gym.count and gym.percentage: | ||
return gym | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import unittest | ||
import responses | ||
from pittapi import gym | ||
from tests.mocks.gym_mocks import mock_gym_html | ||
|
||
|
||
class GymTest(unittest.TestCase): | ||
def __init__(self, *args, **kwargs): | ||
unittest.TestCase.__init__(self, *args, **kwargs) | ||
|
||
@responses.activate | ||
def test_fetch_gym_info(self): | ||
|
||
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200) | ||
|
||
gym_info = gym.get_all_gyms_info() | ||
expected_info = [ | ||
gym.Gym(name="Baierl Rec Center", date="07/09/2024 09:05 AM", count=100, percentage=50), | ||
gym.Gym(name="Bellefield Hall: Fitness Center & Weight Room", date="07/09/2024 09:05 AM", count=50, percentage=0), | ||
gym.Gym(name="Bellefield Hall: Court & Dance Studio", date=None, count=None, percentage=None), | ||
gym.Gym(name="Trees Hall: Fitness Center", date="07/09/2024 09:05 AM", count=70, percentage=58), | ||
gym.Gym(name="Trees Hall: Courts", date="07/09/2024 09:05 AM", count=20, percentage=33), | ||
gym.Gym( | ||
name="Trees Hall: Racquetball Courts & Multipurpose Room", | ||
date="07/09/2024 09:05 AM", | ||
count=10, | ||
percentage=25, | ||
), | ||
gym.Gym(name="William Pitt Union", date="07/09/2024 09:05 AM", count=25, percentage=25), | ||
gym.Gym(name="Pitt Sports Dome", date="07/09/2024 09:05 AM", count=15, percentage=20), | ||
] | ||
|
||
self.assertEqual(gym_info, expected_info) | ||
|
||
@responses.activate | ||
def test_get_gym_info(self): | ||
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200) | ||
|
||
gym_info = gym.get_gym_info("Baierl Rec Center") | ||
expected_info = gym.Gym(name="Baierl Rec Center", date="07/09/2024 09:05 AM", count=100, percentage=50) | ||
self.assertEqual(gym_info, expected_info) | ||
|
||
@responses.activate | ||
def test_invalid_gym_name(self): | ||
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200) | ||
|
||
gym_info = gym.get_gym_info("Invalid Gym Name") | ||
self.assertIsNone(gym_info) | ||
|
||
@responses.activate | ||
def test_valid_gym_name_not_all_info(self): | ||
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200) | ||
|
||
gym_info = gym.get_gym_info("Bellefield Hall: Court & Dance Studio") | ||
self.assertIsNone(gym_info) | ||
|
||
@responses.activate | ||
def test_percentage_value_error(self): | ||
responses.add(responses.GET, gym.GYM_URL, body=mock_gym_html, status=200) | ||
|
||
gym_info = gym.get_gym_info("Bellefield Hall: Fitness Center & Weight Roomo") | ||
self.assertIsNone(gym_info) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
mock_gym_html = """ | ||
<div class="barChart" style="width:90%;"> | ||
Baierl Rec Center | ||
<br> | ||
<span style="color:green">(Open)</span> | ||
<br> | ||
Last Count: 100 | ||
<br> | ||
Updated: 07/09/2024 09:05 AM | ||
<div class="barChart_row" data-value="50.0"> | ||
<span class="barChart__value">50%</span> | ||
<span class="barChart__bar" style=" background: rgb(239, 239, 239);"> | ||
<span class="barChart__barFill" style="background: #2A5B84;"></span> | ||
</span> | ||
</div> | ||
</div> | ||
<div class="barChart" style="width:90%;"> | ||
Bellefield Hall: Fitness Center & Weight Room | ||
<br> | ||
<span style="color:green">(Open)</span> | ||
<br> | ||
Last Count: 50 | ||
<br> | ||
Updated: 07/09/2024 09:05 AM | ||
<div class="barChart_row" data-value="33.0"> | ||
<span class="barChart__value">non%</span> | ||
<span class="barChart__bar" style=" background: rgb(239, 239, 239);"> | ||
<span class="barChart__barFill" style="background: #2A5B84;"></span> | ||
</span> | ||
</div> | ||
</div> | ||
<div class="barChart" style="width:90%;"> | ||
Bellefield Hall: Court & Dance Studio | ||
<br> | ||
<span style="color:green">(Open)</span> | ||
<br> | ||
<!-- Missing Last Count --> | ||
<!-- Missing Updated Date --> | ||
<div class="barChart_row" data-value="38.0"> | ||
<span class="barChart__value">38%</span> | ||
<span class="barChart__bar" style=" background: rgb(239, 239, 239);"> | ||
<span class="barChart__barFill" style="background: #2A5B84;"></span> | ||
</span> | ||
</div> | ||
</div> | ||
<div class="barChart" style="width:90%;"> | ||
Trees Hall: Fitness Center | ||
<br> | ||
<span style="color:green">(Open)</span> | ||
<br> | ||
Last Count: 70 | ||
<br> | ||
Updated: 07/09/2024 09:05 AM | ||
<div class="barChart_row" data-value="58.0"> | ||
<span class="barChart__value">58%</span> | ||
<span class="barChart__bar" style=" background: rgb(239, 239, 239);"> | ||
<span class="barChart__barFill" style="background: #2A5B84;"></span> | ||
</span> | ||
</div> | ||
</div> | ||
<div class="barChart" style="width:90%;"> | ||
Trees Hall: Courts | ||
<br> | ||
<span style="color:green">(Open)</span> | ||
<br> | ||
Last Count: 20 | ||
<br> | ||
Updated: 07/09/2024 09:05 AM | ||
<div class="barChart_row" data-value="33.0"> | ||
<span class="barChart__value">33%</span> | ||
<span class="barChart__bar" style=" background: rgb(239, 239, 239);"> | ||
<span class="barChart__barFill" style="background: #2A5B84;"></span> | ||
</span> | ||
</div> | ||
</div> | ||
<div class="barChart" style="width:90%;"> | ||
Trees Hall: Racquetball Courts & Multipurpose Room | ||
<br> | ||
<span style="color:green">(Open)</span> | ||
<br> | ||
Last Count: 10 | ||
<br> | ||
Updated: 07/09/2024 09:05 AM | ||
<div class="barChart_row" data-value="25.0"> | ||
<span class="barChart__value">25%</span> | ||
<span class="barChart__bar" style=" background: rgb(239, 239, 239);"> | ||
<span class="barChart__barFill" style="background: #2A5B84;"></span> | ||
</span> | ||
</div> | ||
</div> | ||
<div class="barChart" style="width:90%;"> | ||
William Pitt Union | ||
<br> | ||
<span style="color:green">(Open)</span> | ||
<br> | ||
Last Count: 25 | ||
<br> | ||
Updated: 07/09/2024 09:05 AM | ||
<div class="barChart_row" data-value="25.0"> | ||
<span class="barChart__value">25%</span> | ||
<span class="barChart__bar" style=" background: rgb(239, 239, 239);"> | ||
<span class="barChart__barFill" style="background: #2A5B84;"></span> | ||
</span> | ||
</div> | ||
</div> | ||
<div class="barChart" style="width:90%;"> | ||
Pitt Sports Dome | ||
<br> | ||
<span style="color:green">(Open)</span> | ||
<br> | ||
Last Count: 15 | ||
<br> | ||
Updated: 07/09/2024 09:05 AM | ||
<div class="barChart_row" data-value="20.0"> | ||
<span class="barChart__value">20%</span> | ||
<span class="barChart__bar" style=" background: rgb(239, 239, 239);"> | ||
<span class="barChart__barFill" style="background: #2A5B84;"></span> | ||
</span> | ||
</div> | ||
</div> | ||
""" |