Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Course.get_enabled_features throws AttributeError: 'str' object has no attribute 'update' #584

Closed
jwals23 opened this issue Jan 19, 2023 · 1 comment · Fixed by #592
Closed
Labels

Comments

@jwals23
Copy link

jwals23 commented Jan 19, 2023

Describe the bug

When trying to access the enabled features for a course using Course.get_enabled_features, an AttributeError is thrown. Full output from an ipython session is below. I am guessing that this is because the API call to /features/enabled does not return output in the same format as the call to /features (see curl output below), but I have not been able to verify that this is the cause of the problem.

To Reproduce

Steps to reproduce the behavior:

In [18]: canvas = Canvas(API_URL, API_KEY)

In [19]: course = canvas.get_course(COURSE_ID)

In [20]: features = course.get_features()

In [21]: type(features)
Out[21]: canvasapi.paginated_list.PaginatedList

In [22]: features[0]
Out[22]: Feature(_requester=<canvasapi.requester.Requester object at 0x7fca7374aad0>, feature=analytics_2,<. . .>

In [23]: enabled_features = course.get_enabled_features()

In [24]: type(enabled_features)
Out[24]: canvasapi.paginated_list.PaginatedList

In [25]: enabled_features[0]
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-25-59616ad1fc05> in <module>
----> 1 enabled_features[0]

/usr/local/lib/python3.10/dist-packages/canvasapi/paginated_list.py in __getitem__(self, index)
     13             if index < 0:
     14                 raise IndexError("Cannot negative index a PaginatedList")
---> 15             self._get_up_to_index(index)
     16             return self._elements[index]
     17         else:

/usr/local/lib/python3.10/dist-packages/canvasapi/paginated_list.py in _get_up_to_index(self, index)
     87     def _get_up_to_index(self, index):
     88         while len(self._elements) <= index and self._has_next():
---> 89             self._grow()
     90
     91     def _grow(self):

/usr/local/lib/python3.10/dist-packages/canvasapi/paginated_list.py in _grow(self)
     90
     91     def _grow(self):
---> 92         new_elements = self._get_next_page()
     93         self._elements += new_elements
     94         return new_elements

/usr/local/lib/python3.10/dist-packages/canvasapi/paginated_list.py in _get_next_page(self)
     80         for element in data:
     81             if element is not None:
---> 82                 element.update(self._extra_attribs)
     83                 content.append(self._content_class(self._requester, element))
     84

Expected behavior

get_enabled_features() should return a response of the same format as get_features()

Environment information

  • Python version: 3.10.6
  • CanvasAPI version: 3.0.0

Additional context

The API call to /features/enabled returns a simple list as output, rather than a full dict of feature information.

curl "https://<API_URL>/api/v1/courses/<COURSE_ID>/features" -H "Authorization: Bearer <API_TOKEN>"
[{"feature":"analytics_2","applies_to":"Course","beta":true,"type":"feature_option","display_name":"New Course and User Analytics","description":"Show new analytics for course and user data. Data may take 24 hours to appear in New Analytics after setting this feature flag to ON. For full details, please see the \u003ca href=\"https://community.canvaslms.com/t5/New-Analytics-Users/gh-p/analytics\"\u003eNew Analytics user group\u003c/a\u003e in the Canvas Community.","feature_flag":{"context_id":1,"context_type":"Account","feature":"analytics_2","state":"allowed_on","locking_account_id":null,"transitions":{"off":{"locked":false},"on":{"locked":false}},"locked":false,"parent_state":"allowed_on"}},{"feature":"anonymous_instructor_annotations","applies_to":"Course","root_opt_in":false,"type":"setting","display_name":"Anonymous Instructor Annotations","description":"Anonymize all instructor comments and annotations within DocViewer","feature_flag":{"context_id":1,"context_type":"Account","feature":"anonymous_instructor_annotations","state":"on","locking_account_id":null,"transitions":{"off":{"locked":false}},"locked":true,"parent_state":"on"}},{"feature":"epub_export","applies_to":"Course","root_opt_in":true,"type":"setting","display_name":"ePub Exporting","description":"This enables users to generate and download course ePub.","feature_flag":{"context_id":1,"context_type":"Account","feature":"epub_export","state":"allowed","locking_account_id":null,"transitions":{"off":{"locked":false},"on":{"locked":false}},"locked":false,"parent_state":"allowed"}},{"feature":"final_grades_override","applies_to":"Course","root_opt_in":true,"type":"setting","display_name":"Final Grade Override","description":"Enable ability to alter the final grade for the entire course without changing scores for assignments.","feature_flag":{"context_id":65221,"context_type":"Course","feature":"final_grades_override","state":"on","locking_account_id":null,"transitions":{"off":{"locked":true},"on":{}},"locked":false,"parent_state":"allowed"}},{"feature":"outcome_gradebook","applies_to":"Course","root_opt_in":false,"type":"setting","display_name":"Learning Mastery Gradebook","description":"Learning Mastery Gradebook provides a way for teachers to quickly view student and course\nprogress on course learning outcomes. Outcomes are presented in a Gradebook-like\nformat and student progress is displayed both as a numerical score and as mastered/near\nmastery/remedial.","feature_flag":{"feature":"outcome_gradebook","state":"allowed","transitions":{"off":{"locked":false},"on":{"locked":false}},"locked":false,"parent_state":"allowed"}},{"feature":"quizzes_next","applies_to":"Course","type":"feature_option","display_name":"New Quizzes","description":"This feature enhances the Canvas experience for quizzing. When this flag is enabled, the New Quizzes tool will be available. For full details, please see the \u003ca href=\"https://community.canvaslms.com/t5/New-Quizzes-Users/gh-p/quizzes\"\u003eNew Quizzes user group\u003c/a\u003e in the Canvas Community.","feature_flag":{"context_id":1,"context_type":"Account","feature":"quizzes_next","state":"on","locking_account_id":null,"transitions":{"off":{"locked":false}},"locked":true,"parent_state":"on"}}]

curl "https://<API_URL>/api/v1/courses/<COURSE_ID>/features/enabled" -H "Authorization: Bearer <API_TOKEN>"
["analytics_2","anonymous_instructor_annotations","final_grades_override","quizzes_next","quiz_log_auditing","anonymous_marking","moderated_grading","new_quizzes_by_default"]

This is confirmed by the Canvas API docs: https://canvas.instructure.com/doc/api/feature_flags.html#method.feature_flags.enabled_features.

@jwals23 jwals23 added the bug label Jan 19, 2023
@bennettscience
Copy link
Contributor

bennettscience commented Feb 18, 2023

I did some digging tonight and it throws an error because the enabled endpoint doesn't return the Link header like it should for paginated responses. The Canvas docs say it gives a paginated response, but for some reason it does not. Maybe it's because the response is so much smaller only returning feature titles instead of objects?

A hotfix would be to build your own request using course._requester.request. You'll get a list back as the response. For a permanent fix, the return on get_enabled_features in course.py needs to be adjusted here. I can submit a PR pretty quickly if everyone is okay with only returning JSON for now.

bennettscience added a commit to bennettscience/canvasapi that referenced this issue Feb 18, 2023
bennettscience added a commit to bennettscience/canvasapi that referenced this issue Mar 9, 2023
The library expected a paginated response from Canvas, but the
API returns a list of strings for features enabled. This updates
the library to return plain JSON instead of a `PaginatedList` for
the account, course, and user modules.
bennettscience added a commit to bennettscience/canvasapi that referenced this issue Mar 9, 2023
Update account, course, and user modules to return JSON instead
of a paginated list.
bennettscience added a commit to bennettscience/canvasapi that referenced this issue Mar 9, 2023
Formatting fixes for several files

When requesting enabled features, Canvas returns a list of strings
for each feature instead of objects. This refactors the account,
course, and user modules to return JSON instead of a
`PaginatedList`.
@Thetwam Thetwam added this to the CanvasAPI v3.1.0 milestone Apr 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants