-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Restore changes and tried data100 and data8 for classes #83
Merged
shaneknapp
merged 17 commits into
berkeley-dsep-infra:main
from
jlucarga:restore-changes
Aug 16, 2024
Merged
Changes from 13 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
26b08cc
Automatic commit by nbgitpuller
344227b
Automatic commit by nbgitpuller
8815b40
added copy of new query_courseid.py called refactor_testing_query_cou…
jlucarga 2e1fe47
updated README.md
jlucarga c1c6441
debugging refactor_query
jlucarga 173fb2e
updated Readme and adding interactive input args, but still missing m…
jlucarga a13fb28
commiting for retesting refactor_testing_query_courseid.py with data8…
jlucarga 4896f6b
trying if refactor_testing_query_courseid.py works for data8 and data…
jlucarga 3573595
first commit for modular changes
jlucarga 9eb924e
testing a new script structure
jlucarga cccf2ac
fixed issues for hardcoding data and Stat
jlucarga c4df253
deleting key
jlucarga bcec10b
Merge branch 'main' into restore-changes
shaneknapp 6fd64f7
addressing comments
jlucarga c45ac7e
updating code following pep8 not done yet
jlucarga abf1d78
updated the base url and added instructor and title course information
jlucarga 0c808c2
updated the base url and added instructor and title course informatio…
jlucarga File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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,76 @@ | ||
## Datahub Usage Analysis (refactor_testing_query_courseid.py) | ||
|
||
## Updates | ||
|
||
1. **Credential Management**: | ||
- Removed private credentials from the script. Users must now set (Windows) or export (Mac) their API user ID and key in the command line before running `query_courseid.py`. | ||
|
||
**Datahub Terminal**: | ||
```bash | ||
export APP_ID='your_app_id' | ||
export APP_KEY='your_app_key' | ||
``` | ||
**Verify Credentials From Terminal**: | ||
```bash | ||
echo $APP_ID | ||
echo $APP_KEY | ||
``` | ||
|
||
|
||
2. **Enhanced Script Structure**: | ||
|
||
- Added a main function to handle argparse in an organized way. | ||
- The main function also allows for interactive input of the term ID and class names for testing purposes. | ||
|
||
3. **Multiple Class Names**: | ||
|
||
- `getCourseInformation` can now accept multiple class names as arguments. | ||
|
||
## Usage | ||
|
||
You can run the script in two ways: | ||
|
||
1. **Command-Line Mode**: | ||
```bash | ||
python refactor_testing_query_courseid.py 2242 data8 data100 compsci189 | ||
``` | ||
Expected Output: | ||
|
||
{ | ||
"display_name": "2024 Spring DATA C8 001", | ||
"department": "Data Science, Undergraduate", | ||
"enrollment_count": 1287 | ||
} | ||
{ | ||
"display_name": "2024 Spring DATA C100 001", | ||
"department": "Data Science, Undergraduate", | ||
"enrollment_count": 1132 | ||
} | ||
{ | ||
"display_name": "2024 Spring COMPSCI 189 001", | ||
"department": "Computer Science", | ||
"enrollment_count": 704 | ||
} | ||
{ | ||
"display_name": "2024 Spring COMPSCI 189 001", | ||
"department": "Computer Science", | ||
"enrollment_count": 704 | ||
} | ||
(notebook) jovyan@jupyter-jlucarga:~/datahub-usage-analysis/scripts$ | ||
``` | ||
|
||
2. **Interactive Mode**: | ||
- Run the script without arguments and follow the prompts: | ||
```bash | ||
python refactor_testing_query_courseid.py | ||
``` | ||
|
||
- You will be prompted to enter the term ID and class names: | ||
```text | ||
Please enter the term ID: ... (eg: 2242) | ||
Please enter the class names (separated by commas): ... (eg: data8, compsci189) | ||
``` | ||
## Questions for Consideration | ||
|
||
|
||
|
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,35 @@ | ||
import os | ||
import requests | ||
import json | ||
|
||
BASE_URL = "https://gateway.api.berkeley.edu/uat/sis/v1/classes?" | ||
|
||
# Fetch course information from the Berkeley API | ||
def fetch_course_info(full_url): | ||
app_id = os.getenv('APP_ID') | ||
app_key = os.getenv('APP_KEY') | ||
|
||
headers = { | ||
"app_id": app_id, | ||
"app_key": app_key, | ||
} | ||
|
||
try: | ||
response = requests.get(full_url, headers=headers) | ||
response.raise_for_status() # Raise an exception for HTTP errors | ||
|
||
# Check if the response status code is 200 | ||
if response.status_code == 200: | ||
# If the response is successful, extract the course information | ||
data = response.json()['apiResponse']['response'] | ||
classes = data['classes'] | ||
extracted_info = { | ||
"display_name": classes[0]['displayName'], | ||
"department": classes[0]['course']['subjectArea']['description'], | ||
"enrollment_count": sum(section['aggregateEnrollmentStatus']['enrolledCount'] for section in classes) | ||
} | ||
return json.dumps(extracted_info, indent=4) | ||
|
||
except requests.exceptions.RequestException as e: | ||
error_string = f"Failed to retrieve data. Error: {str(e)}" | ||
return json.dumps(error_string, indent=4) |
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,185 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import argparse | ||
import json | ||
import os | ||
import re | ||
import requests | ||
|
||
# Define the base URL as a global variable | ||
BASE_URL = "https://gateway.api.berkeley.edu/uat/sis/v1/classes?" | ||
|
||
# Check if the input string contains any digits | ||
def has_digits(input_string): | ||
""" | ||
Check if the input string contains any digits. | ||
Args: input_string (str): The input string. | ||
Returns: bool: True if the input string contains digits, False otherwise. | ||
""" | ||
return any(char.isdigit() for char in input_string) | ||
|
||
# Check if the string matches the pattern 'c\d+$' | ||
def check_pattern(s): | ||
""" | ||
Check if the string matches the pattern 'c\d+$'. | ||
Args: s (str): The input string. | ||
Returns: bool: True if the string matches the pattern, False otherwise. | ||
""" | ||
pattern = re.compile(r'c\d+$') | ||
match = re.search(pattern, s) | ||
return match is not None | ||
|
||
# Extract the pattern from the string and format it accordingly | ||
def extract_pattern(s): | ||
""" | ||
Extract the pattern from the string and format it accordingly. | ||
Args: s (str): The input string. | ||
Returns: str: The formatted string. | ||
""" | ||
pattern = re.compile(r'([a-zA-Z])(\d+)$') | ||
match = re.search(pattern, s) | ||
if match: | ||
char = match.group(1) | ||
numbers = match.group(2) | ||
remaining = s[:match.start()] # Extracts characters before the matched pattern | ||
return f"{remaining} {char}{numbers}" | ||
|
||
# Fetch course information from the Berkeley API | ||
def getCourseInformation(term_id, class_name, page_number=1, page_size=100): | ||
""" | ||
Fetch course information from the Berkeley API. | ||
Args: | ||
term_id (int): The term ID. | ||
class_name (str): The class name. | ||
page_number (int, optional): The page number. Defaults to 1. | ||
page_size (int, optional): The page size. Defaults to 100. | ||
Returns: str: JSON string with extracted information or error message. | ||
""" | ||
# Check if class name is "unknown" | ||
if class_name == "unknown": | ||
# If the class name is "unknown", return an error message | ||
error_string = "Class name is unknown. Please enter a valid class name." | ||
return json.dumps(error_string, indent=4) | ||
|
||
# Check if class name has digits | ||
elif not has_digits(class_name): | ||
# If the class name does not contain any digits, return an error message | ||
error_string = f"Class name {class_name} is invalid. Please enter a valid class name." | ||
return json.dumps(error_string, indent=4) | ||
|
||
# Extract subject area code from the class name | ||
subject_area_code = re.search(r'([a-zA-Z]+)\d+', class_name) | ||
subject_area_code = subject_area_code.group(1).upper() | ||
|
||
# Find the numeric part of the class name | ||
for i in range(len(class_name)): | ||
if class_name[i].isdigit(): | ||
number = class_name[i:].upper() | ||
break | ||
|
||
desired_display_name = subject_area_code + " " + str(number) | ||
|
||
url_params = f"term-id={term_id}&subject-area-code={subject_area_code}&catalog-number={number}&page-number={page_number}&page-size={page_size}" | ||
full_url = BASE_URL + url_params | ||
|
||
app_id = os.getenv('APP_ID') | ||
app_key = os.getenv('APP_KEY') | ||
|
||
headers = { | ||
"app_id": app_id, | ||
"app_key": app_key, | ||
} | ||
|
||
response = requests.get(full_url, headers=headers) | ||
|
||
# Check if the response status code is 200 | ||
if response.status_code == 200: | ||
# If the response is successful, extract the course information | ||
data = response.json()['apiResponse']['response'] | ||
classes = data['classes'] | ||
extracted_info = { | ||
"display_name": classes[0]['displayName'], | ||
"department": classes[0]['course']['subjectArea']['description'], | ||
"enrollment_count": sum(section['aggregateEnrollmentStatus']['enrolledCount'] for section in classes) | ||
} | ||
# Creating a new JSON object with the extracted information | ||
return_json = json.dumps(extracted_info, indent=4) | ||
print(return_json) | ||
return return_json | ||
|
||
# Check if class name matches pattern 'c\d+$' | ||
elif check_pattern(class_name): | ||
# If the class name matches the pattern 'c\d+$', extract and reformat the pattern in the class name | ||
desired_display_name = extract_pattern(class_name) | ||
subject_area_code, number = desired_display_name.split() | ||
full_url = BASE_URL + f"term-id={term_id}&subject-area-code={subject_area_code}&catalog-number={number}&page-number={page_number}&page-size={page_size}" | ||
|
||
response = requests.get(full_url, headers=headers) | ||
# Check if the response status code is 200 | ||
if response.status_code == 200: | ||
# If the response is successful, extract the course information | ||
data = response.json()['apiResponse']['response'] | ||
classes = data['classes'] | ||
extracted_info = { | ||
"display_name": classes[0]['displayName'], | ||
"department": classes[0]['course']['subjectArea']['description'], | ||
"enrollment_count": sum(section['aggregateEnrollmentStatus']['enrolledCount'] for section in classes) | ||
} | ||
return json.dumps(extracted_info, indent=4) | ||
|
||
else: | ||
# If the class name does not match the pattern, modify it to include 'C' | ||
number = "C" + number | ||
desired_display_name = subject_area_code + " " + str(number) | ||
full_url = BASE_URL + f"term-id={term_id}&subject-area-code={subject_area_code}&catalog-number={number}&page-number={page_number}&page-size={page_size}" | ||
|
||
response = requests.get(full_url, headers=headers) | ||
|
||
# Check if the response status code is 200 | ||
if response.status_code == 200: | ||
# If the response is successful, extract the course information | ||
data = response.json()['apiResponse']['response'] | ||
classes = data['classes'] | ||
extracted_info = { | ||
"display_name": classes[0]['displayName'], | ||
"department": classes[0]['course']['subjectArea']['description'], | ||
"enrollment_count": sum(section['aggregateEnrollmentStatus']['enrolledCount'] for section in classes) | ||
} | ||
return json.dumps(extracted_info, indent=4) | ||
else: | ||
error_string = f"Failed to retrieve data for {class_name}. Status code: {response.status_code}" | ||
return json.dumps(error_string, indent=4) | ||
|
||
# Main function to handle command-line arguments and fetch course information | ||
def main(): | ||
|
||
parser = argparse.ArgumentParser(description="Fetch course information based on term ID and class name.") | ||
parser.add_argument('term_id', type=int, nargs='?', default=2232, help="The term ID (e.g., '2232').") | ||
parser.add_argument('class_names', type=str, nargs='*', help="One or more class names (e.g., 'data8', 'compsci189').") | ||
|
||
args = parser.parse_args() | ||
|
||
# Check if the necessary environment variables are set | ||
if not os.getenv('APP_ID') or not os.getenv('APP_KEY'): | ||
print("Error: The environment variables APP_ID and APP_KEY must be set.") | ||
return | ||
|
||
# Check if term_id or class_names are provided | ||
if not args.class_names: | ||
# If not provided, prompt the user for input | ||
term_id = input("Please enter the term ID: ") | ||
class_names = input("Please enter the class names (separated by commas): ").split(',') | ||
args.term_id = int(term_id) | ||
args.class_names = [class_name.strip() for class_name in class_names] | ||
|
||
else: | ||
term_id = args.term_id | ||
class_names = args.class_names | ||
|
||
# Loop through each class name and fetch information | ||
for class_name in args.class_names: | ||
result = getCourseInformation(args.term_id, class_name) | ||
print(result) | ||
|
||
if __name__ == "__main__": | ||
main() |
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,33 @@ | ||
import re | ||
|
||
#Check if the input string contains any digits | ||
def has_digits(input_string): | ||
""" | ||
Args: input_string (str): The input string. | ||
Returns: bool: True if the input string contains digits, False otherwise. | ||
""" | ||
return any(char.isdigit() for char in input_string) | ||
|
||
#Check if the string matches the pattern 'c\d+$' | ||
def check_pattern(s): | ||
""" | ||
Args: s (str): The input string. | ||
Returns: bool: True if the string matches the pattern, False otherwise. | ||
""" | ||
pattern = re.compile(r'c\d+$') | ||
match = re.search(pattern, s) | ||
return match is not None | ||
|
||
#Extract the pattern from the string and format it accordingly | ||
def extract_pattern(s): | ||
""" | ||
Args: s (str): The input string. | ||
Returns: str: The formatted string. | ||
""" | ||
pattern = re.compile(r'([a-zA-Z])(\d+)$') | ||
match = re.search(pattern, s) | ||
if match: | ||
char = match.group(1) | ||
numbers = match.group(2) | ||
remaining = s[:match.start()] # Extracts characters before the matched pattern | ||
return f"{remaining} {char}{numbers}" |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert this to the prior version pls ty