diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 751a8a9..747aff9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ # These owners will be the default owners for everything in # the repo. Unless a later match takes precedence, -* @michael-linnane-lrn @ferdia-sopermaccafraidh-lrn +* @michael-linnane-lrn @sean-roche-lrn @jack-oconnor-lrn diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b869b0f..4356ec3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,5 +5,5 @@ updates: schedule: interval: "daily" time: "09:00" - reviewers: - - "@Learnosity/ai-labs-dev" \ No newline at end of file + reviewers: + - "@Learnosity/ai-labs-dev" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70f0f2f..6c9c605 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,40 @@ on: pull_request: jobs: + pre_commit: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.9' + + - name: Install Pre-commit Dependencies + run: pip install pre-commit + + - name: Run Pre-commit Hooks + run: pre-commit run --all-files + + type_check: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.9' + + - name: Install Test Dependencies + run: pip install .[test] + + - name: Type Checking with Mypy + run: mypy + tests: runs-on: ubuntu-latest strategy: @@ -16,7 +50,7 @@ jobs: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/dispatch-release-pypi.yml b/.github/workflows/dispatch-release-pypi.yml index 2ee3542..445efe6 100644 --- a/.github/workflows/dispatch-release-pypi.yml +++ b/.github/workflows/dispatch-release-pypi.yml @@ -28,7 +28,7 @@ jobs: grep "${{ github.ref_name }}" learnosity_sdk/_version.py - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: '3.x' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..9e969a6 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace + - id: check-yaml + - id: check-json + - id: pretty-format-json + args: [ --autofix ] + - id: check-merge-conflict + - id: check-symlinks + - id: detect-private-key + + - repo: https://github.com/crate-ci/typos + rev: v1.26.8 + hooks: + - id: typos diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 58c6197..328ab94 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Contribution in the form of [PRs] are welcome. -Why We Are No Longer Accepting Public Issues +Why We Are No Longer Accepting Public Issues After careful consideration, we’ve decided to discontinue accepting issues via GitHub Issues for our public repositories. Here’s why: diff --git a/ChangeLog.md b/ChangeLog.md index 88f59c7..15c44a3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [v0.3.12] - 2024-11-22 +### Added +- Added pre-commit hooks and Github CI action for code formatting and linting. +- Added MyPy with strict settings to enforce type hints (and Github CI action). +- Added `pytest-randomly` to shuffle test order + ## [v0.3.11] - 2024-11-01 ### Fixed - Deprecation warning for `datetime.utcnow()` @@ -74,9 +80,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [v0.3.1] - 2019-08-07 ### Fixed -- Fixed an issue where the `DataApi` class's `results_iter` method would return no data +- Fixed an issue where the `DataApi` class's `results_iter` method would return no data when receiving responses from Data API endpoints that set the "`data`" field of the - response to an object (like the [itembank/questions endpoint](https://reference.learnosity.com/data-api/endpoints/itembank_endpoints#getQuestions) + response to an object (like the [itembank/questions endpoint](https://reference.learnosity.com/data-api/endpoints/itembank_endpoints#getQuestions) when `item_references` is included in the request). ## [v0.3.0] - 2019-06-17 diff --git a/README.md b/README.md index f587553..61585b7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

Learnosity SDK - Python

-

Everything you need to start building your app in Learnosity, with the Python programming language.
+

Everything you need to start building your app in Learnosity, with the Python programming language.
(Prefer another language? Click here)
An official Learnosity open-source project.

