Skip to main content

Brightspace CLI, grading automation and management system.

Project description

Brightspace CLI

BS CLI is a command line interface for the D2L Brightspace LMS, bundled with a collection of scripts that simplifies and partially automates grading assignments. Submissions can be downloaded via the Brightspace API and can be distributed to graders in a structured way. Potentially, some preprocessing can be done on the submissions before they are distributed to graders.

You can use bscli in two ways: either by specifying course and assignment IDs manually for quick access, or by creating a dedicated folder for each course with a course.json file containing course-specific settings and aliases for assignments (recommended).

Graders will receive an archive containing all submissions they were assigned to grade, and can write their feedback in a feedback.txt file (with partial Markdown support). They can do so on their local machine, using any tools they prefer, without the need to interact with the Brightspace LMS web interface. Once they are done, they can upload their feedback via the Brightspace API.

More specifically, submissions are downloaded, and after potential preprocessing, an .7z archive is created for each grader containing the submissions they are assigned to grade. There are several strategies to distribute submissions to graders, such as randomly or according to Brightspace group registration. The archives can be sent to graders via FileSender.

The automated processing pipeline works as follows:

  1. Download submissions from Brightspace
  2. Preprocess submissions (remove unwanted files, convert formats, organize structure)
  3. Distribute submissions to graders using the configured strategy
  4. Package submissions into encrypted .7z archives for each grader
  5. Deliver archives to graders via FileSender with password protection
  6. Upload graded feedback back to Brightspace Apart from Brightspace access, the scripts thus require access to a FileSender server.

Notice that files will be encrypted with a password while being uploaded to FileSender. The password can be set per assignment, and must be provided to graders separately. FileSender may not receive the password, and does not accept it being included in the email (they actively check for this).

Installation

The scripts are written in Python and should run with python 3.10 and higher.

To install, simply run

pip install brightspace-cli

Apart from that, the following OS packages are required:

  • 7za to create the encrypted archives
  • libreoffice to convert .docx files to .pdf files (optional)

Running

Run the scripts by executing bscli.

Notice that you will need to configure the scripts to authenticate with Brightspace
You can do so by running bscli config init bsapi.

To distribute assignments, you will also need to configure FileSender. You can do so by running bscli config init filesender.

Two usage modes

Direct mode (quick access): For quick operations, you can specify course and assignment IDs directly:

bscli assignments list --course-id 12345
bscli assignments download --course-id 12345 --assignment-id 67890
bscli assignments grading-progress --course-id 12345 --assignment-id 67890

Course configuration mode (recommended): For regular use, create a dedicated folder for each course and configure a course.json file. This allows you to use assignment aliases and enables advanced grading automation features. You can create a default configuration file by running bscli courses config-create. Typically, you create this file once per course, and then modify it as needed.

mkdir my-course-2025
cd my-course-2025
bscli courses config-create
bscli assignments download homework-1    # Uses alias from course.json
bscli assignments distribute homework-1  # Automated distribution with custom processing

Configuration

bscli uses configuration files to store settings and credentials. The bsapi.json and filesender.json files are used to configure the Brightspace API and FileSender server respectively and are stored by default in the ~/.config/bscli/ directory. More information on the contents of these files can be found below, or in the /bscli/data/scheme/ directory that contains JSON schema files for these configuration files._

bsapi.json

This file configures communication with the Brightspace API. An example of the bsapi.json file can be found below.

{
  "clientId": "...",
  "clientSecret": "...",
  "lmsUrl": "brightspace.example.com",
  "redirectUri": "https://redirect.example.com/callback",
  "leVersion": "1.79",
  "lpVersion": "1.47"
}

The settings should match those of a registered API application in your Brightspace LMS.

OAuth Callback Setup

The redirectUri in your bsapi.json configuration must point to a publicly accessible HTTPS URL hosting the callback.html file. This is required because:

  1. Brightspace requires HTTPS: OAuth redirects must use HTTPS for security
  2. CLI limitation: The CLI runs locally and cannot directly receive HTTPS callbacks
  3. Bridge solution: The callback page acts as a bridge between the HTTPS OAuth flow and your local CLI

Setting up the callback page

  1. Host the callback page: Upload the callback.html file (included in this repository) to any web server with HTTPS support:

    • GitLab Pages (this repository includes GitLab CI configuration)
    • GitHub Pages
    • Your university's web hosting
    • Any cloud hosting service (Netlify, Vercel, etc.)
  2. Configure the redirect URI: Set the redirectUri in your bsapi.json to point to your hosted callback page:

    {
      "redirectUri": "https://yourdomain.gitlab.io/bsscripts/callback.html"
    }
    
  3. Register in Brightspace: When registering your OAuth application in Brightspace, use the same HTTPS URL as your redirect URI.

How the OAuth flow works

  1. CLI opens your browser to the Brightspace authorization URL
  2. After authorization, Brightspace redirects to your hosted callback.html page
  3. The callback page extracts the authorization code and either:
    • Automatically redirects to your local CLI (if supported)
    • Displays the code for manual copy-paste into the CLI
  4. You enter the code in the CLI to complete authentication

Using GitLab Pages (Recommended)

