Created
November 9, 2017 13:58
-
-
Save N-Coder/0f8b73f72c4b087c50a5fe176af7c239 to your computer and use it in GitHub Desktop.
Fetch all available data through the python Stud.IP API client
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
import asyncio | |
import logging | |
import os | |
import warnings | |
from asyncio.futures import _chain_future as chain_future | |
import attr | |
from studip_api.session import StudIPSession | |
@attr.s | |
class AsyncState(object): | |
root: asyncio.Future = attr.ib(default=attr.Factory(asyncio.Future)) | |
semesters: asyncio.Future = attr.ib(default=attr.Factory(asyncio.Future)) # [List[Semester]] | |
courses: asyncio.Future = attr.ib(default=attr.Factory(asyncio.Future)) # [List[Course]] | |
files: asyncio.Future = attr.ib(default=attr.Factory(asyncio.Future)) # [List[File]] | |
async def main(state): | |
with open(os.path.expanduser('~/.studip-pwd')) as f: | |
password = f.read() | |
async with StudIPSession( | |
user_name="fink13", | |
password=password, | |
studip_base="https://studip.uni-passau.de", | |
sso_base="https://sso.uni-passau.de" | |
) as session: | |
password = "" | |
# Track all pending file listings for courses and recurse into subfolders | |
all_files_done, handle_files_future_started = track_pending_files(session) | |
# List semesters and their courses | |
semester_future = await load_semesters(session, state) | |
courses_futures = await load_courses(session, state, semester_future, handle_files_future_started) | |
# Wait for all listings to complete | |
await semester_future | |
for course_future in courses_futures: | |
await course_future | |
all_file_futures = await all_files_done() | |
chain_future(asyncio.gather(*all_file_futures, return_exceptions=True), state.files) | |
def track_pending_files(session): | |
all_file_futures = [] | |
files_done_condition = asyncio.Condition() | |
# This coroutine returns once all file listings are loaded | |
async def all_files_done(): | |
async with files_done_condition: | |
await files_done_condition.wait_for(lambda: all(f.done() for f in all_file_futures)) | |
return all_file_futures | |
# When a listing is complete, also recurse into its subfolders and notify the Condition | |
async def handle_files_future_done(get_files_future): | |
has_subfolders = False | |
for file in get_files_future.result().contents: | |
if file.is_folder(): | |
has_subfolders = True | |
handle_files_future_started(asyncio.ensure_future(session.get_folder_files(file))) | |
# No need to notify the files_done_condition condition if we just requested a listing for subfolders | |
if not has_subfolders: | |
async with files_done_condition: | |
files_done_condition.notify_all() | |
# Add a pending listing to the list of all futures and track its return value | |
def handle_files_future_started(get_files_future): | |
get_files_future.add_done_callback(lambda f: asyncio.ensure_future(handle_files_future_done(f))) | |
all_file_futures.append(get_files_future) | |
return all_files_done, handle_files_future_started | |
async def load_semesters(session, state): | |
semester_future = asyncio.ensure_future(session.get_semesters()) | |
chain_future(semester_future, state.semesters) | |
return semester_future | |
async def load_courses(session, state, semester_future, handle_files_future): | |
courses_futures = [] | |
for s in await semester_future: | |
if s.name not in ["WS 17/18"]: | |
continue | |
f = asyncio.ensure_future(session.get_courses(s)) | |
courses_futures.append(f) | |
for course in await f: | |
if course.number not in ["5792UE", "5792V", "5792"]: | |
continue | |
handle_files_future(asyncio.ensure_future(session.get_course_files(course))) | |
chain_future(asyncio.gather(*courses_futures), state.courses) | |
return courses_futures | |
# courses_futures = [asyncio.ensure_future(session.get_courses(s)) for s in await semester_future] | |
# for course_future in courses_futures: | |
# course_future.add_done_callback(lambda cf: ( | |
# handle_files_future(session.get_course_files(course)) | |
# for course in cf.result())) | |
loop = asyncio.get_event_loop() | |
loop.set_debug(True) | |
logging.basicConfig(level=logging.DEBUG) | |
warnings.resetwarnings() | |
state = AsyncState() | |
chain_future(loop.create_task(main(state)), state.root) | |
loop.run_until_complete(state.root) | |
loop.run_until_complete(asyncio.sleep(1)) | |
loop.close() | |
print(state) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment