diff --git a/.gitignore b/.gitignore index 81ec437..08e86d7 100644 --- a/.gitignore +++ b/.gitignore @@ -174,3 +174,6 @@ cython_debug/ # Built Visual Studio Code Extensions *.vsix +# local build +/build +/edapiwl.egg-info/ diff --git a/README.md b/README.md index fead054..63ec1ba 100644 --- a/README.md +++ b/README.md @@ -59,4 +59,4 @@ There are utility methods included to help with the process of creating thread d - `new_document()`: creates a new blank document containing the bare XML tags necessary to create a new thread. - Returns a new `BeautifulSoup` instance for the new document, along with the root document tag (use the document tag to serialize for the API). - `parse_document(content: str)`: parses the content string, which holds the XML content of a thread. - - Similar to `new_document`, returns a new `BeautifulSoup` instance for the parsed document, along with the root document tag. + - Similar to `new_document`, returns a new `BeautifulSoup` instance for the parsed document, along with the root document tag. \ No newline at end of file diff --git a/edapi/edapi.py b/edapi/edapi.py index 7d23728..7b7426e 100644 --- a/edapi/edapi.py +++ b/edapi/edapi.py @@ -11,6 +11,8 @@ from requests.compat import urljoin from .types import EdAuthError, EdError, EditThreadParams, PostThreadParams + + from .types.api_types.endpoints.activity import ( API_ListUserActivity_Response, API_ListUserActivity_Response_Item, @@ -24,9 +26,13 @@ API_PutThread_Response, API_PutThread_Response_Thread, ) +from .types.api_types.endpoints.lessons import API_GetLesson + from .types.api_types.endpoints.user import API_User_Response from .types.api_types.thread import API_Thread_WithComments, API_Thread_WithUser +from .types.api_types.lesson import API_Lesson + ANSI_BLUE = lambda text: f"\u001b[34m{text}\u001b[0m" ANSI_GREEN = lambda text: f"\u001b[32m{text}\u001b[0m" ANSI_RED = lambda text: f"\u001b[31m{text}\u001b[0m" @@ -206,7 +212,7 @@ def list_user_activity( f"Failed to list user activity for user {user_id} in course {course_id}.", response.content, ) - + @_ensure_login def list_threads( self, /, course_id: int, *, limit: int = 30, offset: int = 0, sort: str = "new" @@ -232,6 +238,26 @@ def list_threads( f"Failed to list threads for course {course_id}.", response.content ) + + + @_ensure_login + def list_lessons(self, course_id: int) -> API_Lesson: + """ + Retrieve the details for lessons. + + GET /api/courses//lessons + + """ + lesson_url = urljoin(API_BASE_URL, f"courses/{course_id}/lessons") + response = self.session.get(lesson_url) + if response.ok: + + response_json: API_GetLesson = response.json() + + return response_json + + _throw_error(f"Failed to get lesson {course_id}.", response.content) + @_ensure_login def get_thread(self, thread_id: int) -> API_Thread_WithComments: """ diff --git a/edapi/types/api_types/endpoints/activity.py b/edapi/types/api_types/endpoints/activity.py index 6663bf4..6e0e932 100644 --- a/edapi/types/api_types/endpoints/activity.py +++ b/edapi/types/api_types/endpoints/activity.py @@ -16,7 +16,7 @@ class API_ListUserActivity_Response(TypedDict): # Union type for both comment and thread items API_ListUserActivity_Response_Item = Union[ "API_ListUserActivity_Response_CommentItem", - "API_ListUserActivity_Response_ThreadItem", + "API_ListUserActivity_Response_ThreadItem" ] @@ -38,6 +38,14 @@ class API_ListUserActivity_Response_ThreadItem(TypedDict): value: "API_ListUserActivity_Response_ThreadItem_Value" +class API_ListUserActivity_Response_Item_Value(TypedDict): + lesson_id: int + type: str + + + + + class API_ListUserActivity_Response_CommentItem_Value(TypedDict): id: int type: str diff --git a/edapi/types/api_types/endpoints/lessons.py b/edapi/types/api_types/endpoints/lessons.py new file mode 100644 index 0000000..3454605 --- /dev/null +++ b/edapi/types/api_types/endpoints/lessons.py @@ -0,0 +1,19 @@ +# TODO: Implement more specific types for the lesson endpoint + +from typing import TypedDict +from ..user import API_User +from ..lesson import API_Lesson + + +# === GET /api/lessons/ === +# also used by /api/courses//lessons/?view=1 + +class API_GetLesson(TypedDict): + """ + Response type for GET /api/lessons/. + + Also used by GET /api/courses//lessons/?view=1. + """ + + lesson: list[API_Lesson] + diff --git a/edapi/types/api_types/lesson.py b/edapi/types/api_types/lesson.py new file mode 100644 index 0000000..3d70e2a --- /dev/null +++ b/edapi/types/api_types/lesson.py @@ -0,0 +1,8 @@ +from typing import TypedDict + +# Note: This should be all we need to define the Lesson type. + +class API_Lesson(TypedDict): + """ + Lesson type used in the Ed API. + """ diff --git a/examples/getlessoninfo.py b/examples/getlessoninfo.py new file mode 100644 index 0000000..72bc2b4 --- /dev/null +++ b/examples/getlessoninfo.py @@ -0,0 +1,8 @@ +from edapi import EdAPI + +ed = EdAPI() +ed.login() + +lesson_info = ed.list_lessons() + +print(f"Lesson 1: {lesson_info['lessons'][0]['title']}") \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index e7b420f..b430f9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "edapi" -version = "0.0.2" +version = "0.0.3" description = "An unofficial integration of the Ed API with Python" readme = "README.md" requires-python = ">=3.9"