This repository includes GitLab CI configuration (.gitlab-ci.yml) that automatically deploys the callback page to GitLab Pages:

  1. Fork or clone this repository to your GitLab account
  2. Push to the main branch - GitLab CI will automatically build and deploy the callback page
  3. Access your callback page at https://yourusername.gitlab.io/bsscripts/callback.html
  4. Use this URL as your redirectUri in bsapi.json

The GitLab CI configuration automatically copies callback.html to the public directory and deploys it to GitLab Pages on every push to the main branch.

course.json

This file configures how the application should behave for a specific course. It contains course-specific settings, such as the course ID, aliases for assignments, grading settings, et cetera.

{
  "courseName": "Sandbox Course 2025", // name of the course in Brightspace
  "course": "sandbox", // internal alias for the course
  "assignmentDefaults": { // default grading settings for assignments
    "ignoredSubmissions": [], // submission ids to ignore
    "draftFeedback": false, // whether to upload feedback as draft or publish it immediately
    "defaultCodeBlockLanguage": "java", // default language for code blocks in feedback
    "fileHierarchy": "smart", // whether to keep the `original` submission's file hierarchy, `flatten`, or unpack in a `smart` way
    "division": { // how to divide the feedback archive
      // ... see below
    },
    "gradeAliases": { // aliases for grades, used in feedback
      "f": "Fail", // entering "f" as grade will be replaced by "Fail" in the feedback
      "i": "Insufficient",
      "s": "Sufficient",
      "g": "Good"
    },
    "removeFiles": [ // files to remove from submissions
      ".*",
      "*.exe",
      "*.jar",
      "*.a",
      "*.o",
      "*.class",
      "*.obj"
    ],
    "removeFolders": [ // folders to remove from submissions
      "__MACOSX",
      "__pycache__",
      ".*"
    ]
  },
  "assignments": { // assignments that should be graded
    "a1": { // 'a1' is the alias for this assignment which can be used in the scripts
      "name": "test assignment", // the name of the assignment in Brightspace
      "encryptionPassword": "MySecureP@ssword123" // the password to encrypt the feedback archive for this assignment, must contain at least one uppercase letter, one lowercase letter, one digit and one special character
    } // this can also contain the same settings as `assignmentDefaults` to override them for a specific assignment
  },
  "graders": { // who are the graders for this course
    "grader1": { // 'grader1' is the alias for this grader which can be used in the scripts
      "name": "Grader 1", // the display name of the grader
      "email": "grader1@example.com", // the email address that should receive the feedback archive
      "contactEmail": "grader1@example.com" // the email of the grader that will be used in the feedback to 
    }
  }
}

Division strategies

There are several strategies to divide submissions to graders.

  • random: submissions are divided randomly to graders
  • brightspace: submissions are divided according to Brightspace groups (depending on which group the submitter is in, it will be divided to the corresponding grader)
  • persistent: submissions are divided according to a persistent mapping of students to graders
  • custom: a custom division strategy can be implemented as a CourseModule

Random division

The random division strategy is the simplest division strategy. Everytime you distribute submissions, they are randomly assigned to graders as specified in the graders field. You should configure the following settings in the course.json file to use this strategy:

{
  "division": {
    "method": "random",
    "graderWeights": {
      "grader1": 1,
      "grader2": 2
    }
  }
}

Brightspace division

The Brightspace division strategy divides submissions according to Brightspace groups. You should configure the following settings in the course.json file to use this strategy:

{
  "division": {
    "method": "brightspace",
    "groupCategoryName": "Grading Groups",
    "groupMapping": {
      "Grading Group 1": "grader1",
      "Grading Group 2": "grader2"
    }
  }
}

Persistent division

Make a random division once and store it in a file, so that the same division can be used in the future.

{
  "division": {
    "method": "persistent", 
    "groupCategoryName": "grading-groups",
    "graderWeights": {
      "grader1": 1, 
      "grader2": 2
    }
  }
}

Custom division

You can implement your own division strategy by creating a Python script as a CourseModule. Place the script in ./data/course/<course>/plugin.py.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bscli-0.2.0.tar.gz (80.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bscli-0.2.0-py3-none-any.whl (99.2 kB view details)

Uploaded Python 3

File details

Details for the file bscli-0.2.0.tar.gz.

File metadata

  • Download URL: bscli-0.2.0.tar.gz
  • Upload date:
  • Size: 80.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.10.9

File hashes

Hashes for bscli-0.2.0.tar.gz
Algorithm Hash digest
SHA256 28c95a26a99d13e0e3cf7c4c715aa600a7cc8947a4ee4bd582a7a2d6f8ccc8d3
MD5 cdfa4cccc3ffa219c7952cdbae623123
BLAKE2b-256 05da6e7baf38483b38f80a6be78bf5c3e17be786c22e3113abf6858dd6deee96

See more details on using hashes here.

File details

Details for the file bscli-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: bscli-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 99.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.0.1 CPython/3.10.9

File hashes

Hashes for bscli-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 135dc864faa6364cc57b4c46a994ba826b48619e4777b064c88fca6e9f47ed16
MD5 4614a33079b9ad791127538652634caf
BLAKE2b-256 28114962318d38e53e59b222782a120a460a7d1d3533941b0c1d571ed6e00a0b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page