@@ -72,7 +72,7 @@ Then, if you're following the tutorial on this page, also run: pip install learnosity_sdk[quickstart] ### **Alternative method 1: download the zip file** -Download the latest version of the SDK as a self-contained ZIP file from the [GitHub Releases](https://github.com/Learnosity/learnosity-sdk-python/releases) page. The distribution ZIP file contains all the necessary dependencies. +Download the latest version of the SDK as a self-contained ZIP file from the [GitHub Releases](https://github.com/Learnosity/learnosity-sdk-python/releases) page. The distribution ZIP file contains all the necessary dependencies. Note: after installation, run this command in the SDK root folder: @@ -119,6 +119,7 @@ Following are the routes to access our APIs. * Items API : http://localhost:8000/itemsapi * Reports API : http://localhost:8000/reportsapi * Question Editor API : http://localhost:8000/questioneditorapi +* Data API : http://localhost:8000/dataapi Open these pages with your web browser. These are all basic examples of Learnosity's integration. You can interact with these demo pages to try out the various APIs. The Items API example is a basic example of an assessment loaded into a web page with Learnosity's assessment player. You can interact with this demo assessment to try out the various Question types. @@ -163,7 +164,7 @@ host = "localhost" port = 8000 ``` -Now we'll declare the configuration parameters for Items API. These specify which assessment content should be rendered, how it should be displayed, which user is taking this assessment and how their responses should be stored. +Now we'll declare the configuration parameters for Items API. These specify which assessment content should be rendered, how it should be displayed, which user is taking this assessment and how their responses should be stored. ``` python items_request = { @@ -252,10 +253,10 @@ The call to `init()` returns an instance of the ItemsApp, which we can use to pr The Jinja template is rendered by the following line, which will bring in those variables. ``` python - response = template.render(name='Standalone Assessment Example', generated_request=generated_request) + response = template.render(name='Standalone Assessment Example', generated_request=generated_request) ``` -There is some additional code in [standalone_assessment.py](docs/quickstart/assessment/standalone_assessment.py), which runs Python's built-in web server. +There is some additional code in [standalone_assessment.py](docs/quickstart/assessment/standalone_assessment.py), which runs Python's built-in web server. This marks the end of the quick start guide. From here, try modifying the example files yourself, you are welcome to use this code as a basis for your own projects. As mentioned earlier, the Jinja template used here can be easily re-used in another framework, for example Python Flask or Django. @@ -271,7 +272,7 @@ See a more detailed breakdown of all the SDK features, and examples of how to us ### **Additional quick start guides** There are more quick start guides, going beyond the initial quick start topic of loading an assessment, these further tutorials show how to set up authoring and analytics: * [Authoring Items quick start guide](https://help.learnosity.com/hc/en-us/articles/360000754958-Getting-Started-With-the-Author-API) (Author API) - create and edit new Questions and Items for your Item bank, then group your assessment Items into Activities, and -* [Analytics / student reporting quick start guide](https://help.learnosity.com/hc/en-us/articles/360000755838-Getting-Started-With-the-Reports-API) (Reports API) - view the results and scores from an assessment Activity. +* [Analytics / student reporting quick start guide](https://help.learnosity.com/hc/en-us/articles/360000755838-Getting-Started-With-the-Reports-API) (Reports API) - view the results and scores from an assessment Activity. ### **Learnosity demos repository** On our [demo site](https://demos.learnosity.com/), browse through many examples of Learnosity API integration. You can also download the entire demo site source code, the code for any single demo, or browse the codebase directly on GitHub. @@ -318,7 +319,7 @@ We use this data to enable better support and feature planning. [(Back to top)](#table-of-contents) ## Further reading -Thanks for reading to the end! Find more information about developing an app with Learnosity on our documentation sites: +Thanks for reading to the end! Find more information about developing an app with Learnosity on our documentation sites: * [help.learnosity.com](http://help.learnosity.com/hc/en-us) -- general help portal and tutorials, * [reference.learnosity.com](http://reference.learnosity.com) -- developer reference site, and diff --git a/REFERENCE.md b/REFERENCE.md index bc952c0..3ac01a6 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -292,11 +292,11 @@ print(signed_request) ``` ## Further reading -Thanks for reading to the end! Find more information about developing an app with Learnosity on our documentation sites: +Thanks for reading to the end! Find more information about developing an app with Learnosity on our documentation sites: -Back to [README.md](README.md) \ No newline at end of file +Back to [README.md](README.md) diff --git a/docs/quickstart/assessment/standalone_assessment.py b/docs/quickstart/assessment/standalone_assessment.py index cacca7d..5361b6c 100644 --- a/docs/quickstart/assessment/standalone_assessment.py +++ b/docs/quickstart/assessment/standalone_assessment.py @@ -5,12 +5,15 @@ # with `rendering_type: "assess"`. # Include server side Learnosity SDK, and set up variables related to user access -from learnosity_sdk.request import Init +from learnosity_sdk.request import Init, DataApi from learnosity_sdk.utils import Uuid +from learnosity_sdk._version import __version__ from .. import config # Load consumer key and secret from config.py # Include web server and Jinja templating libraries. from http.server import BaseHTTPRequestHandler, HTTPServer from jinja2 import Template +import json +import os # - - - - - - Section 1: Learnosity server-side configuration - - - - - - # @@ -32,13 +35,6 @@ "domain": host, } -# Author Aide does not accept user_id so we need a separate security object -authorAideSecurity = { - "consumer_key": config.consumer_key, - # Change to the domain used in the browser, e.g. 127.0.0.1, learnosity.com - "domain": host, -} - # Items API configuration parameters. items_request = { # Unique student identifier, a UUID generated above. @@ -268,16 +264,6 @@ } } -# Author Aide API configuration parameters. -author_aide_request = { - "user": { - "id": 'python-demo-user', - "firstname": 'Demos', - "lastname": 'User', - "email": 'demos@learnosity.com' - } -} - # Set up Learnosity initialization data. initItems = Init( "items", security, config.consumer_secret, @@ -304,25 +290,19 @@ request = question_editor_request ) -initAuthorAide = Init( - "authoraide", authorAideSecurity, config.consumer_secret, - request = author_aide_request -) - # Generated request(initOptions) w.r.t all apis generated_request_Items = initItems.generate() generated_request_Questions = initQuestions.generate() generated_request_Author = initAuthor.generate() generated_request_Reports = initReports.generate() generated_request_QuestionEditor = initQuestionEditor.generate() -generated_request_AuthorAide = initAuthorAide.generate() # - - - - - - Section 2: your web page configuration - - - - - -# # Set up the HTML page template, for serving to the built-in Python web server class LearnosityServer(BaseHTTPRequestHandler): - def createResponse(self,response): + def createResponse(self, response: str) -> None: # Send headers and data back to the client. self.send_response(200) self.send_header("Content-type", "text/html") @@ -330,7 +310,30 @@ def createResponse(self,response): # Send the response to the client. self.wfile.write(response.encode("utf-8")) - def do_GET(self): + def do_GET(self) -> None: + + # Serve CSS file + if self.path == "/css/style.css": + try: + # Get the directory where this script is located + script_dir = os.path.dirname(os.path.abspath(__file__)) + # Navigate to the CSS file location + css_path = os.path.join(script_dir, "..", "css", "style.css") + + with open(css_path, 'r') as f: + css_content = f.read() + + self.send_response(200) + self.send_header("Content-type", "text/css") + self.end_headers() + self.wfile.write(css_content.encode("utf-8")) + return + except FileNotFoundError: + self.send_response(404) + self.send_header("Content-type", "text/plain") + self.end_headers() + self.wfile.write(b"CSS file not found") + return if self.path.endswith("/"): @@ -338,6 +341,7 @@ def do_GET(self): template = Template(""" +