CanvasAPI

repository·develop·Indexed 20 days ago

https://github.com/ucfopen/canvasapi

A Python library providing programmatic access to Instructure's Canvas LMS API. It allows developers to manage courses, users, gradebooks, and other Canvas resources through high-level Python objects, including specialized classes for accounts, assignments, blueprints, and content migration.

Tokens
12.6K
Snippets
33
Records
113
Agent score
67%

What's inside canvasapi

  1. Use the Quiz API classes

    develop

    The canvasapi.quiz module provides several classes to interact with Canvas Quizzes. You can use these classes to manage quiz settings, retrieve questions, analyze student submissions, and access quiz statistics or reports.

    Key classes include:

    • Quiz: Represents a quiz itself.
    • QuizQuestion: Represents an individual question within a quiz.
    • QuizSubmission: Represents a student's attempt at a quiz.
    • QuizSubmissionQuestion: Represents a specific answer provided by a student to a question.
    • QuizReport and QuizStatistic: Used for retrieving analytical data about quiz performance.
    • QuizAssignmentOverrideSet: Manages overrides for quiz assignments.
    • QuizExtension: Handles quiz extensions.
    • QuizSubmissionEvent: Represents events related to quiz submissions.
  2. Use the CurrentUser class

    develop
    The canvasapi.current_user.CurrentUser class is a specialized subclass of canvasapi.user.User. It provides access to the user currently authenticated via your Canvas API key. Because it inherits from the User class, it includes all standard user methods (such as retrieving profile information, managing enrollments, etc.) but is specifically scoped to the identity of the authenticated requester.
  3. Distinguish between InvalidAccessToken and Unauthorized

    develop

    Both exceptions return an HTTP 401 status code, but they indicate different issues:

    • InvalidAccessToken: Thrown when the WWW-Authenticate header is present. This means your API key is invalid.
    • Unauthorized: Thrown when the WWW-Authenticate header is NOT present. This means your API key is valid, but the user does not have permission to access the specific resource.
  4. Use PaginatedList to iterate over large collections

    develop

    The PaginatedList class is used to handle collections of objects returned by the Canvas API that are spread across multiple pages. Instead of manually managing page numbers or tokens, you can iterate over a PaginatedList object as if it were a standard Python list. The class automatically fetches subsequent pages of results as you iterate through the items, making it easy to process large datasets like all users in a course or all assignments in a module.

    # Example pattern for iterating over a paginated collection
    for item in paginated_list:
        print(item.name)
  5. Understand the CanvasObject base class

    develop
    In canvasapi, most domain-specific objects (like Course, User, or Assignment) inherit from the CanvasObject class. A CanvasObject represents a single resource within Canvas and provides a consistent interface for interacting with that resource via the Canvas API. It typically includes methods for retrieving the object's own data and potentially interacting with related resources.
  6. How Smart DateTimes work

    develop

    CanvasAPI simplifies working with ISO 8601 datetime strings:

    1. Sending Dates: When updating objects, you can pass a standard Python datetime object instead of a formatted string. CanvasAPI will handle the conversion.
    2. Receiving Dates: When Canvas returns an ISO 8601 string, CanvasAPI automatically creates a datetime object for you. This object is assigned to a new attribute with _date appended to the original key name. The original string representation is preserved under the original key name.
    from datetime import datetime
    
    # 1. Sending a datetime object to an update call
    start_date = datetime(2018, 1, 1, 0, 1)
    end_date = datetime(2018, 12, 31, 11, 59)
    
    course.update(
        course={
            'start_at': start_date,
            'end_at': end_date,
        }
    )
    
    # 2. Receiving a datetime object from the API
    course = canvas.get_course(1)
    print(course.start_at)      # Returns the original string: '2014-02-11T16:38:00Z'
    print(course.start_at_date) # Returns a datetime object: datetime.datetime(2014, 2, 11, 16, 38, ...)
  7. How PaginatedList works

    develop

    When an API call returns multiple objects (e.g., user.get_courses()), CanvasAPI returns a PaginatedList.

    Key Characteristics:

    • Interface: It behaves like a standard Python list. You can access elements by index, iterate over it, or take slices.
    • Lazy Loading: Elements are loaded lazily. The first access to an element triggers an API call to fetch a page of results. Subsequent elements within that page are accessed instantly.
    • Limitations: Because it loads lazily, the list does not know its own total length. Therefore, negative indexing is not supported.
    # Retrieve a list of courses the user is enrolled in
    >>> courses = user.get_courses()
    
    # Access the first element
    >>> print(courses[0])
    
    # Iterate over the list
    >>> for course in courses:
             print(course)
    
    # Take a slice
    >>> courses[:2]
    # Retrieve a list of courses the user is enrolled in
    >>> courses = user.get_courses()
    
    >>> print(courses)
    <PaginatedList of type Course>
    
    # Access the first element in our list.
    >>> print(courses[0])
    TST101 Test Course (1234567)
    
    # Iterate over our course list
    >>> for course in courses:
             print(course)
    
    TST101 Test Course 1 (1234567)
    TST102 Test Course 2 (1234568)
    TST103 Test Course 3 (1234569)
    
    # Take a slice of our course list
    >>> courses[:2]
    [TST101 Test Course 1 (1234567), TST102 Test Course 2 (1234568)]
  8. Handle CanvasAPI exceptions

    develop

    All exceptions in the canvasapi library inherit from canvasapi.exceptions.CanvasException. You can use this base class to catch any error thrown by the library, or catch specific exceptions to handle different error scenarios (like invalid keys or missing resources) uniquely.

    To catch any library-related error, import CanvasException and use a try...except block.

    from canvasapi.exceptions import CanvasException
    
    try:
        canvas.get_course(1)
    except CanvasException as e:
        print(e)
  9. Handle deep nested parameters (e.g., `foo[bar1][bar2]`)

    develop

    For parameters requiring multiple levels of nesting, such as user[avatar][url], use nested dictionaries in Python.

    # Representing user[avatar][url]
    user.edit(
        user={
            'avatar': {
                'url': 'http://example.com/john_avatar.png'
            }
        }
    )
  10. Deploy CanvasAPI to PyPI

    develop

    To release a new version of CanvasAPI to PyPI, follow these deployment steps:

    1. Update Version: Increment the version number in __init__.py.
    2. Commit and Push: Commit the changes to __init__.py and push to the repository.
    3. Merge to Master: Create a merge request from the develop branch to the master branch and merge it.
    4. Tag the Release: Create a signed git tag using the version number and the merge commit hash.
    5. Push Tag: Push the tag to the upstream repository. This triggers GitHub Actions to automatically deploy the code to PyPI.
    6. GitHub Release: Create a new release on GitHub for the tag, using the content from the CHANGELOG for the release notes.
    # Example tagging and pushing a release
    git tag -s v0.0.0 -m "Release version 0.0.0" abc1234
    git push upstream v0.0.0
  11. Handle nested list parameters (e.g., `foo[bar][]`)

    develop

    When a parameter represents a nested object where one of the properties is a list (e.g., assignment[submission_types][]), pass a dictionary where the key for that property contains a list.

    # Representing assignment[submission_types][] and assignment[allowed_extensions][]
    course.create_assignment(
        assignment={
            'name': 'Assignment 1',
            'submission_types': ['online_text_entry', 'online_upload'],
            'allowed_extensions': ['doc', 'docx']
        }
    )
  12. Manage Accounts and Users

    develop

    You can interact with accounts to manage users and list courses. Use canvas.get_account(account_id) to retrieve an account object.

    Create a New User

    To create a user under a specific account, use account.create_user() providing a user dictionary (e.g., for name) and a pseudonym dictionary (e.g., for password and sis_user_id).

    List Courses under an Account

    Use account.get_courses() to retrieve a list of courses associated with that account.

    # Grab the account to create the user under
    account = canvas.get_account(1)
    
    user = account.create_user(
        user={
            'name': 'New User'            
        },
        pseudonym={
            'password': 'secure123',
            'sis_user_id': 'new_user'
        }
    )
    
    # List courses
    courses = account.get_courses()
    for course in courses:
        print(course)