API wrapper for the Canvas LMS
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pages, files, folders, modules, external tools, and content organization within courses. Comprehensive content creation and management capabilities for structuring course materials.
Create and manage wiki-style pages for course content.
class Course(CanvasObject):
def get_pages(self, **kwargs) -> PaginatedList[Page]:
"""
List pages in the course.
Parameters:
- sort: Sort pages by field ('title', 'created_at', 'updated_at')
- order: Sort order ('asc', 'desc')
- search_term: Search term to filter pages
- published: Filter by published status
- include: Additional data ('body', 'locked_for_user', 'can_edit')
Returns:
Paginated list of Page objects
"""
def create_page(self, wiki_page: dict, **kwargs) -> Page:
"""
Create a new page.
Parameters:
- wiki_page: Dictionary with page attributes:
- title: Page title (required)
- body: Page content (HTML)
- editing_roles: Who can edit ('teachers', 'students', 'members', 'public')
- notify_of_update: Notify users of page creation
- published: Whether page is published
- front_page: Whether this is the course front page
Returns:
Page object
"""
def get_page(self, url_or_id, **kwargs) -> Page:
"""
Get a specific page by URL or ID.
Parameters:
- url_or_id: Page URL slug or page ID
- include: Additional data to include
Returns:
Page object
"""
class Page(CanvasObject):
def edit(self, **kwargs) -> Page:
"""
Edit page content and settings.
Parameters:
- wiki_page: Dictionary with page updates:
- title: Page title
- body: Page content (HTML)
- editing_roles: Who can edit the page
- notify_of_update: Notify users of changes
- published: Publication status
- front_page: Whether this is the front page
Returns:
Updated Page object
"""
def delete(self, **kwargs) -> Page:
"""Delete the page."""
def get_revisions(self, **kwargs) -> PaginatedList[PageRevision]:
"""
Get page revision history.
Returns:
Paginated list of PageRevision objects
"""
def show_latest_revision(self, **kwargs) -> PageRevision:
"""Get the latest revision of the page."""Manage course file storage and organization.
def get_files(self, **kwargs) -> PaginatedList[File]:
"""
List files in the course.
Parameters:
- content_types: Filter by MIME type
- exclude_content_types: Exclude specific MIME types
- search_term: Search term to filter files
- include: Additional data ('user', 'usage_rights', 'context_asset_string')
- only: Filter file types ('names', 'folders')
- sort: Sort files by field ('name', 'size', 'created_at', 'updated_at', 'content_type')
- order: Sort order ('asc', 'desc')
Returns:
Paginated list of File objects
"""
def get_folders(self, **kwargs) -> PaginatedList[Folder]:
"""
List folders in the course.
Parameters:
- sort: Sort folders by field
- order: Sort order
Returns:
Paginated list of Folder objects
"""
def create_folder(self, name: str, **kwargs) -> Folder:
"""
Create a new folder.
Parameters:
- name: Folder name
- parent_folder_id: Parent folder ID
- locked: Whether folder is locked
- hidden: Whether folder is hidden from students
- position: Position in folder list
Returns:
Folder object
"""
def get_file(self, file_id, **kwargs) -> File:
"""Get a specific file by ID."""
class File(CanvasObject):
def delete(self, **kwargs) -> File:
"""Delete the file."""
def get_contents(self, **kwargs) -> bytes:
"""
Download file contents.
Returns:
File contents as bytes
"""
def get_public_url(self, **kwargs) -> dict:
"""
Get a public URL for the file.
Returns:
Dictionary with public_url and expires_at
"""
class Folder(CanvasObject):
def edit(self, **kwargs) -> Folder:
"""
Edit folder properties.
Parameters:
- name: Folder name
- parent_folder_id: Parent folder ID
- locked: Whether folder is locked
- hidden: Whether folder is hidden
- position: Position in folder list
Returns:
Updated Folder object
"""
def delete(self, **kwargs) -> Folder:
"""Delete the folder."""
def get_files(self, **kwargs) -> PaginatedList[File]:
"""List files in this folder."""
def get_folders(self, **kwargs) -> PaginatedList[Folder]:
"""List subfolders in this folder."""
def create_folder(self, name: str, **kwargs) -> Folder:
"""Create a subfolder in this folder."""
def upload_file(self, file_path: str, **kwargs) -> File:
"""
Upload a file to this folder.
Parameters:
- file_path: Path to file to upload
- name: Custom name for uploaded file
- on_duplicate: Action for duplicate files ('overwrite', 'rename')
Returns:
File object
"""Organize course content into sequential learning modules.
def get_modules(self, **kwargs) -> PaginatedList[Module]:
"""
List modules in the course.
Parameters:
- include: Additional data ('items', 'content_details')
- search_term: Search term to filter modules
- student_id: Get modules as seen by specific student
Returns:
Paginated list of Module objects
"""
def create_module(self, module: dict, **kwargs) -> Module:
"""
Create a new module.
Parameters:
- module: Dictionary with module attributes:
- name: Module name (required)
- unlock_at: Date when module becomes available
- position: Position in module list
- require_sequential_progress: Items must be completed in order
- prerequisite_module_ids: List of prerequisite module IDs
- publish_final_grade: Publish grades when module completed
- completion_requirements: List of completion requirements
Returns:
Module object
"""
class Module(CanvasObject):
def edit(self, **kwargs) -> Module:
"""
Edit module properties.
Parameters:
- module: Dictionary with module updates (same as create_module)
Returns:
Updated Module object
"""
def delete(self, **kwargs) -> Module:
"""Delete the module."""
def get_module_items(self, **kwargs) -> PaginatedList[ModuleItem]:
"""
List items in this module.
Parameters:
- include: Additional data ('content_details', 'mastery_paths')
- search_term: Search term to filter items
- student_id: Get items as seen by specific student
Returns:
Paginated list of ModuleItem objects
"""
def create_module_item(self, module_item: dict, **kwargs) -> ModuleItem:
"""
Create a new module item.
Parameters:
- module_item: Dictionary with item attributes:
- title: Item title
- type: Item type ('File', 'Page', 'Discussion', 'Assignment', 'Quiz', 'SubHeader', 'ExternalUrl', 'ExternalTool')
- content_id: ID of the content object
- position: Position in module
- indent: Indentation level (0-3)
- page_url: For Page items, the page URL
- external_url: For ExternalUrl items
- new_tab: Open external content in new tab
- completion_requirement: Completion requirement for this item
Returns:
ModuleItem object
"""
class ModuleItem(CanvasObject):
def edit(self, **kwargs) -> ModuleItem:
"""Edit module item properties."""
def delete(self, **kwargs) -> ModuleItem:
"""Delete the module item."""
def mark_as_done(self, **kwargs) -> ModuleItem:
"""Mark item as done for current user."""
def mark_as_not_done(self, **kwargs) -> ModuleItem:
"""Mark item as not done for current user."""Integrate external applications and LTI tools.
def get_external_tools(self, **kwargs) -> PaginatedList[ExternalTool]:
"""
List external tools in the course.
Parameters:
- search_term: Search term to filter tools
- selectable: Filter by selectable tools
- include_parents: Include tools from parent account
Returns:
Paginated list of ExternalTool objects
"""
def create_external_tool(self, **kwargs) -> ExternalTool:
"""
Create an external tool.
Parameters:
- name: Tool name
- privacy_level: Privacy level ('anonymous', 'name_only', 'public')
- consumer_key: OAuth consumer key
- shared_secret: OAuth shared secret
- url: Tool launch URL
- domain: Tool domain (alternative to URL)
- description: Tool description
- custom_fields: Custom fields for tool launch
- account_navigation: Account navigation settings
- user_navigation: User navigation settings
- course_navigation: Course navigation settings
- editor_button: Rich editor button settings
- homework_submission: Homework submission settings
- link_selection: Link selection settings
- migration_selection: Migration selection settings
- resource_selection: Resource selection settings
- tool_configuration: Tool configuration settings
- not_selectable: Whether tool is selectable
Returns:
ExternalTool object
"""
class ExternalTool(CanvasObject):
def edit(self, **kwargs) -> ExternalTool:
"""Edit external tool settings."""
def delete(self, **kwargs) -> ExternalTool:
"""Delete the external tool."""Import content from external sources or other Canvas courses.
def create_content_migration(self, migration_type: str, **kwargs) -> ContentMigration:
"""
Create a content migration.
Parameters:
- migration_type: Type of migration ('course_copy_importer', 'zip_file_importer', 'qti_converter', 'moodle_converter', etc.)
- pre_attachment: File attachment for migration
- settings: Migration-specific settings dictionary:
- source_course_id: For course copy migrations
- folder_id: Target folder for file imports
- overwrite_quizzes: Whether to overwrite existing quizzes
- question_bank_id: Target question bank
- question_bank_name: Name for new question bank
- date_shift_options: Options for shifting dates:
- shift_dates: Whether to shift dates
- old_start_date: Original course start date
- old_end_date: Original course end date
- new_start_date: New course start date
- new_end_date: New course end date
- day_substitutions: Day of week substitutions
- selective_import: Whether to allow selective import
Returns:
ContentMigration object
"""
def get_content_migrations(self, **kwargs) -> PaginatedList[ContentMigration]:
"""
List content migrations for the course.
Returns:
Paginated list of ContentMigration objects
"""
class ContentMigration(CanvasObject):
def get_progress(self, **kwargs) -> Progress:
"""Get progress of the migration."""
def get_migration_issues(self, **kwargs) -> PaginatedList[MigrationIssue]:
"""Get issues encountered during migration."""
def update(self, **kwargs) -> ContentMigration:
"""Update migration settings."""Manage copyright and usage rights for course content.
def set_usage_rights(self, file_ids: list, usage_rights: dict, **kwargs) -> UsageRights:
"""
Set usage rights for files.
Parameters:
- file_ids: List of file IDs
- usage_rights: Dictionary with rights information:
- use_justification: Justification ('own_copyright', 'used_by_permission', 'fair_use', 'public_domain', 'creative_commons')
- legal_copyright: Copyright information
- license: License type for Creative Commons
Returns:
UsageRights object
"""
def remove_usage_rights(self, file_ids: list, **kwargs) -> UsageRights:
"""Remove usage rights from files."""
class UsageRights(CanvasObject):
"""Represents usage rights and copyright information for content."""from canvasapi import Canvas
canvas = Canvas("https://canvas.example.com", "your-token")
course = canvas.get_course(12345)
# Create course pages
syllabus = course.create_page({
'title': 'Course Syllabus',
'body': '''
<h1>Introduction to Computer Science</h1>
<h2>Course Description</h2>
<p>This course introduces fundamental concepts of computer science...</p>
<h2>Learning Objectives</h2>
<ul>
<li>Understand basic programming concepts</li>
<li>Learn problem-solving techniques</li>
<li>Apply algorithms to real-world problems</li>
</ul>
''',
'published': True,
'front_page': True,
'editing_roles': 'teachers'
})
# Create additional content pages
resources_page = course.create_page({
'title': 'Additional Resources',
'body': '<h1>Helpful Links and References</h1><p>Here are some additional resources...</p>',
'published': True,
'editing_roles': 'teachers,students'
})
# Create folder structure for file organization
lectures_folder = course.create_folder('Lecture Materials')
assignments_folder = course.create_folder('Assignment Templates')
resources_folder = course.create_folder('Additional Resources')
# Upload files to specific folders
lecture1_file = lectures_folder.upload_file(
'/path/to/lecture1.pdf',
name='Lecture 1 - Introduction.pdf'
)
assignment_template = assignments_folder.upload_file(
'/path/to/assignment_template.docx',
name='Assignment Template.docx'
)# Create modules for course organization
week1_module = course.create_module({
'name': 'Week 1: Introduction to Programming',
'unlock_at': '2024-01-15T00:00:00Z',
'require_sequential_progress': True,
'completion_requirements': [
{
'type': 'must_view',
'min_score': None,
'completed': False
}
]
})
# Add items to the module
# Add the syllabus page
syllabus_item = week1_module.create_module_item({
'title': 'Course Syllabus',
'type': 'Page',
'page_url': syllabus.url,
'position': 1,
'completion_requirement': {
'type': 'must_view'
}
})
# Add lecture file
lecture_item = week1_module.create_module_item({
'title': 'Lecture 1: Introduction',
'type': 'File',
'content_id': lecture1_file.id,
'position': 2,
'completion_requirement': {
'type': 'must_view'
}
})
# Add external resource
external_item = week1_module.create_module_item({
'title': 'Python Tutorial (External)',
'type': 'ExternalUrl',
'external_url': 'https://docs.python.org/3/tutorial/',
'position': 3,
'new_tab': True,
'completion_requirement': {
'type': 'must_view'
}
})
# Add assignment (assuming assignment exists)
assignment = course.get_assignment(67890)
assignment_item = week1_module.create_module_item({
'title': 'Week 1 Assignment',
'type': 'Assignment',
'content_id': assignment.id,
'position': 4,
'completion_requirement': {
'type': 'must_submit'
}
})# Create an external LTI tool
external_tool = course.create_external_tool(
name="Code Execution Environment",
privacy_level="public",
consumer_key="your_consumer_key",
shared_secret="your_shared_secret",
url="https://coderunner.example.com/lti",
description="Interactive coding environment for assignments",
custom_fields={
'course_id': '$Canvas.course.id',
'user_id': '$Canvas.user.id'
},
course_navigation={
'enabled': True,
'text': 'Code Runner',
'visibility': 'public'
},
editor_button={
'enabled': True,
'icon_url': 'https://coderunner.example.com/icon.png',
'text': 'Insert Code',
'url': 'https://coderunner.example.com/editor_select'
}
)
# Add external tool as module item
tool_item = week1_module.create_module_item({
'title': 'Interactive Coding Exercise',
'type': 'ExternalTool',
'content_id': external_tool.id,
'position': 5,
'completion_requirement': {
'type': 'must_view'
}
})# Import content from another Canvas course
migration = course.create_content_migration(
migration_type='course_copy_importer',
settings={
'source_course_id': 54321, # Source course ID
'selective_import': True
},
date_shift_options={
'shift_dates': True,
'old_start_date': '2023-08-01',
'old_end_date': '2023-12-15',
'new_start_date': '2024-01-15',
'new_end_date': '2024-05-15',
'day_substitutions': {
'monday': 'tuesday', # Move Monday classes to Tuesday
'wednesday': 'thursday' # Move Wednesday to Thursday
}
}
)
# Monitor migration progress
progress = migration.get_progress()
print(f"Migration status: {progress.workflow_state}")
print(f"Progress: {progress.completion}%")
# Check for migration issues
if progress.workflow_state == 'completed':
issues = migration.get_migration_issues()
for issue in issues:
print(f"Migration issue: {issue.description}")
# Import from a ZIP file
zip_migration = course.create_content_migration(
migration_type='zip_file_importer',
pre_attachment={
'name': 'course_content.zip',
'size': 1024000 # File size in bytes
}
# File upload would be handled separately
)# Set usage rights for course files
files_to_update = [lecture1_file.id, assignment_template.id]
usage_rights = course.set_usage_rights(
file_ids=files_to_update,
usage_rights={
'use_justification': 'own_copyright',
'legal_copyright': '© 2024 University Name. All rights reserved.'
}
)
# Set Creative Commons license
cc_files = [resources_file.id]
cc_rights = course.set_usage_rights(
file_ids=cc_files,
usage_rights={
'use_justification': 'creative_commons',
'license': 'cc_by_sa', # Creative Commons Attribution-ShareAlike
'legal_copyright': 'Licensed under CC BY-SA 4.0'
}
)# Get all files in course and organize them
all_files = course.get_files(
sort='created_at',
order='desc',
include=['user']
)
# Create folders by file type
image_folder = course.create_folder('Images')
document_folder = course.create_folder('Documents')
video_folder = course.create_folder('Videos')
# Organize files by type
for file in all_files:
if file.content_type.startswith('image/'):
target_folder = image_folder
elif file.content_type in ['application/pdf', 'application/msword']:
target_folder = document_folder
elif file.content_type.startswith('video/'):
target_folder = video_folder
else:
continue
# Move file to appropriate folder (would require file update API)
print(f"Would move {file.display_name} to {target_folder.name}")
# Get file usage statistics
for file in all_files[:10]: # Check first 10 files
print(f"File: {file.display_name}")
print(f"Size: {file.size} bytes")
print(f"Downloads: {file.view_count if hasattr(file, 'view_count') else 'N/A'}")
print(f"Created: {file.created_at}")
print("---")Install with Tessl CLI
npx tessl i tessl/pypi-canvasapi