Skip to content

Commit

Permalink
Merge pull request #555 from ucfopen/develop
Browse files Browse the repository at this point in the history
Release v3.0.0
  • Loading branch information
Thetwam committed Sep 21, 2022
2 parents 2ac9979 + 6364ad6 commit 2859820
Show file tree
Hide file tree
Showing 54 changed files with 1,889 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: ['3.7', '3.8', '3.9', '3.10']

steps:
- uses: actions/checkout@v2
Expand Down
8 changes: 8 additions & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ Patches and Suggestions
- Anthony Rodriguez [@AnthonyRodriguez726](https://github.com/AnthonyRodriguez726)
- Ashutosh Saxena [@Xx-Ashutosh-xX](https://github.com/Xx-Ashutosh-xX)
- Ben Liblit [@liblit](https://github.com/liblit)
- Benjamin Reed [@breed](https://github.com/breed)
- Bill Wrbican [@wjw27](https://github.com/wjw27)
- [@Birdmaaan4](https://github.com/Birdmaaan4)
- [@blepabyte](https://github.com/blepabyte)
- Bradford Lynch [@bradfordlynch](https://github.com/bradfordlynch)
- Brian Bennett [@bennettscience](https://github.com/bennettscience)
- Bruce Spang [@brucespang](https://github.com/brucespang)
- Catherine Abbruzzese [@cat0698](https://github.com/cat0698))
- Cameron Cuff [@ctcuff](https://github.com/ctcuff)
- Craig Thompson [@craigdsthompson](https://github.com/craigdsthompson)
- Dalton Durst [@UniversalSuperBox](https://github.com/UniversalSuperBox)
- Damian Sweeney [@damianfs](https://github.com/damianfs)
- Daniel Brinkman [@DanBrink91](https://github.com/DanBrink91)
Expand All @@ -39,6 +42,7 @@ Patches and Suggestions
- Elli Howard [@qwertynerd97](https://github.com/qwertynerd97)
- Erik Tews [@eriktews](https://github.com/eriktews)
- Ethan Finlay [@atarisafari](https://github.com/atarisafari)
- Gabriel Garfinkel [@ggarfink](https://github.com/ggarfink)
- Gabriela Dijkhoffz [@gdijkhoffz](https://github.com/gdijkhoffz)
- Harlan Colclough [@hcolclou](https://github.com/hcolclou)
- Henry Acevedo [@Colombiangmr](https://github.com/Colombiangmr)
Expand All @@ -51,6 +55,7 @@ Patches and Suggestions
- Jonathan Guilbe [@JonGuilbe](https://github.com/JonGuilbe)
- Jose Silveti [@jrsilveti](https://github.com/jrsilveti)
- Joshua Salzedo [@theunkn0wn1](https://github.com/theunkn0wn1)
- [@kailukaitisBrendan](https://github.com/kailukaitisBrendan)
- Keegan Berry [@keeeeeegan](https://github.com/keeeeeegan)
- Kenny Perez [@kennygperez](https://github.com/kennygperez)
- [@kensler](https://github.com/kensler)
Expand All @@ -68,10 +73,13 @@ Patches and Suggestions
- Philip Carter [@phillyc](https://github.com/phillyc)
- Ralph Baird [@rmanbaird](https://github.com/rmanbaird)
- [@Screeeech](https://github.com/Screeeech)
- Shane Rosenkrantz [@shaneros](https://github.com/shaneros)
- Sigurður Baldursson [@sigurdurb](https://github.com/sigurdurb)
- Spencer Rogers [@spencer1248](https://github.com/spencer1248)
- Stephen Woosley [@stephenwoosley](https://github.com/stephenwoosley)
- Steven Bell [@stevenbell](https://github.com/stevenbell)
- Steven Williams [@onomou](https://github.com/onomou)
- Tinson Lai [@laitingsheng](https://github.com/laitingsheng)
- Toan Vu [@vutoan1245](https://github.com/vutoan1245)
- [@Tobiaqs](https://github.com/Tobiaqs)
- Tuan Pham [@tuanvpham](https://github.com/tuanvpham)
Expand Down
32 changes: 31 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,35 @@

## [Unreleased]

## [3.0.0] - 2022-09-21

### New Endpoint Coverage

- Delete a Rubric (Thanks, [@ggarfink](https://github.com/ggarfink))
- Grade Change Log for Assignments, Courses, and Users (Thanks, [@matthewf-ucsd](https://github.com/matthewf-ucsd))
- Content Migrations: List items for selective import (Thanks, [@matthewf-ucsd](https://github.com/matthewf-ucsd))
- List observers of a User (Thanks, [@bennettscience](https://github.com/bennettscience))
- ePortfolio endpoints (Thanks, [@Birdmaaan4](https://github.com/Birdmaaan4) and [@bennettscience](https://github.com/bennettscience))
- Delete an Admin from an Account (Thanks, [@shaneros](https://github.com/shaneros))

### General

- Added support for Python 3.10
- Smart DateTimes now support any ISO 8601 format, including time offsets. (Thanks, [@kailukaitisBrendan](https://github.com/kailukaitisBrendan))

### Bugfixes

- Fixed an issue where kwargs were not passed along to Canvas in `User.get_profile()`. (Thanks, [@breed](https://github.com/breed))

### Breaking Changes

- Dropped support for Python 3.6
- Update `QuizSubmission.get_submission_events` to return a `PaginatedList`. (Thanks, [@stevenbell](https://github.com/stevenbell))
- Update `Course.get_course_level_student_summary_data` to return a `PaginatedList` of `CourseStudentSummary` items instead of a dictionary. (Thanks, [@craigdsthompson](https://github.com/craigdsthompson))
- Update `Course.get_outcome_results` to return a `PaginatedList` of `OutcomeResult` items instead of a dictionary. (Thanks, [@bennettscience](https://github.com/bennettscience))
- Remove unnecessary `id` parameter from `delete`, `reorder_question_group`, and `update` methods in `QuizGroup` class. (Thanks, [@kailukaitisBrendan](https://github.com/kailukaitisBrendan))
- Update `Submission` to return attachments as `File` objects instead of dictionaries. (Thanks, [@laitingsheng](https://github.com/laitingsheng))

## [2.2.0] - 2021-03-25

### New Endpoint Coverage
Expand Down Expand Up @@ -534,7 +563,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/v2.2.0...develop
[Unreleased]: https://github.com/ucfopen/canvasapi/compare/v3.0.0...develop
[3.0.0]: https://github.com/ucfopen/canvasapi/compare/v2.2.0...v3.0.0
[2.2.0]: https://github.com/ucfopen/canvasapi/compare/v2.1.0...v2.2.0
[2.1.0]: https://github.com/ucfopen/canvasapi/compare/v2.0.0...v2.1.0
[2.0.0]: https://github.com/ucfopen/canvasapi/compare/v1.0.0...v2.0.0
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
[![License](https://img.shields.io/pypi/l/canvasapi.svg)](https://pypi.python.org/pypi/canvasapi)
[![Python Versions](https://img.shields.io/pypi/pyversions/canvasapi.svg)](https://pypi.python.org/pypi/canvasapi)
[![Documentation Status](https://readthedocs.org/projects/canvasapi/badge/?version=stable)](http://canvasapi.readthedocs.io/en/stable/?badge=stable)
[![Build Status](https://travis-ci.org/ucfopen/canvasapi.svg?branch=master)](https://travis-ci.org/ucfopen/canvasapi)
[![Coverage Status](https://coveralls.io/repos/github/ucfopen/canvasapi/badge.svg?branch=master)](https://coveralls.io/github/ucfopen/canvasapi?branch=master)
[![Join UCF Open Slack Discussions](https://ucf-open-slackin.herokuapp.com/badge.svg)](https://ucf-open-slackin.herokuapp.com/)
[![Build Status](https://github.com/ucfopen/canvasapi/actions/workflows/run-tests.yml/badge.svg?branch=develop)](https://github.com/ucfopen/canvasapi/actions)
[![codecov](https://codecov.io/gh/ucfopen/canvasapi/branch/develop/graph/badge.svg?token=CFNpp8f56M)](https://codecov.io/gh/ucfopen/canvasapi)
[![Join UCF Open Slack Discussions](https://badgen.net/badge/icon/ucfopen?icon=slack&label=slack&color=pink)](https://dl.ucf.edu/join-ucfopen)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

# CanvasAPI
Expand Down Expand Up @@ -167,4 +167,4 @@ If you have a project that uses CanvasAPI that you'd like to promote, please con

## Contact Us

Need help? Have an idea? Feel free to check out our [Discussions](https://github.com/ucfopen/canvasapi/discussions) board. Just want to say hi or get extended spport? Come join us on the [UCF Open Slack Channel](https://ucf-open-slackin.herokuapp.com) and join the `#canvasapi` channel!
Need help? Have an idea? Feel free to check out our [Discussions](https://github.com/ucfopen/canvasapi/discussions) board. Just want to say hi or get extended spport? Come join us on the [UCF Open Slack Channel](https://dl.ucf.edu/join-ucfopen) and join the `#canvasapi` channel!
2 changes: 1 addition & 1 deletion canvasapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

__all__ = ["Canvas"]

__version__ = "2.2.0"
__version__ = "3.0.0"
25 changes: 25 additions & 0 deletions canvasapi/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,31 @@ def delete(self, **kwargs):

return response.json().get("workflow_state") == "deleted"

def delete_admin(self, user, **kwargs):
"""
Remove an admin role from an existing user in the current account.
:calls: `DELETE /api/v1/accounts/:account_id/admins/:user_id \
<https://canvas.instructure.com/doc/api/admins.html#method.admins.destroy>`_
:param user: The user object or ID to remove as admin.
:type user: :class:`canvasapi.user.User` or int
:rtype: :class:`canvasapi.account.Admin`
"""
from canvasapi.user import User

user_id = obj_or_id(user, "user", (User,))
kwargs["user_id"] = user_id

response = self._requester.request(
"DELETE",
"accounts/{}/admins/{}".format(self.id, user_id),
_kwargs=combine_kwargs(**kwargs),
)

return Admin(self._requester, response.json())

def delete_grading_period(self, grading_period, **kwargs):
"""
Delete a grading period for an account.
Expand Down
21 changes: 21 additions & 0 deletions canvasapi/assignment.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from canvasapi.canvas_object import CanvasObject
from canvasapi.exceptions import CanvasException, RequiredFieldMissing
from canvasapi.grade_change_log import GradeChangeEvent
from canvasapi.paginated_list import PaginatedList
from canvasapi.peer_review import PeerReview
from canvasapi.progress import Progress
Expand Down Expand Up @@ -76,6 +77,26 @@ def edit(self, **kwargs):

return Assignment(self._requester, response.json())

def get_grade_change_events(self, **kwargs):
"""
Returns the grade change events for the assignment.
:calls: `/api/v1/audit/grade_change/assignments/:assignment_id \
<https://canvas.instructure.com/doc/api/grade_change_log.html#method.grade_change_audit_api.for_assignment>`_
:rtype: :class:`canvasapi.paginated_list.PaginatedList` of
:class:`canvasapi.grade_change_log.GradeChangeEvent`
"""

return PaginatedList(
GradeChangeEvent,
self._requester,
"GET",
"audit/grade_change/assignments/{}".format(self.id),
_root="events",
_kwargs=combine_kwargs(**kwargs),
)

def get_gradeable_students(self, **kwargs):
"""
List students eligible to submit the assignment.
Expand Down
22 changes: 22 additions & 0 deletions canvasapi/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from canvasapi.course import Course
from canvasapi.course_epub_export import CourseEpubExport
from canvasapi.current_user import CurrentUser
from canvasapi.eportfolio import EPortfolio
from canvasapi.exceptions import RequiredFieldMissing
from canvasapi.file import File
from canvasapi.folder import Folder
Expand Down Expand Up @@ -771,6 +772,27 @@ def get_current_user(self):
"""
return CurrentUser(self.__requester)

def get_eportfolio(self, eportfolio, **kwargs):
"""
Get an eportfolio by ID.
:param eportfolio: The object or ID of the eportfolio to retrieve.
:type eportfolio: :class: `canvasapi.eportfolio.EPortfolio` or int
:calls: `GET /api/v1/eportfolios/:id` \
`<https://canvas.instructure.com/doc/api/e_portfolios.html#method.eportfolios_api.show>`_
:rtype: :class:`canvasapi.eportfolio.EPortfolio`
"""
eportfolio_id = obj_or_id(eportfolio, "eportfolio", (EPortfolio,))
response = self.__requester.request(
"GET",
"eportfolios/{}".format(eportfolio_id),
_kwargs=combine_kwargs(**kwargs),
)

return EPortfolio(self.__requester, response.json())

def get_epub_exports(self, **kwargs):
"""
Return a list of epub exports for the associated course.
Expand Down
17 changes: 8 additions & 9 deletions canvasapi/canvas_object.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import re
from datetime import datetime

import arrow
import pytz

DATE_PATTERN = re.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z")


class CanvasObject(object):
"""
Expand Down Expand Up @@ -65,8 +61,11 @@ def set_attributes(self, attributes):
for attribute, value in attributes.items():
self.__setattr__(attribute, value)

# datetime field
if DATE_PATTERN.match(str(value)):
naive = datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ")
aware = naive.replace(tzinfo=pytz.utc)
try:
naive = arrow.get(str(value)).datetime
aware = naive.replace(tzinfo=pytz.utc) - naive.utcoffset()
self.__setattr__(attribute + "_date", aware)
except arrow.ParserError:
pass
except ValueError:
pass
47 changes: 47 additions & 0 deletions canvasapi/content_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,48 @@ def get_progress(self, **kwargs):
)
return Progress(self._requester, response.json())

def get_selective_data(self, **kwargs):
"""
Return the selective data associated with this content migration. Use this to get a list
of available objects to import for a migration created with 'waiting_for_select=True'.
:calls:
`GET
/api/v1/accounts/:account_id/content_migrations/:content_migration_id/selective_data
<https://canvas.instructure.com/doc/api/content_migrations.html#method.content_migrations.content_list>`_
or `GET
/api/v1/courses/:course_id/content_migrations/:content_migration_id/selective_data
<https://canvas.instructure.com/doc/api/content_migrations.html#method.content_migrations.content_list>`_
or `GET
/api/v1/groups/:group_id/content_migrations/:content_migration_id/selective_data
<https://canvas.instructure.com/doc/api/content_migrations.html#method.content_migrations.content_list>`_
or `GET
/api/v1/users/:user_id/content_migrations/:content_migration_id/selective_data
<https://canvas.instructure.com/doc/api/content_migrations.html#method.content_migrations.content_list>`_
:returns: Paginated List of of nodes available for selection in this migration
:rtype: :class:`canvasapi.content_migration.ContentMigrationSelectionNode`
"""
from canvasapi.content_migration import ContentMigrationSelectionNode

return PaginatedList(
ContentMigrationSelectionNode,
self._requester,
"GET",
"{}s/{}/content_migrations/{}/selective_data".format(
self._parent_type, self._parent_id, self.id
),
{
"context_type": self._parent_type,
"context_id": self._parent_id,
"content_migration_id": self.id,
},
_kwargs=combine_kwargs(**kwargs),
)

def update(self, **kwargs):
"""
Update an existing content migration.
Expand Down Expand Up @@ -220,6 +262,11 @@ def update(self, **kwargs):
return False


class ContentMigrationSelectionNode(CanvasObject):
def __str__(self):
return "{}".format(self.type)


class MigrationIssue(CanvasObject):
def __str__(self):
return "{}: {}".format(self.id, self.description)
Expand Down

0 comments on commit 2859820

Please sign in to comment.