From 94082fae93c9f2863a6b30f7450553ac2990c64b Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Thu, 12 Mar 2026 12:24:43 -0400 Subject: [PATCH 1/9] Add build info to and update python version in readthedocs config --- .readthedocs.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 151e7cc1..c676e2a0 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -5,12 +5,16 @@ # Required version: 2 +build: + os: latest + tools: + python: "3.13" + # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py python: - version: 3.7 + version: 3.13 install: - requirements: dev_requirements.txt - \ No newline at end of file From 77ff5b248603db987e57f11a104767d4b790265a Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Thu, 12 Mar 2026 12:28:36 -0400 Subject: [PATCH 2/9] Fix readthedocs config --- .readthedocs.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index c676e2a0..22e04999 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -6,7 +6,7 @@ version: 2 build: - os: latest + os: ubuntu-lts-latest tools: python: "3.13" @@ -15,6 +15,5 @@ sphinx: configuration: docs/conf.py python: - version: 3.13 install: - requirements: dev_requirements.txt From 384b0e5b4ade02f27e350fc848f27a83f88c056d Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Tue, 31 Mar 2026 15:10:05 -0400 Subject: [PATCH 3/9] Update obj_or_str to work like obj_or_id, and update tests accordingly --- canvasapi/util.py | 43 ++++++++++++++++++++----------------------- tests/test_util.py | 12 +++++++++++- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/canvasapi/util.py b/canvasapi/util.py index 21c2a02b..a4cc08ed 100644 --- a/canvasapi/util.py +++ b/canvasapi/util.py @@ -133,37 +133,34 @@ def obj_or_id(parameter, param_name, object_types): raise TypeError(message) -def obj_or_str(obj, attr, object_types): +def obj_or_str(parameter, param_name, object_types): """ - Accepts an object. If the object has the attribute, return the + Accepts either an object or a string. If it is a string, return it directly. + If it is an object and the object is of correct type, return the object's corresponding string. Otherwise, throw an exception. - :param obj: object from which to retrieve attribute - :type obj: object - :param attr: name of the attribute to retrieve - :type attr: str + :param parameter: object from which to retrieve attribute + :type parameter: str or object + :param param_name: name of the attribute to retrieve + :type param_name: str :param object_types: tuple containing the types of the object being passed in :type object_types: tuple :rtype: str """ - try: - return str(getattr(obj, attr)) - except (AttributeError, TypeError): - if not isinstance(attr, str): - raise TypeError( - "Atttibute parameter {} must be of type string".format(attr) - ) - for obj_type in object_types: - if isinstance(obj, obj_type): - try: - return str(getattr(obj, attr)) - except AttributeError: - raise AttributeError("{} object does not have {} attribute").format( - obj, attr - ) + if isinstance(parameter, str): + return parameter - obj_type_list = ",".join([obj_type.__name__ for obj_type in object_types]) - raise TypeError("Parameter {} must be of type {}.".format(obj, obj_type_list)) + for obj_type in object_types: + if isinstance(parameter, obj_type): + try: + return str(getattr(parameter, param_name)) + except AttributeError: + raise AttributeError("{} object does not have {} attribute").format( + parameter, param_name + ) + + obj_type_list = ",".join([obj_type.__name__ for obj_type in object_types]) + raise TypeError("Parameter {} must be of type {}.".format(parameter, obj_type_list)) def get_institution_url(base_url): diff --git a/tests/test_util.py b/tests/test_util.py index cd85648b..211ed597 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -431,6 +431,12 @@ def test_obj_or_id_nonuser_self(self, m): obj_or_id("self", "user_id", (CourseNickname,)) # obj_or_str() + def test_obj_or_str_str(self, m): + name = obj_or_str("test", "name", (User,)) + + self.assertIsInstance(name, str) + self.assertEqual(name, "test") + def test_obj_or_str_obj_attr(self, m): register_uris({"user": ["get_by_id"]}, m) @@ -467,8 +473,12 @@ def test_obj_or_str_invalid_attr_parameter(self, m): obj_or_str(user, user, (User,)) def test_obj_or_str_invalid_obj_type(self, m): + register_uris({"course": ["get_by_id"]}, m) + + course = self.canvas.get_course(1) + with self.assertRaises(TypeError): - obj_or_str("user", "name", (User,)) + obj_or_str(course, "name", (User,)) # get_institution_url() def test_get_institution_url(self, m): From d28e0503bf8b1823cf4770c303ce926c86c89718 Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Tue, 14 Apr 2026 14:11:26 -0400 Subject: [PATCH 4/9] Update black to avoid CVE-2026-32274. Update changelog --- CHANGELOG.md | 8 ++++++++ tests_requirements.txt | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bedc43e..30f7d70a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## [Unreleased] +### Bugfixes + +- Fixed unexpected behavior from the `obj_or_str` utility function that prevented `Feature`-related functions from accepting `str` arguments. + +### Backstage + +- Updated minimum `black` version to avoid CVE-2026-32274 + ## [3.5.0] - 2026-03-12 ### General diff --git a/tests_requirements.txt b/tests_requirements.txt index d83fdc09..dca1f670 100644 --- a/tests_requirements.txt +++ b/tests_requirements.txt @@ -1,6 +1,6 @@ -r requirements.txt -black~=25.1.0 +black~=26.3.1 coverage flake8 isort From c12c910734972a8f83f69260fffbf26fb6874969 Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Tue, 14 Apr 2026 14:16:08 -0400 Subject: [PATCH 5/9] Update support Python versions --- .github/workflows/run-tests.yml | 2 +- CHANGELOG.md | 5 +++++ setup.py | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 2ac3e2af..136cc695 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 30f7d70a..1b907f9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [Unreleased] +### General + +- Added support for Python 3.14 +- Dropped support for Python 3.9 + ### Bugfixes - Fixed unexpected behavior from the `obj_or_str` utility function that prevented `Feature`-related functions from accepting `str` arguments. diff --git a/setup.py b/setup.py index d0cedd3e..c700948c 100644 --- a/setup.py +++ b/setup.py @@ -39,11 +39,11 @@ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries", ], ) From 22d5cd7f2edf3fc68c8d78c4fe807387fbebc1b2 Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Tue, 14 Apr 2026 14:21:10 -0400 Subject: [PATCH 6/9] Update GH Actions versions --- .github/workflows/run-tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 136cc695..4f28b5fe 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -14,9 +14,9 @@ jobs: python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -40,7 +40,7 @@ jobs: - name: Check for missing kwargs run: python scripts/find_missing_kwargs.py - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v6 with: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} From 50da7b26146732d005889f9ace9f3460bd7ccfcc Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Tue, 14 Apr 2026 14:26:45 -0400 Subject: [PATCH 7/9] Prep for v3.6.0 release. Update deploy actions --- .github/workflows/deploy.yml | 4 ++-- CHANGELOG.md | 6 +++++- canvasapi/__init__.py | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 54466a09..2ffb4b10 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -9,10 +9,10 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 - name: Install build dependency run: pip install build diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b907f9d..96377c41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## [Unreleased] +## [3.6.0] - 2026-04-14 + ### General - Added support for Python 3.14 @@ -14,6 +16,7 @@ ### Backstage - Updated minimum `black` version to avoid CVE-2026-32274 +- Updated various GitHub Actions ## [3.5.0] - 2026-03-12 @@ -680,7 +683,8 @@ Huge thanks to [@liblit](https://github.com/liblit) for lots of issues, suggesti - Fixed some incorrectly defined parameters - Fixed an issue where tests would fail due to an improperly configured requires block -[Unreleased]: https://github.com/ucfopen/canvasapi/compare/v3.5.0...develop +[Unreleased]: https://github.com/ucfopen/canvasapi/compare/v3.6.0...develop +[3.6.0]: https://github.com/ucfopen/canvasapi/compare/v3.5.0...v3.6.0 [3.5.0]: https://github.com/ucfopen/canvasapi/compare/v3.4.0...v3.5.0 [3.4.0]: https://github.com/ucfopen/canvasapi/compare/v3.3.0...v3.4.0 [3.3.0]: https://github.com/ucfopen/canvasapi/compare/v3.2.0...v3.3.0 diff --git a/canvasapi/__init__.py b/canvasapi/__init__.py index 46277f79..f054979e 100644 --- a/canvasapi/__init__.py +++ b/canvasapi/__init__.py @@ -4,4 +4,4 @@ __all__ = ["Canvas"] -__version__ = "3.5.0" +__version__ = "3.6.0" From ddcacce3a7c53cad330771a673393f89c370b316 Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Tue, 14 Apr 2026 14:30:21 -0400 Subject: [PATCH 8/9] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96377c41..98b43e30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Updated minimum `black` version to avoid CVE-2026-32274 - Updated various GitHub Actions +- Update readthedocs config to include build info ## [3.5.0] - 2026-03-12 From 513588f3077fbc7470c28ae56fa541b5ddce6849 Mon Sep 17 00:00:00 2001 From: Matthew Emond Date: Thu, 16 Apr 2026 00:17:46 -0400 Subject: [PATCH 9/9] Update release date for 3.6.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98b43e30..15827094 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [Unreleased] -## [3.6.0] - 2026-04-14 +## [3.6.0] - 2026-04-16 ### General