#!/usr/bin/env python3
"""Stony Brook University course scheduling module.
At the moment, this module mainly supports CSE majors.
.. autosummary::
:nosignatures:
main
"""
import os
import sys
from typing import Any, Dict, Iterable, List, Tuple
# Add project root to the Python path
_PKG_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.append(_PKG_PATH)
# Import project modules
from src.cli.parser import arg_parser
from src.scheduler import download, convert, query as qry
[docs]
def main() -> None:
"""Main function for the course scheduling module.
Raises:
ValueError: Arises if method is not ``download``, ``convert``, or ``query``, or if required arguments are not provided.
Returns:
None
"""
parser = arg_parser()
args = parser.parse_args()
# Print help message in the case of no arguments
if len(sys.argv) == 1:
parser.print_help(sys.stderr)
sys.exit(1)
else:
args: Dict[str, Any] = vars(args)
# Get variable names
method: str = args.get("method")
# Download
url: str = args.get("url")
major: str = args.get("major")
output: str = args.get("output") # appears in download and convert
wait_time: int = args.get("wait_time")
headless: bool = args.get("headless")
verbose: bool = args.get("verbose")
# Convert
json_file: str = args.get("json_file")
clingo: bool = args.get("clingo") # appears in convert and query
ergoai: bool = args.get("ergoai") # appears in convert and query
# Query
knowledge: str = args.get("knowledge")
num_models: int = args.get("num_models")
config: str = args.get("configuration")
parallel_mode: int = args.get("parallel_mode")
try:
query: Iterable[str] = _flatten_nested_list_to_tuple(args.get("query"))
except TypeError:
query: Iterable[str] = ()
# Perform actions
if method == "graph":
if (not url) or (not major):
raise ValueError("URL and major are required for downloading course data.")
download.procure_course_data(
url=url,
major=major,
output=output,
headless=headless,
verbose=verbose,
wait_time=wait_time,
)
elif method == "convert":
if (not json_file) or ((not clingo) and (not ergoai)):
raise ValueError(
"JSON file and conversion method are required for converting course data."
)
if clingo:
convert.convert_course_data(
json_file=json_file,
output_file=output,
method="clingo",
)
if ergoai:
convert.convert_course_data(
json_file=json_file,
output_file=output,
method="ergoai",
)
elif method == "query":
if (not knowledge) or ((not clingo) and (not ergoai)):
raise ValueError(
"Knowledge base and execution method are required for querying course data."
)
if clingo:
qry.query(
knowledge=knowledge,
method="clingo",
verbose=verbose,
num_models=num_models,
configuration=config,
parallel_mode=parallel_mode,
query=query,
)
elif ergoai:
qry.query(
knowledge=knowledge,
method="ergoai",
query=query,
)
else:
raise ValueError(f"Method '{method}' is not supported.")
return None
def _flatten_nested_list_to_tuple(nested_list: List[List[str]]) -> Tuple[str]:
"""Flatten a nested list and convert it to a tuple.
Args:
nested_list: Nested list to be flattened.
Returns:
Flattened tuple.
"""
result: List[str] = []
def flatten(lst):
for item in lst:
if isinstance(item, list):
flatten(item)
else:
result.append(item)
flatten(nested_list)
return tuple(result)
# Call main function
if __name__ == "__main__":
main()