diff --git a/modules.txt b/modules.txt index 3663eb98..a73327c9 100644 --- a/modules.txt +++ b/modules.txt @@ -14,3 +14,4 @@ PyMySQL tempfile re shutil +pycanvas diff --git a/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/INSTALLER b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/LICENSE b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/LICENSE new file mode 100644 index 00000000..7ce0f1ea --- /dev/null +++ b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 PGower + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/METADATA b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/METADATA new file mode 100644 index 00000000..a3acf1fe --- /dev/null +++ b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/METADATA @@ -0,0 +1,23 @@ +Metadata-Version: 2.1 +Name: pycanvas +Version: 0.2.6 +Summary: Client library for the Instructure Canvas REST api. +Home-page: https://github.com/PGower/PyCanvas +Author: Paul Gower +Author-email: p.gower@gmail.com +License: BSD +Download-URL: https://github.com/PGower/PyCanvas/releases +Keywords: canvas,instructure +Platform: UNKNOWN +Classifier: Development Status :: 3 - Alpha +Classifier: Environment :: Web Environment +Classifier: Programming Language :: Python +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Dist: requests + +A client library for accessing the Instructure Canvas rest library. Mostly generated by the swagger-codegen-cli tool. + + diff --git a/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/RECORD b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/RECORD new file mode 100644 index 00000000..82260b57 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/RECORD @@ -0,0 +1,290 @@ +pycanvas-0.2.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pycanvas-0.2.6.dist-info/LICENSE,sha256=9fml3Omwx5Cf1rbk8yn_08ZDuMKkqGyz6bHlb5b6Yco,1092 +pycanvas-0.2.6.dist-info/METADATA,sha256=XmnxeBJJFydM4Gjqm7a0VnT5tnU9ImSjtIn0p3tJGpQ,841 +pycanvas-0.2.6.dist-info/RECORD,, +pycanvas-0.2.6.dist-info/WHEEL,sha256=OhvoqDhCIO-nqAap0bTP_Ct4OjSealO2NkC2junPf8w,98 +pycanvas-0.2.6.dist-info/top_level.txt,sha256=dwb5KGGfQxgEPM8jotn63g6ZTE_En_aUZuAhR-J_9Is,9 +pycanvas/__init__.py,sha256=APDY_qLH9snh4CFDWfR9s601TXcZ46_n5u_N1u-Eyx4,285 +pycanvas/__init__.pyc,, +pycanvas/apis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pycanvas/apis/__init__.pyc,, +pycanvas/apis/account_domain_lookups.py,sha256=KJdP9kmW4L13b4z2fDK7uUJJZn0rxPgpGI-uEJjWGeU,1736 +pycanvas/apis/account_domain_lookups.pyc,, +pycanvas/apis/account_notifications.py,sha256=Qa0Z4uhjfUG8Eu-2PrRHdKwuBevu_nK8eviwIZgsSqY,11882 +pycanvas/apis/account_notifications.pyc,, +pycanvas/apis/account_reports.py,sha256=RzFTZKO3XlXqakBRYnph5BHyTezdR5TvQl9njFUxGkc,15167 +pycanvas/apis/account_reports.pyc,, +pycanvas/apis/accounts.py,sha256=I7W4gWXRQ99UkxbUuxOO2VLaSMyvUenC_zbetUBpiXc,24615 +pycanvas/apis/accounts.pyc,, +pycanvas/apis/admins.py,sha256=n3Yc3GlBZowTrU6xgtXwFe5e5Lr2Wa3qbkqKK_6bQdg,6024 +pycanvas/apis/admins.pyc,, +pycanvas/apis/announcement_external_feeds.py,sha256=Ovf5qlmrzpRWuoS5elD6boKa80Fxaa16BxY6YZ8e6cg,9151 +pycanvas/apis/appointment_groups.py,sha256=A4wvEzTLdpWEi4FE7Qlh-Q_xOfPSqswDeSsuRfM6tus,33736 +pycanvas/apis/assignment_groups.py,sha256=DXg7tvlz5QX-W-ZusF-99tS0NZ5YZdnyArqtdmDWqTo,15084 +pycanvas/apis/assignment_groups.pyc,, +pycanvas/apis/assignments.py,sha256=qF2QhpEg72tBlKv0GLn_xgkYdhOxAC9pI4c0qqXIvfk,102076 +pycanvas/apis/assignments.pyc,, +pycanvas/apis/authentications_log.py,sha256=CBpIqg6LV5VRVC14NBzG1xl4T2uHrQzbOuSLSBi_TgM,6210 +pycanvas/apis/authentications_log.pyc,, +pycanvas/apis/base.py,sha256=dRoA96FhpkZ8TXajPr1vwSQWM2UJ3x60g5RQj2K1kJ8,7209 +pycanvas/apis/base.pyc,, +pycanvas/apis/calendar_events.py,sha256=MdbaLhIoes-G3I01zfhuUolfBGQSgM-E_pGKfE27hS0,48655 +pycanvas/apis/collaborations.py,sha256=E48WWDpEhovGbBMsSOrNWA8JUQ64Hcr049LKWdfYbrU,10940 +pycanvas/apis/collaborations.pyc,, +pycanvas/apis/comm_messages.py,sha256=FCyjrz2EjitEkitCG_JohQ4OFz8Jp5TEGVvudV59zAc,5876 +pycanvas/apis/communication_channels.py,sha256=-s1z1tZeXiWweiMsYZ8XgA-v_Q_ImsCQLDubf7ACMAc,8280 +pycanvas/apis/communication_channels.pyc,, +pycanvas/apis/conferences.py,sha256=KsU4nKn8ljEb3D43OFSpOhTBzUyf-ok_2I8cgZCLRCI,11193 +pycanvas/apis/conferences.pyc,, +pycanvas/apis/content_exports.py,sha256=uoA_AjP4FsNltTv-O-FxE5Tf10E0lhLV1_TSpxYuWZU,13341 +pycanvas/apis/content_exports.pyc,, +pycanvas/apis/content_migrations.py,sha256=-8d3JjprVaESYPKzS2P74pjgkWzIorXbSTAe0nkra2w,67646 +pycanvas/apis/conversations.py,sha256=JzHoAbn8BDh8jLthI3LT7poCVlwOu31atD7CTFCH66c,30488 +pycanvas/apis/conversations.pyc,, +pycanvas/apis/course_audit_log.py,sha256=bvVLiuxcbbr-1D4sgqQot2HPTtrvKch53DKfE_-_8gU,11942 +pycanvas/apis/course_audit_log.pyc,, +pycanvas/apis/course_quiz_extensions.py,sha256=zlBFgChrdR8--aPuEU368txz-_9Ow1RcD9nPvAd22MA,5792 +pycanvas/apis/course_quiz_extensions.pyc,, +pycanvas/apis/courses.py,sha256=nQSdMYhzTQh4b712I7JABMmw8LxNrKk_5RqsOySk5EQ,92728 +pycanvas/apis/courses.pyc,, +pycanvas/apis/custom_gradebook_columns.py,sha256=eJHZYs21GqNY2vIR4i0XQHjByTCVYPa0n7RLmAVjlyc,10020 +pycanvas/apis/custom_gradebook_columns.pyc,, +pycanvas/apis/discussion_topics.py,sha256=1Ajzsxp5BrlLrarohGu9ZaPQRpGXDxv_qzxV2SUfoso,96685 +pycanvas/apis/discussion_topics.pyc,, +pycanvas/apis/document_previews.py,sha256=8naJBAiki-fvEddRjcHu-2i87CyDeedAZ3dukE1M_ic,558 +pycanvas/apis/document_previews.pyc,, +pycanvas/apis/enrollment_terms.py,sha256=3l3MWy13sKPfV2_Ble81_li40iSWK8slSw8CU-pgJfI,8632 +pycanvas/apis/enrollment_terms.pyc,, +pycanvas/apis/enrollments.py,sha256=22LDk41rav8lHcFRMt1MosxPbpqBLbp7S49zMWmlJwA,53844 +pycanvas/apis/external_tools.py,sha256=_ahAI5Ud4ccax20VhBqSl8LjeaEduJQRtsZaWQaOq7g,47432 +pycanvas/apis/favorites.py,sha256=v_ObwpjAM6Smwlrnj096zIgzX4HGuDpDj36VDlDG6Ng,7196 +pycanvas/apis/feature_flags.py,sha256=GNyxx6-fYcwL_eQu8z2xdeC6UH-stbWUKD1y9q2_6HQ,23622 +pycanvas/apis/feature_flags.pyc,, +pycanvas/apis/files.py,sha256=e8mYrR0m-SCSQSFhK-cyifvVwQlhF5-pBd7R73tTD0w,81904 +pycanvas/apis/files.pyc,, +pycanvas/apis/grade_change_log.py,sha256=JHbBYqRdF6CEOBh08mVpt58CHXIJkslmAVg-SlLL_wI,12481 +pycanvas/apis/grade_change_log.pyc,, +pycanvas/apis/gradebook_history.py,sha256=S6CwiXknb9YifyRb1YgmpEFa0fwYzI-mp-DCxdlux_0,20700 +pycanvas/apis/gradebook_history.pyc,, +pycanvas/apis/grading_periods.py,sha256=6Ejl_wnvGVlZwz3brn-MvghmX0c3uwyL4zMjyCpEnXI,8484 +pycanvas/apis/grading_periods.pyc,, +pycanvas/apis/grading_standards.py,sha256=M_xa72pw7hwNpy2RHwOuj659cW-7GkIea9KF7z4RMHQ,9800 +pycanvas/apis/grading_standards.pyc,, +pycanvas/apis/group_categories.py,sha256=65unf9Pse-M285q7HMzYl3hyLzCDTxfWSwBcK7aOHf8,19932 +pycanvas/apis/group_categories.pyc,, +pycanvas/apis/groups.py,sha256=6FDR10mj02nvUk1eeDG6r0cn_OLu-AlUgeF2n3fphPg,37402 +pycanvas/apis/live_assessments.py,sha256=aI5ok-OaQ1xQZP1qZQNLrX8cfqk1OOD-QNn9ufXBGJU,8535 +pycanvas/apis/live_assessments.pyc,, +pycanvas/apis/logins.py,sha256=QakUS9aXBz8j_mRuAv2CIAnKcPDD3_qC220C-xcW6AM,7036 +pycanvas/apis/logins.pyc,, +pycanvas/apis/modules.py,sha256=sxlohXXO14EKHRRZk5sQ7Ks689lUqJ_jFsa8Azuj7LE,54742 +pycanvas/apis/modules.pyc,, +pycanvas/apis/notification_preferences.py,sha256=p72Xg3AEoJD5A2PWXxCVdjC0sGEV8YbyP9kOTnwsQQk,13830 +pycanvas/apis/outcome_groups.py,sha256=-E0Q_8l8qMDM5eOGT9T_PyR0PDIZOu-42_E3UleMJI4,70387 +pycanvas/apis/outcome_results.py,sha256=hQ2-NLikD55b4LPRxWx9g_mJQTvbvz_WhQVbEDZffag,15142 +pycanvas/apis/outcome_results.pyc,, +pycanvas/apis/outcomes.py,sha256=6DDUA0onvHxmb4zq_538Vw-6eCCP0ND5yu4IWcqcgeY,11939 +pycanvas/apis/pages.py,sha256=4OGUybOzA4WN8GoP8Ycw6RNKcUctZ9mf-MH7VdjSdEk,40228 +pycanvas/apis/pages.pyc,, +pycanvas/apis/poll_choices.py,sha256=ZyLOCTp4yXYAKX7Ynfug3V4wNGECGOWYY5Kb-Hiewoo,7701 +pycanvas/apis/poll_choices.pyc,, +pycanvas/apis/poll_sessions.py,sha256=X6ty7llAh9OhQY2XiGSoLQeWY5s41nVrxBlBKCXlcYs,12723 +pycanvas/apis/poll_sessions.pyc,, +pycanvas/apis/poll_submissions.py,sha256=LdMg89u6euw2gX7XMBe4xT0yk58FfjpGxPGSehVkRHw,4547 +pycanvas/apis/poll_submissions.pyc,, +pycanvas/apis/polls.py,sha256=653lrhGBUhrslL8RV697S3rhxeb85rcnkfrXEWOofkQ,6653 +pycanvas/apis/polls.pyc,, +pycanvas/apis/progress.py,sha256=TiT--tU2EpZIBPpdGpIGwDyqLlz6GXw_22dLHJeUJTI,5763 +pycanvas/apis/progress.pyc,, +pycanvas/apis/quiz_assignment_overrides.py,sha256=J6VBJ5bPAmgpGQf4Zqd0t4cajQwkFWEig1TvY_I-JGg,7471 +pycanvas/apis/quiz_assignment_overrides.pyc,, +pycanvas/apis/quiz_extensions.py,sha256=oN1YzI3hPS1erwQ8kpFaJO5e3dg3QLvHHzTMD1B7qIE,6265 +pycanvas/apis/quiz_extensions.pyc,, +pycanvas/apis/quiz_ip_filters.py,sha256=q80R14fU1s2q--uMtV-51PAo6Btd0ksRq7cvcJ7zh4w,2825 +pycanvas/apis/quiz_ip_filters.pyc,, +pycanvas/apis/quiz_question_groups.py,sha256=HrFsLbXRMlLg3OA2abqUs5QghaJH054UfXUMcXxCZ8Y,10706 +pycanvas/apis/quiz_question_groups.pyc,, +pycanvas/apis/quiz_questions.py,sha256=3qx2QCrYUTb9iixXVcTOZdP4GdWFBu8UqeNx1YWpgmQ,25992 +pycanvas/apis/quiz_questions.pyc,, +pycanvas/apis/quiz_reports.py,sha256=lfrhX3ecQC17bQECMD7ODH2CnLtJmGlTCNr1zmczMO4,13113 +pycanvas/apis/quiz_reports.pyc,, +pycanvas/apis/quiz_statistics.py,sha256=AkP_XIRRl1SsyFxb-8CkFpPAGy5MO9jSNjI-KEh7aQw,18137 +pycanvas/apis/quiz_statistics.pyc,, +pycanvas/apis/quiz_submission_events.py,sha256=aVEDhEKPWuDMuNlOHLBXrYHZdE5NU8CFOH9G_4slpWE,4536 +pycanvas/apis/quiz_submission_events.pyc,, +pycanvas/apis/quiz_submission_files.py,sha256=vLdMIUYCKmt0AM0ddelbBQtpJunN7GcJpX25FO16pxY,1971 +pycanvas/apis/quiz_submission_files.pyc,, +pycanvas/apis/quiz_submission_questions.py,sha256=RWVVABChd14YvfaVnWbc6ptpVdEB0vNSObWbVevk0uc,8470 +pycanvas/apis/quiz_submission_questions.pyc,, +pycanvas/apis/quiz_submission_user_list.py,sha256=SxmJk5o-7zTYxBz8iAjwj6O57bLyQrwYQOBKeBzRZ5s,2983 +pycanvas/apis/quiz_submission_user_list.pyc,, +pycanvas/apis/quiz_submissions.py,sha256=y5t7srSw7xSWesuWmQiLwoNruNPDPSpMT_OT5gTX_EU,21028 +pycanvas/apis/quiz_submissions.pyc,, +pycanvas/apis/quizzes.py,sha256=1yR4ekFQAq-bwDuLo0xCn65XH9lMonolxhtChu2yFbU,36968 +pycanvas/apis/quizzes.pyc,, +pycanvas/apis/roles.py,sha256=uvXAWoA_GI3naLY8CxHSex8PfFL3k590vLbpZlNYkFQ,23455 +pycanvas/apis/search.py,sha256=Q7B6b3zA62rY96kX40V_k1DzvjdPYOuj2vUXzdF5Yqs,8033 +pycanvas/apis/search.pyc,, +pycanvas/apis/sections.py,sha256=F0C3eb_V9smgviwt-OifENNXDgRq0tETxcehfEJE2LU,16754 +pycanvas/apis/sections.pyc,, +pycanvas/apis/services.py,sha256=JfHghqNsyfTw_PbHRr4iTzhAo0ateRRNAxLWHf56ivk,1614 +pycanvas/apis/services.pyc,, +pycanvas/apis/sis_imports.py,sha256=XBtJRPM8UUUX-Wf85cqUgwowuPUQ11W9G4QonoZ8QQI,28123 +pycanvas/apis/sis_imports.pyc,, +pycanvas/apis/submission_comments.py,sha256=Pw0AVWWF1rFSFKv-oYZAKJzMT50ZMPjSApBye7u8wSs,1863 +pycanvas/apis/submission_comments.pyc,, +pycanvas/apis/submissions.py,sha256=3C9hY_UwXYlgmegHhR_LAh1ZZMPM1XeanTVAB9YTMBM,75223 +pycanvas/apis/tabs.py,sha256=EynYGDOA_bdHvr1xu5YDbOktS8OR9b-PgwQWWrtHjBI,6385 +pycanvas/apis/tabs.pyc,, +pycanvas/apis/user_observees.py,sha256=H7YKB6owoNeX5m0ISTvka1cmxxJiHSqomBlQ41FWi3k,5629 +pycanvas/apis/user_observees.pyc,, +pycanvas/apis/users.py,sha256=qjQw_ang3I6g6d-ntpShiMs8munA6qEqxsuMu172nMU,92360 +pycanvas/apis/users.pyc,, +pycanvas/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pycanvas/tests/__init__.pyc,, +pycanvas/tests/account_domain_lookups.py,sha256=FzH1gNQAzmyrv4KSKLTG02Xs1F0QOXT_rze2xEBkvj0,736 +pycanvas/tests/account_domain_lookups.pyc,, +pycanvas/tests/account_notifications.py,sha256=guOXQ346xP8bGYzDLdmWpU6zsF73pPQmtwR5MhtMtQE,2181 +pycanvas/tests/account_notifications.pyc,, +pycanvas/tests/account_reports.py,sha256=A_1o3fOsI_CG-JKtcHfkENQYKqn9c9NGNwkYqQ9J1K8,1921 +pycanvas/tests/account_reports.pyc,, +pycanvas/tests/accounts.py,sha256=apMTFvFw8ZhCRcb8Es0R-9uYS2EdP6Znapf0pWfHKYI,2594 +pycanvas/tests/accounts.pyc,, +pycanvas/tests/admins.py,sha256=p5EJ9isedxrV5c1IhScP7frzuhH0x3g28whJShSYYR0,1225 +pycanvas/tests/admins.pyc,, +pycanvas/tests/announcement_external_feeds.py,sha256=4rfOav5MBjckbONXlqILgAtkQpMfc_6qtTgWm1KnxlY,2371 +pycanvas/tests/announcement_external_feeds.pyc,, +pycanvas/tests/appointment_groups.py,sha256=zV0r3zuIlae-Rv2J9230JdGNSC9NyPhbM6-Qyjj6caA,2676 +pycanvas/tests/appointment_groups.pyc,, +pycanvas/tests/assignment_groups.py,sha256=lEpyNimP-qk3EB9YuLo5pqozLpKtxnJflTvAqy9XwbU,2241 +pycanvas/tests/assignment_groups.pyc,, +pycanvas/tests/assignments.py,sha256=gUFJ1Rdyie_zaSnaYUYZw8-SAkJmI3Y4d-W5OjXmbz0,6038 +pycanvas/tests/assignments.pyc,, +pycanvas/tests/authentications_log.py,sha256=wgNcBFVlDFKUIJC5AP6bD9zVZ2d6r-iRx_UGKAzUxRw,1288 +pycanvas/tests/authentications_log.pyc,, +pycanvas/tests/calendar_events.py,sha256=2T49u0fQ9EXoja9YDZLadNZVpHMYbYvapnn1aSv9KZ8,3684 +pycanvas/tests/calendar_events.pyc,, +pycanvas/tests/collaborations.py,sha256=WkmrANh6tVwJd1ofjhNRH7Nua6j6s0oWatYWfygwVqg,1314 +pycanvas/tests/collaborations.pyc,, +pycanvas/tests/comm_messages.py,sha256=b4hjPKcWRhABiCR6pdZ7rJQp0CuTDN05QXBGQGVdorc,770 +pycanvas/tests/comm_messages.pyc,, +pycanvas/tests/communication_channels.py,sha256=XbyC7CtvMUnGWXA0AsLZaNvV3-T6zi-X76m-6Gjkz6o,1801 +pycanvas/tests/communication_channels.pyc,, +pycanvas/tests/conferences.py,sha256=4FBj1zdsN0VovBhrgjXFC8Mx5iAErlFHxDvB3R3W-HE,1009 +pycanvas/tests/conferences.pyc,, +pycanvas/tests/content_exports.py,sha256=z3JAWuxm76WPpXtQGV1mKwgt1Ybywul_UI0OBej_uOU,2934 +pycanvas/tests/content_exports.pyc,, +pycanvas/tests/content_migrations.py,sha256=fvLpNNP8SLdsL2oKKqjX0N-CJrGK8bgAo8ILwpvSHH8,10289 +pycanvas/tests/content_migrations.pyc,, +pycanvas/tests/conversations.py,sha256=iwJjgUWVmteo5HmFGM4qiRfHpfJhmn6JjexBA7QoU9o,3674 +pycanvas/tests/conversations.pyc,, +pycanvas/tests/course_audit_log.py,sha256=lvF4_9rXmBCFwkaO33tf4QHSAI8GPuE9DWVh_JqsC6E,934 +pycanvas/tests/course_audit_log.pyc,, +pycanvas/tests/course_quiz_extensions.py,sha256=mDC8Ln5OWfERlEu_7FVdnVYRUP61SMJWMkONvJIClQc,885 +pycanvas/tests/course_quiz_extensions.pyc,, +pycanvas/tests/courses.py,sha256=w72fVLGSFdEo8xTN1U2AzxpYFbQYZGTzk1Hlqo_USRA,7147 +pycanvas/tests/courses.pyc,, +pycanvas/tests/custom_gradebook_columns.py,sha256=tC9u0-L4wWQckglE2HkG5EujUCxlqkzm0PzsgBVuGa8,2696 +pycanvas/tests/custom_gradebook_columns.pyc,, +pycanvas/tests/discussion_topics.py,sha256=gzMNOmWBqSmBah9RRSAyLHCr_cS5IarnjmLXhS1hPfc,14476 +pycanvas/tests/discussion_topics.pyc,, +pycanvas/tests/document_previews.py,sha256=vS2UrphyEXE7so41xsyDesVp1an2PMB4nEbcNAN8rGk,461 +pycanvas/tests/document_previews.pyc,, +pycanvas/tests/enrollment_terms.py,sha256=HUkxFZJAW3opf8ujQ2dpFRjHHJGXeBskBDu_4gVYwY0,1604 +pycanvas/tests/enrollment_terms.pyc,, +pycanvas/tests/enrollments.py,sha256=Rmhu84tP6-WlCVkWNmNPI_0NTHx5-ZOs1HOVm6VPLOE,3123 +pycanvas/tests/enrollments.pyc,, +pycanvas/tests/external_tools.py,sha256=2Y9-aHo4-6SjlZrllALeo7v9c_FYZEmY8C7Xvj4zGYQ,4637 +pycanvas/tests/external_tools.pyc,, +pycanvas/tests/favorites.py,sha256=NZORQ-FPxHrazdi4hBLFBRYgZaSUHrcT-irQf9OXELU,2188 +pycanvas/tests/favorites.pyc,, +pycanvas/tests/feature_flags.py,sha256=OIDZjv9lbMEYyG0nQOyYmvdKJ95tq8QflCsKDj2R3h4,4572 +pycanvas/tests/feature_flags.pyc,, +pycanvas/tests/files.py,sha256=ixjKlFCj2czPN_uL9Sn2ygGlFvkznN1Fh6s8HxwxeoU,11948 +pycanvas/tests/files.pyc,, +pycanvas/tests/grade_change_log.py,sha256=fHtyhi99OhCsiGqpU-kL-S2V_JQ8kfnjPQqdXVfAPkE,1592 +pycanvas/tests/grade_change_log.pyc,, +pycanvas/tests/gradebook_history.py,sha256=eCdNiaRxNGY5Cwqy75A6SUoBPTz0c90b6e0mxp9VVEg,2082 +pycanvas/tests/gradebook_history.pyc,, +pycanvas/tests/grading_periods.py,sha256=2IqSz1SyWwkUJ6--Gyopu71JXDQ9f10enObbgf-Fm0A,2188 +pycanvas/tests/grading_periods.pyc,, +pycanvas/tests/grading_standards.py,sha256=mCHp7D_wSK-k8RtPDPdZ54eE1KAVAFblkeyTcYzKbUg,1855 +pycanvas/tests/grading_standards.pyc,, +pycanvas/tests/group_categories.py,sha256=R-ZOdvR7bbrRQ5Tr9feimk-nv09VYTtRDUHT5Or1cvw,3348 +pycanvas/tests/group_categories.pyc,, +pycanvas/tests/groups.py,sha256=bizD1fvcuyobOk5L_bdRFWQoUUDysVxtvDqJsQNjbMk,6283 +pycanvas/tests/groups.pyc,, +pycanvas/tests/live_assessments.py,sha256=qGDjs7XcLCFxLYx7tVT5ZbCjtQdmJ-xDcgavWdlIKvw,1769 +pycanvas/tests/live_assessments.pyc,, +pycanvas/tests/logins.py,sha256=1Z8RML-bleBIGsQuJuXkH8iGfy7iP5MvwHlPz0CtewM,1616 +pycanvas/tests/logins.pyc,, +pycanvas/tests/modules.py,sha256=D_bEPWhyCBOiwkOgFPqecUmpDAAmbxgCftRJYeCLCK0,4999 +pycanvas/tests/modules.pyc,, +pycanvas/tests/notification_preferences.py,sha256=nthS1RgZSdCwnleMKHY58tLXoF4nP_dF2xqXEf2es9c,4015 +pycanvas/tests/notification_preferences.pyc,, +pycanvas/tests/outcome_groups.py,sha256=b9vh8lQ_BUSHqf9OLT7bPozF0BUYJJzrzetG_UpzumQ,11305 +pycanvas/tests/outcome_groups.pyc,, +pycanvas/tests/outcome_results.py,sha256=HBn9cEp7hGlNdzspryuXPf09zf0JHLcJ9eF3n92AIaI,1513 +pycanvas/tests/outcome_results.pyc,, +pycanvas/tests/outcomes.py,sha256=uaDLFUZ-CMrLfLIV8h57HQ5SKs_2LMK1WQOOQ7C0SIs,889 +pycanvas/tests/outcomes.pyc,, +pycanvas/tests/pages.py,sha256=36gorKJb93pec0O-dhHlm6Ey2Z7-ABYCDOepQQCc2Kk,6534 +pycanvas/tests/pages.pyc,, +pycanvas/tests/poll_choices.py,sha256=KiSl3Q469isevYz69oRDrelShH9Sh4nWK26n72JpGq8,1799 +pycanvas/tests/poll_choices.pyc,, +pycanvas/tests/poll_sessions.py,sha256=1LbV0W9KD59rAmC6JGWHzIJABiGN46bMqIV746wzOHg,2785 +pycanvas/tests/poll_sessions.pyc,, +pycanvas/tests/poll_submissions.py,sha256=U_-2ZrGpSj275rLsUQZaOq8yLGSwHAWvnjDbk7AMKbo,1153 +pycanvas/tests/poll_submissions.pyc,, +pycanvas/tests/polls.py,sha256=l5yWloNZykqRrUloFDal1tsncW2vcMLWcPHnHxmL1Vs,1456 +pycanvas/tests/polls.pyc,, +pycanvas/tests/progress.py,sha256=e91qiYeC8JnC403tDoSjgffwGhIloJdJIm1okwsVDfw,642 +pycanvas/tests/progress.pyc,, +pycanvas/tests/quiz_assignment_overrides.py,sha256=lKI-SAnmOv1xkc7CmJOQypfJHyt2Cje2t7NydSyhHUw,1121 +pycanvas/tests/quiz_assignment_overrides.pyc,, +pycanvas/tests/quiz_extensions.py,sha256=5GOyGS8Voe0vlc6lgDJr_gQBufDY8s1OwUScaL-whgs,823 +pycanvas/tests/quiz_extensions.pyc,, +pycanvas/tests/quiz_ip_filters.py,sha256=B7_hdc4qt2-OcAEiAPwpZJp_6yigWBM2kBMdZSsMafM,802 +pycanvas/tests/quiz_ip_filters.pyc,, +pycanvas/tests/quiz_question_groups.py,sha256=XslHwbZePsGqexVM4No5n9UvQdQW-szzmJtiU351vJ4,2022 +pycanvas/tests/quiz_question_groups.pyc,, +pycanvas/tests/quiz_questions.py,sha256=R-lWQf0YBmSSr7vWAvKnF52cioMQZHDnLaAZz6NSAto,2144 +pycanvas/tests/quiz_questions.pyc,, +pycanvas/tests/quiz_reports.py,sha256=qRUyQhyOHY-s7t-ZhQgaSDwhkre_Rsx0sS2WM-jxy3E,1812 +pycanvas/tests/quiz_reports.pyc,, +pycanvas/tests/quiz_statistics.py,sha256=VzIEnNZbbUCgPCNt8_GF3wNJYln-k1gi4_Wxf-uJAeQ,1204 +pycanvas/tests/quiz_statistics.pyc,, +pycanvas/tests/quiz_submission_events.py,sha256=Z3x_ZeUT11pxWLIJRxyVh1hMZee6rNEXoUCoAM5KLnw,1192 +pycanvas/tests/quiz_submission_events.pyc,, +pycanvas/tests/quiz_submission_files.py,sha256=Yeu8zU7R5hg0MKLltOCKlI9I469k9qVx5JVymWIELWU,743 +pycanvas/tests/quiz_submission_files.pyc,, +pycanvas/tests/quiz_submission_questions.py,sha256=7otZ1XQ05HjxvXnI3Ii7X62mQSJtDVbGFHEPFnCR0xw,1732 +pycanvas/tests/quiz_submission_questions.pyc,, +pycanvas/tests/quiz_submission_user_list.py,sha256=bOdkmYfJaOf6zzIdbEyP5y5vtutz7m9mNPfLblloZio,1083 +pycanvas/tests/quiz_submission_user_list.pyc,, +pycanvas/tests/quiz_submissions.py,sha256=LUytmkXmgE52KcZUEp9mTGNvepllxX38nD1eNfVgRrI,2770 +pycanvas/tests/quiz_submissions.pyc,, +pycanvas/tests/quizzes.py,sha256=ZcTtMg18La_n1RtRd2OBHTZGmpedOFeXtj6dDFM9URw,2247 +pycanvas/tests/quizzes.pyc,, +pycanvas/tests/roles.py,sha256=ttXJxf0PS3dAzMjDTO9fYZyeZztr36-Ts8AtV9tGFbM,2058 +pycanvas/tests/roles.pyc,, +pycanvas/tests/search.py,sha256=pWFvFNHiQ3USBrKIC461OmDjIX35wz7wgYkwlz35D6A,1204 +pycanvas/tests/search.pyc,, +pycanvas/tests/secrets.py,sha256=2vDyHIy0wgDRwCMXCf7fAF5ochACZM183BgUw1Pkb08,200 +pycanvas/tests/secrets.pyc,, +pycanvas/tests/sections.py,sha256=1HYnz7egXalajqJ0O78pVxTSzL8oKzQOAfb65bSel9Y,2447 +pycanvas/tests/sections.pyc,, +pycanvas/tests/services.py,sha256=_JiC7yDflppjo3bjuE-OjDmzT6xzneDLKgQ7QjV-DYo,842 +pycanvas/tests/services.pyc,, +pycanvas/tests/sis_imports.py,sha256=SCQL7PY-KaduZmHgRwcRkj04O_emyahyaANxsnzEPzc,1897 +pycanvas/tests/sis_imports.pyc,, +pycanvas/tests/submission_comments.py,sha256=Doagml9IymuztAlZAhqUBZwGXFpr23Ygvq3i_pAZIQo,734 +pycanvas/tests/submission_comments.pyc,, +pycanvas/tests/submissions.py,sha256=A4r2hNgwYPAvUH3gDmr3yzXIj4YMjLprp_zyMcS3u0I,7707 +pycanvas/tests/submissions.pyc,, +pycanvas/tests/tabs.py,sha256=SXPTR--my5YlAaI_j2VrvdYFmWmBUkV7fbV9NBEFzKA,1303 +pycanvas/tests/tabs.pyc,, +pycanvas/tests/user_observees.py,sha256=wb7npblM3YQcKsMHT1uhruVIbWF61qR9HBIE6ocEAqE,1735 +pycanvas/tests/user_observees.pyc,, +pycanvas/tests/users.py,sha256=sEQEvf7UcfAcBv7NEbKGNaE9-SfFKGu324ognR7Ey0E,8576 +pycanvas/tests/users.pyc,, diff --git a/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/WHEEL b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/WHEEL new file mode 100644 index 00000000..5d264975 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.33.1) +Root-Is-Purelib: true +Tag: cp27-none-any + diff --git a/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/top_level.txt b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/top_level.txt new file mode 100644 index 00000000..295ef8be --- /dev/null +++ b/venv/Lib/site-packages/pycanvas-0.2.6.dist-info/top_level.txt @@ -0,0 +1 @@ +pycanvas diff --git a/venv/Lib/site-packages/pycanvas/__init__.py b/venv/Lib/site-packages/pycanvas/__init__.py new file mode 100644 index 00000000..66d9fd08 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/__init__.py @@ -0,0 +1,6 @@ +# Given a version number MAJOR.MINOR.PATCH, increment the: + +# MAJOR version when you make incompatible API changes, +# MINOR version when you add functionality in a backwards-compatible manner, and +# PATCH version when you make backwards-compatible bug fixes. +__version__ = '0.2.6' \ No newline at end of file diff --git a/venv/Lib/site-packages/pycanvas/apis/__init__.py b/venv/Lib/site-packages/pycanvas/apis/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/venv/Lib/site-packages/pycanvas/apis/account_domain_lookups.py b/venv/Lib/site-packages/pycanvas/apis/account_domain_lookups.py new file mode 100644 index 00000000..423a2add --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/account_domain_lookups.py @@ -0,0 +1,53 @@ +"""AccountDomainLookups API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + + +class AccountDomainLookupsAPI(BaseCanvasAPI): + """AccountDomainLookups API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AccountDomainLookupsAPI.""" + super(AccountDomainLookupsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AccountDomainLookupsAPI") + + def search_account_domains(self, domain=None, latitude=None, longitude=None, name=None): + """ + Search account domains. + + Returns a list of up to 5 matching account domains + + Partial match on name / domain are supported + """ + path = {} + data = {} + params = {} + + # OPTIONAL - name + """campus name""" + if name is not None: + params["name"] = name + + # OPTIONAL - domain + """no description""" + if domain is not None: + params["domain"] = domain + + # OPTIONAL - latitude + """no description""" + if latitude is not None: + params["latitude"] = latitude + + # OPTIONAL - longitude + """no description""" + if longitude is not None: + params["longitude"] = longitude + + self.logger.debug("GET /api/v1/accounts/search with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/search".format(**path), data=data, params=params, no_data=True) + diff --git a/venv/Lib/site-packages/pycanvas/apis/account_notifications.py b/venv/Lib/site-packages/pycanvas/apis/account_notifications.py new file mode 100644 index 00000000..c9099e59 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/account_notifications.py @@ -0,0 +1,289 @@ +"""AccountNotifications API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AccountNotificationsAPI(BaseCanvasAPI): + """AccountNotifications API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AccountNotificationsAPI.""" + super(AccountNotificationsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AccountNotificationsAPI") + + def index_of_active_global_notification_for_user(self, user_id, account_id): + """ + Index of active global notification for the user. + + Returns a list of all global notifications in the account for this user + Any notifications that have been closed by the user will not be returned + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/users/{user_id}/account_notifications with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/users/{user_id}/account_notifications".format(**path), data=data, params=params, all_pages=True) + + def show_global_notification(self, id, user_id, account_id): + """ + Show a global notification. + + Returns a global notification + A notification that has been closed by the user will not be returned + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{account_id}/users/{user_id}/account_notifications/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/users/{user_id}/account_notifications/{id}".format(**path), data=data, params=params, single_item=True) + + def close_notification_for_user(self, id, user_id, account_id): + """ + Close notification for user. + + If the user no long wants to see this notification it can be excused with this call + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/users/{user_id}/account_notifications/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/users/{user_id}/account_notifications/{id}".format(**path), data=data, params=params, single_item=True) + + def create_global_notification(self, account_id, account_notification_end_at, account_notification_subject, account_notification_message, account_notification_start_at, account_notification_icon=None, account_notification_roles=None): + """ + Create a global notification. + + Create and return a new global notification for an account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - account_notification[subject] + """The subject of the notification.""" + data["account_notification[subject]"] = account_notification_subject + + # REQUIRED - account_notification[message] + """The message body of the notification.""" + data["account_notification[message]"] = account_notification_message + + # REQUIRED - account_notification[start_at] + """The start date and time of the notification in ISO8601 format. + e.g. 2014-01-01T01:00Z""" + data["account_notification[start_at]"] = account_notification_start_at + + # REQUIRED - account_notification[end_at] + """The end date and time of the notification in ISO8601 format. + e.g. 2014-01-01T01:00Z""" + data["account_notification[end_at]"] = account_notification_end_at + + # OPTIONAL - account_notification[icon] + """The icon to display with the notification. + Note: Defaults to warning.""" + if account_notification_icon is not None: + self._validate_enum(account_notification_icon, ["warning", "information", "question", "error", "calendar"]) + data["account_notification[icon]"] = account_notification_icon + + # OPTIONAL - account_notification_roles + """The role(s) to send global notification to. Note: ommitting this field will send to everyone + Example: + account_notification_roles: ["StudentEnrollment", "TeacherEnrollment"]""" + if account_notification_roles is not None: + data["account_notification_roles"] = account_notification_roles + + self.logger.debug("POST /api/v1/accounts/{account_id}/account_notifications with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/account_notifications".format(**path), data=data, params=params, no_data=True) + + def update_global_notification(self, id, account_id, account_notification_end_at=None, account_notification_icon=None, account_notification_message=None, account_notification_roles=None, account_notification_start_at=None, account_notification_subject=None): + """ + Update a global notification. + + Update global notification for an account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - account_notification[subject] + """The subject of the notification.""" + if account_notification_subject is not None: + data["account_notification[subject]"] = account_notification_subject + + # OPTIONAL - account_notification[message] + """The message body of the notification.""" + if account_notification_message is not None: + data["account_notification[message]"] = account_notification_message + + # OPTIONAL - account_notification[start_at] + """The start date and time of the notification in ISO8601 format. + e.g. 2014-01-01T01:00Z""" + if account_notification_start_at is not None: + data["account_notification[start_at]"] = account_notification_start_at + + # OPTIONAL - account_notification[end_at] + """The end date and time of the notification in ISO8601 format. + e.g. 2014-01-01T01:00Z""" + if account_notification_end_at is not None: + data["account_notification[end_at]"] = account_notification_end_at + + # OPTIONAL - account_notification[icon] + """The icon to display with the notification.""" + if account_notification_icon is not None: + self._validate_enum(account_notification_icon, ["warning", "information", "question", "error", "calendar"]) + data["account_notification[icon]"] = account_notification_icon + + # OPTIONAL - account_notification_roles + """The role(s) to send global notification to. Note: ommitting this field will send to everyone + Example: + account_notification_roles: ["StudentEnrollment", "TeacherEnrollment"]""" + if account_notification_roles is not None: + data["account_notification_roles"] = account_notification_roles + + self.logger.debug("PUT /api/v1/accounts/{account_id}/account_notifications/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/account_notifications/{id}".format(**path), data=data, params=params, no_data=True) + + +class Accountnotification(BaseModel): + """Accountnotification Model.""" + + def __init__(self, role_ids=None, start_at=None, roles=None, end_at=None, message=None, subject=None, icon=None): + """Init method for Accountnotification class.""" + self._role_ids = role_ids + self._start_at = start_at + self._roles = roles + self._end_at = end_at + self._message = message + self._subject = subject + self._icon = icon + + self.logger = logging.getLogger('pycanvas.Accountnotification') + + @property + def role_ids(self): + """The roles to send the notification to. If roles is not passed it defaults to all roles.""" + return self._role_ids + + @role_ids.setter + def role_ids(self, value): + """Setter for role_ids property.""" + self.logger.warn("Setting values on role_ids will NOT update the remote Canvas instance.") + self._role_ids = value + + @property + def start_at(self): + """When to send out the notification.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def roles(self): + """(Deprecated) The roles to send the notification to. If roles is not passed it defaults to all roles.""" + return self._roles + + @roles.setter + def roles(self, value): + """Setter for roles property.""" + self.logger.warn("Setting values on roles will NOT update the remote Canvas instance.") + self._roles = value + + @property + def end_at(self): + """When to expire the notification.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def message(self): + """The message to be sent in the notification.""" + return self._message + + @message.setter + def message(self, value): + """Setter for message property.""" + self.logger.warn("Setting values on message will NOT update the remote Canvas instance.") + self._message = value + + @property + def subject(self): + """The subject of the notifications.""" + return self._subject + + @subject.setter + def subject(self, value): + """Setter for subject property.""" + self.logger.warn("Setting values on subject will NOT update the remote Canvas instance.") + self._subject = value + + @property + def icon(self): + """The icon to display with the message. Defaults to warning.""" + return self._icon + + @icon.setter + def icon(self, value): + """Setter for icon property.""" + self.logger.warn("Setting values on icon will NOT update the remote Canvas instance.") + self._icon = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/account_reports.py b/venv/Lib/site-packages/pycanvas/apis/account_reports.py new file mode 100644 index 00000000..6e150512 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/account_reports.py @@ -0,0 +1,439 @@ +"""AccountReports API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AccountReportsAPI(BaseCanvasAPI): + """AccountReports API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AccountReportsAPI.""" + super(AccountReportsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AccountReportsAPI") + + def list_available_reports(self, account_id): + """ + List Available Reports. + + Returns the list of reports for the current context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/reports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/reports".format(**path), data=data, params=params, no_data=True) + + def start_report(self, report, account_id, _parameters=None): + """ + Start a Report. + + Generates a report instance for the account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - report + """ID""" + path["report"] = report + + # OPTIONAL - [parameters] + """The parameters will vary for each report""" + if _parameters is not None: + data["[parameters]"] = _parameters + + self.logger.debug("POST /api/v1/accounts/{account_id}/reports/{report} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/reports/{report}".format(**path), data=data, params=params, single_item=True) + + def index_of_reports(self, report, account_id): + """ + Index of Reports. + + Shows all reports that have been run for the account of a specific type. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - report + """ID""" + path["report"] = report + + self.logger.debug("GET /api/v1/accounts/{account_id}/reports/{report} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/reports/{report}".format(**path), data=data, params=params, all_pages=True) + + def status_of_report(self, id, report, account_id): + """ + Status of a Report. + + Returns the status of a report. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - report + """ID""" + path["report"] = report + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{account_id}/reports/{report}/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/reports/{report}/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_report(self, id, report, account_id): + """ + Delete a Report. + + Deletes a generated report instance. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - report + """ID""" + path["report"] = report + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/reports/{report}/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/reports/{report}/{id}".format(**path), data=data, params=params, single_item=True) + + +class Report(BaseModel): + """Report Model.""" + + def __init__(self, status=None, parameters=None, file_url=None, report=None, progress=None, id=None): + """Init method for Report class.""" + self._status = status + self._parameters = parameters + self._file_url = file_url + self._report = report + self._progress = progress + self._id = id + + self.logger = logging.getLogger('pycanvas.Report') + + @property + def status(self): + """The status of the report.""" + return self._status + + @status.setter + def status(self, value): + """Setter for status property.""" + self.logger.warn("Setting values on status will NOT update the remote Canvas instance.") + self._status = value + + @property + def parameters(self): + """The report parameters.""" + return self._parameters + + @parameters.setter + def parameters(self, value): + """Setter for parameters property.""" + self.logger.warn("Setting values on parameters will NOT update the remote Canvas instance.") + self._parameters = value + + @property + def file_url(self): + """The url to the report download.""" + return self._file_url + + @file_url.setter + def file_url(self, value): + """Setter for file_url property.""" + self.logger.warn("Setting values on file_url will NOT update the remote Canvas instance.") + self._file_url = value + + @property + def report(self): + """The type of report.""" + return self._report + + @report.setter + def report(self, value): + """Setter for report property.""" + self.logger.warn("Setting values on report will NOT update the remote Canvas instance.") + self._report = value + + @property + def progress(self): + """The progress of the report.""" + return self._progress + + @progress.setter + def progress(self, value): + """Setter for progress property.""" + self.logger.warn("Setting values on progress will NOT update the remote Canvas instance.") + self._progress = value + + @property + def id(self): + """The unique identifier for the report.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Reportparameters(BaseModel): + """Reportparameters Model. + The parameters returned will vary for each report.""" + + def __init__(self, include_enrollment_state=None, sis_terms_csv=None, terms=None, users=None, enrollments=None, enrollment_term_id=None, include_deleted=None, courses=None, sis_accounts_csv=None, accounts=None, groups=None, course_id=None, start_at=None, enrollment_state=None, end_at=None, sections=None, order=None, xlist=None): + """Init method for Reportparameters class.""" + self._include_enrollment_state = include_enrollment_state + self._sis_terms_csv = sis_terms_csv + self._terms = terms + self._users = users + self._enrollments = enrollments + self._enrollment_term_id = enrollment_term_id + self._include_deleted = include_deleted + self._courses = courses + self._sis_accounts_csv = sis_accounts_csv + self._accounts = accounts + self._groups = groups + self._course_id = course_id + self._start_at = start_at + self._enrollment_state = enrollment_state + self._end_at = end_at + self._sections = sections + self._order = order + self._xlist = xlist + + self.logger = logging.getLogger('pycanvas.Reportparameters') + + @property + def include_enrollment_state(self): + """Include enrollment state. Defaults to false.""" + return self._include_enrollment_state + + @include_enrollment_state.setter + def include_enrollment_state(self, value): + """Setter for include_enrollment_state property.""" + self.logger.warn("Setting values on include_enrollment_state will NOT update the remote Canvas instance.") + self._include_enrollment_state = value + + @property + def sis_terms_csv(self): + """sis_terms_csv.""" + return self._sis_terms_csv + + @sis_terms_csv.setter + def sis_terms_csv(self, value): + """Setter for sis_terms_csv property.""" + self.logger.warn("Setting values on sis_terms_csv will NOT update the remote Canvas instance.") + self._sis_terms_csv = value + + @property + def terms(self): + """Get the data for terms.""" + return self._terms + + @terms.setter + def terms(self, value): + """Setter for terms property.""" + self.logger.warn("Setting values on terms will NOT update the remote Canvas instance.") + self._terms = value + + @property + def users(self): + """Get the data for users.""" + return self._users + + @users.setter + def users(self, value): + """Setter for users property.""" + self.logger.warn("Setting values on users will NOT update the remote Canvas instance.") + self._users = value + + @property + def enrollments(self): + """Get the data for enrollments.""" + return self._enrollments + + @enrollments.setter + def enrollments(self, value): + """Setter for enrollments property.""" + self.logger.warn("Setting values on enrollments will NOT update the remote Canvas instance.") + self._enrollments = value + + @property + def enrollment_term_id(self): + """The canvas id of the term to get grades from.""" + return self._enrollment_term_id + + @enrollment_term_id.setter + def enrollment_term_id(self, value): + """Setter for enrollment_term_id property.""" + self.logger.warn("Setting values on enrollment_term_id will NOT update the remote Canvas instance.") + self._enrollment_term_id = value + + @property + def include_deleted(self): + """Include deleted objects.""" + return self._include_deleted + + @include_deleted.setter + def include_deleted(self, value): + """Setter for include_deleted property.""" + self.logger.warn("Setting values on include_deleted will NOT update the remote Canvas instance.") + self._include_deleted = value + + @property + def courses(self): + """Get the data for courses.""" + return self._courses + + @courses.setter + def courses(self, value): + """Setter for courses property.""" + self.logger.warn("Setting values on courses will NOT update the remote Canvas instance.") + self._courses = value + + @property + def sis_accounts_csv(self): + """sis_accounts_csv.""" + return self._sis_accounts_csv + + @sis_accounts_csv.setter + def sis_accounts_csv(self, value): + """Setter for sis_accounts_csv property.""" + self.logger.warn("Setting values on sis_accounts_csv will NOT update the remote Canvas instance.") + self._sis_accounts_csv = value + + @property + def accounts(self): + """Get the data for accounts.""" + return self._accounts + + @accounts.setter + def accounts(self, value): + """Setter for accounts property.""" + self.logger.warn("Setting values on accounts will NOT update the remote Canvas instance.") + self._accounts = value + + @property + def groups(self): + """Get the data for groups.""" + return self._groups + + @groups.setter + def groups(self, value): + """Setter for groups property.""" + self.logger.warn("Setting values on groups will NOT update the remote Canvas instance.") + self._groups = value + + @property + def course_id(self): + """The course to report on.""" + return self._course_id + + @course_id.setter + def course_id(self, value): + """Setter for course_id property.""" + self.logger.warn("Setting values on course_id will NOT update the remote Canvas instance.") + self._course_id = value + + @property + def start_at(self): + """The beginning date for submissions. Max time range is 2 weeks.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def enrollment_state(self): + """Include enrollment state. Defaults to 'all' Options: ['active'| 'invited'| 'creation_pending'| 'deleted'| 'rejected'| 'completed'| 'inactive'| 'all'].""" + return self._enrollment_state + + @enrollment_state.setter + def enrollment_state(self, value): + """Setter for enrollment_state property.""" + self.logger.warn("Setting values on enrollment_state will NOT update the remote Canvas instance.") + self._enrollment_state = value + + @property + def end_at(self): + """The end date for submissions. Max time range is 2 weeks.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def sections(self): + """Get the data for sections.""" + return self._sections + + @sections.setter + def sections(self, value): + """Setter for sections property.""" + self.logger.warn("Setting values on sections will NOT update the remote Canvas instance.") + self._sections = value + + @property + def order(self): + """The sort order for the csv, Options: 'users', 'courses', 'outcomes'.""" + return self._order + + @order.setter + def order(self, value): + """Setter for order property.""" + self.logger.warn("Setting values on order will NOT update the remote Canvas instance.") + self._order = value + + @property + def xlist(self): + """Get the data for cross-listed courses.""" + return self._xlist + + @xlist.setter + def xlist(self, value): + """Setter for xlist property.""" + self.logger.warn("Setting values on xlist will NOT update the remote Canvas instance.") + self._xlist = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/accounts.py b/venv/Lib/site-packages/pycanvas/apis/accounts.py new file mode 100644 index 00000000..985ae5cb --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/accounts.py @@ -0,0 +1,508 @@ +"""Accounts API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AccountsAPI(BaseCanvasAPI): + """Accounts API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AccountsAPI.""" + super(AccountsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AccountsAPI") + + def list_accounts(self, include=None): + """ + List accounts. + + List accounts that the current user can view or manage. Typically, + students and even teachers will get an empty list in response, only + account admins can view the accounts that they are in. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - include + """Array of additional information to include. + + "lti_guid":: the 'tool_consumer_instance_guid' that will be sent for this account on LTI launches + "registration_settings":: returns info about the privacy policy and terms of use + "services":: returns services and whether they are enabled (requires account management permissions)""" + if include is not None: + self._validate_enum(include, ["lti_guid", "registration_settings", "services"]) + params["include"] = include + + self.logger.debug("GET /api/v1/accounts with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts".format(**path), data=data, params=params, all_pages=True) + + def list_accounts_for_course_admins(self): + """ + List accounts for course admins. + + List accounts that the current user can view through their admin course enrollments. + (Teacher, TA, or designer enrollments). + Only returns "id", "name", "workflow_state", "root_account_id" and "parent_account_id" + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/course_accounts with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/course_accounts".format(**path), data=data, params=params, all_pages=True) + + def get_single_account(self, id): + """ + Get a single account. + + Retrieve information on an individual account, given by id or sis + sis_account_id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{id}".format(**path), data=data, params=params, single_item=True) + + def get_sub_accounts_of_account(self, account_id, recursive=None): + """ + Get the sub-accounts of an account. + + List accounts that are sub-accounts of the given account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - recursive + """If true, the entire account tree underneath + this account will be returned (though still paginated). If false, only + direct sub-accounts of this account will be returned. Defaults to false.""" + if recursive is not None: + params["recursive"] = recursive + + self.logger.debug("GET /api/v1/accounts/{account_id}/sub_accounts with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/sub_accounts".format(**path), data=data, params=params, all_pages=True) + + def list_active_courses_in_account(self, account_id, by_subaccounts=None, by_teachers=None, completed=None, enrollment_term_id=None, enrollment_type=None, hide_enrollmentless_courses=None, include=None, published=None, search_term=None, state=None, with_enrollments=None): + """ + List active courses in an account. + + Retrieve the list of courses in this account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - with_enrollments + """If true, include only courses with at least one enrollment. If false, + include only courses with no enrollments. If not present, do not filter + on course enrollment status.""" + if with_enrollments is not None: + params["with_enrollments"] = with_enrollments + + # OPTIONAL - enrollment_type + """If set, only return courses that have at least one user enrolled in + in the course with one of the specified enrollment types.""" + if enrollment_type is not None: + self._validate_enum(enrollment_type, ["teacher", "student", "ta", "observer", "designer"]) + params["enrollment_type"] = enrollment_type + + # OPTIONAL - published + """If true, include only published courses. If false, exclude published + courses. If not present, do not filter on published status.""" + if published is not None: + params["published"] = published + + # OPTIONAL - completed + """If true, include only completed courses (these may be in state + 'completed', or their enrollment term may have ended). If false, exclude + completed courses. If not present, do not filter on completed status.""" + if completed is not None: + params["completed"] = completed + + # OPTIONAL - by_teachers + """List of User IDs of teachers; if supplied, include only courses taught by + one of the referenced users.""" + if by_teachers is not None: + params["by_teachers"] = by_teachers + + # OPTIONAL - by_subaccounts + """List of Account IDs; if supplied, include only courses associated with one + of the referenced subaccounts.""" + if by_subaccounts is not None: + params["by_subaccounts"] = by_subaccounts + + # OPTIONAL - hide_enrollmentless_courses + """If present, only return courses that have at least one enrollment. + Equivalent to 'with_enrollments=true'; retained for compatibility.""" + if hide_enrollmentless_courses is not None: + params["hide_enrollmentless_courses"] = hide_enrollmentless_courses + + # OPTIONAL - state + """If set, only return courses that are in the given state(s). By default, + all states but "deleted" are returned.""" + if state is not None: + self._validate_enum(state, ["created", "claimed", "available", "completed", "deleted", "all"]) + params["state"] = state + + # OPTIONAL - enrollment_term_id + """If set, only includes courses from the specified term.""" + if enrollment_term_id is not None: + params["enrollment_term_id"] = enrollment_term_id + + # OPTIONAL - search_term + """The partial course name, code, or full ID to match and return in the results list. Must be at least 3 characters.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - include + """- All explanations can be seen in the {api:CoursesController#index Course API index documentation} + - "sections", "needs_grading_count" and "total_scores" are not valid options at the account level""" + if include is not None: + self._validate_enum(include, ["syllabus_body", "term", "course_progress", "storage_quota_used_mb", "total_students", "teachers"]) + params["include"] = include + + self.logger.debug("GET /api/v1/accounts/{account_id}/courses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/courses".format(**path), data=data, params=params, all_pages=True) + + def update_account(self, id, account_default_group_storage_quota_mb=None, account_default_storage_quota_mb=None, account_default_time_zone=None, account_default_user_storage_quota_mb=None, account_name=None, account_services=None, account_settings_lock_all_announcements_locked=None, account_settings_lock_all_announcements_value=None, account_settings_restrict_student_future_listing_locked=None, account_settings_restrict_student_future_listing_value=None, account_settings_restrict_student_future_view_locked=None, account_settings_restrict_student_future_view_value=None, account_settings_restrict_student_past_view_locked=None, account_settings_restrict_student_past_view_value=None): + """ + Update an account. + + Update an existing account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - account[name] + """Updates the account name""" + if account_name is not None: + data["account[name]"] = account_name + + # OPTIONAL - account[default_time_zone] + """The default time zone of the account. Allowed time zones are + {http://www.iana.org/time-zones IANA time zones} or friendlier + {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + if account_default_time_zone is not None: + data["account[default_time_zone]"] = account_default_time_zone + + # OPTIONAL - account[default_storage_quota_mb] + """The default course storage quota to be used, if not otherwise specified.""" + if account_default_storage_quota_mb is not None: + data["account[default_storage_quota_mb]"] = account_default_storage_quota_mb + + # OPTIONAL - account[default_user_storage_quota_mb] + """The default user storage quota to be used, if not otherwise specified.""" + if account_default_user_storage_quota_mb is not None: + data["account[default_user_storage_quota_mb]"] = account_default_user_storage_quota_mb + + # OPTIONAL - account[default_group_storage_quota_mb] + """The default group storage quota to be used, if not otherwise specified.""" + if account_default_group_storage_quota_mb is not None: + data["account[default_group_storage_quota_mb]"] = account_default_group_storage_quota_mb + + # OPTIONAL - account[settings][restrict_student_past_view][value] + """Restrict students from viewing courses after end date""" + if account_settings_restrict_student_past_view_value is not None: + data["account[settings][restrict_student_past_view][value]"] = account_settings_restrict_student_past_view_value + + # OPTIONAL - account[settings][restrict_student_past_view][locked] + """Lock this setting for sub-accounts and courses""" + if account_settings_restrict_student_past_view_locked is not None: + data["account[settings][restrict_student_past_view][locked]"] = account_settings_restrict_student_past_view_locked + + # OPTIONAL - account[settings][restrict_student_future_view][value] + """Restrict students from viewing courses before start date""" + if account_settings_restrict_student_future_view_value is not None: + data["account[settings][restrict_student_future_view][value]"] = account_settings_restrict_student_future_view_value + + # OPTIONAL - account[settings][restrict_student_future_view][locked] + """Lock this setting for sub-accounts and courses""" + if account_settings_restrict_student_future_view_locked is not None: + data["account[settings][restrict_student_future_view][locked]"] = account_settings_restrict_student_future_view_locked + + # OPTIONAL - account[settings][lock_all_announcements][value] + """Disable comments on announcements""" + if account_settings_lock_all_announcements_value is not None: + data["account[settings][lock_all_announcements][value]"] = account_settings_lock_all_announcements_value + + # OPTIONAL - account[settings][lock_all_announcements][locked] + """Lock this setting for sub-accounts and courses""" + if account_settings_lock_all_announcements_locked is not None: + data["account[settings][lock_all_announcements][locked]"] = account_settings_lock_all_announcements_locked + + # OPTIONAL - account[settings][restrict_student_future_listing][value] + """Restrict students from viewing future enrollments in course list""" + if account_settings_restrict_student_future_listing_value is not None: + data["account[settings][restrict_student_future_listing][value]"] = account_settings_restrict_student_future_listing_value + + # OPTIONAL - account[settings][restrict_student_future_listing][locked] + """Lock this setting for sub-accounts and courses""" + if account_settings_restrict_student_future_listing_locked is not None: + data["account[settings][restrict_student_future_listing][locked]"] = account_settings_restrict_student_future_listing_locked + + # OPTIONAL - account[services] + """Give this a set of keys and boolean values to enable or disable services matching the keys""" + if account_services is not None: + data["account[services]"] = account_services + + self.logger.debug("PUT /api/v1/accounts/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_user_from_root_account(self, user_id, account_id): + """ + Delete a user from the root account. + + Delete a user record from a Canvas root account. If a user is associated + with multiple root accounts (in a multi-tenant instance of Canvas), this + action will NOT remove them from the other accounts. + + WARNING: This API will allow a user to remove themselves from the account. + If they do this, they won't be able to make API calls or log into Canvas at + that account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/users/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/users/{user_id}".format(**path), data=data, params=params, single_item=True) + + def create_new_sub_account(self, account_id, account_name, account_default_group_storage_quota_mb=None, account_default_storage_quota_mb=None, account_default_user_storage_quota_mb=None, account_sis_account_id=None): + """ + Create a new sub-account. + + Add a new sub-account to a given account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - account[name] + """The name of the new sub-account.""" + data["account[name]"] = account_name + + # OPTIONAL - account[sis_account_id] + """The account's identifier in the Student Information System.""" + if account_sis_account_id is not None: + data["account[sis_account_id]"] = account_sis_account_id + + # OPTIONAL - account[default_storage_quota_mb] + """The default course storage quota to be used, if not otherwise specified.""" + if account_default_storage_quota_mb is not None: + data["account[default_storage_quota_mb]"] = account_default_storage_quota_mb + + # OPTIONAL - account[default_user_storage_quota_mb] + """The default user storage quota to be used, if not otherwise specified.""" + if account_default_user_storage_quota_mb is not None: + data["account[default_user_storage_quota_mb]"] = account_default_user_storage_quota_mb + + # OPTIONAL - account[default_group_storage_quota_mb] + """The default group storage quota to be used, if not otherwise specified.""" + if account_default_group_storage_quota_mb is not None: + data["account[default_group_storage_quota_mb]"] = account_default_group_storage_quota_mb + + self.logger.debug("POST /api/v1/accounts/{account_id}/sub_accounts with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/sub_accounts".format(**path), data=data, params=params, single_item=True) + + +class Account(BaseModel): + """Account Model.""" + + def __init__(self, integration_id=None, default_time_zone=None, name=None, default_storage_quota_mb=None, sis_account_id=None, root_account_id=None, default_group_storage_quota_mb=None, id=None, sis_import_id=None, lti_guid=None, workflow_state=None, parent_account_id=None, default_user_storage_quota_mb=None): + """Init method for Account class.""" + self._integration_id = integration_id + self._default_time_zone = default_time_zone + self._name = name + self._default_storage_quota_mb = default_storage_quota_mb + self._sis_account_id = sis_account_id + self._root_account_id = root_account_id + self._default_group_storage_quota_mb = default_group_storage_quota_mb + self._id = id + self._sis_import_id = sis_import_id + self._lti_guid = lti_guid + self._workflow_state = workflow_state + self._parent_account_id = parent_account_id + self._default_user_storage_quota_mb = default_user_storage_quota_mb + + self.logger = logging.getLogger('pycanvas.Account') + + @property + def integration_id(self): + """The account's identifier in the Student Information System. Only included if the user has permission to view SIS information.""" + return self._integration_id + + @integration_id.setter + def integration_id(self, value): + """Setter for integration_id property.""" + self.logger.warn("Setting values on integration_id will NOT update the remote Canvas instance.") + self._integration_id = value + + @property + def default_time_zone(self): + """The default time zone of the account. Allowed time zones are {http://www.iana.org/time-zones IANA time zones} or friendlier {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + return self._default_time_zone + + @default_time_zone.setter + def default_time_zone(self, value): + """Setter for default_time_zone property.""" + self.logger.warn("Setting values on default_time_zone will NOT update the remote Canvas instance.") + self._default_time_zone = value + + @property + def name(self): + """The display name of the account.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def default_storage_quota_mb(self): + """The storage quota for the account in megabytes, if not otherwise specified.""" + return self._default_storage_quota_mb + + @default_storage_quota_mb.setter + def default_storage_quota_mb(self, value): + """Setter for default_storage_quota_mb property.""" + self.logger.warn("Setting values on default_storage_quota_mb will NOT update the remote Canvas instance.") + self._default_storage_quota_mb = value + + @property + def sis_account_id(self): + """The account's identifier in the Student Information System. Only included if the user has permission to view SIS information.""" + return self._sis_account_id + + @sis_account_id.setter + def sis_account_id(self, value): + """Setter for sis_account_id property.""" + self.logger.warn("Setting values on sis_account_id will NOT update the remote Canvas instance.") + self._sis_account_id = value + + @property + def root_account_id(self): + """The ID of the root account, or null if this is the root account.""" + return self._root_account_id + + @root_account_id.setter + def root_account_id(self, value): + """Setter for root_account_id property.""" + self.logger.warn("Setting values on root_account_id will NOT update the remote Canvas instance.") + self._root_account_id = value + + @property + def default_group_storage_quota_mb(self): + """The storage quota for a group in the account in megabytes, if not otherwise specified.""" + return self._default_group_storage_quota_mb + + @default_group_storage_quota_mb.setter + def default_group_storage_quota_mb(self, value): + """Setter for default_group_storage_quota_mb property.""" + self.logger.warn("Setting values on default_group_storage_quota_mb will NOT update the remote Canvas instance.") + self._default_group_storage_quota_mb = value + + @property + def id(self): + """the ID of the Account object.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def sis_import_id(self): + """The id of the SIS import if created through SIS. Only included if the user has permission to manage SIS information.""" + return self._sis_import_id + + @sis_import_id.setter + def sis_import_id(self, value): + """Setter for sis_import_id property.""" + self.logger.warn("Setting values on sis_import_id will NOT update the remote Canvas instance.") + self._sis_import_id = value + + @property + def lti_guid(self): + """The account's identifier that is sent as context_id in LTI launches.""" + return self._lti_guid + + @lti_guid.setter + def lti_guid(self, value): + """Setter for lti_guid property.""" + self.logger.warn("Setting values on lti_guid will NOT update the remote Canvas instance.") + self._lti_guid = value + + @property + def workflow_state(self): + """The state of the account. Can be 'active' or 'deleted'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def parent_account_id(self): + """The account's parent ID, or null if this is the root account.""" + return self._parent_account_id + + @parent_account_id.setter + def parent_account_id(self, value): + """Setter for parent_account_id property.""" + self.logger.warn("Setting values on parent_account_id will NOT update the remote Canvas instance.") + self._parent_account_id = value + + @property + def default_user_storage_quota_mb(self): + """The storage quota for a user in the account in megabytes, if not otherwise specified.""" + return self._default_user_storage_quota_mb + + @default_user_storage_quota_mb.setter + def default_user_storage_quota_mb(self, value): + """Setter for default_user_storage_quota_mb property.""" + self.logger.warn("Setting values on default_user_storage_quota_mb will NOT update the remote Canvas instance.") + self._default_user_storage_quota_mb = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/admins.py b/venv/Lib/site-packages/pycanvas/apis/admins.py new file mode 100644 index 00000000..d25bbb6e --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/admins.py @@ -0,0 +1,171 @@ +"""Admins API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AdminsAPI(BaseCanvasAPI): + """Admins API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AdminsAPI.""" + super(AdminsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AdminsAPI") + + def make_account_admin(self, user_id, account_id, role=None, role_id=None, send_confirmation=None): + """ + Make an account admin. + + Flag an existing user as an admin within the account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - user_id + """The id of the user to promote.""" + data["user_id"] = user_id + + # OPTIONAL - role + """(deprecated) + The user's admin relationship with the account will be created with the + given role. Defaults to 'AccountAdmin'.""" + if role is not None: + data["role"] = role + + # OPTIONAL - role_id + """The user's admin relationship with the account will be created with the + given role. Defaults to the built-in role for 'AccountAdmin'.""" + if role_id is not None: + data["role_id"] = role_id + + # OPTIONAL - send_confirmation + """Send a notification email to + the new admin if true. Default is true.""" + if send_confirmation is not None: + data["send_confirmation"] = send_confirmation + + self.logger.debug("POST /api/v1/accounts/{account_id}/admins with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/admins".format(**path), data=data, params=params, single_item=True) + + def remove_account_admin(self, user_id, account_id, role=None, role_id=None): + """ + Remove account admin. + + Remove the rights associated with an account admin role from a user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - role + """(Deprecated) + Account role to remove from the user. Defaults to 'AccountAdmin'. Any + other account role must be specified explicitly.""" + if role is not None: + params["role"] = role + + # OPTIONAL - role_id + """The user's admin relationship with the account will be created with the + given role. Defaults to the built-in role for 'AccountAdmin'.""" + if role_id is not None: + params["role_id"] = role_id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/admins/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/admins/{user_id}".format(**path), data=data, params=params, single_item=True) + + def list_account_admins(self, account_id, user_id=None): + """ + List account admins. + + List the admins in the account + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - user_id + """Scope the results to those with user IDs equal to any of the IDs specified here.""" + if user_id is not None: + params["user_id"] = user_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/admins with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/admins".format(**path), data=data, params=params, all_pages=True) + + +class Admin(BaseModel): + """Admin Model.""" + + def __init__(self, id, status=None, role=None, user=None): + """Init method for Admin class.""" + self._status = status + self._role = role + self._id = id + self._user = user + + self.logger = logging.getLogger('pycanvas.Admin') + + @property + def status(self): + """The status of the account role/user assignment.""" + return self._status + + @status.setter + def status(self, value): + """Setter for status property.""" + self.logger.warn("Setting values on status will NOT update the remote Canvas instance.") + self._status = value + + @property + def role(self): + """The account role assigned. This can be 'AccountAdmin' or a user-defined role created by the Roles API.""" + return self._role + + @role.setter + def role(self, value): + """Setter for role property.""" + self.logger.warn("Setting values on role will NOT update the remote Canvas instance.") + self._role = value + + @property + def id(self): + """The unique identifier for the account role/user assignment.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def user(self): + """The user the role is assigned to. See the Users API for details.""" + return self._user + + @user.setter + def user(self, value): + """Setter for user property.""" + self.logger.warn("Setting values on user will NOT update the remote Canvas instance.") + self._user = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/announcement_external_feeds.py b/venv/Lib/site-packages/pycanvas/apis/announcement_external_feeds.py new file mode 100644 index 00000000..b2ccc51e --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/announcement_external_feeds.py @@ -0,0 +1,239 @@ +"""AnnouncementExternalFeeds API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AnnouncementExternalFeedsAPI(BaseCanvasAPI): + """AnnouncementExternalFeeds API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AnnouncementExternalFeedsAPI.""" + super(AnnouncementExternalFeedsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AnnouncementExternalFeedsAPI") + + def list_external_feeds_courses(self, course_id): + """ + List external feeds. + + Returns the list of External Feeds this course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/external_feeds with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/external_feeds".format(**path), data=data, params=params, all_pages=True) + + def list_external_feeds_groups(self, group_id): + """ + List external feeds. + + Returns the list of External Feeds this course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/external_feeds with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/external_feeds".format(**path), data=data, params=params, all_pages=True) + + def create_external_feed_courses(self, url, course_id, header_match=None, verbosity=None): + """ + Create an external feed. + + Create a new external feed for the course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - url + """The url to the external rss or atom feed""" + data["url"] = url + + # OPTIONAL - header_match + """If given, only feed entries that contain this string in their title will be imported""" + if header_match is not None: + data["header_match"] = header_match + + # OPTIONAL - verbosity + """Defaults to "full"""" + if verbosity is not None: + self._validate_enum(verbosity, ["full", "truncate", "link_only"]) + data["verbosity"] = verbosity + + self.logger.debug("POST /api/v1/courses/{course_id}/external_feeds with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/external_feeds".format(**path), data=data, params=params, single_item=True) + + def create_external_feed_groups(self, url, group_id, header_match=None, verbosity=None): + """ + Create an external feed. + + Create a new external feed for the course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - url + """The url to the external rss or atom feed""" + data["url"] = url + + # OPTIONAL - header_match + """If given, only feed entries that contain this string in their title will be imported""" + if header_match is not None: + data["header_match"] = header_match + + # OPTIONAL - verbosity + """Defaults to "full"""" + if verbosity is not None: + self._validate_enum(verbosity, ["full", "truncate", "link_only"]) + data["verbosity"] = verbosity + + self.logger.debug("POST /api/v1/groups/{group_id}/external_feeds with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/external_feeds".format(**path), data=data, params=params, single_item=True) + + def delete_external_feed_courses(self, course_id, external_feed_id): + """ + Delete an external feed. + + Deletes the external feed. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - external_feed_id + """ID""" + path["external_feed_id"] = external_feed_id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/external_feeds/{external_feed_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/external_feeds/{external_feed_id}".format(**path), data=data, params=params, single_item=True) + + def delete_external_feed_groups(self, group_id, external_feed_id): + """ + Delete an external feed. + + Deletes the external feed. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - external_feed_id + """ID""" + path["external_feed_id"] = external_feed_id + + self.logger.debug("DELETE /api/v1/groups/{group_id}/external_feeds/{external_feed_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/external_feeds/{external_feed_id}".format(**path), data=data, params=params, single_item=True) + + +class Externalfeed(BaseModel): + """Externalfeed Model.""" + + def __init__(self, display_name=None, url=None, created_at=None, id=None, header_match=None, verbosity=None): + """Init method for Externalfeed class.""" + self._display_name = display_name + self._url = url + self._created_at = created_at + self._id = id + self._header_match = header_match + self._verbosity = verbosity + + self.logger = logging.getLogger('pycanvas.Externalfeed') + + @property + def display_name(self): + """The title of the feed, pulled from the feed itself. If the feed hasn't yet been pulled, a temporary name will be synthesized based on the URL.""" + return self._display_name + + @display_name.setter + def display_name(self, value): + """Setter for display_name property.""" + self.logger.warn("Setting values on display_name will NOT update the remote Canvas instance.") + self._display_name = value + + @property + def url(self): + """The HTTP/HTTPS URL to the feed.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def created_at(self): + """When this external feed was added to Canvas.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def id(self): + """The ID of the feed.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def header_match(self): + """If not null, only feed entries whose title contains this string will trigger new posts in Canvas.""" + return self._header_match + + @header_match.setter + def header_match(self, value): + """Setter for header_match property.""" + self.logger.warn("Setting values on header_match will NOT update the remote Canvas instance.") + self._header_match = value + + @property + def verbosity(self): + """The verbosity setting determines how much of the feed's content is imported into Canvas as part of the posting. 'link_only' means that only the title and a link to the item. 'truncate' means that a summary of the first portion of the item body will be used. 'full' means that the full item body will be used.""" + return self._verbosity + + @verbosity.setter + def verbosity(self, value): + """Setter for verbosity property.""" + self.logger.warn("Setting values on verbosity will NOT update the remote Canvas instance.") + self._verbosity = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/appointment_groups.py b/venv/Lib/site-packages/pycanvas/apis/appointment_groups.py new file mode 100644 index 00000000..648d7ba2 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/appointment_groups.py @@ -0,0 +1,715 @@ +"""AppointmentGroups API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AppointmentGroupsAPI(BaseCanvasAPI): + """AppointmentGroups API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AppointmentGroupsAPI.""" + super(AppointmentGroupsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AppointmentGroupsAPI") + + def list_appointment_groups(self, context_codes=None, include=None, include_past_appointments=None, scope=None): + """ + List appointment groups. + + Retrieve the list of appointment groups that can be reserved or managed by + the current user. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - scope + """Defaults to "reservable"""" + if scope is not None: + self._validate_enum(scope, ["reservable", "manageable"]) + params["scope"] = scope + + # OPTIONAL - context_codes + """Array of context codes used to limit returned results.""" + if context_codes is not None: + params["context_codes"] = context_codes + + # OPTIONAL - include_past_appointments + """Defaults to false. If true, includes past appointment groups""" + if include_past_appointments is not None: + params["include_past_appointments"] = include_past_appointments + + # OPTIONAL - include + """Array of additional information to include. + + "appointments":: calendar event time slots for this appointment group + "child_events":: reservations of those time slots + "participant_count":: number of reservations + "reserved_times":: the event id, start time and end time of reservations + the current user has made) + "all_context_codes":: all context codes associated with this appointment group""" + if include is not None: + self._validate_enum(include, ["appointments", "child_events", "participant_count", "reserved_times", "all_context_codes"]) + params["include"] = include + + self.logger.debug("GET /api/v1/appointment_groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/appointment_groups".format(**path), data=data, params=params, no_data=True) + + def create_appointment_group(self, appointment_group_title, appointment_group_context_codes, appointment_group_description=None, appointment_group_location_address=None, appointment_group_location_name=None, appointment_group_max_appointments_per_participant=None, appointment_group_min_appointments_per_participant=None, appointment_group_new_appointments_X=None, appointment_group_participant_visibility=None, appointment_group_participants_per_appointment=None, appointment_group_publish=None, appointment_group_sub_context_codes=None): + """ + Create an appointment group. + + Create and return a new appointment group. If new_appointments are + specified, the response will return a new_appointments array (same format + as appointments array, see "List appointment groups" action) + """ + path = {} + data = {} + params = {} + + # REQUIRED - appointment_group[context_codes] + """Array of context codes (courses, e.g. course_1) this group should be + linked to (1 or more). Users in the course(s) with appropriate permissions + will be able to sign up for this appointment group.""" + data["appointment_group[context_codes]"] = appointment_group_context_codes + + # OPTIONAL - appointment_group[sub_context_codes] + """Array of sub context codes (course sections or a single group category) + this group should be linked to. Used to limit the appointment group to + particular sections. If a group category is specified, students will sign + up in groups and the participant_type will be "Group" instead of "User".""" + if appointment_group_sub_context_codes is not None: + data["appointment_group[sub_context_codes]"] = appointment_group_sub_context_codes + + # REQUIRED - appointment_group[title] + """Short title for the appointment group.""" + data["appointment_group[title]"] = appointment_group_title + + # OPTIONAL - appointment_group[description] + """Longer text description of the appointment group.""" + if appointment_group_description is not None: + data["appointment_group[description]"] = appointment_group_description + + # OPTIONAL - appointment_group[location_name] + """Location name of the appointment group.""" + if appointment_group_location_name is not None: + data["appointment_group[location_name]"] = appointment_group_location_name + + # OPTIONAL - appointment_group[location_address] + """Location address.""" + if appointment_group_location_address is not None: + data["appointment_group[location_address]"] = appointment_group_location_address + + # OPTIONAL - appointment_group[publish] + """Indicates whether this appointment group should be published (i.e. made + available for signup). Once published, an appointment group cannot be + unpublished. Defaults to false.""" + if appointment_group_publish is not None: + data["appointment_group[publish]"] = appointment_group_publish + + # OPTIONAL - appointment_group[participants_per_appointment] + """Maximum number of participants that may register for each time slot. + Defaults to null (no limit).""" + if appointment_group_participants_per_appointment is not None: + data["appointment_group[participants_per_appointment]"] = appointment_group_participants_per_appointment + + # OPTIONAL - appointment_group[min_appointments_per_participant] + """Minimum number of time slots a user must register for. If not set, users + do not need to sign up for any time slots.""" + if appointment_group_min_appointments_per_participant is not None: + data["appointment_group[min_appointments_per_participant]"] = appointment_group_min_appointments_per_participant + + # OPTIONAL - appointment_group[max_appointments_per_participant] + """Maximum number of time slots a user may register for.""" + if appointment_group_max_appointments_per_participant is not None: + data["appointment_group[max_appointments_per_participant]"] = appointment_group_max_appointments_per_participant + + # OPTIONAL - appointment_group[new_appointments][X] + """Nested array of start time/end time pairs indicating time slots for this + appointment group. Refer to the example request.""" + if appointment_group_new_appointments_X is not None: + data["appointment_group[new_appointments][X]"] = appointment_group_new_appointments_X + + # OPTIONAL - appointment_group[participant_visibility] + """"private":: participants cannot see who has signed up for a particular + time slot + "protected":: participants can see who has signed up. Defaults to + "private".""" + if appointment_group_participant_visibility is not None: + self._validate_enum(appointment_group_participant_visibility, ["private", "protected"]) + data["appointment_group[participant_visibility]"] = appointment_group_participant_visibility + + self.logger.debug("POST /api/v1/appointment_groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/appointment_groups".format(**path), data=data, params=params, no_data=True) + + def get_single_appointment_group(self, id, include=None): + """ + Get a single appointment group. + + Returns information for a single appointment group + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """Array of additional information to include. See include[] argument of + "List appointment groups" action. + + "child_events":: reservations of time slots time slots + "appointments":: will always be returned + "all_context_codes":: all context codes associated with this appointment group""" + if include is not None: + self._validate_enum(include, ["child_events", "appointments", "all_context_codes"]) + params["include"] = include + + self.logger.debug("GET /api/v1/appointment_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/appointment_groups/{id}".format(**path), data=data, params=params, no_data=True) + + def update_appointment_group(self, id, appointment_group_context_codes, appointment_group_description=None, appointment_group_location_address=None, appointment_group_location_name=None, appointment_group_max_appointments_per_participant=None, appointment_group_min_appointments_per_participant=None, appointment_group_new_appointments_X=None, appointment_group_participant_visibility=None, appointment_group_participants_per_appointment=None, appointment_group_publish=None, appointment_group_sub_context_codes=None, appointment_group_title=None): + """ + Update an appointment group. + + Update and return an appointment group. If new_appointments are specified, + the response will return a new_appointments array (same format as + appointments array, see "List appointment groups" action). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - appointment_group[context_codes] + """Array of context codes (courses, e.g. course_1) this group should be + linked to (1 or more). Users in the course(s) with appropriate permissions + will be able to sign up for this appointment group.""" + data["appointment_group[context_codes]"] = appointment_group_context_codes + + # OPTIONAL - appointment_group[sub_context_codes] + """Array of sub context codes (course sections or a single group category) + this group should be linked to. Used to limit the appointment group to + particular sections. If a group category is specified, students will sign + up in groups and the participant_type will be "Group" instead of "User".""" + if appointment_group_sub_context_codes is not None: + data["appointment_group[sub_context_codes]"] = appointment_group_sub_context_codes + + # OPTIONAL - appointment_group[title] + """Short title for the appointment group.""" + if appointment_group_title is not None: + data["appointment_group[title]"] = appointment_group_title + + # OPTIONAL - appointment_group[description] + """Longer text description of the appointment group.""" + if appointment_group_description is not None: + data["appointment_group[description]"] = appointment_group_description + + # OPTIONAL - appointment_group[location_name] + """Location name of the appointment group.""" + if appointment_group_location_name is not None: + data["appointment_group[location_name]"] = appointment_group_location_name + + # OPTIONAL - appointment_group[location_address] + """Location address.""" + if appointment_group_location_address is not None: + data["appointment_group[location_address]"] = appointment_group_location_address + + # OPTIONAL - appointment_group[publish] + """Indicates whether this appointment group should be published (i.e. made + available for signup). Once published, an appointment group cannot be + unpublished. Defaults to false.""" + if appointment_group_publish is not None: + data["appointment_group[publish]"] = appointment_group_publish + + # OPTIONAL - appointment_group[participants_per_appointment] + """Maximum number of participants that may register for each time slot. + Defaults to null (no limit).""" + if appointment_group_participants_per_appointment is not None: + data["appointment_group[participants_per_appointment]"] = appointment_group_participants_per_appointment + + # OPTIONAL - appointment_group[min_appointments_per_participant] + """Minimum number of time slots a user must register for. If not set, users + do not need to sign up for any time slots.""" + if appointment_group_min_appointments_per_participant is not None: + data["appointment_group[min_appointments_per_participant]"] = appointment_group_min_appointments_per_participant + + # OPTIONAL - appointment_group[max_appointments_per_participant] + """Maximum number of time slots a user may register for.""" + if appointment_group_max_appointments_per_participant is not None: + data["appointment_group[max_appointments_per_participant]"] = appointment_group_max_appointments_per_participant + + # OPTIONAL - appointment_group[new_appointments][X] + """Nested array of start time/end time pairs indicating time slots for this + appointment group. Refer to the example request.""" + if appointment_group_new_appointments_X is not None: + data["appointment_group[new_appointments][X]"] = appointment_group_new_appointments_X + + # OPTIONAL - appointment_group[participant_visibility] + """"private":: participants cannot see who has signed up for a particular + time slot + "protected":: participants can see who has signed up. Defaults to "private".""" + if appointment_group_participant_visibility is not None: + self._validate_enum(appointment_group_participant_visibility, ["private", "protected"]) + data["appointment_group[participant_visibility]"] = appointment_group_participant_visibility + + self.logger.debug("PUT /api/v1/appointment_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/appointment_groups/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_appointment_group(self, id, cancel_reason=None): + """ + Delete an appointment group. + + Delete an appointment group (and associated time slots and reservations) + and return the deleted group + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - cancel_reason + """Reason for deleting/canceling the appointment group.""" + if cancel_reason is not None: + params["cancel_reason"] = cancel_reason + + self.logger.debug("DELETE /api/v1/appointment_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/appointment_groups/{id}".format(**path), data=data, params=params, no_data=True) + + def list_user_participants(self, id, registration_status=None): + """ + List user participants. + + List users that are (or may be) participating in this appointment group. + Refer to the Users API for the response fields. Returns no results for + appointment groups with the "Group" participant_type. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - registration_status + """Limits results to the a given participation status, defaults to "all"""" + if registration_status is not None: + self._validate_enum(registration_status, ["all", "registered", "registered"]) + params["registration_status"] = registration_status + + self.logger.debug("GET /api/v1/appointment_groups/{id}/users with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/appointment_groups/{id}/users".format(**path), data=data, params=params, no_data=True) + + def list_student_group_participants(self, id, registration_status=None): + """ + List student group participants. + + List student groups that are (or may be) participating in this appointment + group. Refer to the Groups API for the response fields. Returns no results + for appointment groups with the "User" participant_type. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - registration_status + """Limits results to the a given participation status, defaults to "all"""" + if registration_status is not None: + self._validate_enum(registration_status, ["all", "registered", "registered"]) + params["registration_status"] = registration_status + + self.logger.debug("GET /api/v1/appointment_groups/{id}/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/appointment_groups/{id}/groups".format(**path), data=data, params=params, no_data=True) + + def get_next_appointment(self, appointment_group_ids=None): + """ + Get next appointment. + + Return the next appointment available to sign up for. The appointment + is returned in a one-element array. If no future appointments are + available, an empty array is returned. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - appointment_group_ids + """List of ids of appointment groups to search.""" + if appointment_group_ids is not None: + params["appointment_group_ids"] = appointment_group_ids + + self.logger.debug("GET /api/v1/appointment_groups/next_appointment with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/appointment_groups/next_appointment".format(**path), data=data, params=params, all_pages=True) + + +class Appointmentgroup(BaseModel): + """Appointmentgroup Model.""" + + def __init__(self, participant_visibility=None, updated_at=None, context_codes=None, participant_type=None, end_at=None, id=None, participants_per_appointment=None, title=None, new_appointments=None, min_appointments_per_participant=None, appointments_count=None, start_at=None, description=None, participant_count=None, workflow_state=None, html_url=None, location_address=None, appointments=None, reserved_times=None, location_name=None, max_appointments_per_participant=None, url=None, created_at=None, sub_context_codes=None, requiring_action=None): + """Init method for Appointmentgroup class.""" + self._participant_visibility = participant_visibility + self._updated_at = updated_at + self._context_codes = context_codes + self._participant_type = participant_type + self._end_at = end_at + self._id = id + self._participants_per_appointment = participants_per_appointment + self._title = title + self._new_appointments = new_appointments + self._min_appointments_per_participant = min_appointments_per_participant + self._appointments_count = appointments_count + self._start_at = start_at + self._description = description + self._participant_count = participant_count + self._workflow_state = workflow_state + self._html_url = html_url + self._location_address = location_address + self._appointments = appointments + self._reserved_times = reserved_times + self._location_name = location_name + self._max_appointments_per_participant = max_appointments_per_participant + self._url = url + self._created_at = created_at + self._sub_context_codes = sub_context_codes + self._requiring_action = requiring_action + + self.logger = logging.getLogger('pycanvas.Appointmentgroup') + + @property + def participant_visibility(self): + """'private' means participants cannot see who has signed up for a particular time slot, 'protected' means that they can.""" + return self._participant_visibility + + @participant_visibility.setter + def participant_visibility(self, value): + """Setter for participant_visibility property.""" + self.logger.warn("Setting values on participant_visibility will NOT update the remote Canvas instance.") + self._participant_visibility = value + + @property + def updated_at(self): + """When the appointment group was last updated.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def context_codes(self): + """The context codes (i.e. courses) this appointment group belongs to. Only people in these courses will be eligible to sign up.""" + return self._context_codes + + @context_codes.setter + def context_codes(self, value): + """Setter for context_codes property.""" + self.logger.warn("Setting values on context_codes will NOT update the remote Canvas instance.") + self._context_codes = value + + @property + def participant_type(self): + """Indicates how participants sign up for the appointment group, either as individuals ('User') or in student groups ('Group'). Related to sub_context_codes (i.e. 'Group' signups always have a single group category).""" + return self._participant_type + + @participant_type.setter + def participant_type(self, value): + """Setter for participant_type property.""" + self.logger.warn("Setting values on participant_type will NOT update the remote Canvas instance.") + self._participant_type = value + + @property + def end_at(self): + """The end of the last time slot in the appointment group.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def id(self): + """The ID of the appointment group.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def participants_per_appointment(self): + """Maximum number of participants that may register for each time slot, or null if no limit.""" + return self._participants_per_appointment + + @participants_per_appointment.setter + def participants_per_appointment(self, value): + """Setter for participants_per_appointment property.""" + self.logger.warn("Setting values on participants_per_appointment will NOT update the remote Canvas instance.") + self._participants_per_appointment = value + + @property + def title(self): + """The title of the appointment group.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def new_appointments(self): + """Newly created time slots (same format as appointments above). Only returned in Create/Update responses where new time slots have been added.""" + return self._new_appointments + + @new_appointments.setter + def new_appointments(self, value): + """Setter for new_appointments property.""" + self.logger.warn("Setting values on new_appointments will NOT update the remote Canvas instance.") + self._new_appointments = value + + @property + def min_appointments_per_participant(self): + """Minimum number of time slots a user must register for. If not set, users do not need to sign up for any time slots.""" + return self._min_appointments_per_participant + + @min_appointments_per_participant.setter + def min_appointments_per_participant(self, value): + """Setter for min_appointments_per_participant property.""" + self.logger.warn("Setting values on min_appointments_per_participant will NOT update the remote Canvas instance.") + self._min_appointments_per_participant = value + + @property + def appointments_count(self): + """Number of time slots in this appointment group.""" + return self._appointments_count + + @appointments_count.setter + def appointments_count(self, value): + """Setter for appointments_count property.""" + self.logger.warn("Setting values on appointments_count will NOT update the remote Canvas instance.") + self._appointments_count = value + + @property + def start_at(self): + """The start of the first time slot in the appointment group.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def description(self): + """The text description of the appointment group.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def participant_count(self): + """The number of participant who have reserved slots (see include[] argument).""" + return self._participant_count + + @participant_count.setter + def participant_count(self, value): + """Setter for participant_count property.""" + self.logger.warn("Setting values on participant_count will NOT update the remote Canvas instance.") + self._participant_count = value + + @property + def workflow_state(self): + """Current state of the appointment group ('pending', 'active' or 'deleted'). 'pending' indicates that it has not been published yet and is invisible to participants.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def html_url(self): + """URL for a user to view this appointment group.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def location_address(self): + """The address of the appointment group's location.""" + return self._location_address + + @location_address.setter + def location_address(self, value): + """Setter for location_address property.""" + self.logger.warn("Setting values on location_address will NOT update the remote Canvas instance.") + self._location_address = value + + @property + def appointments(self): + """Calendar Events representing the time slots (see include[] argument) Refer to the Calendar Events API for more information.""" + return self._appointments + + @appointments.setter + def appointments(self, value): + """Setter for appointments property.""" + self.logger.warn("Setting values on appointments will NOT update the remote Canvas instance.") + self._appointments = value + + @property + def reserved_times(self): + """The start and end times of slots reserved by the current user as well as the id of the calendar event for the reservation (see include[] argument).""" + return self._reserved_times + + @reserved_times.setter + def reserved_times(self, value): + """Setter for reserved_times property.""" + self.logger.warn("Setting values on reserved_times will NOT update the remote Canvas instance.") + self._reserved_times = value + + @property + def location_name(self): + """The location name of the appointment group.""" + return self._location_name + + @location_name.setter + def location_name(self, value): + """Setter for location_name property.""" + self.logger.warn("Setting values on location_name will NOT update the remote Canvas instance.") + self._location_name = value + + @property + def max_appointments_per_participant(self): + """Maximum number of time slots a user may register for, or null if no limit.""" + return self._max_appointments_per_participant + + @max_appointments_per_participant.setter + def max_appointments_per_participant(self, value): + """Setter for max_appointments_per_participant property.""" + self.logger.warn("Setting values on max_appointments_per_participant will NOT update the remote Canvas instance.") + self._max_appointments_per_participant = value + + @property + def url(self): + """URL for this appointment group (to update, delete, etc.).""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def created_at(self): + """When the appointment group was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def sub_context_codes(self): + """The sub-context codes (i.e. course sections and group categories) this appointment group is restricted to.""" + return self._sub_context_codes + + @sub_context_codes.setter + def sub_context_codes(self, value): + """Setter for sub_context_codes property.""" + self.logger.warn("Setting values on sub_context_codes will NOT update the remote Canvas instance.") + self._sub_context_codes = value + + @property + def requiring_action(self): + """Boolean indicating whether the current user needs to sign up for this appointment group (i.e. it's reservable and the min_appointments_per_participant limit has not been met by this user).""" + return self._requiring_action + + @requiring_action.setter + def requiring_action(self, value): + """Setter for requiring_action property.""" + self.logger.warn("Setting values on requiring_action will NOT update the remote Canvas instance.") + self._requiring_action = value + + +class Appointment(BaseModel): + """Appointment Model. + Date and time for an appointment""" + + def __init__(self, start_at=None, id=None, end_at=None): + """Init method for Appointment class.""" + self._start_at = start_at + self._id = id + self._end_at = end_at + + self.logger = logging.getLogger('pycanvas.Appointment') + + @property + def start_at(self): + """Start time for the appointment.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def id(self): + """The appointment identifier.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def end_at(self): + """End time for the appointment.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/assignment_groups.py b/venv/Lib/site-packages/pycanvas/apis/assignment_groups.py new file mode 100644 index 00000000..b9259bda --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/assignment_groups.py @@ -0,0 +1,360 @@ +"""AssignmentGroups API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AssignmentGroupsAPI(BaseCanvasAPI): + """AssignmentGroups API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AssignmentGroupsAPI.""" + super(AssignmentGroupsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AssignmentGroupsAPI") + + def list_assignment_groups(self, course_id, exclude_assignment_submission_types=None, grading_period_id=None, include=None, override_assignment_dates=None, scope_assignments_to_student=None): + """ + List assignment groups. + + Returns the list of assignment groups for the current context. The returned + groups are sorted by their position field. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - include + """Associations to include with the group. "discussion_topic", "all_dates" + "assignment_visibility" & "submission" are only valid are only valid if "assignments" is also included. + The "assignment_visibility" option additionally requires that the Differentiated Assignments course feature be turned on.""" + if include is not None: + self._validate_enum(include, ["assignments", "discussion_topic", "all_dates", "assignment_visibility", "overrides", "submission"]) + params["include"] = include + + # OPTIONAL - exclude_assignment_submission_types + """If "assignments" are included, those with the specified submission types + will be excluded from the assignment groups.""" + if exclude_assignment_submission_types is not None: + self._validate_enum(exclude_assignment_submission_types, ["online_quiz", "discussion_topic", "wiki_page", "external_tool"]) + params["exclude_assignment_submission_types"] = exclude_assignment_submission_types + + # OPTIONAL - override_assignment_dates + """Apply assignment overrides for each assignment, defaults to true.""" + if override_assignment_dates is not None: + params["override_assignment_dates"] = override_assignment_dates + + # OPTIONAL - grading_period_id + """The id of the grading period in which assignment groups are being requested + (Requires the Multiple Grading Periods feature turned on.)""" + if grading_period_id is not None: + params["grading_period_id"] = grading_period_id + + # OPTIONAL - scope_assignments_to_student + """If true, all assignments returned will apply to the current user in the + specified grading period. If assignments apply to other students in the + specified grading period, but not the current user, they will not be + returned. (Requires the grading_period_id argument and the Multiple Grading + Periods feature turned on. In addition, the current user must be a student.)""" + if scope_assignments_to_student is not None: + params["scope_assignments_to_student"] = scope_assignments_to_student + + self.logger.debug("GET /api/v1/courses/{course_id}/assignment_groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignment_groups".format(**path), data=data, params=params, all_pages=True) + + def get_assignment_group(self, course_id, assignment_group_id, grading_period_id=None, include=None, override_assignment_dates=None): + """ + Get an Assignment Group. + + Returns the assignment group with the given id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_group_id + """ID""" + path["assignment_group_id"] = assignment_group_id + + # OPTIONAL - include + """Associations to include with the group. "discussion_topic" and "assignment_visibility" and "submission" + are only valid if "assignments" is also included. The "assignment_visibility" option additionally + requires that the Differentiated Assignments course feature be turned on.""" + if include is not None: + self._validate_enum(include, ["assignments", "discussion_topic", "assignment_visibility", "submission"]) + params["include"] = include + + # OPTIONAL - override_assignment_dates + """Apply assignment overrides for each assignment, defaults to true.""" + if override_assignment_dates is not None: + params["override_assignment_dates"] = override_assignment_dates + + # OPTIONAL - grading_period_id + """The id of the grading period in which assignment groups are being requested + (Requires the Multiple Grading Periods account feature turned on)""" + if grading_period_id is not None: + params["grading_period_id"] = grading_period_id + + self.logger.debug("GET /api/v1/courses/{course_id}/assignment_groups/{assignment_group_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignment_groups/{assignment_group_id}".format(**path), data=data, params=params, single_item=True) + + def create_assignment_group(self, course_id, group_weight=None, integration_data=None, name=None, position=None, rules=None, sis_source_id=None): + """ + Create an Assignment Group. + + Create a new assignment group for this course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - name + """The assignment group's name""" + if name is not None: + data["name"] = name + + # OPTIONAL - position + """The position of this assignment group in relation to the other assignment groups""" + if position is not None: + data["position"] = position + + # OPTIONAL - group_weight + """The percent of the total grade that this assignment group represents""" + if group_weight is not None: + data["group_weight"] = group_weight + + # OPTIONAL - sis_source_id + """The sis source id of the Assignment Group""" + if sis_source_id is not None: + data["sis_source_id"] = sis_source_id + + # OPTIONAL - integration_data + """The integration data of the Assignment Group""" + if integration_data is not None: + data["integration_data"] = integration_data + + # OPTIONAL - rules + """The grading rules that are applied within this assignment group + See the Assignment Group object definition for format""" + if rules is not None: + data["rules"] = rules + + self.logger.debug("POST /api/v1/courses/{course_id}/assignment_groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/assignment_groups".format(**path), data=data, params=params, single_item=True) + + def edit_assignment_group(self, course_id, assignment_group_id): + """ + Edit an Assignment Group. + + Modify an existing Assignment Group. + Accepts the same parameters as Assignment Group creation + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_group_id + """ID""" + path["assignment_group_id"] = assignment_group_id + + self.logger.debug("PUT /api/v1/courses/{course_id}/assignment_groups/{assignment_group_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/assignment_groups/{assignment_group_id}".format(**path), data=data, params=params, single_item=True) + + def destroy_assignment_group(self, course_id, assignment_group_id, move_assignments_to=None): + """ + Destroy an Assignment Group. + + Deletes the assignment group with the given id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_group_id + """ID""" + path["assignment_group_id"] = assignment_group_id + + # OPTIONAL - move_assignments_to + """The ID of an active Assignment Group to which the assignments that are + currently assigned to the destroyed Assignment Group will be assigned. + NOTE: If this argument is not provided, any assignments in this Assignment + Group will be deleted.""" + if move_assignments_to is not None: + params["move_assignments_to"] = move_assignments_to + + self.logger.debug("DELETE /api/v1/courses/{course_id}/assignment_groups/{assignment_group_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/assignment_groups/{assignment_group_id}".format(**path), data=data, params=params, single_item=True) + + +class Gradingrules(BaseModel): + """Gradingrules Model.""" + + def __init__(self, never_drop=None, drop_highest=None, drop_lowest=None): + """Init method for Gradingrules class.""" + self._never_drop = never_drop + self._drop_highest = drop_highest + self._drop_lowest = drop_lowest + + self.logger = logging.getLogger('pycanvas.Gradingrules') + + @property + def never_drop(self): + """Assignment IDs that should never be dropped.""" + return self._never_drop + + @never_drop.setter + def never_drop(self, value): + """Setter for never_drop property.""" + self.logger.warn("Setting values on never_drop will NOT update the remote Canvas instance.") + self._never_drop = value + + @property + def drop_highest(self): + """Number of highest scores to be dropped for each user.""" + return self._drop_highest + + @drop_highest.setter + def drop_highest(self, value): + """Setter for drop_highest property.""" + self.logger.warn("Setting values on drop_highest will NOT update the remote Canvas instance.") + self._drop_highest = value + + @property + def drop_lowest(self): + """Number of lowest scores to be dropped for each user.""" + return self._drop_lowest + + @drop_lowest.setter + def drop_lowest(self, value): + """Setter for drop_lowest property.""" + self.logger.warn("Setting values on drop_lowest will NOT update the remote Canvas instance.") + self._drop_lowest = value + + +class Assignmentgroup(BaseModel): + """Assignmentgroup Model.""" + + def __init__(self, group_weight=None, name=None, rules=None, assignments=None, sis_source_id=None, integration_data=None, position=None, id=None): + """Init method for Assignmentgroup class.""" + self._group_weight = group_weight + self._name = name + self._rules = rules + self._assignments = assignments + self._sis_source_id = sis_source_id + self._integration_data = integration_data + self._position = position + self._id = id + + self.logger = logging.getLogger('pycanvas.Assignmentgroup') + + @property + def group_weight(self): + """the weight of the Assignment Group.""" + return self._group_weight + + @group_weight.setter + def group_weight(self, value): + """Setter for group_weight property.""" + self.logger.warn("Setting values on group_weight will NOT update the remote Canvas instance.") + self._group_weight = value + + @property + def name(self): + """the name of the Assignment Group.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def rules(self): + """the grading rules that this Assignment Group has.""" + return self._rules + + @rules.setter + def rules(self, value): + """Setter for rules property.""" + self.logger.warn("Setting values on rules will NOT update the remote Canvas instance.") + self._rules = value + + @property + def assignments(self): + """the assignments in this Assignment Group (see the Assignment API for a detailed list of fields).""" + return self._assignments + + @assignments.setter + def assignments(self, value): + """Setter for assignments property.""" + self.logger.warn("Setting values on assignments will NOT update the remote Canvas instance.") + self._assignments = value + + @property + def sis_source_id(self): + """the sis source id of the Assignment Group.""" + return self._sis_source_id + + @sis_source_id.setter + def sis_source_id(self, value): + """Setter for sis_source_id property.""" + self.logger.warn("Setting values on sis_source_id will NOT update the remote Canvas instance.") + self._sis_source_id = value + + @property + def integration_data(self): + """the integration data of the Assignment Group.""" + return self._integration_data + + @integration_data.setter + def integration_data(self, value): + """Setter for integration_data property.""" + self.logger.warn("Setting values on integration_data will NOT update the remote Canvas instance.") + self._integration_data = value + + @property + def position(self): + """the position of the Assignment Group.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def id(self): + """the id of the Assignment Group.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/assignments.py b/venv/Lib/site-packages/pycanvas/apis/assignments.py new file mode 100644 index 00000000..5403b0eb --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/assignments.py @@ -0,0 +1,2252 @@ +"""Assignments API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AssignmentsAPI(BaseCanvasAPI): + """Assignments API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AssignmentsAPI.""" + super(AssignmentsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AssignmentsAPI") + + def delete_assignment(self, id, course_id): + """ + Delete an assignment. + + Delete the given assignment. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/assignments/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/assignments/{id}".format(**path), data=data, params=params, single_item=True) + + def list_assignments(self, course_id, assignment_ids=None, bucket=None, include=None, needs_grading_count_by_section=None, override_assignment_dates=None, search_term=None): + """ + List assignments. + + Returns the list of assignments for the current context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - include + """Associations to include with the assignment. The "assignment_visibility" option + requires that the Differentiated Assignments course feature be turned on. If + "observed_users" is passed, submissions for observed users will also be included as an array.""" + if include is not None: + self._validate_enum(include, ["submission", "assignment_visibility", "all_dates", "overrides", "observed_users"]) + params["include"] = include + + # OPTIONAL - search_term + """The partial title of the assignments to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - override_assignment_dates + """Apply assignment overrides for each assignment, defaults to true.""" + if override_assignment_dates is not None: + params["override_assignment_dates"] = override_assignment_dates + + # OPTIONAL - needs_grading_count_by_section + """Split up "needs_grading_count" by sections into the "needs_grading_count_by_section" key, defaults to false""" + if needs_grading_count_by_section is not None: + params["needs_grading_count_by_section"] = needs_grading_count_by_section + + # OPTIONAL - bucket + """If included, only return certain assignments depending on due date and submission status.""" + if bucket is not None: + self._validate_enum(bucket, ["past", "overdue", "undated", "ungraded", "unsubmitted", "upcoming", "future"]) + params["bucket"] = bucket + + # OPTIONAL - assignment_ids + """if set, return only assignments specified""" + if assignment_ids is not None: + params["assignment_ids"] = assignment_ids + + self.logger.debug("GET /api/v1/courses/{course_id}/assignments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignments".format(**path), data=data, params=params, all_pages=True) + + def list_assignments_for_user(self, user_id, course_id): + """ + List assignments for user. + + Returns the list of assignments for the specified user if the current user has rights to view. + See {api:AssignmentsApiController#index List assignments} for valid arguments. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/users/{user_id}/courses/{course_id}/assignments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/courses/{course_id}/assignments".format(**path), data=data, params=params, no_data=True) + + def get_single_assignment(self, id, course_id, all_dates=None, include=None, needs_grading_count_by_section=None, override_assignment_dates=None): + """ + Get a single assignment. + + Returns the assignment with the given id. + "observed_users" is passed, submissions for observed users will also be included. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """Associations to include with the assignment. The "assignment_visibility" option + requires that the Differentiated Assignments course feature be turned on. If""" + if include is not None: + self._validate_enum(include, ["submission", "assignment_visibility", "overrides", "observed_users"]) + params["include"] = include + + # OPTIONAL - override_assignment_dates + """Apply assignment overrides to the assignment, defaults to true.""" + if override_assignment_dates is not None: + params["override_assignment_dates"] = override_assignment_dates + + # OPTIONAL - needs_grading_count_by_section + """Split up "needs_grading_count" by sections into the "needs_grading_count_by_section" key, defaults to false""" + if needs_grading_count_by_section is not None: + params["needs_grading_count_by_section"] = needs_grading_count_by_section + + # OPTIONAL - all_dates + """All dates associated with the assignment, if applicable""" + if all_dates is not None: + params["all_dates"] = all_dates + + self.logger.debug("GET /api/v1/courses/{course_id}/assignments/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignments/{id}".format(**path), data=data, params=params, single_item=True) + + def create_assignment(self, course_id, assignment_name, assignment_allowed_extensions=None, assignment_assignment_group_id=None, assignment_assignment_overrides=None, assignment_automatic_peer_reviews=None, assignment_description=None, assignment_due_at=None, assignment_external_tool_tag_attributes=None, assignment_grade_group_students_individually=None, assignment_grading_standard_id=None, assignment_grading_type=None, assignment_group_category_id=None, assignment_integration_data=None, assignment_integration_id=None, assignment_lock_at=None, assignment_muted=None, assignment_notify_of_update=None, assignment_omit_from_final_grade=None, assignment_only_visible_to_overrides=None, assignment_peer_reviews=None, assignment_points_possible=None, assignment_position=None, assignment_published=None, assignment_submission_types=None, assignment_turnitin_enabled=None, assignment_turnitin_settings=None, assignment_unlock_at=None, assignment_vericite_enabled=None): + """ + Create an assignment. + + Create a new assignment for this course. The assignment is created in the + active state. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - assignment[name] + """The assignment name.""" + data["assignment[name]"] = assignment_name + + # OPTIONAL - assignment[position] + """The position of this assignment in the group when displaying + assignment lists.""" + if assignment_position is not None: + data["assignment[position]"] = assignment_position + + # OPTIONAL - assignment[submission_types] + """List of supported submission types for the assignment. + Unless the assignment is allowing online submissions, the array should + only have one element. + + If not allowing online submissions, your options are: + "online_quiz" + "none" + "on_paper" + "online_quiz" + "discussion_topic" + "external_tool" + + If you are allowing online submissions, you can have one or many + allowed submission types: + + "online_upload" + "online_text_entry" + "online_url" + "media_recording" (Only valid when the Kaltura plugin is enabled)""" + if assignment_submission_types is not None: + self._validate_enum(assignment_submission_types, ["online_quiz", "none", "on_paper", "online_quiz", "discussion_topic", "external_tool", "online_upload", "online_text_entry", "online_url", "media_recording"]) + data["assignment[submission_types]"] = assignment_submission_types + + # OPTIONAL - assignment[allowed_extensions] + """Allowed extensions if submission_types includes "online_upload" + + Example: + allowed_extensions: ["docx","ppt"]""" + if assignment_allowed_extensions is not None: + data["assignment[allowed_extensions]"] = assignment_allowed_extensions + + # OPTIONAL - assignment[turnitin_enabled] + """Only applies when the Turnitin plugin is enabled for a course and + the submission_types array includes "online_upload". + Toggles Turnitin submissions for the assignment. + Will be ignored if Turnitin is not available for the course.""" + if assignment_turnitin_enabled is not None: + data["assignment[turnitin_enabled]"] = assignment_turnitin_enabled + + # OPTIONAL - assignment[vericite_enabled] + """Only applies when the VeriCite plugin is enabled for a course and + the submission_types array includes "online_upload". + Toggles VeriCite submissions for the assignment. + Will be ignored if VeriCite is not available for the course.""" + if assignment_vericite_enabled is not None: + data["assignment[vericite_enabled]"] = assignment_vericite_enabled + + # OPTIONAL - assignment[turnitin_settings] + """Settings to send along to turnitin. See Assignment object definition for + format.""" + if assignment_turnitin_settings is not None: + data["assignment[turnitin_settings]"] = assignment_turnitin_settings + + # OPTIONAL - assignment[integration_data] + """Data related to third party integrations, JSON string required.""" + if assignment_integration_data is not None: + data["assignment[integration_data]"] = assignment_integration_data + + # OPTIONAL - assignment[integration_id] + """Unique ID from third party integrations""" + if assignment_integration_id is not None: + data["assignment[integration_id]"] = assignment_integration_id + + # OPTIONAL - assignment[peer_reviews] + """If submission_types does not include external_tool,discussion_topic, + online_quiz, or on_paper, determines whether or not peer reviews + will be turned on for the assignment.""" + if assignment_peer_reviews is not None: + data["assignment[peer_reviews]"] = assignment_peer_reviews + + # OPTIONAL - assignment[automatic_peer_reviews] + """Whether peer reviews will be assigned automatically by Canvas or if + teachers must manually assign peer reviews. Does not apply if peer reviews + are not enabled.""" + if assignment_automatic_peer_reviews is not None: + data["assignment[automatic_peer_reviews]"] = assignment_automatic_peer_reviews + + # OPTIONAL - assignment[notify_of_update] + """If true, Canvas will send a notification to students in the class + notifying them that the content has changed.""" + if assignment_notify_of_update is not None: + data["assignment[notify_of_update]"] = assignment_notify_of_update + + # OPTIONAL - assignment[group_category_id] + """If present, the assignment will become a group assignment assigned + to the group.""" + if assignment_group_category_id is not None: + data["assignment[group_category_id]"] = assignment_group_category_id + + # OPTIONAL - assignment[grade_group_students_individually] + """If this is a group assignment, teachers have the options to grade + students individually. If false, Canvas will apply the assignment's + score to each member of the group. If true, the teacher can manually + assign scores to each member of the group.""" + if assignment_grade_group_students_individually is not None: + data["assignment[grade_group_students_individually]"] = assignment_grade_group_students_individually + + # OPTIONAL - assignment[external_tool_tag_attributes] + """Hash of external tool parameters if submission_types is ["external_tool"]. + See Assignment object definition for format.""" + if assignment_external_tool_tag_attributes is not None: + data["assignment[external_tool_tag_attributes]"] = assignment_external_tool_tag_attributes + + # OPTIONAL - assignment[points_possible] + """The maximum points possible on the assignment.""" + if assignment_points_possible is not None: + data["assignment[points_possible]"] = assignment_points_possible + + # OPTIONAL - assignment[grading_type] + """The strategy used for grading the assignment. + The assignment defaults to "points" if this field is omitted.""" + if assignment_grading_type is not None: + self._validate_enum(assignment_grading_type, ["pass_fail", "percent", "letter_grade", "gpa_scale", "points"]) + data["assignment[grading_type]"] = assignment_grading_type + + # OPTIONAL - assignment[due_at] + """The day/time the assignment is due. + Accepts times in ISO 8601 format, e.g. 2014-10-21T18:48:00Z.""" + if assignment_due_at is not None: + data["assignment[due_at]"] = assignment_due_at + + # OPTIONAL - assignment[lock_at] + """The day/time the assignment is locked after. + Accepts times in ISO 8601 format, e.g. 2014-10-21T18:48:00Z.""" + if assignment_lock_at is not None: + data["assignment[lock_at]"] = assignment_lock_at + + # OPTIONAL - assignment[unlock_at] + """The day/time the assignment is unlocked. + Accepts times in ISO 8601 format, e.g. 2014-10-21T18:48:00Z.""" + if assignment_unlock_at is not None: + data["assignment[unlock_at]"] = assignment_unlock_at + + # OPTIONAL - assignment[description] + """The assignment's description, supports HTML.""" + if assignment_description is not None: + data["assignment[description]"] = assignment_description + + # OPTIONAL - assignment[assignment_group_id] + """The assignment group id to put the assignment in. + Defaults to the top assignment group in the course.""" + if assignment_assignment_group_id is not None: + data["assignment[assignment_group_id]"] = assignment_assignment_group_id + + # OPTIONAL - assignment[muted] + """Whether this assignment is muted. + A muted assignment does not send change notifications + and hides grades from students. + Defaults to false.""" + if assignment_muted is not None: + data["assignment[muted]"] = assignment_muted + + # OPTIONAL - assignment[assignment_overrides] + """List of overrides for the assignment. + NOTE: The assignment overrides feature is in beta.""" + if assignment_assignment_overrides is not None: + data["assignment[assignment_overrides]"] = assignment_assignment_overrides + + # OPTIONAL - assignment[only_visible_to_overrides] + """Whether this assignment is only visible to overrides + (Only useful if 'differentiated assignments' account setting is on)""" + if assignment_only_visible_to_overrides is not None: + data["assignment[only_visible_to_overrides]"] = assignment_only_visible_to_overrides + + # OPTIONAL - assignment[published] + """Whether this assignment is published. + (Only useful if 'draft state' account setting is on) + Unpublished assignments are not visible to students.""" + if assignment_published is not None: + data["assignment[published]"] = assignment_published + + # OPTIONAL - assignment[grading_standard_id] + """The grading standard id to set for the course. If no value is provided for this argument the current grading_standard will be un-set from this course. + This will update the grading_type for the course to 'letter_grade' unless it is already 'gpa_scale'.""" + if assignment_grading_standard_id is not None: + data["assignment[grading_standard_id]"] = assignment_grading_standard_id + + # OPTIONAL - assignment[omit_from_final_grade] + """Whether this assignment is counted towards a student's final grade.""" + if assignment_omit_from_final_grade is not None: + data["assignment[omit_from_final_grade]"] = assignment_omit_from_final_grade + + self.logger.debug("POST /api/v1/courses/{course_id}/assignments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/assignments".format(**path), data=data, params=params, single_item=True) + + def edit_assignment(self, id, course_id, assignment_allowed_extensions=None, assignment_assignment_group_id=None, assignment_assignment_overrides=None, assignment_automatic_peer_reviews=None, assignment_description=None, assignment_due_at=None, assignment_external_tool_tag_attributes=None, assignment_grade_group_students_individually=None, assignment_grading_standard_id=None, assignment_grading_type=None, assignment_group_category_id=None, assignment_integration_data=None, assignment_integration_id=None, assignment_lock_at=None, assignment_muted=None, assignment_name=None, assignment_notify_of_update=None, assignment_omit_from_final_grade=None, assignment_only_visible_to_overrides=None, assignment_peer_reviews=None, assignment_points_possible=None, assignment_position=None, assignment_published=None, assignment_submission_types=None, assignment_turnitin_enabled=None, assignment_turnitin_settings=None, assignment_unlock_at=None, assignment_vericite_enabled=None): + """ + Edit an assignment. + + Modify an existing assignment. + + If the assignment [assignment_overrides] key is absent, any existing + overrides are kept as is. If the assignment [assignment_overrides] key is + present, existing overrides are updated or deleted (and new ones created, + as necessary) to match the provided list. + + NOTE: The assignment overrides feature is in beta. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - assignment[name] + """The assignment name.""" + if assignment_name is not None: + data["assignment[name]"] = assignment_name + + # OPTIONAL - assignment[position] + """The position of this assignment in the group when displaying + assignment lists.""" + if assignment_position is not None: + data["assignment[position]"] = assignment_position + + # OPTIONAL - assignment[submission_types] + """List of supported submission types for the assignment. + Unless the assignment is allowing online submissions, the array should + only have one element. + + If not allowing online submissions, your options are: + "online_quiz" + "none" + "on_paper" + "online_quiz" + "discussion_topic" + "external_tool" + + If you are allowing online submissions, you can have one or many + allowed submission types: + + "online_upload" + "online_text_entry" + "online_url" + "media_recording" (Only valid when the Kaltura plugin is enabled)""" + if assignment_submission_types is not None: + self._validate_enum(assignment_submission_types, ["online_quiz", "none", "on_paper", "online_quiz", "discussion_topic", "external_tool", "online_upload", "online_text_entry", "online_url", "media_recording"]) + data["assignment[submission_types]"] = assignment_submission_types + + # OPTIONAL - assignment[allowed_extensions] + """Allowed extensions if submission_types includes "online_upload" + + Example: + allowed_extensions: ["docx","ppt"]""" + if assignment_allowed_extensions is not None: + data["assignment[allowed_extensions]"] = assignment_allowed_extensions + + # OPTIONAL - assignment[turnitin_enabled] + """Only applies when the Turnitin plugin is enabled for a course and + the submission_types array includes "online_upload". + Toggles Turnitin submissions for the assignment. + Will be ignored if Turnitin is not available for the course.""" + if assignment_turnitin_enabled is not None: + data["assignment[turnitin_enabled]"] = assignment_turnitin_enabled + + # OPTIONAL - assignment[vericite_enabled] + """Only applies when the VeriCite plugin is enabled for a course and + the submission_types array includes "online_upload". + Toggles VeriCite submissions for the assignment. + Will be ignored if VeriCite is not available for the course.""" + if assignment_vericite_enabled is not None: + data["assignment[vericite_enabled]"] = assignment_vericite_enabled + + # OPTIONAL - assignment[turnitin_settings] + """Settings to send along to turnitin. See Assignment object definition for + format.""" + if assignment_turnitin_settings is not None: + data["assignment[turnitin_settings]"] = assignment_turnitin_settings + + # OPTIONAL - assignment[integration_data] + """Data related to third party integrations, JSON string required.""" + if assignment_integration_data is not None: + data["assignment[integration_data]"] = assignment_integration_data + + # OPTIONAL - assignment[integration_id] + """Unique ID from third party integrations""" + if assignment_integration_id is not None: + data["assignment[integration_id]"] = assignment_integration_id + + # OPTIONAL - assignment[peer_reviews] + """If submission_types does not include external_tool,discussion_topic, + online_quiz, or on_paper, determines whether or not peer reviews + will be turned on for the assignment.""" + if assignment_peer_reviews is not None: + data["assignment[peer_reviews]"] = assignment_peer_reviews + + # OPTIONAL - assignment[automatic_peer_reviews] + """Whether peer reviews will be assigned automatically by Canvas or if + teachers must manually assign peer reviews. Does not apply if peer reviews + are not enabled.""" + if assignment_automatic_peer_reviews is not None: + data["assignment[automatic_peer_reviews]"] = assignment_automatic_peer_reviews + + # OPTIONAL - assignment[notify_of_update] + """If true, Canvas will send a notification to students in the class + notifying them that the content has changed.""" + if assignment_notify_of_update is not None: + data["assignment[notify_of_update]"] = assignment_notify_of_update + + # OPTIONAL - assignment[group_category_id] + """If present, the assignment will become a group assignment assigned + to the group.""" + if assignment_group_category_id is not None: + data["assignment[group_category_id]"] = assignment_group_category_id + + # OPTIONAL - assignment[grade_group_students_individually] + """If this is a group assignment, teachers have the options to grade + students individually. If false, Canvas will apply the assignment's + score to each member of the group. If true, the teacher can manually + assign scores to each member of the group.""" + if assignment_grade_group_students_individually is not None: + data["assignment[grade_group_students_individually]"] = assignment_grade_group_students_individually + + # OPTIONAL - assignment[external_tool_tag_attributes] + """Hash of external tool parameters if submission_types is ["external_tool"]. + See Assignment object definition for format.""" + if assignment_external_tool_tag_attributes is not None: + data["assignment[external_tool_tag_attributes]"] = assignment_external_tool_tag_attributes + + # OPTIONAL - assignment[points_possible] + """The maximum points possible on the assignment.""" + if assignment_points_possible is not None: + data["assignment[points_possible]"] = assignment_points_possible + + # OPTIONAL - assignment[grading_type] + """The strategy used for grading the assignment. + The assignment defaults to "points" if this field is omitted.""" + if assignment_grading_type is not None: + self._validate_enum(assignment_grading_type, ["pass_fail", "percent", "letter_grade", "gpa_scale", "points"]) + data["assignment[grading_type]"] = assignment_grading_type + + # OPTIONAL - assignment[due_at] + """The day/time the assignment is due. + Accepts times in ISO 8601 format, e.g. 2014-10-21T18:48:00Z.""" + if assignment_due_at is not None: + data["assignment[due_at]"] = assignment_due_at + + # OPTIONAL - assignment[lock_at] + """The day/time the assignment is locked after. + Accepts times in ISO 8601 format, e.g. 2014-10-21T18:48:00Z.""" + if assignment_lock_at is not None: + data["assignment[lock_at]"] = assignment_lock_at + + # OPTIONAL - assignment[unlock_at] + """The day/time the assignment is unlocked. + Accepts times in ISO 8601 format, e.g. 2014-10-21T18:48:00Z.""" + if assignment_unlock_at is not None: + data["assignment[unlock_at]"] = assignment_unlock_at + + # OPTIONAL - assignment[description] + """The assignment's description, supports HTML.""" + if assignment_description is not None: + data["assignment[description]"] = assignment_description + + # OPTIONAL - assignment[assignment_group_id] + """The assignment group id to put the assignment in. + Defaults to the top assignment group in the course.""" + if assignment_assignment_group_id is not None: + data["assignment[assignment_group_id]"] = assignment_assignment_group_id + + # OPTIONAL - assignment[muted] + """Whether this assignment is muted. + A muted assignment does not send change notifications + and hides grades from students. + Defaults to false.""" + if assignment_muted is not None: + data["assignment[muted]"] = assignment_muted + + # OPTIONAL - assignment[assignment_overrides] + """List of overrides for the assignment. + NOTE: The assignment overrides feature is in beta.""" + if assignment_assignment_overrides is not None: + data["assignment[assignment_overrides]"] = assignment_assignment_overrides + + # OPTIONAL - assignment[only_visible_to_overrides] + """Whether this assignment is only visible to overrides + (Only useful if 'differentiated assignments' account setting is on)""" + if assignment_only_visible_to_overrides is not None: + data["assignment[only_visible_to_overrides]"] = assignment_only_visible_to_overrides + + # OPTIONAL - assignment[published] + """Whether this assignment is published. + (Only useful if 'draft state' account setting is on) + Unpublished assignments are not visible to students.""" + if assignment_published is not None: + data["assignment[published]"] = assignment_published + + # OPTIONAL - assignment[grading_standard_id] + """The grading standard id to set for the course. If no value is provided for this argument the current grading_standard will be un-set from this course. + This will update the grading_type for the course to 'letter_grade' unless it is already 'gpa_scale'.""" + if assignment_grading_standard_id is not None: + data["assignment[grading_standard_id]"] = assignment_grading_standard_id + + # OPTIONAL - assignment[omit_from_final_grade] + """Whether this assignment is counted towards a student's final grade.""" + if assignment_omit_from_final_grade is not None: + data["assignment[omit_from_final_grade]"] = assignment_omit_from_final_grade + + self.logger.debug("PUT /api/v1/courses/{course_id}/assignments/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/assignments/{id}".format(**path), data=data, params=params, single_item=True) + + def list_assignment_overrides(self, course_id, assignment_id): + """ + List assignment overrides. + + Returns the list of overrides for this assignment that target + sections/groups/students visible to the current user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + self.logger.debug("GET /api/v1/courses/{course_id}/assignments/{assignment_id}/overrides with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignments/{assignment_id}/overrides".format(**path), data=data, params=params, all_pages=True) + + def get_single_assignment_override(self, id, course_id, assignment_id): + """ + Get a single assignment override. + + Returns details of the the override with the given id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/assignments/{assignment_id}/overrides/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignments/{assignment_id}/overrides/{id}".format(**path), data=data, params=params, single_item=True) + + def redirect_to_assignment_override_for_group(self, group_id, assignment_id): + """ + Redirect to the assignment override for a group. + + Responds with a redirect to the override for the given group, if any + (404 otherwise). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + self.logger.debug("GET /api/v1/groups/{group_id}/assignments/{assignment_id}/override with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/assignments/{assignment_id}/override".format(**path), data=data, params=params, no_data=True) + + def redirect_to_assignment_override_for_section(self, assignment_id, course_section_id): + """ + Redirect to the assignment override for a section. + + Responds with a redirect to the override for the given section, if any + (404 otherwise). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_section_id + """ID""" + path["course_section_id"] = course_section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + self.logger.debug("GET /api/v1/sections/{course_section_id}/assignments/{assignment_id}/override with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/sections/{course_section_id}/assignments/{assignment_id}/override".format(**path), data=data, params=params, no_data=True) + + def create_assignment_override(self, course_id, assignment_id, assignment_override_course_section_id=None, assignment_override_due_at=None, assignment_override_group_id=None, assignment_override_lock_at=None, assignment_override_student_ids=None, assignment_override_title=None, assignment_override_unlock_at=None): + """ + Create an assignment override. + + One of student_ids, group_id, or course_section_id must be present. At most + one should be present; if multiple are present only the most specific + (student_ids first, then group_id, then course_section_id) is used and any + others are ignored. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # OPTIONAL - assignment_override[student_ids] + """The IDs of + the override's target students. If present, the IDs must each identify a + user with an active student enrollment in the course that is not already + targetted by a different adhoc override.""" + if assignment_override_student_ids is not None: + data["assignment_override[student_ids]"] = assignment_override_student_ids + + # OPTIONAL - assignment_override[title] + """The title of the adhoc + assignment override. Required if student_ids is present, ignored + otherwise (the title is set to the name of the targetted group or section + instead).""" + if assignment_override_title is not None: + data["assignment_override[title]"] = assignment_override_title + + # OPTIONAL - assignment_override[group_id] + """The ID of the + override's target group. If present, the following conditions must be met + for the override to be successful: + + 1. the assignment MUST be a group assignment (a group_category_id is assigned to it) + 2. the ID must identify an active group in the group set the assignment is in + 3. the ID must not be targetted by a different override + + See {Appendix: Group assignments} for more info.""" + if assignment_override_group_id is not None: + data["assignment_override[group_id]"] = assignment_override_group_id + + # OPTIONAL - assignment_override[course_section_id] + """The ID + of the override's target section. If present, must identify an active + section of the assignment's course not already targetted by a different + override.""" + if assignment_override_course_section_id is not None: + data["assignment_override[course_section_id]"] = assignment_override_course_section_id + + # OPTIONAL - assignment_override[due_at] + """The day/time + the overridden assignment is due. Accepts times in ISO 8601 format, e.g. + 2014-10-21T18:48:00Z. If absent, this override will not affect due date. + May be present but null to indicate the override removes any previous due + date.""" + if assignment_override_due_at is not None: + data["assignment_override[due_at]"] = assignment_override_due_at + + # OPTIONAL - assignment_override[unlock_at] + """The day/time + the overridden assignment becomes unlocked. Accepts times in ISO 8601 + format, e.g. 2014-10-21T18:48:00Z. If absent, this override will not + affect the unlock date. May be present but null to indicate the override + removes any previous unlock date.""" + if assignment_override_unlock_at is not None: + data["assignment_override[unlock_at]"] = assignment_override_unlock_at + + # OPTIONAL - assignment_override[lock_at] + """The day/time + the overridden assignment becomes locked. Accepts times in ISO 8601 + format, e.g. 2014-10-21T18:48:00Z. If absent, this override will not + affect the lock date. May be present but null to indicate the override + removes any previous lock date.""" + if assignment_override_lock_at is not None: + data["assignment_override[lock_at]"] = assignment_override_lock_at + + self.logger.debug("POST /api/v1/courses/{course_id}/assignments/{assignment_id}/overrides with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/assignments/{assignment_id}/overrides".format(**path), data=data, params=params, single_item=True) + + def update_assignment_override(self, id, course_id, assignment_id, assignment_override_due_at=None, assignment_override_lock_at=None, assignment_override_student_ids=None, assignment_override_title=None, assignment_override_unlock_at=None): + """ + Update an assignment override. + + All current overridden values must be supplied if they are to be retained; + e.g. if due_at was overridden, but this PUT omits a value for due_at, + due_at will no longer be overridden. If the override is adhoc and + student_ids is not supplied, the target override set is unchanged. Target + override sets cannot be changed for group or section overrides. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - assignment_override[student_ids] + """The IDs of the + override's target students. If present, the IDs must each identify a + user with an active student enrollment in the course that is not already + targetted by a different adhoc override. Ignored unless the override + being updated is adhoc.""" + if assignment_override_student_ids is not None: + data["assignment_override[student_ids]"] = assignment_override_student_ids + + # OPTIONAL - assignment_override[title] + """The title of an adhoc + assignment override. Ignored unless the override being updated is adhoc.""" + if assignment_override_title is not None: + data["assignment_override[title]"] = assignment_override_title + + # OPTIONAL - assignment_override[due_at] + """The day/time + the overridden assignment is due. Accepts times in ISO 8601 format, e.g. + 2014-10-21T18:48:00Z. If absent, this override will not affect due date. + May be present but null to indicate the override removes any previous due + date.""" + if assignment_override_due_at is not None: + data["assignment_override[due_at]"] = assignment_override_due_at + + # OPTIONAL - assignment_override[unlock_at] + """The day/time + the overridden assignment becomes unlocked. Accepts times in ISO 8601 + format, e.g. 2014-10-21T18:48:00Z. If absent, this override will not + affect the unlock date. May be present but null to indicate the override + removes any previous unlock date.""" + if assignment_override_unlock_at is not None: + data["assignment_override[unlock_at]"] = assignment_override_unlock_at + + # OPTIONAL - assignment_override[lock_at] + """The day/time + the overridden assignment becomes locked. Accepts times in ISO 8601 + format, e.g. 2014-10-21T18:48:00Z. If absent, this override will not + affect the lock date. May be present but null to indicate the override + removes any previous lock date.""" + if assignment_override_lock_at is not None: + data["assignment_override[lock_at]"] = assignment_override_lock_at + + self.logger.debug("PUT /api/v1/courses/{course_id}/assignments/{assignment_id}/overrides/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/assignments/{assignment_id}/overrides/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_assignment_override(self, id, course_id, assignment_id): + """ + Delete an assignment override. + + Deletes an override and returns its former details. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/assignments/{assignment_id}/overrides/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/assignments/{assignment_id}/overrides/{id}".format(**path), data=data, params=params, single_item=True) + + def batch_retrieve_overrides_in_course(self, course_id, assignment_overrides_id, assignment_overrides_assignment_id): + """ + Batch retrieve overrides in a course. + + Returns a list of specified overrides in this course, providing + they target sections/groups/students visible to the current user. + Returns null elements in the list for requests that were not found. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - assignment_overrides[id] + """Ids of overrides to retrieve""" + params["assignment_overrides[id]"] = assignment_overrides_id + + # REQUIRED - assignment_overrides[assignment_id] + """Ids of assignments for each override""" + params["assignment_overrides[assignment_id]"] = assignment_overrides_assignment_id + + self.logger.debug("GET /api/v1/courses/{course_id}/assignments/overrides with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignments/overrides".format(**path), data=data, params=params, all_pages=True) + + def batch_create_overrides_in_course(self, course_id, assignment_overrides): + """ + Batch create overrides in a course. + + Creates the specified overrides for each assignment. Handles creation in a + transaction, so all records are created or none are. + + One of student_ids, group_id, or course_section_id must be present. At most + one should be present; if multiple are present only the most specific + (student_ids first, then group_id, then course_section_id) is used and any + others are ignored. + + Errors are reported in an errors attribute, an array of errors corresponding + to inputs. Global errors will be reported as a single element errors array + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - assignment_overrides + """Attributes for the new assignment overrides. + See {api:AssignmentOverridesController#create Create an assignment override} for available + attributes""" + data["assignment_overrides"] = assignment_overrides + + self.logger.debug("POST /api/v1/courses/{course_id}/assignments/overrides with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/assignments/overrides".format(**path), data=data, params=params, all_pages=True) + + def batch_update_overrides_in_course(self, course_id, assignment_overrides): + """ + Batch update overrides in a course. + + Updates a list of specified overrides for each assignment. Handles overrides + in a transaction, so either all updates are applied or none. + See {api:AssignmentOverridesController#update Update an assignment override} for + available attributes. + + All current overridden values must be supplied if they are to be retained; + e.g. if due_at was overridden, but this PUT omits a value for due_at, + due_at will no longer be overridden. If the override is adhoc and + student_ids is not supplied, the target override set is unchanged. Target + override sets cannot be changed for group or section overrides. + + Errors are reported in an errors attribute, an array of errors corresponding + to inputs. Global errors will be reported as a single element errors array + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - assignment_overrides + """Attributes for the updated overrides.""" + data["assignment_overrides"] = assignment_overrides + + self.logger.debug("PUT /api/v1/courses/{course_id}/assignments/overrides with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/assignments/overrides".format(**path), data=data, params=params, all_pages=True) + + +class Turnitinsettings(BaseModel): + """Turnitinsettings Model.""" + + def __init__(self, originality_report_visibility=None, s_paper_check=None, journal_check=None, exclude_small_matches_type=None, exclude_quoted=None, internet_check=None, exclude_small_matches_value=None, exclude_biblio=None): + """Init method for Turnitinsettings class.""" + self._originality_report_visibility = originality_report_visibility + self._s_paper_check = s_paper_check + self._journal_check = journal_check + self._exclude_small_matches_type = exclude_small_matches_type + self._exclude_quoted = exclude_quoted + self._internet_check = internet_check + self._exclude_small_matches_value = exclude_small_matches_value + self._exclude_biblio = exclude_biblio + + self.logger = logging.getLogger('pycanvas.Turnitinsettings') + + @property + def originality_report_visibility(self): + """originality_report_visibility.""" + return self._originality_report_visibility + + @originality_report_visibility.setter + def originality_report_visibility(self, value): + """Setter for originality_report_visibility property.""" + self.logger.warn("Setting values on originality_report_visibility will NOT update the remote Canvas instance.") + self._originality_report_visibility = value + + @property + def s_paper_check(self): + """s_paper_check.""" + return self._s_paper_check + + @s_paper_check.setter + def s_paper_check(self, value): + """Setter for s_paper_check property.""" + self.logger.warn("Setting values on s_paper_check will NOT update the remote Canvas instance.") + self._s_paper_check = value + + @property + def journal_check(self): + """journal_check.""" + return self._journal_check + + @journal_check.setter + def journal_check(self, value): + """Setter for journal_check property.""" + self.logger.warn("Setting values on journal_check will NOT update the remote Canvas instance.") + self._journal_check = value + + @property + def exclude_small_matches_type(self): + """exclude_small_matches_type.""" + return self._exclude_small_matches_type + + @exclude_small_matches_type.setter + def exclude_small_matches_type(self, value): + """Setter for exclude_small_matches_type property.""" + self.logger.warn("Setting values on exclude_small_matches_type will NOT update the remote Canvas instance.") + self._exclude_small_matches_type = value + + @property + def exclude_quoted(self): + """exclude_quoted.""" + return self._exclude_quoted + + @exclude_quoted.setter + def exclude_quoted(self, value): + """Setter for exclude_quoted property.""" + self.logger.warn("Setting values on exclude_quoted will NOT update the remote Canvas instance.") + self._exclude_quoted = value + + @property + def internet_check(self): + """internet_check.""" + return self._internet_check + + @internet_check.setter + def internet_check(self, value): + """Setter for internet_check property.""" + self.logger.warn("Setting values on internet_check will NOT update the remote Canvas instance.") + self._internet_check = value + + @property + def exclude_small_matches_value(self): + """exclude_small_matches_value.""" + return self._exclude_small_matches_value + + @exclude_small_matches_value.setter + def exclude_small_matches_value(self, value): + """Setter for exclude_small_matches_value property.""" + self.logger.warn("Setting values on exclude_small_matches_value will NOT update the remote Canvas instance.") + self._exclude_small_matches_value = value + + @property + def exclude_biblio(self): + """exclude_biblio.""" + return self._exclude_biblio + + @exclude_biblio.setter + def exclude_biblio(self, value): + """Setter for exclude_biblio property.""" + self.logger.warn("Setting values on exclude_biblio will NOT update the remote Canvas instance.") + self._exclude_biblio = value + + +class Assignmentoverride(BaseModel): + """Assignmentoverride Model. + NOTE: The Assignment Override feature is in beta! This API is not finalized and there could be breaking changes before its final release.""" + + def __init__(self, unlock_at=None, title=None, assignment_id=None, lock_at=None, course_section_id=None, all_day=None, student_ids=None, all_day_date=None, due_at=None, group_id=None, id=None): + """Init method for Assignmentoverride class.""" + self._unlock_at = unlock_at + self._title = title + self._assignment_id = assignment_id + self._lock_at = lock_at + self._course_section_id = course_section_id + self._all_day = all_day + self._student_ids = student_ids + self._all_day_date = all_day_date + self._due_at = due_at + self._group_id = group_id + self._id = id + + self.logger = logging.getLogger('pycanvas.Assignmentoverride') + + @property + def unlock_at(self): + """the overridden unlock at (present if unlock_at is overridden).""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def title(self): + """the title of the override.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def assignment_id(self): + """the ID of the assignment the override applies to.""" + return self._assignment_id + + @assignment_id.setter + def assignment_id(self, value): + """Setter for assignment_id property.""" + self.logger.warn("Setting values on assignment_id will NOT update the remote Canvas instance.") + self._assignment_id = value + + @property + def lock_at(self): + """the overridden lock at, if any (present if lock_at is overridden).""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def course_section_id(self): + """the ID of the overrides's target section (present if the override targets a section).""" + return self._course_section_id + + @course_section_id.setter + def course_section_id(self, value): + """Setter for course_section_id property.""" + self.logger.warn("Setting values on course_section_id will NOT update the remote Canvas instance.") + self._course_section_id = value + + @property + def all_day(self): + """the overridden all day flag (present if due_at is overridden).""" + return self._all_day + + @all_day.setter + def all_day(self, value): + """Setter for all_day property.""" + self.logger.warn("Setting values on all_day will NOT update the remote Canvas instance.") + self._all_day = value + + @property + def student_ids(self): + """the IDs of the override's target students (present if the override targets an ad-hoc set of students).""" + return self._student_ids + + @student_ids.setter + def student_ids(self, value): + """Setter for student_ids property.""" + self.logger.warn("Setting values on student_ids will NOT update the remote Canvas instance.") + self._student_ids = value + + @property + def all_day_date(self): + """the overridden all day date (present if due_at is overridden).""" + return self._all_day_date + + @all_day_date.setter + def all_day_date(self, value): + """Setter for all_day_date property.""" + self.logger.warn("Setting values on all_day_date will NOT update the remote Canvas instance.") + self._all_day_date = value + + @property + def due_at(self): + """the overridden due at (present if due_at is overridden).""" + return self._due_at + + @due_at.setter + def due_at(self, value): + """Setter for due_at property.""" + self.logger.warn("Setting values on due_at will NOT update the remote Canvas instance.") + self._due_at = value + + @property + def group_id(self): + """the ID of the override's target group (present if the override targets a group and the assignment is a group assignment).""" + return self._group_id + + @group_id.setter + def group_id(self, value): + """Setter for group_id property.""" + self.logger.warn("Setting values on group_id will NOT update the remote Canvas instance.") + self._group_id = value + + @property + def id(self): + """the ID of the assignment override.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Externaltooltagattributes(BaseModel): + """Externaltooltagattributes Model.""" + + def __init__(self, url=None, new_tab=None, resource_link_id=None): + """Init method for Externaltooltagattributes class.""" + self._url = url + self._new_tab = new_tab + self._resource_link_id = resource_link_id + + self.logger = logging.getLogger('pycanvas.Externaltooltagattributes') + + @property + def url(self): + """URL to the external tool.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def new_tab(self): + """Whether or not there is a new tab for the external tool.""" + return self._new_tab + + @new_tab.setter + def new_tab(self, value): + """Setter for new_tab property.""" + self.logger.warn("Setting values on new_tab will NOT update the remote Canvas instance.") + self._new_tab = value + + @property + def resource_link_id(self): + """the identifier for this tool_tag.""" + return self._resource_link_id + + @resource_link_id.setter + def resource_link_id(self, value): + """Setter for resource_link_id property.""" + self.logger.warn("Setting values on resource_link_id will NOT update the remote Canvas instance.") + self._resource_link_id = value + + +class Assignment(BaseModel): + """Assignment Model.""" + + def __init__(self, use_rubric_for_grading=None, has_overrides=None, lock_info=None, frozen_attributes=None, points_possible=None, assignment_visibility=None, updated_at=None, turnitin_enabled=None, rubric=None, omit_from_final_grade=None, course_id=None, needs_grading_count_by_section=None, id=None, locked_for_user=None, muted=None, grading_type=None, rubric_settings=None, anonymous_submissions=None, peer_reviews=None, discussion_topic=None, intra_group_peer_reviews=None, quiz_id=None, freeze_on_copy=None, all_dates=None, integration_data=None, description=None, peer_review_count=None, grade_group_students_individually=None, grading_standard_id=None, external_tool_tag_attributes=None, html_url=None, turnitin_settings=None, group_category_id=None, lock_explanation=None, needs_grading_count=None, vericite_enabled=None, peer_reviews_assign_at=None, name=None, integration_id=None, frozen=None, only_visible_to_overrides=None, unlock_at=None, submission=None, due_at=None, created_at=None, post_to_sis=None, lock_at=None, assignment_group_id=None, allowed_extensions=None, automatic_peer_reviews=None, published=None, position=None, submission_types=None, submissions_download_url=None, overrides=None, unpublishable=None): + """Init method for Assignment class.""" + self._use_rubric_for_grading = use_rubric_for_grading + self._has_overrides = has_overrides + self._lock_info = lock_info + self._frozen_attributes = frozen_attributes + self._points_possible = points_possible + self._assignment_visibility = assignment_visibility + self._updated_at = updated_at + self._turnitin_enabled = turnitin_enabled + self._rubric = rubric + self._omit_from_final_grade = omit_from_final_grade + self._course_id = course_id + self._needs_grading_count_by_section = needs_grading_count_by_section + self._id = id + self._locked_for_user = locked_for_user + self._muted = muted + self._grading_type = grading_type + self._rubric_settings = rubric_settings + self._anonymous_submissions = anonymous_submissions + self._peer_reviews = peer_reviews + self._discussion_topic = discussion_topic + self._intra_group_peer_reviews = intra_group_peer_reviews + self._quiz_id = quiz_id + self._freeze_on_copy = freeze_on_copy + self._all_dates = all_dates + self._integration_data = integration_data + self._description = description + self._peer_review_count = peer_review_count + self._grade_group_students_individually = grade_group_students_individually + self._grading_standard_id = grading_standard_id + self._external_tool_tag_attributes = external_tool_tag_attributes + self._html_url = html_url + self._turnitin_settings = turnitin_settings + self._group_category_id = group_category_id + self._lock_explanation = lock_explanation + self._needs_grading_count = needs_grading_count + self._vericite_enabled = vericite_enabled + self._peer_reviews_assign_at = peer_reviews_assign_at + self._name = name + self._integration_id = integration_id + self._frozen = frozen + self._only_visible_to_overrides = only_visible_to_overrides + self._unlock_at = unlock_at + self._submission = submission + self._due_at = due_at + self._created_at = created_at + self._post_to_sis = post_to_sis + self._lock_at = lock_at + self._assignment_group_id = assignment_group_id + self._allowed_extensions = allowed_extensions + self._automatic_peer_reviews = automatic_peer_reviews + self._published = published + self._position = position + self._submission_types = submission_types + self._submissions_download_url = submissions_download_url + self._overrides = overrides + self._unpublishable = unpublishable + + self.logger = logging.getLogger('pycanvas.Assignment') + + @property + def use_rubric_for_grading(self): + """(Optional) If true, the rubric is directly tied to grading the assignment. Otherwise, it is only advisory. Included if there is an associated rubric.""" + return self._use_rubric_for_grading + + @use_rubric_for_grading.setter + def use_rubric_for_grading(self, value): + """Setter for use_rubric_for_grading property.""" + self.logger.warn("Setting values on use_rubric_for_grading will NOT update the remote Canvas instance.") + self._use_rubric_for_grading = value + + @property + def has_overrides(self): + """whether this assignment has overrides.""" + return self._has_overrides + + @has_overrides.setter + def has_overrides(self, value): + """Setter for has_overrides property.""" + self.logger.warn("Setting values on has_overrides will NOT update the remote Canvas instance.") + self._has_overrides = value + + @property + def lock_info(self): + """(Optional) Information for the user about the lock. Present when locked_for_user is true.""" + return self._lock_info + + @lock_info.setter + def lock_info(self, value): + """Setter for lock_info property.""" + self.logger.warn("Setting values on lock_info will NOT update the remote Canvas instance.") + self._lock_info = value + + @property + def frozen_attributes(self): + """(Optional) Array of frozen attributes for the assignment. Only account administrators currently have permission to change an attribute in this list. Will be empty if no attributes are frozen for this assignment. Possible frozen attributes are: title, description, lock_at, points_possible, grading_type, submission_types, assignment_group_id, allowed_extensions, group_category_id, notify_of_update, peer_reviews NOTE: This field will only be present if the AssignmentFreezer plugin is available for your account.""" + return self._frozen_attributes + + @frozen_attributes.setter + def frozen_attributes(self, value): + """Setter for frozen_attributes property.""" + self.logger.warn("Setting values on frozen_attributes will NOT update the remote Canvas instance.") + self._frozen_attributes = value + + @property + def points_possible(self): + """the maximum points possible for the assignment.""" + return self._points_possible + + @points_possible.setter + def points_possible(self, value): + """Setter for points_possible property.""" + self.logger.warn("Setting values on points_possible will NOT update the remote Canvas instance.") + self._points_possible = value + + @property + def assignment_visibility(self): + """(Optional) If 'assignment_visibility' is included in the 'include' parameter, includes an array of student IDs who can see this assignment.""" + return self._assignment_visibility + + @assignment_visibility.setter + def assignment_visibility(self, value): + """Setter for assignment_visibility property.""" + self.logger.warn("Setting values on assignment_visibility will NOT update the remote Canvas instance.") + self._assignment_visibility = value + + @property + def updated_at(self): + """The time at which this assignment was last modified in any way.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def turnitin_enabled(self): + """Boolean flag indicating whether or not Turnitin has been enabled for the assignment. NOTE: This flag will not appear unless your account has the Turnitin plugin available.""" + return self._turnitin_enabled + + @turnitin_enabled.setter + def turnitin_enabled(self, value): + """Setter for turnitin_enabled property.""" + self.logger.warn("Setting values on turnitin_enabled will NOT update the remote Canvas instance.") + self._turnitin_enabled = value + + @property + def rubric(self): + """(Optional) A list of scoring criteria and ratings for each rubric criterion. Included if there is an associated rubric.""" + return self._rubric + + @rubric.setter + def rubric(self, value): + """Setter for rubric property.""" + self.logger.warn("Setting values on rubric will NOT update the remote Canvas instance.") + self._rubric = value + + @property + def omit_from_final_grade(self): + """(Optional) If true, the assignment will be ommitted from the student's final grade.""" + return self._omit_from_final_grade + + @omit_from_final_grade.setter + def omit_from_final_grade(self, value): + """Setter for omit_from_final_grade property.""" + self.logger.warn("Setting values on omit_from_final_grade will NOT update the remote Canvas instance.") + self._omit_from_final_grade = value + + @property + def course_id(self): + """the ID of the course the assignment belongs to.""" + return self._course_id + + @course_id.setter + def course_id(self, value): + """Setter for course_id property.""" + self.logger.warn("Setting values on course_id will NOT update the remote Canvas instance.") + self._course_id = value + + @property + def needs_grading_count_by_section(self): + """if the requesting user has grading rights and the 'needs_grading_count_by_section' flag is specified, the number of submissions that need grading split out by section. NOTE: This key is NOT present unless you pass the 'needs_grading_count_by_section' argument as true. ANOTHER NOTE: it's possible to be enrolled in multiple sections, and if a student is setup that way they will show an assignment that needs grading in multiple sections (effectively the count will be duplicated between sections).""" + return self._needs_grading_count_by_section + + @needs_grading_count_by_section.setter + def needs_grading_count_by_section(self, value): + """Setter for needs_grading_count_by_section property.""" + self.logger.warn("Setting values on needs_grading_count_by_section will NOT update the remote Canvas instance.") + self._needs_grading_count_by_section = value + + @property + def id(self): + """the ID of the assignment.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def locked_for_user(self): + """Whether or not this is locked for the user.""" + return self._locked_for_user + + @locked_for_user.setter + def locked_for_user(self, value): + """Setter for locked_for_user property.""" + self.logger.warn("Setting values on locked_for_user will NOT update the remote Canvas instance.") + self._locked_for_user = value + + @property + def muted(self): + """whether the assignment is muted.""" + return self._muted + + @muted.setter + def muted(self, value): + """Setter for muted property.""" + self.logger.warn("Setting values on muted will NOT update the remote Canvas instance.") + self._muted = value + + @property + def grading_type(self): + """The type of grading the assignment receives; one of 'pass_fail', 'percent', 'letter_grade', 'gpa_scale', 'points'.""" + return self._grading_type + + @grading_type.setter + def grading_type(self, value): + """Setter for grading_type property.""" + self.logger.warn("Setting values on grading_type will NOT update the remote Canvas instance.") + self._grading_type = value + + @property + def rubric_settings(self): + """(Optional) An object describing the basic attributes of the rubric, including the point total. Included if there is an associated rubric.""" + return self._rubric_settings + + @rubric_settings.setter + def rubric_settings(self, value): + """Setter for rubric_settings property.""" + self.logger.warn("Setting values on rubric_settings will NOT update the remote Canvas instance.") + self._rubric_settings = value + + @property + def anonymous_submissions(self): + """(Optional) whether anonymous submissions are accepted (applies only to quiz assignments).""" + return self._anonymous_submissions + + @anonymous_submissions.setter + def anonymous_submissions(self, value): + """Setter for anonymous_submissions property.""" + self.logger.warn("Setting values on anonymous_submissions will NOT update the remote Canvas instance.") + self._anonymous_submissions = value + + @property + def peer_reviews(self): + """Boolean indicating if peer reviews are required for this assignment.""" + return self._peer_reviews + + @peer_reviews.setter + def peer_reviews(self, value): + """Setter for peer_reviews property.""" + self.logger.warn("Setting values on peer_reviews will NOT update the remote Canvas instance.") + self._peer_reviews = value + + @property + def discussion_topic(self): + """(Optional) the DiscussionTopic associated with the assignment, if applicable.""" + return self._discussion_topic + + @discussion_topic.setter + def discussion_topic(self, value): + """Setter for discussion_topic property.""" + self.logger.warn("Setting values on discussion_topic will NOT update the remote Canvas instance.") + self._discussion_topic = value + + @property + def intra_group_peer_reviews(self): + """Boolean representing whether or not members from within the same group on a group assignment can be assigned to peer review their own group's work.""" + return self._intra_group_peer_reviews + + @intra_group_peer_reviews.setter + def intra_group_peer_reviews(self, value): + """Setter for intra_group_peer_reviews property.""" + self.logger.warn("Setting values on intra_group_peer_reviews will NOT update the remote Canvas instance.") + self._intra_group_peer_reviews = value + + @property + def quiz_id(self): + """(Optional) id of the associated quiz (applies only when submission_types is ['online_quiz']).""" + return self._quiz_id + + @quiz_id.setter + def quiz_id(self, value): + """Setter for quiz_id property.""" + self.logger.warn("Setting values on quiz_id will NOT update the remote Canvas instance.") + self._quiz_id = value + + @property + def freeze_on_copy(self): + """(Optional) Boolean indicating if assignment will be frozen when it is copied. NOTE: This field will only be present if the AssignmentFreezer plugin is available for your account.""" + return self._freeze_on_copy + + @freeze_on_copy.setter + def freeze_on_copy(self, value): + """Setter for freeze_on_copy property.""" + self.logger.warn("Setting values on freeze_on_copy will NOT update the remote Canvas instance.") + self._freeze_on_copy = value + + @property + def all_dates(self): + """(Optional) all dates associated with the assignment, if applicable.""" + return self._all_dates + + @all_dates.setter + def all_dates(self, value): + """Setter for all_dates property.""" + self.logger.warn("Setting values on all_dates will NOT update the remote Canvas instance.") + self._all_dates = value + + @property + def integration_data(self): + """(optional, Third Party integration data for assignment).""" + return self._integration_data + + @integration_data.setter + def integration_data(self, value): + """Setter for integration_data property.""" + self.logger.warn("Setting values on integration_data will NOT update the remote Canvas instance.") + self._integration_data = value + + @property + def description(self): + """the assignment description, in an HTML fragment.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def peer_review_count(self): + """Integer representing the amount of reviews each user is assigned. NOTE: This key is NOT present unless you have automatic_peer_reviews set to true.""" + return self._peer_review_count + + @peer_review_count.setter + def peer_review_count(self, value): + """Setter for peer_review_count property.""" + self.logger.warn("Setting values on peer_review_count will NOT update the remote Canvas instance.") + self._peer_review_count = value + + @property + def grade_group_students_individually(self): + """If this is a group assignment, boolean flag indicating whether or not students will be graded individually.""" + return self._grade_group_students_individually + + @grade_group_students_individually.setter + def grade_group_students_individually(self, value): + """Setter for grade_group_students_individually property.""" + self.logger.warn("Setting values on grade_group_students_individually will NOT update the remote Canvas instance.") + self._grade_group_students_individually = value + + @property + def grading_standard_id(self): + """The id of the grading standard being applied to this assignment. Valid if grading_type is 'letter_grade' or 'gpa_scale'.""" + return self._grading_standard_id + + @grading_standard_id.setter + def grading_standard_id(self, value): + """Setter for grading_standard_id property.""" + self.logger.warn("Setting values on grading_standard_id will NOT update the remote Canvas instance.") + self._grading_standard_id = value + + @property + def external_tool_tag_attributes(self): + """(Optional) assignment's settings for external tools if submission_types include 'external_tool'. Only url and new_tab are included (new_tab defaults to false). Use the 'External Tools' API if you need more information about an external tool.""" + return self._external_tool_tag_attributes + + @external_tool_tag_attributes.setter + def external_tool_tag_attributes(self, value): + """Setter for external_tool_tag_attributes property.""" + self.logger.warn("Setting values on external_tool_tag_attributes will NOT update the remote Canvas instance.") + self._external_tool_tag_attributes = value + + @property + def html_url(self): + """the URL to the assignment's web page.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def turnitin_settings(self): + """Settings to pass along to turnitin to control what kinds of matches should be considered. originality_report_visibility can be 'immediate', 'after_grading', 'after_due_date', or 'never' exclude_small_matches_type can be null, 'percent', 'words' exclude_small_matches_value: - if type is null, this will be null also - if type is 'percent', this will be a number between 0 and 100 representing match size to exclude as a percentage of the document size. - if type is 'words', this will be number > 0 representing how many words a match must contain for it to be considered NOTE: This flag will not appear unless your account has the Turnitin plugin available.""" + return self._turnitin_settings + + @turnitin_settings.setter + def turnitin_settings(self, value): + """Setter for turnitin_settings property.""" + self.logger.warn("Setting values on turnitin_settings will NOT update the remote Canvas instance.") + self._turnitin_settings = value + + @property + def group_category_id(self): + """The ID of the assignment's group set, if this is a group assignment. For group discussions, set group_category_id on the discussion topic, not the linked assignment.""" + return self._group_category_id + + @group_category_id.setter + def group_category_id(self, value): + """Setter for group_category_id property.""" + self.logger.warn("Setting values on group_category_id will NOT update the remote Canvas instance.") + self._group_category_id = value + + @property + def lock_explanation(self): + """(Optional) An explanation of why this is locked for the user. Present when locked_for_user is true.""" + return self._lock_explanation + + @lock_explanation.setter + def lock_explanation(self, value): + """Setter for lock_explanation property.""" + self.logger.warn("Setting values on lock_explanation will NOT update the remote Canvas instance.") + self._lock_explanation = value + + @property + def needs_grading_count(self): + """if the requesting user has grading rights, the number of submissions that need grading.""" + return self._needs_grading_count + + @needs_grading_count.setter + def needs_grading_count(self, value): + """Setter for needs_grading_count property.""" + self.logger.warn("Setting values on needs_grading_count will NOT update the remote Canvas instance.") + self._needs_grading_count = value + + @property + def vericite_enabled(self): + """Boolean flag indicating whether or not VeriCite has been enabled for the assignment. NOTE: This flag will not appear unless your account has the VeriCite plugin available.""" + return self._vericite_enabled + + @vericite_enabled.setter + def vericite_enabled(self, value): + """Setter for vericite_enabled property.""" + self.logger.warn("Setting values on vericite_enabled will NOT update the remote Canvas instance.") + self._vericite_enabled = value + + @property + def peer_reviews_assign_at(self): + """String representing a date the reviews are due by. Must be a date that occurs after the default due date. If blank, or date is not after the assignment's due date, the assignment's due date will be used. NOTE: This key is NOT present unless you have automatic_peer_reviews set to true.""" + return self._peer_reviews_assign_at + + @peer_reviews_assign_at.setter + def peer_reviews_assign_at(self, value): + """Setter for peer_reviews_assign_at property.""" + self.logger.warn("Setting values on peer_reviews_assign_at will NOT update the remote Canvas instance.") + self._peer_reviews_assign_at = value + + @property + def name(self): + """the name of the assignment.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def integration_id(self): + """(optional, Third Party unique identifier for Assignment).""" + return self._integration_id + + @integration_id.setter + def integration_id(self, value): + """Setter for integration_id property.""" + self.logger.warn("Setting values on integration_id will NOT update the remote Canvas instance.") + self._integration_id = value + + @property + def frozen(self): + """(Optional) Boolean indicating if assignment is frozen for the calling user. NOTE: This field will only be present if the AssignmentFreezer plugin is available for your account.""" + return self._frozen + + @frozen.setter + def frozen(self, value): + """Setter for frozen property.""" + self.logger.warn("Setting values on frozen will NOT update the remote Canvas instance.") + self._frozen = value + + @property + def only_visible_to_overrides(self): + """Whether the assignment is only visible to overrides.""" + return self._only_visible_to_overrides + + @only_visible_to_overrides.setter + def only_visible_to_overrides(self, value): + """Setter for only_visible_to_overrides property.""" + self.logger.warn("Setting values on only_visible_to_overrides will NOT update the remote Canvas instance.") + self._only_visible_to_overrides = value + + @property + def unlock_at(self): + """the unlock date (assignment is unlocked after this date) returns null if not present NOTE: If this assignment has assignment overrides, this field will be the unlock date as it applies to the user requesting information from the API.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def submission(self): + """(Optional) If 'submission' is included in the 'include' parameter, includes a Submission object that represents the current user's (user who is requesting information from the api) current submission for the assignment. See the Submissions API for an example response. If the user does not have a submission, this key will be absent.""" + return self._submission + + @submission.setter + def submission(self, value): + """Setter for submission property.""" + self.logger.warn("Setting values on submission will NOT update the remote Canvas instance.") + self._submission = value + + @property + def due_at(self): + """the due date for the assignment. returns null if not present. NOTE: If this assignment has assignment overrides, this field will be the due date as it applies to the user requesting information from the API.""" + return self._due_at + + @due_at.setter + def due_at(self, value): + """Setter for due_at property.""" + self.logger.warn("Setting values on due_at will NOT update the remote Canvas instance.") + self._due_at = value + + @property + def created_at(self): + """The time at which this assignment was originally created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def post_to_sis(self): + """(optional, present if Post Grades to SIS feature is enabled).""" + return self._post_to_sis + + @post_to_sis.setter + def post_to_sis(self, value): + """Setter for post_to_sis property.""" + self.logger.warn("Setting values on post_to_sis will NOT update the remote Canvas instance.") + self._post_to_sis = value + + @property + def lock_at(self): + """the lock date (assignment is locked after this date). returns null if not present. NOTE: If this assignment has assignment overrides, this field will be the lock date as it applies to the user requesting information from the API.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def assignment_group_id(self): + """the ID of the assignment's group.""" + return self._assignment_group_id + + @assignment_group_id.setter + def assignment_group_id(self, value): + """Setter for assignment_group_id property.""" + self.logger.warn("Setting values on assignment_group_id will NOT update the remote Canvas instance.") + self._assignment_group_id = value + + @property + def allowed_extensions(self): + """Allowed file extensions, which take effect if submission_types includes 'online_upload'.""" + return self._allowed_extensions + + @allowed_extensions.setter + def allowed_extensions(self, value): + """Setter for allowed_extensions property.""" + self.logger.warn("Setting values on allowed_extensions will NOT update the remote Canvas instance.") + self._allowed_extensions = value + + @property + def automatic_peer_reviews(self): + """Boolean indicating peer reviews are assigned automatically. If false, the teacher is expected to manually assign peer reviews.""" + return self._automatic_peer_reviews + + @automatic_peer_reviews.setter + def automatic_peer_reviews(self, value): + """Setter for automatic_peer_reviews property.""" + self.logger.warn("Setting values on automatic_peer_reviews will NOT update the remote Canvas instance.") + self._automatic_peer_reviews = value + + @property + def published(self): + """Whether the assignment is published.""" + return self._published + + @published.setter + def published(self, value): + """Setter for published property.""" + self.logger.warn("Setting values on published will NOT update the remote Canvas instance.") + self._published = value + + @property + def position(self): + """the sorting order of the assignment in the group.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def submission_types(self): + """the types of submissions allowed for this assignment list containing one or more of the following: 'discussion_topic', 'online_quiz', 'on_paper', 'none', 'external_tool', 'online_text_entry', 'online_url', 'online_upload' 'media_recording'.""" + return self._submission_types + + @submission_types.setter + def submission_types(self, value): + """Setter for submission_types property.""" + self.logger.warn("Setting values on submission_types will NOT update the remote Canvas instance.") + self._submission_types = value + + @property + def submissions_download_url(self): + """the URL to download all submissions as a zip.""" + return self._submissions_download_url + + @submissions_download_url.setter + def submissions_download_url(self, value): + """Setter for submissions_download_url property.""" + self.logger.warn("Setting values on submissions_download_url will NOT update the remote Canvas instance.") + self._submissions_download_url = value + + @property + def overrides(self): + """(Optional) If 'overrides' is included in the 'include' parameter, includes an array of assignment override objects.""" + return self._overrides + + @overrides.setter + def overrides(self, value): + """Setter for overrides property.""" + self.logger.warn("Setting values on overrides will NOT update the remote Canvas instance.") + self._overrides = value + + @property + def unpublishable(self): + """Whether the assignment's 'published' state can be changed to false. Will be false if there are student submissions for the assignment.""" + return self._unpublishable + + @unpublishable.setter + def unpublishable(self, value): + """Setter for unpublishable property.""" + self.logger.warn("Setting values on unpublishable will NOT update the remote Canvas instance.") + self._unpublishable = value + + +class Needsgradingcount(BaseModel): + """Needsgradingcount Model. + Used by Assignment model""" + + def __init__(self, needs_grading_count=None, section_id=None): + """Init method for Needsgradingcount class.""" + self._needs_grading_count = needs_grading_count + self._section_id = section_id + + self.logger = logging.getLogger('pycanvas.Needsgradingcount') + + @property + def needs_grading_count(self): + """Number of submissions that need grading.""" + return self._needs_grading_count + + @needs_grading_count.setter + def needs_grading_count(self, value): + """Setter for needs_grading_count property.""" + self.logger.warn("Setting values on needs_grading_count will NOT update the remote Canvas instance.") + self._needs_grading_count = value + + @property + def section_id(self): + """The section ID.""" + return self._section_id + + @section_id.setter + def section_id(self, value): + """Setter for section_id property.""" + self.logger.warn("Setting values on section_id will NOT update the remote Canvas instance.") + self._section_id = value + + +class Rubriccriteria(BaseModel): + """Rubriccriteria Model.""" + + def __init__(self, vendor_guid=None, description=None, ratings=None, id=None, points=None, outcome_id=None, long_description=None): + """Init method for Rubriccriteria class.""" + self._vendor_guid = vendor_guid + self._description = description + self._ratings = ratings + self._id = id + self._points = points + self._outcome_id = outcome_id + self._long_description = long_description + + self.logger = logging.getLogger('pycanvas.Rubriccriteria') + + @property + def vendor_guid(self): + """(Optional) The 3rd party vendor's GUID for the outcome this criteria references, if any.""" + return self._vendor_guid + + @vendor_guid.setter + def vendor_guid(self, value): + """Setter for vendor_guid property.""" + self.logger.warn("Setting values on vendor_guid will NOT update the remote Canvas instance.") + self._vendor_guid = value + + @property + def description(self): + """description.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def ratings(self): + """ratings.""" + return self._ratings + + @ratings.setter + def ratings(self, value): + """Setter for ratings property.""" + self.logger.warn("Setting values on ratings will NOT update the remote Canvas instance.") + self._ratings = value + + @property + def id(self): + """The id of rubric criteria.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def points(self): + """points.""" + return self._points + + @points.setter + def points(self, value): + """Setter for points property.""" + self.logger.warn("Setting values on points will NOT update the remote Canvas instance.") + self._points = value + + @property + def outcome_id(self): + """(Optional) The id of the learning outcome this criteria uses, if any.""" + return self._outcome_id + + @outcome_id.setter + def outcome_id(self, value): + """Setter for outcome_id property.""" + self.logger.warn("Setting values on outcome_id will NOT update the remote Canvas instance.") + self._outcome_id = value + + @property + def long_description(self): + """long_description.""" + return self._long_description + + @long_description.setter + def long_description(self, value): + """Setter for long_description property.""" + self.logger.warn("Setting values on long_description will NOT update the remote Canvas instance.") + self._long_description = value + + +class Assignmentdate(BaseModel): + """Assignmentdate Model. + Object representing a due date for an assignment or quiz. If the due date came from an assignment override, it will have an 'id' field.""" + + def __init__(self, unlock_at=None, title=None, due_at=None, lock_at=None, base=None, id=None): + """Init method for Assignmentdate class.""" + self._unlock_at = unlock_at + self._title = title + self._due_at = due_at + self._lock_at = lock_at + self._base = base + self._id = id + + self.logger = logging.getLogger('pycanvas.Assignmentdate') + + @property + def unlock_at(self): + """unlock_at.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def title(self): + """title.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def due_at(self): + """due_at.""" + return self._due_at + + @due_at.setter + def due_at(self, value): + """Setter for due_at property.""" + self.logger.warn("Setting values on due_at will NOT update the remote Canvas instance.") + self._due_at = value + + @property + def lock_at(self): + """lock_at.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def base(self): + """(Optional, present if 'id' is missing) whether this date represents the assignment's or quiz's default due date.""" + return self._base + + @base.setter + def base(self, value): + """Setter for base property.""" + self.logger.warn("Setting values on base will NOT update the remote Canvas instance.") + self._base = value + + @property + def id(self): + """(Optional, missing if 'base' is present) id of the assignment override this date represents.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Rubricrating(BaseModel): + """Rubricrating Model.""" + + def __init__(self, points=None, id=None, description=None): + """Init method for Rubricrating class.""" + self._points = points + self._id = id + self._description = description + + self.logger = logging.getLogger('pycanvas.Rubricrating') + + @property + def points(self): + """points.""" + return self._points + + @points.setter + def points(self, value): + """Setter for points property.""" + self.logger.warn("Setting values on points will NOT update the remote Canvas instance.") + self._points = value + + @property + def id(self): + """id.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def description(self): + """description.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + +class Lockinfo(BaseModel): + """Lockinfo Model.""" + + def __init__(self, lock_at=None, context_module=None, asset_string=None, unlock_at=None, manually_locked=None): + """Init method for Lockinfo class.""" + self._lock_at = lock_at + self._context_module = context_module + self._asset_string = asset_string + self._unlock_at = unlock_at + self._manually_locked = manually_locked + + self.logger = logging.getLogger('pycanvas.Lockinfo') + + @property + def lock_at(self): + """(Optional) Time at which this was/will be locked.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def context_module(self): + """(Optional) Context module causing the lock.""" + return self._context_module + + @context_module.setter + def context_module(self, value): + """Setter for context_module property.""" + self.logger.warn("Setting values on context_module will NOT update the remote Canvas instance.") + self._context_module = value + + @property + def asset_string(self): + """Asset string for the object causing the lock.""" + return self._asset_string + + @asset_string.setter + def asset_string(self, value): + """Setter for asset_string property.""" + self.logger.warn("Setting values on asset_string will NOT update the remote Canvas instance.") + self._asset_string = value + + @property + def unlock_at(self): + """(Optional) Time at which this was/will be unlocked.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def manually_locked(self): + """manually_locked.""" + return self._manually_locked + + @manually_locked.setter + def manually_locked(self, value): + """Setter for manually_locked property.""" + self.logger.warn("Setting values on manually_locked will NOT update the remote Canvas instance.") + self._manually_locked = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/authentications_log.py b/venv/Lib/site-packages/pycanvas/apis/authentications_log.py new file mode 100644 index 00000000..fbd496c1 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/authentications_log.py @@ -0,0 +1,168 @@ +"""AuthenticationsLog API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class AuthenticationsLogAPI(BaseCanvasAPI): + """AuthenticationsLog API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for AuthenticationsLogAPI.""" + super(AuthenticationsLogAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.AuthenticationsLogAPI") + + def query_by_login(self, login_id, end_time=None, start_time=None): + """ + Query by login. + + List authentication events for a given login. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - login_id + """ID""" + path["login_id"] = login_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want events.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want events.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/audit/authentication/logins/{login_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/audit/authentication/logins/{login_id}".format(**path), data=data, params=params, no_data=True) + + def query_by_account(self, account_id, end_time=None, start_time=None): + """ + Query by account. + + List authentication events for a given account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want events.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want events.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/audit/authentication/accounts/{account_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/audit/authentication/accounts/{account_id}".format(**path), data=data, params=params, no_data=True) + + def query_by_user(self, user_id, end_time=None, start_time=None): + """ + Query by user. + + List authentication events for a given user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want events.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want events.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/audit/authentication/users/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/audit/authentication/users/{user_id}".format(**path), data=data, params=params, no_data=True) + + +class Authenticationevent(BaseModel): + """Authenticationevent Model.""" + + def __init__(self, pseudonym_id=None, created_at=None, user_id=None, event_type=None, account_id=None): + """Init method for Authenticationevent class.""" + self._pseudonym_id = pseudonym_id + self._created_at = created_at + self._user_id = user_id + self._event_type = event_type + self._account_id = account_id + + self.logger = logging.getLogger('pycanvas.Authenticationevent') + + @property + def pseudonym_id(self): + """ID of the pseudonym (login) associated with the event.""" + return self._pseudonym_id + + @pseudonym_id.setter + def pseudonym_id(self, value): + """Setter for pseudonym_id property.""" + self.logger.warn("Setting values on pseudonym_id will NOT update the remote Canvas instance.") + self._pseudonym_id = value + + @property + def created_at(self): + """timestamp of the event.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def user_id(self): + """ID of the user associated with the event will match the user_id in the associated pseudonym.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def event_type(self): + """authentication event type ('login' or 'logout').""" + return self._event_type + + @event_type.setter + def event_type(self, value): + """Setter for event_type property.""" + self.logger.warn("Setting values on event_type will NOT update the remote Canvas instance.") + self._event_type = value + + @property + def account_id(self): + """ID of the account associated with the event. will match the account_id in the associated pseudonym.""" + return self._account_id + + @account_id.setter + def account_id(self, value): + """Setter for account_id property.""" + self.logger.warn("Setting values on account_id will NOT update the remote Canvas instance.") + self._account_id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/base.py b/venv/Lib/site-packages/pycanvas/apis/base.py new file mode 100644 index 00000000..de7e5cab --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/base.py @@ -0,0 +1,187 @@ +import requests +import re +import urllib +import logging + +logger = logging.getLogger('pycanvas.BaseCanvasAPI') + + +class BaseCanvasAPI(object): + def __init__(self, instance_address, access_token, **kwargs): + self.instance_address = instance_address + self.access_token = access_token + logger.debug('Created new CanvasAPI client for instance: {}.'.format('self.instance_address')) + + self.session = requests.Session() + self.session.headers.update({'Authorization': 'Bearer {}'.format(self.access_token)}) + logger.debug('Using Authorization Token authentication method. Added token to headers: {}'.format('Authorization: Bearer {}'.format(self.access_token))) + + self.rel_matcher = re.compile(r' ?rel="([a-z]+)"') + + def uri_for(self, a): + return self.instance_address + a + + def extract_data_from_response(self, response, data_key=None): + """Given a response and an optional data_key should return a dictionary of data returned as part of the response.""" + response_json_data = response.json() + # Seems to be two types of response, a dict with keys and then lists of data or a flat list data with no key. + if type(response_json_data) == list: + # Return the data + return response_json_data + elif type(response_json_data) == dict: + if data_key is None: + return response_json_data + else: + return response_json_data[data_key] + else: + raise CanvasAPIError(response) + + def extract_pagination_links(self, response): + '''Given a wrapped_response from a Canvas API endpoint, + extract the pagination links from the response headers''' + try: + link_header = response.headers['Link'] + except KeyError: + logger.warn('Unable to find the Link header. Unable to continue with pagination.') + return None + + split_header = link_header.split(',') + exploded_split_header = [i.split(';') for i in split_header] + + pagination_links = {} + for h in exploded_split_header: + link = h[0] + rel = h[1] + # Check that the link format is what we expect + if link.startswith('<') and link.endswith('>'): + link = link[1:-1] + else: + continue + # Extract the rel argument + m = self.rel_matcher.match(rel) + try: + rel = m.groups()[0] + except AttributeError: + # Match returned None, just skip. + continue + except IndexError: + # Matched but no groups returned + continue + + pagination_links[rel] = link + return pagination_links + + def has_pagination_links(self, response): + return 'Link' in response.headers + + def depaginate(self, response, data_key=None): + logging.debug('Attempting to depaginate response from {}'.format(response.url)) + all_data = [] + this_data = self.extract_data_from_response(response, data_key=data_key) + if this_data is not None: + if type(this_data) == list: + all_data += this_data + else: + all_data.append(this_data) + + if self.has_pagination_links(response): + pagination_links = self.extract_pagination_links(response) + while 'next' in pagination_links: + response = self.session.get(pagination_links['next']) + pagination_links = self.extract_pagination_links(response) + this_data = self.extract_data_from_response(response, data_key=data_key) + if this_data is not None: + if type(this_data) == list: + all_data += this_data + else: + all_data.append(this_data) + else: + logging.warn('Response from {} has no pagination links.'.format(response.url)) + return all_data + + def generic_request(self, method, uri, + all_pages=False, + data_key=None, + no_data=False, + do_not_process=False, + force_urlencode_data=False, + data=None, + params=None, + files=None, + single_item=False): + """Generic Canvas Request Method.""" + if not uri.startswith('http'): + uri = self.uri_for(uri) + + if force_urlencode_data is True: + uri += '?' + urllib.urlencode(data) + + assert method in ['GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS'] + + if method == 'GET': + response = self.session.get(uri, params=params) + elif method == 'POST': + response = self.session.post(uri, data=data, files=files) + elif method == 'PUT': + response = self.session.put(uri, data=data) + elif method == 'DELETE': + response = self.session.delete(uri, params=params) + elif method == 'HEAD': + response = self.session.head(uri, params=params) + elif method == 'OPTIONS': + response = self.session.options(uri, params=params) + + response.raise_for_status() + + if do_not_process is True: + return response + + if no_data: + return response.status_code + + if all_pages: + return self.depaginate(response, data_key) + + if single_item: + r = response.json() + if data_key: + return r[data_key] + else: + return r + + return response.json() + + def _validate_enum(self, value, acceptable_values): + if not hasattr(value, '__iter__'): + if value not in acceptable_values: + raise ValueError('{} not in {}'.format(value, str(acceptable_values))) + else: + for v in value: + if v not in acceptable_values: + raise ValueError('{} not in {}'.format(value, str(acceptable_values))) + return value + + def _validate_iso8601_string(self, value): + """Return the value or raise a ValueError if it is not a string in ISO8601 format.""" + ISO8601_REGEX = r'(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})([+-](\d{2})\:(\d{2})|Z)' + if re.match(ISO8601_REGEX, value): + return value + else: + raise ValueError('{} must be in ISO8601 format.'.format(value)) + + +class CanvasAPIError(Exception): + def __init__(self, response): + self.response = response + + def __unicode__(self): + return u'API Request Failed. Status: {} Content: {}'.format(self.response.status_code, self.response.content) + + def __str__(self): + return 'API Request Failed. Status: {} Content: {}'.format(self.response.status_code, self.response.content) + + +class BaseModel(object): + pass + +HTTPError = requests.HTTPError diff --git a/venv/Lib/site-packages/pycanvas/apis/calendar_events.py b/venv/Lib/site-packages/pycanvas/apis/calendar_events.py new file mode 100644 index 00000000..2ea5011c --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/calendar_events.py @@ -0,0 +1,1097 @@ +"""CalendarEvents API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class CalendarEventsAPI(BaseCanvasAPI): + """CalendarEvents API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for CalendarEventsAPI.""" + super(CalendarEventsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.CalendarEventsAPI") + + def list_calendar_events(self, all_events=None, context_codes=None, end_date=None, excludes=None, start_date=None, type=None, undated=None): + """ + List calendar events. + + Retrieve the list of calendar events or assignments for the current user + """ + path = {} + data = {} + params = {} + + # OPTIONAL - type + """Defaults to "event"""" + if type is not None: + self._validate_enum(type, ["event", "assignment"]) + params["type"] = type + + # OPTIONAL - start_date + """Only return events since the start_date (inclusive). + Defaults to today. The value should be formatted as: yyyy-mm-dd or ISO 8601 YYYY-MM-DDTHH:MM:SSZ.""" + if start_date is not None: + params["start_date"] = start_date + + # OPTIONAL - end_date + """Only return events before the end_date (inclusive). + Defaults to start_date. The value should be formatted as: yyyy-mm-dd or ISO 8601 YYYY-MM-DDTHH:MM:SSZ. + If end_date is the same as start_date, then only events on that day are + returned.""" + if end_date is not None: + params["end_date"] = end_date + + # OPTIONAL - undated + """Defaults to false (dated events only). + If true, only return undated events and ignore start_date and end_date.""" + if undated is not None: + params["undated"] = undated + + # OPTIONAL - all_events + """Defaults to false (uses start_date, end_date, and undated criteria). + If true, all events are returned, ignoring start_date, end_date, and undated criteria.""" + if all_events is not None: + params["all_events"] = all_events + + # OPTIONAL - context_codes + """List of context codes of courses/groups/users whose events you want to see. + If not specified, defaults to the current user (i.e personal calendar, + no course/group events). Limited to 10 context codes, additional ones are + ignored. The format of this field is the context type, followed by an + underscore, followed by the context id. For example: course_42""" + if context_codes is not None: + params["context_codes"] = context_codes + + # OPTIONAL - excludes + """Array of attributes to exclude. Possible values are "description", "child_events" and "assignment"""" + if excludes is not None: + params["excludes"] = excludes + + self.logger.debug("GET /api/v1/calendar_events with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/calendar_events".format(**path), data=data, params=params, all_pages=True) + + def list_calendar_events_for_user(self, user_id, all_events=None, context_codes=None, end_date=None, excludes=None, start_date=None, type=None, undated=None): + """ + List calendar events for a user. + + Retrieve the list of calendar events or assignments for the specified user. + To view calendar events for a user other than yourself, + you must either be an observer of that user or an administrator. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - type + """Defaults to "event"""" + if type is not None: + self._validate_enum(type, ["event", "assignment"]) + params["type"] = type + + # OPTIONAL - start_date + """Only return events since the start_date (inclusive). + Defaults to today. The value should be formatted as: yyyy-mm-dd or ISO 8601 YYYY-MM-DDTHH:MM:SSZ.""" + if start_date is not None: + params["start_date"] = start_date + + # OPTIONAL - end_date + """Only return events before the end_date (inclusive). + Defaults to start_date. The value should be formatted as: yyyy-mm-dd or ISO 8601 YYYY-MM-DDTHH:MM:SSZ. + If end_date is the same as start_date, then only events on that day are + returned.""" + if end_date is not None: + params["end_date"] = end_date + + # OPTIONAL - undated + """Defaults to false (dated events only). + If true, only return undated events and ignore start_date and end_date.""" + if undated is not None: + params["undated"] = undated + + # OPTIONAL - all_events + """Defaults to false (uses start_date, end_date, and undated criteria). + If true, all events are returned, ignoring start_date, end_date, and undated criteria.""" + if all_events is not None: + params["all_events"] = all_events + + # OPTIONAL - context_codes + """List of context codes of courses/groups/users whose events you want to see. + If not specified, defaults to the current user (i.e personal calendar, + no course/group events). Limited to 10 context codes, additional ones are + ignored. The format of this field is the context type, followed by an + underscore, followed by the context id. For example: course_42""" + if context_codes is not None: + params["context_codes"] = context_codes + + # OPTIONAL - excludes + """Array of attributes to exclude. Possible values are "description", "child_events" and "assignment"""" + if excludes is not None: + params["excludes"] = excludes + + self.logger.debug("GET /api/v1/users/{user_id}/calendar_events with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/calendar_events".format(**path), data=data, params=params, all_pages=True) + + def create_calendar_event(self, calendar_event_context_code, calendar_event_child_event_data_X_context_code=None, calendar_event_child_event_data_X_end_at=None, calendar_event_child_event_data_X_start_at=None, calendar_event_description=None, calendar_event_duplicate_append_iterator=None, calendar_event_duplicate_count=None, calendar_event_duplicate_frequency=None, calendar_event_duplicate_interval=None, calendar_event_end_at=None, calendar_event_location_address=None, calendar_event_location_name=None, calendar_event_start_at=None, calendar_event_time_zone_edited=None, calendar_event_title=None): + """ + Create a calendar event. + + Create and return a new calendar event + """ + path = {} + data = {} + params = {} + + # REQUIRED - calendar_event[context_code] + """Context code of the course/group/user whose calendar this event should be + added to.""" + data["calendar_event[context_code]"] = calendar_event_context_code + + # OPTIONAL - calendar_event[title] + """Short title for the calendar event.""" + if calendar_event_title is not None: + data["calendar_event[title]"] = calendar_event_title + + # OPTIONAL - calendar_event[description] + """Longer HTML description of the event.""" + if calendar_event_description is not None: + data["calendar_event[description]"] = calendar_event_description + + # OPTIONAL - calendar_event[start_at] + """Start date/time of the event.""" + if calendar_event_start_at is not None: + data["calendar_event[start_at]"] = calendar_event_start_at + + # OPTIONAL - calendar_event[end_at] + """End date/time of the event.""" + if calendar_event_end_at is not None: + data["calendar_event[end_at]"] = calendar_event_end_at + + # OPTIONAL - calendar_event[location_name] + """Location name of the event.""" + if calendar_event_location_name is not None: + data["calendar_event[location_name]"] = calendar_event_location_name + + # OPTIONAL - calendar_event[location_address] + """Location address""" + if calendar_event_location_address is not None: + data["calendar_event[location_address]"] = calendar_event_location_address + + # OPTIONAL - calendar_event[time_zone_edited] + """Time zone of the user editing the event. Allowed time zones are + {http://www.iana.org/time-zones IANA time zones} or friendlier + {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + if calendar_event_time_zone_edited is not None: + data["calendar_event[time_zone_edited]"] = calendar_event_time_zone_edited + + # OPTIONAL - calendar_event[child_event_data][X][start_at] + """Section-level start time(s) if this is a course event. X can be any + identifier, provided that it is consistent across the start_at, end_at + and context_code""" + if calendar_event_child_event_data_X_start_at is not None: + data["calendar_event[child_event_data][X][start_at]"] = calendar_event_child_event_data_X_start_at + + # OPTIONAL - calendar_event[child_event_data][X][end_at] + """Section-level end time(s) if this is a course event.""" + if calendar_event_child_event_data_X_end_at is not None: + data["calendar_event[child_event_data][X][end_at]"] = calendar_event_child_event_data_X_end_at + + # OPTIONAL - calendar_event[child_event_data][X][context_code] + """Context code(s) corresponding to the section-level start and end time(s).""" + if calendar_event_child_event_data_X_context_code is not None: + data["calendar_event[child_event_data][X][context_code]"] = calendar_event_child_event_data_X_context_code + + # OPTIONAL - calendar_event[duplicate][count] + """Number of times to copy/duplicate the event.""" + if calendar_event_duplicate_count is not None: + data["calendar_event[duplicate][count]"] = calendar_event_duplicate_count + + # OPTIONAL - calendar_event[duplicate][interval] + """Defaults to 1 if duplicate `count` is set. The interval between the duplicated events.""" + if calendar_event_duplicate_interval is not None: + data["calendar_event[duplicate][interval]"] = calendar_event_duplicate_interval + + # OPTIONAL - calendar_event[duplicate][frequency] + """Defaults to "weekly". The frequency at which to duplicate the event""" + if calendar_event_duplicate_frequency is not None: + self._validate_enum(calendar_event_duplicate_frequency, ["daily", "weekly", "monthly"]) + data["calendar_event[duplicate][frequency]"] = calendar_event_duplicate_frequency + + # OPTIONAL - calendar_event[duplicate][append_iterator] + """Defaults to false. If set to `true`, an increasing counter number will be appended to the event title + when the event is duplicated. (e.g. Event 1, Event 2, Event 3, etc)""" + if calendar_event_duplicate_append_iterator is not None: + data["calendar_event[duplicate][append_iterator]"] = calendar_event_duplicate_append_iterator + + self.logger.debug("POST /api/v1/calendar_events with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/calendar_events".format(**path), data=data, params=params, no_data=True) + + def get_single_calendar_event_or_assignment(self, id): + """ + Get a single calendar event or assignment. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/calendar_events/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/calendar_events/{id}".format(**path), data=data, params=params, single_item=True) + + def reserve_time_slot(self, id, cancel_existing=None, comments=None, participant_id=None): + """ + Reserve a time slot. + + Reserves a particular time slot and return the new reservation + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - participant_id + """User or group id for whom you are making the reservation (depends on the + participant type). Defaults to the current user (or user's candidate group).""" + if participant_id is not None: + data["participant_id"] = participant_id + + # OPTIONAL - comments + """Comments to associate with this reservation""" + if comments is not None: + data["comments"] = comments + + # OPTIONAL - cancel_existing + """Defaults to false. If true, cancel any previous reservation(s) for this + participant and appointment group.""" + if cancel_existing is not None: + data["cancel_existing"] = cancel_existing + + self.logger.debug("POST /api/v1/calendar_events/{id}/reservations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/calendar_events/{id}/reservations".format(**path), data=data, params=params, no_data=True) + + def reserve_time_slot_participant_id(self, id, participant_id, cancel_existing=None, comments=None): + """ + Reserve a time slot. + + Reserves a particular time slot and return the new reservation + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - participant_id + """User or group id for whom you are making the reservation (depends on the + participant type). Defaults to the current user (or user's candidate group).""" + path["participant_id"] = participant_id + + # OPTIONAL - comments + """Comments to associate with this reservation""" + if comments is not None: + data["comments"] = comments + + # OPTIONAL - cancel_existing + """Defaults to false. If true, cancel any previous reservation(s) for this + participant and appointment group.""" + if cancel_existing is not None: + data["cancel_existing"] = cancel_existing + + self.logger.debug("POST /api/v1/calendar_events/{id}/reservations/{participant_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/calendar_events/{id}/reservations/{participant_id}".format(**path), data=data, params=params, no_data=True) + + def update_calendar_event(self, id, calendar_event_child_event_data_X_context_code=None, calendar_event_child_event_data_X_end_at=None, calendar_event_child_event_data_X_start_at=None, calendar_event_context_code=None, calendar_event_description=None, calendar_event_end_at=None, calendar_event_location_address=None, calendar_event_location_name=None, calendar_event_start_at=None, calendar_event_time_zone_edited=None, calendar_event_title=None): + """ + Update a calendar event. + + Update and return a calendar event + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - calendar_event[context_code] + """Context code of the course/group/user to move this event to. + Scheduler appointments and events with section-specific times cannot be moved between calendars.""" + if calendar_event_context_code is not None: + data["calendar_event[context_code]"] = calendar_event_context_code + + # OPTIONAL - calendar_event[title] + """Short title for the calendar event.""" + if calendar_event_title is not None: + data["calendar_event[title]"] = calendar_event_title + + # OPTIONAL - calendar_event[description] + """Longer HTML description of the event.""" + if calendar_event_description is not None: + data["calendar_event[description]"] = calendar_event_description + + # OPTIONAL - calendar_event[start_at] + """Start date/time of the event.""" + if calendar_event_start_at is not None: + data["calendar_event[start_at]"] = calendar_event_start_at + + # OPTIONAL - calendar_event[end_at] + """End date/time of the event.""" + if calendar_event_end_at is not None: + data["calendar_event[end_at]"] = calendar_event_end_at + + # OPTIONAL - calendar_event[location_name] + """Location name of the event.""" + if calendar_event_location_name is not None: + data["calendar_event[location_name]"] = calendar_event_location_name + + # OPTIONAL - calendar_event[location_address] + """Location address""" + if calendar_event_location_address is not None: + data["calendar_event[location_address]"] = calendar_event_location_address + + # OPTIONAL - calendar_event[time_zone_edited] + """Time zone of the user editing the event. Allowed time zones are + {http://www.iana.org/time-zones IANA time zones} or friendlier + {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + if calendar_event_time_zone_edited is not None: + data["calendar_event[time_zone_edited]"] = calendar_event_time_zone_edited + + # OPTIONAL - calendar_event[child_event_data][X][start_at] + """Section-level start time(s) if this is a course event. X can be any + identifier, provided that it is consistent across the start_at, end_at + and context_code""" + if calendar_event_child_event_data_X_start_at is not None: + data["calendar_event[child_event_data][X][start_at]"] = calendar_event_child_event_data_X_start_at + + # OPTIONAL - calendar_event[child_event_data][X][end_at] + """Section-level end time(s) if this is a course event.""" + if calendar_event_child_event_data_X_end_at is not None: + data["calendar_event[child_event_data][X][end_at]"] = calendar_event_child_event_data_X_end_at + + # OPTIONAL - calendar_event[child_event_data][X][context_code] + """Context code(s) corresponding to the section-level start and end time(s).""" + if calendar_event_child_event_data_X_context_code is not None: + data["calendar_event[child_event_data][X][context_code]"] = calendar_event_child_event_data_X_context_code + + self.logger.debug("PUT /api/v1/calendar_events/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/calendar_events/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_calendar_event(self, id, cancel_reason=None): + """ + Delete a calendar event. + + Delete an event from the calendar and return the deleted event + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - cancel_reason + """Reason for deleting/canceling the event.""" + if cancel_reason is not None: + params["cancel_reason"] = cancel_reason + + self.logger.debug("DELETE /api/v1/calendar_events/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/calendar_events/{id}".format(**path), data=data, params=params, no_data=True) + + def set_course_timetable(self, course_id, timetables_course_section_id=None, timetables_course_section_id_end_time=None, timetables_course_section_id_location_name=None, timetables_course_section_id_start_time=None, timetables_course_section_id_weekdays=None): + """ + Set a course timetable. + + Creates and updates "timetable" events for a course. + Can automaticaly generate a series of calendar events based on simple schedules + (e.g. "Monday and Wednesday at 2:00pm" ) + + Existing timetable events for the course and course sections + will be updated if they still are part of the timetable. + Otherwise, they will be deleted. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - timetables[course_section_id] + """An array of timetable objects for the course section specified by course_section_id. + If course_section_id is set to "all", events will be created for the entire course.""" + if timetables_course_section_id is not None: + data["timetables[course_section_id]"] = timetables_course_section_id + + # OPTIONAL - timetables[course_section_id][weekdays] + """A comma-separated list of abbreviated weekdays + (Mon-Monday, Tue-Tuesday, Wed-Wednesday, Thu-Thursday, Fri-Friday, Sat-Saturday, Sun-Sunday)""" + if timetables_course_section_id_weekdays is not None: + data["timetables[course_section_id][weekdays]"] = timetables_course_section_id_weekdays + + # OPTIONAL - timetables[course_section_id][start_time] + """Time to start each event at (e.g. "9:00 am")""" + if timetables_course_section_id_start_time is not None: + data["timetables[course_section_id][start_time]"] = timetables_course_section_id_start_time + + # OPTIONAL - timetables[course_section_id][end_time] + """Time to end each event at (e.g. "9:00 am")""" + if timetables_course_section_id_end_time is not None: + data["timetables[course_section_id][end_time]"] = timetables_course_section_id_end_time + + # OPTIONAL - timetables[course_section_id][location_name] + """A location name to set for each event""" + if timetables_course_section_id_location_name is not None: + data["timetables[course_section_id][location_name]"] = timetables_course_section_id_location_name + + self.logger.debug("POST /api/v1/courses/{course_id}/calendar_events/timetable with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/calendar_events/timetable".format(**path), data=data, params=params, no_data=True) + + def get_course_timetable(self, course_id): + """ + Get course timetable. + + Returns the last timetable set by the + {api:CalendarEventsApiController#set_course_timetable Set a course timetable} endpoint + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/calendar_events/timetable with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/calendar_events/timetable".format(**path), data=data, params=params, no_data=True) + + def create_or_update_events_directly_for_course_timetable(self, course_id, course_section_id=None, events=None, events_code=None, events_end_at=None, events_location_name=None, events_start_at=None): + """ + Create or update events directly for a course timetable. + + Creates and updates "timetable" events for a course or course section. + Similar to {api:CalendarEventsApiController#set_course_timetable setting a course timetable}, + but instead of generating a list of events based on a timetable schedule, + this endpoint expects a complete list of events. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - course_section_id + """Events will be created for the course section specified by course_section_id. + If not present, events will be created for the entire course.""" + if course_section_id is not None: + data["course_section_id"] = course_section_id + + # OPTIONAL - events + """An array of event objects to use.""" + if events is not None: + data["events"] = events + + # OPTIONAL - events[start_at] + """Start time for the event""" + if events_start_at is not None: + data["events[start_at]"] = events_start_at + + # OPTIONAL - events[end_at] + """End time for the event""" + if events_end_at is not None: + data["events[end_at]"] = events_end_at + + # OPTIONAL - events[location_name] + """Location name for the event""" + if events_location_name is not None: + data["events[location_name]"] = events_location_name + + # OPTIONAL - events[code] + """A unique identifier that can be used to update the event at a later time + If one is not specified, an identifier will be generated based on the start and end times""" + if events_code is not None: + data["events[code]"] = events_code + + self.logger.debug("POST /api/v1/courses/{course_id}/calendar_events/timetable_events with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/calendar_events/timetable_events".format(**path), data=data, params=params, no_data=True) + + +class Calendarevent(BaseModel): + """Calendarevent Model.""" + + def __init__(self, reserved=None, updated_at=None, group=None, child_events_count=None, available_slots=None, id=None, reserve_url=None, location_name=None, title=None, end_at=None, appointment_group_id=None, context_code=None, hidden=None, start_at=None, description=None, child_events=None, workflow_state=None, effective_context_code=None, html_url=None, all_day_date=None, user=None, participants_per_appointment=None, parent_event_id=None, created_at=None, all_day=None, url=None, location_address=None, own_reservation=None, appointment_group_url=None, all_context_codes=None): + """Init method for Calendarevent class.""" + self._reserved = reserved + self._updated_at = updated_at + self._group = group + self._child_events_count = child_events_count + self._available_slots = available_slots + self._id = id + self._reserve_url = reserve_url + self._location_name = location_name + self._title = title + self._end_at = end_at + self._appointment_group_id = appointment_group_id + self._context_code = context_code + self._hidden = hidden + self._start_at = start_at + self._description = description + self._child_events = child_events + self._workflow_state = workflow_state + self._effective_context_code = effective_context_code + self._html_url = html_url + self._all_day_date = all_day_date + self._user = user + self._participants_per_appointment = participants_per_appointment + self._parent_event_id = parent_event_id + self._created_at = created_at + self._all_day = all_day + self._url = url + self._location_address = location_address + self._own_reservation = own_reservation + self._appointment_group_url = appointment_group_url + self._all_context_codes = all_context_codes + + self.logger = logging.getLogger('pycanvas.Calendarevent') + + @property + def reserved(self): + """If the event is a time slot, a boolean indicating whether the user has already made a reservation for it.""" + return self._reserved + + @reserved.setter + def reserved(self, value): + """Setter for reserved property.""" + self.logger.warn("Setting values on reserved will NOT update the remote Canvas instance.") + self._reserved = value + + @property + def updated_at(self): + """When the calendar event was last updated.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def group(self): + """If the event is a group-level reservation, this will contain the group participant JSON (refer to the Groups API).""" + return self._group + + @group.setter + def group(self, value): + """Setter for group property.""" + self.logger.warn("Setting values on group will NOT update the remote Canvas instance.") + self._group = value + + @property + def child_events_count(self): + """The number of child_events. See child_events (and parent_event_id).""" + return self._child_events_count + + @child_events_count.setter + def child_events_count(self, value): + """Setter for child_events_count property.""" + self.logger.warn("Setting values on child_events_count will NOT update the remote Canvas instance.") + self._child_events_count = value + + @property + def available_slots(self): + """If the event is a time slot and it has a participant limit, an integer indicating how many slots are available.""" + return self._available_slots + + @available_slots.setter + def available_slots(self, value): + """Setter for available_slots property.""" + self.logger.warn("Setting values on available_slots will NOT update the remote Canvas instance.") + self._available_slots = value + + @property + def id(self): + """The ID of the calendar event.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def reserve_url(self): + """If the event is a time slot, the API URL for reserving it.""" + return self._reserve_url + + @reserve_url.setter + def reserve_url(self, value): + """Setter for reserve_url property.""" + self.logger.warn("Setting values on reserve_url will NOT update the remote Canvas instance.") + self._reserve_url = value + + @property + def location_name(self): + """The location name of the event.""" + return self._location_name + + @location_name.setter + def location_name(self, value): + """Setter for location_name property.""" + self.logger.warn("Setting values on location_name will NOT update the remote Canvas instance.") + self._location_name = value + + @property + def title(self): + """The title of the calendar event.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def end_at(self): + """The end timestamp of the event.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def appointment_group_id(self): + """Various Appointment-Group-related fields.These fields are only pertinent to time slots (appointments) and reservations of those time slots. See the Appointment Groups API. The id of the appointment group.""" + return self._appointment_group_id + + @appointment_group_id.setter + def appointment_group_id(self, value): + """Setter for appointment_group_id property.""" + self.logger.warn("Setting values on appointment_group_id will NOT update the remote Canvas instance.") + self._appointment_group_id = value + + @property + def context_code(self): + """the context code of the calendar this event belongs to (course, user or group).""" + return self._context_code + + @context_code.setter + def context_code(self, value): + """Setter for context_code property.""" + self.logger.warn("Setting values on context_code will NOT update the remote Canvas instance.") + self._context_code = value + + @property + def hidden(self): + """Whether this event should be displayed on the calendar. Only true for course-level events with section-level child events.""" + return self._hidden + + @hidden.setter + def hidden(self, value): + """Setter for hidden property.""" + self.logger.warn("Setting values on hidden will NOT update the remote Canvas instance.") + self._hidden = value + + @property + def start_at(self): + """The start timestamp of the event.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def description(self): + """The HTML description of the event.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def child_events(self): + """Included by default, but may be excluded (see include[] option). If this is a time slot (see the Appointment Groups API) this will be a list of any reservations. If this is a course-level event, this will be a list of section-level events (if any).""" + return self._child_events + + @child_events.setter + def child_events(self, value): + """Setter for child_events property.""" + self.logger.warn("Setting values on child_events will NOT update the remote Canvas instance.") + self._child_events = value + + @property + def workflow_state(self): + """Current state of the event ('active', 'locked' or 'deleted') 'locked' indicates that start_at/end_at cannot be changed (though the event could be deleted). Normally only reservations or time slots with reservations are locked (see the Appointment Groups API).""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def effective_context_code(self): + """if specified, it indicates which calendar this event should be displayed on. for example, a section-level event would have the course's context code here, while the section's context code would be returned above).""" + return self._effective_context_code + + @effective_context_code.setter + def effective_context_code(self, value): + """Setter for effective_context_code property.""" + self.logger.warn("Setting values on effective_context_code will NOT update the remote Canvas instance.") + self._effective_context_code = value + + @property + def html_url(self): + """URL for a user to view this event.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def all_day_date(self): + """The date of this event.""" + return self._all_day_date + + @all_day_date.setter + def all_day_date(self, value): + """Setter for all_day_date property.""" + self.logger.warn("Setting values on all_day_date will NOT update the remote Canvas instance.") + self._all_day_date = value + + @property + def user(self): + """If the event is a user-level reservation, this will contain the user participant JSON (refer to the Users API).""" + return self._user + + @user.setter + def user(self, value): + """Setter for user property.""" + self.logger.warn("Setting values on user will NOT update the remote Canvas instance.") + self._user = value + + @property + def participants_per_appointment(self): + """If the event is a time slot, this is the participant limit.""" + return self._participants_per_appointment + + @participants_per_appointment.setter + def participants_per_appointment(self, value): + """Setter for participants_per_appointment property.""" + self.logger.warn("Setting values on participants_per_appointment will NOT update the remote Canvas instance.") + self._participants_per_appointment = value + + @property + def parent_event_id(self): + """Normally null. If this is a reservation (see the Appointment Groups API), the id will indicate the time slot it is for. If this is a section-level event, this will be the course-level parent event.""" + return self._parent_event_id + + @parent_event_id.setter + def parent_event_id(self, value): + """Setter for parent_event_id property.""" + self.logger.warn("Setting values on parent_event_id will NOT update the remote Canvas instance.") + self._parent_event_id = value + + @property + def created_at(self): + """When the calendar event was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def all_day(self): + """Boolean indicating whether this is an all-day event (midnight to midnight).""" + return self._all_day + + @all_day.setter + def all_day(self, value): + """Setter for all_day property.""" + self.logger.warn("Setting values on all_day will NOT update the remote Canvas instance.") + self._all_day = value + + @property + def url(self): + """URL for this calendar event (to update, delete, etc.).""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def location_address(self): + """The address where the event is taking place.""" + return self._location_address + + @location_address.setter + def location_address(self, value): + """Setter for location_address property.""" + self.logger.warn("Setting values on location_address will NOT update the remote Canvas instance.") + self._location_address = value + + @property + def own_reservation(self): + """If the event is a reservation, this a boolean indicating whether it is the current user's reservation, or someone else's.""" + return self._own_reservation + + @own_reservation.setter + def own_reservation(self, value): + """Setter for own_reservation property.""" + self.logger.warn("Setting values on own_reservation will NOT update the remote Canvas instance.") + self._own_reservation = value + + @property + def appointment_group_url(self): + """The API URL of the appointment group.""" + return self._appointment_group_url + + @appointment_group_url.setter + def appointment_group_url(self, value): + """Setter for appointment_group_url property.""" + self.logger.warn("Setting values on appointment_group_url will NOT update the remote Canvas instance.") + self._appointment_group_url = value + + @property + def all_context_codes(self): + """a comma-separated list of all calendar contexts this event is part of.""" + return self._all_context_codes + + @all_context_codes.setter + def all_context_codes(self, value): + """Setter for all_context_codes property.""" + self.logger.warn("Setting values on all_context_codes will NOT update the remote Canvas instance.") + self._all_context_codes = value + + +class Assignmentevent(BaseModel): + """Assignmentevent Model.""" + + def __init__(self, start_at=None, description=None, title=None, url=None, assignment=None, created_at=None, workflow_state=None, html_url=None, end_at=None, updated_at=None, all_day_date=None, context_code=None, assignment_overrides=None, id=None, all_day=None): + """Init method for Assignmentevent class.""" + self._start_at = start_at + self._description = description + self._title = title + self._url = url + self._assignment = assignment + self._created_at = created_at + self._workflow_state = workflow_state + self._html_url = html_url + self._end_at = end_at + self._updated_at = updated_at + self._all_day_date = all_day_date + self._context_code = context_code + self._assignment_overrides = assignment_overrides + self._id = id + self._all_day = all_day + + self.logger = logging.getLogger('pycanvas.Assignmentevent') + + @property + def start_at(self): + """The due_at timestamp of the assignment.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def description(self): + """The HTML description of the assignment.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def title(self): + """The title of the assignment.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def url(self): + """URL for this assignment (note that updating/deleting should be done via the Assignments API).""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def assignment(self): + """The full assignment JSON data (See the Assignments API).""" + return self._assignment + + @assignment.setter + def assignment(self, value): + """Setter for assignment property.""" + self.logger.warn("Setting values on assignment will NOT update the remote Canvas instance.") + self._assignment = value + + @property + def created_at(self): + """When the assignment was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def workflow_state(self): + """Current state of the assignment ('published' or 'deleted').""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def html_url(self): + """URL for a user to view this assignment.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def end_at(self): + """The due_at timestamp of the assignment.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def updated_at(self): + """When the assignment was last updated.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def all_day_date(self): + """The due date of this assignment.""" + return self._all_day_date + + @all_day_date.setter + def all_day_date(self, value): + """Setter for all_day_date property.""" + self.logger.warn("Setting values on all_day_date will NOT update the remote Canvas instance.") + self._all_day_date = value + + @property + def context_code(self): + """the context code of the (course) calendar this assignment belongs to.""" + return self._context_code + + @context_code.setter + def context_code(self, value): + """Setter for context_code property.""" + self.logger.warn("Setting values on context_code will NOT update the remote Canvas instance.") + self._context_code = value + + @property + def assignment_overrides(self): + """The list of AssignmentOverrides that apply to this event (See the Assignments API). This information is useful for determining which students or sections this assignment-due event applies to.""" + return self._assignment_overrides + + @assignment_overrides.setter + def assignment_overrides(self, value): + """Setter for assignment_overrides property.""" + self.logger.warn("Setting values on assignment_overrides will NOT update the remote Canvas instance.") + self._assignment_overrides = value + + @property + def id(self): + """A synthetic ID for the assignment.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def all_day(self): + """Boolean indicating whether this is an all-day event (e.g. assignment due at midnight).""" + return self._all_day + + @all_day.setter + def all_day(self, value): + """Setter for all_day property.""" + self.logger.warn("Setting values on all_day will NOT update the remote Canvas instance.") + self._all_day = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/collaborations.py b/venv/Lib/site-packages/pycanvas/apis/collaborations.py new file mode 100644 index 00000000..95785f1c --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/collaborations.py @@ -0,0 +1,308 @@ +"""Collaborations API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class CollaborationsAPI(BaseCanvasAPI): + """Collaborations API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for CollaborationsAPI.""" + super(CollaborationsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.CollaborationsAPI") + + def list_collaborations_courses(self, course_id): + """ + List collaborations. + + List collaborations the current user has access to in the context of the course + provided in the url. NOTE: this only returns ExternalToolCollaboration type + collaborations. + + curl https:///api/v1/courses/1/collaborations/ + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/collaborations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/collaborations".format(**path), data=data, params=params, all_pages=True) + + def list_collaborations_groups(self, group_id): + """ + List collaborations. + + List collaborations the current user has access to in the context of the course + provided in the url. NOTE: this only returns ExternalToolCollaboration type + collaborations. + + curl https:///api/v1/courses/1/collaborations/ + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/collaborations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/collaborations".format(**path), data=data, params=params, all_pages=True) + + def list_members_of_collaboration(self, id, include=None): + """ + List members of a collaboration. + + List the collaborators of a given collaboration + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """- "collaborator_lti_id": Optional information to include with each member. + Represents an identifier to be used for the member in an LTI context. + - "avatar_image_url": Optional information to include with each member. + The url for the avatar of a collaborator with type 'user'.""" + if include is not None: + self._validate_enum(include, ["collaborator_lti_id", "avatar_image_url"]) + params["include"] = include + + self.logger.debug("GET /api/v1/collaborations/{id}/members with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/collaborations/{id}/members".format(**path), data=data, params=params, all_pages=True) + + +class Collaborator(BaseModel): + """Collaborator Model.""" + + def __init__(self, id, type=None, name=None): + """Init method for Collaborator class.""" + self._type = type + self._id = id + self._name = name + + self.logger = logging.getLogger('pycanvas.Collaborator') + + @property + def type(self): + """The type of collaborator (e.g. 'user' or 'group').""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def id(self): + """The unique user or group identifier for the collaborator.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def name(self): + """The name of the collaborator.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class Collaboration(BaseModel): + """Collaboration Model.""" + + def __init__(self, user_id=None, description=None, title=None, context_type=None, context_id=None, created_at=None, updated_at=None, url=None, user_name=None, collaboration_type=None, update_url=None, type=None, id=None, document_id=None): + """Init method for Collaboration class.""" + self._user_id = user_id + self._description = description + self._title = title + self._context_type = context_type + self._context_id = context_id + self._created_at = created_at + self._updated_at = updated_at + self._url = url + self._user_name = user_name + self._collaboration_type = collaboration_type + self._update_url = update_url + self._type = type + self._id = id + self._document_id = document_id + + self.logger = logging.getLogger('pycanvas.Collaboration') + + @property + def user_id(self): + """The canvas id of the user who created the collaboration.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def description(self): + """description.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def title(self): + """title.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def context_type(self): + """The canvas type of the course or group to which the collaboration belongs.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def context_id(self): + """The canvas id of the course or group to which the collaboration belongs.""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + + @property + def created_at(self): + """The timestamp when the collaboration was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def updated_at(self): + """The timestamp when the collaboration was last modified.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def url(self): + """The LTI launch url to view collaboration.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def user_name(self): + """The name of the user who owns the collaboration.""" + return self._user_name + + @user_name.setter + def user_name(self, value): + """Setter for user_name property.""" + self.logger.warn("Setting values on user_name will NOT update the remote Canvas instance.") + self._user_name = value + + @property + def collaboration_type(self): + """A name for the type of collaboration.""" + return self._collaboration_type + + @collaboration_type.setter + def collaboration_type(self, value): + """Setter for collaboration_type property.""" + self.logger.warn("Setting values on collaboration_type will NOT update the remote Canvas instance.") + self._collaboration_type = value + + @property + def update_url(self): + """The LTI launch url to edit the collaboration.""" + return self._update_url + + @update_url.setter + def update_url(self, value): + """Setter for update_url property.""" + self.logger.warn("Setting values on update_url will NOT update the remote Canvas instance.") + self._update_url = value + + @property + def type(self): + """Another representation of the collaboration type.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def id(self): + """The unique identifier for the collaboration.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def document_id(self): + """The collaboration document identifier for the collaboration provider.""" + return self._document_id + + @document_id.setter + def document_id(self, value): + """Setter for document_id property.""" + self.logger.warn("Setting values on document_id will NOT update the remote Canvas instance.") + self._document_id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/comm_messages.py b/venv/Lib/site-packages/pycanvas/apis/comm_messages.py new file mode 100644 index 00000000..8a167f44 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/comm_messages.py @@ -0,0 +1,174 @@ +"""CommMessages API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class CommMessagesAPI(BaseCanvasAPI): + """CommMessages API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for CommMessagesAPI.""" + super(CommMessagesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.CommMessagesAPI") + + def list_of_commmessages_for_user(self, user_id, end_time=None, start_time=None): + """ + List of CommMessages for a user. + + Retrieve messages sent to a user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - user_id + """The user id for whom you want to retrieve CommMessages""" + params["user_id"] = user_id + + # OPTIONAL - start_time + """The beginning of the time range you want to retrieve message from.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range you want to retrieve messages for.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/comm_messages with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/comm_messages".format(**path), data=data, params=params, all_pages=True) + + +class Commmessage(BaseModel): + """Commmessage Model.""" + + def __init__(self, body=None, from=None, sent_at=None, workflow_state=None, created_at=None, to=None, reply_to=None, html_body=None, id=None, subject=None): + """Init method for Commmessage class.""" + self._body = body + self._from = from + self._sent_at = sent_at + self._workflow_state = workflow_state + self._created_at = created_at + self._to = to + self._reply_to = reply_to + self._html_body = html_body + self._id = id + self._subject = subject + + self.logger = logging.getLogger('pycanvas.Commmessage') + + @property + def body(self): + """The plain text body of the message.""" + return self._body + + @body.setter + def body(self, value): + """Setter for body property.""" + self.logger.warn("Setting values on body will NOT update the remote Canvas instance.") + self._body = value + + @property + def from(self): + """The address that was put in the 'from' field of the message.""" + return self._from + + @from.setter + def from(self, value): + """Setter for from property.""" + self.logger.warn("Setting values on from will NOT update the remote Canvas instance.") + self._from = value + + @property + def sent_at(self): + """The date and time this message was sent.""" + return self._sent_at + + @sent_at.setter + def sent_at(self, value): + """Setter for sent_at property.""" + self.logger.warn("Setting values on sent_at will NOT update the remote Canvas instance.") + self._sent_at = value + + @property + def workflow_state(self): + """The workflow state of the message. One of 'created', 'staged', 'sending', 'sent', 'bounced', 'dashboard', 'cancelled', or 'closed'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def created_at(self): + """The date and time this message was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def to(self): + """The address the message was sent to:.""" + return self._to + + @to.setter + def to(self, value): + """Setter for to property.""" + self.logger.warn("Setting values on to will NOT update the remote Canvas instance.") + self._to = value + + @property + def reply_to(self): + """The reply_to header of the message.""" + return self._reply_to + + @reply_to.setter + def reply_to(self, value): + """Setter for reply_to property.""" + self.logger.warn("Setting values on reply_to will NOT update the remote Canvas instance.") + self._reply_to = value + + @property + def html_body(self): + """The HTML body of the message.""" + return self._html_body + + @html_body.setter + def html_body(self, value): + """Setter for html_body property.""" + self.logger.warn("Setting values on html_body will NOT update the remote Canvas instance.") + self._html_body = value + + @property + def id(self): + """The ID of the CommMessage.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def subject(self): + """The message subject.""" + return self._subject + + @subject.setter + def subject(self, value): + """Setter for subject property.""" + self.logger.warn("Setting values on subject will NOT update the remote Canvas instance.") + self._subject = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/communication_channels.py b/venv/Lib/site-packages/pycanvas/apis/communication_channels.py new file mode 100644 index 00000000..a1d2c362 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/communication_channels.py @@ -0,0 +1,209 @@ +"""CommunicationChannels API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class CommunicationChannelsAPI(BaseCanvasAPI): + """CommunicationChannels API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for CommunicationChannelsAPI.""" + super(CommunicationChannelsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.CommunicationChannelsAPI") + + def list_user_communication_channels(self, user_id): + """ + List user communication channels. + + Returns a list of communication channels for the specified user, sorted by + position. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/communication_channels with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/communication_channels".format(**path), data=data, params=params, all_pages=True) + + def create_communication_channel(self, user_id, communication_channel_type, communication_channel_address, communication_channel_token=None, skip_confirmation=None): + """ + Create a communication channel. + + Creates a new communication channel for the specified user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - communication_channel[address] + """An email address or SMS number. Not required for "push" type channels.""" + data["communication_channel[address]"] = communication_channel_address + + # REQUIRED - communication_channel[type] + """The type of communication channel. + + In order to enable push notification support, the server must be + properly configured (via sns.yml) to communicate with Amazon + Simple Notification Services, and the developer key used to create + the access token from this request must have an SNS ARN configured on + it.""" + self._validate_enum(communication_channel_type, ["email", "sms", "push"]) + data["communication_channel[type]"] = communication_channel_type + + # OPTIONAL - communication_channel[token] + """A registration id, device token, or equivalent token given to an app when + registering with a push notification provider. Only valid for "push" type channels.""" + if communication_channel_token is not None: + data["communication_channel[token]"] = communication_channel_token + + # OPTIONAL - skip_confirmation + """Only valid for site admins and account admins making requests; If true, the channel is + automatically validated and no confirmation email or SMS is sent. + Otherwise, the user must respond to a confirmation message to confirm the + channel.""" + if skip_confirmation is not None: + data["skip_confirmation"] = skip_confirmation + + self.logger.debug("POST /api/v1/users/{user_id}/communication_channels with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/{user_id}/communication_channels".format(**path), data=data, params=params, single_item=True) + + def delete_communication_channel_id(self, id, user_id): + """ + Delete a communication channel. + + Delete an existing communication channel. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/users/{user_id}/communication_channels/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/{user_id}/communication_channels/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_communication_channel_type(self, type, user_id, address): + """ + Delete a communication channel. + + Delete an existing communication channel. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - type + """ID""" + path["type"] = type + + # REQUIRED - PATH - address + """ID""" + path["address"] = address + + self.logger.debug("DELETE /api/v1/users/{user_id}/communication_channels/{type}/{address} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/{user_id}/communication_channels/{type}/{address}".format(**path), data=data, params=params, single_item=True) + + +class Communicationchannel(BaseModel): + """Communicationchannel Model.""" + + def __init__(self, user_id=None, workflow_state=None, address=None, position=None, type=None, id=None): + """Init method for Communicationchannel class.""" + self._user_id = user_id + self._workflow_state = workflow_state + self._address = address + self._position = position + self._type = type + self._id = id + + self.logger = logging.getLogger('pycanvas.Communicationchannel') + + @property + def user_id(self): + """The ID of the user that owns this communication channel.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def workflow_state(self): + """The current state of the communication channel. Possible values are: 'unconfirmed' or 'active'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def address(self): + """The address, or path, of the communication channel.""" + return self._address + + @address.setter + def address(self, value): + """Setter for address property.""" + self.logger.warn("Setting values on address will NOT update the remote Canvas instance.") + self._address = value + + @property + def position(self): + """The position of this communication channel relative to the user's other channels when they are ordered.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def type(self): + """The type of communcation channel being described. Possible values are: 'email', 'push', 'sms', 'twitter' or 'yo'. This field determines the type of value seen in 'address'.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def id(self): + """The ID of the communication channel.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/conferences.py b/venv/Lib/site-packages/pycanvas/apis/conferences.py new file mode 100644 index 00000000..c4ee880e --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/conferences.py @@ -0,0 +1,316 @@ +"""Conferences API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class ConferencesAPI(BaseCanvasAPI): + """Conferences API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for ConferencesAPI.""" + super(ConferencesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.ConferencesAPI") + + def list_conferences_courses(self, course_id): + """ + List conferences. + + Retrieve the list of conferences for this context + + This API returns a JSON object containing the list of conferences, + the key for the list of conferences is "conferences" + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/conferences with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/conferences".format(**path), data=data, params=params, all_pages=True) + + def list_conferences_groups(self, group_id): + """ + List conferences. + + Retrieve the list of conferences for this context + + This API returns a JSON object containing the list of conferences, + the key for the list of conferences is "conferences" + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/conferences with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/conferences".format(**path), data=data, params=params, all_pages=True) + + +class Conference(BaseModel): + """Conference Model.""" + + def __init__(self, conference_key=None, ended_at=None, description=None, conference_type=None, title=None, url=None, join_url=None, has_advanced_settings=None, recordings=None, user_settings=None, duration=None, long_running=None, started_at=None, id=None, users=None): + """Init method for Conference class.""" + self._conference_key = conference_key + self._ended_at = ended_at + self._description = description + self._conference_type = conference_type + self._title = title + self._url = url + self._join_url = join_url + self._has_advanced_settings = has_advanced_settings + self._recordings = recordings + self._user_settings = user_settings + self._duration = duration + self._long_running = long_running + self._started_at = started_at + self._id = id + self._users = users + + self.logger = logging.getLogger('pycanvas.Conference') + + @property + def conference_key(self): + """The 3rd party's ID for the conference.""" + return self._conference_key + + @conference_key.setter + def conference_key(self, value): + """Setter for conference_key property.""" + self.logger.warn("Setting values on conference_key will NOT update the remote Canvas instance.") + self._conference_key = value + + @property + def ended_at(self): + """The date that the conference ended at, null if it hasn't ended.""" + return self._ended_at + + @ended_at.setter + def ended_at(self, value): + """Setter for ended_at property.""" + self.logger.warn("Setting values on ended_at will NOT update the remote Canvas instance.") + self._ended_at = value + + @property + def description(self): + """The description for the conference.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def conference_type(self): + """The type of conference.""" + return self._conference_type + + @conference_type.setter + def conference_type(self, value): + """Setter for conference_type property.""" + self.logger.warn("Setting values on conference_type will NOT update the remote Canvas instance.") + self._conference_type = value + + @property + def title(self): + """The title of the conference.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def url(self): + """URL for the conference, may be null if the conference type doesn't set it.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def join_url(self): + """URL to join the conference, may be null if the conference type doesn't set it.""" + return self._join_url + + @join_url.setter + def join_url(self, value): + """Setter for join_url property.""" + self.logger.warn("Setting values on join_url will NOT update the remote Canvas instance.") + self._join_url = value + + @property + def has_advanced_settings(self): + """True if the conference type has advanced settings.""" + return self._has_advanced_settings + + @has_advanced_settings.setter + def has_advanced_settings(self, value): + """Setter for has_advanced_settings property.""" + self.logger.warn("Setting values on has_advanced_settings will NOT update the remote Canvas instance.") + self._has_advanced_settings = value + + @property + def recordings(self): + """A List of recordings for the conference.""" + return self._recordings + + @recordings.setter + def recordings(self, value): + """Setter for recordings property.""" + self.logger.warn("Setting values on recordings will NOT update the remote Canvas instance.") + self._recordings = value + + @property + def user_settings(self): + """A collection of settings specific to the conference type.""" + return self._user_settings + + @user_settings.setter + def user_settings(self, value): + """Setter for user_settings property.""" + self.logger.warn("Setting values on user_settings will NOT update the remote Canvas instance.") + self._user_settings = value + + @property + def duration(self): + """The expected duration the conference is supposed to last.""" + return self._duration + + @duration.setter + def duration(self, value): + """Setter for duration property.""" + self.logger.warn("Setting values on duration will NOT update the remote Canvas instance.") + self._duration = value + + @property + def long_running(self): + """If true the conference is long running and has no expected end time.""" + return self._long_running + + @long_running.setter + def long_running(self, value): + """Setter for long_running property.""" + self.logger.warn("Setting values on long_running will NOT update the remote Canvas instance.") + self._long_running = value + + @property + def started_at(self): + """The date the conference started at, null if it hasn't started.""" + return self._started_at + + @started_at.setter + def started_at(self, value): + """Setter for started_at property.""" + self.logger.warn("Setting values on started_at will NOT update the remote Canvas instance.") + self._started_at = value + + @property + def id(self): + """The id of the conference.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def users(self): + """Array of user ids that are participants in the conference.""" + return self._users + + @users.setter + def users(self, value): + """Setter for users property.""" + self.logger.warn("Setting values on users will NOT update the remote Canvas instance.") + self._users = value + + +class Conferencerecording(BaseModel): + """Conferencerecording Model.""" + + def __init__(self, created_at=None, duration_minutes=None, updated_at=None, playback_url=None, title=None): + """Init method for Conferencerecording class.""" + self._created_at = created_at + self._duration_minutes = duration_minutes + self._updated_at = updated_at + self._playback_url = playback_url + self._title = title + + self.logger = logging.getLogger('pycanvas.Conferencerecording') + + @property + def created_at(self): + """created_at.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def duration_minutes(self): + """duration_minutes.""" + return self._duration_minutes + + @duration_minutes.setter + def duration_minutes(self, value): + """Setter for duration_minutes property.""" + self.logger.warn("Setting values on duration_minutes will NOT update the remote Canvas instance.") + self._duration_minutes = value + + @property + def updated_at(self): + """updated_at.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def playback_url(self): + """playback_url.""" + return self._playback_url + + @playback_url.setter + def playback_url(self, value): + """Setter for playback_url property.""" + self.logger.warn("Setting values on playback_url will NOT update the remote Canvas instance.") + self._playback_url = value + + @property + def title(self): + """title.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/content_exports.py b/venv/Lib/site-packages/pycanvas/apis/content_exports.py new file mode 100644 index 00000000..cde00473 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/content_exports.py @@ -0,0 +1,336 @@ +"""ContentExports API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class ContentExportsAPI(BaseCanvasAPI): + """ContentExports API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for ContentExportsAPI.""" + super(ContentExportsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.ContentExportsAPI") + + def list_content_exports_courses(self, course_id): + """ + List content exports. + + List the past and pending content export jobs for a course, group, or user. + Exports are returned newest first. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/content_exports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/content_exports".format(**path), data=data, params=params, all_pages=True) + + def list_content_exports_groups(self, group_id): + """ + List content exports. + + List the past and pending content export jobs for a course, group, or user. + Exports are returned newest first. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/content_exports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/content_exports".format(**path), data=data, params=params, all_pages=True) + + def list_content_exports_users(self, user_id): + """ + List content exports. + + List the past and pending content export jobs for a course, group, or user. + Exports are returned newest first. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/content_exports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/content_exports".format(**path), data=data, params=params, all_pages=True) + + def show_content_export_courses(self, id, course_id): + """ + Show content export. + + Get information about a single content export. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/content_exports/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/content_exports/{id}".format(**path), data=data, params=params, single_item=True) + + def show_content_export_groups(self, id, group_id): + """ + Show content export. + + Get information about a single content export. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/groups/{group_id}/content_exports/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/content_exports/{id}".format(**path), data=data, params=params, single_item=True) + + def show_content_export_users(self, id, user_id): + """ + Show content export. + + Get information about a single content export. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/users/{user_id}/content_exports/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/content_exports/{id}".format(**path), data=data, params=params, single_item=True) + + def export_content_courses(self, course_id, export_type, skip_notifications=None): + """ + Export content. + + Begin a content export job for a course, group, or user. + + You can use the {api:ProgressController#show Progress API} to track the + progress of the export. The migration's progress is linked to with the + _progress_url_ value. + + When the export completes, use the {api:ContentExportsApiController#show Show content export} endpoint + to retrieve a download URL for the exported content. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - export_type + """"common_cartridge":: Export the contents of the course in the Common Cartridge (.imscc) format + "qti":: Export quizzes from a course in the QTI format + "zip":: Export files from a course, group, or user in a zip file""" + self._validate_enum(export_type, ["common_cartridge", "qti", "zip"]) + data["export_type"] = export_type + + # OPTIONAL - skip_notifications + """Don't send the notifications about the export to the user. Default: false""" + if skip_notifications is not None: + data["skip_notifications"] = skip_notifications + + self.logger.debug("POST /api/v1/courses/{course_id}/content_exports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/content_exports".format(**path), data=data, params=params, single_item=True) + + def export_content_groups(self, group_id, export_type, skip_notifications=None): + """ + Export content. + + Begin a content export job for a course, group, or user. + + You can use the {api:ProgressController#show Progress API} to track the + progress of the export. The migration's progress is linked to with the + _progress_url_ value. + + When the export completes, use the {api:ContentExportsApiController#show Show content export} endpoint + to retrieve a download URL for the exported content. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - export_type + """"common_cartridge":: Export the contents of the course in the Common Cartridge (.imscc) format + "qti":: Export quizzes from a course in the QTI format + "zip":: Export files from a course, group, or user in a zip file""" + self._validate_enum(export_type, ["common_cartridge", "qti", "zip"]) + data["export_type"] = export_type + + # OPTIONAL - skip_notifications + """Don't send the notifications about the export to the user. Default: false""" + if skip_notifications is not None: + data["skip_notifications"] = skip_notifications + + self.logger.debug("POST /api/v1/groups/{group_id}/content_exports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/content_exports".format(**path), data=data, params=params, single_item=True) + + def export_content_users(self, user_id, export_type, skip_notifications=None): + """ + Export content. + + Begin a content export job for a course, group, or user. + + You can use the {api:ProgressController#show Progress API} to track the + progress of the export. The migration's progress is linked to with the + _progress_url_ value. + + When the export completes, use the {api:ContentExportsApiController#show Show content export} endpoint + to retrieve a download URL for the exported content. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - export_type + """"common_cartridge":: Export the contents of the course in the Common Cartridge (.imscc) format + "qti":: Export quizzes from a course in the QTI format + "zip":: Export files from a course, group, or user in a zip file""" + self._validate_enum(export_type, ["common_cartridge", "qti", "zip"]) + data["export_type"] = export_type + + # OPTIONAL - skip_notifications + """Don't send the notifications about the export to the user. Default: false""" + if skip_notifications is not None: + data["skip_notifications"] = skip_notifications + + self.logger.debug("POST /api/v1/users/{user_id}/content_exports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/{user_id}/content_exports".format(**path), data=data, params=params, single_item=True) + + +class Contentexport(BaseModel): + """Contentexport Model.""" + + def __init__(self, progress_url=None, user_id=None, workflow_state=None, created_at=None, id=None, attachment=None, export_type=None): + """Init method for Contentexport class.""" + self._progress_url = progress_url + self._user_id = user_id + self._workflow_state = workflow_state + self._created_at = created_at + self._id = id + self._attachment = attachment + self._export_type = export_type + + self.logger = logging.getLogger('pycanvas.Contentexport') + + @property + def progress_url(self): + """The api endpoint for polling the current progress.""" + return self._progress_url + + @progress_url.setter + def progress_url(self, value): + """Setter for progress_url property.""" + self.logger.warn("Setting values on progress_url will NOT update the remote Canvas instance.") + self._progress_url = value + + @property + def user_id(self): + """The ID of the user who started the export.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def workflow_state(self): + """Current state of the content migration: created exporting exported failed.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def created_at(self): + """the date and time this export was requested.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def id(self): + """the unique identifier for the export.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def attachment(self): + """attachment api object for the export package (not present until the export completes).""" + return self._attachment + + @attachment.setter + def attachment(self, value): + """Setter for attachment property.""" + self.logger.warn("Setting values on attachment will NOT update the remote Canvas instance.") + self._attachment = value + + @property + def export_type(self): + """the type of content migration: 'common_cartridge' or 'qti'.""" + return self._export_type + + @export_type.setter + def export_type(self, value): + """Setter for export_type property.""" + self.logger.warn("Setting values on export_type will NOT update the remote Canvas instance.") + self._export_type = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/content_migrations.py b/venv/Lib/site-packages/pycanvas/apis/content_migrations.py new file mode 100644 index 00000000..53f168f9 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/content_migrations.py @@ -0,0 +1,1513 @@ +"""ContentMigrations API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class ContentMigrationsAPI(BaseCanvasAPI): + """ContentMigrations API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for ContentMigrationsAPI.""" + super(ContentMigrationsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.ContentMigrationsAPI") + + def list_migration_issues_accounts(self, account_id, content_migration_id): + """ + List migration issues. + + Returns paginated migration issues + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/content_migrations/{content_migration_id}/migration_issues with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/content_migrations/{content_migration_id}/migration_issues".format(**path), data=data, params=params, all_pages=True) + + def list_migration_issues_courses(self, course_id, content_migration_id): + """ + List migration issues. + + Returns paginated migration issues + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + self.logger.debug("GET /api/v1/courses/{course_id}/content_migrations/{content_migration_id}/migration_issues with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/content_migrations/{content_migration_id}/migration_issues".format(**path), data=data, params=params, all_pages=True) + + def list_migration_issues_groups(self, group_id, content_migration_id): + """ + List migration issues. + + Returns paginated migration issues + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + self.logger.debug("GET /api/v1/groups/{group_id}/content_migrations/{content_migration_id}/migration_issues with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/content_migrations/{content_migration_id}/migration_issues".format(**path), data=data, params=params, all_pages=True) + + def list_migration_issues_users(self, user_id, content_migration_id): + """ + List migration issues. + + Returns paginated migration issues + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + self.logger.debug("GET /api/v1/users/{user_id}/content_migrations/{content_migration_id}/migration_issues with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/content_migrations/{content_migration_id}/migration_issues".format(**path), data=data, params=params, all_pages=True) + + def get_migration_issue_accounts(self, id, account_id, content_migration_id): + """ + Get a migration issue. + + Returns data on an individual migration issue + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{account_id}/content_migrations/{content_migration_id}/migration_issues/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/content_migrations/{content_migration_id}/migration_issues/{id}".format(**path), data=data, params=params, single_item=True) + + def get_migration_issue_courses(self, id, course_id, content_migration_id): + """ + Get a migration issue. + + Returns data on an individual migration issue + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/content_migrations/{content_migration_id}/migration_issues/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/content_migrations/{content_migration_id}/migration_issues/{id}".format(**path), data=data, params=params, single_item=True) + + def get_migration_issue_groups(self, id, group_id, content_migration_id): + """ + Get a migration issue. + + Returns data on an individual migration issue + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/groups/{group_id}/content_migrations/{content_migration_id}/migration_issues/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/content_migrations/{content_migration_id}/migration_issues/{id}".format(**path), data=data, params=params, single_item=True) + + def get_migration_issue_users(self, id, user_id, content_migration_id): + """ + Get a migration issue. + + Returns data on an individual migration issue + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/users/{user_id}/content_migrations/{content_migration_id}/migration_issues/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/content_migrations/{content_migration_id}/migration_issues/{id}".format(**path), data=data, params=params, single_item=True) + + def update_migration_issue_accounts(self, id, account_id, workflow_state, content_migration_id): + """ + Update a migration issue. + + Update the workflow_state of a migration issue + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - workflow_state + """Set the workflow_state of the issue.""" + self._validate_enum(workflow_state, ["active", "resolved"]) + data["workflow_state"] = workflow_state + + self.logger.debug("PUT /api/v1/accounts/{account_id}/content_migrations/{content_migration_id}/migration_issues/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/content_migrations/{content_migration_id}/migration_issues/{id}".format(**path), data=data, params=params, single_item=True) + + def update_migration_issue_courses(self, id, course_id, workflow_state, content_migration_id): + """ + Update a migration issue. + + Update the workflow_state of a migration issue + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - workflow_state + """Set the workflow_state of the issue.""" + self._validate_enum(workflow_state, ["active", "resolved"]) + data["workflow_state"] = workflow_state + + self.logger.debug("PUT /api/v1/courses/{course_id}/content_migrations/{content_migration_id}/migration_issues/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/content_migrations/{content_migration_id}/migration_issues/{id}".format(**path), data=data, params=params, single_item=True) + + def update_migration_issue_groups(self, id, group_id, workflow_state, content_migration_id): + """ + Update a migration issue. + + Update the workflow_state of a migration issue + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - workflow_state + """Set the workflow_state of the issue.""" + self._validate_enum(workflow_state, ["active", "resolved"]) + data["workflow_state"] = workflow_state + + self.logger.debug("PUT /api/v1/groups/{group_id}/content_migrations/{content_migration_id}/migration_issues/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/content_migrations/{content_migration_id}/migration_issues/{id}".format(**path), data=data, params=params, single_item=True) + + def update_migration_issue_users(self, id, user_id, workflow_state, content_migration_id): + """ + Update a migration issue. + + Update the workflow_state of a migration issue + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - content_migration_id + """ID""" + path["content_migration_id"] = content_migration_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - workflow_state + """Set the workflow_state of the issue.""" + self._validate_enum(workflow_state, ["active", "resolved"]) + data["workflow_state"] = workflow_state + + self.logger.debug("PUT /api/v1/users/{user_id}/content_migrations/{content_migration_id}/migration_issues/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{user_id}/content_migrations/{content_migration_id}/migration_issues/{id}".format(**path), data=data, params=params, single_item=True) + + def list_content_migrations_accounts(self, account_id): + """ + List content migrations. + + Returns paginated content migrations + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/content_migrations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/content_migrations".format(**path), data=data, params=params, all_pages=True) + + def list_content_migrations_courses(self, course_id): + """ + List content migrations. + + Returns paginated content migrations + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/content_migrations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/content_migrations".format(**path), data=data, params=params, all_pages=True) + + def list_content_migrations_groups(self, group_id): + """ + List content migrations. + + Returns paginated content migrations + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/content_migrations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/content_migrations".format(**path), data=data, params=params, all_pages=True) + + def list_content_migrations_users(self, user_id): + """ + List content migrations. + + Returns paginated content migrations + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/content_migrations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/content_migrations".format(**path), data=data, params=params, all_pages=True) + + def get_content_migration_accounts(self, id, account_id): + """ + Get a content migration. + + Returns data on an individual content migration + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{account_id}/content_migrations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/content_migrations/{id}".format(**path), data=data, params=params, single_item=True) + + def get_content_migration_courses(self, id, course_id): + """ + Get a content migration. + + Returns data on an individual content migration + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/content_migrations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/content_migrations/{id}".format(**path), data=data, params=params, single_item=True) + + def get_content_migration_groups(self, id, group_id): + """ + Get a content migration. + + Returns data on an individual content migration + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/groups/{group_id}/content_migrations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/content_migrations/{id}".format(**path), data=data, params=params, single_item=True) + + def get_content_migration_users(self, id, user_id): + """ + Get a content migration. + + Returns data on an individual content migration + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/users/{user_id}/content_migrations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/content_migrations/{id}".format(**path), data=data, params=params, single_item=True) + + def create_content_migration_accounts(self, account_id, migration_type, date_shift_options_day_substitutions_X=None, date_shift_options_new_end_date=None, date_shift_options_new_start_date=None, date_shift_options_old_end_date=None, date_shift_options_old_start_date=None, date_shift_options_remove_dates=None, date_shift_options_shift_dates=None, pre_attachment_*=None, pre_attachment_name=None, settings_file_url=None, settings_folder_id=None, settings_overwrite_quizzes=None, settings_question_bank_id=None, settings_question_bank_name=None, settings_source_course_id=None): + """ + Create a content migration. + + Create a content migration. If the migration requires a file to be uploaded + the actual processing of the file will start once the file upload process is completed. + File uploading works as described in the {file:file_uploads.html File Upload Documentation} + except that the values are set on a *pre_attachment* sub-hash. + + For migrations that don't require a file to be uploaded, like course copy, the + processing will begin as soon as the migration is created. + + You can use the {api:ProgressController#show Progress API} to track the + progress of the migration. The migration's progress is linked to with the + _progress_url_ value. + + The two general workflows are: + + If no file upload is needed: + + 1. POST to create + 2. Use the {api:ProgressController#show Progress} specified in _progress_url_ to monitor progress + + For file uploading: + + 1. POST to create with file info in *pre_attachment* + 2. Do {file:file_uploads.html file upload processing} using the data in the *pre_attachment* data + 3. {api:ContentMigrationsController#show GET} the ContentMigration + 4. Use the {api:ProgressController#show Progress} specified in _progress_url_ to monitor progress + + (required if doing .zip file upload) + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - migration_type + """The type of the migration. Use the + {api:ContentMigrationsController#available_migrators Migrator} endpoint to + see all available migrators. Default allowed values: + canvas_cartridge_importer, common_cartridge_importer, + course_copy_importer, zip_file_importer, qti_converter, moodle_converter""" + data["migration_type"] = migration_type + + # OPTIONAL - pre_attachment[name] + """Required if uploading a file. This is the first step in uploading a file + to the content migration. See the {file:file_uploads.html File Upload + Documentation} for details on the file upload workflow.""" + if pre_attachment_name is not None: + data["pre_attachment[name]"] = pre_attachment_name + + # OPTIONAL - pre_attachment[*] + """Other file upload properties, See {file:file_uploads.html File Upload + Documentation}""" + if pre_attachment_* is not None: + data["pre_attachment[*]"] = pre_attachment_* + + # OPTIONAL - settings[file_url] + """A URL to download the file from. Must not require authentication.""" + if settings_file_url is not None: + data["settings[file_url]"] = settings_file_url + + # OPTIONAL - settings[source_course_id] + """The course to copy from for a course copy migration. (required if doing + course copy)""" + if settings_source_course_id is not None: + data["settings[source_course_id]"] = settings_source_course_id + + # OPTIONAL - settings[folder_id] + """The folder to unzip the .zip file into for a zip_file_import.""" + if settings_folder_id is not None: + data["settings[folder_id]"] = settings_folder_id + + # OPTIONAL - settings[overwrite_quizzes] + """Whether to overwrite quizzes with the same identifiers between content + packages.""" + if settings_overwrite_quizzes is not None: + data["settings[overwrite_quizzes]"] = settings_overwrite_quizzes + + # OPTIONAL - settings[question_bank_id] + """The existing question bank ID to import questions into if not specified in + the content package.""" + if settings_question_bank_id is not None: + data["settings[question_bank_id]"] = settings_question_bank_id + + # OPTIONAL - settings[question_bank_name] + """The question bank to import questions into if not specified in the content + package, if both bank id and name are set, id will take precedence.""" + if settings_question_bank_name is not None: + data["settings[question_bank_name]"] = settings_question_bank_name + + # OPTIONAL - date_shift_options[shift_dates] + """Whether to shift dates in the copied course""" + if date_shift_options_shift_dates is not None: + data["date_shift_options[shift_dates]"] = date_shift_options_shift_dates + + # OPTIONAL - date_shift_options[old_start_date] + """The original start date of the source content/course""" + if date_shift_options_old_start_date is not None: + data["date_shift_options[old_start_date]"] = date_shift_options_old_start_date + + # OPTIONAL - date_shift_options[old_end_date] + """The original end date of the source content/course""" + if date_shift_options_old_end_date is not None: + data["date_shift_options[old_end_date]"] = date_shift_options_old_end_date + + # OPTIONAL - date_shift_options[new_start_date] + """The new start date for the content/course""" + if date_shift_options_new_start_date is not None: + data["date_shift_options[new_start_date]"] = date_shift_options_new_start_date + + # OPTIONAL - date_shift_options[new_end_date] + """The new end date for the source content/course""" + if date_shift_options_new_end_date is not None: + data["date_shift_options[new_end_date]"] = date_shift_options_new_end_date + + # OPTIONAL - date_shift_options[day_substitutions][X] + """Move anything scheduled for day 'X' to the specified day. (0-Sunday, + 1-Monday, 2-Tuesday, 3-Wednesday, 4-Thursday, 5-Friday, 6-Saturday)""" + if date_shift_options_day_substitutions_X is not None: + data["date_shift_options[day_substitutions][X]"] = date_shift_options_day_substitutions_X + + # OPTIONAL - date_shift_options[remove_dates] + """Whether to remove dates in the copied course. Cannot be used + in conjunction with *shift_dates*.""" + if date_shift_options_remove_dates is not None: + data["date_shift_options[remove_dates]"] = date_shift_options_remove_dates + + self.logger.debug("POST /api/v1/accounts/{account_id}/content_migrations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/content_migrations".format(**path), data=data, params=params, single_item=True) + + def create_content_migration_courses(self, course_id, migration_type, date_shift_options_day_substitutions_X=None, date_shift_options_new_end_date=None, date_shift_options_new_start_date=None, date_shift_options_old_end_date=None, date_shift_options_old_start_date=None, date_shift_options_remove_dates=None, date_shift_options_shift_dates=None, pre_attachment_*=None, pre_attachment_name=None, settings_file_url=None, settings_folder_id=None, settings_overwrite_quizzes=None, settings_question_bank_id=None, settings_question_bank_name=None, settings_source_course_id=None): + """ + Create a content migration. + + Create a content migration. If the migration requires a file to be uploaded + the actual processing of the file will start once the file upload process is completed. + File uploading works as described in the {file:file_uploads.html File Upload Documentation} + except that the values are set on a *pre_attachment* sub-hash. + + For migrations that don't require a file to be uploaded, like course copy, the + processing will begin as soon as the migration is created. + + You can use the {api:ProgressController#show Progress API} to track the + progress of the migration. The migration's progress is linked to with the + _progress_url_ value. + + The two general workflows are: + + If no file upload is needed: + + 1. POST to create + 2. Use the {api:ProgressController#show Progress} specified in _progress_url_ to monitor progress + + For file uploading: + + 1. POST to create with file info in *pre_attachment* + 2. Do {file:file_uploads.html file upload processing} using the data in the *pre_attachment* data + 3. {api:ContentMigrationsController#show GET} the ContentMigration + 4. Use the {api:ProgressController#show Progress} specified in _progress_url_ to monitor progress + + (required if doing .zip file upload) + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - migration_type + """The type of the migration. Use the + {api:ContentMigrationsController#available_migrators Migrator} endpoint to + see all available migrators. Default allowed values: + canvas_cartridge_importer, common_cartridge_importer, + course_copy_importer, zip_file_importer, qti_converter, moodle_converter""" + data["migration_type"] = migration_type + + # OPTIONAL - pre_attachment[name] + """Required if uploading a file. This is the first step in uploading a file + to the content migration. See the {file:file_uploads.html File Upload + Documentation} for details on the file upload workflow.""" + if pre_attachment_name is not None: + data["pre_attachment[name]"] = pre_attachment_name + + # OPTIONAL - pre_attachment[*] + """Other file upload properties, See {file:file_uploads.html File Upload + Documentation}""" + if pre_attachment_* is not None: + data["pre_attachment[*]"] = pre_attachment_* + + # OPTIONAL - settings[file_url] + """A URL to download the file from. Must not require authentication.""" + if settings_file_url is not None: + data["settings[file_url]"] = settings_file_url + + # OPTIONAL - settings[source_course_id] + """The course to copy from for a course copy migration. (required if doing + course copy)""" + if settings_source_course_id is not None: + data["settings[source_course_id]"] = settings_source_course_id + + # OPTIONAL - settings[folder_id] + """The folder to unzip the .zip file into for a zip_file_import.""" + if settings_folder_id is not None: + data["settings[folder_id]"] = settings_folder_id + + # OPTIONAL - settings[overwrite_quizzes] + """Whether to overwrite quizzes with the same identifiers between content + packages.""" + if settings_overwrite_quizzes is not None: + data["settings[overwrite_quizzes]"] = settings_overwrite_quizzes + + # OPTIONAL - settings[question_bank_id] + """The existing question bank ID to import questions into if not specified in + the content package.""" + if settings_question_bank_id is not None: + data["settings[question_bank_id]"] = settings_question_bank_id + + # OPTIONAL - settings[question_bank_name] + """The question bank to import questions into if not specified in the content + package, if both bank id and name are set, id will take precedence.""" + if settings_question_bank_name is not None: + data["settings[question_bank_name]"] = settings_question_bank_name + + # OPTIONAL - date_shift_options[shift_dates] + """Whether to shift dates in the copied course""" + if date_shift_options_shift_dates is not None: + data["date_shift_options[shift_dates]"] = date_shift_options_shift_dates + + # OPTIONAL - date_shift_options[old_start_date] + """The original start date of the source content/course""" + if date_shift_options_old_start_date is not None: + data["date_shift_options[old_start_date]"] = date_shift_options_old_start_date + + # OPTIONAL - date_shift_options[old_end_date] + """The original end date of the source content/course""" + if date_shift_options_old_end_date is not None: + data["date_shift_options[old_end_date]"] = date_shift_options_old_end_date + + # OPTIONAL - date_shift_options[new_start_date] + """The new start date for the content/course""" + if date_shift_options_new_start_date is not None: + data["date_shift_options[new_start_date]"] = date_shift_options_new_start_date + + # OPTIONAL - date_shift_options[new_end_date] + """The new end date for the source content/course""" + if date_shift_options_new_end_date is not None: + data["date_shift_options[new_end_date]"] = date_shift_options_new_end_date + + # OPTIONAL - date_shift_options[day_substitutions][X] + """Move anything scheduled for day 'X' to the specified day. (0-Sunday, + 1-Monday, 2-Tuesday, 3-Wednesday, 4-Thursday, 5-Friday, 6-Saturday)""" + if date_shift_options_day_substitutions_X is not None: + data["date_shift_options[day_substitutions][X]"] = date_shift_options_day_substitutions_X + + # OPTIONAL - date_shift_options[remove_dates] + """Whether to remove dates in the copied course. Cannot be used + in conjunction with *shift_dates*.""" + if date_shift_options_remove_dates is not None: + data["date_shift_options[remove_dates]"] = date_shift_options_remove_dates + + self.logger.debug("POST /api/v1/courses/{course_id}/content_migrations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/content_migrations".format(**path), data=data, params=params, single_item=True) + + def create_content_migration_groups(self, group_id, migration_type, date_shift_options_day_substitutions_X=None, date_shift_options_new_end_date=None, date_shift_options_new_start_date=None, date_shift_options_old_end_date=None, date_shift_options_old_start_date=None, date_shift_options_remove_dates=None, date_shift_options_shift_dates=None, pre_attachment_*=None, pre_attachment_name=None, settings_file_url=None, settings_folder_id=None, settings_overwrite_quizzes=None, settings_question_bank_id=None, settings_question_bank_name=None, settings_source_course_id=None): + """ + Create a content migration. + + Create a content migration. If the migration requires a file to be uploaded + the actual processing of the file will start once the file upload process is completed. + File uploading works as described in the {file:file_uploads.html File Upload Documentation} + except that the values are set on a *pre_attachment* sub-hash. + + For migrations that don't require a file to be uploaded, like course copy, the + processing will begin as soon as the migration is created. + + You can use the {api:ProgressController#show Progress API} to track the + progress of the migration. The migration's progress is linked to with the + _progress_url_ value. + + The two general workflows are: + + If no file upload is needed: + + 1. POST to create + 2. Use the {api:ProgressController#show Progress} specified in _progress_url_ to monitor progress + + For file uploading: + + 1. POST to create with file info in *pre_attachment* + 2. Do {file:file_uploads.html file upload processing} using the data in the *pre_attachment* data + 3. {api:ContentMigrationsController#show GET} the ContentMigration + 4. Use the {api:ProgressController#show Progress} specified in _progress_url_ to monitor progress + + (required if doing .zip file upload) + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - migration_type + """The type of the migration. Use the + {api:ContentMigrationsController#available_migrators Migrator} endpoint to + see all available migrators. Default allowed values: + canvas_cartridge_importer, common_cartridge_importer, + course_copy_importer, zip_file_importer, qti_converter, moodle_converter""" + data["migration_type"] = migration_type + + # OPTIONAL - pre_attachment[name] + """Required if uploading a file. This is the first step in uploading a file + to the content migration. See the {file:file_uploads.html File Upload + Documentation} for details on the file upload workflow.""" + if pre_attachment_name is not None: + data["pre_attachment[name]"] = pre_attachment_name + + # OPTIONAL - pre_attachment[*] + """Other file upload properties, See {file:file_uploads.html File Upload + Documentation}""" + if pre_attachment_* is not None: + data["pre_attachment[*]"] = pre_attachment_* + + # OPTIONAL - settings[file_url] + """A URL to download the file from. Must not require authentication.""" + if settings_file_url is not None: + data["settings[file_url]"] = settings_file_url + + # OPTIONAL - settings[source_course_id] + """The course to copy from for a course copy migration. (required if doing + course copy)""" + if settings_source_course_id is not None: + data["settings[source_course_id]"] = settings_source_course_id + + # OPTIONAL - settings[folder_id] + """The folder to unzip the .zip file into for a zip_file_import.""" + if settings_folder_id is not None: + data["settings[folder_id]"] = settings_folder_id + + # OPTIONAL - settings[overwrite_quizzes] + """Whether to overwrite quizzes with the same identifiers between content + packages.""" + if settings_overwrite_quizzes is not None: + data["settings[overwrite_quizzes]"] = settings_overwrite_quizzes + + # OPTIONAL - settings[question_bank_id] + """The existing question bank ID to import questions into if not specified in + the content package.""" + if settings_question_bank_id is not None: + data["settings[question_bank_id]"] = settings_question_bank_id + + # OPTIONAL - settings[question_bank_name] + """The question bank to import questions into if not specified in the content + package, if both bank id and name are set, id will take precedence.""" + if settings_question_bank_name is not None: + data["settings[question_bank_name]"] = settings_question_bank_name + + # OPTIONAL - date_shift_options[shift_dates] + """Whether to shift dates in the copied course""" + if date_shift_options_shift_dates is not None: + data["date_shift_options[shift_dates]"] = date_shift_options_shift_dates + + # OPTIONAL - date_shift_options[old_start_date] + """The original start date of the source content/course""" + if date_shift_options_old_start_date is not None: + data["date_shift_options[old_start_date]"] = date_shift_options_old_start_date + + # OPTIONAL - date_shift_options[old_end_date] + """The original end date of the source content/course""" + if date_shift_options_old_end_date is not None: + data["date_shift_options[old_end_date]"] = date_shift_options_old_end_date + + # OPTIONAL - date_shift_options[new_start_date] + """The new start date for the content/course""" + if date_shift_options_new_start_date is not None: + data["date_shift_options[new_start_date]"] = date_shift_options_new_start_date + + # OPTIONAL - date_shift_options[new_end_date] + """The new end date for the source content/course""" + if date_shift_options_new_end_date is not None: + data["date_shift_options[new_end_date]"] = date_shift_options_new_end_date + + # OPTIONAL - date_shift_options[day_substitutions][X] + """Move anything scheduled for day 'X' to the specified day. (0-Sunday, + 1-Monday, 2-Tuesday, 3-Wednesday, 4-Thursday, 5-Friday, 6-Saturday)""" + if date_shift_options_day_substitutions_X is not None: + data["date_shift_options[day_substitutions][X]"] = date_shift_options_day_substitutions_X + + # OPTIONAL - date_shift_options[remove_dates] + """Whether to remove dates in the copied course. Cannot be used + in conjunction with *shift_dates*.""" + if date_shift_options_remove_dates is not None: + data["date_shift_options[remove_dates]"] = date_shift_options_remove_dates + + self.logger.debug("POST /api/v1/groups/{group_id}/content_migrations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/content_migrations".format(**path), data=data, params=params, single_item=True) + + def create_content_migration_users(self, user_id, migration_type, date_shift_options_day_substitutions_X=None, date_shift_options_new_end_date=None, date_shift_options_new_start_date=None, date_shift_options_old_end_date=None, date_shift_options_old_start_date=None, date_shift_options_remove_dates=None, date_shift_options_shift_dates=None, pre_attachment_*=None, pre_attachment_name=None, settings_file_url=None, settings_folder_id=None, settings_overwrite_quizzes=None, settings_question_bank_id=None, settings_question_bank_name=None, settings_source_course_id=None): + """ + Create a content migration. + + Create a content migration. If the migration requires a file to be uploaded + the actual processing of the file will start once the file upload process is completed. + File uploading works as described in the {file:file_uploads.html File Upload Documentation} + except that the values are set on a *pre_attachment* sub-hash. + + For migrations that don't require a file to be uploaded, like course copy, the + processing will begin as soon as the migration is created. + + You can use the {api:ProgressController#show Progress API} to track the + progress of the migration. The migration's progress is linked to with the + _progress_url_ value. + + The two general workflows are: + + If no file upload is needed: + + 1. POST to create + 2. Use the {api:ProgressController#show Progress} specified in _progress_url_ to monitor progress + + For file uploading: + + 1. POST to create with file info in *pre_attachment* + 2. Do {file:file_uploads.html file upload processing} using the data in the *pre_attachment* data + 3. {api:ContentMigrationsController#show GET} the ContentMigration + 4. Use the {api:ProgressController#show Progress} specified in _progress_url_ to monitor progress + + (required if doing .zip file upload) + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - migration_type + """The type of the migration. Use the + {api:ContentMigrationsController#available_migrators Migrator} endpoint to + see all available migrators. Default allowed values: + canvas_cartridge_importer, common_cartridge_importer, + course_copy_importer, zip_file_importer, qti_converter, moodle_converter""" + data["migration_type"] = migration_type + + # OPTIONAL - pre_attachment[name] + """Required if uploading a file. This is the first step in uploading a file + to the content migration. See the {file:file_uploads.html File Upload + Documentation} for details on the file upload workflow.""" + if pre_attachment_name is not None: + data["pre_attachment[name]"] = pre_attachment_name + + # OPTIONAL - pre_attachment[*] + """Other file upload properties, See {file:file_uploads.html File Upload + Documentation}""" + if pre_attachment_* is not None: + data["pre_attachment[*]"] = pre_attachment_* + + # OPTIONAL - settings[file_url] + """A URL to download the file from. Must not require authentication.""" + if settings_file_url is not None: + data["settings[file_url]"] = settings_file_url + + # OPTIONAL - settings[source_course_id] + """The course to copy from for a course copy migration. (required if doing + course copy)""" + if settings_source_course_id is not None: + data["settings[source_course_id]"] = settings_source_course_id + + # OPTIONAL - settings[folder_id] + """The folder to unzip the .zip file into for a zip_file_import.""" + if settings_folder_id is not None: + data["settings[folder_id]"] = settings_folder_id + + # OPTIONAL - settings[overwrite_quizzes] + """Whether to overwrite quizzes with the same identifiers between content + packages.""" + if settings_overwrite_quizzes is not None: + data["settings[overwrite_quizzes]"] = settings_overwrite_quizzes + + # OPTIONAL - settings[question_bank_id] + """The existing question bank ID to import questions into if not specified in + the content package.""" + if settings_question_bank_id is not None: + data["settings[question_bank_id]"] = settings_question_bank_id + + # OPTIONAL - settings[question_bank_name] + """The question bank to import questions into if not specified in the content + package, if both bank id and name are set, id will take precedence.""" + if settings_question_bank_name is not None: + data["settings[question_bank_name]"] = settings_question_bank_name + + # OPTIONAL - date_shift_options[shift_dates] + """Whether to shift dates in the copied course""" + if date_shift_options_shift_dates is not None: + data["date_shift_options[shift_dates]"] = date_shift_options_shift_dates + + # OPTIONAL - date_shift_options[old_start_date] + """The original start date of the source content/course""" + if date_shift_options_old_start_date is not None: + data["date_shift_options[old_start_date]"] = date_shift_options_old_start_date + + # OPTIONAL - date_shift_options[old_end_date] + """The original end date of the source content/course""" + if date_shift_options_old_end_date is not None: + data["date_shift_options[old_end_date]"] = date_shift_options_old_end_date + + # OPTIONAL - date_shift_options[new_start_date] + """The new start date for the content/course""" + if date_shift_options_new_start_date is not None: + data["date_shift_options[new_start_date]"] = date_shift_options_new_start_date + + # OPTIONAL - date_shift_options[new_end_date] + """The new end date for the source content/course""" + if date_shift_options_new_end_date is not None: + data["date_shift_options[new_end_date]"] = date_shift_options_new_end_date + + # OPTIONAL - date_shift_options[day_substitutions][X] + """Move anything scheduled for day 'X' to the specified day. (0-Sunday, + 1-Monday, 2-Tuesday, 3-Wednesday, 4-Thursday, 5-Friday, 6-Saturday)""" + if date_shift_options_day_substitutions_X is not None: + data["date_shift_options[day_substitutions][X]"] = date_shift_options_day_substitutions_X + + # OPTIONAL - date_shift_options[remove_dates] + """Whether to remove dates in the copied course. Cannot be used + in conjunction with *shift_dates*.""" + if date_shift_options_remove_dates is not None: + data["date_shift_options[remove_dates]"] = date_shift_options_remove_dates + + self.logger.debug("POST /api/v1/users/{user_id}/content_migrations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/{user_id}/content_migrations".format(**path), data=data, params=params, single_item=True) + + def update_content_migration_accounts(self, id, account_id): + """ + Update a content migration. + + Update a content migration. Takes same arguments as create except that you + can't change the migration type. However, changing most settings after the + migration process has started will not do anything. Generally updating the + content migration will be used when there is a file upload problem. If the + first upload has a problem you can supply new _pre_attachment_ values to + start the process again. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/accounts/{account_id}/content_migrations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/content_migrations/{id}".format(**path), data=data, params=params, single_item=True) + + def update_content_migration_courses(self, id, course_id): + """ + Update a content migration. + + Update a content migration. Takes same arguments as create except that you + can't change the migration type. However, changing most settings after the + migration process has started will not do anything. Generally updating the + content migration will be used when there is a file upload problem. If the + first upload has a problem you can supply new _pre_attachment_ values to + start the process again. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/courses/{course_id}/content_migrations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/content_migrations/{id}".format(**path), data=data, params=params, single_item=True) + + def update_content_migration_groups(self, id, group_id): + """ + Update a content migration. + + Update a content migration. Takes same arguments as create except that you + can't change the migration type. However, changing most settings after the + migration process has started will not do anything. Generally updating the + content migration will be used when there is a file upload problem. If the + first upload has a problem you can supply new _pre_attachment_ values to + start the process again. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/groups/{group_id}/content_migrations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/content_migrations/{id}".format(**path), data=data, params=params, single_item=True) + + def update_content_migration_users(self, id, user_id): + """ + Update a content migration. + + Update a content migration. Takes same arguments as create except that you + can't change the migration type. However, changing most settings after the + migration process has started will not do anything. Generally updating the + content migration will be used when there is a file upload problem. If the + first upload has a problem you can supply new _pre_attachment_ values to + start the process again. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/users/{user_id}/content_migrations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{user_id}/content_migrations/{id}".format(**path), data=data, params=params, single_item=True) + + def list_migration_systems_accounts(self, account_id): + """ + List Migration Systems. + + Lists the currently available migration types. These values may change. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/content_migrations/migrators with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/content_migrations/migrators".format(**path), data=data, params=params, all_pages=True) + + def list_migration_systems_courses(self, course_id): + """ + List Migration Systems. + + Lists the currently available migration types. These values may change. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/content_migrations/migrators with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/content_migrations/migrators".format(**path), data=data, params=params, all_pages=True) + + def list_migration_systems_groups(self, group_id): + """ + List Migration Systems. + + Lists the currently available migration types. These values may change. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/content_migrations/migrators with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/content_migrations/migrators".format(**path), data=data, params=params, all_pages=True) + + def list_migration_systems_users(self, user_id): + """ + List Migration Systems. + + Lists the currently available migration types. These values may change. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/content_migrations/migrators with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/content_migrations/migrators".format(**path), data=data, params=params, all_pages=True) + + +class Contentmigration(BaseModel): + """Contentmigration Model.""" + + def __init__(self, progress_url=None, user_id=None, workflow_state=None, migration_type_title=None, finished_at=None, migration_type=None, migration_issues_url=None, pre_attachment=None, attachment=None, started_at=None, id=None): + """Init method for Contentmigration class.""" + self._progress_url = progress_url + self._user_id = user_id + self._workflow_state = workflow_state + self._migration_type_title = migration_type_title + self._finished_at = finished_at + self._migration_type = migration_type + self._migration_issues_url = migration_issues_url + self._pre_attachment = pre_attachment + self._attachment = attachment + self._started_at = started_at + self._id = id + + self.logger = logging.getLogger('pycanvas.Contentmigration') + + @property + def progress_url(self): + """The api endpoint for polling the current progress.""" + return self._progress_url + + @progress_url.setter + def progress_url(self, value): + """Setter for progress_url property.""" + self.logger.warn("Setting values on progress_url will NOT update the remote Canvas instance.") + self._progress_url = value + + @property + def user_id(self): + """The user who started the migration.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def workflow_state(self): + """Current state of the content migration: pre_processing, pre_processed, running, waiting_for_select, completed, failed.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def migration_type_title(self): + """the name of the content migration type.""" + return self._migration_type_title + + @migration_type_title.setter + def migration_type_title(self, value): + """Setter for migration_type_title property.""" + self.logger.warn("Setting values on migration_type_title will NOT update the remote Canvas instance.") + self._migration_type_title = value + + @property + def finished_at(self): + """timestamp.""" + return self._finished_at + + @finished_at.setter + def finished_at(self, value): + """Setter for finished_at property.""" + self.logger.warn("Setting values on finished_at will NOT update the remote Canvas instance.") + self._finished_at = value + + @property + def migration_type(self): + """the type of content migration.""" + return self._migration_type + + @migration_type.setter + def migration_type(self, value): + """Setter for migration_type property.""" + self.logger.warn("Setting values on migration_type will NOT update the remote Canvas instance.") + self._migration_type = value + + @property + def migration_issues_url(self): + """API url to the content migration's issues.""" + return self._migration_issues_url + + @migration_issues_url.setter + def migration_issues_url(self, value): + """Setter for migration_issues_url property.""" + self.logger.warn("Setting values on migration_issues_url will NOT update the remote Canvas instance.") + self._migration_issues_url = value + + @property + def pre_attachment(self): + """file uploading data, see {file:file_uploads.html File Upload Documentation} for file upload workflow This works a little differently in that all the file data is in the pre_attachment hash if there is no upload_url then there was an attachment pre-processing error, the error message will be in the message key This data will only be here after a create or update call.""" + return self._pre_attachment + + @pre_attachment.setter + def pre_attachment(self, value): + """Setter for pre_attachment property.""" + self.logger.warn("Setting values on pre_attachment will NOT update the remote Canvas instance.") + self._pre_attachment = value + + @property + def attachment(self): + """attachment api object for the uploaded file may not be present for all migrations.""" + return self._attachment + + @attachment.setter + def attachment(self, value): + """Setter for attachment property.""" + self.logger.warn("Setting values on attachment will NOT update the remote Canvas instance.") + self._attachment = value + + @property + def started_at(self): + """timestamp.""" + return self._started_at + + @started_at.setter + def started_at(self, value): + """Setter for started_at property.""" + self.logger.warn("Setting values on started_at will NOT update the remote Canvas instance.") + self._started_at = value + + @property + def id(self): + """the unique identifier for the migration.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Migrationissue(BaseModel): + """Migrationissue Model.""" + + def __init__(self, error_message=None, description=None, workflow_state=None, created_at=None, fix_issue_html_url=None, updated_at=None, issue_type=None, content_migration_url=None, error_report_html_url=None, id=None): + """Init method for Migrationissue class.""" + self._error_message = error_message + self._description = description + self._workflow_state = workflow_state + self._created_at = created_at + self._fix_issue_html_url = fix_issue_html_url + self._updated_at = updated_at + self._issue_type = issue_type + self._content_migration_url = content_migration_url + self._error_report_html_url = error_report_html_url + self._id = id + + self.logger = logging.getLogger('pycanvas.Migrationissue') + + @property + def error_message(self): + """Site administrator error message (If the requesting user has permissions).""" + return self._error_message + + @error_message.setter + def error_message(self, value): + """Setter for error_message property.""" + self.logger.warn("Setting values on error_message will NOT update the remote Canvas instance.") + self._error_message = value + + @property + def description(self): + """Description of the issue for the end-user.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def workflow_state(self): + """Current state of the issue: active, resolved.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def created_at(self): + """timestamp.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def fix_issue_html_url(self): + """HTML Url to the Canvas page to investigate the issue.""" + return self._fix_issue_html_url + + @fix_issue_html_url.setter + def fix_issue_html_url(self, value): + """Setter for fix_issue_html_url property.""" + self.logger.warn("Setting values on fix_issue_html_url will NOT update the remote Canvas instance.") + self._fix_issue_html_url = value + + @property + def updated_at(self): + """timestamp.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def issue_type(self): + """Severity of the issue: todo, warning, error.""" + return self._issue_type + + @issue_type.setter + def issue_type(self, value): + """Setter for issue_type property.""" + self.logger.warn("Setting values on issue_type will NOT update the remote Canvas instance.") + self._issue_type = value + + @property + def content_migration_url(self): + """API url to the content migration.""" + return self._content_migration_url + + @content_migration_url.setter + def content_migration_url(self, value): + """Setter for content_migration_url property.""" + self.logger.warn("Setting values on content_migration_url will NOT update the remote Canvas instance.") + self._content_migration_url = value + + @property + def error_report_html_url(self): + """Link to a Canvas error report if present (If the requesting user has permissions).""" + return self._error_report_html_url + + @error_report_html_url.setter + def error_report_html_url(self, value): + """Setter for error_report_html_url property.""" + self.logger.warn("Setting values on error_report_html_url will NOT update the remote Canvas instance.") + self._error_report_html_url = value + + @property + def id(self): + """the unique identifier for the issue.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Migrator(BaseModel): + """Migrator Model.""" + + def __init__(self, required_settings=None, type=None, name=None, requires_file_upload=None): + """Init method for Migrator class.""" + self._required_settings = required_settings + self._type = type + self._name = name + self._requires_file_upload = requires_file_upload + + self.logger = logging.getLogger('pycanvas.Migrator') + + @property + def required_settings(self): + """A list of fields this system requires.""" + return self._required_settings + + @required_settings.setter + def required_settings(self, value): + """Setter for required_settings property.""" + self.logger.warn("Setting values on required_settings will NOT update the remote Canvas instance.") + self._required_settings = value + + @property + def type(self): + """The value to pass to the create endpoint.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def name(self): + """Description of the package type expected.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def requires_file_upload(self): + """Whether this endpoint requires a file upload.""" + return self._requires_file_upload + + @requires_file_upload.setter + def requires_file_upload(self, value): + """Setter for requires_file_upload property.""" + self.logger.warn("Setting values on requires_file_upload will NOT update the remote Canvas instance.") + self._requires_file_upload = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/conversations.py b/venv/Lib/site-packages/pycanvas/apis/conversations.py new file mode 100644 index 00000000..2ceb2134 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/conversations.py @@ -0,0 +1,698 @@ +"""Conversations API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class ConversationsAPI(BaseCanvasAPI): + """Conversations API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for ConversationsAPI.""" + super(ConversationsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.ConversationsAPI") + + def list_conversations(self, filter=None, filter_mode=None, include=None, include_all_conversation_ids=None, interleave_submissions=None, scope=None): + """ + List conversations. + + Returns the list of conversations for the current user, most recent ones first. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - scope + """When set, only return conversations of the specified type. For example, + set to "unread" to return only conversations that haven't been read. + The default behavior is to return all non-archived conversations (i.e. + read and unread).""" + if scope is not None: + self._validate_enum(scope, ["unread", "starred", "archived"]) + params["scope"] = scope + + # OPTIONAL - filter + """When set, only return conversations for the specified courses, groups + or users. The id should be prefixed with its type, e.g. "user_123" or + "course_456". Can be an array (by setting "filter[]") or single value + (by setting "filter")""" + if filter is not None: + params["filter"] = filter + + # OPTIONAL - filter_mode + """When filter[] contains multiple filters, combine them with this mode, + filtering conversations that at have at least all of the contexts ("and") + or at least one of the contexts ("or")""" + if filter_mode is not None: + self._validate_enum(filter_mode, ["and", "or", "default or"]) + params["filter_mode"] = filter_mode + + # OPTIONAL - interleave_submissions + """(Obsolete) Submissions are no + longer linked to conversations. This parameter is ignored.""" + if interleave_submissions is not None: + params["interleave_submissions"] = interleave_submissions + + # OPTIONAL - include_all_conversation_ids + """Default is false. If true, + the top-level element of the response will be an object rather than + an array, and will have the keys "conversations" which will contain the + paged conversation data, and "conversation_ids" which will contain the + ids of all conversations under this scope/filter in the same order.""" + if include_all_conversation_ids is not None: + params["include_all_conversation_ids"] = include_all_conversation_ids + + # OPTIONAL - include + """"participant_avatars":: Optionally include an "avatar_url" key for each user participanting in the conversation""" + if include is not None: + self._validate_enum(include, ["participant_avatars"]) + params["include"] = include + + self.logger.debug("GET /api/v1/conversations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/conversations".format(**path), data=data, params=params, all_pages=True) + + def create_conversation(self, body, recipients, attachment_ids=None, context_code=None, filter=None, filter_mode=None, group_conversation=None, media_comment_id=None, media_comment_type=None, mode=None, scope=None, subject=None, user_note=None): + """ + Create a conversation. + + Create a new conversation with one or more recipients. If there is already + an existing private conversation with the given recipients, it will be + reused. + """ + path = {} + data = {} + params = {} + + # REQUIRED - recipients + """An array of recipient ids. These may be user ids or course/group ids + prefixed with "course_" or "group_" respectively, e.g. + recipients[]=1&recipients[]=2&recipients[]=course_3""" + data["recipients"] = recipients + + # OPTIONAL - subject + """The subject of the conversation. This is ignored when reusing a + conversation. Maximum length is 255 characters.""" + if subject is not None: + data["subject"] = subject + + # REQUIRED - body + """The message to be sent""" + data["body"] = body + + # OPTIONAL - group_conversation + """Defaults to false. If true, this will be a group conversation (i.e. all + recipients may see all messages and replies). If false, individual private + conversations will be started with each recipient. Must be set false if the + number of recipients is over the set maximum (default is 100).""" + if group_conversation is not None: + data["group_conversation"] = group_conversation + + # OPTIONAL - attachment_ids + """An array of attachments ids. These must be files that have been previously + uploaded to the sender's "conversation attachments" folder.""" + if attachment_ids is not None: + data["attachment_ids"] = attachment_ids + + # OPTIONAL - media_comment_id + """Media comment id of an audio of video file to be associated with this + message.""" + if media_comment_id is not None: + data["media_comment_id"] = media_comment_id + + # OPTIONAL - media_comment_type + """Type of the associated media file""" + if media_comment_type is not None: + self._validate_enum(media_comment_type, ["audio", "video"]) + data["media_comment_type"] = media_comment_type + + # OPTIONAL - user_note + """Will add a faculty journal entry for each recipient as long as the user + making the api call has permission, the recipient is a student and + faculty journals are enabled in the account.""" + if user_note is not None: + data["user_note"] = user_note + + # OPTIONAL - mode + """Determines whether the messages will be created/sent synchronously or + asynchronously. Defaults to sync, and this option is ignored if this is a + group conversation or there is just one recipient (i.e. it must be a bulk + private message). When sent async, the response will be an empty array + (batch status can be queried via the {api:ConversationsController#batches batches API})""" + if mode is not None: + self._validate_enum(mode, ["sync", "async"]) + data["mode"] = mode + + # OPTIONAL - scope + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if scope is not None: + self._validate_enum(scope, ["unread", "starred", "archived"]) + data["scope"] = scope + + # OPTIONAL - filter + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if filter is not None: + data["filter"] = filter + + # OPTIONAL - filter_mode + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if filter_mode is not None: + self._validate_enum(filter_mode, ["and", "or", "default or"]) + data["filter_mode"] = filter_mode + + # OPTIONAL - context_code + """The course or group that is the context for this conversation. Same format + as courses or groups in the recipients argument.""" + if context_code is not None: + data["context_code"] = context_code + + self.logger.debug("POST /api/v1/conversations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/conversations".format(**path), data=data, params=params, no_data=True) + + def get_running_batches(self): + """ + Get running batches. + + Returns any currently running conversation batches for the current user. + Conversation batches are created when a bulk private message is sent + asynchronously (see the mode argument to the {api:ConversationsController#create create API action}). + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/conversations/batches with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/conversations/batches".format(**path), data=data, params=params, no_data=True) + + def get_single_conversation(self, id, auto_mark_as_read=None, filter=None, filter_mode=None, interleave_submissions=None, scope=None): + """ + Get a single conversation. + + Returns information for a single conversation for the current user. Response includes all + fields that are present in the list/index action as well as messages + and extended participant information. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - interleave_submissions + """(Obsolete) Submissions are no + longer linked to conversations. This parameter is ignored.""" + if interleave_submissions is not None: + params["interleave_submissions"] = interleave_submissions + + # OPTIONAL - scope + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if scope is not None: + self._validate_enum(scope, ["unread", "starred", "archived"]) + params["scope"] = scope + + # OPTIONAL - filter + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if filter is not None: + params["filter"] = filter + + # OPTIONAL - filter_mode + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if filter_mode is not None: + self._validate_enum(filter_mode, ["and", "or", "default or"]) + params["filter_mode"] = filter_mode + + # OPTIONAL - auto_mark_as_read + """Default true. If true, unread + conversations will be automatically marked as read. This will default + to false in a future API release, so clients should explicitly send + true if that is the desired behavior.""" + if auto_mark_as_read is not None: + params["auto_mark_as_read"] = auto_mark_as_read + + self.logger.debug("GET /api/v1/conversations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/conversations/{id}".format(**path), data=data, params=params, no_data=True) + + def edit_conversation(self, id, conversation_starred=None, conversation_subscribed=None, conversation_workflow_state=None, filter=None, filter_mode=None, scope=None): + """ + Edit a conversation. + + Updates attributes for a single conversation. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - conversation[workflow_state] + """Change the state of this conversation""" + if conversation_workflow_state is not None: + self._validate_enum(conversation_workflow_state, ["read", "unread", "archived"]) + data["conversation[workflow_state]"] = conversation_workflow_state + + # OPTIONAL - conversation[subscribed] + """Toggle the current user's subscription to the conversation (only valid for + group conversations). If unsubscribed, the user will still have access to + the latest messages, but the conversation won't be automatically flagged + as unread, nor will it jump to the top of the inbox.""" + if conversation_subscribed is not None: + data["conversation[subscribed]"] = conversation_subscribed + + # OPTIONAL - conversation[starred] + """Toggle the starred state of the current user's view of the conversation.""" + if conversation_starred is not None: + data["conversation[starred]"] = conversation_starred + + # OPTIONAL - scope + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if scope is not None: + self._validate_enum(scope, ["unread", "starred", "archived"]) + data["scope"] = scope + + # OPTIONAL - filter + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if filter is not None: + data["filter"] = filter + + # OPTIONAL - filter_mode + """Used when generating "visible" in the API response. See the explanation + under the {api:ConversationsController#index index API action}""" + if filter_mode is not None: + self._validate_enum(filter_mode, ["and", "or", "default or"]) + data["filter_mode"] = filter_mode + + self.logger.debug("PUT /api/v1/conversations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/conversations/{id}".format(**path), data=data, params=params, no_data=True) + + def mark_all_as_read(self): + """ + Mark all as read. + + Mark all conversations as read. + """ + path = {} + data = {} + params = {} + + self.logger.debug("POST /api/v1/conversations/mark_all_as_read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/conversations/mark_all_as_read".format(**path), data=data, params=params, no_data=True) + + def delete_conversation(self, id): + """ + Delete a conversation. + + Delete this conversation and its messages. Note that this only deletes + this user's view of the conversation. + + Response includes same fields as UPDATE action + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/conversations/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/conversations/{id}".format(**path), data=data, params=params, no_data=True) + + def add_recipients(self, id, recipients): + """ + Add recipients. + + Add recipients to an existing group conversation. Response is similar to + the GET/show action, except that only includes the + latest message (e.g. "joe was added to the conversation by bob") + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - recipients + """An array of recipient ids. These may be user ids or course/group ids + prefixed with "course_" or "group_" respectively, e.g. + recipients[]=1&recipients[]=2&recipients[]=course_3""" + data["recipients"] = recipients + + self.logger.debug("POST /api/v1/conversations/{id}/add_recipients with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/conversations/{id}/add_recipients".format(**path), data=data, params=params, no_data=True) + + def add_message(self, id, body, attachment_ids=None, included_messages=None, media_comment_id=None, media_comment_type=None, recipients=None, user_note=None): + """ + Add a message. + + Add a message to an existing conversation. Response is similar to the + GET/show action, except that only includes the + latest message (i.e. what we just sent) + + An array of user ids. Defaults to all of the current conversation + recipients. To explicitly send a message to no other recipients, + this array should consist of the logged-in user id. + + An array of message ids from this conversation to send to recipients + of the new message. Recipients who already had a copy of included + messages will not be affected. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - body + """The message to be sent.""" + data["body"] = body + + # OPTIONAL - attachment_ids + """An array of attachments ids. These must be files that have been previously + uploaded to the sender's "conversation attachments" folder.""" + if attachment_ids is not None: + data["attachment_ids"] = attachment_ids + + # OPTIONAL - media_comment_id + """Media comment id of an audio of video file to be associated with this + message.""" + if media_comment_id is not None: + data["media_comment_id"] = media_comment_id + + # OPTIONAL - media_comment_type + """Type of the associated media file.""" + if media_comment_type is not None: + self._validate_enum(media_comment_type, ["audio", "video"]) + data["media_comment_type"] = media_comment_type + + # OPTIONAL - recipients + """no description""" + if recipients is not None: + data["recipients"] = recipients + + # OPTIONAL - included_messages + """no description""" + if included_messages is not None: + data["included_messages"] = included_messages + + # OPTIONAL - user_note + """Will add a faculty journal entry for each recipient as long as the user + making the api call has permission, the recipient is a student and + faculty journals are enabled in the account.""" + if user_note is not None: + data["user_note"] = user_note + + self.logger.debug("POST /api/v1/conversations/{id}/add_message with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/conversations/{id}/add_message".format(**path), data=data, params=params, no_data=True) + + def delete_message(self, id, remove): + """ + Delete a message. + + Delete messages from this conversation. Note that this only affects this + user's view of the conversation. If all messages are deleted, the + conversation will be as well (equivalent to DELETE) + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - remove + """Array of message ids to be deleted""" + data["remove"] = remove + + self.logger.debug("POST /api/v1/conversations/{id}/remove_messages with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/conversations/{id}/remove_messages".format(**path), data=data, params=params, no_data=True) + + def batch_update_conversations(self, event, conversation_ids): + """ + Batch update conversations. + + Perform a change on a set of conversations. Operates asynchronously; use the {api:ProgressController#show progress endpoint} + to query the status of an operation. + """ + path = {} + data = {} + params = {} + + # REQUIRED - conversation_ids + """List of conversations to update. Limited to 500 conversations.""" + data["conversation_ids"] = conversation_ids + + # REQUIRED - event + """The action to take on each conversation.""" + self._validate_enum(event, ["mark_as_read", "mark_as_unread", "star", "unstar", "archive", "destroy"]) + data["event"] = event + + self.logger.debug("PUT /api/v1/conversations with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/conversations".format(**path), data=data, params=params, single_item=True) + + def find_recipients(self): + """ + Find recipients. + + Deprecated, see the {api:SearchController#recipients Find recipients endpoint} in the Search API + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/conversations/find_recipients with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/conversations/find_recipients".format(**path), data=data, params=params, no_data=True) + + def unread_count(self): + """ + Unread count. + + Get the number of unread conversations for the current user + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/conversations/unread_count with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/conversations/unread_count".format(**path), data=data, params=params, no_data=True) + + +class Conversation(BaseModel): + """Conversation Model.""" + + def __init__(self, start_at=None, subscribed=None, workflow_state=None, last_message=None, visible=None, participants=None, private=None, properties=None, message_count=None, audience_contexts=None, audience=None, avatar_url=None, context_name=None, starred=None, id=None, subject=None): + """Init method for Conversation class.""" + self._start_at = start_at + self._subscribed = subscribed + self._workflow_state = workflow_state + self._last_message = last_message + self._visible = visible + self._participants = participants + self._private = private + self._properties = properties + self._message_count = message_count + self._audience_contexts = audience_contexts + self._audience = audience + self._avatar_url = avatar_url + self._context_name = context_name + self._starred = starred + self._id = id + self._subject = subject + + self.logger = logging.getLogger('pycanvas.Conversation') + + @property + def start_at(self): + """the date and time at which the last message was sent.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def subscribed(self): + """whether the current user is subscribed to the conversation.""" + return self._subscribed + + @subscribed.setter + def subscribed(self, value): + """Setter for subscribed property.""" + self.logger.warn("Setting values on subscribed will NOT update the remote Canvas instance.") + self._subscribed = value + + @property + def workflow_state(self): + """The current state of the conversation (read, unread or archived).""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def last_message(self): + """A <=100 character preview from the most recent message.""" + return self._last_message + + @last_message.setter + def last_message(self, value): + """Setter for last_message property.""" + self.logger.warn("Setting values on last_message will NOT update the remote Canvas instance.") + self._last_message = value + + @property + def visible(self): + """indicates whether the conversation is visible under the current scope and filter. This attribute is always true in the index API response, and is primarily useful in create/update responses so that you can know if the record should be displayed in the UI. The default scope is assumed, unless a scope or filter is passed to the create/update API call.""" + return self._visible + + @visible.setter + def visible(self, value): + """Setter for visible property.""" + self.logger.warn("Setting values on visible will NOT update the remote Canvas instance.") + self._visible = value + + @property + def participants(self): + """Array of users (id, name) participating in the conversation. Includes current user.""" + return self._participants + + @participants.setter + def participants(self, value): + """Setter for participants property.""" + self.logger.warn("Setting values on participants will NOT update the remote Canvas instance.") + self._participants = value + + @property + def private(self): + """whether the conversation is private.""" + return self._private + + @private.setter + def private(self, value): + """Setter for private property.""" + self.logger.warn("Setting values on private will NOT update the remote Canvas instance.") + self._private = value + + @property + def properties(self): + """Additional conversation flags (last_author, attachments, media_objects). Each listed property means the flag is set to true (i.e. the current user is the most recent author, there are attachments, or there are media objects).""" + return self._properties + + @properties.setter + def properties(self, value): + """Setter for properties property.""" + self.logger.warn("Setting values on properties will NOT update the remote Canvas instance.") + self._properties = value + + @property + def message_count(self): + """the number of messages in the conversation.""" + return self._message_count + + @message_count.setter + def message_count(self, value): + """Setter for message_count property.""" + self.logger.warn("Setting values on message_count will NOT update the remote Canvas instance.") + self._message_count = value + + @property + def audience_contexts(self): + """Most relevant shared contexts (courses and groups) between current user and other participants. If there is only one participant, it will also include that user's enrollment(s)/ membership type(s) in each course/group.""" + return self._audience_contexts + + @audience_contexts.setter + def audience_contexts(self, value): + """Setter for audience_contexts property.""" + self.logger.warn("Setting values on audience_contexts will NOT update the remote Canvas instance.") + self._audience_contexts = value + + @property + def audience(self): + """Array of user ids who are involved in the conversation, ordered by participation level, then alphabetical. Excludes current user, unless this is a monologue.""" + return self._audience + + @audience.setter + def audience(self, value): + """Setter for audience property.""" + self.logger.warn("Setting values on audience will NOT update the remote Canvas instance.") + self._audience = value + + @property + def avatar_url(self): + """URL to appropriate icon for this conversation (custom, individual or group avatar, depending on audience).""" + return self._avatar_url + + @avatar_url.setter + def avatar_url(self, value): + """Setter for avatar_url property.""" + self.logger.warn("Setting values on avatar_url will NOT update the remote Canvas instance.") + self._avatar_url = value + + @property + def context_name(self): + """Name of the course or group in which the conversation is occurring.""" + return self._context_name + + @context_name.setter + def context_name(self, value): + """Setter for context_name property.""" + self.logger.warn("Setting values on context_name will NOT update the remote Canvas instance.") + self._context_name = value + + @property + def starred(self): + """whether the conversation is starred.""" + return self._starred + + @starred.setter + def starred(self, value): + """Setter for starred property.""" + self.logger.warn("Setting values on starred will NOT update the remote Canvas instance.") + self._starred = value + + @property + def id(self): + """the unique identifier for the conversation.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def subject(self): + """the subject of the conversation.""" + return self._subject + + @subject.setter + def subject(self, value): + """Setter for subject property.""" + self.logger.warn("Setting values on subject will NOT update the remote Canvas instance.") + self._subject = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/course_audit_log.py b/venv/Lib/site-packages/pycanvas/apis/course_audit_log.py new file mode 100644 index 00000000..8f00cbb9 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/course_audit_log.py @@ -0,0 +1,335 @@ +"""CourseAuditLog API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class CourseAuditLogAPI(BaseCanvasAPI): + """CourseAuditLog API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for CourseAuditLogAPI.""" + super(CourseAuditLogAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.CourseAuditLogAPI") + + def query_by_course(self, course_id, end_time=None, start_time=None): + """ + Query by course. + + List course change events for a given course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want events.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want events.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/audit/course/courses/{course_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/audit/course/courses/{course_id}".format(**path), data=data, params=params, all_pages=True) + + +class Createdeventdata(BaseModel): + """Createdeventdata Model. + The created event data object returns all the fields that were set in the format of the following example. If a field does not exist it was not set. The value of each field changed is in the format of [:old_value, :new_value]. The created event type also includes a created_source field to specify what triggered the creation of the course.""" + + def __init__(self, is_public=None, conclude_at=None, start_at=None, name=None, created_source=None): + """Init method for Createdeventdata class.""" + self._is_public = is_public + self._conclude_at = conclude_at + self._start_at = start_at + self._name = name + self._created_source = created_source + + self.logger = logging.getLogger('pycanvas.Createdeventdata') + + @property + def is_public(self): + """is_public.""" + return self._is_public + + @is_public.setter + def is_public(self, value): + """Setter for is_public property.""" + self.logger.warn("Setting values on is_public will NOT update the remote Canvas instance.") + self._is_public = value + + @property + def conclude_at(self): + """conclude_at.""" + return self._conclude_at + + @conclude_at.setter + def conclude_at(self, value): + """Setter for conclude_at property.""" + self.logger.warn("Setting values on conclude_at will NOT update the remote Canvas instance.") + self._conclude_at = value + + @property + def start_at(self): + """start_at.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def name(self): + """name.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def created_source(self): + """The type of action that triggered the creation of the course.""" + return self._created_source + + @created_source.setter + def created_source(self, value): + """Setter for created_source property.""" + self.logger.warn("Setting values on created_source will NOT update the remote Canvas instance.") + self._created_source = value + + +class Courseevent(BaseModel): + """Courseevent Model.""" + + def __init__(self, event_source=None, event_type=None, links=None, created_at=None, id=None, event_data=None): + """Init method for Courseevent class.""" + self._event_source = event_source + self._event_type = event_type + self._links = links + self._created_at = created_at + self._id = id + self._event_data = event_data + + self.logger = logging.getLogger('pycanvas.Courseevent') + + @property + def event_source(self): + """Course event source depending on the event type. This will return a string containing the source of the event.""" + return self._event_source + + @event_source.setter + def event_source(self, value): + """Setter for event_source property.""" + self.logger.warn("Setting values on event_source will NOT update the remote Canvas instance.") + self._event_source = value + + @property + def event_type(self): + """Course event type The event type defines the type and schema of the event_data object.""" + return self._event_type + + @event_type.setter + def event_type(self, value): + """Setter for event_type property.""" + self.logger.warn("Setting values on event_type will NOT update the remote Canvas instance.") + self._event_type = value + + @property + def links(self): + """Jsonapi.org links.""" + return self._links + + @links.setter + def links(self, value): + """Setter for links property.""" + self.logger.warn("Setting values on links will NOT update the remote Canvas instance.") + self._links = value + + @property + def created_at(self): + """timestamp of the event.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def id(self): + """ID of the event.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def event_data(self): + """Course event data depending on the event type. This will return an object containing the relevant event data. An updated event type will return an UpdatedEventData object.""" + return self._event_data + + @event_data.setter + def event_data(self, value): + """Setter for event_data property.""" + self.logger.warn("Setting values on event_data will NOT update the remote Canvas instance.") + self._event_data = value + + +class Courseeventlink(BaseModel): + """Courseeventlink Model.""" + + def __init__(self, copied_from=None, course=None, sis_batch=None, user=None, copied_to=None, page_view=None): + """Init method for Courseeventlink class.""" + self._copied_from = copied_from + self._course = course + self._sis_batch = sis_batch + self._user = user + self._copied_to = copied_to + self._page_view = page_view + + self.logger = logging.getLogger('pycanvas.Courseeventlink') + + @property + def copied_from(self): + """ID of the course that this course was copied from. This is only included if the event_type is copied_from.""" + return self._copied_from + + @copied_from.setter + def copied_from(self, value): + """Setter for copied_from property.""" + self.logger.warn("Setting values on copied_from will NOT update the remote Canvas instance.") + self._copied_from = value + + @property + def course(self): + """ID of the course for the event.""" + return self._course + + @course.setter + def course(self, value): + """Setter for course property.""" + self.logger.warn("Setting values on course will NOT update the remote Canvas instance.") + self._course = value + + @property + def sis_batch(self): + """ID of the SIS batch that triggered the event.""" + return self._sis_batch + + @sis_batch.setter + def sis_batch(self, value): + """Setter for sis_batch property.""" + self.logger.warn("Setting values on sis_batch will NOT update the remote Canvas instance.") + self._sis_batch = value + + @property + def user(self): + """ID of the user for the event (who made the change).""" + return self._user + + @user.setter + def user(self, value): + """Setter for user property.""" + self.logger.warn("Setting values on user will NOT update the remote Canvas instance.") + self._user = value + + @property + def copied_to(self): + """ID of the course that this course was copied to. This is only included if the event_type is copied_to.""" + return self._copied_to + + @copied_to.setter + def copied_to(self, value): + """Setter for copied_to property.""" + self.logger.warn("Setting values on copied_to will NOT update the remote Canvas instance.") + self._copied_to = value + + @property + def page_view(self): + """ID of the page view during the event if it exists.""" + return self._page_view + + @page_view.setter + def page_view(self, value): + """Setter for page_view property.""" + self.logger.warn("Setting values on page_view will NOT update the remote Canvas instance.") + self._page_view = value + + +class Updatedeventdata(BaseModel): + """Updatedeventdata Model. + The updated event data object returns all the fields that have changed in the format of the following example. If a field does not exist it was not changed. The value is an array that contains the before and after values for the change as in [:old_value, :new_value].""" + + def __init__(self, is_public=None, conclude_at=None, start_at=None, name=None): + """Init method for Updatedeventdata class.""" + self._is_public = is_public + self._conclude_at = conclude_at + self._start_at = start_at + self._name = name + + self.logger = logging.getLogger('pycanvas.Updatedeventdata') + + @property + def is_public(self): + """is_public.""" + return self._is_public + + @is_public.setter + def is_public(self, value): + """Setter for is_public property.""" + self.logger.warn("Setting values on is_public will NOT update the remote Canvas instance.") + self._is_public = value + + @property + def conclude_at(self): + """conclude_at.""" + return self._conclude_at + + @conclude_at.setter + def conclude_at(self, value): + """Setter for conclude_at property.""" + self.logger.warn("Setting values on conclude_at will NOT update the remote Canvas instance.") + self._conclude_at = value + + @property + def start_at(self): + """start_at.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def name(self): + """name.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/course_quiz_extensions.py b/venv/Lib/site-packages/pycanvas/apis/course_quiz_extensions.py new file mode 100644 index 00000000..165c2d2c --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/course_quiz_extensions.py @@ -0,0 +1,144 @@ +"""CourseQuizExtensions API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class CourseQuizExtensionsAPI(BaseCanvasAPI): + """CourseQuizExtensions API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for CourseQuizExtensionsAPI.""" + super(CourseQuizExtensionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.CourseQuizExtensionsAPI") + + def set_extensions_for_student_quiz_submissions(self, user_id, course_id, extend_from_end_at=None, extend_from_now=None, extra_attempts=None, extra_time=None, manually_unlocked=None): + """ + Set extensions for student quiz submissions. + + Responses + + * 200 OK if the request was successful + * 403 Forbidden if you are not allowed to extend quizzes for this course + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - user_id + """The ID of the user we want to add quiz extensions for.""" + data["user_id"] = user_id + + # OPTIONAL - extra_attempts + """Number of times the student is allowed to re-take the quiz over the + multiple-attempt limit. This is limited to 1000 attempts or less.""" + if extra_attempts is not None: + data["extra_attempts"] = extra_attempts + + # OPTIONAL - extra_time + """The number of extra minutes to allow for all attempts. This will + add to the existing time limit on the submission. This is limited to + 10080 minutes (1 week)""" + if extra_time is not None: + data["extra_time"] = extra_time + + # OPTIONAL - manually_unlocked + """Allow the student to take the quiz even if it's locked for + everyone else.""" + if manually_unlocked is not None: + data["manually_unlocked"] = manually_unlocked + + # OPTIONAL - extend_from_now + """The number of minutes to extend the quiz from the current time. This is + mutually exclusive to extend_from_end_at. This is limited to 1440 + minutes (24 hours)""" + if extend_from_now is not None: + data["extend_from_now"] = extend_from_now + + # OPTIONAL - extend_from_end_at + """The number of minutes to extend the quiz beyond the quiz's current + ending time. This is mutually exclusive to extend_from_now. This is + limited to 1440 minutes (24 hours)""" + if extend_from_end_at is not None: + data["extend_from_end_at"] = extend_from_end_at + + self.logger.debug("POST /api/v1/courses/{course_id}/quiz_extensions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quiz_extensions".format(**path), data=data, params=params, no_data=True) + + +class Coursequizextension(BaseModel): + """Coursequizextension Model.""" + + def __init__(self, user_id, manually_unlocked=None, extra_time=None, extra_attempts=None, end_at=None): + """Init method for Coursequizextension class.""" + self._manually_unlocked = manually_unlocked + self._extra_time = extra_time + self._user_id = user_id + self._extra_attempts = extra_attempts + self._end_at = end_at + + self.logger = logging.getLogger('pycanvas.Coursequizextension') + + @property + def manually_unlocked(self): + """The student can take the quiz even if it's locked for everyone else.""" + return self._manually_unlocked + + @manually_unlocked.setter + def manually_unlocked(self, value): + """Setter for manually_unlocked property.""" + self.logger.warn("Setting values on manually_unlocked will NOT update the remote Canvas instance.") + self._manually_unlocked = value + + @property + def extra_time(self): + """Amount of extra time allowed for the quiz submission, in minutes.""" + return self._extra_time + + @extra_time.setter + def extra_time(self, value): + """Setter for extra_time property.""" + self.logger.warn("Setting values on extra_time will NOT update the remote Canvas instance.") + self._extra_time = value + + @property + def user_id(self): + """The ID of the Student that needs the quiz extension.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def extra_attempts(self): + """Number of times the student is allowed to re-take the quiz over the multiple-attempt limit.""" + return self._extra_attempts + + @extra_attempts.setter + def extra_attempts(self, value): + """Setter for extra_attempts property.""" + self.logger.warn("Setting values on extra_attempts will NOT update the remote Canvas instance.") + self._extra_attempts = value + + @property + def end_at(self): + """The time at which the quiz submission will be overdue, and be flagged as a late submission.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/courses.py b/venv/Lib/site-packages/pycanvas/apis/courses.py new file mode 100644 index 00000000..44129a01 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/courses.py @@ -0,0 +1,1940 @@ +"""Courses API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class CoursesAPI(BaseCanvasAPI): + """Courses API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for CoursesAPI.""" + super(CoursesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.CoursesAPI") + + def list_your_courses(self, enrollment_role=None, enrollment_role_id=None, enrollment_state=None, enrollment_type=None, include=None, state=None): + """ + List your courses. + + Returns the list of active courses for the current user. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - enrollment_type + """When set, only return courses where the user is enrolled as this type. For + example, set to "teacher" to return only courses where the user is + enrolled as a Teacher. This argument is ignored if enrollment_role is given.""" + if enrollment_type is not None: + self._validate_enum(enrollment_type, ["teacher", "student", "ta", "observer", "designer"]) + params["enrollment_type"] = enrollment_type + + # OPTIONAL - enrollment_role + """Deprecated + When set, only return courses where the user is enrolled with the specified + course-level role. This can be a role created with the + {api:RoleOverridesController#add_role Add Role API} or a base role type of + 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', 'ObserverEnrollment', + or 'DesignerEnrollment'.""" + if enrollment_role is not None: + params["enrollment_role"] = enrollment_role + + # OPTIONAL - enrollment_role_id + """When set, only return courses where the user is enrolled with the specified + course-level role. This can be a role created with the + {api:RoleOverridesController#add_role Add Role API} or a built_in role type of + 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', 'ObserverEnrollment', + or 'DesignerEnrollment'.""" + if enrollment_role_id is not None: + params["enrollment_role_id"] = enrollment_role_id + + # OPTIONAL - enrollment_state + """When set, only return courses where the user has an enrollment with the given state. + This will respect section/course/term date overrides.""" + if enrollment_state is not None: + self._validate_enum(enrollment_state, ["active", "invited_or_pending", "completed"]) + params["enrollment_state"] = enrollment_state + + # OPTIONAL - include + """- "needs_grading_count": Optional information to include with each Course. + When needs_grading_count is given, and the current user has grading + rights, the total number of submissions needing grading for all + assignments is returned. + - "syllabus_body": Optional information to include with each Course. + When syllabus_body is given the user-generated html for the course + syllabus is returned. + - "public_description": Optional information to include with each Course. + When public_description is given the user-generated text for the course + public description is returned. + - "total_scores": Optional information to include with each Course. + When total_scores is given, any student enrollments will also + include the fields 'computed_current_score', 'computed_final_score', + 'computed_current_grade', and 'computed_final_grade' (see Enrollment + documentation for more information on these fields). This argument + is ignored if the course is configured to hide final grades. + - "current_grading_period_scores": Optional information to include with + each Course. When current_grading_period_scores is given and total_scores + is given, any student enrollments will also include the fields + 'multiple_grading_periods_enabled', + 'totals_for_all_grading_periods_option', 'current_grading_period_title', + 'current_grading_period_id', current_period_computed_current_score', + 'current_period_computed_final_score', + 'current_period_computed_current_grade', and + 'current_period_computed_final_grade' (see Enrollment documentation for + more information on these fields). In addition, when this argument is + passed, the course will have a 'multiple_grading_periods_enabled' attribute + on it. This argument is ignored if the course is configured to hide final + grades or if the total_scores argument is not included. + - "term": Optional information to include with each Course. When + term is given, the information for the enrollment term for each course + is returned. + - "course_progress": Optional information to include with each Course. + When course_progress is given, each course will include a + 'course_progress' object with the fields: 'requirement_count', an integer + specifying the total number of requirements in the course, + 'requirement_completed_count', an integer specifying the total number of + requirements in this course that have been completed, and + 'next_requirement_url', a string url to the next requirement item, and + 'completed_at', the date the course was completed (null if incomplete). + 'next_requirement_url' will be null if all requirements have been + completed or the current module does not require sequential progress. + "course_progress" will return an error message if the course is not + module based or the user is not enrolled as a student in the course. + - "sections": Section enrollment information to include with each Course. + Returns an array of hashes containing the section ID (id), section name + (name), start and end dates (start_at, end_at), as well as the enrollment + type (enrollment_role, e.g. 'StudentEnrollment'). + - "storage_quota_used_mb": The amount of storage space used by the files in this course + - "total_students": Optional information to include with each Course. + Returns an integer for the total amount of active and invited students. + - "passback_status": Include the grade passback_status + - "favorites": Optional information to include with each Course. + Indicates if the user has marked the course as a favorite course. + - "teachers": Teacher information to include with each Course. + Returns an array of hashes containing the {api:Users:UserDisplay UserDisplay} information + for each teacher in the course. + - "observed_users": Optional information to include with each Course. + Will include data for observed users if the current user has an + observer enrollment. + - "tabs": Optional information to include with each Course. + Will include the list of tabs configured for each course. See the + {api:TabsController#index List available tabs API} for more information.""" + if include is not None: + self._validate_enum(include, ["needs_grading_count", "syllabus_body", "public_description", "total_scores", "current_grading_period_scores", "term", "course_progress", "sections", "storage_quota_used_mb", "total_students", "passback_status", "favorites", "teachers", "observed_users"]) + params["include"] = include + + # OPTIONAL - state + """If set, only return courses that are in the given state(s). + By default, "available" is returned for students and observers, and + anything except "deleted", for all other enrollment types""" + if state is not None: + self._validate_enum(state, ["unpublished", "available", "completed", "deleted"]) + params["state"] = state + + self.logger.debug("GET /api/v1/courses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses".format(**path), data=data, params=params, all_pages=True) + + def list_courses_for_user(self, user_id, enrollment_state=None, include=None, state=None): + """ + List courses for a user. + + Returns a list of active courses for this user. To view the course list for a user other than yourself, you must be either an observer of that user or an administrator. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - include + """- "needs_grading_count": Optional information to include with each Course. + When needs_grading_count is given, and the current user has grading + rights, the total number of submissions needing grading for all + assignments is returned. + - "syllabus_body": Optional information to include with each Course. + When syllabus_body is given the user-generated html for the course + syllabus is returned. + - "public_description": Optional information to include with each Course. + When public_description is given the user-generated text for the course + public description is returned. + - "total_scores": Optional information to include with each Course. + When total_scores is given, any student enrollments will also + include the fields 'computed_current_score', 'computed_final_score', + 'computed_current_grade', and 'computed_final_grade' (see Enrollment + documentation for more information on these fields). This argument + is ignored if the course is configured to hide final grades. + - "current_grading_period_scores": Optional information to include with + each Course. When current_grading_period_scores is given and total_scores + is given, any student enrollments will also include the fields + 'multiple_grading_periods_enabled', + 'totals_for_all_grading_periods_option', 'current_grading_period_title', + 'current_grading_period_id', current_period_computed_current_score', + 'current_period_computed_final_score', + 'current_period_computed_current_grade', and + 'current_period_computed_final_grade' (see Enrollment documentation for + more information on these fields). In addition, when this argument is + passed, the course will have a 'multiple_grading_periods_enabled' attribute + on it. This argument is ignored if the course is configured to hide final + grades or if the total_scores argument is not included. + - "term": Optional information to include with each Course. When + term is given, the information for the enrollment term for each course + is returned. + - "course_progress": Optional information to include with each Course. + When course_progress is given, each course will include a + 'course_progress' object with the fields: 'requirement_count', an integer + specifying the total number of requirements in the course, + 'requirement_completed_count', an integer specifying the total number of + requirements in this course that have been completed, and + 'next_requirement_url', a string url to the next requirement item, and + 'completed_at', the date the course was completed (null if incomplete). + 'next_requirement_url' will be null if all requirements have been + completed or the current module does not require sequential progress. + "course_progress" will return an error message if the course is not + module based or the user is not enrolled as a student in the course. + - "sections": Section enrollment information to include with each Course. + Returns an array of hashes containing the section ID (id), section name + (name), start and end dates (start_at, end_at), as well as the enrollment + type (enrollment_role, e.g. 'StudentEnrollment'). + - "storage_quota_used_mb": The amount of storage space used by the files in this course + - "total_students": Optional information to include with each Course. + Returns an integer for the total amount of active and invited students. + - "passback_status": Include the grade passback_status + - "favorites": Optional information to include with each Course. + Indicates if the user has marked the course as a favorite course. + - "teachers": Teacher information to include with each Course. + Returns an array of hashes containing the {api:Users:UserDisplay UserDisplay} information + for each teacher in the course. + - "observed_users": Optional information to include with each Course. + Will include data for observed users if the current user has an + observer enrollment. + - "tabs": Optional information to include with each Course. + Will include the list of tabs configured for each course. See the + {api:TabsController#index List available tabs API} for more information.""" + if include is not None: + self._validate_enum(include, ["needs_grading_count", "syllabus_body", "public_description", "total_scores", "current_grading_period_scores", "term", "course_progress", "sections", "storage_quota_used_mb", "total_students", "passback_status", "favorites", "teachers", "observed_users"]) + params["include"] = include + + # OPTIONAL - state + """If set, only return courses that are in the given state(s). + By default, "available" is returned for students and observers, and + anything except "deleted", for all other enrollment types""" + if state is not None: + self._validate_enum(state, ["unpublished", "available", "completed", "deleted"]) + params["state"] = state + + # OPTIONAL - enrollment_state + """When set, only return courses where the user has an enrollment with the given state. + This will respect section/course/term date overrides.""" + if enrollment_state is not None: + self._validate_enum(enrollment_state, ["active", "invited_or_pending", "completed"]) + params["enrollment_state"] = enrollment_state + + self.logger.debug("GET /api/v1/users/{user_id}/courses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/courses".format(**path), data=data, params=params, all_pages=True) + + def create_new_course(self, account_id, course_allow_student_forum_attachments=None, course_allow_student_wiki_edits=None, course_allow_wiki_comments=None, course_apply_assignment_group_weights=None, course_course_code=None, course_course_format=None, course_end_at=None, course_grading_standard_id=None, course_hide_final_grades=None, course_integration_id=None, course_is_public=None, course_is_public_to_auth_users=None, course_license=None, course_name=None, course_open_enrollment=None, course_public_description=None, course_public_syllabus=None, course_public_syllabus_to_auth=None, course_restrict_enrollments_to_course_dates=None, course_self_enrollment=None, course_sis_course_id=None, course_start_at=None, course_syllabus_body=None, course_term_id=None, course_time_zone=None, enable_sis_reactivation=None, enroll_me=None, offer=None): + """ + Create a new course. + + Create a new course + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - course[name] + """The name of the course. If omitted, the course will be named "Unnamed + Course." """ + if course_name is not None: + data["course[name]"] = course_name + + # OPTIONAL - course[course_code] + """The course code for the course.""" + if course_course_code is not None: + data["course[course_code]"] = course_course_code + + # OPTIONAL - course[start_at] + """Course start date in ISO8601 format, e.g. 2011-01-01T01:00Z""" + if course_start_at is not None: + data["course[start_at]"] = course_start_at + + # OPTIONAL - course[end_at] + """Course end date in ISO8601 format. e.g. 2011-01-01T01:00Z""" + if course_end_at is not None: + data["course[end_at]"] = course_end_at + + # OPTIONAL - course[license] + """The name of the licensing. Should be one of the following abbreviations + (a descriptive name is included in parenthesis for reference): + - 'private' (Private Copyrighted) + - 'cc_by_nc_nd' (CC Attribution Non-Commercial No Derivatives) + - 'cc_by_nc_sa' (CC Attribution Non-Commercial Share Alike) + - 'cc_by_nc' (CC Attribution Non-Commercial) + - 'cc_by_nd' (CC Attribution No Derivatives) + - 'cc_by_sa' (CC Attribution Share Alike) + - 'cc_by' (CC Attribution) + - 'public_domain' (Public Domain).""" + if course_license is not None: + data["course[license]"] = course_license + + # OPTIONAL - course[is_public] + """Set to true if course is public to both authenticated and unauthenticated users.""" + if course_is_public is not None: + data["course[is_public]"] = course_is_public + + # OPTIONAL - course[is_public_to_auth_users] + """Set to true if course is public only to authenticated users.""" + if course_is_public_to_auth_users is not None: + data["course[is_public_to_auth_users]"] = course_is_public_to_auth_users + + # OPTIONAL - course[public_syllabus] + """Set to true to make the course syllabus public.""" + if course_public_syllabus is not None: + data["course[public_syllabus]"] = course_public_syllabus + + # OPTIONAL - course[public_syllabus_to_auth] + """Set to true to make the course syllabus public for authenticated users.""" + if course_public_syllabus_to_auth is not None: + data["course[public_syllabus_to_auth]"] = course_public_syllabus_to_auth + + # OPTIONAL - course[public_description] + """A publicly visible description of the course.""" + if course_public_description is not None: + data["course[public_description]"] = course_public_description + + # OPTIONAL - course[allow_student_wiki_edits] + """If true, students will be able to modify the course wiki.""" + if course_allow_student_wiki_edits is not None: + data["course[allow_student_wiki_edits]"] = course_allow_student_wiki_edits + + # OPTIONAL - course[allow_wiki_comments] + """If true, course members will be able to comment on wiki pages.""" + if course_allow_wiki_comments is not None: + data["course[allow_wiki_comments]"] = course_allow_wiki_comments + + # OPTIONAL - course[allow_student_forum_attachments] + """If true, students can attach files to forum posts.""" + if course_allow_student_forum_attachments is not None: + data["course[allow_student_forum_attachments]"] = course_allow_student_forum_attachments + + # OPTIONAL - course[open_enrollment] + """Set to true if the course is open enrollment.""" + if course_open_enrollment is not None: + data["course[open_enrollment]"] = course_open_enrollment + + # OPTIONAL - course[self_enrollment] + """Set to true if the course is self enrollment.""" + if course_self_enrollment is not None: + data["course[self_enrollment]"] = course_self_enrollment + + # OPTIONAL - course[restrict_enrollments_to_course_dates] + """Set to true to restrict user enrollments to the start and end dates of the + course.""" + if course_restrict_enrollments_to_course_dates is not None: + data["course[restrict_enrollments_to_course_dates]"] = course_restrict_enrollments_to_course_dates + + # OPTIONAL - course[term_id] + """The unique ID of the term to create to course in.""" + if course_term_id is not None: + data["course[term_id]"] = course_term_id + + # OPTIONAL - course[sis_course_id] + """The unique SIS identifier.""" + if course_sis_course_id is not None: + data["course[sis_course_id]"] = course_sis_course_id + + # OPTIONAL - course[integration_id] + """The unique Integration identifier.""" + if course_integration_id is not None: + data["course[integration_id]"] = course_integration_id + + # OPTIONAL - course[hide_final_grades] + """If this option is set to true, the totals in student grades summary will + be hidden.""" + if course_hide_final_grades is not None: + data["course[hide_final_grades]"] = course_hide_final_grades + + # OPTIONAL - course[apply_assignment_group_weights] + """Set to true to weight final grade based on assignment groups percentages.""" + if course_apply_assignment_group_weights is not None: + data["course[apply_assignment_group_weights]"] = course_apply_assignment_group_weights + + # OPTIONAL - course[time_zone] + """The time zone for the course. Allowed time zones are + {http://www.iana.org/time-zones IANA time zones} or friendlier + {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + if course_time_zone is not None: + data["course[time_zone]"] = course_time_zone + + # OPTIONAL - offer + """If this option is set to true, the course will be available to students + immediately.""" + if offer is not None: + data["offer"] = offer + + # OPTIONAL - enroll_me + """Set to true to enroll the current user as the teacher.""" + if enroll_me is not None: + data["enroll_me"] = enroll_me + + # OPTIONAL - course[syllabus_body] + """The syllabus body for the course""" + if course_syllabus_body is not None: + data["course[syllabus_body]"] = course_syllabus_body + + # OPTIONAL - course[grading_standard_id] + """The grading standard id to set for the course. If no value is provided for this argument the current grading_standard will be un-set from this course.""" + if course_grading_standard_id is not None: + data["course[grading_standard_id]"] = course_grading_standard_id + + # OPTIONAL - course[course_format] + """Optional. Specifies the format of the course. (Should be 'on_campus', 'online', or 'blended')""" + if course_course_format is not None: + data["course[course_format]"] = course_course_format + + # OPTIONAL - enable_sis_reactivation + """When true, will first try to re-activate a deleted course with matching sis_course_id if possible.""" + if enable_sis_reactivation is not None: + data["enable_sis_reactivation"] = enable_sis_reactivation + + self.logger.debug("POST /api/v1/accounts/{account_id}/courses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/courses".format(**path), data=data, params=params, single_item=True) + + def upload_file(self, course_id): + """ + Upload a file. + + Upload a file to the course. + + This API endpoint is the first step in uploading a file to a course. + See the {file:file_uploads.html File Upload Documentation} for details on + the file upload workflow. + + Only those with the "Manage Files" permission on a course can upload files + to the course. By default, this is Teachers, TAs and Designers. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("POST /api/v1/courses/{course_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/files".format(**path), data=data, params=params, no_data=True) + + def list_students(self, course_id): + """ + List students. + + Returns the list of students enrolled in this course. + + DEPRECATED: Please use the {api:CoursesController#users course users} endpoint + and pass "student" as the enrollment_type. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/students with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/students".format(**path), data=data, params=params, all_pages=True) + + def list_users_in_course_users(self, course_id, enrollment_role=None, enrollment_role_id=None, enrollment_state=None, enrollment_type=None, include=None, search_term=None, user_id=None, user_ids=None): + """ + List users in course. + + Returns the list of users in this course. And optionally the user's enrollments in the course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - search_term + """The partial name or full ID of the users to match and return in the results list.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - enrollment_type + """When set, only return users where the user is enrolled as this type. + "student_view" implies include[]=test_student. + This argument is ignored if enrollment_role is given.""" + if enrollment_type is not None: + self._validate_enum(enrollment_type, ["teacher", "student", "student_view", "ta", "observer", "designer"]) + params["enrollment_type"] = enrollment_type + + # OPTIONAL - enrollment_role + """Deprecated + When set, only return users enrolled with the specified course-level role. This can be + a role created with the {api:RoleOverridesController#add_role Add Role API} or a + base role type of 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', + 'ObserverEnrollment', or 'DesignerEnrollment'.""" + if enrollment_role is not None: + params["enrollment_role"] = enrollment_role + + # OPTIONAL - enrollment_role_id + """When set, only return courses where the user is enrolled with the specified + course-level role. This can be a role created with the + {api:RoleOverridesController#add_role Add Role API} or a built_in role id with type + 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', 'ObserverEnrollment', + or 'DesignerEnrollment'.""" + if enrollment_role_id is not None: + params["enrollment_role_id"] = enrollment_role_id + + # OPTIONAL - include + """- "email": Optional user email. + - "enrollments": + Optionally include with each Course the user's current and invited + enrollments. If the user is enrolled as a student, and the account has + permission to manage or view all grades, each enrollment will include a + 'grades' key with 'current_score', 'final_score', 'current_grade' and + 'final_grade' values. + - "locked": Optionally include whether an enrollment is locked. + - "avatar_url": Optionally include avatar_url. + - "bio": Optionally include each user's bio. + - "test_student": Optionally include the course's Test Student, + if present. Default is to not include Test Student. + - "custom_links": Optionally include plugin-supplied custom links for each student, + such as analytics information""" + if include is not None: + self._validate_enum(include, ["email", "enrollments", "locked", "avatar_url", "test_student", "bio", "custom_links"]) + params["include"] = include + + # OPTIONAL - user_id + """If this parameter is given and it corresponds to a user in the course, + the +page+ parameter will be ignored and the page containing the specified user + will be returned instead.""" + if user_id is not None: + params["user_id"] = user_id + + # OPTIONAL - user_ids + """If included, the course users set will only include users with IDs + specified by the param. Note: this will not work in conjunction + with the "user_id" argument but multiple user_ids can be included.""" + if user_ids is not None: + params["user_ids"] = user_ids + + # OPTIONAL - enrollment_state + """When set, only return users where the enrollment workflow state is of one of the given types. + "active" and "invited" enrollments are returned by default.""" + if enrollment_state is not None: + self._validate_enum(enrollment_state, ["active", "invited", "rejected", "completed", "inactive"]) + params["enrollment_state"] = enrollment_state + + self.logger.debug("GET /api/v1/courses/{course_id}/users with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/users".format(**path), data=data, params=params, all_pages=True) + + def list_users_in_course_search_users(self, course_id, enrollment_role=None, enrollment_role_id=None, enrollment_state=None, enrollment_type=None, include=None, search_term=None, user_id=None, user_ids=None): + """ + List users in course. + + Returns the list of users in this course. And optionally the user's enrollments in the course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - search_term + """The partial name or full ID of the users to match and return in the results list.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - enrollment_type + """When set, only return users where the user is enrolled as this type. + "student_view" implies include[]=test_student. + This argument is ignored if enrollment_role is given.""" + if enrollment_type is not None: + self._validate_enum(enrollment_type, ["teacher", "student", "student_view", "ta", "observer", "designer"]) + params["enrollment_type"] = enrollment_type + + # OPTIONAL - enrollment_role + """Deprecated + When set, only return users enrolled with the specified course-level role. This can be + a role created with the {api:RoleOverridesController#add_role Add Role API} or a + base role type of 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', + 'ObserverEnrollment', or 'DesignerEnrollment'.""" + if enrollment_role is not None: + params["enrollment_role"] = enrollment_role + + # OPTIONAL - enrollment_role_id + """When set, only return courses where the user is enrolled with the specified + course-level role. This can be a role created with the + {api:RoleOverridesController#add_role Add Role API} or a built_in role id with type + 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', 'ObserverEnrollment', + or 'DesignerEnrollment'.""" + if enrollment_role_id is not None: + params["enrollment_role_id"] = enrollment_role_id + + # OPTIONAL - include + """- "email": Optional user email. + - "enrollments": + Optionally include with each Course the user's current and invited + enrollments. If the user is enrolled as a student, and the account has + permission to manage or view all grades, each enrollment will include a + 'grades' key with 'current_score', 'final_score', 'current_grade' and + 'final_grade' values. + - "locked": Optionally include whether an enrollment is locked. + - "avatar_url": Optionally include avatar_url. + - "bio": Optionally include each user's bio. + - "test_student": Optionally include the course's Test Student, + if present. Default is to not include Test Student. + - "custom_links": Optionally include plugin-supplied custom links for each student, + such as analytics information""" + if include is not None: + self._validate_enum(include, ["email", "enrollments", "locked", "avatar_url", "test_student", "bio", "custom_links"]) + params["include"] = include + + # OPTIONAL - user_id + """If this parameter is given and it corresponds to a user in the course, + the +page+ parameter will be ignored and the page containing the specified user + will be returned instead.""" + if user_id is not None: + params["user_id"] = user_id + + # OPTIONAL - user_ids + """If included, the course users set will only include users with IDs + specified by the param. Note: this will not work in conjunction + with the "user_id" argument but multiple user_ids can be included.""" + if user_ids is not None: + params["user_ids"] = user_ids + + # OPTIONAL - enrollment_state + """When set, only return users where the enrollment workflow state is of one of the given types. + "active" and "invited" enrollments are returned by default.""" + if enrollment_state is not None: + self._validate_enum(enrollment_state, ["active", "invited", "rejected", "completed", "inactive"]) + params["enrollment_state"] = enrollment_state + + self.logger.debug("GET /api/v1/courses/{course_id}/search_users with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/search_users".format(**path), data=data, params=params, all_pages=True) + + def list_recently_logged_in_students(self, course_id): + """ + List recently logged in students. + + Returns the list of users in this course, ordered by how recently they have + logged in. The records include the 'last_login' field which contains + a timestamp of the last time that user logged into canvas. The querying + user must have the 'View usage reports' permission. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/recent_students with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/recent_students".format(**path), data=data, params=params, all_pages=True) + + def get_single_user(self, id, course_id): + """ + Get single user. + + Return information on a single user. + + Accepts the same include[] parameters as the :users: action, and returns a + single user with the same fields as that action. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/users/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/users/{id}".format(**path), data=data, params=params, single_item=True) + + def preview_processed_html(self, course_id, html=None): + """ + Preview processed html. + + Preview html content processed for this course + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - html + """The html content to process""" + if html is not None: + data["html"] = html + + self.logger.debug("POST /api/v1/courses/{course_id}/preview_html with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/preview_html".format(**path), data=data, params=params, no_data=True) + + def course_activity_stream(self, course_id): + """ + Course activity stream. + + Returns the current user's course-specific activity stream, paginated. + + For full documentation, see the API documentation for the user activity + stream, in the user api. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/activity_stream with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/activity_stream".format(**path), data=data, params=params, no_data=True) + + def course_activity_stream_summary(self, course_id): + """ + Course activity stream summary. + + Returns a summary of the current user's course-specific activity stream. + + For full documentation, see the API documentation for the user activity + stream summary, in the user api. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/activity_stream/summary with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/activity_stream/summary".format(**path), data=data, params=params, no_data=True) + + def course_todo_items(self, course_id): + """ + Course TODO items. + + Returns the current user's course-specific todo items. + + For full documentation, see the API documentation for the user todo items, in the user api. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/todo with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/todo".format(**path), data=data, params=params, no_data=True) + + def conclude_course(self, id, event): + """ + Conclude a course. + + Delete or conclude an existing course + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - event + """The action to take on the course.""" + self._validate_enum(event, ["delete", "conclude"]) + params["event"] = event + + self.logger.debug("DELETE /api/v1/courses/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{id}".format(**path), data=data, params=params, no_data=True) + + def get_course_settings(self, course_id): + """ + Get course settings. + + Returns some of a course's settings. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/settings with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/settings".format(**path), data=data, params=params, no_data=True) + + def update_course_settings(self, course_id, allow_student_discussion_editing=None, allow_student_discussion_topics=None, allow_student_forum_attachments=None, allow_student_organized_groups=None, hide_distribution_graphs=None, hide_final_grades=None, home_page_announcement_limit=None, lock_all_announcements=None, restrict_student_future_view=None, restrict_student_past_view=None, show_announcements_on_home_page=None): + """ + Update course settings. + + Can update the following course settings: + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - allow_student_discussion_topics + """Let students create discussion topics""" + if allow_student_discussion_topics is not None: + data["allow_student_discussion_topics"] = allow_student_discussion_topics + + # OPTIONAL - allow_student_forum_attachments + """Let students attach files to discussions""" + if allow_student_forum_attachments is not None: + data["allow_student_forum_attachments"] = allow_student_forum_attachments + + # OPTIONAL - allow_student_discussion_editing + """Let students edit or delete their own discussion posts""" + if allow_student_discussion_editing is not None: + data["allow_student_discussion_editing"] = allow_student_discussion_editing + + # OPTIONAL - allow_student_organized_groups + """Let students organize their own groups""" + if allow_student_organized_groups is not None: + data["allow_student_organized_groups"] = allow_student_organized_groups + + # OPTIONAL - hide_final_grades + """Hide totals in student grades summary""" + if hide_final_grades is not None: + data["hide_final_grades"] = hide_final_grades + + # OPTIONAL - hide_distribution_graphs + """Hide grade distribution graphs from students""" + if hide_distribution_graphs is not None: + data["hide_distribution_graphs"] = hide_distribution_graphs + + # OPTIONAL - lock_all_announcements + """Disable comments on announcements""" + if lock_all_announcements is not None: + data["lock_all_announcements"] = lock_all_announcements + + # OPTIONAL - restrict_student_past_view + """Restrict students from viewing courses after end date""" + if restrict_student_past_view is not None: + data["restrict_student_past_view"] = restrict_student_past_view + + # OPTIONAL - restrict_student_future_view + """Restrict students from viewing courses before start date""" + if restrict_student_future_view is not None: + data["restrict_student_future_view"] = restrict_student_future_view + + # OPTIONAL - show_announcements_on_home_page + """Show the most recent announcements on the Course home page (if a Wiki, defaults to five announcements, configurable via home_page_announcement_limit)""" + if show_announcements_on_home_page is not None: + data["show_announcements_on_home_page"] = show_announcements_on_home_page + + # OPTIONAL - home_page_announcement_limit + """Limit the number of announcements on the home page if enabled via show_announcements_on_home_page""" + if home_page_announcement_limit is not None: + data["home_page_announcement_limit"] = home_page_announcement_limit + + self.logger.debug("PUT /api/v1/courses/{course_id}/settings with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/settings".format(**path), data=data, params=params, no_data=True) + + def get_single_course_courses(self, id, include=None): + """ + Get a single course. + + Return information on a single course. + + Accepts the same include[] parameters as the list action plus: + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """- "all_courses": Also search recently deleted courses. + - "permissions": Include permissions the current user has + for the course. + - "observed_users": include observed users in the enrollments""" + if include is not None: + self._validate_enum(include, ["needs_grading_count", "syllabus_body", "public_description", "total_scores", "current_grading_period_scores", "term", "course_progress", "sections", "storage_quota_used_mb", "total_students", "passback_status", "favorites", "teachers", "observed_users", "all_courses", "permissions", "observed_users"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{id}".format(**path), data=data, params=params, single_item=True) + + def get_single_course_accounts(self, id, account_id, include=None): + """ + Get a single course. + + Return information on a single course. + + Accepts the same include[] parameters as the list action plus: + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """- "all_courses": Also search recently deleted courses. + - "permissions": Include permissions the current user has + for the course. + - "observed_users": include observed users in the enrollments""" + if include is not None: + self._validate_enum(include, ["needs_grading_count", "syllabus_body", "public_description", "total_scores", "current_grading_period_scores", "term", "course_progress", "sections", "storage_quota_used_mb", "total_students", "passback_status", "favorites", "teachers", "observed_users", "all_courses", "permissions", "observed_users"]) + params["include"] = include + + self.logger.debug("GET /api/v1/accounts/{account_id}/courses/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/courses/{id}".format(**path), data=data, params=params, single_item=True) + + def update_course(self, id, course_account_id=None, course_allow_student_forum_attachments=None, course_allow_student_wiki_edits=None, course_allow_wiki_comments=None, course_apply_assignment_group_weights=None, course_course_code=None, course_course_format=None, course_end_at=None, course_event=None, course_grading_standard_id=None, course_hide_final_grades=None, course_image_id=None, course_image_url=None, course_integration_id=None, course_is_public=None, course_is_public_to_auth_users=None, course_license=None, course_name=None, course_open_enrollment=None, course_public_description=None, course_public_syllabus=None, course_public_syllabus_to_auth=None, course_remove_image=None, course_restrict_enrollments_to_course_dates=None, course_self_enrollment=None, course_sis_course_id=None, course_start_at=None, course_storage_quota_mb=None, course_syllabus_body=None, course_term_id=None, course_time_zone=None, offer=None): + """ + Update a course. + + Update an existing course. + + Arguments are the same as Courses#create, with a few exceptions (enroll_me). + + If a user has content management rights, but not full course editing rights, the only attribute + editable through this endpoint will be "syllabus_body" + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - course[account_id] + """The unique ID of the account to move the course to.""" + if course_account_id is not None: + data["course[account_id]"] = course_account_id + + # OPTIONAL - course[name] + """The name of the course. If omitted, the course will be named "Unnamed + Course." """ + if course_name is not None: + data["course[name]"] = course_name + + # OPTIONAL - course[course_code] + """The course code for the course.""" + if course_course_code is not None: + data["course[course_code]"] = course_course_code + + # OPTIONAL - course[start_at] + """Course start date in ISO8601 format, e.g. 2011-01-01T01:00Z""" + if course_start_at is not None: + data["course[start_at]"] = course_start_at + + # OPTIONAL - course[end_at] + """Course end date in ISO8601 format. e.g. 2011-01-01T01:00Z""" + if course_end_at is not None: + data["course[end_at]"] = course_end_at + + # OPTIONAL - course[license] + """The name of the licensing. Should be one of the following abbreviations + (a descriptive name is included in parenthesis for reference): + - 'private' (Private Copyrighted) + - 'cc_by_nc_nd' (CC Attribution Non-Commercial No Derivatives) + - 'cc_by_nc_sa' (CC Attribution Non-Commercial Share Alike) + - 'cc_by_nc' (CC Attribution Non-Commercial) + - 'cc_by_nd' (CC Attribution No Derivatives) + - 'cc_by_sa' (CC Attribution Share Alike) + - 'cc_by' (CC Attribution) + - 'public_domain' (Public Domain).""" + if course_license is not None: + data["course[license]"] = course_license + + # OPTIONAL - course[is_public] + """Set to true if course is public to both authenticated and unauthenticated users.""" + if course_is_public is not None: + data["course[is_public]"] = course_is_public + + # OPTIONAL - course[is_public_to_auth_users] + """Set to true if course is public only to authenticated users.""" + if course_is_public_to_auth_users is not None: + data["course[is_public_to_auth_users]"] = course_is_public_to_auth_users + + # OPTIONAL - course[public_syllabus] + """Set to true to make the course syllabus public.""" + if course_public_syllabus is not None: + data["course[public_syllabus]"] = course_public_syllabus + + # OPTIONAL - course[public_syllabus_to_auth] + """Set to true to make the course syllabus to public for authenticated users.""" + if course_public_syllabus_to_auth is not None: + data["course[public_syllabus_to_auth]"] = course_public_syllabus_to_auth + + # OPTIONAL - course[public_description] + """A publicly visible description of the course.""" + if course_public_description is not None: + data["course[public_description]"] = course_public_description + + # OPTIONAL - course[allow_student_wiki_edits] + """If true, students will be able to modify the course wiki.""" + if course_allow_student_wiki_edits is not None: + data["course[allow_student_wiki_edits]"] = course_allow_student_wiki_edits + + # OPTIONAL - course[allow_wiki_comments] + """If true, course members will be able to comment on wiki pages.""" + if course_allow_wiki_comments is not None: + data["course[allow_wiki_comments]"] = course_allow_wiki_comments + + # OPTIONAL - course[allow_student_forum_attachments] + """If true, students can attach files to forum posts.""" + if course_allow_student_forum_attachments is not None: + data["course[allow_student_forum_attachments]"] = course_allow_student_forum_attachments + + # OPTIONAL - course[open_enrollment] + """Set to true if the course is open enrollment.""" + if course_open_enrollment is not None: + data["course[open_enrollment]"] = course_open_enrollment + + # OPTIONAL - course[self_enrollment] + """Set to true if the course is self enrollment.""" + if course_self_enrollment is not None: + data["course[self_enrollment]"] = course_self_enrollment + + # OPTIONAL - course[restrict_enrollments_to_course_dates] + """Set to true to restrict user enrollments to the start and end dates of the + course.""" + if course_restrict_enrollments_to_course_dates is not None: + data["course[restrict_enrollments_to_course_dates]"] = course_restrict_enrollments_to_course_dates + + # OPTIONAL - course[term_id] + """The unique ID of the term to create to course in.""" + if course_term_id is not None: + data["course[term_id]"] = course_term_id + + # OPTIONAL - course[sis_course_id] + """The unique SIS identifier.""" + if course_sis_course_id is not None: + data["course[sis_course_id]"] = course_sis_course_id + + # OPTIONAL - course[integration_id] + """The unique Integration identifier.""" + if course_integration_id is not None: + data["course[integration_id]"] = course_integration_id + + # OPTIONAL - course[hide_final_grades] + """If this option is set to true, the totals in student grades summary will + be hidden.""" + if course_hide_final_grades is not None: + data["course[hide_final_grades]"] = course_hide_final_grades + + # OPTIONAL - course[time_zone] + """The time zone for the course. Allowed time zones are + {http://www.iana.org/time-zones IANA time zones} or friendlier + {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + if course_time_zone is not None: + data["course[time_zone]"] = course_time_zone + + # OPTIONAL - course[apply_assignment_group_weights] + """Set to true to weight final grade based on assignment groups percentages.""" + if course_apply_assignment_group_weights is not None: + data["course[apply_assignment_group_weights]"] = course_apply_assignment_group_weights + + # OPTIONAL - course[storage_quota_mb] + """Set the storage quota for the course, in megabytes. The caller must have + the "Manage storage quotas" account permission.""" + if course_storage_quota_mb is not None: + data["course[storage_quota_mb]"] = course_storage_quota_mb + + # OPTIONAL - offer + """If this option is set to true, the course will be available to students + immediately.""" + if offer is not None: + data["offer"] = offer + + # OPTIONAL - course[event] + """The action to take on each course. + * 'claim' makes a course no longer visible to students. This action is also called "unpublish" on the web site. + A course cannot be unpublished if students have received graded submissions. + * 'offer' makes a course visible to students. This action is also called "publish" on the web site. + * 'conclude' prevents future enrollments and makes a course read-only for all participants. The course still appears + in prior-enrollment lists. + * 'delete' completely removes the course from the web site (including course menus and prior-enrollment lists). + All enrollments are deleted. Course content may be physically deleted at a future date. + * 'undelete' attempts to recover a course that has been deleted. (Recovery is not guaranteed; please conclude + rather than delete a course if there is any possibility the course will be used again.) The recovered course + will be unpublished. Deleted enrollments will not be recovered.""" + if course_event is not None: + self._validate_enum(course_event, ["claim", "offer", "conclude", "delete", "undelete"]) + data["course[event]"] = course_event + + # OPTIONAL - course[syllabus_body] + """The syllabus body for the course""" + if course_syllabus_body is not None: + data["course[syllabus_body]"] = course_syllabus_body + + # OPTIONAL - course[grading_standard_id] + """The grading standard id to set for the course. If no value is provided for this argument the current grading_standard will be un-set from this course.""" + if course_grading_standard_id is not None: + data["course[grading_standard_id]"] = course_grading_standard_id + + # OPTIONAL - course[course_format] + """Optional. Specifies the format of the course. (Should be either 'on_campus' or 'online')""" + if course_course_format is not None: + data["course[course_format]"] = course_course_format + + # OPTIONAL - course[image_id] + """This is a file ID corresponding to an image file in the course that will + be used as the course image. + This will clear the course's image_url setting if set. If you attempt + to provide image_url and image_id in a request it will fail.""" + if course_image_id is not None: + data["course[image_id]"] = course_image_id + + # OPTIONAL - course[image_url] + """This is a URL to an image to be used as the course image. + This will clear the course's image_id setting if set. If you attempt + to provide image_url and image_id in a request it will fail.""" + if course_image_url is not None: + data["course[image_url]"] = course_image_url + + # OPTIONAL - course[remove_image] + """If this option is set to true, the course image url and course image + ID are both set to nil""" + if course_remove_image is not None: + data["course[remove_image]"] = course_remove_image + + self.logger.debug("PUT /api/v1/courses/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{id}".format(**path), data=data, params=params, no_data=True) + + def update_courses(self, event, account_id, course_ids): + """ + Update courses. + + Update multiple courses in an account. Operates asynchronously; use the {api:ProgressController#show progress endpoint} + to query the status of an operation. + + The action to take on each course. Must be one of 'offer', 'conclude', 'delete', or 'undelete'. + * 'offer' makes a course visible to students. This action is also called "publish" on the web site. + * 'conclude' prevents future enrollments and makes a course read-only for all participants. The course still appears + in prior-enrollment lists. + * 'delete' completely removes the course from the web site (including course menus and prior-enrollment lists). + All enrollments are deleted. Course content may be physically deleted at a future date. + * 'undelete' attempts to recover a course that has been deleted. (Recovery is not guaranteed; please conclude + rather than delete a course if there is any possibility the course will be used again.) The recovered course + will be unpublished. Deleted enrollments will not be recovered. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - course_ids + """List of ids of courses to update. At most 500 courses may be updated in one call.""" + data["course_ids"] = course_ids + + # REQUIRED - event + """no description""" + self._validate_enum(event, ["offer", "conclude", "delete", "undelete"]) + data["event"] = event + + self.logger.debug("PUT /api/v1/accounts/{account_id}/courses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/courses".format(**path), data=data, params=params, single_item=True) + + def reset_course(self, course_id): + """ + Reset a course. + + Deletes the current course, and creates a new equivalent course with + no content, but all sections and users moved over. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("POST /api/v1/courses/{course_id}/reset_content with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/reset_content".format(**path), data=data, params=params, single_item=True) + + def get_effective_due_dates(self, course_id, assignment_ids=None): + """ + Get effective due dates. + + For each assignment in the course, returns each assigned student's ID + and their corresponding due date along with some Multiple Grading Periods + data. Returns a collection with keys representing assignment IDs and values + as a collection containing keys representing student IDs and values representing + the student's effective due_at, the grading_period_id of which the due_at falls + in, and whether or not the grading period is closed (in_closed_grading_period) + + The list of assignment IDs for which effective student due dates are + requested. If not provided, all assignments in the course will be used. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - assignment_ids + """no description""" + if assignment_ids is not None: + params["assignment_ids"] = assignment_ids + + self.logger.debug("GET /api/v1/courses/{course_id}/effective_due_dates with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/effective_due_dates".format(**path), data=data, params=params, single_item=True) + + def permissions(self, course_id, permissions=None): + """ + Permissions. + + Returns permission information for provided course & current_user + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - permissions + """List of permissions to check against authenticated user""" + if permissions is not None: + params["permissions"] = permissions + + self.logger.debug("GET /api/v1/courses/{course_id}/permissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/permissions".format(**path), data=data, params=params, no_data=True) + + def get_course_copy_status(self, id, course_id): + """ + Get course copy status. + + DEPRECATED: Please use the {api:ContentMigrationsController#create Content Migrations API} + + Retrieve the status of a course copy + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/course_copy/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/course_copy/{id}".format(**path), data=data, params=params, no_data=True) + + def copy_course_content(self, course_id, exclude=None, only=None, source_course=None): + """ + Copy course content. + + DEPRECATED: Please use the {api:ContentMigrationsController#create Content Migrations API} + + Copies content from one course into another. The default is to copy all course + content. You can control specific types to copy by using either the 'except' option + or the 'only' option. + + The response is the same as the course copy status endpoint + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - source_course + """ID or SIS-ID of the course to copy the content from""" + if source_course is not None: + data["source_course"] = source_course + + # OPTIONAL - except + """A list of the course content types to exclude, all areas not listed will + be copied.""" + if exclude is not None: + self._validate_enum(exclude, ["course_settings", "assignments", "external_tools", "files", "topics", "calendar_events", "quizzes", "wiki_pages", "modules", "outcomes"]) + data["except"] = exclude + + # OPTIONAL - only + """A list of the course content types to copy, all areas not listed will not + be copied.""" + if only is not None: + self._validate_enum(only, ["course_settings", "assignments", "external_tools", "files", "topics", "calendar_events", "quizzes", "wiki_pages", "modules", "outcomes"]) + data["only"] = only + + self.logger.debug("POST /api/v1/courses/{course_id}/course_copy with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/course_copy".format(**path), data=data, params=params, no_data=True) + + +class Course(BaseModel): + """Course Model.""" + + def __init__(self, open_enrollment=None, storage_quota_used_mb=None, is_public=None, calendar=None, allow_wiki_comments=None, id=None, public_syllabus_to_auth=None, default_view=None, is_public_to_auth_users=None, access_restricted_by_date=None, root_account_id=None, end_at=None, storage_quota_mb=None, self_enrollment=None, syllabus_body=None, start_at=None, account_id=None, workflow_state=None, public_syllabus=None, grading_standard_id=None, apply_assignment_group_weights=None, enrollment_term_id=None, course_format=None, enrollments=None, needs_grading_count=None, permissions=None, integration_id=None, term=None, name=None, license=None, allow_student_forum_attachments=None, restrict_enrollments_to_course_dates=None, time_zone=None, hide_final_grades=None, allow_student_assignment_edits=None, sis_course_id=None, course_progress=None, public_description=None, course_code=None, total_students=None): + """Init method for Course class.""" + self._open_enrollment = open_enrollment + self._storage_quota_used_mb = storage_quota_used_mb + self._is_public = is_public + self._calendar = calendar + self._allow_wiki_comments = allow_wiki_comments + self._id = id + self._public_syllabus_to_auth = public_syllabus_to_auth + self._default_view = default_view + self._is_public_to_auth_users = is_public_to_auth_users + self._access_restricted_by_date = access_restricted_by_date + self._root_account_id = root_account_id + self._end_at = end_at + self._storage_quota_mb = storage_quota_mb + self._self_enrollment = self_enrollment + self._syllabus_body = syllabus_body + self._start_at = start_at + self._account_id = account_id + self._workflow_state = workflow_state + self._public_syllabus = public_syllabus + self._grading_standard_id = grading_standard_id + self._apply_assignment_group_weights = apply_assignment_group_weights + self._enrollment_term_id = enrollment_term_id + self._course_format = course_format + self._enrollments = enrollments + self._needs_grading_count = needs_grading_count + self._permissions = permissions + self._integration_id = integration_id + self._term = term + self._name = name + self._license = license + self._allow_student_forum_attachments = allow_student_forum_attachments + self._restrict_enrollments_to_course_dates = restrict_enrollments_to_course_dates + self._time_zone = time_zone + self._hide_final_grades = hide_final_grades + self._allow_student_assignment_edits = allow_student_assignment_edits + self._sis_course_id = sis_course_id + self._course_progress = course_progress + self._public_description = public_description + self._course_code = course_code + self._total_students = total_students + + self.logger = logging.getLogger('pycanvas.Course') + + @property + def open_enrollment(self): + """open_enrollment.""" + return self._open_enrollment + + @open_enrollment.setter + def open_enrollment(self, value): + """Setter for open_enrollment property.""" + self.logger.warn("Setting values on open_enrollment will NOT update the remote Canvas instance.") + self._open_enrollment = value + + @property + def storage_quota_used_mb(self): + """storage_quota_used_mb.""" + return self._storage_quota_used_mb + + @storage_quota_used_mb.setter + def storage_quota_used_mb(self, value): + """Setter for storage_quota_used_mb property.""" + self.logger.warn("Setting values on storage_quota_used_mb will NOT update the remote Canvas instance.") + self._storage_quota_used_mb = value + + @property + def is_public(self): + """is_public.""" + return self._is_public + + @is_public.setter + def is_public(self, value): + """Setter for is_public property.""" + self.logger.warn("Setting values on is_public will NOT update the remote Canvas instance.") + self._is_public = value + + @property + def calendar(self): + """course calendar.""" + return self._calendar + + @calendar.setter + def calendar(self, value): + """Setter for calendar property.""" + self.logger.warn("Setting values on calendar will NOT update the remote Canvas instance.") + self._calendar = value + + @property + def allow_wiki_comments(self): + """allow_wiki_comments.""" + return self._allow_wiki_comments + + @allow_wiki_comments.setter + def allow_wiki_comments(self, value): + """Setter for allow_wiki_comments property.""" + self.logger.warn("Setting values on allow_wiki_comments will NOT update the remote Canvas instance.") + self._allow_wiki_comments = value + + @property + def id(self): + """the unique identifier for the course.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def public_syllabus_to_auth(self): + """public_syllabus_to_auth.""" + return self._public_syllabus_to_auth + + @public_syllabus_to_auth.setter + def public_syllabus_to_auth(self, value): + """Setter for public_syllabus_to_auth property.""" + self.logger.warn("Setting values on public_syllabus_to_auth will NOT update the remote Canvas instance.") + self._public_syllabus_to_auth = value + + @property + def default_view(self): + """the type of page that users will see when they first visit the course - 'feed': Recent Activity Dashboard - 'wiki': Wiki Front Page - 'modules': Course Modules/Sections Page - 'assignments': Course Assignments List - 'syllabus': Course Syllabus Page other types may be added in the future.""" + return self._default_view + + @default_view.setter + def default_view(self, value): + """Setter for default_view property.""" + self.logger.warn("Setting values on default_view will NOT update the remote Canvas instance.") + self._default_view = value + + @property + def is_public_to_auth_users(self): + """is_public_to_auth_users.""" + return self._is_public_to_auth_users + + @is_public_to_auth_users.setter + def is_public_to_auth_users(self, value): + """Setter for is_public_to_auth_users property.""" + self.logger.warn("Setting values on is_public_to_auth_users will NOT update the remote Canvas instance.") + self._is_public_to_auth_users = value + + @property + def access_restricted_by_date(self): + """optional: this will be true if this user is currently prevented from viewing the course because of date restriction settings.""" + return self._access_restricted_by_date + + @access_restricted_by_date.setter + def access_restricted_by_date(self, value): + """Setter for access_restricted_by_date property.""" + self.logger.warn("Setting values on access_restricted_by_date will NOT update the remote Canvas instance.") + self._access_restricted_by_date = value + + @property + def root_account_id(self): + """the root account associated with the course.""" + return self._root_account_id + + @root_account_id.setter + def root_account_id(self, value): + """Setter for root_account_id property.""" + self.logger.warn("Setting values on root_account_id will NOT update the remote Canvas instance.") + self._root_account_id = value + + @property + def end_at(self): + """the end date for the course, if applicable.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def storage_quota_mb(self): + """storage_quota_mb.""" + return self._storage_quota_mb + + @storage_quota_mb.setter + def storage_quota_mb(self, value): + """Setter for storage_quota_mb property.""" + self.logger.warn("Setting values on storage_quota_mb will NOT update the remote Canvas instance.") + self._storage_quota_mb = value + + @property + def self_enrollment(self): + """self_enrollment.""" + return self._self_enrollment + + @self_enrollment.setter + def self_enrollment(self, value): + """Setter for self_enrollment property.""" + self.logger.warn("Setting values on self_enrollment will NOT update the remote Canvas instance.") + self._self_enrollment = value + + @property + def syllabus_body(self): + """optional: user-generated HTML for the course syllabus.""" + return self._syllabus_body + + @syllabus_body.setter + def syllabus_body(self, value): + """Setter for syllabus_body property.""" + self.logger.warn("Setting values on syllabus_body will NOT update the remote Canvas instance.") + self._syllabus_body = value + + @property + def start_at(self): + """the start date for the course, if applicable.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def account_id(self): + """the account associated with the course.""" + return self._account_id + + @account_id.setter + def account_id(self, value): + """Setter for account_id property.""" + self.logger.warn("Setting values on account_id will NOT update the remote Canvas instance.") + self._account_id = value + + @property + def workflow_state(self): + """the current state of the course one of 'unpublished', 'available', 'completed', or 'deleted'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def public_syllabus(self): + """public_syllabus.""" + return self._public_syllabus + + @public_syllabus.setter + def public_syllabus(self, value): + """Setter for public_syllabus property.""" + self.logger.warn("Setting values on public_syllabus will NOT update the remote Canvas instance.") + self._public_syllabus = value + + @property + def grading_standard_id(self): + """the grading standard associated with the course.""" + return self._grading_standard_id + + @grading_standard_id.setter + def grading_standard_id(self, value): + """Setter for grading_standard_id property.""" + self.logger.warn("Setting values on grading_standard_id will NOT update the remote Canvas instance.") + self._grading_standard_id = value + + @property + def apply_assignment_group_weights(self): + """weight final grade based on assignment group percentages.""" + return self._apply_assignment_group_weights + + @apply_assignment_group_weights.setter + def apply_assignment_group_weights(self, value): + """Setter for apply_assignment_group_weights property.""" + self.logger.warn("Setting values on apply_assignment_group_weights will NOT update the remote Canvas instance.") + self._apply_assignment_group_weights = value + + @property + def enrollment_term_id(self): + """the enrollment term associated with the course.""" + return self._enrollment_term_id + + @enrollment_term_id.setter + def enrollment_term_id(self, value): + """Setter for enrollment_term_id property.""" + self.logger.warn("Setting values on enrollment_term_id will NOT update the remote Canvas instance.") + self._enrollment_term_id = value + + @property + def course_format(self): + """course_format.""" + return self._course_format + + @course_format.setter + def course_format(self, value): + """Setter for course_format property.""" + self.logger.warn("Setting values on course_format will NOT update the remote Canvas instance.") + self._course_format = value + + @property + def enrollments(self): + """A list of enrollments linking the current user to the course. for student enrollments, grading information may be included if include[]=total_scores.""" + return self._enrollments + + @enrollments.setter + def enrollments(self, value): + """Setter for enrollments property.""" + self.logger.warn("Setting values on enrollments will NOT update the remote Canvas instance.") + self._enrollments = value + + @property + def needs_grading_count(self): + """optional: the number of submissions needing grading returned only if the current user has grading rights and include[]=needs_grading_count.""" + return self._needs_grading_count + + @needs_grading_count.setter + def needs_grading_count(self, value): + """Setter for needs_grading_count property.""" + self.logger.warn("Setting values on needs_grading_count will NOT update the remote Canvas instance.") + self._needs_grading_count = value + + @property + def permissions(self): + """optional: the permissions the user has for the course. returned only for a single course and include[]=permissions.""" + return self._permissions + + @permissions.setter + def permissions(self, value): + """Setter for permissions property.""" + self.logger.warn("Setting values on permissions will NOT update the remote Canvas instance.") + self._permissions = value + + @property + def integration_id(self): + """the integration identifier for the course, if defined. This field is only included if the user has permission to view SIS information.""" + return self._integration_id + + @integration_id.setter + def integration_id(self, value): + """Setter for integration_id property.""" + self.logger.warn("Setting values on integration_id will NOT update the remote Canvas instance.") + self._integration_id = value + + @property + def term(self): + """optional: the enrollment term object for the course returned only if include[]=term.""" + return self._term + + @term.setter + def term(self, value): + """Setter for term property.""" + self.logger.warn("Setting values on term will NOT update the remote Canvas instance.") + self._term = value + + @property + def name(self): + """the full name of the course.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def license(self): + """license.""" + return self._license + + @license.setter + def license(self, value): + """Setter for license property.""" + self.logger.warn("Setting values on license will NOT update the remote Canvas instance.") + self._license = value + + @property + def allow_student_forum_attachments(self): + """allow_student_forum_attachments.""" + return self._allow_student_forum_attachments + + @allow_student_forum_attachments.setter + def allow_student_forum_attachments(self, value): + """Setter for allow_student_forum_attachments property.""" + self.logger.warn("Setting values on allow_student_forum_attachments will NOT update the remote Canvas instance.") + self._allow_student_forum_attachments = value + + @property + def restrict_enrollments_to_course_dates(self): + """restrict_enrollments_to_course_dates.""" + return self._restrict_enrollments_to_course_dates + + @restrict_enrollments_to_course_dates.setter + def restrict_enrollments_to_course_dates(self, value): + """Setter for restrict_enrollments_to_course_dates property.""" + self.logger.warn("Setting values on restrict_enrollments_to_course_dates will NOT update the remote Canvas instance.") + self._restrict_enrollments_to_course_dates = value + + @property + def time_zone(self): + """The course's IANA time zone name.""" + return self._time_zone + + @time_zone.setter + def time_zone(self, value): + """Setter for time_zone property.""" + self.logger.warn("Setting values on time_zone will NOT update the remote Canvas instance.") + self._time_zone = value + + @property + def hide_final_grades(self): + """hide_final_grades.""" + return self._hide_final_grades + + @hide_final_grades.setter + def hide_final_grades(self, value): + """Setter for hide_final_grades property.""" + self.logger.warn("Setting values on hide_final_grades will NOT update the remote Canvas instance.") + self._hide_final_grades = value + + @property + def allow_student_assignment_edits(self): + """allow_student_assignment_edits.""" + return self._allow_student_assignment_edits + + @allow_student_assignment_edits.setter + def allow_student_assignment_edits(self, value): + """Setter for allow_student_assignment_edits property.""" + self.logger.warn("Setting values on allow_student_assignment_edits will NOT update the remote Canvas instance.") + self._allow_student_assignment_edits = value + + @property + def sis_course_id(self): + """the SIS identifier for the course, if defined. This field is only included if the user has permission to view SIS information.""" + return self._sis_course_id + + @sis_course_id.setter + def sis_course_id(self, value): + """Setter for sis_course_id property.""" + self.logger.warn("Setting values on sis_course_id will NOT update the remote Canvas instance.") + self._sis_course_id = value + + @property + def course_progress(self): + """optional (beta): information on progress through the course returned only if include[]=course_progress.""" + return self._course_progress + + @course_progress.setter + def course_progress(self, value): + """Setter for course_progress property.""" + self.logger.warn("Setting values on course_progress will NOT update the remote Canvas instance.") + self._course_progress = value + + @property + def public_description(self): + """optional: the public description of the course.""" + return self._public_description + + @public_description.setter + def public_description(self, value): + """Setter for public_description property.""" + self.logger.warn("Setting values on public_description will NOT update the remote Canvas instance.") + self._public_description = value + + @property + def course_code(self): + """the course code.""" + return self._course_code + + @course_code.setter + def course_code(self, value): + """Setter for course_code property.""" + self.logger.warn("Setting values on course_code will NOT update the remote Canvas instance.") + self._course_code = value + + @property + def total_students(self): + """optional: the total number of active and invited students in the course.""" + return self._total_students + + @total_students.setter + def total_students(self, value): + """Setter for total_students property.""" + self.logger.warn("Setting values on total_students will NOT update the remote Canvas instance.") + self._total_students = value + + +class Term(BaseModel): + """Term Model.""" + + def __init__(self, end_at=None, start_at=None, id=None, name=None): + """Init method for Term class.""" + self._end_at = end_at + self._start_at = start_at + self._id = id + self._name = name + + self.logger = logging.getLogger('pycanvas.Term') + + @property + def end_at(self): + """end_at.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def start_at(self): + """start_at.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def id(self): + """id.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def name(self): + """name.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class Courseprogress(BaseModel): + """Courseprogress Model.""" + + def __init__(self, requirement_count=None, next_requirement_url=None, requirement_completed_count=None, completed_at=None): + """Init method for Courseprogress class.""" + self._requirement_count = requirement_count + self._next_requirement_url = next_requirement_url + self._requirement_completed_count = requirement_completed_count + self._completed_at = completed_at + + self.logger = logging.getLogger('pycanvas.Courseprogress') + + @property + def requirement_count(self): + """total number of requirements from all modules.""" + return self._requirement_count + + @requirement_count.setter + def requirement_count(self, value): + """Setter for requirement_count property.""" + self.logger.warn("Setting values on requirement_count will NOT update the remote Canvas instance.") + self._requirement_count = value + + @property + def next_requirement_url(self): + """url to next module item that has an unmet requirement. null if the user has completed the course or the current module does not require sequential progress.""" + return self._next_requirement_url + + @next_requirement_url.setter + def next_requirement_url(self, value): + """Setter for next_requirement_url property.""" + self.logger.warn("Setting values on next_requirement_url will NOT update the remote Canvas instance.") + self._next_requirement_url = value + + @property + def requirement_completed_count(self): + """total number of requirements the user has completed from all modules.""" + return self._requirement_completed_count + + @requirement_completed_count.setter + def requirement_completed_count(self, value): + """Setter for requirement_completed_count property.""" + self.logger.warn("Setting values on requirement_completed_count will NOT update the remote Canvas instance.") + self._requirement_completed_count = value + + @property + def completed_at(self): + """date the course was completed. null if the course has not been completed by this user.""" + return self._completed_at + + @completed_at.setter + def completed_at(self, value): + """Setter for completed_at property.""" + self.logger.warn("Setting values on completed_at will NOT update the remote Canvas instance.") + self._completed_at = value + + +class Calendarlink(BaseModel): + """Calendarlink Model.""" + + def __init__(self, ics=None): + """Init method for Calendarlink class.""" + self._ics = ics + + self.logger = logging.getLogger('pycanvas.Calendarlink') + + @property + def ics(self): + """The URL of the calendar in ICS format.""" + return self._ics + + @ics.setter + def ics(self, value): + """Setter for ics property.""" + self.logger.warn("Setting values on ics will NOT update the remote Canvas instance.") + self._ics = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/custom_gradebook_columns.py b/venv/Lib/site-packages/pycanvas/apis/custom_gradebook_columns.py new file mode 100644 index 00000000..303b5df1 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/custom_gradebook_columns.py @@ -0,0 +1,278 @@ +"""CustomGradebookColumns API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class CustomGradebookColumnsAPI(BaseCanvasAPI): + """CustomGradebookColumns API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for CustomGradebookColumnsAPI.""" + super(CustomGradebookColumnsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.CustomGradebookColumnsAPI") + + def list_custom_gradebook_columns(self, course_id, include_hidden=None): + """ + List custom gradebook columns. + + List all custom gradebook columns for a course + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - include_hidden + """Include hidden parameters (defaults to false)""" + if include_hidden is not None: + params["include_hidden"] = include_hidden + + self.logger.debug("GET /api/v1/courses/{course_id}/custom_gradebook_columns with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/custom_gradebook_columns".format(**path), data=data, params=params, all_pages=True) + + def create_custom_gradebook_column(self, course_id, column_title, column_hidden=None, column_position=None, column_teacher_notes=None): + """ + Create a custom gradebook column. + + Create a custom gradebook column + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - column[title] + """no description""" + data["column[title]"] = column_title + + # OPTIONAL - column[position] + """The position of the column relative to other custom columns""" + if column_position is not None: + data["column[position]"] = column_position + + # OPTIONAL - column[hidden] + """Hidden columns are not displayed in the gradebook""" + if column_hidden is not None: + data["column[hidden]"] = column_hidden + + # OPTIONAL - column[teacher_notes] + """Set this if the column is created by a teacher. The gradebook only + supports one teacher_notes column.""" + if column_teacher_notes is not None: + data["column[teacher_notes]"] = column_teacher_notes + + self.logger.debug("POST /api/v1/courses/{course_id}/custom_gradebook_columns with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/custom_gradebook_columns".format(**path), data=data, params=params, single_item=True) + + def update_custom_gradebook_column(self, id, course_id): + """ + Update a custom gradebook column. + + Accepts the same parameters as custom gradebook column creation + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/courses/{course_id}/custom_gradebook_columns/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/custom_gradebook_columns/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_custom_gradebook_column(self, id, course_id): + """ + Delete a custom gradebook column. + + Permanently deletes a custom column and its associated data + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/custom_gradebook_columns/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/custom_gradebook_columns/{id}".format(**path), data=data, params=params, single_item=True) + + def reorder_custom_columns(self, order, course_id): + """ + Reorder custom columns. + + Puts the given columns in the specified order + + 200 OK is returned if successful + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - order + """no description""" + data["order"] = order + + self.logger.debug("POST /api/v1/courses/{course_id}/custom_gradebook_columns/reorder with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/custom_gradebook_columns/reorder".format(**path), data=data, params=params, no_data=True) + + def list_entries_for_column(self, id, course_id, include_hidden=None): + """ + List entries for a column. + + This does not list entries for students without associated data. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include_hidden + """If true, hidden columns will be included in the + result. If false or absent, only visible columns + will be returned.""" + if include_hidden is not None: + params["include_hidden"] = include_hidden + + self.logger.debug("GET /api/v1/courses/{course_id}/custom_gradebook_columns/{id}/data with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/custom_gradebook_columns/{id}/data".format(**path), data=data, params=params, all_pages=True) + + def update_column_data(self, id, user_id, course_id, column_data_content): + """ + Update column data. + + Set the content of a custom column + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - column_data[content] + """Column content. Setting this to blank will delete the datum object.""" + data["column_data[content]"] = column_data_content + + self.logger.debug("PUT /api/v1/courses/{course_id}/custom_gradebook_columns/{id}/data/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/custom_gradebook_columns/{id}/data/{user_id}".format(**path), data=data, params=params, single_item=True) + + +class Columndatum(BaseModel): + """Columndatum Model. + ColumnDatum objects contain the entry for a column for each user.""" + + def __init__(self, content=None, user_id=None): + """Init method for Columndatum class.""" + self._content = content + self._user_id = user_id + + self.logger = logging.getLogger('pycanvas.Columndatum') + + @property + def content(self): + """content.""" + return self._content + + @content.setter + def content(self, value): + """Setter for content property.""" + self.logger.warn("Setting values on content will NOT update the remote Canvas instance.") + self._content = value + + @property + def user_id(self): + """user_id.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + +class Customcolumn(BaseModel): + """Customcolumn Model.""" + + def __init__(self, position=None, hidden=None, title=None): + """Init method for Customcolumn class.""" + self._position = position + self._hidden = hidden + self._title = title + + self.logger = logging.getLogger('pycanvas.Customcolumn') + + @property + def position(self): + """column order.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def hidden(self): + """won't be displayed if hidden is true.""" + return self._hidden + + @hidden.setter + def hidden(self, value): + """Setter for hidden property.""" + self.logger.warn("Setting values on hidden will NOT update the remote Canvas instance.") + self._hidden = value + + @property + def title(self): + """header text.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/discussion_topics.py b/venv/Lib/site-packages/pycanvas/apis/discussion_topics.py new file mode 100644 index 00000000..4aaa0f30 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/discussion_topics.py @@ -0,0 +1,2312 @@ +"""DiscussionTopics API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class DiscussionTopicsAPI(BaseCanvasAPI): + """DiscussionTopics API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for DiscussionTopicsAPI.""" + super(DiscussionTopicsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.DiscussionTopicsAPI") + + def list_discussion_topics_courses(self, course_id, exclude_context_module_locked_topics=None, include=None, only_announcements=None, order_by=None, scope=None, search_term=None): + """ + List discussion topics. + + Returns the paginated list of discussion topics for this course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - include + """If "all_dates" is passed, all dates associated with graded discussions' + assignments will be included.""" + if include is not None: + self._validate_enum(include, ["all_dates"]) + params["include"] = include + + # OPTIONAL - order_by + """Determines the order of the discussion topic list. Defaults to "position".""" + if order_by is not None: + self._validate_enum(order_by, ["position", "recent_activity"]) + params["order_by"] = order_by + + # OPTIONAL - scope + """Only return discussion topics in the given state(s). Defaults to including + all topics. Filtering is done after pagination, so pages + may be smaller than requested if topics are filtered. + Can pass multiple states as comma separated string.""" + if scope is not None: + self._validate_enum(scope, ["locked", "unlocked", "pinned", "unpinned"]) + params["scope"] = scope + + # OPTIONAL - only_announcements + """Return announcements instead of discussion topics. Defaults to false""" + if only_announcements is not None: + params["only_announcements"] = only_announcements + + # OPTIONAL - search_term + """The partial title of the discussion topics to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - exclude_context_module_locked_topics + """For students, exclude topics that are locked by module progression. + Defaults to false.""" + if exclude_context_module_locked_topics is not None: + params["exclude_context_module_locked_topics"] = exclude_context_module_locked_topics + + self.logger.debug("GET /api/v1/courses/{course_id}/discussion_topics with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/discussion_topics".format(**path), data=data, params=params, all_pages=True) + + def list_discussion_topics_groups(self, group_id, exclude_context_module_locked_topics=None, include=None, only_announcements=None, order_by=None, scope=None, search_term=None): + """ + List discussion topics. + + Returns the paginated list of discussion topics for this course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - include + """If "all_dates" is passed, all dates associated with graded discussions' + assignments will be included.""" + if include is not None: + self._validate_enum(include, ["all_dates"]) + params["include"] = include + + # OPTIONAL - order_by + """Determines the order of the discussion topic list. Defaults to "position".""" + if order_by is not None: + self._validate_enum(order_by, ["position", "recent_activity"]) + params["order_by"] = order_by + + # OPTIONAL - scope + """Only return discussion topics in the given state(s). Defaults to including + all topics. Filtering is done after pagination, so pages + may be smaller than requested if topics are filtered. + Can pass multiple states as comma separated string.""" + if scope is not None: + self._validate_enum(scope, ["locked", "unlocked", "pinned", "unpinned"]) + params["scope"] = scope + + # OPTIONAL - only_announcements + """Return announcements instead of discussion topics. Defaults to false""" + if only_announcements is not None: + params["only_announcements"] = only_announcements + + # OPTIONAL - search_term + """The partial title of the discussion topics to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - exclude_context_module_locked_topics + """For students, exclude topics that are locked by module progression. + Defaults to false.""" + if exclude_context_module_locked_topics is not None: + params["exclude_context_module_locked_topics"] = exclude_context_module_locked_topics + + self.logger.debug("GET /api/v1/groups/{group_id}/discussion_topics with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/discussion_topics".format(**path), data=data, params=params, all_pages=True) + + def create_new_discussion_topic_courses(self, course_id, allow_rating=None, assignment=None, attachment=None, delayed_post_at=None, discussion_type=None, group_category_id=None, is_announcement=None, lock_at=None, message=None, only_graders_can_rate=None, pinned=None, podcast_enabled=None, podcast_has_student_posts=None, position_after=None, published=None, require_initial_post=None, sort_by_rating=None, title=None): + """ + Create a new discussion topic. + + Create an new discussion topic for the course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - title + """no description""" + if title is not None: + data["title"] = title + + # OPTIONAL - message + """no description""" + if message is not None: + data["message"] = message + + # OPTIONAL - discussion_type + """The type of discussion. Defaults to side_comment if not value is given. Accepted values are 'side_comment', for discussions that only allow one level of nested comments, and 'threaded' for fully threaded discussions.""" + if discussion_type is not None: + self._validate_enum(discussion_type, ["side_comment", "threaded"]) + data["discussion_type"] = discussion_type + + # OPTIONAL - published + """Whether this topic is published (true) or draft state (false). Only + teachers and TAs have the ability to create draft state topics.""" + if published is not None: + data["published"] = published + + # OPTIONAL - delayed_post_at + """If a timestamp is given, the topic will not be published until that time.""" + if delayed_post_at is not None: + data["delayed_post_at"] = delayed_post_at + + # OPTIONAL - lock_at + """If a timestamp is given, the topic will be scheduled to lock at the + provided timestamp. If the timestamp is in the past, the topic will be + locked.""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - podcast_enabled + """If true, the topic will have an associated podcast feed.""" + if podcast_enabled is not None: + data["podcast_enabled"] = podcast_enabled + + # OPTIONAL - podcast_has_student_posts + """If true, the podcast will include posts from students as well. Implies + podcast_enabled.""" + if podcast_has_student_posts is not None: + data["podcast_has_student_posts"] = podcast_has_student_posts + + # OPTIONAL - require_initial_post + """If true then a user may not respond to other replies until that user has + made an initial reply. Defaults to false.""" + if require_initial_post is not None: + data["require_initial_post"] = require_initial_post + + # OPTIONAL - assignment + """To create an assignment discussion, pass the assignment parameters as a + sub-object. See the {api:AssignmentsApiController#create Create an Assignment API} + for the available parameters. The name parameter will be ignored, as it's + taken from the discussion title. If you want to make a discussion that was + an assignment NOT an assignment, pass set_assignment = false as part of + the assignment object""" + if assignment is not None: + data["assignment"] = assignment + + # OPTIONAL - is_announcement + """If true, this topic is an announcement. It will appear in the + announcement's section rather than the discussions section. This requires + announcment-posting permissions.""" + if is_announcement is not None: + data["is_announcement"] = is_announcement + + # OPTIONAL - pinned + """If true, this topic will be listed in the "Pinned Discussion" section""" + if pinned is not None: + data["pinned"] = pinned + + # OPTIONAL - position_after + """By default, discussions are sorted chronologically by creation date, you + can pass the id of another topic to have this one show up after the other + when they are listed.""" + if position_after is not None: + data["position_after"] = position_after + + # OPTIONAL - group_category_id + """If present, the topic will become a group discussion assigned + to the group.""" + if group_category_id is not None: + data["group_category_id"] = group_category_id + + # OPTIONAL - allow_rating + """If true, users will be allowed to rate entries.""" + if allow_rating is not None: + data["allow_rating"] = allow_rating + + # OPTIONAL - only_graders_can_rate + """If true, only graders will be allowed to rate entries.""" + if only_graders_can_rate is not None: + data["only_graders_can_rate"] = only_graders_can_rate + + # OPTIONAL - sort_by_rating + """If true, entries will be sorted by rating.""" + if sort_by_rating is not None: + data["sort_by_rating"] = sort_by_rating + + # OPTIONAL - attachment + """A multipart/form-data form-field-style attachment. + Attachments larger than 1 kilobyte are subject to quota restrictions.""" + if attachment is not None: + data["attachment"] = attachment + + self.logger.debug("POST /api/v1/courses/{course_id}/discussion_topics with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/discussion_topics".format(**path), data=data, params=params, no_data=True) + + def create_new_discussion_topic_groups(self, group_id, allow_rating=None, assignment=None, attachment=None, delayed_post_at=None, discussion_type=None, group_category_id=None, is_announcement=None, lock_at=None, message=None, only_graders_can_rate=None, pinned=None, podcast_enabled=None, podcast_has_student_posts=None, position_after=None, published=None, require_initial_post=None, sort_by_rating=None, title=None): + """ + Create a new discussion topic. + + Create an new discussion topic for the course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - title + """no description""" + if title is not None: + data["title"] = title + + # OPTIONAL - message + """no description""" + if message is not None: + data["message"] = message + + # OPTIONAL - discussion_type + """The type of discussion. Defaults to side_comment if not value is given. Accepted values are 'side_comment', for discussions that only allow one level of nested comments, and 'threaded' for fully threaded discussions.""" + if discussion_type is not None: + self._validate_enum(discussion_type, ["side_comment", "threaded"]) + data["discussion_type"] = discussion_type + + # OPTIONAL - published + """Whether this topic is published (true) or draft state (false). Only + teachers and TAs have the ability to create draft state topics.""" + if published is not None: + data["published"] = published + + # OPTIONAL - delayed_post_at + """If a timestamp is given, the topic will not be published until that time.""" + if delayed_post_at is not None: + data["delayed_post_at"] = delayed_post_at + + # OPTIONAL - lock_at + """If a timestamp is given, the topic will be scheduled to lock at the + provided timestamp. If the timestamp is in the past, the topic will be + locked.""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - podcast_enabled + """If true, the topic will have an associated podcast feed.""" + if podcast_enabled is not None: + data["podcast_enabled"] = podcast_enabled + + # OPTIONAL - podcast_has_student_posts + """If true, the podcast will include posts from students as well. Implies + podcast_enabled.""" + if podcast_has_student_posts is not None: + data["podcast_has_student_posts"] = podcast_has_student_posts + + # OPTIONAL - require_initial_post + """If true then a user may not respond to other replies until that user has + made an initial reply. Defaults to false.""" + if require_initial_post is not None: + data["require_initial_post"] = require_initial_post + + # OPTIONAL - assignment + """To create an assignment discussion, pass the assignment parameters as a + sub-object. See the {api:AssignmentsApiController#create Create an Assignment API} + for the available parameters. The name parameter will be ignored, as it's + taken from the discussion title. If you want to make a discussion that was + an assignment NOT an assignment, pass set_assignment = false as part of + the assignment object""" + if assignment is not None: + data["assignment"] = assignment + + # OPTIONAL - is_announcement + """If true, this topic is an announcement. It will appear in the + announcement's section rather than the discussions section. This requires + announcment-posting permissions.""" + if is_announcement is not None: + data["is_announcement"] = is_announcement + + # OPTIONAL - pinned + """If true, this topic will be listed in the "Pinned Discussion" section""" + if pinned is not None: + data["pinned"] = pinned + + # OPTIONAL - position_after + """By default, discussions are sorted chronologically by creation date, you + can pass the id of another topic to have this one show up after the other + when they are listed.""" + if position_after is not None: + data["position_after"] = position_after + + # OPTIONAL - group_category_id + """If present, the topic will become a group discussion assigned + to the group.""" + if group_category_id is not None: + data["group_category_id"] = group_category_id + + # OPTIONAL - allow_rating + """If true, users will be allowed to rate entries.""" + if allow_rating is not None: + data["allow_rating"] = allow_rating + + # OPTIONAL - only_graders_can_rate + """If true, only graders will be allowed to rate entries.""" + if only_graders_can_rate is not None: + data["only_graders_can_rate"] = only_graders_can_rate + + # OPTIONAL - sort_by_rating + """If true, entries will be sorted by rating.""" + if sort_by_rating is not None: + data["sort_by_rating"] = sort_by_rating + + # OPTIONAL - attachment + """A multipart/form-data form-field-style attachment. + Attachments larger than 1 kilobyte are subject to quota restrictions.""" + if attachment is not None: + data["attachment"] = attachment + + self.logger.debug("POST /api/v1/groups/{group_id}/discussion_topics with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/discussion_topics".format(**path), data=data, params=params, no_data=True) + + def update_topic_courses(self, topic_id, course_id, allow_rating=None, assignment=None, delayed_post_at=None, discussion_type=None, group_category_id=None, is_announcement=None, lock_at=None, message=None, only_graders_can_rate=None, pinned=None, podcast_enabled=None, podcast_has_student_posts=None, position_after=None, published=None, require_initial_post=None, sort_by_rating=None, title=None): + """ + Update a topic. + + Update an existing discussion topic for the course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - title + """no description""" + if title is not None: + data["title"] = title + + # OPTIONAL - message + """no description""" + if message is not None: + data["message"] = message + + # OPTIONAL - discussion_type + """The type of discussion. Defaults to side_comment if not value is given. Accepted values are 'side_comment', for discussions that only allow one level of nested comments, and 'threaded' for fully threaded discussions.""" + if discussion_type is not None: + self._validate_enum(discussion_type, ["side_comment", "threaded"]) + data["discussion_type"] = discussion_type + + # OPTIONAL - published + """Whether this topic is published (true) or draft state (false). Only + teachers and TAs have the ability to create draft state topics.""" + if published is not None: + data["published"] = published + + # OPTIONAL - delayed_post_at + """If a timestamp is given, the topic will not be published until that time.""" + if delayed_post_at is not None: + data["delayed_post_at"] = delayed_post_at + + # OPTIONAL - lock_at + """If a timestamp is given, the topic will be scheduled to lock at the + provided timestamp. If the timestamp is in the past, the topic will be + locked.""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - podcast_enabled + """If true, the topic will have an associated podcast feed.""" + if podcast_enabled is not None: + data["podcast_enabled"] = podcast_enabled + + # OPTIONAL - podcast_has_student_posts + """If true, the podcast will include posts from students as well. Implies + podcast_enabled.""" + if podcast_has_student_posts is not None: + data["podcast_has_student_posts"] = podcast_has_student_posts + + # OPTIONAL - require_initial_post + """If true then a user may not respond to other replies until that user has + made an initial reply. Defaults to false.""" + if require_initial_post is not None: + data["require_initial_post"] = require_initial_post + + # OPTIONAL - assignment + """To create an assignment discussion, pass the assignment parameters as a + sub-object. See the {api:AssignmentsApiController#create Create an Assignment API} + for the available parameters. The name parameter will be ignored, as it's + taken from the discussion title. If you want to make a discussion that was + an assignment NOT an assignment, pass set_assignment = false as part of + the assignment object""" + if assignment is not None: + data["assignment"] = assignment + + # OPTIONAL - is_announcement + """If true, this topic is an announcement. It will appear in the + announcement's section rather than the discussions section. This requires + announcment-posting permissions.""" + if is_announcement is not None: + data["is_announcement"] = is_announcement + + # OPTIONAL - pinned + """If true, this topic will be listed in the "Pinned Discussion" section""" + if pinned is not None: + data["pinned"] = pinned + + # OPTIONAL - position_after + """By default, discussions are sorted chronologically by creation date, you + can pass the id of another topic to have this one show up after the other + when they are listed.""" + if position_after is not None: + data["position_after"] = position_after + + # OPTIONAL - group_category_id + """If present, the topic will become a group discussion assigned + to the group.""" + if group_category_id is not None: + data["group_category_id"] = group_category_id + + # OPTIONAL - allow_rating + """If true, users will be allowed to rate entries.""" + if allow_rating is not None: + data["allow_rating"] = allow_rating + + # OPTIONAL - only_graders_can_rate + """If true, only graders will be allowed to rate entries.""" + if only_graders_can_rate is not None: + data["only_graders_can_rate"] = only_graders_can_rate + + # OPTIONAL - sort_by_rating + """If true, entries will be sorted by rating.""" + if sort_by_rating is not None: + data["sort_by_rating"] = sort_by_rating + + self.logger.debug("PUT /api/v1/courses/{course_id}/discussion_topics/{topic_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}".format(**path), data=data, params=params, no_data=True) + + def update_topic_groups(self, group_id, topic_id, allow_rating=None, assignment=None, delayed_post_at=None, discussion_type=None, group_category_id=None, is_announcement=None, lock_at=None, message=None, only_graders_can_rate=None, pinned=None, podcast_enabled=None, podcast_has_student_posts=None, position_after=None, published=None, require_initial_post=None, sort_by_rating=None, title=None): + """ + Update a topic. + + Update an existing discussion topic for the course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - title + """no description""" + if title is not None: + data["title"] = title + + # OPTIONAL - message + """no description""" + if message is not None: + data["message"] = message + + # OPTIONAL - discussion_type + """The type of discussion. Defaults to side_comment if not value is given. Accepted values are 'side_comment', for discussions that only allow one level of nested comments, and 'threaded' for fully threaded discussions.""" + if discussion_type is not None: + self._validate_enum(discussion_type, ["side_comment", "threaded"]) + data["discussion_type"] = discussion_type + + # OPTIONAL - published + """Whether this topic is published (true) or draft state (false). Only + teachers and TAs have the ability to create draft state topics.""" + if published is not None: + data["published"] = published + + # OPTIONAL - delayed_post_at + """If a timestamp is given, the topic will not be published until that time.""" + if delayed_post_at is not None: + data["delayed_post_at"] = delayed_post_at + + # OPTIONAL - lock_at + """If a timestamp is given, the topic will be scheduled to lock at the + provided timestamp. If the timestamp is in the past, the topic will be + locked.""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - podcast_enabled + """If true, the topic will have an associated podcast feed.""" + if podcast_enabled is not None: + data["podcast_enabled"] = podcast_enabled + + # OPTIONAL - podcast_has_student_posts + """If true, the podcast will include posts from students as well. Implies + podcast_enabled.""" + if podcast_has_student_posts is not None: + data["podcast_has_student_posts"] = podcast_has_student_posts + + # OPTIONAL - require_initial_post + """If true then a user may not respond to other replies until that user has + made an initial reply. Defaults to false.""" + if require_initial_post is not None: + data["require_initial_post"] = require_initial_post + + # OPTIONAL - assignment + """To create an assignment discussion, pass the assignment parameters as a + sub-object. See the {api:AssignmentsApiController#create Create an Assignment API} + for the available parameters. The name parameter will be ignored, as it's + taken from the discussion title. If you want to make a discussion that was + an assignment NOT an assignment, pass set_assignment = false as part of + the assignment object""" + if assignment is not None: + data["assignment"] = assignment + + # OPTIONAL - is_announcement + """If true, this topic is an announcement. It will appear in the + announcement's section rather than the discussions section. This requires + announcment-posting permissions.""" + if is_announcement is not None: + data["is_announcement"] = is_announcement + + # OPTIONAL - pinned + """If true, this topic will be listed in the "Pinned Discussion" section""" + if pinned is not None: + data["pinned"] = pinned + + # OPTIONAL - position_after + """By default, discussions are sorted chronologically by creation date, you + can pass the id of another topic to have this one show up after the other + when they are listed.""" + if position_after is not None: + data["position_after"] = position_after + + # OPTIONAL - group_category_id + """If present, the topic will become a group discussion assigned + to the group.""" + if group_category_id is not None: + data["group_category_id"] = group_category_id + + # OPTIONAL - allow_rating + """If true, users will be allowed to rate entries.""" + if allow_rating is not None: + data["allow_rating"] = allow_rating + + # OPTIONAL - only_graders_can_rate + """If true, only graders will be allowed to rate entries.""" + if only_graders_can_rate is not None: + data["only_graders_can_rate"] = only_graders_can_rate + + # OPTIONAL - sort_by_rating + """If true, entries will be sorted by rating.""" + if sort_by_rating is not None: + data["sort_by_rating"] = sort_by_rating + + self.logger.debug("PUT /api/v1/groups/{group_id}/discussion_topics/{topic_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}".format(**path), data=data, params=params, no_data=True) + + def delete_topic_courses(self, topic_id, course_id): + """ + Delete a topic. + + Deletes the discussion topic. This will also delete the assignment, if it's + an assignment discussion. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/discussion_topics/{topic_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}".format(**path), data=data, params=params, no_data=True) + + def delete_topic_groups(self, group_id, topic_id): + """ + Delete a topic. + + Deletes the discussion topic. This will also delete the assignment, if it's + an assignment discussion. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("DELETE /api/v1/groups/{group_id}/discussion_topics/{topic_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}".format(**path), data=data, params=params, no_data=True) + + def reorder_pinned_topics_courses(self, order, course_id): + """ + Reorder pinned topics. + + Puts the pinned discussion topics in the specified order. + All pinned topics should be included. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - order + """The ids of the pinned discussion topics in the desired order. + (For example, "order=104,102,103".)""" + data["order"] = order + + self.logger.debug("POST /api/v1/courses/{course_id}/discussion_topics/reorder with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/discussion_topics/reorder".format(**path), data=data, params=params, no_data=True) + + def reorder_pinned_topics_groups(self, order, group_id): + """ + Reorder pinned topics. + + Puts the pinned discussion topics in the specified order. + All pinned topics should be included. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - order + """The ids of the pinned discussion topics in the desired order. + (For example, "order=104,102,103".)""" + data["order"] = order + + self.logger.debug("POST /api/v1/groups/{group_id}/discussion_topics/reorder with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/discussion_topics/reorder".format(**path), data=data, params=params, no_data=True) + + def update_entry_courses(self, id, topic_id, course_id, message=None): + """ + Update an entry. + + Update an existing discussion entry. + + The entry must have been created by the current user, or the current user + must have admin rights to the discussion. If the edit is not allowed, a 401 will be returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - message + """The updated body of the entry.""" + if message is not None: + data["message"] = message + + self.logger.debug("PUT /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{id}".format(**path), data=data, params=params, no_data=True) + + def update_entry_groups(self, id, group_id, topic_id, message=None): + """ + Update an entry. + + Update an existing discussion entry. + + The entry must have been created by the current user, or the current user + must have admin rights to the discussion. If the edit is not allowed, a 401 will be returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - message + """The updated body of the entry.""" + if message is not None: + data["message"] = message + + self.logger.debug("PUT /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_entry_courses(self, id, topic_id, course_id): + """ + Delete an entry. + + Delete a discussion entry. + + The entry must have been created by the current user, or the current user + must have admin rights to the discussion. If the delete is not allowed, a 401 will be returned. + + The discussion will be marked deleted, and the user_id and message will be cleared out. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_entry_groups(self, id, group_id, topic_id): + """ + Delete an entry. + + Delete a discussion entry. + + The entry must have been created by the current user, or the current user + must have admin rights to the discussion. If the delete is not allowed, a 401 will be returned. + + The discussion will be marked deleted, and the user_id and message will be cleared out. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{id}".format(**path), data=data, params=params, no_data=True) + + def get_single_topic_courses(self, topic_id, course_id): + """ + Get a single topic. + + Returns data on an individual discussion topic. See the List action for the response formatting. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("GET /api/v1/courses/{course_id}/discussion_topics/{topic_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}".format(**path), data=data, params=params, no_data=True) + + def get_single_topic_groups(self, group_id, topic_id): + """ + Get a single topic. + + Returns data on an individual discussion topic. See the List action for the response formatting. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("GET /api/v1/groups/{group_id}/discussion_topics/{topic_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}".format(**path), data=data, params=params, no_data=True) + + def get_full_topic_courses(self, topic_id, course_id): + """ + Get the full topic. + + Return a cached structure of the discussion topic, containing all entries, + their authors, and their message bodies. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + + In some rare situations, this cached structure may not be available yet. In + that case, the server will respond with a 503 error, and the caller should + try again soon. + + The response is an object containing the following keys: + * "participants": A list of summary information on users who have posted to + the discussion. Each value is an object containing their id, display_name, + and avatar_url. + * "unread_entries": A list of entry ids that are unread by the current + user. this implies that any entry not in this list is read. + * "entry_ratings": A map of entry ids to ratings by the current user. Entries + not in this list have no rating. Only populated if rating is enabled. + * "forced_entries": A list of entry ids that have forced_read_state set to + true. This flag is meant to indicate the entry's read_state has been + manually set to 'unread' by the user, so the entry should not be + automatically marked as read. + * "view": A threaded view of all the entries in the discussion, containing + the id, user_id, and message. + * "new_entries": Because this view is eventually consistent, it's possible + that newly created or updated entries won't yet be reflected in the view. + If the application wants to also get a flat list of all entries not yet + reflected in the view, pass include_new_entries=1 to the request and this + array of entries will be returned. These entries are returned in a flat + array, in ascending created_at order. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("GET /api/v1/courses/{course_id}/discussion_topics/{topic_id}/view with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/view".format(**path), data=data, params=params, no_data=True) + + def get_full_topic_groups(self, group_id, topic_id): + """ + Get the full topic. + + Return a cached structure of the discussion topic, containing all entries, + their authors, and their message bodies. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + + In some rare situations, this cached structure may not be available yet. In + that case, the server will respond with a 503 error, and the caller should + try again soon. + + The response is an object containing the following keys: + * "participants": A list of summary information on users who have posted to + the discussion. Each value is an object containing their id, display_name, + and avatar_url. + * "unread_entries": A list of entry ids that are unread by the current + user. this implies that any entry not in this list is read. + * "entry_ratings": A map of entry ids to ratings by the current user. Entries + not in this list have no rating. Only populated if rating is enabled. + * "forced_entries": A list of entry ids that have forced_read_state set to + true. This flag is meant to indicate the entry's read_state has been + manually set to 'unread' by the user, so the entry should not be + automatically marked as read. + * "view": A threaded view of all the entries in the discussion, containing + the id, user_id, and message. + * "new_entries": Because this view is eventually consistent, it's possible + that newly created or updated entries won't yet be reflected in the view. + If the application wants to also get a flat list of all entries not yet + reflected in the view, pass include_new_entries=1 to the request and this + array of entries will be returned. These entries are returned in a flat + array, in ascending created_at order. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("GET /api/v1/groups/{group_id}/discussion_topics/{topic_id}/view with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/view".format(**path), data=data, params=params, no_data=True) + + def post_entry_courses(self, topic_id, course_id, attachment=None, message=None): + """ + Post an entry. + + Create a new entry in a discussion topic. Returns a json representation of + the created entry (see documentation for 'entries' method) on success. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - message + """The body of the entry.""" + if message is not None: + data["message"] = message + + # OPTIONAL - attachment + """a multipart/form-data form-field-style + attachment. Attachments larger than 1 kilobyte are subject to quota + restrictions.""" + if attachment is not None: + data["attachment"] = attachment + + self.logger.debug("POST /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries".format(**path), data=data, params=params, no_data=True) + + def post_entry_groups(self, group_id, topic_id, attachment=None, message=None): + """ + Post an entry. + + Create a new entry in a discussion topic. Returns a json representation of + the created entry (see documentation for 'entries' method) on success. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - message + """The body of the entry.""" + if message is not None: + data["message"] = message + + # OPTIONAL - attachment + """a multipart/form-data form-field-style + attachment. Attachments larger than 1 kilobyte are subject to quota + restrictions.""" + if attachment is not None: + data["attachment"] = attachment + + self.logger.debug("POST /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries".format(**path), data=data, params=params, no_data=True) + + def list_topic_entries_courses(self, topic_id, course_id): + """ + List topic entries. + + Retrieve the (paginated) top-level entries in a discussion topic. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + + Will include the 10 most recent replies, if any, for each entry returned. + + If the topic is a root topic with children corresponding to groups of a + group assignment, entries from those subtopics for which the user belongs + to the corresponding group will be returned. + + Ordering of returned entries is newest-first by posting timestamp (reply + activity is ignored). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("GET /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries".format(**path), data=data, params=params, no_data=True) + + def list_topic_entries_groups(self, group_id, topic_id): + """ + List topic entries. + + Retrieve the (paginated) top-level entries in a discussion topic. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + + Will include the 10 most recent replies, if any, for each entry returned. + + If the topic is a root topic with children corresponding to groups of a + group assignment, entries from those subtopics for which the user belongs + to the corresponding group will be returned. + + Ordering of returned entries is newest-first by posting timestamp (reply + activity is ignored). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("GET /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries".format(**path), data=data, params=params, no_data=True) + + def post_reply_courses(self, topic_id, entry_id, course_id, attachment=None, message=None): + """ + Post a reply. + + Add a reply to an entry in a discussion topic. Returns a json + representation of the created reply (see documentation for 'replies' + method) on success. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + # OPTIONAL - message + """The body of the entry.""" + if message is not None: + data["message"] = message + + # OPTIONAL - attachment + """a multipart/form-data form-field-style + attachment. Attachments larger than 1 kilobyte are subject to quota + restrictions.""" + if attachment is not None: + data["attachment"] = attachment + + self.logger.debug("POST /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies".format(**path), data=data, params=params, no_data=True) + + def post_reply_groups(self, group_id, topic_id, entry_id, attachment=None, message=None): + """ + Post a reply. + + Add a reply to an entry in a discussion topic. Returns a json + representation of the created reply (see documentation for 'replies' + method) on success. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + # OPTIONAL - message + """The body of the entry.""" + if message is not None: + data["message"] = message + + # OPTIONAL - attachment + """a multipart/form-data form-field-style + attachment. Attachments larger than 1 kilobyte are subject to quota + restrictions.""" + if attachment is not None: + data["attachment"] = attachment + + self.logger.debug("POST /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies".format(**path), data=data, params=params, no_data=True) + + def list_entry_replies_courses(self, topic_id, entry_id, course_id): + """ + List entry replies. + + Retrieve the (paginated) replies to a top-level entry in a discussion + topic. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + + Ordering of returned entries is newest-first by creation timestamp. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + self.logger.debug("GET /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies".format(**path), data=data, params=params, no_data=True) + + def list_entry_replies_groups(self, group_id, topic_id, entry_id): + """ + List entry replies. + + Retrieve the (paginated) replies to a top-level entry in a discussion + topic. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + + Ordering of returned entries is newest-first by creation timestamp. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + self.logger.debug("GET /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/replies".format(**path), data=data, params=params, no_data=True) + + def list_entries_courses(self, topic_id, course_id, ids=None): + """ + List entries. + + Retrieve a paginated list of discussion entries, given a list of ids. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - ids + """A list of entry ids to retrieve. Entries will be returned in id order, + smallest id first.""" + if ids is not None: + params["ids"] = ids + + self.logger.debug("GET /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entry_list with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entry_list".format(**path), data=data, params=params, no_data=True) + + def list_entries_groups(self, group_id, topic_id, ids=None): + """ + List entries. + + Retrieve a paginated list of discussion entries, given a list of ids. + + May require (depending on the topic) that the user has posted in the topic. + If it is required, and the user has not posted, will respond with a 403 + Forbidden status and the body 'require_initial_post'. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - ids + """A list of entry ids to retrieve. Entries will be returned in id order, + smallest id first.""" + if ids is not None: + params["ids"] = ids + + self.logger.debug("GET /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entry_list with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entry_list".format(**path), data=data, params=params, no_data=True) + + def mark_topic_as_read_courses(self, topic_id, course_id): + """ + Mark topic as read. + + Mark the initial text of the discussion topic as read. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("PUT /api/v1/courses/{course_id}/discussion_topics/{topic_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_topic_as_read_groups(self, group_id, topic_id): + """ + Mark topic as read. + + Mark the initial text of the discussion topic as read. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("PUT /api/v1/groups/{group_id}/discussion_topics/{topic_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_topic_as_unread_courses(self, topic_id, course_id): + """ + Mark topic as unread. + + Mark the initial text of the discussion topic as unread. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/discussion_topics/{topic_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_topic_as_unread_groups(self, group_id, topic_id): + """ + Mark topic as unread. + + Mark the initial text of the discussion topic as unread. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("DELETE /api/v1/groups/{group_id}/discussion_topics/{topic_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_all_entries_as_read_courses(self, topic_id, course_id, forced_read_state=None): + """ + Mark all entries as read. + + Mark the discussion topic and all its entries as read. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - forced_read_state + """A boolean value to set all of the entries' forced_read_state. No change + is made if this argument is not specified.""" + if forced_read_state is not None: + data["forced_read_state"] = forced_read_state + + self.logger.debug("PUT /api/v1/courses/{course_id}/discussion_topics/{topic_id}/read_all with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/read_all".format(**path), data=data, params=params, no_data=True) + + def mark_all_entries_as_read_groups(self, group_id, topic_id, forced_read_state=None): + """ + Mark all entries as read. + + Mark the discussion topic and all its entries as read. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - forced_read_state + """A boolean value to set all of the entries' forced_read_state. No change + is made if this argument is not specified.""" + if forced_read_state is not None: + data["forced_read_state"] = forced_read_state + + self.logger.debug("PUT /api/v1/groups/{group_id}/discussion_topics/{topic_id}/read_all with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/read_all".format(**path), data=data, params=params, no_data=True) + + def mark_all_entries_as_unread_courses(self, topic_id, course_id, forced_read_state=None): + """ + Mark all entries as unread. + + Mark the discussion topic and all its entries as unread. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - forced_read_state + """A boolean value to set all of the entries' forced_read_state. No change is + made if this argument is not specified.""" + if forced_read_state is not None: + params["forced_read_state"] = forced_read_state + + self.logger.debug("DELETE /api/v1/courses/{course_id}/discussion_topics/{topic_id}/read_all with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/read_all".format(**path), data=data, params=params, no_data=True) + + def mark_all_entries_as_unread_groups(self, group_id, topic_id, forced_read_state=None): + """ + Mark all entries as unread. + + Mark the discussion topic and all its entries as unread. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # OPTIONAL - forced_read_state + """A boolean value to set all of the entries' forced_read_state. No change is + made if this argument is not specified.""" + if forced_read_state is not None: + params["forced_read_state"] = forced_read_state + + self.logger.debug("DELETE /api/v1/groups/{group_id}/discussion_topics/{topic_id}/read_all with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/read_all".format(**path), data=data, params=params, no_data=True) + + def mark_entry_as_read_courses(self, topic_id, entry_id, course_id, forced_read_state=None): + """ + Mark entry as read. + + Mark a discussion entry as read. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + # OPTIONAL - forced_read_state + """A boolean value to set the entry's forced_read_state. No change is made if + this argument is not specified.""" + if forced_read_state is not None: + data["forced_read_state"] = forced_read_state + + self.logger.debug("PUT /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_entry_as_read_groups(self, group_id, topic_id, entry_id, forced_read_state=None): + """ + Mark entry as read. + + Mark a discussion entry as read. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + # OPTIONAL - forced_read_state + """A boolean value to set the entry's forced_read_state. No change is made if + this argument is not specified.""" + if forced_read_state is not None: + data["forced_read_state"] = forced_read_state + + self.logger.debug("PUT /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_entry_as_unread_courses(self, topic_id, entry_id, course_id, forced_read_state=None): + """ + Mark entry as unread. + + Mark a discussion entry as unread. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + # OPTIONAL - forced_read_state + """A boolean value to set the entry's forced_read_state. No change is made if + this argument is not specified.""" + if forced_read_state is not None: + params["forced_read_state"] = forced_read_state + + self.logger.debug("DELETE /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_entry_as_unread_groups(self, group_id, topic_id, entry_id, forced_read_state=None): + """ + Mark entry as unread. + + Mark a discussion entry as unread. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + # OPTIONAL - forced_read_state + """A boolean value to set the entry's forced_read_state. No change is made if + this argument is not specified.""" + if forced_read_state is not None: + params["forced_read_state"] = forced_read_state + + self.logger.debug("DELETE /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/read".format(**path), data=data, params=params, no_data=True) + + def rate_entry_courses(self, topic_id, entry_id, course_id, rating=None): + """ + Rate entry. + + Rate a discussion entry. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + # OPTIONAL - rating + """A rating to set on this entry. Only 0 and 1 are accepted.""" + if rating is not None: + data["rating"] = rating + + self.logger.debug("POST /api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/rating with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/entries/{entry_id}/rating".format(**path), data=data, params=params, no_data=True) + + def rate_entry_groups(self, group_id, topic_id, entry_id, rating=None): + """ + Rate entry. + + Rate a discussion entry. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + # REQUIRED - PATH - entry_id + """ID""" + path["entry_id"] = entry_id + + # OPTIONAL - rating + """A rating to set on this entry. Only 0 and 1 are accepted.""" + if rating is not None: + data["rating"] = rating + + self.logger.debug("POST /api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/rating with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/entries/{entry_id}/rating".format(**path), data=data, params=params, no_data=True) + + def subscribe_to_topic_courses(self, topic_id, course_id): + """ + Subscribe to a topic. + + Subscribe to a topic to receive notifications about new entries + + On success, the response will be 204 No Content with an empty body + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("PUT /api/v1/courses/{course_id}/discussion_topics/{topic_id}/subscribed with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/subscribed".format(**path), data=data, params=params, no_data=True) + + def subscribe_to_topic_groups(self, group_id, topic_id): + """ + Subscribe to a topic. + + Subscribe to a topic to receive notifications about new entries + + On success, the response will be 204 No Content with an empty body + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("PUT /api/v1/groups/{group_id}/discussion_topics/{topic_id}/subscribed with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/subscribed".format(**path), data=data, params=params, no_data=True) + + def unsubscribe_from_topic_courses(self, topic_id, course_id): + """ + Unsubscribe from a topic. + + Unsubscribe from a topic to stop receiving notifications about new entries + + On success, the response will be 204 No Content with an empty body + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/discussion_topics/{topic_id}/subscribed with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/discussion_topics/{topic_id}/subscribed".format(**path), data=data, params=params, no_data=True) + + def unsubscribe_from_topic_groups(self, group_id, topic_id): + """ + Unsubscribe from a topic. + + Unsubscribe from a topic to stop receiving notifications about new entries + + On success, the response will be 204 No Content with an empty body + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - topic_id + """ID""" + path["topic_id"] = topic_id + + self.logger.debug("DELETE /api/v1/groups/{group_id}/discussion_topics/{topic_id}/subscribed with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/discussion_topics/{topic_id}/subscribed".format(**path), data=data, params=params, no_data=True) + + +class Discussiontopic(BaseModel): + """Discussiontopic Model. + A discussion topic""" + + def __init__(self, lock_info=None, delayed_post_at=None, last_reply_at=None, only_graders_can_rate=None, subscription_hold=None, message=None, read_state=None, id=None, locked_for_user=None, subscribed=None, title=None, discussion_type=None, posted_at=None, require_initial_post=None, pinned=None, allow_rating=None, discussion_subentry_count=None, topic_children=None, user_name=None, sort_by_rating=None, root_topic_id=None, html_url=None, podcast_url=None, user_can_see_posts=None, permissions=None, locked=None, group_category_id=None, assignment_id=None, lock_at=None, attachments=None, unread_count=None, published=None, lock_explanation=None): + """Init method for Discussiontopic class.""" + self._lock_info = lock_info + self._delayed_post_at = delayed_post_at + self._last_reply_at = last_reply_at + self._only_graders_can_rate = only_graders_can_rate + self._subscription_hold = subscription_hold + self._message = message + self._read_state = read_state + self._id = id + self._locked_for_user = locked_for_user + self._subscribed = subscribed + self._title = title + self._discussion_type = discussion_type + self._posted_at = posted_at + self._require_initial_post = require_initial_post + self._pinned = pinned + self._allow_rating = allow_rating + self._discussion_subentry_count = discussion_subentry_count + self._topic_children = topic_children + self._user_name = user_name + self._sort_by_rating = sort_by_rating + self._root_topic_id = root_topic_id + self._html_url = html_url + self._podcast_url = podcast_url + self._user_can_see_posts = user_can_see_posts + self._permissions = permissions + self._locked = locked + self._group_category_id = group_category_id + self._assignment_id = assignment_id + self._lock_at = lock_at + self._attachments = attachments + self._unread_count = unread_count + self._published = published + self._lock_explanation = lock_explanation + + self.logger = logging.getLogger('pycanvas.Discussiontopic') + + @property + def lock_info(self): + """(Optional) Information for the user about the lock. Present when locked_for_user is true.""" + return self._lock_info + + @lock_info.setter + def lock_info(self, value): + """Setter for lock_info property.""" + self.logger.warn("Setting values on lock_info will NOT update the remote Canvas instance.") + self._lock_info = value + + @property + def delayed_post_at(self): + """The datetime to publish the topic (if not right away).""" + return self._delayed_post_at + + @delayed_post_at.setter + def delayed_post_at(self, value): + """Setter for delayed_post_at property.""" + self.logger.warn("Setting values on delayed_post_at will NOT update the remote Canvas instance.") + self._delayed_post_at = value + + @property + def last_reply_at(self): + """The datetime for when the last reply was in the topic.""" + return self._last_reply_at + + @last_reply_at.setter + def last_reply_at(self, value): + """Setter for last_reply_at property.""" + self.logger.warn("Setting values on last_reply_at will NOT update the remote Canvas instance.") + self._last_reply_at = value + + @property + def only_graders_can_rate(self): + """Whether or not grade permissions are required to rate entries.""" + return self._only_graders_can_rate + + @only_graders_can_rate.setter + def only_graders_can_rate(self, value): + """Setter for only_graders_can_rate property.""" + self.logger.warn("Setting values on only_graders_can_rate will NOT update the remote Canvas instance.") + self._only_graders_can_rate = value + + @property + def subscription_hold(self): + """(Optional) Why the user cannot subscribe to this topic. Only one reason will be returned even if multiple apply. Can be one of: 'initial_post_required': The user must post a reply first; 'not_in_group_set': The user is not in the group set for this graded group discussion; 'not_in_group': The user is not in this topic's group; 'topic_is_announcement': This topic is an announcement.""" + return self._subscription_hold + + @subscription_hold.setter + def subscription_hold(self, value): + """Setter for subscription_hold property.""" + self.logger.warn("Setting values on subscription_hold will NOT update the remote Canvas instance.") + self._subscription_hold = value + + @property + def message(self): + """The HTML content of the message body.""" + return self._message + + @message.setter + def message(self, value): + """Setter for message property.""" + self.logger.warn("Setting values on message will NOT update the remote Canvas instance.") + self._message = value + + @property + def read_state(self): + """The read_state of the topic for the current user, 'read' or 'unread'.""" + return self._read_state + + @read_state.setter + def read_state(self, value): + """Setter for read_state property.""" + self.logger.warn("Setting values on read_state will NOT update the remote Canvas instance.") + self._read_state = value + + @property + def id(self): + """The ID of this topic.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def locked_for_user(self): + """Whether or not this is locked for the user.""" + return self._locked_for_user + + @locked_for_user.setter + def locked_for_user(self, value): + """Setter for locked_for_user property.""" + self.logger.warn("Setting values on locked_for_user will NOT update the remote Canvas instance.") + self._locked_for_user = value + + @property + def subscribed(self): + """Whether or not the current user is subscribed to this topic.""" + return self._subscribed + + @subscribed.setter + def subscribed(self, value): + """Setter for subscribed property.""" + self.logger.warn("Setting values on subscribed will NOT update the remote Canvas instance.") + self._subscribed = value + + @property + def title(self): + """The topic title.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def discussion_type(self): + """The type of discussion. Values are 'side_comment', for discussions that only allow one level of nested comments, and 'threaded' for fully threaded discussions.""" + return self._discussion_type + + @discussion_type.setter + def discussion_type(self, value): + """Setter for discussion_type property.""" + self.logger.warn("Setting values on discussion_type will NOT update the remote Canvas instance.") + self._discussion_type = value + + @property + def posted_at(self): + """The datetime the topic was posted. If it is null it hasn't been posted yet. (see delayed_post_at).""" + return self._posted_at + + @posted_at.setter + def posted_at(self, value): + """Setter for posted_at property.""" + self.logger.warn("Setting values on posted_at will NOT update the remote Canvas instance.") + self._posted_at = value + + @property + def require_initial_post(self): + """If true then a user may not respond to other replies until that user has made an initial reply. Defaults to false.""" + return self._require_initial_post + + @require_initial_post.setter + def require_initial_post(self, value): + """Setter for require_initial_post property.""" + self.logger.warn("Setting values on require_initial_post will NOT update the remote Canvas instance.") + self._require_initial_post = value + + @property + def pinned(self): + """Whether or not the discussion has been 'pinned' by an instructor.""" + return self._pinned + + @pinned.setter + def pinned(self, value): + """Setter for pinned property.""" + self.logger.warn("Setting values on pinned will NOT update the remote Canvas instance.") + self._pinned = value + + @property + def allow_rating(self): + """Whether or not users can rate entries in this topic.""" + return self._allow_rating + + @allow_rating.setter + def allow_rating(self, value): + """Setter for allow_rating property.""" + self.logger.warn("Setting values on allow_rating will NOT update the remote Canvas instance.") + self._allow_rating = value + + @property + def discussion_subentry_count(self): + """The count of entries in the topic.""" + return self._discussion_subentry_count + + @discussion_subentry_count.setter + def discussion_subentry_count(self, value): + """Setter for discussion_subentry_count property.""" + self.logger.warn("Setting values on discussion_subentry_count will NOT update the remote Canvas instance.") + self._discussion_subentry_count = value + + @property + def topic_children(self): + """An array of topic_ids for the group discussions the user is a part of.""" + return self._topic_children + + @topic_children.setter + def topic_children(self, value): + """Setter for topic_children property.""" + self.logger.warn("Setting values on topic_children will NOT update the remote Canvas instance.") + self._topic_children = value + + @property + def user_name(self): + """The username of the topic creator.""" + return self._user_name + + @user_name.setter + def user_name(self, value): + """Setter for user_name property.""" + self.logger.warn("Setting values on user_name will NOT update the remote Canvas instance.") + self._user_name = value + + @property + def sort_by_rating(self): + """Whether or not entries should be sorted by rating.""" + return self._sort_by_rating + + @sort_by_rating.setter + def sort_by_rating(self, value): + """Setter for sort_by_rating property.""" + self.logger.warn("Setting values on sort_by_rating will NOT update the remote Canvas instance.") + self._sort_by_rating = value + + @property + def root_topic_id(self): + """If the topic is for grading and a group assignment this will point to the original topic in the course.""" + return self._root_topic_id + + @root_topic_id.setter + def root_topic_id(self, value): + """Setter for root_topic_id property.""" + self.logger.warn("Setting values on root_topic_id will NOT update the remote Canvas instance.") + self._root_topic_id = value + + @property + def html_url(self): + """The URL to the discussion topic in canvas.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def podcast_url(self): + """If the topic is a podcast topic this is the feed url for the current user.""" + return self._podcast_url + + @podcast_url.setter + def podcast_url(self, value): + """Setter for podcast_url property.""" + self.logger.warn("Setting values on podcast_url will NOT update the remote Canvas instance.") + self._podcast_url = value + + @property + def user_can_see_posts(self): + """Whether or not posts in this topic are visible to the user.""" + return self._user_can_see_posts + + @user_can_see_posts.setter + def user_can_see_posts(self, value): + """Setter for user_can_see_posts property.""" + self.logger.warn("Setting values on user_can_see_posts will NOT update the remote Canvas instance.") + self._user_can_see_posts = value + + @property + def permissions(self): + """The current user's permissions on this topic.""" + return self._permissions + + @permissions.setter + def permissions(self, value): + """Setter for permissions property.""" + self.logger.warn("Setting values on permissions will NOT update the remote Canvas instance.") + self._permissions = value + + @property + def locked(self): + """Whether or not the discussion is 'closed for comments'.""" + return self._locked + + @locked.setter + def locked(self, value): + """Setter for locked property.""" + self.logger.warn("Setting values on locked will NOT update the remote Canvas instance.") + self._locked = value + + @property + def group_category_id(self): + """The unique identifier of the group category if the topic is a group discussion, otherwise null.""" + return self._group_category_id + + @group_category_id.setter + def group_category_id(self, value): + """Setter for group_category_id property.""" + self.logger.warn("Setting values on group_category_id will NOT update the remote Canvas instance.") + self._group_category_id = value + + @property + def assignment_id(self): + """The unique identifier of the assignment if the topic is for grading, otherwise null.""" + return self._assignment_id + + @assignment_id.setter + def assignment_id(self, value): + """Setter for assignment_id property.""" + self.logger.warn("Setting values on assignment_id will NOT update the remote Canvas instance.") + self._assignment_id = value + + @property + def lock_at(self): + """The datetime to lock the topic (if ever).""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def attachments(self): + """Array of file attachments.""" + return self._attachments + + @attachments.setter + def attachments(self, value): + """Setter for attachments property.""" + self.logger.warn("Setting values on attachments will NOT update the remote Canvas instance.") + self._attachments = value + + @property + def unread_count(self): + """The count of unread entries of this topic for the current user.""" + return self._unread_count + + @unread_count.setter + def unread_count(self, value): + """Setter for unread_count property.""" + self.logger.warn("Setting values on unread_count will NOT update the remote Canvas instance.") + self._unread_count = value + + @property + def published(self): + """Whether this discussion topic is published (true) or draft state (false).""" + return self._published + + @published.setter + def published(self, value): + """Setter for published property.""" + self.logger.warn("Setting values on published will NOT update the remote Canvas instance.") + self._published = value + + @property + def lock_explanation(self): + """(Optional) An explanation of why this is locked for the user. Present when locked_for_user is true.""" + return self._lock_explanation + + @lock_explanation.setter + def lock_explanation(self, value): + """Setter for lock_explanation property.""" + self.logger.warn("Setting values on lock_explanation will NOT update the remote Canvas instance.") + self._lock_explanation = value + + +class Fileattachment(BaseModel): + """Fileattachment Model. + A file attachment""" + + def __init__(self, url=None, display_name=None, content_type=None, filename=None): + """Init method for Fileattachment class.""" + self._url = url + self._display_name = display_name + self._content_type = content_type + self._filename = filename + + self.logger = logging.getLogger('pycanvas.Fileattachment') + + @property + def url(self): + """url.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def display_name(self): + """display_name.""" + return self._display_name + + @display_name.setter + def display_name(self, value): + """Setter for display_name property.""" + self.logger.warn("Setting values on display_name will NOT update the remote Canvas instance.") + self._display_name = value + + @property + def content_type(self): + """content_type.""" + return self._content_type + + @content_type.setter + def content_type(self, value): + """Setter for content_type property.""" + self.logger.warn("Setting values on content_type will NOT update the remote Canvas instance.") + self._content_type = value + + @property + def filename(self): + """filename.""" + return self._filename + + @filename.setter + def filename(self, value): + """Setter for filename property.""" + self.logger.warn("Setting values on filename will NOT update the remote Canvas instance.") + self._filename = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/document_previews.py b/venv/Lib/site-packages/pycanvas/apis/document_previews.py new file mode 100644 index 00000000..d5cc9cac --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/document_previews.py @@ -0,0 +1,18 @@ +"""DocumentPreviews API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + + +class DocumentPreviewsAPI(BaseCanvasAPI): + """DocumentPreviews API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for DocumentPreviewsAPI.""" + super(DocumentPreviewsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.DocumentPreviewsAPI") + diff --git a/venv/Lib/site-packages/pycanvas/apis/enrollment_terms.py b/venv/Lib/site-packages/pycanvas/apis/enrollment_terms.py new file mode 100644 index 00000000..26b91d84 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/enrollment_terms.py @@ -0,0 +1,226 @@ +"""EnrollmentTerms API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class EnrollmentTermsAPI(BaseCanvasAPI): + """EnrollmentTerms API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for EnrollmentTermsAPI.""" + super(EnrollmentTermsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.EnrollmentTermsAPI") + + def create_enrollment_term(self, account_id, enrollment_term_end_at=None, enrollment_term_name=None, enrollment_term_sis_term_id=None, enrollment_term_start_at=None): + """ + Create enrollment term. + + Create a new enrollment term for the specified account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - enrollment_term[name] + """The name of the term.""" + if enrollment_term_name is not None: + data["enrollment_term[name]"] = enrollment_term_name + + # OPTIONAL - enrollment_term[start_at] + """The day/time the term starts. + Accepts times in ISO 8601 format, e.g. 2015-01-10T18:48:00Z.""" + if enrollment_term_start_at is not None: + data["enrollment_term[start_at]"] = enrollment_term_start_at + + # OPTIONAL - enrollment_term[end_at] + """The day/time the term ends. + Accepts times in ISO 8601 format, e.g. 2015-01-10T18:48:00Z.""" + if enrollment_term_end_at is not None: + data["enrollment_term[end_at]"] = enrollment_term_end_at + + # OPTIONAL - enrollment_term[sis_term_id] + """The unique SIS identifier for the term.""" + if enrollment_term_sis_term_id is not None: + data["enrollment_term[sis_term_id]"] = enrollment_term_sis_term_id + + self.logger.debug("POST /api/v1/accounts/{account_id}/terms with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/terms".format(**path), data=data, params=params, single_item=True) + + def update_enrollment_term(self, id, account_id, enrollment_term_end_at=None, enrollment_term_name=None, enrollment_term_sis_term_id=None, enrollment_term_start_at=None): + """ + Update enrollment term. + + Update an existing enrollment term for the specified account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - enrollment_term[name] + """The name of the term.""" + if enrollment_term_name is not None: + data["enrollment_term[name]"] = enrollment_term_name + + # OPTIONAL - enrollment_term[start_at] + """The day/time the term starts. + Accepts times in ISO 8601 format, e.g. 2015-01-10T18:48:00Z.""" + if enrollment_term_start_at is not None: + data["enrollment_term[start_at]"] = enrollment_term_start_at + + # OPTIONAL - enrollment_term[end_at] + """The day/time the term ends. + Accepts times in ISO 8601 format, e.g. 2015-01-10T18:48:00Z.""" + if enrollment_term_end_at is not None: + data["enrollment_term[end_at]"] = enrollment_term_end_at + + # OPTIONAL - enrollment_term[sis_term_id] + """The unique SIS identifier for the term.""" + if enrollment_term_sis_term_id is not None: + data["enrollment_term[sis_term_id]"] = enrollment_term_sis_term_id + + self.logger.debug("PUT /api/v1/accounts/{account_id}/terms/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/terms/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_enrollment_term(self, id, account_id): + """ + Delete enrollment term. + + Delete the specified enrollment term. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/terms/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/terms/{id}".format(**path), data=data, params=params, single_item=True) + + def list_enrollment_terms(self, account_id, workflow_state=None): + """ + List enrollment terms. + + Return all of the terms in the account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - workflow_state + """If set, only returns terms that are in the given state. + Defaults to 'active'.""" + if workflow_state is not None: + self._validate_enum(workflow_state, ["active", "deleted", "all"]) + params["workflow_state"] = workflow_state + + self.logger.debug("GET /api/v1/accounts/{account_id}/terms with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/terms".format(**path), data=data, params=params, data_key='enrollment_terms', all_pages=True) + + +class Enrollmentterm(BaseModel): + """Enrollmentterm Model.""" + + def __init__(self, start_at=None, name=None, workflow_state=None, sis_term_id=None, end_at=None, id=None): + """Init method for Enrollmentterm class.""" + self._start_at = start_at + self._name = name + self._workflow_state = workflow_state + self._sis_term_id = sis_term_id + self._end_at = end_at + self._id = id + + self.logger = logging.getLogger('pycanvas.Enrollmentterm') + + @property + def start_at(self): + """The datetime of the start of the term.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def name(self): + """The name of the term.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def workflow_state(self): + """The state of the term. Can be 'active' or 'deleted'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def sis_term_id(self): + """The SIS id of the term. Only included if the user has permission to view SIS information.""" + return self._sis_term_id + + @sis_term_id.setter + def sis_term_id(self, value): + """Setter for sis_term_id property.""" + self.logger.warn("Setting values on sis_term_id will NOT update the remote Canvas instance.") + self._sis_term_id = value + + @property + def end_at(self): + """The datetime of the end of the term.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def id(self): + """The unique identifier for the enrollment term.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/enrollments.py b/venv/Lib/site-packages/pycanvas/apis/enrollments.py new file mode 100644 index 00000000..8bcea7a5 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/enrollments.py @@ -0,0 +1,1081 @@ +"""Enrollments API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class EnrollmentsAPI(BaseCanvasAPI): + """Enrollments API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for EnrollmentsAPI.""" + super(EnrollmentsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.EnrollmentsAPI") + + def list_enrollments_courses(self, course_id, grading_period_id=None, include=None, role=None, sis_account_id=None, sis_course_id=None, sis_section_id=None, sis_user_id=None, state=None, type=None, user_id=None): + """ + List enrollments. + + Depending on the URL given, return either (1) all of the enrollments in + a course, (2) all of the enrollments in a section or (3) all of a user's + enrollments. This includes student, teacher, TA, and observer enrollments. + + If a user has multiple enrollments in a context (e.g. as a teacher + and a student or in multiple course sections), each enrollment will be + listed separately. + + note: Currently, only an admin user can return other users' enrollments. A + user can, however, return his/her own enrollments. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - type + """A list of enrollment types to return. Accepted values are + 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', + 'DesignerEnrollment', and 'ObserverEnrollment.' If omitted, all enrollment + types are returned. This argument is ignored if `role` is given.""" + if type is not None: + params["type"] = type + + # OPTIONAL - role + """A list of enrollment roles to return. Accepted values include course-level + roles created by the {api:RoleOverridesController#add_role Add Role API} + as well as the base enrollment types accepted by the `type` argument above.""" + if role is not None: + params["role"] = role + + # OPTIONAL - state + """Filter by enrollment state. If omitted, 'active' and 'invited' enrollments + are returned. When querying a user's enrollments (either via user_id + argument or via user enrollments endpoint), the following additional + synthetic states are supported: "current_and_invited"|"current_and_future"|"current_and_concluded"""" + if state is not None: + self._validate_enum(state, ["active", "invited", "creation_pending", "deleted", "rejected", "completed", "inactive"]) + params["state"] = state + + # OPTIONAL - include + """Array of additional information to include on the enrollment or user records. + "avatar_url" and "group_ids" will be returned on the user record.""" + if include is not None: + self._validate_enum(include, ["avatar_url", "group_ids", "locked", "observed_users", "can_be_removed"]) + params["include"] = include + + # OPTIONAL - user_id + """Filter by user_id (only valid for course or section enrollment + queries). If set to the current user's id, this is a way to + determine if the user has any enrollments in the course or section, + independent of whether the user has permission to view other people + on the roster.""" + if user_id is not None: + params["user_id"] = user_id + + # OPTIONAL - grading_period_id + """Return grades for the given grading_period. If this parameter is not + specified, the returned grades will be for the whole course.""" + if grading_period_id is not None: + params["grading_period_id"] = grading_period_id + + # OPTIONAL - sis_account_id + """Returns only enrollments for the specified SIS account ID(s). Does not + look into subaccounts. May pass in array or string.""" + if sis_account_id is not None: + params["sis_account_id"] = sis_account_id + + # OPTIONAL - sis_course_id + """Returns only enrollments matching the specified SIS course ID(s). + May pass in array or string.""" + if sis_course_id is not None: + params["sis_course_id"] = sis_course_id + + # OPTIONAL - sis_section_id + """Returns only section enrollments matching the specified SIS section ID(s). + May pass in array or string.""" + if sis_section_id is not None: + params["sis_section_id"] = sis_section_id + + # OPTIONAL - sis_user_id + """Returns only enrollments for the specified SIS user ID(s). May pass in + array or string.""" + if sis_user_id is not None: + params["sis_user_id"] = sis_user_id + + self.logger.debug("GET /api/v1/courses/{course_id}/enrollments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/enrollments".format(**path), data=data, params=params, all_pages=True) + + def list_enrollments_sections(self, section_id, grading_period_id=None, include=None, role=None, sis_account_id=None, sis_course_id=None, sis_section_id=None, sis_user_id=None, state=None, type=None, user_id=None): + """ + List enrollments. + + Depending on the URL given, return either (1) all of the enrollments in + a course, (2) all of the enrollments in a section or (3) all of a user's + enrollments. This includes student, teacher, TA, and observer enrollments. + + If a user has multiple enrollments in a context (e.g. as a teacher + and a student or in multiple course sections), each enrollment will be + listed separately. + + note: Currently, only an admin user can return other users' enrollments. A + user can, however, return his/her own enrollments. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # OPTIONAL - type + """A list of enrollment types to return. Accepted values are + 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', + 'DesignerEnrollment', and 'ObserverEnrollment.' If omitted, all enrollment + types are returned. This argument is ignored if `role` is given.""" + if type is not None: + params["type"] = type + + # OPTIONAL - role + """A list of enrollment roles to return. Accepted values include course-level + roles created by the {api:RoleOverridesController#add_role Add Role API} + as well as the base enrollment types accepted by the `type` argument above.""" + if role is not None: + params["role"] = role + + # OPTIONAL - state + """Filter by enrollment state. If omitted, 'active' and 'invited' enrollments + are returned. When querying a user's enrollments (either via user_id + argument or via user enrollments endpoint), the following additional + synthetic states are supported: "current_and_invited"|"current_and_future"|"current_and_concluded"""" + if state is not None: + self._validate_enum(state, ["active", "invited", "creation_pending", "deleted", "rejected", "completed", "inactive"]) + params["state"] = state + + # OPTIONAL - include + """Array of additional information to include on the enrollment or user records. + "avatar_url" and "group_ids" will be returned on the user record.""" + if include is not None: + self._validate_enum(include, ["avatar_url", "group_ids", "locked", "observed_users", "can_be_removed"]) + params["include"] = include + + # OPTIONAL - user_id + """Filter by user_id (only valid for course or section enrollment + queries). If set to the current user's id, this is a way to + determine if the user has any enrollments in the course or section, + independent of whether the user has permission to view other people + on the roster.""" + if user_id is not None: + params["user_id"] = user_id + + # OPTIONAL - grading_period_id + """Return grades for the given grading_period. If this parameter is not + specified, the returned grades will be for the whole course.""" + if grading_period_id is not None: + params["grading_period_id"] = grading_period_id + + # OPTIONAL - sis_account_id + """Returns only enrollments for the specified SIS account ID(s). Does not + look into subaccounts. May pass in array or string.""" + if sis_account_id is not None: + params["sis_account_id"] = sis_account_id + + # OPTIONAL - sis_course_id + """Returns only enrollments matching the specified SIS course ID(s). + May pass in array or string.""" + if sis_course_id is not None: + params["sis_course_id"] = sis_course_id + + # OPTIONAL - sis_section_id + """Returns only section enrollments matching the specified SIS section ID(s). + May pass in array or string.""" + if sis_section_id is not None: + params["sis_section_id"] = sis_section_id + + # OPTIONAL - sis_user_id + """Returns only enrollments for the specified SIS user ID(s). May pass in + array or string.""" + if sis_user_id is not None: + params["sis_user_id"] = sis_user_id + + self.logger.debug("GET /api/v1/sections/{section_id}/enrollments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/sections/{section_id}/enrollments".format(**path), data=data, params=params, all_pages=True) + + def list_enrollments_users(self, user_id, grading_period_id=None, include=None, role=None, sis_account_id=None, sis_course_id=None, sis_section_id=None, sis_user_id=None, state=None, type=None): + """ + List enrollments. + + Depending on the URL given, return either (1) all of the enrollments in + a course, (2) all of the enrollments in a section or (3) all of a user's + enrollments. This includes student, teacher, TA, and observer enrollments. + + If a user has multiple enrollments in a context (e.g. as a teacher + and a student or in multiple course sections), each enrollment will be + listed separately. + + note: Currently, only an admin user can return other users' enrollments. A + user can, however, return his/her own enrollments. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - type + """A list of enrollment types to return. Accepted values are + 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', + 'DesignerEnrollment', and 'ObserverEnrollment.' If omitted, all enrollment + types are returned. This argument is ignored if `role` is given.""" + if type is not None: + params["type"] = type + + # OPTIONAL - role + """A list of enrollment roles to return. Accepted values include course-level + roles created by the {api:RoleOverridesController#add_role Add Role API} + as well as the base enrollment types accepted by the `type` argument above.""" + if role is not None: + params["role"] = role + + # OPTIONAL - state + """Filter by enrollment state. If omitted, 'active' and 'invited' enrollments + are returned. When querying a user's enrollments (either via user_id + argument or via user enrollments endpoint), the following additional + synthetic states are supported: "current_and_invited"|"current_and_future"|"current_and_concluded"""" + if state is not None: + self._validate_enum(state, ["active", "invited", "creation_pending", "deleted", "rejected", "completed", "inactive"]) + params["state"] = state + + # OPTIONAL - include + """Array of additional information to include on the enrollment or user records. + "avatar_url" and "group_ids" will be returned on the user record.""" + if include is not None: + self._validate_enum(include, ["avatar_url", "group_ids", "locked", "observed_users", "can_be_removed"]) + params["include"] = include + + # REQUIRED - PATH - user_id + """Filter by user_id (only valid for course or section enrollment + queries). If set to the current user's id, this is a way to + determine if the user has any enrollments in the course or section, + independent of whether the user has permission to view other people + on the roster.""" + path["user_id"] = user_id + + # OPTIONAL - grading_period_id + """Return grades for the given grading_period. If this parameter is not + specified, the returned grades will be for the whole course.""" + if grading_period_id is not None: + params["grading_period_id"] = grading_period_id + + # OPTIONAL - sis_account_id + """Returns only enrollments for the specified SIS account ID(s). Does not + look into subaccounts. May pass in array or string.""" + if sis_account_id is not None: + params["sis_account_id"] = sis_account_id + + # OPTIONAL - sis_course_id + """Returns only enrollments matching the specified SIS course ID(s). + May pass in array or string.""" + if sis_course_id is not None: + params["sis_course_id"] = sis_course_id + + # OPTIONAL - sis_section_id + """Returns only section enrollments matching the specified SIS section ID(s). + May pass in array or string.""" + if sis_section_id is not None: + params["sis_section_id"] = sis_section_id + + # OPTIONAL - sis_user_id + """Returns only enrollments for the specified SIS user ID(s). May pass in + array or string.""" + if sis_user_id is not None: + params["sis_user_id"] = sis_user_id + + self.logger.debug("GET /api/v1/users/{user_id}/enrollments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/enrollments".format(**path), data=data, params=params, all_pages=True) + + def enrollment_by_id(self, id, account_id): + """ + Enrollment by ID. + + Get an Enrollment object by Enrollment ID + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """The ID of the enrollment object""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{account_id}/enrollments/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/enrollments/{id}".format(**path), data=data, params=params, single_item=True) + + def enroll_user_courses(self, course_id, enrollment_type, enrollment_user_id, enrollment_associated_user_id=None, enrollment_course_section_id=None, enrollment_enrollment_state=None, enrollment_limit_privileges_to_course_section=None, enrollment_notify=None, enrollment_role=None, enrollment_role_id=None, enrollment_self_enrolled=None, enrollment_self_enrollment_code=None): + """ + Enroll a user. + + Create a new user enrollment for a course or section. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - enrollment[user_id] + """The ID of the user to be enrolled in the course.""" + data["enrollment[user_id]"] = enrollment_user_id + + # REQUIRED - enrollment[type] + """Enroll the user as a student, teacher, TA, observer, or designer. If no + value is given, the type will be inferred by enrollment[role] if supplied, + otherwise 'StudentEnrollment' will be used.""" + self._validate_enum(enrollment_type, ["StudentEnrollment", "TeacherEnrollment", "TaEnrollment", "ObserverEnrollment", "DesignerEnrollment"]) + data["enrollment[type]"] = enrollment_type + + # OPTIONAL - enrollment[role] + """Assigns a custom course-level role to the user.""" + if enrollment_role is not None: + data["enrollment[role]"] = enrollment_role + + # OPTIONAL - enrollment[role_id] + """Assigns a custom course-level role to the user.""" + if enrollment_role_id is not None: + data["enrollment[role_id]"] = enrollment_role_id + + # OPTIONAL - enrollment[enrollment_state] + """If set to 'active,' student will be immediately enrolled in the course. + Otherwise they will be required to accept a course invitation. Default is + 'invited.'. + + If set to 'inactive', student will be listed in the course roster for + teachers, but will not be able to participate in the course until + their enrollment is activated.""" + if enrollment_enrollment_state is not None: + self._validate_enum(enrollment_enrollment_state, ["active", "invited", "inactive"]) + data["enrollment[enrollment_state]"] = enrollment_enrollment_state + + # OPTIONAL - enrollment[course_section_id] + """The ID of the course section to enroll the student in. If the + section-specific URL is used, this argument is redundant and will be + ignored.""" + if enrollment_course_section_id is not None: + data["enrollment[course_section_id]"] = enrollment_course_section_id + + # OPTIONAL - enrollment[limit_privileges_to_course_section] + """If set, the enrollment will only allow the user to see and interact with + users enrolled in the section given by course_section_id. + * For teachers and TAs, this includes grading privileges. + * Section-limited students will not see any users (including teachers + and TAs) not enrolled in their sections. + * Users may have other enrollments that grant privileges to + multiple sections in the same course.""" + if enrollment_limit_privileges_to_course_section is not None: + data["enrollment[limit_privileges_to_course_section]"] = enrollment_limit_privileges_to_course_section + + # OPTIONAL - enrollment[notify] + """If true, a notification will be sent to the enrolled user. + Notifications are not sent by default.""" + if enrollment_notify is not None: + data["enrollment[notify]"] = enrollment_notify + + # OPTIONAL - enrollment[self_enrollment_code] + """If the current user is not allowed to manage enrollments in this + course, but the course allows self-enrollment, the user can self- + enroll as a student in the default section by passing in a valid + code. When self-enrolling, the user_id must be 'self'. The + enrollment_state will be set to 'active' and all other arguments + will be ignored.""" + if enrollment_self_enrollment_code is not None: + data["enrollment[self_enrollment_code]"] = enrollment_self_enrollment_code + + # OPTIONAL - enrollment[self_enrolled] + """If true, marks the enrollment as a self-enrollment, which gives + students the ability to drop the course if desired. Defaults to false.""" + if enrollment_self_enrolled is not None: + data["enrollment[self_enrolled]"] = enrollment_self_enrolled + + # OPTIONAL - enrollment[associated_user_id] + """For an observer enrollment, the ID of a student to observe. The + caller must have +manage_students+ permission in the course. + This is a one-off operation; to automatically observe all a + student's enrollments (for example, as a parent), please use + the {api:UserObserveesController#create User Observees API}.""" + if enrollment_associated_user_id is not None: + data["enrollment[associated_user_id]"] = enrollment_associated_user_id + + self.logger.debug("POST /api/v1/courses/{course_id}/enrollments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/enrollments".format(**path), data=data, params=params, single_item=True) + + def enroll_user_sections(self, section_id, enrollment_type, enrollment_user_id, enrollment_associated_user_id=None, enrollment_course_section_id=None, enrollment_enrollment_state=None, enrollment_limit_privileges_to_course_section=None, enrollment_notify=None, enrollment_role=None, enrollment_role_id=None, enrollment_self_enrolled=None, enrollment_self_enrollment_code=None): + """ + Enroll a user. + + Create a new user enrollment for a course or section. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - enrollment[user_id] + """The ID of the user to be enrolled in the course.""" + data["enrollment[user_id]"] = enrollment_user_id + + # REQUIRED - enrollment[type] + """Enroll the user as a student, teacher, TA, observer, or designer. If no + value is given, the type will be inferred by enrollment[role] if supplied, + otherwise 'StudentEnrollment' will be used.""" + self._validate_enum(enrollment_type, ["StudentEnrollment", "TeacherEnrollment", "TaEnrollment", "ObserverEnrollment", "DesignerEnrollment"]) + data["enrollment[type]"] = enrollment_type + + # OPTIONAL - enrollment[role] + """Assigns a custom course-level role to the user.""" + if enrollment_role is not None: + data["enrollment[role]"] = enrollment_role + + # OPTIONAL - enrollment[role_id] + """Assigns a custom course-level role to the user.""" + if enrollment_role_id is not None: + data["enrollment[role_id]"] = enrollment_role_id + + # OPTIONAL - enrollment[enrollment_state] + """If set to 'active,' student will be immediately enrolled in the course. + Otherwise they will be required to accept a course invitation. Default is + 'invited.'. + + If set to 'inactive', student will be listed in the course roster for + teachers, but will not be able to participate in the course until + their enrollment is activated.""" + if enrollment_enrollment_state is not None: + self._validate_enum(enrollment_enrollment_state, ["active", "invited", "inactive"]) + data["enrollment[enrollment_state]"] = enrollment_enrollment_state + + # OPTIONAL - enrollment[course_section_id] + """The ID of the course section to enroll the student in. If the + section-specific URL is used, this argument is redundant and will be + ignored.""" + if enrollment_course_section_id is not None: + data["enrollment[course_section_id]"] = enrollment_course_section_id + + # OPTIONAL - enrollment[limit_privileges_to_course_section] + """If set, the enrollment will only allow the user to see and interact with + users enrolled in the section given by course_section_id. + * For teachers and TAs, this includes grading privileges. + * Section-limited students will not see any users (including teachers + and TAs) not enrolled in their sections. + * Users may have other enrollments that grant privileges to + multiple sections in the same course.""" + if enrollment_limit_privileges_to_course_section is not None: + data["enrollment[limit_privileges_to_course_section]"] = enrollment_limit_privileges_to_course_section + + # OPTIONAL - enrollment[notify] + """If true, a notification will be sent to the enrolled user. + Notifications are not sent by default.""" + if enrollment_notify is not None: + data["enrollment[notify]"] = enrollment_notify + + # OPTIONAL - enrollment[self_enrollment_code] + """If the current user is not allowed to manage enrollments in this + course, but the course allows self-enrollment, the user can self- + enroll as a student in the default section by passing in a valid + code. When self-enrolling, the user_id must be 'self'. The + enrollment_state will be set to 'active' and all other arguments + will be ignored.""" + if enrollment_self_enrollment_code is not None: + data["enrollment[self_enrollment_code]"] = enrollment_self_enrollment_code + + # OPTIONAL - enrollment[self_enrolled] + """If true, marks the enrollment as a self-enrollment, which gives + students the ability to drop the course if desired. Defaults to false.""" + if enrollment_self_enrolled is not None: + data["enrollment[self_enrolled]"] = enrollment_self_enrolled + + # OPTIONAL - enrollment[associated_user_id] + """For an observer enrollment, the ID of a student to observe. The + caller must have +manage_students+ permission in the course. + This is a one-off operation; to automatically observe all a + student's enrollments (for example, as a parent), please use + the {api:UserObserveesController#create User Observees API}.""" + if enrollment_associated_user_id is not None: + data["enrollment[associated_user_id]"] = enrollment_associated_user_id + + self.logger.debug("POST /api/v1/sections/{section_id}/enrollments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/sections/{section_id}/enrollments".format(**path), data=data, params=params, single_item=True) + + def conclude_deactivate_or_delete_enrollment(self, id, course_id, task=None): + """ + Conclude, deactivate, or delete an enrollment. + + Conclude, deactivate, or delete an enrollment. If the +task+ argument isn't given, the enrollment + will be concluded. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - task + """The action to take on the enrollment. + When inactive, a user will still appear in the course roster to admins, but be unable to participate. + ("inactivate" and "deactivate" are equivalent tasks)""" + if task is not None: + self._validate_enum(task, ["conclude", "delete", "inactivate", "deactivate"]) + params["task"] = task + + self.logger.debug("DELETE /api/v1/courses/{course_id}/enrollments/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/enrollments/{id}".format(**path), data=data, params=params, single_item=True) + + def re_activate_enrollment(self, id, course_id): + """ + Re-activate an enrollment. + + Activates an inactive enrollment + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/courses/{course_id}/enrollments/{id}/reactivate with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/enrollments/{id}/reactivate".format(**path), data=data, params=params, single_item=True) + + +class Grade(BaseModel): + """Grade Model.""" + + def __init__(self, current_score=None, final_score=None, html_url=None, current_grade=None, final_grade=None): + """Init method for Grade class.""" + self._current_score = current_score + self._final_score = final_score + self._html_url = html_url + self._current_grade = current_grade + self._final_grade = final_grade + + self.logger = logging.getLogger('pycanvas.Grade') + + @property + def current_score(self): + """The user's current score in the class. Only included if user has permissions to view this score.""" + return self._current_score + + @current_score.setter + def current_score(self, value): + """Setter for current_score property.""" + self.logger.warn("Setting values on current_score will NOT update the remote Canvas instance.") + self._current_score = value + + @property + def final_score(self): + """The user's final score for the class. Only included if user has permissions to view this score.""" + return self._final_score + + @final_score.setter + def final_score(self, value): + """Setter for final_score property.""" + self.logger.warn("Setting values on final_score will NOT update the remote Canvas instance.") + self._final_score = value + + @property + def html_url(self): + """The URL to the Canvas web UI page for the user's grades, if this is a student enrollment.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def current_grade(self): + """The user's current grade in the class. Only included if user has permissions to view this grade.""" + return self._current_grade + + @current_grade.setter + def current_grade(self, value): + """Setter for current_grade property.""" + self.logger.warn("Setting values on current_grade will NOT update the remote Canvas instance.") + self._current_grade = value + + @property + def final_grade(self): + """The user's final grade for the class. Only included if user has permissions to view this grade.""" + return self._final_grade + + @final_grade.setter + def final_grade(self, value): + """Setter for final_grade property.""" + self.logger.warn("Setting values on final_grade will NOT update the remote Canvas instance.") + self._final_grade = value + + +class Enrollment(BaseModel): + """Enrollment Model.""" + + def __init__(self, limit_privileges_to_course_section=None, course_section_id=None, updated_at=None, current_period_computed_current_score=None, grades=None, course_id=None, multiple_grading_periods_enabled=None, id=None, user_id=None, sis_user_id=None, root_account_id=None, current_period_computed_current_grade=None, end_at=None, computed_final_grade=None, sis_import_id=None, role=None, enrollment_state=None, type=None, course_integration_id=None, section_integration_id=None, start_at=None, computed_current_score=None, current_grading_period_id=None, html_url=None, current_period_computed_final_score=None, computed_current_grade=None, associated_user_id=None, last_activity_at=None, sis_account_id=None, totals_for_all_grading_periods_option=None, computed_final_score=None, current_period_computed_final_grade=None, sis_course_id=None, current_grading_period_title=None, sis_section_id=None, total_activity_time=None): + """Init method for Enrollment class.""" + self._limit_privileges_to_course_section = limit_privileges_to_course_section + self._course_section_id = course_section_id + self._updated_at = updated_at + self._current_period_computed_current_score = current_period_computed_current_score + self._grades = grades + self._course_id = course_id + self._multiple_grading_periods_enabled = multiple_grading_periods_enabled + self._id = id + self._user_id = user_id + self._sis_user_id = sis_user_id + self._root_account_id = root_account_id + self._current_period_computed_current_grade = current_period_computed_current_grade + self._end_at = end_at + self._computed_final_grade = computed_final_grade + self._sis_import_id = sis_import_id + self._role = role + self._enrollment_state = enrollment_state + self._type = type + self._course_integration_id = course_integration_id + self._section_integration_id = section_integration_id + self._start_at = start_at + self._computed_current_score = computed_current_score + self._current_grading_period_id = current_grading_period_id + self._html_url = html_url + self._current_period_computed_final_score = current_period_computed_final_score + self._computed_current_grade = computed_current_grade + self._associated_user_id = associated_user_id + self._last_activity_at = last_activity_at + self._sis_account_id = sis_account_id + self._totals_for_all_grading_periods_option = totals_for_all_grading_periods_option + self._computed_final_score = computed_final_score + self._current_period_computed_final_grade = current_period_computed_final_grade + self._sis_course_id = sis_course_id + self._current_grading_period_title = current_grading_period_title + self._sis_section_id = sis_section_id + self._total_activity_time = total_activity_time + + self.logger = logging.getLogger('pycanvas.Enrollment') + + @property + def limit_privileges_to_course_section(self): + """User can only access his or her own course section. Applies to Teacher and TA enrollments.""" + return self._limit_privileges_to_course_section + + @limit_privileges_to_course_section.setter + def limit_privileges_to_course_section(self, value): + """Setter for limit_privileges_to_course_section property.""" + self.logger.warn("Setting values on limit_privileges_to_course_section will NOT update the remote Canvas instance.") + self._limit_privileges_to_course_section = value + + @property + def course_section_id(self): + """The unique id of the user's section.""" + return self._course_section_id + + @course_section_id.setter + def course_section_id(self, value): + """Setter for course_section_id property.""" + self.logger.warn("Setting values on course_section_id will NOT update the remote Canvas instance.") + self._course_section_id = value + + @property + def updated_at(self): + """The updated time of the enrollment, in ISO8601 format.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def current_period_computed_current_score(self): + """optional: The student's score in the course for the current grading period, ignoring ungraded assignments. If the course the enrollment belongs to does not have Multiple Grading Periods enabled, or if no currently active grading period exists, the value will be null. (applies only to student enrollments, and only available in course endpoints).""" + return self._current_period_computed_current_score + + @current_period_computed_current_score.setter + def current_period_computed_current_score(self, value): + """Setter for current_period_computed_current_score property.""" + self.logger.warn("Setting values on current_period_computed_current_score will NOT update the remote Canvas instance.") + self._current_period_computed_current_score = value + + @property + def grades(self): + """The URL to the Canvas web UI page containing the grades associated with this enrollment.""" + return self._grades + + @grades.setter + def grades(self, value): + """Setter for grades property.""" + self.logger.warn("Setting values on grades will NOT update the remote Canvas instance.") + self._grades = value + + @property + def course_id(self): + """The unique id of the course.""" + return self._course_id + + @course_id.setter + def course_id(self, value): + """Setter for course_id property.""" + self.logger.warn("Setting values on course_id will NOT update the remote Canvas instance.") + self._course_id = value + + @property + def multiple_grading_periods_enabled(self): + """optional: Indicates whether the course the enrollment belongs to has the Multiple Grading Periods feature enabled. (applies only to student enrollments, and only available in course endpoints).""" + return self._multiple_grading_periods_enabled + + @multiple_grading_periods_enabled.setter + def multiple_grading_periods_enabled(self, value): + """Setter for multiple_grading_periods_enabled property.""" + self.logger.warn("Setting values on multiple_grading_periods_enabled will NOT update the remote Canvas instance.") + self._multiple_grading_periods_enabled = value + + @property + def id(self): + """The ID of the enrollment.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def user_id(self): + """The unique id of the user.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def sis_user_id(self): + """The SIS User ID in which the enrollment is associated. Only displayed if present. This field is only included if the user has permission to view SIS information.""" + return self._sis_user_id + + @sis_user_id.setter + def sis_user_id(self, value): + """Setter for sis_user_id property.""" + self.logger.warn("Setting values on sis_user_id will NOT update the remote Canvas instance.") + self._sis_user_id = value + + @property + def root_account_id(self): + """The unique id of the user's account.""" + return self._root_account_id + + @root_account_id.setter + def root_account_id(self, value): + """Setter for root_account_id property.""" + self.logger.warn("Setting values on root_account_id will NOT update the remote Canvas instance.") + self._root_account_id = value + + @property + def current_period_computed_current_grade(self): + """optional: The letter grade equivalent of current_period_computed_current_score, if available. If the course the enrollment belongs to does not have Multiple Grading Periods enabled, or if no currently active grading period exists, the value will be null. (applies only to student enrollments, and only available in course endpoints).""" + return self._current_period_computed_current_grade + + @current_period_computed_current_grade.setter + def current_period_computed_current_grade(self, value): + """Setter for current_period_computed_current_grade property.""" + self.logger.warn("Setting values on current_period_computed_current_grade will NOT update the remote Canvas instance.") + self._current_period_computed_current_grade = value + + @property + def end_at(self): + """The end time of the enrollment, in ISO8601 format.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def computed_final_grade(self): + """optional: The letter grade equivalent of computed_final_score, if available. (applies only to student enrollments, and only available in course endpoints).""" + return self._computed_final_grade + + @computed_final_grade.setter + def computed_final_grade(self, value): + """Setter for computed_final_grade property.""" + self.logger.warn("Setting values on computed_final_grade will NOT update the remote Canvas instance.") + self._computed_final_grade = value + + @property + def sis_import_id(self): + """The unique identifier for the SIS import. This field is only included if the user has permission to manage SIS information.""" + return self._sis_import_id + + @sis_import_id.setter + def sis_import_id(self, value): + """Setter for sis_import_id property.""" + self.logger.warn("Setting values on sis_import_id will NOT update the remote Canvas instance.") + self._sis_import_id = value + + @property + def role(self): + """The enrollment role, for course-level permissions. This field will match `type` if the enrollment role has not been customized.""" + return self._role + + @role.setter + def role(self, value): + """Setter for role property.""" + self.logger.warn("Setting values on role will NOT update the remote Canvas instance.") + self._role = value + + @property + def enrollment_state(self): + """The state of the user's enrollment in the course.""" + return self._enrollment_state + + @enrollment_state.setter + def enrollment_state(self, value): + """Setter for enrollment_state property.""" + self.logger.warn("Setting values on enrollment_state will NOT update the remote Canvas instance.") + self._enrollment_state = value + + @property + def type(self): + """The enrollment type. One of 'StudentEnrollment', 'TeacherEnrollment', 'TaEnrollment', 'DesignerEnrollment', 'ObserverEnrollment'.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def course_integration_id(self): + """The Course Integration ID in which the enrollment is associated. This field is only included if the user has permission to view SIS information.""" + return self._course_integration_id + + @course_integration_id.setter + def course_integration_id(self, value): + """Setter for course_integration_id property.""" + self.logger.warn("Setting values on course_integration_id will NOT update the remote Canvas instance.") + self._course_integration_id = value + + @property + def section_integration_id(self): + """The Section Integration ID in which the enrollment is associated. This field is only included if the user has permission to view SIS information.""" + return self._section_integration_id + + @section_integration_id.setter + def section_integration_id(self, value): + """Setter for section_integration_id property.""" + self.logger.warn("Setting values on section_integration_id will NOT update the remote Canvas instance.") + self._section_integration_id = value + + @property + def start_at(self): + """The start time of the enrollment, in ISO8601 format.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def computed_current_score(self): + """optional: The student's score in the course, ignoring ungraded assignments. (applies only to student enrollments, and only available in course endpoints).""" + return self._computed_current_score + + @computed_current_score.setter + def computed_current_score(self, value): + """Setter for computed_current_score property.""" + self.logger.warn("Setting values on computed_current_score will NOT update the remote Canvas instance.") + self._computed_current_score = value + + @property + def current_grading_period_id(self): + """optional: The id of the currently active grading period, if one exists. If the course the enrollment belongs to does not have Multiple Grading Periods enabled, or if no currently active grading period exists, the value will be null. (applies only to student enrollments, and only available in course endpoints).""" + return self._current_grading_period_id + + @current_grading_period_id.setter + def current_grading_period_id(self, value): + """Setter for current_grading_period_id property.""" + self.logger.warn("Setting values on current_grading_period_id will NOT update the remote Canvas instance.") + self._current_grading_period_id = value + + @property + def html_url(self): + """The URL to the Canvas web UI page for this course enrollment.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def current_period_computed_final_score(self): + """optional: The student's score in the course for the current grading period, including ungraded assignments with a score of 0. If the course the enrollment belongs to does not have Multiple Grading Periods enabled, or if no currently active grading period exists, the value will be null. (applies only to student enrollments, and only available in course endpoints).""" + return self._current_period_computed_final_score + + @current_period_computed_final_score.setter + def current_period_computed_final_score(self, value): + """Setter for current_period_computed_final_score property.""" + self.logger.warn("Setting values on current_period_computed_final_score will NOT update the remote Canvas instance.") + self._current_period_computed_final_score = value + + @property + def computed_current_grade(self): + """optional: The letter grade equivalent of computed_current_score, if available. (applies only to student enrollments, and only available in course endpoints).""" + return self._computed_current_grade + + @computed_current_grade.setter + def computed_current_grade(self, value): + """Setter for computed_current_grade property.""" + self.logger.warn("Setting values on computed_current_grade will NOT update the remote Canvas instance.") + self._computed_current_grade = value + + @property + def associated_user_id(self): + """The unique id of the associated user. Will be null unless type is ObserverEnrollment.""" + return self._associated_user_id + + @associated_user_id.setter + def associated_user_id(self, value): + """Setter for associated_user_id property.""" + self.logger.warn("Setting values on associated_user_id will NOT update the remote Canvas instance.") + self._associated_user_id = value + + @property + def last_activity_at(self): + """The last activity time of the user for the enrollment, in ISO8601 format.""" + return self._last_activity_at + + @last_activity_at.setter + def last_activity_at(self, value): + """Setter for last_activity_at property.""" + self.logger.warn("Setting values on last_activity_at will NOT update the remote Canvas instance.") + self._last_activity_at = value + + @property + def sis_account_id(self): + """The SIS Account ID in which the enrollment is associated. Only displayed if present. This field is only included if the user has permission to view SIS information.""" + return self._sis_account_id + + @sis_account_id.setter + def sis_account_id(self, value): + """Setter for sis_account_id property.""" + self.logger.warn("Setting values on sis_account_id will NOT update the remote Canvas instance.") + self._sis_account_id = value + + @property + def totals_for_all_grading_periods_option(self): + """optional: Indicates whether the course the enrollment belongs to has the Display Totals for 'All Grading Periods' feature enabled. (applies only to student enrollments, and only available in course endpoints).""" + return self._totals_for_all_grading_periods_option + + @totals_for_all_grading_periods_option.setter + def totals_for_all_grading_periods_option(self, value): + """Setter for totals_for_all_grading_periods_option property.""" + self.logger.warn("Setting values on totals_for_all_grading_periods_option will NOT update the remote Canvas instance.") + self._totals_for_all_grading_periods_option = value + + @property + def computed_final_score(self): + """optional: The student's score in the course including ungraded assignments with a score of 0. (applies only to student enrollments, and only available in course endpoints).""" + return self._computed_final_score + + @computed_final_score.setter + def computed_final_score(self, value): + """Setter for computed_final_score property.""" + self.logger.warn("Setting values on computed_final_score will NOT update the remote Canvas instance.") + self._computed_final_score = value + + @property + def current_period_computed_final_grade(self): + """optional: The letter grade equivalent of current_period_computed_final_score, if available. If the course the enrollment belongs to does not have Multiple Grading Periods enabled, or if no currently active grading period exists, the value will be null. (applies only to student enrollments, and only available in course endpoints).""" + return self._current_period_computed_final_grade + + @current_period_computed_final_grade.setter + def current_period_computed_final_grade(self, value): + """Setter for current_period_computed_final_grade property.""" + self.logger.warn("Setting values on current_period_computed_final_grade will NOT update the remote Canvas instance.") + self._current_period_computed_final_grade = value + + @property + def sis_course_id(self): + """The SIS Course ID in which the enrollment is associated. Only displayed if present. This field is only included if the user has permission to view SIS information.""" + return self._sis_course_id + + @sis_course_id.setter + def sis_course_id(self, value): + """Setter for sis_course_id property.""" + self.logger.warn("Setting values on sis_course_id will NOT update the remote Canvas instance.") + self._sis_course_id = value + + @property + def current_grading_period_title(self): + """optional: The name of the currently active grading period, if one exists. If the course the enrollment belongs to does not have Multiple Grading Periods enabled, or if no currently active grading period exists, the value will be null. (applies only to student enrollments, and only available in course endpoints).""" + return self._current_grading_period_title + + @current_grading_period_title.setter + def current_grading_period_title(self, value): + """Setter for current_grading_period_title property.""" + self.logger.warn("Setting values on current_grading_period_title will NOT update the remote Canvas instance.") + self._current_grading_period_title = value + + @property + def sis_section_id(self): + """The SIS Section ID in which the enrollment is associated. Only displayed if present. This field is only included if the user has permission to view SIS information.""" + return self._sis_section_id + + @sis_section_id.setter + def sis_section_id(self, value): + """Setter for sis_section_id property.""" + self.logger.warn("Setting values on sis_section_id will NOT update the remote Canvas instance.") + self._sis_section_id = value + + @property + def total_activity_time(self): + """The total activity time of the user for the enrollment, in seconds.""" + return self._total_activity_time + + @total_activity_time.setter + def total_activity_time(self, value): + """Setter for total_activity_time property.""" + self.logger.warn("Setting values on total_activity_time will NOT update the remote Canvas instance.") + self._total_activity_time = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/external_tools.py b/venv/Lib/site-packages/pycanvas/apis/external_tools.py new file mode 100644 index 00000000..3add2986 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/external_tools.py @@ -0,0 +1,983 @@ +"""ExternalTools API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + + +class ExternalToolsAPI(BaseCanvasAPI): + """ExternalTools API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for ExternalToolsAPI.""" + super(ExternalToolsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.ExternalToolsAPI") + + def list_external_tools_courses(self, course_id, include_parents=None, search_term=None, selectable=None): + """ + List external tools. + + Returns the paginated list of external tools for the current context. + See the get request docs for a single tool for a list of properties on an external tool. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - search_term + """The partial name of the tools to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - selectable + """If true, then only tools that are meant to be selectable are returned""" + if selectable is not None: + params["selectable"] = selectable + + # OPTIONAL - include_parents + """If true, then include tools installed in all accounts above the current context""" + if include_parents is not None: + params["include_parents"] = include_parents + + self.logger.debug("GET /api/v1/courses/{course_id}/external_tools with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/external_tools".format(**path), data=data, params=params, no_data=True) + + def list_external_tools_accounts(self, account_id, include_parents=None, search_term=None, selectable=None): + """ + List external tools. + + Returns the paginated list of external tools for the current context. + See the get request docs for a single tool for a list of properties on an external tool. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - search_term + """The partial name of the tools to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - selectable + """If true, then only tools that are meant to be selectable are returned""" + if selectable is not None: + params["selectable"] = selectable + + # OPTIONAL - include_parents + """If true, then include tools installed in all accounts above the current context""" + if include_parents is not None: + params["include_parents"] = include_parents + + self.logger.debug("GET /api/v1/accounts/{account_id}/external_tools with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/external_tools".format(**path), data=data, params=params, no_data=True) + + def list_external_tools_groups(self, group_id, include_parents=None, search_term=None, selectable=None): + """ + List external tools. + + Returns the paginated list of external tools for the current context. + See the get request docs for a single tool for a list of properties on an external tool. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - search_term + """The partial name of the tools to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - selectable + """If true, then only tools that are meant to be selectable are returned""" + if selectable is not None: + params["selectable"] = selectable + + # OPTIONAL - include_parents + """If true, then include tools installed in all accounts above the current context""" + if include_parents is not None: + params["include_parents"] = include_parents + + self.logger.debug("GET /api/v1/groups/{group_id}/external_tools with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/external_tools".format(**path), data=data, params=params, no_data=True) + + def get_sessionless_launch_url_for_external_tool_courses(self, course_id, assignment_id=None, id=None, launch_type=None, module_item_id=None, url=None): + """ + Get a sessionless launch url for an external tool. + + Returns a sessionless launch url for an external tool. + + NOTE: Either the id or url must be provided unless launch_type is assessment or module_item. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - id + """The external id of the tool to launch.""" + if id is not None: + params["id"] = id + + # OPTIONAL - url + """The LTI launch url for the external tool.""" + if url is not None: + params["url"] = url + + # OPTIONAL - assignment_id + """The assignment id for an assignment launch. Required if launch_type is set to "assessment".""" + if assignment_id is not None: + params["assignment_id"] = assignment_id + + # OPTIONAL - module_item_id + """The assignment id for a module item launch. Required if launch_type is set to "module_item".""" + if module_item_id is not None: + params["module_item_id"] = module_item_id + + # OPTIONAL - launch_type + """The type of launch to perform on the external tool. Placement names (eg. "course_navigation") + can also be specified to use the custom launch url for that placement; if done, the tool id + must be provided.""" + if launch_type is not None: + self._validate_enum(launch_type, ["assessment", "module_item"]) + params["launch_type"] = launch_type + + self.logger.debug("GET /api/v1/courses/{course_id}/external_tools/sessionless_launch with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/external_tools/sessionless_launch".format(**path), data=data, params=params, no_data=True) + + def get_sessionless_launch_url_for_external_tool_accounts(self, account_id, assignment_id=None, id=None, launch_type=None, module_item_id=None, url=None): + """ + Get a sessionless launch url for an external tool. + + Returns a sessionless launch url for an external tool. + + NOTE: Either the id or url must be provided unless launch_type is assessment or module_item. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - id + """The external id of the tool to launch.""" + if id is not None: + params["id"] = id + + # OPTIONAL - url + """The LTI launch url for the external tool.""" + if url is not None: + params["url"] = url + + # OPTIONAL - assignment_id + """The assignment id for an assignment launch. Required if launch_type is set to "assessment".""" + if assignment_id is not None: + params["assignment_id"] = assignment_id + + # OPTIONAL - module_item_id + """The assignment id for a module item launch. Required if launch_type is set to "module_item".""" + if module_item_id is not None: + params["module_item_id"] = module_item_id + + # OPTIONAL - launch_type + """The type of launch to perform on the external tool. Placement names (eg. "course_navigation") + can also be specified to use the custom launch url for that placement; if done, the tool id + must be provided.""" + if launch_type is not None: + self._validate_enum(launch_type, ["assessment", "module_item"]) + params["launch_type"] = launch_type + + self.logger.debug("GET /api/v1/accounts/{account_id}/external_tools/sessionless_launch with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/external_tools/sessionless_launch".format(**path), data=data, params=params, no_data=True) + + def get_single_external_tool_courses(self, course_id, external_tool_id): + """ + Get a single external tool. + + Returns the specified external tool. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - external_tool_id + """ID""" + path["external_tool_id"] = external_tool_id + + self.logger.debug("GET /api/v1/courses/{course_id}/external_tools/{external_tool_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/external_tools/{external_tool_id}".format(**path), data=data, params=params, no_data=True) + + def get_single_external_tool_accounts(self, account_id, external_tool_id): + """ + Get a single external tool. + + Returns the specified external tool. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - external_tool_id + """ID""" + path["external_tool_id"] = external_tool_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/external_tools/{external_tool_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/external_tools/{external_tool_id}".format(**path), data=data, params=params, no_data=True) + + def create_external_tool_courses(self, name, course_id, consumer_key, privacy_level, shared_secret, account_navigation_enabled=None, account_navigation_selection_height=None, account_navigation_selection_width=None, account_navigation_text=None, account_navigation_url=None, config_type=None, config_url=None, config_xml=None, course_home_sub_navigation_enabled=None, course_home_sub_navigation_icon_url=None, course_home_sub_navigation_text=None, course_home_sub_navigation_url=None, course_navigation_default=None, course_navigation_enabled=None, course_navigation_text=None, course_navigation_visibility=None, course_navigation_windowTarget=None, custom_fields_field_name=None, description=None, domain=None, editor_button_enabled=None, editor_button_icon_url=None, editor_button_message_type=None, editor_button_selection_height=None, editor_button_selection_width=None, editor_button_url=None, homework_submission_enabled=None, homework_submission_message_type=None, homework_submission_text=None, homework_submission_url=None, icon_url=None, link_selection_enabled=None, link_selection_message_type=None, link_selection_text=None, link_selection_url=None, migration_selection_enabled=None, migration_selection_message_type=None, migration_selection_url=None, not_selectable=None, oauth_compliant=None, resource_selection_enabled=None, resource_selection_icon_url=None, resource_selection_selection_height=None, resource_selection_selection_width=None, resource_selection_url=None, text=None, tool_configuration_enabled=None, tool_configuration_message_type=None, tool_configuration_url=None, url=None, user_navigation_enabled=None, user_navigation_text=None, user_navigation_url=None): + """ + Create an external tool. + + Create an external tool in the specified course/account. + The created tool will be returned, see the "show" endpoint for an example. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - name + """The name of the tool""" + data["name"] = name + + # REQUIRED - privacy_level + """What information to send to the external tool.""" + self._validate_enum(privacy_level, ["anonymous", "name_only", "public"]) + data["privacy_level"] = privacy_level + + # REQUIRED - consumer_key + """The consumer key for the external tool""" + data["consumer_key"] = consumer_key + + # REQUIRED - shared_secret + """The shared secret with the external tool""" + data["shared_secret"] = shared_secret + + # OPTIONAL - description + """A description of the tool""" + if description is not None: + data["description"] = description + + # OPTIONAL - url + """The url to match links against. Either "url" or "domain" should be set, + not both.""" + if url is not None: + data["url"] = url + + # OPTIONAL - domain + """The domain to match links against. Either "url" or "domain" should be + set, not both.""" + if domain is not None: + data["domain"] = domain + + # OPTIONAL - icon_url + """The url of the icon to show for this tool""" + if icon_url is not None: + data["icon_url"] = icon_url + + # OPTIONAL - text + """The default text to show for this tool""" + if text is not None: + data["text"] = text + + # OPTIONAL - custom_fields[field_name] + """Custom fields that will be sent to the tool consumer; can be used + multiple times""" + if custom_fields_field_name is not None: + data["custom_fields[field_name]"] = custom_fields_field_name + + # OPTIONAL - account_navigation[url] + """The url of the external tool for account navigation""" + if account_navigation_url is not None: + data["account_navigation[url]"] = account_navigation_url + + # OPTIONAL - account_navigation[enabled] + """Set this to enable this feature""" + if account_navigation_enabled is not None: + data["account_navigation[enabled]"] = account_navigation_enabled + + # OPTIONAL - account_navigation[text] + """The text that will show on the left-tab in the account navigation""" + if account_navigation_text is not None: + data["account_navigation[text]"] = account_navigation_text + + # OPTIONAL - account_navigation[selection_width] + """The width of the dialog the tool is launched in""" + if account_navigation_selection_width is not None: + data["account_navigation[selection_width]"] = account_navigation_selection_width + + # OPTIONAL - account_navigation[selection_height] + """The height of the dialog the tool is launched in""" + if account_navigation_selection_height is not None: + data["account_navigation[selection_height]"] = account_navigation_selection_height + + # OPTIONAL - user_navigation[url] + """The url of the external tool for user navigation""" + if user_navigation_url is not None: + data["user_navigation[url]"] = user_navigation_url + + # OPTIONAL - user_navigation[enabled] + """Set this to enable this feature""" + if user_navigation_enabled is not None: + data["user_navigation[enabled]"] = user_navigation_enabled + + # OPTIONAL - user_navigation[text] + """The text that will show on the left-tab in the user navigation""" + if user_navigation_text is not None: + data["user_navigation[text]"] = user_navigation_text + + # OPTIONAL - course_home_sub_navigation[url] + """The url of the external tool for right-side course home navigation menu""" + if course_home_sub_navigation_url is not None: + data["course_home_sub_navigation[url]"] = course_home_sub_navigation_url + + # OPTIONAL - course_home_sub_navigation[enabled] + """Set this to enable this feature""" + if course_home_sub_navigation_enabled is not None: + data["course_home_sub_navigation[enabled]"] = course_home_sub_navigation_enabled + + # OPTIONAL - course_home_sub_navigation[text] + """The text that will show on the right-side course home navigation menu""" + if course_home_sub_navigation_text is not None: + data["course_home_sub_navigation[text]"] = course_home_sub_navigation_text + + # OPTIONAL - course_home_sub_navigation[icon_url] + """The url of the icon to show in the right-side course home navigation menu""" + if course_home_sub_navigation_icon_url is not None: + data["course_home_sub_navigation[icon_url]"] = course_home_sub_navigation_icon_url + + # OPTIONAL - course_navigation[enabled] + """Set this to enable this feature""" + if course_navigation_enabled is not None: + data["course_navigation[enabled]"] = course_navigation_enabled + + # OPTIONAL - course_navigation[text] + """The text that will show on the left-tab in the course navigation""" + if course_navigation_text is not None: + data["course_navigation[text]"] = course_navigation_text + + # OPTIONAL - course_navigation[visibility] + """Who will see the navigation tab. "admins" for course admins, "members" for + students, null for everyone""" + if course_navigation_visibility is not None: + self._validate_enum(course_navigation_visibility, ["admins", "members"]) + data["course_navigation[visibility]"] = course_navigation_visibility + + # OPTIONAL - course_navigation[windowTarget] + """Determines how the navigation tab will be opened. + "_blank" Launches the external tool in a new window or tab. + "_self" (Default) Launches the external tool in an iframe inside of Canvas.""" + if course_navigation_windowTarget is not None: + self._validate_enum(course_navigation_windowTarget, ["_blank", "_self"]) + data["course_navigation[windowTarget]"] = course_navigation_windowTarget + + # OPTIONAL - course_navigation[default] + """Whether the navigation option will show in the course by default or + whether the teacher will have to explicitly enable it""" + if course_navigation_default is not None: + data["course_navigation[default]"] = course_navigation_default + + # OPTIONAL - editor_button[url] + """The url of the external tool""" + if editor_button_url is not None: + data["editor_button[url]"] = editor_button_url + + # OPTIONAL - editor_button[enabled] + """Set this to enable this feature""" + if editor_button_enabled is not None: + data["editor_button[enabled]"] = editor_button_enabled + + # OPTIONAL - editor_button[icon_url] + """The url of the icon to show in the WYSIWYG editor""" + if editor_button_icon_url is not None: + data["editor_button[icon_url]"] = editor_button_icon_url + + # OPTIONAL - editor_button[selection_width] + """The width of the dialog the tool is launched in""" + if editor_button_selection_width is not None: + data["editor_button[selection_width]"] = editor_button_selection_width + + # OPTIONAL - editor_button[selection_height] + """The height of the dialog the tool is launched in""" + if editor_button_selection_height is not None: + data["editor_button[selection_height]"] = editor_button_selection_height + + # OPTIONAL - editor_button[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if editor_button_message_type is not None: + data["editor_button[message_type]"] = editor_button_message_type + + # OPTIONAL - homework_submission[url] + """The url of the external tool""" + if homework_submission_url is not None: + data["homework_submission[url]"] = homework_submission_url + + # OPTIONAL - homework_submission[enabled] + """Set this to enable this feature""" + if homework_submission_enabled is not None: + data["homework_submission[enabled]"] = homework_submission_enabled + + # OPTIONAL - homework_submission[text] + """The text that will show on the homework submission tab""" + if homework_submission_text is not None: + data["homework_submission[text]"] = homework_submission_text + + # OPTIONAL - homework_submission[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if homework_submission_message_type is not None: + data["homework_submission[message_type]"] = homework_submission_message_type + + # OPTIONAL - link_selection[url] + """The url of the external tool""" + if link_selection_url is not None: + data["link_selection[url]"] = link_selection_url + + # OPTIONAL - link_selection[enabled] + """Set this to enable this feature""" + if link_selection_enabled is not None: + data["link_selection[enabled]"] = link_selection_enabled + + # OPTIONAL - link_selection[text] + """The text that will show for the link selection text""" + if link_selection_text is not None: + data["link_selection[text]"] = link_selection_text + + # OPTIONAL - link_selection[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if link_selection_message_type is not None: + data["link_selection[message_type]"] = link_selection_message_type + + # OPTIONAL - migration_selection[url] + """The url of the external tool""" + if migration_selection_url is not None: + data["migration_selection[url]"] = migration_selection_url + + # OPTIONAL - migration_selection[enabled] + """Set this to enable this feature""" + if migration_selection_enabled is not None: + data["migration_selection[enabled]"] = migration_selection_enabled + + # OPTIONAL - migration_selection[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if migration_selection_message_type is not None: + data["migration_selection[message_type]"] = migration_selection_message_type + + # OPTIONAL - tool_configuration[url] + """The url of the external tool""" + if tool_configuration_url is not None: + data["tool_configuration[url]"] = tool_configuration_url + + # OPTIONAL - tool_configuration[enabled] + """Set this to enable this feature""" + if tool_configuration_enabled is not None: + data["tool_configuration[enabled]"] = tool_configuration_enabled + + # OPTIONAL - tool_configuration[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if tool_configuration_message_type is not None: + data["tool_configuration[message_type]"] = tool_configuration_message_type + + # OPTIONAL - resource_selection[url] + """The url of the external tool""" + if resource_selection_url is not None: + data["resource_selection[url]"] = resource_selection_url + + # OPTIONAL - resource_selection[enabled] + """Set this to enable this feature""" + if resource_selection_enabled is not None: + data["resource_selection[enabled]"] = resource_selection_enabled + + # OPTIONAL - resource_selection[icon_url] + """The url of the icon to show in the module external tool list""" + if resource_selection_icon_url is not None: + data["resource_selection[icon_url]"] = resource_selection_icon_url + + # OPTIONAL - resource_selection[selection_width] + """The width of the dialog the tool is launched in""" + if resource_selection_selection_width is not None: + data["resource_selection[selection_width]"] = resource_selection_selection_width + + # OPTIONAL - resource_selection[selection_height] + """The height of the dialog the tool is launched in""" + if resource_selection_selection_height is not None: + data["resource_selection[selection_height]"] = resource_selection_selection_height + + # OPTIONAL - config_type + """Configuration can be passed in as CC xml instead of using query + parameters. If this value is "by_url" or "by_xml" then an xml + configuration will be expected in either the "config_xml" or "config_url" + parameter. Note that the name parameter overrides the tool name provided + in the xml""" + if config_type is not None: + data["config_type"] = config_type + + # OPTIONAL - config_xml + """XML tool configuration, as specified in the CC xml specification. This is + required if "config_type" is set to "by_xml"""" + if config_xml is not None: + data["config_xml"] = config_xml + + # OPTIONAL - config_url + """URL where the server can retrieve an XML tool configuration, as specified + in the CC xml specification. This is required if "config_type" is set to + "by_url"""" + if config_url is not None: + data["config_url"] = config_url + + # OPTIONAL - not_selectable + """Default: false, if set to true the tool won't show up in the external tool + selection UI in modules and assignments""" + if not_selectable is not None: + data["not_selectable"] = not_selectable + + # OPTIONAL - oauth_compliant + """Default: false, if set to true LTI query params will not be copied to the + post body.""" + if oauth_compliant is not None: + data["oauth_compliant"] = oauth_compliant + + self.logger.debug("POST /api/v1/courses/{course_id}/external_tools with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/external_tools".format(**path), data=data, params=params, no_data=True) + + def create_external_tool_accounts(self, name, account_id, consumer_key, privacy_level, shared_secret, account_navigation_enabled=None, account_navigation_selection_height=None, account_navigation_selection_width=None, account_navigation_text=None, account_navigation_url=None, config_type=None, config_url=None, config_xml=None, course_home_sub_navigation_enabled=None, course_home_sub_navigation_icon_url=None, course_home_sub_navigation_text=None, course_home_sub_navigation_url=None, course_navigation_default=None, course_navigation_enabled=None, course_navigation_text=None, course_navigation_visibility=None, course_navigation_windowTarget=None, custom_fields_field_name=None, description=None, domain=None, editor_button_enabled=None, editor_button_icon_url=None, editor_button_message_type=None, editor_button_selection_height=None, editor_button_selection_width=None, editor_button_url=None, homework_submission_enabled=None, homework_submission_message_type=None, homework_submission_text=None, homework_submission_url=None, icon_url=None, link_selection_enabled=None, link_selection_message_type=None, link_selection_text=None, link_selection_url=None, migration_selection_enabled=None, migration_selection_message_type=None, migration_selection_url=None, not_selectable=None, oauth_compliant=None, resource_selection_enabled=None, resource_selection_icon_url=None, resource_selection_selection_height=None, resource_selection_selection_width=None, resource_selection_url=None, text=None, tool_configuration_enabled=None, tool_configuration_message_type=None, tool_configuration_url=None, url=None, user_navigation_enabled=None, user_navigation_text=None, user_navigation_url=None): + """ + Create an external tool. + + Create an external tool in the specified course/account. + The created tool will be returned, see the "show" endpoint for an example. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - name + """The name of the tool""" + data["name"] = name + + # REQUIRED - privacy_level + """What information to send to the external tool.""" + self._validate_enum(privacy_level, ["anonymous", "name_only", "public"]) + data["privacy_level"] = privacy_level + + # REQUIRED - consumer_key + """The consumer key for the external tool""" + data["consumer_key"] = consumer_key + + # REQUIRED - shared_secret + """The shared secret with the external tool""" + data["shared_secret"] = shared_secret + + # OPTIONAL - description + """A description of the tool""" + if description is not None: + data["description"] = description + + # OPTIONAL - url + """The url to match links against. Either "url" or "domain" should be set, + not both.""" + if url is not None: + data["url"] = url + + # OPTIONAL - domain + """The domain to match links against. Either "url" or "domain" should be + set, not both.""" + if domain is not None: + data["domain"] = domain + + # OPTIONAL - icon_url + """The url of the icon to show for this tool""" + if icon_url is not None: + data["icon_url"] = icon_url + + # OPTIONAL - text + """The default text to show for this tool""" + if text is not None: + data["text"] = text + + # OPTIONAL - custom_fields[field_name] + """Custom fields that will be sent to the tool consumer; can be used + multiple times""" + if custom_fields_field_name is not None: + data["custom_fields[field_name]"] = custom_fields_field_name + + # OPTIONAL - account_navigation[url] + """The url of the external tool for account navigation""" + if account_navigation_url is not None: + data["account_navigation[url]"] = account_navigation_url + + # OPTIONAL - account_navigation[enabled] + """Set this to enable this feature""" + if account_navigation_enabled is not None: + data["account_navigation[enabled]"] = account_navigation_enabled + + # OPTIONAL - account_navigation[text] + """The text that will show on the left-tab in the account navigation""" + if account_navigation_text is not None: + data["account_navigation[text]"] = account_navigation_text + + # OPTIONAL - account_navigation[selection_width] + """The width of the dialog the tool is launched in""" + if account_navigation_selection_width is not None: + data["account_navigation[selection_width]"] = account_navigation_selection_width + + # OPTIONAL - account_navigation[selection_height] + """The height of the dialog the tool is launched in""" + if account_navigation_selection_height is not None: + data["account_navigation[selection_height]"] = account_navigation_selection_height + + # OPTIONAL - user_navigation[url] + """The url of the external tool for user navigation""" + if user_navigation_url is not None: + data["user_navigation[url]"] = user_navigation_url + + # OPTIONAL - user_navigation[enabled] + """Set this to enable this feature""" + if user_navigation_enabled is not None: + data["user_navigation[enabled]"] = user_navigation_enabled + + # OPTIONAL - user_navigation[text] + """The text that will show on the left-tab in the user navigation""" + if user_navigation_text is not None: + data["user_navigation[text]"] = user_navigation_text + + # OPTIONAL - course_home_sub_navigation[url] + """The url of the external tool for right-side course home navigation menu""" + if course_home_sub_navigation_url is not None: + data["course_home_sub_navigation[url]"] = course_home_sub_navigation_url + + # OPTIONAL - course_home_sub_navigation[enabled] + """Set this to enable this feature""" + if course_home_sub_navigation_enabled is not None: + data["course_home_sub_navigation[enabled]"] = course_home_sub_navigation_enabled + + # OPTIONAL - course_home_sub_navigation[text] + """The text that will show on the right-side course home navigation menu""" + if course_home_sub_navigation_text is not None: + data["course_home_sub_navigation[text]"] = course_home_sub_navigation_text + + # OPTIONAL - course_home_sub_navigation[icon_url] + """The url of the icon to show in the right-side course home navigation menu""" + if course_home_sub_navigation_icon_url is not None: + data["course_home_sub_navigation[icon_url]"] = course_home_sub_navigation_icon_url + + # OPTIONAL - course_navigation[enabled] + """Set this to enable this feature""" + if course_navigation_enabled is not None: + data["course_navigation[enabled]"] = course_navigation_enabled + + # OPTIONAL - course_navigation[text] + """The text that will show on the left-tab in the course navigation""" + if course_navigation_text is not None: + data["course_navigation[text]"] = course_navigation_text + + # OPTIONAL - course_navigation[visibility] + """Who will see the navigation tab. "admins" for course admins, "members" for + students, null for everyone""" + if course_navigation_visibility is not None: + self._validate_enum(course_navigation_visibility, ["admins", "members"]) + data["course_navigation[visibility]"] = course_navigation_visibility + + # OPTIONAL - course_navigation[windowTarget] + """Determines how the navigation tab will be opened. + "_blank" Launches the external tool in a new window or tab. + "_self" (Default) Launches the external tool in an iframe inside of Canvas.""" + if course_navigation_windowTarget is not None: + self._validate_enum(course_navigation_windowTarget, ["_blank", "_self"]) + data["course_navigation[windowTarget]"] = course_navigation_windowTarget + + # OPTIONAL - course_navigation[default] + """Whether the navigation option will show in the course by default or + whether the teacher will have to explicitly enable it""" + if course_navigation_default is not None: + data["course_navigation[default]"] = course_navigation_default + + # OPTIONAL - editor_button[url] + """The url of the external tool""" + if editor_button_url is not None: + data["editor_button[url]"] = editor_button_url + + # OPTIONAL - editor_button[enabled] + """Set this to enable this feature""" + if editor_button_enabled is not None: + data["editor_button[enabled]"] = editor_button_enabled + + # OPTIONAL - editor_button[icon_url] + """The url of the icon to show in the WYSIWYG editor""" + if editor_button_icon_url is not None: + data["editor_button[icon_url]"] = editor_button_icon_url + + # OPTIONAL - editor_button[selection_width] + """The width of the dialog the tool is launched in""" + if editor_button_selection_width is not None: + data["editor_button[selection_width]"] = editor_button_selection_width + + # OPTIONAL - editor_button[selection_height] + """The height of the dialog the tool is launched in""" + if editor_button_selection_height is not None: + data["editor_button[selection_height]"] = editor_button_selection_height + + # OPTIONAL - editor_button[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if editor_button_message_type is not None: + data["editor_button[message_type]"] = editor_button_message_type + + # OPTIONAL - homework_submission[url] + """The url of the external tool""" + if homework_submission_url is not None: + data["homework_submission[url]"] = homework_submission_url + + # OPTIONAL - homework_submission[enabled] + """Set this to enable this feature""" + if homework_submission_enabled is not None: + data["homework_submission[enabled]"] = homework_submission_enabled + + # OPTIONAL - homework_submission[text] + """The text that will show on the homework submission tab""" + if homework_submission_text is not None: + data["homework_submission[text]"] = homework_submission_text + + # OPTIONAL - homework_submission[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if homework_submission_message_type is not None: + data["homework_submission[message_type]"] = homework_submission_message_type + + # OPTIONAL - link_selection[url] + """The url of the external tool""" + if link_selection_url is not None: + data["link_selection[url]"] = link_selection_url + + # OPTIONAL - link_selection[enabled] + """Set this to enable this feature""" + if link_selection_enabled is not None: + data["link_selection[enabled]"] = link_selection_enabled + + # OPTIONAL - link_selection[text] + """The text that will show for the link selection text""" + if link_selection_text is not None: + data["link_selection[text]"] = link_selection_text + + # OPTIONAL - link_selection[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if link_selection_message_type is not None: + data["link_selection[message_type]"] = link_selection_message_type + + # OPTIONAL - migration_selection[url] + """The url of the external tool""" + if migration_selection_url is not None: + data["migration_selection[url]"] = migration_selection_url + + # OPTIONAL - migration_selection[enabled] + """Set this to enable this feature""" + if migration_selection_enabled is not None: + data["migration_selection[enabled]"] = migration_selection_enabled + + # OPTIONAL - migration_selection[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if migration_selection_message_type is not None: + data["migration_selection[message_type]"] = migration_selection_message_type + + # OPTIONAL - tool_configuration[url] + """The url of the external tool""" + if tool_configuration_url is not None: + data["tool_configuration[url]"] = tool_configuration_url + + # OPTIONAL - tool_configuration[enabled] + """Set this to enable this feature""" + if tool_configuration_enabled is not None: + data["tool_configuration[enabled]"] = tool_configuration_enabled + + # OPTIONAL - tool_configuration[message_type] + """Set this to ContentItemSelectionRequest to tell the tool to use + content-item; otherwise, omit""" + if tool_configuration_message_type is not None: + data["tool_configuration[message_type]"] = tool_configuration_message_type + + # OPTIONAL - resource_selection[url] + """The url of the external tool""" + if resource_selection_url is not None: + data["resource_selection[url]"] = resource_selection_url + + # OPTIONAL - resource_selection[enabled] + """Set this to enable this feature""" + if resource_selection_enabled is not None: + data["resource_selection[enabled]"] = resource_selection_enabled + + # OPTIONAL - resource_selection[icon_url] + """The url of the icon to show in the module external tool list""" + if resource_selection_icon_url is not None: + data["resource_selection[icon_url]"] = resource_selection_icon_url + + # OPTIONAL - resource_selection[selection_width] + """The width of the dialog the tool is launched in""" + if resource_selection_selection_width is not None: + data["resource_selection[selection_width]"] = resource_selection_selection_width + + # OPTIONAL - resource_selection[selection_height] + """The height of the dialog the tool is launched in""" + if resource_selection_selection_height is not None: + data["resource_selection[selection_height]"] = resource_selection_selection_height + + # OPTIONAL - config_type + """Configuration can be passed in as CC xml instead of using query + parameters. If this value is "by_url" or "by_xml" then an xml + configuration will be expected in either the "config_xml" or "config_url" + parameter. Note that the name parameter overrides the tool name provided + in the xml""" + if config_type is not None: + data["config_type"] = config_type + + # OPTIONAL - config_xml + """XML tool configuration, as specified in the CC xml specification. This is + required if "config_type" is set to "by_xml"""" + if config_xml is not None: + data["config_xml"] = config_xml + + # OPTIONAL - config_url + """URL where the server can retrieve an XML tool configuration, as specified + in the CC xml specification. This is required if "config_type" is set to + "by_url"""" + if config_url is not None: + data["config_url"] = config_url + + # OPTIONAL - not_selectable + """Default: false, if set to true the tool won't show up in the external tool + selection UI in modules and assignments""" + if not_selectable is not None: + data["not_selectable"] = not_selectable + + # OPTIONAL - oauth_compliant + """Default: false, if set to true LTI query params will not be copied to the + post body.""" + if oauth_compliant is not None: + data["oauth_compliant"] = oauth_compliant + + self.logger.debug("POST /api/v1/accounts/{account_id}/external_tools with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/external_tools".format(**path), data=data, params=params, no_data=True) + + def edit_external_tool_courses(self, course_id, external_tool_id): + """ + Edit an external tool. + + Update the specified external tool. Uses same parameters as create + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - external_tool_id + """ID""" + path["external_tool_id"] = external_tool_id + + self.logger.debug("PUT /api/v1/courses/{course_id}/external_tools/{external_tool_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/external_tools/{external_tool_id}".format(**path), data=data, params=params, no_data=True) + + def edit_external_tool_accounts(self, account_id, external_tool_id): + """ + Edit an external tool. + + Update the specified external tool. Uses same parameters as create + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - external_tool_id + """ID""" + path["external_tool_id"] = external_tool_id + + self.logger.debug("PUT /api/v1/accounts/{account_id}/external_tools/{external_tool_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/external_tools/{external_tool_id}".format(**path), data=data, params=params, no_data=True) + + def delete_external_tool_courses(self, course_id, external_tool_id): + """ + Delete an external tool. + + Remove the specified external tool + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - external_tool_id + """ID""" + path["external_tool_id"] = external_tool_id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/external_tools/{external_tool_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/external_tools/{external_tool_id}".format(**path), data=data, params=params, no_data=True) + + def delete_external_tool_accounts(self, account_id, external_tool_id): + """ + Delete an external tool. + + Remove the specified external tool + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - external_tool_id + """ID""" + path["external_tool_id"] = external_tool_id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/external_tools/{external_tool_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/external_tools/{external_tool_id}".format(**path), data=data, params=params, no_data=True) + diff --git a/venv/Lib/site-packages/pycanvas/apis/favorites.py b/venv/Lib/site-packages/pycanvas/apis/favorites.py new file mode 100644 index 00000000..e57c0987 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/favorites.py @@ -0,0 +1,181 @@ +"""Favorites API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class FavoritesAPI(BaseCanvasAPI): + """Favorites API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for FavoritesAPI.""" + super(FavoritesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.FavoritesAPI") + + def list_favorite_courses(self): + """ + List favorite courses. + + Retrieve the list of favorite courses for the current user. If the user has not chosen + any favorites, then a selection of currently enrolled courses will be returned. + + See the {api:CoursesController#index List courses API} for details on accepted include[] parameters. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/users/self/favorites/courses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/favorites/courses".format(**path), data=data, params=params, all_pages=True) + + def list_favorite_groups(self): + """ + List favorite groups. + + Retrieve the list of favorite groups for the current user. If the user has not chosen + any favorites, then a selection of groups that the user is a member of will be returned. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/users/self/favorites/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/favorites/groups".format(**path), data=data, params=params, all_pages=True) + + def add_course_to_favorites(self, id): + """ + Add course to favorites. + + Add a course to the current user's favorites. If the course is already + in the user's favorites, nothing happens. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """The ID or SIS ID of the course to add. The current user must be + registered in the course.""" + path["id"] = id + + self.logger.debug("POST /api/v1/users/self/favorites/courses/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/self/favorites/courses/{id}".format(**path), data=data, params=params, single_item=True) + + def add_group_to_favorites(self, id): + """ + Add group to favorites. + + Add a group to the current user's favorites. If the group is already + in the user's favorites, nothing happens. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """The ID or SIS ID of the group to add. The current user must be + a member of the group.""" + path["id"] = id + + self.logger.debug("POST /api/v1/users/self/favorites/groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/self/favorites/groups/{id}".format(**path), data=data, params=params, single_item=True) + + def remove_course_from_favorites(self, id): + """ + Remove course from favorites. + + Remove a course from the current user's favorites. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """the ID or SIS ID of the course to remove""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/users/self/favorites/courses/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/self/favorites/courses/{id}".format(**path), data=data, params=params, single_item=True) + + def remove_group_from_favorites(self, id): + """ + Remove group from favorites. + + Remove a group from the current user's favorites. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """the ID or SIS ID of the group to remove""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/users/self/favorites/groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/self/favorites/groups/{id}".format(**path), data=data, params=params, single_item=True) + + def reset_course_favorites(self): + """ + Reset course favorites. + + Reset the current user's course favorites to the default + automatically generated list of enrolled courses + """ + path = {} + data = {} + params = {} + + self.logger.debug("DELETE /api/v1/users/self/favorites/courses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/self/favorites/courses".format(**path), data=data, params=params, no_data=True) + + def reset_group_favorites(self): + """ + Reset group favorites. + + Reset the current user's group favorites to the default + automatically generated list of enrolled group + """ + path = {} + data = {} + params = {} + + self.logger.debug("DELETE /api/v1/users/self/favorites/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/self/favorites/groups".format(**path), data=data, params=params, no_data=True) + + +class Favorite(BaseModel): + """Favorite Model.""" + + def __init__(self, , context_type=None, context_id=None): + """Init method for Favorite class.""" + self._context_type = context_type + self._context_id = context_id + + self.logger = logging.getLogger('pycanvas.Favorite') + + @property + def context_type(self): + """The type of the object the Favorite refers to (currently, only 'Course' is supported).""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def context_id(self): + """The ID of the object the Favorite refers to.""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/feature_flags.py b/venv/Lib/site-packages/pycanvas/apis/feature_flags.py new file mode 100644 index 00000000..e876a9f6 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/feature_flags.py @@ -0,0 +1,565 @@ +"""FeatureFlags API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class FeatureFlagsAPI(BaseCanvasAPI): + """FeatureFlags API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for FeatureFlagsAPI.""" + super(FeatureFlagsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.FeatureFlagsAPI") + + def list_features_courses(self, course_id): + """ + List features. + + List all features that apply to a given Account, Course, or User. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/features with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/features".format(**path), data=data, params=params, all_pages=True) + + def list_features_accounts(self, account_id): + """ + List features. + + List all features that apply to a given Account, Course, or User. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/features with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/features".format(**path), data=data, params=params, all_pages=True) + + def list_features_users(self, user_id): + """ + List features. + + List all features that apply to a given Account, Course, or User. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/features with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/features".format(**path), data=data, params=params, all_pages=True) + + def list_enabled_features_courses(self, course_id): + """ + List enabled features. + + List all features that are enabled on a given Account, Course, or User. + Only the feature names are returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/features/enabled with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/features/enabled".format(**path), data=data, params=params, no_data=True) + + def list_enabled_features_accounts(self, account_id): + """ + List enabled features. + + List all features that are enabled on a given Account, Course, or User. + Only the feature names are returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/features/enabled with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/features/enabled".format(**path), data=data, params=params, no_data=True) + + def list_enabled_features_users(self, user_id): + """ + List enabled features. + + List all features that are enabled on a given Account, Course, or User. + Only the feature names are returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/features/enabled with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/features/enabled".format(**path), data=data, params=params, no_data=True) + + def get_feature_flag_courses(self, feature, course_id): + """ + Get feature flag. + + Get the feature flag that applies to a given Account, Course, or User. + The flag may be defined on the object, or it may be inherited from a parent + account. You can look at the context_id and context_type of the returned object + to determine which is the case. If these fields are missing, then the object + is the global Canvas default. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + self.logger.debug("GET /api/v1/courses/{course_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + def get_feature_flag_accounts(self, feature, account_id): + """ + Get feature flag. + + Get the feature flag that applies to a given Account, Course, or User. + The flag may be defined on the object, or it may be inherited from a parent + account. You can look at the context_id and context_type of the returned object + to determine which is the case. If these fields are missing, then the object + is the global Canvas default. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + self.logger.debug("GET /api/v1/accounts/{account_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + def get_feature_flag_users(self, user_id, feature): + """ + Get feature flag. + + Get the feature flag that applies to a given Account, Course, or User. + The flag may be defined on the object, or it may be inherited from a parent + account. You can look at the context_id and context_type of the returned object + to determine which is the case. If these fields are missing, then the object + is the global Canvas default. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + self.logger.debug("GET /api/v1/users/{user_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + def set_feature_flag_courses(self, feature, course_id, state=None): + """ + Set feature flag. + + Set a feature flag for a given Account, Course, or User. This call will fail if a parent account sets + a feature flag for the same feature in any state other than "allowed". + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + # OPTIONAL - state + """"off":: The feature is not available for the course, user, or account and sub-accounts. + "allowed":: (valid only on accounts) The feature is off in the account, but may be enabled in + sub-accounts and courses by setting a feature flag on the sub-account or course. + "on":: The feature is turned on unconditionally for the user, course, or account and sub-accounts.""" + if state is not None: + self._validate_enum(state, ["off", "allowed", "on"]) + data["state"] = state + + self.logger.debug("PUT /api/v1/courses/{course_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + def set_feature_flag_accounts(self, feature, account_id, state=None): + """ + Set feature flag. + + Set a feature flag for a given Account, Course, or User. This call will fail if a parent account sets + a feature flag for the same feature in any state other than "allowed". + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + # OPTIONAL - state + """"off":: The feature is not available for the course, user, or account and sub-accounts. + "allowed":: (valid only on accounts) The feature is off in the account, but may be enabled in + sub-accounts and courses by setting a feature flag on the sub-account or course. + "on":: The feature is turned on unconditionally for the user, course, or account and sub-accounts.""" + if state is not None: + self._validate_enum(state, ["off", "allowed", "on"]) + data["state"] = state + + self.logger.debug("PUT /api/v1/accounts/{account_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + def set_feature_flag_users(self, user_id, feature, state=None): + """ + Set feature flag. + + Set a feature flag for a given Account, Course, or User. This call will fail if a parent account sets + a feature flag for the same feature in any state other than "allowed". + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + # OPTIONAL - state + """"off":: The feature is not available for the course, user, or account and sub-accounts. + "allowed":: (valid only on accounts) The feature is off in the account, but may be enabled in + sub-accounts and courses by setting a feature flag on the sub-account or course. + "on":: The feature is turned on unconditionally for the user, course, or account and sub-accounts.""" + if state is not None: + self._validate_enum(state, ["off", "allowed", "on"]) + data["state"] = state + + self.logger.debug("PUT /api/v1/users/{user_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{user_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + def remove_feature_flag_courses(self, feature, course_id): + """ + Remove feature flag. + + Remove feature flag for a given Account, Course, or User. (Note that the flag must + be defined on the Account, Course, or User directly.) The object will then inherit + the feature flags from a higher account, if any exist. If this flag was 'on' or 'off', + then lower-level account flags that were masked by this one will apply again. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + self.logger.debug("DELETE /api/v1/courses/{course_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + def remove_feature_flag_accounts(self, feature, account_id): + """ + Remove feature flag. + + Remove feature flag for a given Account, Course, or User. (Note that the flag must + be defined on the Account, Course, or User directly.) The object will then inherit + the feature flags from a higher account, if any exist. If this flag was 'on' or 'off', + then lower-level account flags that were masked by this one will apply again. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + def remove_feature_flag_users(self, user_id, feature): + """ + Remove feature flag. + + Remove feature flag for a given Account, Course, or User. (Note that the flag must + be defined on the Account, Course, or User directly.) The object will then inherit + the feature flags from a higher account, if any exist. If this flag was 'on' or 'off', + then lower-level account flags that were masked by this one will apply again. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - feature + """ID""" + path["feature"] = feature + + self.logger.debug("DELETE /api/v1/users/{user_id}/features/flags/{feature} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/{user_id}/features/flags/{feature}".format(**path), data=data, params=params, single_item=True) + + +class Featureflag(BaseModel): + """Featureflag Model.""" + + def __init__(self, context_type=None, context_id=None, state=None, locked=None, feature=None): + """Init method for Featureflag class.""" + self._context_type = context_type + self._context_id = context_id + self._state = state + self._locked = locked + self._feature = feature + + self.logger = logging.getLogger('pycanvas.Featureflag') + + @property + def context_type(self): + """The type of object to which this flag applies (Account, Course, or User). (This field is not present if this FeatureFlag represents the global Canvas default).""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def context_id(self): + """The id of the object to which this flag applies (This field is not present if this FeatureFlag represents the global Canvas default).""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + + @property + def state(self): + """The policy for the feature at this context. can be 'off', 'allowed', or 'on'.""" + return self._state + + @state.setter + def state(self, value): + """Setter for state property.""" + self.logger.warn("Setting values on state will NOT update the remote Canvas instance.") + self._state = value + + @property + def locked(self): + """If set, this feature flag cannot be changed in the caller's context because the flag is set 'off' or 'on' in a higher context.""" + return self._locked + + @locked.setter + def locked(self, value): + """Setter for locked property.""" + self.logger.warn("Setting values on locked will NOT update the remote Canvas instance.") + self._locked = value + + @property + def feature(self): + """The feature this flag controls.""" + return self._feature + + @feature.setter + def feature(self, value): + """Setter for feature property.""" + self.logger.warn("Setting values on feature will NOT update the remote Canvas instance.") + self._feature = value + + +class Feature(BaseModel): + """Feature Model.""" + + def __init__(self, development=None, display_name=None, name=None, autoexpand=None, enable_at=None, beta=None, feature_flag=None, applies_to=None, root_opt_in=None, release_notes_url=None): + """Init method for Feature class.""" + self._development = development + self._display_name = display_name + self._name = name + self._autoexpand = autoexpand + self._enable_at = enable_at + self._beta = beta + self._feature_flag = feature_flag + self._applies_to = applies_to + self._root_opt_in = root_opt_in + self._release_notes_url = release_notes_url + + self.logger = logging.getLogger('pycanvas.Feature') + + @property + def development(self): + """Whether the feature is in active development. Features in this state are only visible in test and beta instances and are not yet available for production use.""" + return self._development + + @development.setter + def development(self, value): + """Setter for development property.""" + self.logger.warn("Setting values on development will NOT update the remote Canvas instance.") + self._development = value + + @property + def display_name(self): + """The user-visible name of the feature.""" + return self._display_name + + @display_name.setter + def display_name(self, value): + """Setter for display_name property.""" + self.logger.warn("Setting values on display_name will NOT update the remote Canvas instance.") + self._display_name = value + + @property + def name(self): + """The symbolic name of the feature, used in FeatureFlags.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def autoexpand(self): + """Whether the details of the feature are autoexpanded on page load vs. the user clicking to expand.""" + return self._autoexpand + + @autoexpand.setter + def autoexpand(self, value): + """Setter for autoexpand property.""" + self.logger.warn("Setting values on autoexpand will NOT update the remote Canvas instance.") + self._autoexpand = value + + @property + def enable_at(self): + """The date this feature will be globally enabled, or null if this is not planned. (This information is subject to change.).""" + return self._enable_at + + @enable_at.setter + def enable_at(self, value): + """Setter for enable_at property.""" + self.logger.warn("Setting values on enable_at will NOT update the remote Canvas instance.") + self._enable_at = value + + @property + def beta(self): + """Whether the feature is a beta feature. If true, the feature may not be fully polished and may be subject to change in the future.""" + return self._beta + + @beta.setter + def beta(self, value): + """Setter for beta property.""" + self.logger.warn("Setting values on beta will NOT update the remote Canvas instance.") + self._beta = value + + @property + def feature_flag(self): + """The FeatureFlag that applies to the caller.""" + return self._feature_flag + + @feature_flag.setter + def feature_flag(self, value): + """Setter for feature_flag property.""" + self.logger.warn("Setting values on feature_flag will NOT update the remote Canvas instance.") + self._feature_flag = value + + @property + def applies_to(self): + """The type of object the feature applies to (RootAccount, Account, Course, or User): + * RootAccount features may only be controlled by flags on root accounts. + * Account features may be controlled by flags on accounts and their parent accounts. + * Course features may be controlled by flags on courses and their parent accounts. + * User features may be controlled by flags on users and site admin only.""" + return self._applies_to + + @applies_to.setter + def applies_to(self, value): + """Setter for applies_to property.""" + self.logger.warn("Setting values on applies_to will NOT update the remote Canvas instance.") + self._applies_to = value + + @property + def root_opt_in(self): + """If true, a feature that is 'allowed' globally will be 'off' by default in root accounts. Otherwise, root accounts inherit the global 'allowed' setting, which allows sub-accounts and courses to turn features on with no root account action.""" + return self._root_opt_in + + @root_opt_in.setter + def root_opt_in(self, value): + """Setter for root_opt_in property.""" + self.logger.warn("Setting values on root_opt_in will NOT update the remote Canvas instance.") + self._root_opt_in = value + + @property + def release_notes_url(self): + """A URL to the release notes describing the feature.""" + return self._release_notes_url + + @release_notes_url.setter + def release_notes_url(self, value): + """Setter for release_notes_url property.""" + self.logger.warn("Setting values on release_notes_url will NOT update the remote Canvas instance.") + self._release_notes_url = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/files.py b/venv/Lib/site-packages/pycanvas/apis/files.py new file mode 100644 index 00000000..67b821f4 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/files.py @@ -0,0 +1,2092 @@ +"""Files API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class FilesAPI(BaseCanvasAPI): + """Files API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for FilesAPI.""" + super(FilesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.FilesAPI") + + def get_quota_information_courses(self, course_id): + """ + Get quota information. + + Returns the total and used storage quota for the course, group, or user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/files/quota with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/files/quota".format(**path), data=data, params=params, no_data=True) + + def get_quota_information_groups(self, group_id): + """ + Get quota information. + + Returns the total and used storage quota for the course, group, or user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/files/quota with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/files/quota".format(**path), data=data, params=params, no_data=True) + + def get_quota_information_users(self, user_id): + """ + Get quota information. + + Returns the total and used storage quota for the course, group, or user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/files/quota with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/files/quota".format(**path), data=data, params=params, no_data=True) + + def list_files_courses(self, course_id, content_types=None, include=None, only=None, order=None, search_term=None, sort=None): + """ + List files. + + Returns the paginated list of files for the folder or course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - content_types + """Filter results by content-type. You can specify type/subtype pairs (e.g., + 'image/jpeg'), or simply types (e.g., 'image', which will match + 'image/gif', 'image/jpeg', etc.).""" + if content_types is not None: + params["content_types"] = content_types + + # OPTIONAL - search_term + """The partial name of the files to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - include + """Array of additional information to include. + + "user":: the user who uploaded the file or last edited its content + "usage_rights":: copyright and license information for the file (see UsageRights)""" + if include is not None: + self._validate_enum(include, ["user"]) + params["include"] = include + + # OPTIONAL - only + """Array of information to restrict to. Overrides include[] + + "names":: only returns file name information""" + if only is not None: + params["only"] = only + + # OPTIONAL - sort + """Sort results by this field. Defaults to 'name'. Note that `sort=user` implies `include[]=user`.""" + if sort is not None: + self._validate_enum(sort, ["name", "size", "created_at", "updated_at", "content_type", "user"]) + params["sort"] = sort + + # OPTIONAL - order + """The sorting order. Defaults to 'asc'.""" + if order is not None: + self._validate_enum(order, ["asc", "desc"]) + params["order"] = order + + self.logger.debug("GET /api/v1/courses/{course_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/files".format(**path), data=data, params=params, all_pages=True) + + def list_files_users(self, user_id, content_types=None, include=None, only=None, order=None, search_term=None, sort=None): + """ + List files. + + Returns the paginated list of files for the folder or course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - content_types + """Filter results by content-type. You can specify type/subtype pairs (e.g., + 'image/jpeg'), or simply types (e.g., 'image', which will match + 'image/gif', 'image/jpeg', etc.).""" + if content_types is not None: + params["content_types"] = content_types + + # OPTIONAL - search_term + """The partial name of the files to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - include + """Array of additional information to include. + + "user":: the user who uploaded the file or last edited its content + "usage_rights":: copyright and license information for the file (see UsageRights)""" + if include is not None: + self._validate_enum(include, ["user"]) + params["include"] = include + + # OPTIONAL - only + """Array of information to restrict to. Overrides include[] + + "names":: only returns file name information""" + if only is not None: + params["only"] = only + + # OPTIONAL - sort + """Sort results by this field. Defaults to 'name'. Note that `sort=user` implies `include[]=user`.""" + if sort is not None: + self._validate_enum(sort, ["name", "size", "created_at", "updated_at", "content_type", "user"]) + params["sort"] = sort + + # OPTIONAL - order + """The sorting order. Defaults to 'asc'.""" + if order is not None: + self._validate_enum(order, ["asc", "desc"]) + params["order"] = order + + self.logger.debug("GET /api/v1/users/{user_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/files".format(**path), data=data, params=params, all_pages=True) + + def list_files_groups(self, group_id, content_types=None, include=None, only=None, order=None, search_term=None, sort=None): + """ + List files. + + Returns the paginated list of files for the folder or course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - content_types + """Filter results by content-type. You can specify type/subtype pairs (e.g., + 'image/jpeg'), or simply types (e.g., 'image', which will match + 'image/gif', 'image/jpeg', etc.).""" + if content_types is not None: + params["content_types"] = content_types + + # OPTIONAL - search_term + """The partial name of the files to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - include + """Array of additional information to include. + + "user":: the user who uploaded the file or last edited its content + "usage_rights":: copyright and license information for the file (see UsageRights)""" + if include is not None: + self._validate_enum(include, ["user"]) + params["include"] = include + + # OPTIONAL - only + """Array of information to restrict to. Overrides include[] + + "names":: only returns file name information""" + if only is not None: + params["only"] = only + + # OPTIONAL - sort + """Sort results by this field. Defaults to 'name'. Note that `sort=user` implies `include[]=user`.""" + if sort is not None: + self._validate_enum(sort, ["name", "size", "created_at", "updated_at", "content_type", "user"]) + params["sort"] = sort + + # OPTIONAL - order + """The sorting order. Defaults to 'asc'.""" + if order is not None: + self._validate_enum(order, ["asc", "desc"]) + params["order"] = order + + self.logger.debug("GET /api/v1/groups/{group_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/files".format(**path), data=data, params=params, all_pages=True) + + def list_files_folders(self, id, content_types=None, include=None, only=None, order=None, search_term=None, sort=None): + """ + List files. + + Returns the paginated list of files for the folder or course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - content_types + """Filter results by content-type. You can specify type/subtype pairs (e.g., + 'image/jpeg'), or simply types (e.g., 'image', which will match + 'image/gif', 'image/jpeg', etc.).""" + if content_types is not None: + params["content_types"] = content_types + + # OPTIONAL - search_term + """The partial name of the files to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - include + """Array of additional information to include. + + "user":: the user who uploaded the file or last edited its content + "usage_rights":: copyright and license information for the file (see UsageRights)""" + if include is not None: + self._validate_enum(include, ["user"]) + params["include"] = include + + # OPTIONAL - only + """Array of information to restrict to. Overrides include[] + + "names":: only returns file name information""" + if only is not None: + params["only"] = only + + # OPTIONAL - sort + """Sort results by this field. Defaults to 'name'. Note that `sort=user` implies `include[]=user`.""" + if sort is not None: + self._validate_enum(sort, ["name", "size", "created_at", "updated_at", "content_type", "user"]) + params["sort"] = sort + + # OPTIONAL - order + """The sorting order. Defaults to 'asc'.""" + if order is not None: + self._validate_enum(order, ["asc", "desc"]) + params["order"] = order + + self.logger.debug("GET /api/v1/folders/{id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/folders/{id}/files".format(**path), data=data, params=params, all_pages=True) + + def get_public_inline_preview_url(self, id, submission_id=None): + """ + Get public inline preview url. + + Determine the URL that should be used for inline preview of the file. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - submission_id + """The id of the submission the file is associated with. Provide this argument to gain access to a file + that has been submitted to an assignment (Canvas will verify that the file belongs to the submission + and the calling user has rights to view the submission).""" + if submission_id is not None: + params["submission_id"] = submission_id + + self.logger.debug("GET /api/v1/files/{id}/public_url with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/files/{id}/public_url".format(**path), data=data, params=params, no_data=True) + + def get_file_files(self, id, include=None): + """ + Get file. + + Returns the standard attachment json object + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """Array of additional information to include. + + "user":: the user who uploaded the file or last edited its content + "usage_rights":: copyright and license information for the file (see UsageRights)""" + if include is not None: + self._validate_enum(include, ["user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/files/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/files/{id}".format(**path), data=data, params=params, single_item=True) + + def get_file_courses(self, id, course_id, include=None): + """ + Get file. + + Returns the standard attachment json object + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """Array of additional information to include. + + "user":: the user who uploaded the file or last edited its content + "usage_rights":: copyright and license information for the file (see UsageRights)""" + if include is not None: + self._validate_enum(include, ["user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/files/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/files/{id}".format(**path), data=data, params=params, single_item=True) + + def get_file_groups(self, id, group_id, include=None): + """ + Get file. + + Returns the standard attachment json object + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """Array of additional information to include. + + "user":: the user who uploaded the file or last edited its content + "usage_rights":: copyright and license information for the file (see UsageRights)""" + if include is not None: + self._validate_enum(include, ["user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/groups/{group_id}/files/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/files/{id}".format(**path), data=data, params=params, single_item=True) + + def get_file_users(self, id, user_id, include=None): + """ + Get file. + + Returns the standard attachment json object + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """Array of additional information to include. + + "user":: the user who uploaded the file or last edited its content + "usage_rights":: copyright and license information for the file (see UsageRights)""" + if include is not None: + self._validate_enum(include, ["user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/users/{user_id}/files/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/files/{id}".format(**path), data=data, params=params, single_item=True) + + def update_file(self, id, hidden=None, lock_at=None, locked=None, name=None, on_duplicate=None, parent_folder_id=None, unlock_at=None): + """ + Update file. + + Update some settings on the specified file + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - name + """The new display name of the file""" + if name is not None: + data["name"] = name + + # OPTIONAL - parent_folder_id + """The id of the folder to move this file into. + The new folder must be in the same context as the original parent folder. + If the file is in a context without folders this does not apply.""" + if parent_folder_id is not None: + data["parent_folder_id"] = parent_folder_id + + # OPTIONAL - on_duplicate + """If the file is moved to a folder containing a file with the same name, + or renamed to a name matching an existing file, the API call will fail + unless this parameter is supplied. + + "overwrite":: Replace the existing file with the same name + "rename":: Add a qualifier to make the new filename unique""" + if on_duplicate is not None: + self._validate_enum(on_duplicate, ["overwrite", "rename"]) + data["on_duplicate"] = on_duplicate + + # OPTIONAL - lock_at + """The datetime to lock the file at""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - unlock_at + """The datetime to unlock the file at""" + if unlock_at is not None: + data["unlock_at"] = unlock_at + + # OPTIONAL - locked + """Flag the file as locked""" + if locked is not None: + data["locked"] = locked + + # OPTIONAL - hidden + """Flag the file as hidden""" + if hidden is not None: + data["hidden"] = hidden + + self.logger.debug("PUT /api/v1/files/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/files/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_file(self, id): + """ + Delete file. + + Remove the specified file + + curl -XDELETE 'https:///api/v1/files/' \ + -H 'Authorization: Bearer ' + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/files/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/files/{id}".format(**path), data=data, params=params, no_data=True) + + def list_folders(self, id): + """ + List folders. + + Returns the paginated list of folders in the folder. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/folders/{id}/folders with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/folders/{id}/folders".format(**path), data=data, params=params, all_pages=True) + + def list_all_folders_courses(self, course_id): + """ + List all folders. + + Returns the paginated list of all folders for the given context. This will + be returned as a flat list containing all subfolders as well. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/folders with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/folders".format(**path), data=data, params=params, all_pages=True) + + def list_all_folders_users(self, user_id): + """ + List all folders. + + Returns the paginated list of all folders for the given context. This will + be returned as a flat list containing all subfolders as well. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/folders with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/folders".format(**path), data=data, params=params, all_pages=True) + + def list_all_folders_groups(self, group_id): + """ + List all folders. + + Returns the paginated list of all folders for the given context. This will + be returned as a flat list containing all subfolders as well. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/folders with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/folders".format(**path), data=data, params=params, all_pages=True) + + def resolve_path_courses_full_path(self, course_id): + """ + Resolve path. + + Given the full path to a folder, returns a list of all Folders in the path hierarchy, + starting at the root folder, and ending at the requested folder. The given path is + relative to the context's root folder and does not include the root folder's name + (e.g., "course files"). If an empty path is given, the context's root folder alone + is returned. Otherwise, if no folder exists with the given full path, a Not Found + error is returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/folders/by_path/*full_path with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/folders/by_path/*full_path".format(**path), data=data, params=params, all_pages=True) + + def resolve_path_courses(self, course_id): + """ + Resolve path. + + Given the full path to a folder, returns a list of all Folders in the path hierarchy, + starting at the root folder, and ending at the requested folder. The given path is + relative to the context's root folder and does not include the root folder's name + (e.g., "course files"). If an empty path is given, the context's root folder alone + is returned. Otherwise, if no folder exists with the given full path, a Not Found + error is returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/folders/by_path with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/folders/by_path".format(**path), data=data, params=params, all_pages=True) + + def resolve_path_users_full_path(self, user_id): + """ + Resolve path. + + Given the full path to a folder, returns a list of all Folders in the path hierarchy, + starting at the root folder, and ending at the requested folder. The given path is + relative to the context's root folder and does not include the root folder's name + (e.g., "course files"). If an empty path is given, the context's root folder alone + is returned. Otherwise, if no folder exists with the given full path, a Not Found + error is returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/folders/by_path/*full_path with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/folders/by_path/*full_path".format(**path), data=data, params=params, all_pages=True) + + def resolve_path_users(self, user_id): + """ + Resolve path. + + Given the full path to a folder, returns a list of all Folders in the path hierarchy, + starting at the root folder, and ending at the requested folder. The given path is + relative to the context's root folder and does not include the root folder's name + (e.g., "course files"). If an empty path is given, the context's root folder alone + is returned. Otherwise, if no folder exists with the given full path, a Not Found + error is returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/folders/by_path with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/folders/by_path".format(**path), data=data, params=params, all_pages=True) + + def resolve_path_groups_full_path(self, group_id): + """ + Resolve path. + + Given the full path to a folder, returns a list of all Folders in the path hierarchy, + starting at the root folder, and ending at the requested folder. The given path is + relative to the context's root folder and does not include the root folder's name + (e.g., "course files"). If an empty path is given, the context's root folder alone + is returned. Otherwise, if no folder exists with the given full path, a Not Found + error is returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/folders/by_path/*full_path with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/folders/by_path/*full_path".format(**path), data=data, params=params, all_pages=True) + + def resolve_path_groups(self, group_id): + """ + Resolve path. + + Given the full path to a folder, returns a list of all Folders in the path hierarchy, + starting at the root folder, and ending at the requested folder. The given path is + relative to the context's root folder and does not include the root folder's name + (e.g., "course files"). If an empty path is given, the context's root folder alone + is returned. Otherwise, if no folder exists with the given full path, a Not Found + error is returned. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/folders/by_path with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/folders/by_path".format(**path), data=data, params=params, all_pages=True) + + def get_folder_courses(self, id, course_id): + """ + Get folder. + + Returns the details for a folder + + You can get the root folder from a context by using 'root' as the :id. + For example, you could get the root folder for a course like: + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/folders/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/folders/{id}".format(**path), data=data, params=params, single_item=True) + + def get_folder_users(self, id, user_id): + """ + Get folder. + + Returns the details for a folder + + You can get the root folder from a context by using 'root' as the :id. + For example, you could get the root folder for a course like: + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/users/{user_id}/folders/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/folders/{id}".format(**path), data=data, params=params, single_item=True) + + def get_folder_groups(self, id, group_id): + """ + Get folder. + + Returns the details for a folder + + You can get the root folder from a context by using 'root' as the :id. + For example, you could get the root folder for a course like: + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/groups/{group_id}/folders/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/folders/{id}".format(**path), data=data, params=params, single_item=True) + + def get_folder_folders(self, id): + """ + Get folder. + + Returns the details for a folder + + You can get the root folder from a context by using 'root' as the :id. + For example, you could get the root folder for a course like: + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/folders/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/folders/{id}".format(**path), data=data, params=params, single_item=True) + + def update_folder(self, id, hidden=None, lock_at=None, locked=None, name=None, parent_folder_id=None, position=None, unlock_at=None): + """ + Update folder. + + Updates a folder + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - name + """The new name of the folder""" + if name is not None: + data["name"] = name + + # OPTIONAL - parent_folder_id + """The id of the folder to move this folder into. The new folder must be in the same context as the original parent folder.""" + if parent_folder_id is not None: + data["parent_folder_id"] = parent_folder_id + + # OPTIONAL - lock_at + """The datetime to lock the folder at""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - unlock_at + """The datetime to unlock the folder at""" + if unlock_at is not None: + data["unlock_at"] = unlock_at + + # OPTIONAL - locked + """Flag the folder as locked""" + if locked is not None: + data["locked"] = locked + + # OPTIONAL - hidden + """Flag the folder as hidden""" + if hidden is not None: + data["hidden"] = hidden + + # OPTIONAL - position + """Set an explicit sort position for the folder""" + if position is not None: + data["position"] = position + + self.logger.debug("PUT /api/v1/folders/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/folders/{id}".format(**path), data=data, params=params, single_item=True) + + def create_folder_courses(self, name, course_id, hidden=None, lock_at=None, locked=None, parent_folder_id=None, parent_folder_path=None, position=None, unlock_at=None): + """ + Create folder. + + Creates a folder in the specified context + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - name + """The name of the folder""" + data["name"] = name + + # OPTIONAL - parent_folder_id + """The id of the folder to store the file in. If this and parent_folder_path are sent an error will be returned. If neither is given, a default folder will be used.""" + if parent_folder_id is not None: + data["parent_folder_id"] = parent_folder_id + + # OPTIONAL - parent_folder_path + """The path of the folder to store the new folder in. The path separator is the forward slash `/`, never a back slash. The parent folder will be created if it does not already exist. This parameter only applies to new folders in a context that has folders, such as a user, a course, or a group. If this and parent_folder_id are sent an error will be returned. If neither is given, a default folder will be used.""" + if parent_folder_path is not None: + data["parent_folder_path"] = parent_folder_path + + # OPTIONAL - lock_at + """The datetime to lock the folder at""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - unlock_at + """The datetime to unlock the folder at""" + if unlock_at is not None: + data["unlock_at"] = unlock_at + + # OPTIONAL - locked + """Flag the folder as locked""" + if locked is not None: + data["locked"] = locked + + # OPTIONAL - hidden + """Flag the folder as hidden""" + if hidden is not None: + data["hidden"] = hidden + + # OPTIONAL - position + """Set an explicit sort position for the folder""" + if position is not None: + data["position"] = position + + self.logger.debug("POST /api/v1/courses/{course_id}/folders with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/folders".format(**path), data=data, params=params, single_item=True) + + def create_folder_users(self, name, user_id, hidden=None, lock_at=None, locked=None, parent_folder_id=None, parent_folder_path=None, position=None, unlock_at=None): + """ + Create folder. + + Creates a folder in the specified context + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - name + """The name of the folder""" + data["name"] = name + + # OPTIONAL - parent_folder_id + """The id of the folder to store the file in. If this and parent_folder_path are sent an error will be returned. If neither is given, a default folder will be used.""" + if parent_folder_id is not None: + data["parent_folder_id"] = parent_folder_id + + # OPTIONAL - parent_folder_path + """The path of the folder to store the new folder in. The path separator is the forward slash `/`, never a back slash. The parent folder will be created if it does not already exist. This parameter only applies to new folders in a context that has folders, such as a user, a course, or a group. If this and parent_folder_id are sent an error will be returned. If neither is given, a default folder will be used.""" + if parent_folder_path is not None: + data["parent_folder_path"] = parent_folder_path + + # OPTIONAL - lock_at + """The datetime to lock the folder at""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - unlock_at + """The datetime to unlock the folder at""" + if unlock_at is not None: + data["unlock_at"] = unlock_at + + # OPTIONAL - locked + """Flag the folder as locked""" + if locked is not None: + data["locked"] = locked + + # OPTIONAL - hidden + """Flag the folder as hidden""" + if hidden is not None: + data["hidden"] = hidden + + # OPTIONAL - position + """Set an explicit sort position for the folder""" + if position is not None: + data["position"] = position + + self.logger.debug("POST /api/v1/users/{user_id}/folders with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/{user_id}/folders".format(**path), data=data, params=params, single_item=True) + + def create_folder_groups(self, name, group_id, hidden=None, lock_at=None, locked=None, parent_folder_id=None, parent_folder_path=None, position=None, unlock_at=None): + """ + Create folder. + + Creates a folder in the specified context + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - name + """The name of the folder""" + data["name"] = name + + # OPTIONAL - parent_folder_id + """The id of the folder to store the file in. If this and parent_folder_path are sent an error will be returned. If neither is given, a default folder will be used.""" + if parent_folder_id is not None: + data["parent_folder_id"] = parent_folder_id + + # OPTIONAL - parent_folder_path + """The path of the folder to store the new folder in. The path separator is the forward slash `/`, never a back slash. The parent folder will be created if it does not already exist. This parameter only applies to new folders in a context that has folders, such as a user, a course, or a group. If this and parent_folder_id are sent an error will be returned. If neither is given, a default folder will be used.""" + if parent_folder_path is not None: + data["parent_folder_path"] = parent_folder_path + + # OPTIONAL - lock_at + """The datetime to lock the folder at""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - unlock_at + """The datetime to unlock the folder at""" + if unlock_at is not None: + data["unlock_at"] = unlock_at + + # OPTIONAL - locked + """Flag the folder as locked""" + if locked is not None: + data["locked"] = locked + + # OPTIONAL - hidden + """Flag the folder as hidden""" + if hidden is not None: + data["hidden"] = hidden + + # OPTIONAL - position + """Set an explicit sort position for the folder""" + if position is not None: + data["position"] = position + + self.logger.debug("POST /api/v1/groups/{group_id}/folders with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/folders".format(**path), data=data, params=params, single_item=True) + + def create_folder_folders(self, name, folder_id, hidden=None, lock_at=None, locked=None, parent_folder_id=None, parent_folder_path=None, position=None, unlock_at=None): + """ + Create folder. + + Creates a folder in the specified context + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - folder_id + """ID""" + path["folder_id"] = folder_id + + # REQUIRED - name + """The name of the folder""" + data["name"] = name + + # OPTIONAL - parent_folder_id + """The id of the folder to store the file in. If this and parent_folder_path are sent an error will be returned. If neither is given, a default folder will be used.""" + if parent_folder_id is not None: + data["parent_folder_id"] = parent_folder_id + + # OPTIONAL - parent_folder_path + """The path of the folder to store the new folder in. The path separator is the forward slash `/`, never a back slash. The parent folder will be created if it does not already exist. This parameter only applies to new folders in a context that has folders, such as a user, a course, or a group. If this and parent_folder_id are sent an error will be returned. If neither is given, a default folder will be used.""" + if parent_folder_path is not None: + data["parent_folder_path"] = parent_folder_path + + # OPTIONAL - lock_at + """The datetime to lock the folder at""" + if lock_at is not None: + data["lock_at"] = lock_at + + # OPTIONAL - unlock_at + """The datetime to unlock the folder at""" + if unlock_at is not None: + data["unlock_at"] = unlock_at + + # OPTIONAL - locked + """Flag the folder as locked""" + if locked is not None: + data["locked"] = locked + + # OPTIONAL - hidden + """Flag the folder as hidden""" + if hidden is not None: + data["hidden"] = hidden + + # OPTIONAL - position + """Set an explicit sort position for the folder""" + if position is not None: + data["position"] = position + + self.logger.debug("POST /api/v1/folders/{folder_id}/folders with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/folders/{folder_id}/folders".format(**path), data=data, params=params, single_item=True) + + def delete_folder(self, id, force=None): + """ + Delete folder. + + Remove the specified folder. You can only delete empty folders unless you + set the 'force' flag + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - force + """Set to 'true' to allow deleting a non-empty folder""" + if force is not None: + params["force"] = force + + self.logger.debug("DELETE /api/v1/folders/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/folders/{id}".format(**path), data=data, params=params, no_data=True) + + def upload_file(self, folder_id): + """ + Upload a file. + + Upload a file to a folder. + + This API endpoint is the first step in uploading a file. + See the {file:file_uploads.html File Upload Documentation} for details on + the file upload workflow. + + Only those with the "Manage Files" permission on a course or group can + upload files to a folder in that course or group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - folder_id + """ID""" + path["folder_id"] = folder_id + + self.logger.debug("POST /api/v1/folders/{folder_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/folders/{folder_id}/files".format(**path), data=data, params=params, no_data=True) + + def copy_file(self, dest_folder_id, source_file_id, on_duplicate=None): + """ + Copy a file. + + Copy a file from elsewhere in Canvas into a folder. + + Copying a file across contexts (between courses and users) is permitted, + but the source and destination must belong to the same institution. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - dest_folder_id + """ID""" + path["dest_folder_id"] = dest_folder_id + + # REQUIRED - source_file_id + """The id of the source file""" + data["source_file_id"] = source_file_id + + # OPTIONAL - on_duplicate + """What to do if a file with the same name already exists at the destination. + If such a file exists and this parameter is not given, the call will fail. + + "overwrite":: Replace an existing file with the same name + "rename":: Add a qualifier to make the new filename unique""" + if on_duplicate is not None: + self._validate_enum(on_duplicate, ["overwrite", "rename"]) + data["on_duplicate"] = on_duplicate + + self.logger.debug("POST /api/v1/folders/{dest_folder_id}/copy_file with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/folders/{dest_folder_id}/copy_file".format(**path), data=data, params=params, single_item=True) + + def copy_folder(self, dest_folder_id, source_folder_id): + """ + Copy a folder. + + Copy a folder (and its contents) from elsewhere in Canvas into a folder. + + Copying a folder across contexts (between courses and users) is permitted, + but the source and destination must belong to the same institution. + If the source and destination folders are in the same context, the + source folder may not contain the destination folder. A folder will be + renamed at its destination if another folder with the same name already + exists. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - dest_folder_id + """ID""" + path["dest_folder_id"] = dest_folder_id + + # REQUIRED - source_folder_id + """The id of the source folder""" + data["source_folder_id"] = source_folder_id + + self.logger.debug("POST /api/v1/folders/{dest_folder_id}/copy_folder with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/folders/{dest_folder_id}/copy_folder".format(**path), data=data, params=params, single_item=True) + + def set_usage_rights_courses(self, file_ids, course_id, usage_rights_use_justification, folder_ids=None, publish=None, usage_rights_legal_copyright=None, usage_rights_license=None): + """ + Set usage rights. + + Sets copyright and license information for one or more files + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - file_ids + """List of ids of files to set usage rights for.""" + data["file_ids"] = file_ids + + # OPTIONAL - folder_ids + """List of ids of folders to search for files to set usage rights for. + Note that new files uploaded to these folders do not automatically inherit these rights.""" + if folder_ids is not None: + data["folder_ids"] = folder_ids + + # OPTIONAL - publish + """Whether the file(s) or folder(s) should be published on save, provided that usage rights have been specified (set to `true` to publish on save).""" + if publish is not None: + data["publish"] = publish + + # REQUIRED - usage_rights[use_justification] + """The intellectual property justification for using the files in Canvas""" + self._validate_enum(usage_rights_use_justification, ["own_copyright", "used_by_permission", "fair_use", "public_domain", "creative_commons"]) + data["usage_rights[use_justification]"] = usage_rights_use_justification + + # OPTIONAL - usage_rights[legal_copyright] + """The legal copyright line for the files""" + if usage_rights_legal_copyright is not None: + data["usage_rights[legal_copyright]"] = usage_rights_legal_copyright + + # OPTIONAL - usage_rights[license] + """The license that applies to the files. See the {api:UsageRightsController#licenses List licenses endpoint} for the supported license types.""" + if usage_rights_license is not None: + data["usage_rights[license]"] = usage_rights_license + + self.logger.debug("PUT /api/v1/courses/{course_id}/usage_rights with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/usage_rights".format(**path), data=data, params=params, single_item=True) + + def set_usage_rights_groups(self, group_id, file_ids, usage_rights_use_justification, folder_ids=None, publish=None, usage_rights_legal_copyright=None, usage_rights_license=None): + """ + Set usage rights. + + Sets copyright and license information for one or more files + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - file_ids + """List of ids of files to set usage rights for.""" + data["file_ids"] = file_ids + + # OPTIONAL - folder_ids + """List of ids of folders to search for files to set usage rights for. + Note that new files uploaded to these folders do not automatically inherit these rights.""" + if folder_ids is not None: + data["folder_ids"] = folder_ids + + # OPTIONAL - publish + """Whether the file(s) or folder(s) should be published on save, provided that usage rights have been specified (set to `true` to publish on save).""" + if publish is not None: + data["publish"] = publish + + # REQUIRED - usage_rights[use_justification] + """The intellectual property justification for using the files in Canvas""" + self._validate_enum(usage_rights_use_justification, ["own_copyright", "used_by_permission", "fair_use", "public_domain", "creative_commons"]) + data["usage_rights[use_justification]"] = usage_rights_use_justification + + # OPTIONAL - usage_rights[legal_copyright] + """The legal copyright line for the files""" + if usage_rights_legal_copyright is not None: + data["usage_rights[legal_copyright]"] = usage_rights_legal_copyright + + # OPTIONAL - usage_rights[license] + """The license that applies to the files. See the {api:UsageRightsController#licenses List licenses endpoint} for the supported license types.""" + if usage_rights_license is not None: + data["usage_rights[license]"] = usage_rights_license + + self.logger.debug("PUT /api/v1/groups/{group_id}/usage_rights with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/usage_rights".format(**path), data=data, params=params, single_item=True) + + def set_usage_rights_users(self, user_id, file_ids, usage_rights_use_justification, folder_ids=None, publish=None, usage_rights_legal_copyright=None, usage_rights_license=None): + """ + Set usage rights. + + Sets copyright and license information for one or more files + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - file_ids + """List of ids of files to set usage rights for.""" + data["file_ids"] = file_ids + + # OPTIONAL - folder_ids + """List of ids of folders to search for files to set usage rights for. + Note that new files uploaded to these folders do not automatically inherit these rights.""" + if folder_ids is not None: + data["folder_ids"] = folder_ids + + # OPTIONAL - publish + """Whether the file(s) or folder(s) should be published on save, provided that usage rights have been specified (set to `true` to publish on save).""" + if publish is not None: + data["publish"] = publish + + # REQUIRED - usage_rights[use_justification] + """The intellectual property justification for using the files in Canvas""" + self._validate_enum(usage_rights_use_justification, ["own_copyright", "used_by_permission", "fair_use", "public_domain", "creative_commons"]) + data["usage_rights[use_justification]"] = usage_rights_use_justification + + # OPTIONAL - usage_rights[legal_copyright] + """The legal copyright line for the files""" + if usage_rights_legal_copyright is not None: + data["usage_rights[legal_copyright]"] = usage_rights_legal_copyright + + # OPTIONAL - usage_rights[license] + """The license that applies to the files. See the {api:UsageRightsController#licenses List licenses endpoint} for the supported license types.""" + if usage_rights_license is not None: + data["usage_rights[license]"] = usage_rights_license + + self.logger.debug("PUT /api/v1/users/{user_id}/usage_rights with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{user_id}/usage_rights".format(**path), data=data, params=params, single_item=True) + + def remove_usage_rights_courses(self, file_ids, course_id, folder_ids=None): + """ + Remove usage rights. + + Removes copyright and license information associated with one or more files + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - file_ids + """List of ids of files to remove associated usage rights from.""" + params["file_ids"] = file_ids + + # OPTIONAL - folder_ids + """List of ids of folders. Usage rights will be removed from all files in these folders.""" + if folder_ids is not None: + params["folder_ids"] = folder_ids + + self.logger.debug("DELETE /api/v1/courses/{course_id}/usage_rights with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/usage_rights".format(**path), data=data, params=params, no_data=True) + + def remove_usage_rights_groups(self, group_id, file_ids, folder_ids=None): + """ + Remove usage rights. + + Removes copyright and license information associated with one or more files + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - file_ids + """List of ids of files to remove associated usage rights from.""" + params["file_ids"] = file_ids + + # OPTIONAL - folder_ids + """List of ids of folders. Usage rights will be removed from all files in these folders.""" + if folder_ids is not None: + params["folder_ids"] = folder_ids + + self.logger.debug("DELETE /api/v1/groups/{group_id}/usage_rights with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/usage_rights".format(**path), data=data, params=params, no_data=True) + + def remove_usage_rights_users(self, user_id, file_ids, folder_ids=None): + """ + Remove usage rights. + + Removes copyright and license information associated with one or more files + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - file_ids + """List of ids of files to remove associated usage rights from.""" + params["file_ids"] = file_ids + + # OPTIONAL - folder_ids + """List of ids of folders. Usage rights will be removed from all files in these folders.""" + if folder_ids is not None: + params["folder_ids"] = folder_ids + + self.logger.debug("DELETE /api/v1/users/{user_id}/usage_rights with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/{user_id}/usage_rights".format(**path), data=data, params=params, no_data=True) + + def list_licenses_courses(self, course_id): + """ + List licenses. + + Lists licenses that can be applied + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/content_licenses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/content_licenses".format(**path), data=data, params=params, all_pages=True) + + def list_licenses_groups(self, group_id): + """ + List licenses. + + Lists licenses that can be applied + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/content_licenses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/content_licenses".format(**path), data=data, params=params, all_pages=True) + + def list_licenses_users(self, user_id): + """ + List licenses. + + Lists licenses that can be applied + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/content_licenses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/content_licenses".format(**path), data=data, params=params, all_pages=True) + + +class Folder(BaseModel): + """Folder Model.""" + + def __init__(self, folders_count=None, locked=None, name=None, parent_folder_id=None, context_type=None, context_id=None, created_at=None, updated_at=None, lock_at=None, files_url=None, hidden_for_user=None, files_count=None, full_name=None, for_submissions=None, position=None, hidden=None, locked_for_user=None, id=None, folders_url=None, unlock_at=None): + """Init method for Folder class.""" + self._folders_count = folders_count + self._locked = locked + self._name = name + self._parent_folder_id = parent_folder_id + self._context_type = context_type + self._context_id = context_id + self._created_at = created_at + self._updated_at = updated_at + self._lock_at = lock_at + self._files_url = files_url + self._hidden_for_user = hidden_for_user + self._files_count = files_count + self._full_name = full_name + self._for_submissions = for_submissions + self._position = position + self._hidden = hidden + self._locked_for_user = locked_for_user + self._id = id + self._folders_url = folders_url + self._unlock_at = unlock_at + + self.logger = logging.getLogger('pycanvas.Folder') + + @property + def folders_count(self): + """folders_count.""" + return self._folders_count + + @folders_count.setter + def folders_count(self, value): + """Setter for folders_count property.""" + self.logger.warn("Setting values on folders_count will NOT update the remote Canvas instance.") + self._folders_count = value + + @property + def locked(self): + """locked.""" + return self._locked + + @locked.setter + def locked(self, value): + """Setter for locked property.""" + self.logger.warn("Setting values on locked will NOT update the remote Canvas instance.") + self._locked = value + + @property + def name(self): + """name.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def parent_folder_id(self): + """parent_folder_id.""" + return self._parent_folder_id + + @parent_folder_id.setter + def parent_folder_id(self, value): + """Setter for parent_folder_id property.""" + self.logger.warn("Setting values on parent_folder_id will NOT update the remote Canvas instance.") + self._parent_folder_id = value + + @property + def context_type(self): + """context_type.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def context_id(self): + """context_id.""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + + @property + def created_at(self): + """created_at.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def updated_at(self): + """updated_at.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def lock_at(self): + """lock_at.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def files_url(self): + """files_url.""" + return self._files_url + + @files_url.setter + def files_url(self, value): + """Setter for files_url property.""" + self.logger.warn("Setting values on files_url will NOT update the remote Canvas instance.") + self._files_url = value + + @property + def hidden_for_user(self): + """hidden_for_user.""" + return self._hidden_for_user + + @hidden_for_user.setter + def hidden_for_user(self, value): + """Setter for hidden_for_user property.""" + self.logger.warn("Setting values on hidden_for_user will NOT update the remote Canvas instance.") + self._hidden_for_user = value + + @property + def files_count(self): + """files_count.""" + return self._files_count + + @files_count.setter + def files_count(self, value): + """Setter for files_count property.""" + self.logger.warn("Setting values on files_count will NOT update the remote Canvas instance.") + self._files_count = value + + @property + def full_name(self): + """full_name.""" + return self._full_name + + @full_name.setter + def full_name(self, value): + """Setter for full_name property.""" + self.logger.warn("Setting values on full_name will NOT update the remote Canvas instance.") + self._full_name = value + + @property + def for_submissions(self): + """If true, indicates this is a read-only folder containing files submitted to assignments.""" + return self._for_submissions + + @for_submissions.setter + def for_submissions(self, value): + """Setter for for_submissions property.""" + self.logger.warn("Setting values on for_submissions will NOT update the remote Canvas instance.") + self._for_submissions = value + + @property + def position(self): + """position.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def hidden(self): + """hidden.""" + return self._hidden + + @hidden.setter + def hidden(self, value): + """Setter for hidden property.""" + self.logger.warn("Setting values on hidden will NOT update the remote Canvas instance.") + self._hidden = value + + @property + def locked_for_user(self): + """locked_for_user.""" + return self._locked_for_user + + @locked_for_user.setter + def locked_for_user(self, value): + """Setter for locked_for_user property.""" + self.logger.warn("Setting values on locked_for_user will NOT update the remote Canvas instance.") + self._locked_for_user = value + + @property + def id(self): + """id.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def folders_url(self): + """folders_url.""" + return self._folders_url + + @folders_url.setter + def folders_url(self, value): + """Setter for folders_url property.""" + self.logger.warn("Setting values on folders_url will NOT update the remote Canvas instance.") + self._folders_url = value + + @property + def unlock_at(self): + """unlock_at.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + +class Usagerights(BaseModel): + """Usagerights Model. + Describes the copyright and license information for a File""" + + def __init__(self, license=None, license_name=None, file_ids=None, legal_copyright=None, use_justification=None, message=None): + """Init method for Usagerights class.""" + self._license = license + self._license_name = license_name + self._file_ids = file_ids + self._legal_copyright = legal_copyright + self._use_justification = use_justification + self._message = message + + self.logger = logging.getLogger('pycanvas.Usagerights') + + @property + def license(self): + """License identifier for the file.""" + return self._license + + @license.setter + def license(self, value): + """Setter for license property.""" + self.logger.warn("Setting values on license will NOT update the remote Canvas instance.") + self._license = value + + @property + def license_name(self): + """Readable license name.""" + return self._license_name + + @license_name.setter + def license_name(self, value): + """Setter for license_name property.""" + self.logger.warn("Setting values on license_name will NOT update the remote Canvas instance.") + self._license_name = value + + @property + def file_ids(self): + """List of ids of files that were updated.""" + return self._file_ids + + @file_ids.setter + def file_ids(self, value): + """Setter for file_ids property.""" + self.logger.warn("Setting values on file_ids will NOT update the remote Canvas instance.") + self._file_ids = value + + @property + def legal_copyright(self): + """Copyright line for the file.""" + return self._legal_copyright + + @legal_copyright.setter + def legal_copyright(self, value): + """Setter for legal_copyright property.""" + self.logger.warn("Setting values on legal_copyright will NOT update the remote Canvas instance.") + self._legal_copyright = value + + @property + def use_justification(self): + """Justification for using the file in a Canvas course. Valid values are 'own_copyright', 'public_domain', 'used_by_permission', 'fair_use', 'creative_commons'.""" + return self._use_justification + + @use_justification.setter + def use_justification(self, value): + """Setter for use_justification property.""" + self.logger.warn("Setting values on use_justification will NOT update the remote Canvas instance.") + self._use_justification = value + + @property + def message(self): + """Explanation of the action performed.""" + return self._message + + @message.setter + def message(self, value): + """Setter for message property.""" + self.logger.warn("Setting values on message will NOT update the remote Canvas instance.") + self._message = value + + +class License(BaseModel): + """License Model.""" + + def __init__(self, url=None, id=None, name=None): + """Init method for License class.""" + self._url = url + self._id = id + self._name = name + + self.logger = logging.getLogger('pycanvas.License') + + @property + def url(self): + """a link to the license text.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def id(self): + """a short string identifying the license.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def name(self): + """the name of the license.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class File(BaseModel): + """File Model.""" + + def __init__(self, media_entry_id=None, display_name=None, unlock_at=None, mime_class=None, url=None, created_at=None, modified_at=None, updated_at=None, preview_url=None, lock_info=None, lock_at=None, thumbnail_url=None, hidden_for_user=None, lock_explanation=None, locked=None, hidden=None, locked_for_user=None, content_type=None, id=None, size=None): + """Init method for File class.""" + self._media_entry_id = media_entry_id + self._display_name = display_name + self._unlock_at = unlock_at + self._mime_class = mime_class + self._url = url + self._created_at = created_at + self._modified_at = modified_at + self._updated_at = updated_at + self._preview_url = preview_url + self._lock_info = lock_info + self._lock_at = lock_at + self._thumbnail_url = thumbnail_url + self._hidden_for_user = hidden_for_user + self._lock_explanation = lock_explanation + self._locked = locked + self._hidden = hidden + self._locked_for_user = locked_for_user + self._content_type = content_type + self._id = id + self._size = size + + self.logger = logging.getLogger('pycanvas.File') + + @property + def media_entry_id(self): + """identifier for file in third-party transcoding service.""" + return self._media_entry_id + + @media_entry_id.setter + def media_entry_id(self, value): + """Setter for media_entry_id property.""" + self.logger.warn("Setting values on media_entry_id will NOT update the remote Canvas instance.") + self._media_entry_id = value + + @property + def display_name(self): + """display_name.""" + return self._display_name + + @display_name.setter + def display_name(self, value): + """Setter for display_name property.""" + self.logger.warn("Setting values on display_name will NOT update the remote Canvas instance.") + self._display_name = value + + @property + def unlock_at(self): + """unlock_at.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def mime_class(self): + """simplified content-type mapping.""" + return self._mime_class + + @mime_class.setter + def mime_class(self, value): + """Setter for mime_class property.""" + self.logger.warn("Setting values on mime_class will NOT update the remote Canvas instance.") + self._mime_class = value + + @property + def url(self): + """url.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def created_at(self): + """created_at.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def modified_at(self): + """modified_at.""" + return self._modified_at + + @modified_at.setter + def modified_at(self, value): + """Setter for modified_at property.""" + self.logger.warn("Setting values on modified_at will NOT update the remote Canvas instance.") + self._modified_at = value + + @property + def updated_at(self): + """updated_at.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def preview_url(self): + """optional: url to the document preview (only included in submission endpoints).""" + return self._preview_url + + @preview_url.setter + def preview_url(self, value): + """Setter for preview_url property.""" + self.logger.warn("Setting values on preview_url will NOT update the remote Canvas instance.") + self._preview_url = value + + @property + def lock_info(self): + """lock_info.""" + return self._lock_info + + @lock_info.setter + def lock_info(self, value): + """Setter for lock_info property.""" + self.logger.warn("Setting values on lock_info will NOT update the remote Canvas instance.") + self._lock_info = value + + @property + def lock_at(self): + """lock_at.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def thumbnail_url(self): + """thumbnail_url.""" + return self._thumbnail_url + + @thumbnail_url.setter + def thumbnail_url(self, value): + """Setter for thumbnail_url property.""" + self.logger.warn("Setting values on thumbnail_url will NOT update the remote Canvas instance.") + self._thumbnail_url = value + + @property + def hidden_for_user(self): + """hidden_for_user.""" + return self._hidden_for_user + + @hidden_for_user.setter + def hidden_for_user(self, value): + """Setter for hidden_for_user property.""" + self.logger.warn("Setting values on hidden_for_user will NOT update the remote Canvas instance.") + self._hidden_for_user = value + + @property + def lock_explanation(self): + """lock_explanation.""" + return self._lock_explanation + + @lock_explanation.setter + def lock_explanation(self, value): + """Setter for lock_explanation property.""" + self.logger.warn("Setting values on lock_explanation will NOT update the remote Canvas instance.") + self._lock_explanation = value + + @property + def locked(self): + """locked.""" + return self._locked + + @locked.setter + def locked(self, value): + """Setter for locked property.""" + self.logger.warn("Setting values on locked will NOT update the remote Canvas instance.") + self._locked = value + + @property + def hidden(self): + """hidden.""" + return self._hidden + + @hidden.setter + def hidden(self, value): + """Setter for hidden property.""" + self.logger.warn("Setting values on hidden will NOT update the remote Canvas instance.") + self._hidden = value + + @property + def locked_for_user(self): + """locked_for_user.""" + return self._locked_for_user + + @locked_for_user.setter + def locked_for_user(self, value): + """Setter for locked_for_user property.""" + self.logger.warn("Setting values on locked_for_user will NOT update the remote Canvas instance.") + self._locked_for_user = value + + @property + def content_type(self): + """content_type.""" + return self._content_type + + @content_type.setter + def content_type(self, value): + """Setter for content_type property.""" + self.logger.warn("Setting values on content_type will NOT update the remote Canvas instance.") + self._content_type = value + + @property + def id(self): + """id.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def size(self): + """size.""" + return self._size + + @size.setter + def size(self, value): + """Setter for size property.""" + self.logger.warn("Setting values on size will NOT update the remote Canvas instance.") + self._size = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/grade_change_log.py b/venv/Lib/site-packages/pycanvas/apis/grade_change_log.py new file mode 100644 index 00000000..fc058dc8 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/grade_change_log.py @@ -0,0 +1,336 @@ +"""GradeChangeLog API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class GradeChangeLogAPI(BaseCanvasAPI): + """GradeChangeLog API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for GradeChangeLogAPI.""" + super(GradeChangeLogAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.GradeChangeLogAPI") + + def query_by_assignment(self, assignment_id, end_time=None, start_time=None): + """ + Query by assignment. + + List grade change events for a given assignment. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want events.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want events.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/audit/grade_change/assignments/{assignment_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/audit/grade_change/assignments/{assignment_id}".format(**path), data=data, params=params, all_pages=True) + + def query_by_course(self, course_id, end_time=None, start_time=None): + """ + Query by course. + + List grade change events for a given course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want events.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want events.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/audit/grade_change/courses/{course_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/audit/grade_change/courses/{course_id}".format(**path), data=data, params=params, all_pages=True) + + def query_by_student(self, student_id, end_time=None, start_time=None): + """ + Query by student. + + List grade change events for a given student. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - student_id + """ID""" + path["student_id"] = student_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want events.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want events.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/audit/grade_change/students/{student_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/audit/grade_change/students/{student_id}".format(**path), data=data, params=params, all_pages=True) + + def query_by_grader(self, grader_id, end_time=None, start_time=None): + """ + Query by grader. + + List grade change events for a given grader. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - grader_id + """ID""" + path["grader_id"] = grader_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want events.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want events.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/audit/grade_change/graders/{grader_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/audit/grade_change/graders/{grader_id}".format(**path), data=data, params=params, all_pages=True) + + +class Gradechangeevent(BaseModel): + """Gradechangeevent Model.""" + + def __init__(self, version_number=None, event_type=None, links=None, created_at=None, request_id=None, grade_before=None, id=None, graded_anonymously=None, excused_after=None, excused_before=None, grade_after=None): + """Init method for Gradechangeevent class.""" + self._version_number = version_number + self._event_type = event_type + self._links = links + self._created_at = created_at + self._request_id = request_id + self._grade_before = grade_before + self._id = id + self._graded_anonymously = graded_anonymously + self._excused_after = excused_after + self._excused_before = excused_before + self._grade_after = grade_after + + self.logger = logging.getLogger('pycanvas.Gradechangeevent') + + @property + def version_number(self): + """Version Number of the grade change submission.""" + return self._version_number + + @version_number.setter + def version_number(self, value): + """Setter for version_number property.""" + self.logger.warn("Setting values on version_number will NOT update the remote Canvas instance.") + self._version_number = value + + @property + def event_type(self): + """GradeChange event type.""" + return self._event_type + + @event_type.setter + def event_type(self, value): + """Setter for event_type property.""" + self.logger.warn("Setting values on event_type will NOT update the remote Canvas instance.") + self._event_type = value + + @property + def links(self): + """links.""" + return self._links + + @links.setter + def links(self, value): + """Setter for links property.""" + self.logger.warn("Setting values on links will NOT update the remote Canvas instance.") + self._links = value + + @property + def created_at(self): + """timestamp of the event.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def request_id(self): + """The unique request id of the request during the grade change.""" + return self._request_id + + @request_id.setter + def request_id(self, value): + """Setter for request_id property.""" + self.logger.warn("Setting values on request_id will NOT update the remote Canvas instance.") + self._request_id = value + + @property + def grade_before(self): + """The grade before the change.""" + return self._grade_before + + @grade_before.setter + def grade_before(self, value): + """Setter for grade_before property.""" + self.logger.warn("Setting values on grade_before will NOT update the remote Canvas instance.") + self._grade_before = value + + @property + def id(self): + """ID of the event.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def graded_anonymously(self): + """Boolean indicating whether the student name was visible when the grade was given. Could be null if the grade change record was created before this feature existed.""" + return self._graded_anonymously + + @graded_anonymously.setter + def graded_anonymously(self, value): + """Setter for graded_anonymously property.""" + self.logger.warn("Setting values on graded_anonymously will NOT update the remote Canvas instance.") + self._graded_anonymously = value + + @property + def excused_after(self): + """Boolean indicating whether the submission was excused after the change.""" + return self._excused_after + + @excused_after.setter + def excused_after(self, value): + """Setter for excused_after property.""" + self.logger.warn("Setting values on excused_after will NOT update the remote Canvas instance.") + self._excused_after = value + + @property + def excused_before(self): + """Boolean indicating whether the submission was excused before the change.""" + return self._excused_before + + @excused_before.setter + def excused_before(self, value): + """Setter for excused_before property.""" + self.logger.warn("Setting values on excused_before will NOT update the remote Canvas instance.") + self._excused_before = value + + @property + def grade_after(self): + """The grade after the change.""" + return self._grade_after + + @grade_after.setter + def grade_after(self, value): + """Setter for grade_after property.""" + self.logger.warn("Setting values on grade_after will NOT update the remote Canvas instance.") + self._grade_after = value + + +class Gradechangeeventlinks(BaseModel): + """Gradechangeeventlinks Model.""" + + def __init__(self, assignment=None, grader=None, page_view=None, student=None, course=None): + """Init method for Gradechangeeventlinks class.""" + self._assignment = assignment + self._grader = grader + self._page_view = page_view + self._student = student + self._course = course + + self.logger = logging.getLogger('pycanvas.Gradechangeeventlinks') + + @property + def assignment(self): + """ID of the assignment associated with the event.""" + return self._assignment + + @assignment.setter + def assignment(self, value): + """Setter for assignment property.""" + self.logger.warn("Setting values on assignment will NOT update the remote Canvas instance.") + self._assignment = value + + @property + def grader(self): + """ID of the grader associated with the event. will match the grader_id in the associated submission.""" + return self._grader + + @grader.setter + def grader(self, value): + """Setter for grader property.""" + self.logger.warn("Setting values on grader will NOT update the remote Canvas instance.") + self._grader = value + + @property + def page_view(self): + """ID of the page view during the event if it exists.""" + return self._page_view + + @page_view.setter + def page_view(self, value): + """Setter for page_view property.""" + self.logger.warn("Setting values on page_view will NOT update the remote Canvas instance.") + self._page_view = value + + @property + def student(self): + """ID of the student associated with the event. will match the user_id in the associated submission.""" + return self._student + + @student.setter + def student(self, value): + """Setter for student property.""" + self.logger.warn("Setting values on student will NOT update the remote Canvas instance.") + self._student = value + + @property + def course(self): + """ID of the course associated with the event. will match the context_id in the associated assignment if the context type for the assignment is a course.""" + return self._course + + @course.setter + def course(self, value): + """Setter for course property.""" + self.logger.warn("Setting values on course will NOT update the remote Canvas instance.") + self._course = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/gradebook_history.py b/venv/Lib/site-packages/pycanvas/apis/gradebook_history.py new file mode 100644 index 00000000..1a952876 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/gradebook_history.py @@ -0,0 +1,524 @@ +"""GradebookHistory API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class GradebookHistoryAPI(BaseCanvasAPI): + """GradebookHistory API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for GradebookHistoryAPI.""" + super(GradebookHistoryAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.GradebookHistoryAPI") + + def days_in_gradebook_history_for_this_course(self, course_id): + """ + Days in gradebook history for this course. + + Returns a map of dates to grader/assignment groups + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """The id of the contextual course for this API call""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/gradebook_history/days with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/gradebook_history/days".format(**path), data=data, params=params, all_pages=True) + + def details_for_given_date_in_gradebook_history_for_this_course(self, date, course_id): + """ + Details for a given date in gradebook history for this course. + + Returns the graders who worked on this day, along with the assignments they worked on. + More details can be obtained by selecting a grader and assignment and calling the + 'submissions' api endpoint for a given date. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """The id of the contextual course for this API call""" + path["course_id"] = course_id + + # REQUIRED - PATH - date + """The date for which you would like to see detailed information""" + path["date"] = date + + self.logger.debug("GET /api/v1/courses/{course_id}/gradebook_history/{date} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/gradebook_history/{date}".format(**path), data=data, params=params, all_pages=True) + + def lists_submissions(self, date, course_id, grader_id, assignment_id): + """ + Lists submissions. + + Gives a nested list of submission versions + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """The id of the contextual course for this API call""" + path["course_id"] = course_id + + # REQUIRED - PATH - date + """The date for which you would like to see submissions""" + path["date"] = date + + # REQUIRED - PATH - grader_id + """The ID of the grader for which you want to see submissions""" + path["grader_id"] = grader_id + + # REQUIRED - PATH - assignment_id + """The ID of the assignment for which you want to see submissions""" + path["assignment_id"] = assignment_id + + self.logger.debug("GET /api/v1/courses/{course_id}/gradebook_history/{date}/graders/{grader_id}/assignments/{assignment_id}/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/gradebook_history/{date}/graders/{grader_id}/assignments/{assignment_id}/submissions".format(**path), data=data, params=params, all_pages=True) + + def list_uncollated_submission_versions(self, course_id, ascending=None, assignment_id=None, user_id=None): + """ + List uncollated submission versions. + + Gives a paginated, uncollated list of submission versions for all matching + submissions in the context. This SubmissionVersion objects will not include + the +new_grade+ or +previous_grade+ keys, only the +grade+; same for + +graded_at+ and +grader+. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """The id of the contextual course for this API call""" + path["course_id"] = course_id + + # OPTIONAL - assignment_id + """The ID of the assignment for which you want to see submissions. If + absent, versions of submissions from any assignment in the course are + included.""" + if assignment_id is not None: + params["assignment_id"] = assignment_id + + # OPTIONAL - user_id + """The ID of the user for which you want to see submissions. If absent, + versions of submissions from any user in the course are included.""" + if user_id is not None: + params["user_id"] = user_id + + # OPTIONAL - ascending + """Returns submission versions in ascending date order (oldest first). If + absent, returns submission versions in descending date order (newest + first).""" + if ascending is not None: + params["ascending"] = ascending + + self.logger.debug("GET /api/v1/courses/{course_id}/gradebook_history/feed with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/gradebook_history/feed".format(**path), data=data, params=params, all_pages=True) + + +class Submissionversion(BaseModel): + """Submissionversion Model. + A SubmissionVersion object contains all the fields that a Submission object does, plus additional fields prefixed with current_* new_* and previous_* described below.""" + + def __init__(self, new_grade=None, previous_grader=None, grader=None, current_grade=None, id=None, user_id=None, previous_graded_at=None, assignment_name=None, score=None, grade_matches_current_submission=None, previous_grade=None, grader_id=None, user_name=None, body=None, current_graded_at=None, workflow_state=None, graded_at=None, new_grader=None, assignment_id=None, current_grader=None, new_graded_at=None, url=None, submission_type=None): + """Init method for Submissionversion class.""" + self._new_grade = new_grade + self._previous_grader = previous_grader + self._grader = grader + self._current_grade = current_grade + self._id = id + self._user_id = user_id + self._previous_graded_at = previous_graded_at + self._assignment_name = assignment_name + self._score = score + self._grade_matches_current_submission = grade_matches_current_submission + self._previous_grade = previous_grade + self._grader_id = grader_id + self._user_name = user_name + self._body = body + self._current_graded_at = current_graded_at + self._workflow_state = workflow_state + self._graded_at = graded_at + self._new_grader = new_grader + self._assignment_id = assignment_id + self._current_grader = current_grader + self._new_graded_at = new_graded_at + self._url = url + self._submission_type = submission_type + + self.logger = logging.getLogger('pycanvas.Submissionversion') + + @property + def new_grade(self): + """the updated grade provided in this version of the submission.""" + return self._new_grade + + @new_grade.setter + def new_grade(self, value): + """Setter for new_grade property.""" + self.logger.warn("Setting values on new_grade will NOT update the remote Canvas instance.") + self._new_grade = value + + @property + def previous_grader(self): + """the name of the grader who graded the version of this submission immediately preceding this one.""" + return self._previous_grader + + @previous_grader.setter + def previous_grader(self, value): + """Setter for previous_grader property.""" + self.logger.warn("Setting values on previous_grader will NOT update the remote Canvas instance.") + self._previous_grader = value + + @property + def grader(self): + """the name of the user who graded this version of the submission.""" + return self._grader + + @grader.setter + def grader(self, value): + """Setter for grader property.""" + self.logger.warn("Setting values on grader will NOT update the remote Canvas instance.") + self._grader = value + + @property + def current_grade(self): + """the most up to date grade for the current version of this submission.""" + return self._current_grade + + @current_grade.setter + def current_grade(self, value): + """Setter for current_grade property.""" + self.logger.warn("Setting values on current_grade will NOT update the remote Canvas instance.") + self._current_grade = value + + @property + def id(self): + """the id of the submission of which this is a version.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def user_id(self): + """the user ID of the student who created this submission.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def previous_graded_at(self): + """the timestamp for the grading of the submission version immediately preceding this one.""" + return self._previous_graded_at + + @previous_graded_at.setter + def previous_graded_at(self, value): + """Setter for previous_graded_at property.""" + self.logger.warn("Setting values on previous_graded_at will NOT update the remote Canvas instance.") + self._previous_graded_at = value + + @property + def assignment_name(self): + """the name of the assignment this submission is for.""" + return self._assignment_name + + @assignment_name.setter + def assignment_name(self, value): + """Setter for assignment_name property.""" + self.logger.warn("Setting values on assignment_name will NOT update the remote Canvas instance.") + self._assignment_name = value + + @property + def score(self): + """the score for this version of the submission.""" + return self._score + + @score.setter + def score(self, value): + """Setter for score property.""" + self.logger.warn("Setting values on score will NOT update the remote Canvas instance.") + self._score = value + + @property + def grade_matches_current_submission(self): + """boolean indicating whether the grade is equal to the current submission grade.""" + return self._grade_matches_current_submission + + @grade_matches_current_submission.setter + def grade_matches_current_submission(self, value): + """Setter for grade_matches_current_submission property.""" + self.logger.warn("Setting values on grade_matches_current_submission will NOT update the remote Canvas instance.") + self._grade_matches_current_submission = value + + @property + def previous_grade(self): + """the grade for the submission version immediately preceding this one.""" + return self._previous_grade + + @previous_grade.setter + def previous_grade(self, value): + """Setter for previous_grade property.""" + self.logger.warn("Setting values on previous_grade will NOT update the remote Canvas instance.") + self._previous_grade = value + + @property + def grader_id(self): + """the user id of the user who graded this version of the submission.""" + return self._grader_id + + @grader_id.setter + def grader_id(self, value): + """Setter for grader_id property.""" + self.logger.warn("Setting values on grader_id will NOT update the remote Canvas instance.") + self._grader_id = value + + @property + def user_name(self): + """the name of the student who created this submission.""" + return self._user_name + + @user_name.setter + def user_name(self, value): + """Setter for user_name property.""" + self.logger.warn("Setting values on user_name will NOT update the remote Canvas instance.") + self._user_name = value + + @property + def body(self): + """the body text of the submission.""" + return self._body + + @body.setter + def body(self, value): + """Setter for body property.""" + self.logger.warn("Setting values on body will NOT update the remote Canvas instance.") + self._body = value + + @property + def current_graded_at(self): + """the latest time stamp for the grading of this submission.""" + return self._current_graded_at + + @current_graded_at.setter + def current_graded_at(self, value): + """Setter for current_graded_at property.""" + self.logger.warn("Setting values on current_graded_at will NOT update the remote Canvas instance.") + self._current_graded_at = value + + @property + def workflow_state(self): + """the state of the submission at this version.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def graded_at(self): + """time stamp for the grading of this version of the submission.""" + return self._graded_at + + @graded_at.setter + def graded_at(self, value): + """Setter for graded_at property.""" + self.logger.warn("Setting values on graded_at will NOT update the remote Canvas instance.") + self._graded_at = value + + @property + def new_grader(self): + """alias for 'grader'.""" + return self._new_grader + + @new_grader.setter + def new_grader(self, value): + """Setter for new_grader property.""" + self.logger.warn("Setting values on new_grader will NOT update the remote Canvas instance.") + self._new_grader = value + + @property + def assignment_id(self): + """the id of the assignment this submissions is for.""" + return self._assignment_id + + @assignment_id.setter + def assignment_id(self, value): + """Setter for assignment_id property.""" + self.logger.warn("Setting values on assignment_id will NOT update the remote Canvas instance.") + self._assignment_id = value + + @property + def current_grader(self): + """the name of the most recent grader for this submission.""" + return self._current_grader + + @current_grader.setter + def current_grader(self, value): + """Setter for current_grader property.""" + self.logger.warn("Setting values on current_grader will NOT update the remote Canvas instance.") + self._current_grader = value + + @property + def new_graded_at(self): + """the timestamp for the grading of this version of the submission (alias for graded_at).""" + return self._new_graded_at + + @new_graded_at.setter + def new_graded_at(self, value): + """Setter for new_graded_at property.""" + self.logger.warn("Setting values on new_graded_at will NOT update the remote Canvas instance.") + self._new_graded_at = value + + @property + def url(self): + """the url of the submission, if there is one.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def submission_type(self): + """the type of submission.""" + return self._submission_type + + @submission_type.setter + def submission_type(self, value): + """Setter for submission_type property.""" + self.logger.warn("Setting values on submission_type will NOT update the remote Canvas instance.") + self._submission_type = value + + +class Grader(BaseModel): + """Grader Model.""" + + def __init__(self, assignments=None, id=None, name=None): + """Init method for Grader class.""" + self._assignments = assignments + self._id = id + self._name = name + + self.logger = logging.getLogger('pycanvas.Grader') + + @property + def assignments(self): + """the assignment groups for all submissions in this response that were graded by this user. The details are not nested inside here, but the fact that an assignment is present here means that the grader did grade submissions for this assignment on the contextual date. You can use the id of a grader and of an assignment to make another API call to find all submissions for a grader/assignment combination on a given date.""" + return self._assignments + + @assignments.setter + def assignments(self, value): + """Setter for assignments property.""" + self.logger.warn("Setting values on assignments will NOT update the remote Canvas instance.") + self._assignments = value + + @property + def id(self): + """the user_id of the user who graded the contained submissions.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def name(self): + """the name of the user who graded the contained submissions.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class Day(BaseModel): + """Day Model.""" + + def __init__(self, date=None, graders=None): + """Init method for Day class.""" + self._date = date + self._graders = graders + + self.logger = logging.getLogger('pycanvas.Day') + + @property + def date(self): + """the date represented by this entry.""" + return self._date + + @date.setter + def date(self, value): + """Setter for date property.""" + self.logger.warn("Setting values on date will NOT update the remote Canvas instance.") + self._date = value + + @property + def graders(self): + """an array of the graders who were responsible for the submissions in this response. the submissions are grouped according to the person who graded them and the assignment they were submitted for.""" + return self._graders + + @graders.setter + def graders(self, value): + """Setter for graders property.""" + self.logger.warn("Setting values on graders will NOT update the remote Canvas instance.") + self._graders = value + + +class Submissionhistory(BaseModel): + """Submissionhistory Model.""" + + def __init__(self, submission_id=None, versions=None): + """Init method for Submissionhistory class.""" + self._submission_id = submission_id + self._versions = versions + + self.logger = logging.getLogger('pycanvas.Submissionhistory') + + @property + def submission_id(self): + """the id of the submission.""" + return self._submission_id + + @submission_id.setter + def submission_id(self, value): + """Setter for submission_id property.""" + self.logger.warn("Setting values on submission_id will NOT update the remote Canvas instance.") + self._submission_id = value + + @property + def versions(self): + """an array of all the versions of this submission.""" + return self._versions + + @versions.setter + def versions(self, value): + """Setter for versions property.""" + self.logger.warn("Setting values on versions will NOT update the remote Canvas instance.") + self._versions = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/grading_periods.py b/venv/Lib/site-packages/pycanvas/apis/grading_periods.py new file mode 100644 index 00000000..868ad563 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/grading_periods.py @@ -0,0 +1,232 @@ +"""GradingPeriods API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class GradingPeriodsAPI(BaseCanvasAPI): + """GradingPeriods API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for GradingPeriodsAPI.""" + super(GradingPeriodsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.GradingPeriodsAPI") + + def list_grading_periods_accounts(self, account_id): + """ + List grading periods. + + Returns the list of grading periods for the current course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/grading_periods with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/grading_periods".format(**path), data=data, params=params, no_data=True) + + def list_grading_periods_courses(self, course_id): + """ + List grading periods. + + Returns the list of grading periods for the current course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/grading_periods with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/grading_periods".format(**path), data=data, params=params, no_data=True) + + def get_single_grading_period(self, id, course_id): + """ + Get a single grading period. + + Returns the grading period with the given id + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/grading_periods/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/grading_periods/{id}".format(**path), data=data, params=params, no_data=True) + + def update_single_grading_period(self, id, course_id, grading_periods_end_date, grading_periods_start_date, grading_periods_weight=None): + """ + Update a single grading period. + + Update an existing grading period. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - grading_periods[start_date] + """The date the grading period starts.""" + data["grading_periods[start_date]"] = grading_periods_start_date + + # REQUIRED - grading_periods[end_date] + """no description""" + data["grading_periods[end_date]"] = grading_periods_end_date + + # OPTIONAL - grading_periods[weight] + """A weight value that contributes to the overall weight of a grading period set which is used to calculate how much assignments in this period contribute to the total grade""" + if grading_periods_weight is not None: + data["grading_periods[weight]"] = grading_periods_weight + + self.logger.debug("PUT /api/v1/courses/{course_id}/grading_periods/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/grading_periods/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_grading_period_courses(self, id, course_id): + """ + Delete a grading period. + + 204 No Content response code is returned if the deletion was + successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/grading_periods/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/grading_periods/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_grading_period_accounts(self, id, account_id): + """ + Delete a grading period. + + 204 No Content response code is returned if the deletion was + successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/grading_periods/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/grading_periods/{id}".format(**path), data=data, params=params, no_data=True) + + +class Gradingperiod(BaseModel): + """Gradingperiod Model.""" + + def __init__(self, id, start_date, end_date, weight=None, title=None, close_date=None): + """Init method for Gradingperiod class.""" + self._end_date = end_date + self._weight = weight + self._title = title + self._id = id + self._close_date = close_date + self._start_date = start_date + + self.logger = logging.getLogger('pycanvas.Gradingperiod') + + @property + def end_date(self): + """The end date of the grading period.""" + return self._end_date + + @end_date.setter + def end_date(self, value): + """Setter for end_date property.""" + self.logger.warn("Setting values on end_date will NOT update the remote Canvas instance.") + self._end_date = value + + @property + def weight(self): + """A weight value that contributes to the overall weight of a grading period set which is used to calculate how much assignments in this period contribute to the total grade.""" + return self._weight + + @weight.setter + def weight(self, value): + """Setter for weight property.""" + self.logger.warn("Setting values on weight will NOT update the remote Canvas instance.") + self._weight = value + + @property + def title(self): + """The title for the grading period.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def id(self): + """The unique identifier for the grading period.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def close_date(self): + """Grades can only be changed before the close date of the grading period.""" + return self._close_date + + @close_date.setter + def close_date(self, value): + """Setter for close_date property.""" + self.logger.warn("Setting values on close_date will NOT update the remote Canvas instance.") + self._close_date = value + + @property + def start_date(self): + """The start date of the grading period.""" + return self._start_date + + @start_date.setter + def start_date(self, value): + """Setter for start_date property.""" + self.logger.warn("Setting values on start_date will NOT update the remote Canvas instance.") + self._start_date = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/grading_standards.py b/venv/Lib/site-packages/pycanvas/apis/grading_standards.py new file mode 100644 index 00000000..6993eb05 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/grading_standards.py @@ -0,0 +1,252 @@ +"""GradingStandards API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class GradingStandardsAPI(BaseCanvasAPI): + """GradingStandards API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for GradingStandardsAPI.""" + super(GradingStandardsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.GradingStandardsAPI") + + def create_new_grading_standard_accounts(self, title, account_id, grading_scheme_entry_name, grading_scheme_entry_value): + """ + Create a new grading standard. + + Create a new grading standard + + If grading_scheme_entry arguments are omitted, then a default grading scheme + will be set. The default scheme is as follows: + "A" : 94, + "A-" : 90, + "B+" : 87, + "B" : 84, + "B-" : 80, + "C+" : 77, + "C" : 74, + "C-" : 70, + "D+" : 67, + "D" : 64, + "D-" : 61, + "F" : 0, + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - title + """The title for the Grading Standard.""" + data["title"] = title + + # REQUIRED - grading_scheme_entry[name] + """The name for an entry value within a GradingStandard that describes the range of the value + e.g. A-""" + data["grading_scheme_entry[name]"] = grading_scheme_entry_name + + # REQUIRED - grading_scheme_entry[value] + """The value for the name of the entry within a GradingStandard. + The entry represents the lower bound of the range for the entry. + This range includes the value up to the next entry in the GradingStandard, + or 100 if there is no upper bound. The lowest value will have a lower bound range of 0. + e.g. 93""" + data["grading_scheme_entry[value]"] = grading_scheme_entry_value + + self.logger.debug("POST /api/v1/accounts/{account_id}/grading_standards with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/grading_standards".format(**path), data=data, params=params, single_item=True) + + def create_new_grading_standard_courses(self, title, course_id, grading_scheme_entry_name, grading_scheme_entry_value): + """ + Create a new grading standard. + + Create a new grading standard + + If grading_scheme_entry arguments are omitted, then a default grading scheme + will be set. The default scheme is as follows: + "A" : 94, + "A-" : 90, + "B+" : 87, + "B" : 84, + "B-" : 80, + "C+" : 77, + "C" : 74, + "C-" : 70, + "D+" : 67, + "D" : 64, + "D-" : 61, + "F" : 0, + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - title + """The title for the Grading Standard.""" + data["title"] = title + + # REQUIRED - grading_scheme_entry[name] + """The name for an entry value within a GradingStandard that describes the range of the value + e.g. A-""" + data["grading_scheme_entry[name]"] = grading_scheme_entry_name + + # REQUIRED - grading_scheme_entry[value] + """The value for the name of the entry within a GradingStandard. + The entry represents the lower bound of the range for the entry. + This range includes the value up to the next entry in the GradingStandard, + or 100 if there is no upper bound. The lowest value will have a lower bound range of 0. + e.g. 93""" + data["grading_scheme_entry[value]"] = grading_scheme_entry_value + + self.logger.debug("POST /api/v1/courses/{course_id}/grading_standards with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/grading_standards".format(**path), data=data, params=params, single_item=True) + + def list_grading_standards_available_in_context_courses(self, course_id): + """ + List the grading standards available in a context. + + Returns the list of grading standards in the given context that are visible to user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/grading_standards with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/grading_standards".format(**path), data=data, params=params, all_pages=True) + + def list_grading_standards_available_in_context_accounts(self, account_id): + """ + List the grading standards available in a context. + + Returns the list of grading standards in the given context that are visible to user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/grading_standards with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/grading_standards".format(**path), data=data, params=params, all_pages=True) + + +class Gradingstandard(BaseModel): + """Gradingstandard Model.""" + + def __init__(self, context_type=None, context_id=None, grading_scheme=None, id=None, title=None): + """Init method for Gradingstandard class.""" + self._context_type = context_type + self._context_id = context_id + self._grading_scheme = grading_scheme + self._id = id + self._title = title + + self.logger = logging.getLogger('pycanvas.Gradingstandard') + + @property + def context_type(self): + """the context this standard is associated with, either 'Account' or 'Course'.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def context_id(self): + """the id for the context either the Account or Course id.""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + + @property + def grading_scheme(self): + """A list of GradingSchemeEntry that make up the Grading Standard as an array of values with the scheme name and value.""" + return self._grading_scheme + + @grading_scheme.setter + def grading_scheme(self, value): + """Setter for grading_scheme property.""" + self.logger.warn("Setting values on grading_scheme will NOT update the remote Canvas instance.") + self._grading_scheme = value + + @property + def id(self): + """the id of the grading standard.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def title(self): + """the title of the grading standard.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + +class Gradingschemeentry(BaseModel): + """Gradingschemeentry Model.""" + + def __init__(self, name=None, value=None): + """Init method for Gradingschemeentry class.""" + self._name = name + self._value = value + + self.logger = logging.getLogger('pycanvas.Gradingschemeentry') + + @property + def name(self): + """The name for an entry value within a GradingStandard that describes the range of the value.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def value(self): + """The value for the name of the entry within a GradingStandard. The entry represents the lower bound of the range for the entry. This range includes the value up to the next entry in the GradingStandard, or 100 if there is no upper bound. The lowest value will have a lower bound range of 0.""" + return self._value + + @value.setter + def value(self, value): + """Setter for value property.""" + self.logger.warn("Setting values on value will NOT update the remote Canvas instance.") + self._value = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/group_categories.py b/venv/Lib/site-packages/pycanvas/apis/group_categories.py new file mode 100644 index 00000000..0c30ab6a --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/group_categories.py @@ -0,0 +1,460 @@ +"""GroupCategories API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class GroupCategoriesAPI(BaseCanvasAPI): + """GroupCategories API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for GroupCategoriesAPI.""" + super(GroupCategoriesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.GroupCategoriesAPI") + + def list_group_categories_for_context_accounts(self, account_id): + """ + List group categories for a context. + + Returns a list of group categories in a context + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/group_categories with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/group_categories".format(**path), data=data, params=params, all_pages=True) + + def list_group_categories_for_context_courses(self, course_id): + """ + List group categories for a context. + + Returns a list of group categories in a context + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/group_categories with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/group_categories".format(**path), data=data, params=params, all_pages=True) + + def get_single_group_category(self, group_category_id): + """ + Get a single group category. + + Returns the data for a single group category, or a 401 if the caller doesn't have + the rights to see it. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_category_id + """ID""" + path["group_category_id"] = group_category_id + + self.logger.debug("GET /api/v1/group_categories/{group_category_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/group_categories/{group_category_id}".format(**path), data=data, params=params, single_item=True) + + def create_group_category_accounts(self, name, account_id, auto_leader=None, create_group_count=None, group_limit=None, self_signup=None, split_group_count=None): + """ + Create a Group Category. + + Create a new group category + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - name + """Name of the group category""" + data["name"] = name + + # OPTIONAL - self_signup + """Allow students to sign up for a group themselves (Course Only). + valid values are: + "enabled":: allows students to self sign up for any group in course + "restricted":: allows students to self sign up only for groups in the + same section null disallows self sign up""" + if self_signup is not None: + self._validate_enum(self_signup, ["enabled", "restricted"]) + data["self_signup"] = self_signup + + # OPTIONAL - auto_leader + """Assigns group leaders automatically when generating and allocating students to groups + Valid values are: + "first":: the first student to be allocated to a group is the leader + "random":: a random student from all members is chosen as the leader""" + if auto_leader is not None: + self._validate_enum(auto_leader, ["first", "random"]) + data["auto_leader"] = auto_leader + + # OPTIONAL - group_limit + """Limit the maximum number of users in each group (Course Only). Requires + self signup.""" + if group_limit is not None: + data["group_limit"] = group_limit + + # OPTIONAL - create_group_count + """Create this number of groups (Course Only).""" + if create_group_count is not None: + data["create_group_count"] = create_group_count + + # OPTIONAL - split_group_count + """(Deprecated) + Create this number of groups, and evenly distribute students + among them. not allowed with "enable_self_signup". because + the group assignment happens synchronously, it's recommended + that you instead use the assign_unassigned_members endpoint. + (Course Only)""" + if split_group_count is not None: + data["split_group_count"] = split_group_count + + self.logger.debug("POST /api/v1/accounts/{account_id}/group_categories with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/group_categories".format(**path), data=data, params=params, single_item=True) + + def create_group_category_courses(self, name, course_id, auto_leader=None, create_group_count=None, group_limit=None, self_signup=None, split_group_count=None): + """ + Create a Group Category. + + Create a new group category + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - name + """Name of the group category""" + data["name"] = name + + # OPTIONAL - self_signup + """Allow students to sign up for a group themselves (Course Only). + valid values are: + "enabled":: allows students to self sign up for any group in course + "restricted":: allows students to self sign up only for groups in the + same section null disallows self sign up""" + if self_signup is not None: + self._validate_enum(self_signup, ["enabled", "restricted"]) + data["self_signup"] = self_signup + + # OPTIONAL - auto_leader + """Assigns group leaders automatically when generating and allocating students to groups + Valid values are: + "first":: the first student to be allocated to a group is the leader + "random":: a random student from all members is chosen as the leader""" + if auto_leader is not None: + self._validate_enum(auto_leader, ["first", "random"]) + data["auto_leader"] = auto_leader + + # OPTIONAL - group_limit + """Limit the maximum number of users in each group (Course Only). Requires + self signup.""" + if group_limit is not None: + data["group_limit"] = group_limit + + # OPTIONAL - create_group_count + """Create this number of groups (Course Only).""" + if create_group_count is not None: + data["create_group_count"] = create_group_count + + # OPTIONAL - split_group_count + """(Deprecated) + Create this number of groups, and evenly distribute students + among them. not allowed with "enable_self_signup". because + the group assignment happens synchronously, it's recommended + that you instead use the assign_unassigned_members endpoint. + (Course Only)""" + if split_group_count is not None: + data["split_group_count"] = split_group_count + + self.logger.debug("POST /api/v1/courses/{course_id}/group_categories with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/group_categories".format(**path), data=data, params=params, single_item=True) + + def update_group_category(self, group_category_id, auto_leader=None, create_group_count=None, group_limit=None, name=None, self_signup=None, split_group_count=None): + """ + Update a Group Category. + + Modifies an existing group category. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_category_id + """ID""" + path["group_category_id"] = group_category_id + + # OPTIONAL - name + """Name of the group category""" + if name is not None: + data["name"] = name + + # OPTIONAL - self_signup + """Allow students to sign up for a group themselves (Course Only). + Valid values are: + "enabled":: allows students to self sign up for any group in course + "restricted":: allows students to self sign up only for groups in the + same section null disallows self sign up""" + if self_signup is not None: + self._validate_enum(self_signup, ["enabled", "restricted"]) + data["self_signup"] = self_signup + + # OPTIONAL - auto_leader + """Assigns group leaders automatically when generating and allocating students to groups + Valid values are: + "first":: the first student to be allocated to a group is the leader + "random":: a random student from all members is chosen as the leader""" + if auto_leader is not None: + self._validate_enum(auto_leader, ["first", "random"]) + data["auto_leader"] = auto_leader + + # OPTIONAL - group_limit + """Limit the maximum number of users in each group (Course Only). Requires + self signup.""" + if group_limit is not None: + data["group_limit"] = group_limit + + # OPTIONAL - create_group_count + """Create this number of groups (Course Only).""" + if create_group_count is not None: + data["create_group_count"] = create_group_count + + # OPTIONAL - split_group_count + """(Deprecated) + Create this number of groups, and evenly distribute students + among them. not allowed with "enable_self_signup". because + the group assignment happens synchronously, it's recommended + that you instead use the assign_unassigned_members endpoint. + (Course Only)""" + if split_group_count is not None: + data["split_group_count"] = split_group_count + + self.logger.debug("PUT /api/v1/group_categories/{group_category_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/group_categories/{group_category_id}".format(**path), data=data, params=params, single_item=True) + + def delete_group_category(self, group_category_id): + """ + Delete a Group Category. + + Deletes a group category and all groups under it. Protected group + categories can not be deleted, i.e. "communities" and "student_organized". + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_category_id + """ID""" + path["group_category_id"] = group_category_id + + self.logger.debug("DELETE /api/v1/group_categories/{group_category_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/group_categories/{group_category_id}".format(**path), data=data, params=params, no_data=True) + + def list_groups_in_group_category(self, group_category_id): + """ + List groups in group category. + + Returns a list of groups in a group category + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_category_id + """ID""" + path["group_category_id"] = group_category_id + + self.logger.debug("GET /api/v1/group_categories/{group_category_id}/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/group_categories/{group_category_id}/groups".format(**path), data=data, params=params, all_pages=True) + + def list_users_in_group_category(self, group_category_id, search_term=None, unassigned=None): + """ + List users in group category. + + Returns a list of users in the group category. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_category_id + """ID""" + path["group_category_id"] = group_category_id + + # OPTIONAL - search_term + """The partial name or full ID of the users to match and return in the results + list. Must be at least 3 characters.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - unassigned + """Set this value to true if you wish only to search unassigned users in the + group category.""" + if unassigned is not None: + params["unassigned"] = unassigned + + self.logger.debug("GET /api/v1/group_categories/{group_category_id}/users with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/group_categories/{group_category_id}/users".format(**path), data=data, params=params, all_pages=True) + + def assign_unassigned_members(self, group_category_id, sync=None): + """ + Assign unassigned members. + + Assign all unassigned members as evenly as possible among the existing + student groups. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_category_id + """ID""" + path["group_category_id"] = group_category_id + + # OPTIONAL - sync + """The assigning is done asynchronously by default. If you would like to + override this and have the assigning done synchronously, set this value + to true.""" + if sync is not None: + data["sync"] = sync + + self.logger.debug("POST /api/v1/group_categories/{group_category_id}/assign_unassigned_members with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/group_categories/{group_category_id}/assign_unassigned_members".format(**path), data=data, params=params, single_item=True) + + +class Groupcategory(BaseModel): + """Groupcategory Model.""" + + def __init__(self, name=None, self_signup=None, auto_leader=None, context_type=None, role=None, group_limit=None, progress=None, id=None, account_id=None): + """Init method for Groupcategory class.""" + self._name = name + self._self_signup = self_signup + self._auto_leader = auto_leader + self._context_type = context_type + self._role = role + self._group_limit = group_limit + self._progress = progress + self._id = id + self._account_id = account_id + + self.logger = logging.getLogger('pycanvas.Groupcategory') + + @property + def name(self): + """The display name of the group category.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def self_signup(self): + """If the group category allows users to join a group themselves, thought they may only be a member of one group per group category at a time. Values include 'restricted', 'enabled', and null 'enabled' allows students to assign themselves to a group 'restricted' restricts them to only joining a group in their section null disallows students from joining groups.""" + return self._self_signup + + @self_signup.setter + def self_signup(self, value): + """Setter for self_signup property.""" + self.logger.warn("Setting values on self_signup will NOT update the remote Canvas instance.") + self._self_signup = value + + @property + def auto_leader(self): + """Gives instructors the ability to automatically have group leaders assigned. Values include 'random', 'first', and null; 'random' picks a student from the group at random as the leader, 'first' sets the first student to be assigned to the group as the leader.""" + return self._auto_leader + + @auto_leader.setter + def auto_leader(self, value): + """Setter for auto_leader property.""" + self.logger.warn("Setting values on auto_leader will NOT update the remote Canvas instance.") + self._auto_leader = value + + @property + def context_type(self): + """The course or account that the category group belongs to. The pattern here is that whatever the context_type is, there will be an _id field named after that type. So if instead context_type was 'Course', the course_id field would be replaced by an course_id field.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def role(self): + """Certain types of group categories have special role designations. Currently, these include: 'communities', 'student_organized', and 'imported'. Regular course/account group categories have a role of null.""" + return self._role + + @role.setter + def role(self, value): + """Setter for role property.""" + self.logger.warn("Setting values on role will NOT update the remote Canvas instance.") + self._role = value + + @property + def group_limit(self): + """If self-signup is enabled, group_limit can be set to cap the number of users in each group. If null, there is no limit.""" + return self._group_limit + + @group_limit.setter + def group_limit(self, value): + """Setter for group_limit property.""" + self.logger.warn("Setting values on group_limit will NOT update the remote Canvas instance.") + self._group_limit = value + + @property + def progress(self): + """If the group category has not yet finished a randomly student assignment request, a progress object will be attached, which will contain information related to the progress of the assignment request. Refer to the Progress API for more information.""" + return self._progress + + @progress.setter + def progress(self, value): + """Setter for progress property.""" + self.logger.warn("Setting values on progress will NOT update the remote Canvas instance.") + self._progress = value + + @property + def id(self): + """The ID of the group category.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def account_id(self): + """account_id.""" + return self._account_id + + @account_id.setter + def account_id(self, value): + """Setter for account_id property.""" + self.logger.warn("Setting values on account_id will NOT update the remote Canvas instance.") + self._account_id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/groups.py b/venv/Lib/site-packages/pycanvas/apis/groups.py new file mode 100644 index 00000000..989c0ab2 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/groups.py @@ -0,0 +1,926 @@ +"""Groups API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class GroupsAPI(BaseCanvasAPI): + """Groups API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for GroupsAPI.""" + super(GroupsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.GroupsAPI") + + def list_your_groups(self, context_type=None, include=None): + """ + List your groups. + + Returns a list of active groups for the current user. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - context_type + """Only include groups that are in this type of context.""" + if context_type is not None: + self._validate_enum(context_type, ["Account", "Course"]) + params["context_type"] = context_type + + # OPTIONAL - include + """- "tabs": Include the list of tabs configured for each group. See the + {api:TabsController#index List available tabs API} for more information.""" + if include is not None: + self._validate_enum(include, ["tabs"]) + params["include"] = include + + self.logger.debug("GET /api/v1/users/self/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/groups".format(**path), data=data, params=params, all_pages=True) + + def list_groups_available_in_context_accounts(self, account_id, include=None, only_own_groups=None): + """ + List the groups available in a context. + + Returns the list of active groups in the given context that are visible to user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - only_own_groups + """Will only include groups that the user belongs to if this is set""" + if only_own_groups is not None: + params["only_own_groups"] = only_own_groups + + # OPTIONAL - include + """- "tabs": Include the list of tabs configured for each group. See the + {api:TabsController#index List available tabs API} for more information.""" + if include is not None: + self._validate_enum(include, ["tabs"]) + params["include"] = include + + self.logger.debug("GET /api/v1/accounts/{account_id}/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/groups".format(**path), data=data, params=params, all_pages=True) + + def list_groups_available_in_context_courses(self, course_id, include=None, only_own_groups=None): + """ + List the groups available in a context. + + Returns the list of active groups in the given context that are visible to user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - only_own_groups + """Will only include groups that the user belongs to if this is set""" + if only_own_groups is not None: + params["only_own_groups"] = only_own_groups + + # OPTIONAL - include + """- "tabs": Include the list of tabs configured for each group. See the + {api:TabsController#index List available tabs API} for more information.""" + if include is not None: + self._validate_enum(include, ["tabs"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/groups".format(**path), data=data, params=params, all_pages=True) + + def get_single_group(self, group_id, include=None): + """ + Get a single group. + + Returns the data for a single group, or a 401 if the caller doesn't have + the rights to see it. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - include + """- "permissions": Include permissions the current user has + for the group. + - "tabs": Include the list of tabs configured for each group. See the + {api:TabsController#index List available tabs API} for more information.""" + if include is not None: + self._validate_enum(include, ["permissions", "tabs"]) + params["include"] = include + + self.logger.debug("GET /api/v1/groups/{group_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}".format(**path), data=data, params=params, single_item=True) + + def create_group_groups(self, description=None, is_public=None, join_level=None, name=None, storage_quota_mb=None): + """ + Create a group. + + Creates a new group. Groups created using the "/api/v1/groups/" + endpoint will be community groups. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - name + """The name of the group""" + if name is not None: + data["name"] = name + + # OPTIONAL - description + """A description of the group""" + if description is not None: + data["description"] = description + + # OPTIONAL - is_public + """whether the group is public (applies only to community groups)""" + if is_public is not None: + data["is_public"] = is_public + + # OPTIONAL - join_level + """no description""" + if join_level is not None: + self._validate_enum(join_level, ["parent_context_auto_join", "parent_context_request", "invitation_only"]) + data["join_level"] = join_level + + # OPTIONAL - storage_quota_mb + """The allowed file storage for the group, in megabytes. This parameter is + ignored if the caller does not have the manage_storage_quotas permission.""" + if storage_quota_mb is not None: + data["storage_quota_mb"] = storage_quota_mb + + self.logger.debug("POST /api/v1/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups".format(**path), data=data, params=params, single_item=True) + + def create_group_group_categories(self, group_category_id, description=None, is_public=None, join_level=None, name=None, storage_quota_mb=None): + """ + Create a group. + + Creates a new group. Groups created using the "/api/v1/groups/" + endpoint will be community groups. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_category_id + """ID""" + path["group_category_id"] = group_category_id + + # OPTIONAL - name + """The name of the group""" + if name is not None: + data["name"] = name + + # OPTIONAL - description + """A description of the group""" + if description is not None: + data["description"] = description + + # OPTIONAL - is_public + """whether the group is public (applies only to community groups)""" + if is_public is not None: + data["is_public"] = is_public + + # OPTIONAL - join_level + """no description""" + if join_level is not None: + self._validate_enum(join_level, ["parent_context_auto_join", "parent_context_request", "invitation_only"]) + data["join_level"] = join_level + + # OPTIONAL - storage_quota_mb + """The allowed file storage for the group, in megabytes. This parameter is + ignored if the caller does not have the manage_storage_quotas permission.""" + if storage_quota_mb is not None: + data["storage_quota_mb"] = storage_quota_mb + + self.logger.debug("POST /api/v1/group_categories/{group_category_id}/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/group_categories/{group_category_id}/groups".format(**path), data=data, params=params, single_item=True) + + def edit_group(self, group_id, avatar_id=None, description=None, is_public=None, join_level=None, members=None, name=None, storage_quota_mb=None): + """ + Edit a group. + + Modifies an existing group. Note that to set an avatar image for the + group, you must first upload the image file to the group, and the use the + id in the response as the argument to this function. See the + {file:file_uploads.html File Upload Documentation} for details on the file + upload workflow. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - name + """The name of the group""" + if name is not None: + data["name"] = name + + # OPTIONAL - description + """A description of the group""" + if description is not None: + data["description"] = description + + # OPTIONAL - is_public + """Whether the group is public (applies only to community groups). Currently + you cannot set a group back to private once it has been made public.""" + if is_public is not None: + data["is_public"] = is_public + + # OPTIONAL - join_level + """no description""" + if join_level is not None: + self._validate_enum(join_level, ["parent_context_auto_join", "parent_context_request", "invitation_only"]) + data["join_level"] = join_level + + # OPTIONAL - avatar_id + """The id of the attachment previously uploaded to the group that you would + like to use as the avatar image for this group.""" + if avatar_id is not None: + data["avatar_id"] = avatar_id + + # OPTIONAL - storage_quota_mb + """The allowed file storage for the group, in megabytes. This parameter is + ignored if the caller does not have the manage_storage_quotas permission.""" + if storage_quota_mb is not None: + data["storage_quota_mb"] = storage_quota_mb + + # OPTIONAL - members + """An array of user ids for users you would like in the group. + Users not in the group will be sent invitations. Existing group + members who aren't in the list will be removed from the group.""" + if members is not None: + data["members"] = members + + self.logger.debug("PUT /api/v1/groups/{group_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}".format(**path), data=data, params=params, single_item=True) + + def delete_group(self, group_id): + """ + Delete a group. + + Deletes a group and removes all members. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("DELETE /api/v1/groups/{group_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}".format(**path), data=data, params=params, single_item=True) + + def invite_others_to_group(self, group_id, invitees): + """ + Invite others to a group. + + Sends an invitation to all supplied email addresses which will allow the + receivers to join the group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - invitees + """An array of email addresses to be sent invitations.""" + data["invitees"] = invitees + + self.logger.debug("POST /api/v1/groups/{group_id}/invite with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/invite".format(**path), data=data, params=params, no_data=True) + + def list_group_s_users(self, group_id, include=None, search_term=None): + """ + List group's users. + + Returns a list of users in the group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - search_term + """The partial name or full ID of the users to match and return in the + results list. Must be at least 3 characters.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - include + """- "avatar_url": Include users' avatar_urls.""" + if include is not None: + self._validate_enum(include, ["avatar_url"]) + params["include"] = include + + self.logger.debug("GET /api/v1/groups/{group_id}/users with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/users".format(**path), data=data, params=params, all_pages=True) + + def upload_file(self, group_id): + """ + Upload a file. + + Upload a file to the group. + + This API endpoint is the first step in uploading a file to a group. + See the {file:file_uploads.html File Upload Documentation} for details on + the file upload workflow. + + Only those with the "Manage Files" permission on a group can upload files + to the group. By default, this is anybody participating in the + group, or any admin over the group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("POST /api/v1/groups/{group_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/files".format(**path), data=data, params=params, no_data=True) + + def preview_processed_html(self, group_id, html=None): + """ + Preview processed html. + + Preview html content processed for this group + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - html + """The html content to process""" + if html is not None: + data["html"] = html + + self.logger.debug("POST /api/v1/groups/{group_id}/preview_html with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/preview_html".format(**path), data=data, params=params, no_data=True) + + def group_activity_stream(self, group_id): + """ + Group activity stream. + + Returns the current user's group-specific activity stream, paginated. + + For full documentation, see the API documentation for the user activity + stream, in the user api. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/activity_stream with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/activity_stream".format(**path), data=data, params=params, no_data=True) + + def group_activity_stream_summary(self, group_id): + """ + Group activity stream summary. + + Returns a summary of the current user's group-specific activity stream. + + For full documentation, see the API documentation for the user activity + stream summary, in the user api. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/activity_stream/summary with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/activity_stream/summary".format(**path), data=data, params=params, no_data=True) + + def list_group_memberships(self, group_id, filter_states=None): + """ + List group memberships. + + List the members of a group. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - filter_states + """Only list memberships with the given workflow_states. By default it will + return all memberships.""" + if filter_states is not None: + self._validate_enum(filter_states, ["accepted", "invited", "requested"]) + params["filter_states"] = filter_states + + self.logger.debug("GET /api/v1/groups/{group_id}/memberships with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/memberships".format(**path), data=data, params=params, all_pages=True) + + def get_single_group_membership_memberships(self, group_id, membership_id): + """ + Get a single group membership. + + Returns the group membership with the given membership id or user id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - membership_id + """ID""" + path["membership_id"] = membership_id + + self.logger.debug("GET /api/v1/groups/{group_id}/memberships/{membership_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/memberships/{membership_id}".format(**path), data=data, params=params, single_item=True) + + def get_single_group_membership_users(self, user_id, group_id): + """ + Get a single group membership. + + Returns the group membership with the given membership id or user id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/groups/{group_id}/users/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/users/{user_id}".format(**path), data=data, params=params, single_item=True) + + def create_membership(self, group_id, user_id=None): + """ + Create a membership. + + Join, or request to join, a group, depending on the join_level of the + group. If the membership or join request already exists, then it is simply + returned + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - user_id + """no description""" + if user_id is not None: + data["user_id"] = user_id + + self.logger.debug("POST /api/v1/groups/{group_id}/memberships with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/memberships".format(**path), data=data, params=params, single_item=True) + + def update_membership_memberships(self, group_id, membership_id, moderator=None, workflow_state=None): + """ + Update a membership. + + Accept a membership request, or add/remove moderator rights. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - membership_id + """ID""" + path["membership_id"] = membership_id + + # OPTIONAL - workflow_state + """Currently, the only allowed value is "accepted"""" + if workflow_state is not None: + self._validate_enum(workflow_state, ["accepted"]) + data["workflow_state"] = workflow_state + + # OPTIONAL - moderator + """no description""" + if moderator is not None: + data["moderator"] = moderator + + self.logger.debug("PUT /api/v1/groups/{group_id}/memberships/{membership_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/memberships/{membership_id}".format(**path), data=data, params=params, single_item=True) + + def update_membership_users(self, user_id, group_id, moderator=None, workflow_state=None): + """ + Update a membership. + + Accept a membership request, or add/remove moderator rights. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - workflow_state + """Currently, the only allowed value is "accepted"""" + if workflow_state is not None: + self._validate_enum(workflow_state, ["accepted"]) + data["workflow_state"] = workflow_state + + # OPTIONAL - moderator + """no description""" + if moderator is not None: + data["moderator"] = moderator + + self.logger.debug("PUT /api/v1/groups/{group_id}/users/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/users/{user_id}".format(**path), data=data, params=params, single_item=True) + + def leave_group_memberships(self, group_id, membership_id): + """ + Leave a group. + + Leave a group if you are allowed to leave (some groups, such as sets of + course groups created by teachers, cannot be left). You may also use 'self' + in place of a membership_id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - membership_id + """ID""" + path["membership_id"] = membership_id + + self.logger.debug("DELETE /api/v1/groups/{group_id}/memberships/{membership_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/memberships/{membership_id}".format(**path), data=data, params=params, no_data=True) + + def leave_group_users(self, user_id, group_id): + """ + Leave a group. + + Leave a group if you are allowed to leave (some groups, such as sets of + course groups created by teachers, cannot be left). You may also use 'self' + in place of a membership_id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("DELETE /api/v1/groups/{group_id}/users/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/users/{user_id}".format(**path), data=data, params=params, no_data=True) + + +class Group(BaseModel): + """Group Model.""" + + def __init__(self, members_count=None, description=None, context_type=None, storage_quota_mb=None, join_level=None, followed_by_user=None, group_category_id=None, sis_import_id=None, avatar_url=None, role=None, sis_group_id=None, course_id=None, is_public=None, permissions=None, id=None, name=None): + """Init method for Group class.""" + self._members_count = members_count + self._description = description + self._context_type = context_type + self._storage_quota_mb = storage_quota_mb + self._join_level = join_level + self._followed_by_user = followed_by_user + self._group_category_id = group_category_id + self._sis_import_id = sis_import_id + self._avatar_url = avatar_url + self._role = role + self._sis_group_id = sis_group_id + self._course_id = course_id + self._is_public = is_public + self._permissions = permissions + self._id = id + self._name = name + + self.logger = logging.getLogger('pycanvas.Group') + + @property + def members_count(self): + """The number of members currently in the group.""" + return self._members_count + + @members_count.setter + def members_count(self, value): + """Setter for members_count property.""" + self.logger.warn("Setting values on members_count will NOT update the remote Canvas instance.") + self._members_count = value + + @property + def description(self): + """A description of the group. This is plain text.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def context_type(self): + """The course or account that the group belongs to. The pattern here is that whatever the context_type is, there will be an _id field named after that type. So if instead context_type was 'account', the course_id field would be replaced by an account_id field.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def storage_quota_mb(self): + """the storage quota for the group, in megabytes.""" + return self._storage_quota_mb + + @storage_quota_mb.setter + def storage_quota_mb(self, value): + """Setter for storage_quota_mb property.""" + self.logger.warn("Setting values on storage_quota_mb will NOT update the remote Canvas instance.") + self._storage_quota_mb = value + + @property + def join_level(self): + """How people are allowed to join the group. For all groups except for community groups, the user must share the group's parent course or account. For student organized or community groups, where a user can be a member of as many or few as they want, the applicable levels are 'parent_context_auto_join', 'parent_context_request', and 'invitation_only'. For class groups, where students are divided up and should only be part of one group of the category, this value will always be 'invitation_only', and is not relevant. * If 'parent_context_auto_join', anyone can join and will be automatically accepted. * If 'parent_context_request', anyone can request to join, which must be approved by a group moderator. * If 'invitation_only', only those how have received an invitation my join the group, by accepting that invitation.""" + return self._join_level + + @join_level.setter + def join_level(self, value): + """Setter for join_level property.""" + self.logger.warn("Setting values on join_level will NOT update the remote Canvas instance.") + self._join_level = value + + @property + def followed_by_user(self): + """Whether or not the current user is following this group.""" + return self._followed_by_user + + @followed_by_user.setter + def followed_by_user(self, value): + """Setter for followed_by_user property.""" + self.logger.warn("Setting values on followed_by_user will NOT update the remote Canvas instance.") + self._followed_by_user = value + + @property + def group_category_id(self): + """The ID of the group's category.""" + return self._group_category_id + + @group_category_id.setter + def group_category_id(self, value): + """Setter for group_category_id property.""" + self.logger.warn("Setting values on group_category_id will NOT update the remote Canvas instance.") + self._group_category_id = value + + @property + def sis_import_id(self): + """The id of the SIS import if created through SIS. Only included if the user has permission to manage SIS information.""" + return self._sis_import_id + + @sis_import_id.setter + def sis_import_id(self, value): + """Setter for sis_import_id property.""" + self.logger.warn("Setting values on sis_import_id will NOT update the remote Canvas instance.") + self._sis_import_id = value + + @property + def avatar_url(self): + """The url of the group's avatar.""" + return self._avatar_url + + @avatar_url.setter + def avatar_url(self, value): + """Setter for avatar_url property.""" + self.logger.warn("Setting values on avatar_url will NOT update the remote Canvas instance.") + self._avatar_url = value + + @property + def role(self): + """Certain types of groups have special role designations. Currently, these include: 'communities', 'student_organized', and 'imported'. Regular course/account groups have a role of null.""" + return self._role + + @role.setter + def role(self, value): + """Setter for role property.""" + self.logger.warn("Setting values on role will NOT update the remote Canvas instance.") + self._role = value + + @property + def sis_group_id(self): + """The SIS ID of the group. Only included if the user has permission to view SIS information.""" + return self._sis_group_id + + @sis_group_id.setter + def sis_group_id(self, value): + """Setter for sis_group_id property.""" + self.logger.warn("Setting values on sis_group_id will NOT update the remote Canvas instance.") + self._sis_group_id = value + + @property + def course_id(self): + """course_id.""" + return self._course_id + + @course_id.setter + def course_id(self, value): + """Setter for course_id property.""" + self.logger.warn("Setting values on course_id will NOT update the remote Canvas instance.") + self._course_id = value + + @property + def is_public(self): + """Whether or not the group is public. Currently only community groups can be made public. Also, once a group has been set to public, it cannot be changed back to private.""" + return self._is_public + + @is_public.setter + def is_public(self, value): + """Setter for is_public property.""" + self.logger.warn("Setting values on is_public will NOT update the remote Canvas instance.") + self._is_public = value + + @property + def permissions(self): + """optional: the permissions the user has for the group. returned only for a single group and include[]=permissions.""" + return self._permissions + + @permissions.setter + def permissions(self, value): + """Setter for permissions property.""" + self.logger.warn("Setting values on permissions will NOT update the remote Canvas instance.") + self._permissions = value + + @property + def id(self): + """The ID of the group.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def name(self): + """The display name of the group.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class Groupmembership(BaseModel): + """Groupmembership Model.""" + + def __init__(self, user_id=None, workflow_state=None, moderator=None, sis_import_id=None, just_created=None, group_id=None, id=None): + """Init method for Groupmembership class.""" + self._user_id = user_id + self._workflow_state = workflow_state + self._moderator = moderator + self._sis_import_id = sis_import_id + self._just_created = just_created + self._group_id = group_id + self._id = id + + self.logger = logging.getLogger('pycanvas.Groupmembership') + + @property + def user_id(self): + """The id of the user object to which the membership belongs.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def workflow_state(self): + """The current state of the membership. Current possible values are 'accepted', 'invited', and 'requested'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def moderator(self): + """Whether or not the user is a moderator of the group (the must also be an active member of the group to moderate).""" + return self._moderator + + @moderator.setter + def moderator(self, value): + """Setter for moderator property.""" + self.logger.warn("Setting values on moderator will NOT update the remote Canvas instance.") + self._moderator = value + + @property + def sis_import_id(self): + """The id of the SIS import if created through SIS. Only included if the user has permission to manage SIS information.""" + return self._sis_import_id + + @sis_import_id.setter + def sis_import_id(self, value): + """Setter for sis_import_id property.""" + self.logger.warn("Setting values on sis_import_id will NOT update the remote Canvas instance.") + self._sis_import_id = value + + @property + def just_created(self): + """optional: whether or not the record was just created on a create call (POST), i.e. was the user just added to the group, or was the user already a member.""" + return self._just_created + + @just_created.setter + def just_created(self, value): + """Setter for just_created property.""" + self.logger.warn("Setting values on just_created will NOT update the remote Canvas instance.") + self._just_created = value + + @property + def group_id(self): + """The id of the group object to which the membership belongs.""" + return self._group_id + + @group_id.setter + def group_id(self, value): + """Setter for group_id property.""" + self.logger.warn("Setting values on group_id will NOT update the remote Canvas instance.") + self._group_id = value + + @property + def id(self): + """The id of the membership object.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/live_assessments.py b/venv/Lib/site-packages/pycanvas/apis/live_assessments.py new file mode 100644 index 00000000..3534eab8 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/live_assessments.py @@ -0,0 +1,250 @@ +"""LiveAssessments API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class LiveAssessmentsAPI(BaseCanvasAPI): + """LiveAssessments API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for LiveAssessmentsAPI.""" + super(LiveAssessmentsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.LiveAssessmentsAPI") + + def create_live_assessment_results(self, course_id, assessment_id): + """ + Create live assessment results. + + Creates live assessment results and adds them to a live assessment + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assessment_id + """ID""" + path["assessment_id"] = assessment_id + + self.logger.debug("POST /api/v1/courses/{course_id}/live_assessments/{assessment_id}/results with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/live_assessments/{assessment_id}/results".format(**path), data=data, params=params, no_data=True) + + def list_live_assessment_results(self, course_id, assessment_id, user_id=None): + """ + List live assessment results. + + Returns a list of live assessment results + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assessment_id + """ID""" + path["assessment_id"] = assessment_id + + # OPTIONAL - user_id + """If set, restrict results to those for this user""" + if user_id is not None: + params["user_id"] = user_id + + self.logger.debug("GET /api/v1/courses/{course_id}/live_assessments/{assessment_id}/results with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/live_assessments/{assessment_id}/results".format(**path), data=data, params=params, no_data=True) + + def create_or_find_live_assessment(self, course_id): + """ + Create or find a live assessment. + + Creates or finds an existing live assessment with the given key and aligns it with + the linked outcome + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("POST /api/v1/courses/{course_id}/live_assessments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/live_assessments".format(**path), data=data, params=params, no_data=True) + + def list_live_assessments(self, course_id): + """ + List live assessments. + + Returns a list of live assessments. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/live_assessments with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/live_assessments".format(**path), data=data, params=params, no_data=True) + + +class Assessment(BaseModel): + """Assessment Model. + A simple assessment that collects pass/fail results for a student""" + + def __init__(self, id=None, key=None, title=None): + """Init method for Assessment class.""" + self._id = id + self._key = key + self._title = title + + self.logger = logging.getLogger('pycanvas.Assessment') + + @property + def id(self): + """A unique identifier for this live assessment.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def key(self): + """A client specified unique identifier for the assessment.""" + return self._key + + @key.setter + def key(self, value): + """Setter for key property.""" + self.logger.warn("Setting values on key will NOT update the remote Canvas instance.") + self._key = value + + @property + def title(self): + """A human readable title for the assessment.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + +class Result(BaseModel): + """Result Model. + A pass/fail results for a student""" + + def __init__(self, assessed_at=None, links=None, id=None, passed=None): + """Init method for Result class.""" + self._assessed_at = assessed_at + self._links = links + self._id = id + self._passed = passed + + self.logger = logging.getLogger('pycanvas.Result') + + @property + def assessed_at(self): + """When this result was recorded.""" + return self._assessed_at + + @assessed_at.setter + def assessed_at(self, value): + """Setter for assessed_at property.""" + self.logger.warn("Setting values on assessed_at will NOT update the remote Canvas instance.") + self._assessed_at = value + + @property + def links(self): + """Unique identifiers of objects associated with this result.""" + return self._links + + @links.setter + def links(self, value): + """Setter for links property.""" + self.logger.warn("Setting values on links will NOT update the remote Canvas instance.") + self._links = value + + @property + def id(self): + """A unique identifier for this result.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def passed(self): + """Whether the user passed or not.""" + return self._passed + + @passed.setter + def passed(self, value): + """Setter for passed property.""" + self.logger.warn("Setting values on passed will NOT update the remote Canvas instance.") + self._passed = value + + +class Resultlinks(BaseModel): + """Resultlinks Model. + Unique identifiers of objects associated with a result""" + + def __init__(self, assessment=None, user=None, assessor=None): + """Init method for Resultlinks class.""" + self._assessment = assessment + self._user = user + self._assessor = assessor + + self.logger = logging.getLogger('pycanvas.Resultlinks') + + @property + def assessment(self): + """A unique identifier for the assessment that this result is for.""" + return self._assessment + + @assessment.setter + def assessment(self, value): + """Setter for assessment property.""" + self.logger.warn("Setting values on assessment will NOT update the remote Canvas instance.") + self._assessment = value + + @property + def user(self): + """A unique identifier for the user to whom this result applies.""" + return self._user + + @user.setter + def user(self, value): + """Setter for user property.""" + self.logger.warn("Setting values on user will NOT update the remote Canvas instance.") + self._user = value + + @property + def assessor(self): + """A unique identifier for the user who created this result.""" + return self._assessor + + @assessor.setter + def assessor(self, value): + """Setter for assessor property.""" + self.logger.warn("Setting values on assessor will NOT update the remote Canvas instance.") + self._assessor = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/logins.py b/venv/Lib/site-packages/pycanvas/apis/logins.py new file mode 100644 index 00000000..f5ccce40 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/logins.py @@ -0,0 +1,171 @@ +"""Logins API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + +class LoginsAPI(BaseCanvasAPI): + """Logins API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for LoginsAPI.""" + super(LoginsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.LoginsAPI") + + def list_user_logins_accounts(self, account_id): + """ + List user logins. + + Given a user ID, return that user's logins for the given account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/logins with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/logins".format(**path), data=data, params=params, all_pages=True) + + def list_user_logins_users(self, user_id): + """ + List user logins. + + Given a user ID, return that user's logins for the given account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/logins with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/logins".format(**path), data=data, params=params, all_pages=True) + + def create_user_login(self, user_id, account_id, login_unique_id, login_authentication_provider_id=None, login_integration_id=None, login_password=None, login_sis_user_id=None): + """ + Create a user login. + + Create a new login for an existing user in the given account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - user[id] + """The ID of the user to create the login for.""" + data["user[id]"] = user_id + + # REQUIRED - login[unique_id] + """The unique ID for the new login.""" + data["login[unique_id]"] = login_unique_id + + # OPTIONAL - login[password] + """The new login's password.""" + if login_password is not None: + data["login[password]"] = login_password + + # OPTIONAL - login[sis_user_id] + """SIS ID for the login. To set this parameter, the caller must be able to + manage SIS permissions on the account.""" + if login_sis_user_id is not None: + data["login[sis_user_id]"] = login_sis_user_id + + # OPTIONAL - login[integration_id] + """Integration ID for the login. To set this parameter, the caller must be able to + manage SIS permissions on the account. The Integration ID is a secondary + identifier useful for more complex SIS integrations.""" + if login_integration_id is not None: + data["login[integration_id]"] = login_integration_id + + # OPTIONAL - login[authentication_provider_id] + """The authentication provider this login is associated with. Logins + associated with a specific provider can only be used with that provider. + Legacy providers (LDAP, CAS, SAML) will search for logins associated with + them, or unassociated logins. New providers will only search for logins + explicitly associated with them. This can be the integer ID of the + provider, or the type of the provider (in which case, it will find the + first matching provider).""" + if login_authentication_provider_id is not None: + data["login[authentication_provider_id]"] = login_authentication_provider_id + + self.logger.debug("POST /api/v1/accounts/{account_id}/logins with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/logins".format(**path), data=data, params=params, no_data=True) + + def edit_user_login(self, id, account_id, login_integration_id=None, login_password=None, login_sis_user_id=None, login_unique_id=None): + """ + Edit a user login. + + Update an existing login for a user in the given account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - login[unique_id] + """The new unique ID for the login.""" + if login_unique_id is not None: + data["login[unique_id]"] = login_unique_id + + # OPTIONAL - login[password] + """The new password for the login. Can only be set by an admin user if admins + are allowed to change passwords for the account.""" + if login_password is not None: + data["login[password]"] = login_password + + # OPTIONAL - login[sis_user_id] + """SIS ID for the login. To set this parameter, the caller must be able to + manage SIS permissions on the account.""" + if login_sis_user_id is not None: + data["login[sis_user_id]"] = login_sis_user_id + + # OPTIONAL - login[integration_id] + """Integration ID for the login. To set this parameter, the caller must be able to + manage SIS permissions on the account. The Integration ID is a secondary + identifier useful for more complex SIS integrations.""" + if login_integration_id is not None: + data["login[integration_id]"] = login_integration_id + + self.logger.debug("PUT /api/v1/accounts/{account_id}/logins/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/logins/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_user_login(self, id, user_id): + """ + Delete a user login. + + Delete an existing login. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/users/{user_id}/logins/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/{user_id}/logins/{id}".format(**path), data=data, params=params, no_data=True) + diff --git a/venv/Lib/site-packages/pycanvas/apis/modules.py b/venv/Lib/site-packages/pycanvas/apis/modules.py new file mode 100644 index 00000000..be47bb31 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/modules.py @@ -0,0 +1,1399 @@ +"""Modules API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class ModulesAPI(BaseCanvasAPI): + """Modules API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for ModulesAPI.""" + super(ModulesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.ModulesAPI") + + def list_modules(self, course_id, include=None, search_term=None, student_id=None): + """ + List modules. + + List the modules in a course + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - include + """- "items": Return module items inline if possible. + This parameter suggests that Canvas return module items directly + in the Module object JSON, to avoid having to make separate API + requests for each module when enumerating modules and items. Canvas + is free to omit 'items' for any particular module if it deems them + too numerous to return inline. Callers must be prepared to use the + {api:ContextModuleItemsApiController#index List Module Items API} + if items are not returned. + - "content_details": Requires include['items']. Returns additional + details with module items specific to their associated content items. + Includes standard lock information for each item.""" + if include is not None: + self._validate_enum(include, ["items", "content_details"]) + params["include"] = include + + # OPTIONAL - search_term + """The partial name of the modules (and module items, if include['items'] is + specified) to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - student_id + """Returns module completion information for the student with this id.""" + if student_id is not None: + params["student_id"] = student_id + + self.logger.debug("GET /api/v1/courses/{course_id}/modules with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/modules".format(**path), data=data, params=params, all_pages=True) + + def show_module(self, id, course_id, include=None, student_id=None): + """ + Show module. + + Get information about a single module + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """- "items": Return module items inline if possible. + This parameter suggests that Canvas return module items directly + in the Module object JSON, to avoid having to make separate API + requests for each module when enumerating modules and items. Canvas + is free to omit 'items' for any particular module if it deems them + too numerous to return inline. Callers must be prepared to use the + {api:ContextModuleItemsApiController#index List Module Items API} + if items are not returned. + - "content_details": Requires include['items']. Returns additional + details with module items specific to their associated content items. + Includes standard lock information for each item.""" + if include is not None: + self._validate_enum(include, ["items", "content_details"]) + params["include"] = include + + # OPTIONAL - student_id + """Returns module completion information for the student with this id.""" + if student_id is not None: + params["student_id"] = student_id + + self.logger.debug("GET /api/v1/courses/{course_id}/modules/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/modules/{id}".format(**path), data=data, params=params, single_item=True) + + def create_module(self, course_id, module_name, module_position=None, module_prerequisite_module_ids=None, module_publish_final_grade=None, module_require_sequential_progress=None, module_unlock_at=None): + """ + Create a module. + + Create and return a new module + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - module[name] + """The name of the module""" + data["module[name]"] = module_name + + # OPTIONAL - module[unlock_at] + """The date the module will unlock""" + if module_unlock_at is not None: + data["module[unlock_at]"] = module_unlock_at + + # OPTIONAL - module[position] + """The position of this module in the course (1-based)""" + if module_position is not None: + data["module[position]"] = module_position + + # OPTIONAL - module[require_sequential_progress] + """Whether module items must be unlocked in order""" + if module_require_sequential_progress is not None: + data["module[require_sequential_progress]"] = module_require_sequential_progress + + # OPTIONAL - module[prerequisite_module_ids] + """IDs of Modules that must be completed before this one is unlocked. + Prerequisite modules must precede this module (i.e. have a lower position + value), otherwise they will be ignored""" + if module_prerequisite_module_ids is not None: + data["module[prerequisite_module_ids]"] = module_prerequisite_module_ids + + # OPTIONAL - module[publish_final_grade] + """Whether to publish the student's final grade for the course upon + completion of this module.""" + if module_publish_final_grade is not None: + data["module[publish_final_grade]"] = module_publish_final_grade + + self.logger.debug("POST /api/v1/courses/{course_id}/modules with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/modules".format(**path), data=data, params=params, single_item=True) + + def update_module(self, id, course_id, module_name=None, module_position=None, module_prerequisite_module_ids=None, module_publish_final_grade=None, module_published=None, module_require_sequential_progress=None, module_unlock_at=None): + """ + Update a module. + + Update and return an existing module + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - module[name] + """The name of the module""" + if module_name is not None: + data["module[name]"] = module_name + + # OPTIONAL - module[unlock_at] + """The date the module will unlock""" + if module_unlock_at is not None: + data["module[unlock_at]"] = module_unlock_at + + # OPTIONAL - module[position] + """The position of the module in the course (1-based)""" + if module_position is not None: + data["module[position]"] = module_position + + # OPTIONAL - module[require_sequential_progress] + """Whether module items must be unlocked in order""" + if module_require_sequential_progress is not None: + data["module[require_sequential_progress]"] = module_require_sequential_progress + + # OPTIONAL - module[prerequisite_module_ids] + """IDs of Modules that must be completed before this one is unlocked + Prerequisite modules must precede this module (i.e. have a lower position + value), otherwise they will be ignored""" + if module_prerequisite_module_ids is not None: + data["module[prerequisite_module_ids]"] = module_prerequisite_module_ids + + # OPTIONAL - module[publish_final_grade] + """Whether to publish the student's final grade for the course upon + completion of this module.""" + if module_publish_final_grade is not None: + data["module[publish_final_grade]"] = module_publish_final_grade + + # OPTIONAL - module[published] + """Whether the module is published and visible to students""" + if module_published is not None: + data["module[published]"] = module_published + + self.logger.debug("PUT /api/v1/courses/{course_id}/modules/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/modules/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_module(self, id, course_id): + """ + Delete module. + + Delete a module + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/modules/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/modules/{id}".format(**path), data=data, params=params, single_item=True) + + def re_lock_module_progressions(self, id, course_id): + """ + Re-lock module progressions. + + Resets module progressions to their default locked state and + recalculates them based on the current requirements. + + Adding progression requirements to an active course will not lock students + out of modules they have already unlocked unless this action is called. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/courses/{course_id}/modules/{id}/relock with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/modules/{id}/relock".format(**path), data=data, params=params, single_item=True) + + def list_module_items(self, course_id, module_id, include=None, search_term=None, student_id=None): + """ + List module items. + + List the items in a module + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - module_id + """ID""" + path["module_id"] = module_id + + # OPTIONAL - include + """If included, will return additional details specific to the content + associated with each item. Refer to the {api:Modules:Module%20Item Module + Item specification} for more details. + Includes standard lock information for each item.""" + if include is not None: + self._validate_enum(include, ["content_details"]) + params["include"] = include + + # OPTIONAL - search_term + """The partial title of the items to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - student_id + """Returns module completion information for the student with this id.""" + if student_id is not None: + params["student_id"] = student_id + + self.logger.debug("GET /api/v1/courses/{course_id}/modules/{module_id}/items with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/modules/{module_id}/items".format(**path), data=data, params=params, all_pages=True) + + def show_module_item(self, id, course_id, module_id, include=None, student_id=None): + """ + Show module item. + + Get information about a single module item + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - module_id + """ID""" + path["module_id"] = module_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """If included, will return additional details specific to the content + associated with this item. Refer to the {api:Modules:Module%20Item Module + Item specification} for more details. + Includes standard lock information for each item.""" + if include is not None: + self._validate_enum(include, ["content_details"]) + params["include"] = include + + # OPTIONAL - student_id + """Returns module completion information for the student with this id.""" + if student_id is not None: + params["student_id"] = student_id + + self.logger.debug("GET /api/v1/courses/{course_id}/modules/{module_id}/items/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/modules/{module_id}/items/{id}".format(**path), data=data, params=params, single_item=True) + + def create_module_item(self, course_id, module_id, module_item_type, module_item_content_id, module_item_completion_requirement_min_score=None, module_item_completion_requirement_type=None, module_item_external_url=None, module_item_indent=None, module_item_new_tab=None, module_item_page_url=None, module_item_position=None, module_item_title=None): + """ + Create a module item. + + Create and return a new module item + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - module_id + """ID""" + path["module_id"] = module_id + + # OPTIONAL - module_item[title] + """The name of the module item and associated content""" + if module_item_title is not None: + data["module_item[title]"] = module_item_title + + # REQUIRED - module_item[type] + """The type of content linked to the item""" + self._validate_enum(module_item_type, ["File", "Page", "Discussion", "Assignment", "Quiz", "SubHeader", "ExternalUrl", "ExternalTool"]) + data["module_item[type]"] = module_item_type + + # REQUIRED - module_item[content_id] + """The id of the content to link to the module item. Required, except for + 'ExternalUrl', 'Page', and 'SubHeader' types.""" + data["module_item[content_id]"] = module_item_content_id + + # OPTIONAL - module_item[position] + """The position of this item in the module (1-based).""" + if module_item_position is not None: + data["module_item[position]"] = module_item_position + + # OPTIONAL - module_item[indent] + """0-based indent level; module items may be indented to show a hierarchy""" + if module_item_indent is not None: + data["module_item[indent]"] = module_item_indent + + # OPTIONAL - module_item[page_url] + """Suffix for the linked wiki page (e.g. 'front-page'). Required for 'Page' + type.""" + if module_item_page_url is not None: + data["module_item[page_url]"] = module_item_page_url + + # OPTIONAL - module_item[external_url] + """External url that the item points to. [Required for 'ExternalUrl' and + 'ExternalTool' types.""" + if module_item_external_url is not None: + data["module_item[external_url]"] = module_item_external_url + + # OPTIONAL - module_item[new_tab] + """Whether the external tool opens in a new tab. Only applies to + 'ExternalTool' type.""" + if module_item_new_tab is not None: + data["module_item[new_tab]"] = module_item_new_tab + + # OPTIONAL - module_item[completion_requirement][type] + """Completion requirement for this module item. + "must_view": Applies to all item types + "must_contribute": Only applies to "Assignment", "Discussion", and "Page" types + "must_submit", "min_score": Only apply to "Assignment" and "Quiz" types + Inapplicable types will be ignored""" + if module_item_completion_requirement_type is not None: + self._validate_enum(module_item_completion_requirement_type, ["must_view", "must_contribute", "must_submit"]) + data["module_item[completion_requirement][type]"] = module_item_completion_requirement_type + + # OPTIONAL - module_item[completion_requirement][min_score] + """Minimum score required to complete. Required for completion_requirement + type 'min_score'.""" + if module_item_completion_requirement_min_score is not None: + data["module_item[completion_requirement][min_score]"] = module_item_completion_requirement_min_score + + self.logger.debug("POST /api/v1/courses/{course_id}/modules/{module_id}/items with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/modules/{module_id}/items".format(**path), data=data, params=params, single_item=True) + + def update_module_item(self, id, course_id, module_id, module_item_completion_requirement_min_score=None, module_item_completion_requirement_type=None, module_item_external_url=None, module_item_indent=None, module_item_module_id=None, module_item_new_tab=None, module_item_position=None, module_item_published=None, module_item_title=None): + """ + Update a module item. + + Update and return an existing module item + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - module_id + """ID""" + path["module_id"] = module_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - module_item[title] + """The name of the module item""" + if module_item_title is not None: + data["module_item[title]"] = module_item_title + + # OPTIONAL - module_item[position] + """The position of this item in the module (1-based)""" + if module_item_position is not None: + data["module_item[position]"] = module_item_position + + # OPTIONAL - module_item[indent] + """0-based indent level; module items may be indented to show a hierarchy""" + if module_item_indent is not None: + data["module_item[indent]"] = module_item_indent + + # OPTIONAL - module_item[external_url] + """External url that the item points to. Only applies to 'ExternalUrl' type.""" + if module_item_external_url is not None: + data["module_item[external_url]"] = module_item_external_url + + # OPTIONAL - module_item[new_tab] + """Whether the external tool opens in a new tab. Only applies to + 'ExternalTool' type.""" + if module_item_new_tab is not None: + data["module_item[new_tab]"] = module_item_new_tab + + # OPTIONAL - module_item[completion_requirement][type] + """Completion requirement for this module item. + "must_view": Applies to all item types + "must_contribute": Only applies to "Assignment", "Discussion", and "Page" types + "must_submit", "min_score": Only apply to "Assignment" and "Quiz" types + Inapplicable types will be ignored""" + if module_item_completion_requirement_type is not None: + self._validate_enum(module_item_completion_requirement_type, ["must_view", "must_contribute", "must_submit"]) + data["module_item[completion_requirement][type]"] = module_item_completion_requirement_type + + # OPTIONAL - module_item[completion_requirement][min_score] + """Minimum score required to complete, Required for completion_requirement + type 'min_score'.""" + if module_item_completion_requirement_min_score is not None: + data["module_item[completion_requirement][min_score]"] = module_item_completion_requirement_min_score + + # OPTIONAL - module_item[published] + """Whether the module item is published and visible to students.""" + if module_item_published is not None: + data["module_item[published]"] = module_item_published + + # OPTIONAL - module_item[module_id] + """Move this item to another module by specifying the target module id here. + The target module must be in the same course.""" + if module_item_module_id is not None: + data["module_item[module_id]"] = module_item_module_id + + self.logger.debug("PUT /api/v1/courses/{course_id}/modules/{module_id}/items/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/modules/{module_id}/items/{id}".format(**path), data=data, params=params, single_item=True) + + def select_mastery_path(self, id, course_id, module_id, assignment_set_id=None, student_id=None): + """ + Select a mastery path. + + Select a mastery path when module item includes several possible paths. + Requires Mastery Paths feature to be enabled. Returns a compound document + with the assignments included in the given path and any module items + related to those assignments + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - module_id + """ID""" + path["module_id"] = module_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - assignment_set_id + """Assignment set chosen, as specified in the mastery_paths portion of the + context module item response""" + if assignment_set_id is not None: + data["assignment_set_id"] = assignment_set_id + + # OPTIONAL - student_id + """Which student the selection applies to. If not specified, current user is + implied.""" + if student_id is not None: + data["student_id"] = student_id + + self.logger.debug("POST /api/v1/courses/{course_id}/modules/{module_id}/items/{id}/select_mastery_path with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/modules/{module_id}/items/{id}/select_mastery_path".format(**path), data=data, params=params, no_data=True) + + def delete_module_item(self, id, course_id, module_id): + """ + Delete module item. + + Delete a module item + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - module_id + """ID""" + path["module_id"] = module_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/modules/{module_id}/items/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/modules/{module_id}/items/{id}".format(**path), data=data, params=params, single_item=True) + + def mark_module_item_as_done_not_done(self, id, course_id, module_id): + """ + Mark module item as done/not done. + + Mark a module item as done/not done. Use HTTP method PUT to mark as done, + and DELETE to mark as not done. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - module_id + """ID""" + path["module_id"] = module_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/courses/{course_id}/modules/{module_id}/items/{id}/done with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/modules/{module_id}/items/{id}/done".format(**path), data=data, params=params, no_data=True) + + def get_module_item_sequence(self, course_id, asset_id=None, asset_type=None): + """ + Get module item sequence. + + Given an asset in a course, find the ModuleItem it belongs to, and also the previous and next Module Items + in the course sequence. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - asset_type + """The type of asset to find module sequence information for. Use the ModuleItem if it is known + (e.g., the user navigated from a module item), since this will avoid ambiguity if the asset + appears more than once in the module sequence.""" + if asset_type is not None: + self._validate_enum(asset_type, ["ModuleItem", "File", "Page", "Discussion", "Assignment", "Quiz", "ExternalTool"]) + params["asset_type"] = asset_type + + # OPTIONAL - asset_id + """The id of the asset (or the url in the case of a Page)""" + if asset_id is not None: + params["asset_id"] = asset_id + + self.logger.debug("GET /api/v1/courses/{course_id}/module_item_sequence with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/module_item_sequence".format(**path), data=data, params=params, single_item=True) + + def mark_module_item_read(self, id, course_id, module_id): + """ + Mark module item read. + + Fulfills "must view" requirement for a module item. It is generally not necessary to do this explicitly, + but it is provided for applications that need to access external content directly (bypassing the html_url + redirect that normally allows Canvas to fulfill "must view" requirements). + + This endpoint cannot be used to complete requirements on locked or unpublished module items. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - module_id + """ID""" + path["module_id"] = module_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("POST /api/v1/courses/{course_id}/modules/{module_id}/items/{id}/mark_read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/modules/{module_id}/items/{id}/mark_read".format(**path), data=data, params=params, no_data=True) + + +class Contentdetails(BaseModel): + """Contentdetails Model.""" + + def __init__(self, unlock_at=None, due_at=None, points_possible=None, lock_info=None, lock_at=None, lock_explanation=None, locked_for_user=None): + """Init method for Contentdetails class.""" + self._unlock_at = unlock_at + self._due_at = due_at + self._points_possible = points_possible + self._lock_info = lock_info + self._lock_at = lock_at + self._lock_explanation = lock_explanation + self._locked_for_user = locked_for_user + + self.logger = logging.getLogger('pycanvas.Contentdetails') + + @property + def unlock_at(self): + """unlock_at.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def due_at(self): + """due_at.""" + return self._due_at + + @due_at.setter + def due_at(self, value): + """Setter for due_at property.""" + self.logger.warn("Setting values on due_at will NOT update the remote Canvas instance.") + self._due_at = value + + @property + def points_possible(self): + """points_possible.""" + return self._points_possible + + @points_possible.setter + def points_possible(self, value): + """Setter for points_possible property.""" + self.logger.warn("Setting values on points_possible will NOT update the remote Canvas instance.") + self._points_possible = value + + @property + def lock_info(self): + """lock_info.""" + return self._lock_info + + @lock_info.setter + def lock_info(self, value): + """Setter for lock_info property.""" + self.logger.warn("Setting values on lock_info will NOT update the remote Canvas instance.") + self._lock_info = value + + @property + def lock_at(self): + """lock_at.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def lock_explanation(self): + """lock_explanation.""" + return self._lock_explanation + + @lock_explanation.setter + def lock_explanation(self, value): + """Setter for lock_explanation property.""" + self.logger.warn("Setting values on lock_explanation will NOT update the remote Canvas instance.") + self._lock_explanation = value + + @property + def locked_for_user(self): + """locked_for_user.""" + return self._locked_for_user + + @locked_for_user.setter + def locked_for_user(self, value): + """Setter for locked_for_user property.""" + self.logger.warn("Setting values on locked_for_user will NOT update the remote Canvas instance.") + self._locked_for_user = value + + +class Moduleitemsequenceasset(BaseModel): + """Moduleitemsequenceasset Model.""" + + def __init__(self, module_id=None, type=None, id=None, title=None): + """Init method for Moduleitemsequenceasset class.""" + self._module_id = module_id + self._type = type + self._id = id + self._title = title + + self.logger = logging.getLogger('pycanvas.Moduleitemsequenceasset') + + @property + def module_id(self): + """module_id.""" + return self._module_id + + @module_id.setter + def module_id(self, value): + """Setter for module_id property.""" + self.logger.warn("Setting values on module_id will NOT update the remote Canvas instance.") + self._module_id = value + + @property + def type(self): + """type.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def id(self): + """id.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def title(self): + """title.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + +class Moduleitemcompletionrequirement(BaseModel): + """Moduleitemcompletionrequirement Model.""" + + def __init__(self, min_score=None, type=None, completed=None): + """Init method for Moduleitemcompletionrequirement class.""" + self._min_score = min_score + self._type = type + self._completed = completed + + self.logger = logging.getLogger('pycanvas.Moduleitemcompletionrequirement') + + @property + def min_score(self): + """min_score.""" + return self._min_score + + @min_score.setter + def min_score(self, value): + """Setter for min_score property.""" + self.logger.warn("Setting values on min_score will NOT update the remote Canvas instance.") + self._min_score = value + + @property + def type(self): + """type.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def completed(self): + """completed.""" + return self._completed + + @completed.setter + def completed(self, value): + """Setter for completed property.""" + self.logger.warn("Setting values on completed will NOT update the remote Canvas instance.") + self._completed = value + + +class Module(BaseModel): + """Module Model.""" + + def __init__(self, completed_at=None, items_count=None, unlock_at=None, workflow_state=None, items=None, prerequisite_module_ids=None, state=None, publish_final_grade=None, position=None, items_url=None, id=None, require_sequential_progress=None, name=None): + """Init method for Module class.""" + self._completed_at = completed_at + self._items_count = items_count + self._unlock_at = unlock_at + self._workflow_state = workflow_state + self._items = items + self._prerequisite_module_ids = prerequisite_module_ids + self._state = state + self._publish_final_grade = publish_final_grade + self._position = position + self._items_url = items_url + self._id = id + self._require_sequential_progress = require_sequential_progress + self._name = name + + self.logger = logging.getLogger('pycanvas.Module') + + @property + def completed_at(self): + """the date the calling user completed the module (Optional; present only if the caller is a student or if the optional parameter 'student_id' is included).""" + return self._completed_at + + @completed_at.setter + def completed_at(self, value): + """Setter for completed_at property.""" + self.logger.warn("Setting values on completed_at will NOT update the remote Canvas instance.") + self._completed_at = value + + @property + def items_count(self): + """The number of items in the module.""" + return self._items_count + + @items_count.setter + def items_count(self, value): + """Setter for items_count property.""" + self.logger.warn("Setting values on items_count will NOT update the remote Canvas instance.") + self._items_count = value + + @property + def unlock_at(self): + """(Optional) the date this module will unlock.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def workflow_state(self): + """the state of the module: 'active', 'deleted'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def items(self): + """The contents of this module, as an array of Module Items. (Present only if requested via include[]=items AND the module is not deemed too large by Canvas.).""" + return self._items + + @items.setter + def items(self, value): + """Setter for items property.""" + self.logger.warn("Setting values on items will NOT update the remote Canvas instance.") + self._items = value + + @property + def prerequisite_module_ids(self): + """IDs of Modules that must be completed before this one is unlocked.""" + return self._prerequisite_module_ids + + @prerequisite_module_ids.setter + def prerequisite_module_ids(self, value): + """Setter for prerequisite_module_ids property.""" + self.logger.warn("Setting values on prerequisite_module_ids will NOT update the remote Canvas instance.") + self._prerequisite_module_ids = value + + @property + def state(self): + """The state of this Module for the calling user one of 'locked', 'unlocked', 'started', 'completed' (Optional; present only if the caller is a student or if the optional parameter 'student_id' is included).""" + return self._state + + @state.setter + def state(self, value): + """Setter for state property.""" + self.logger.warn("Setting values on state will NOT update the remote Canvas instance.") + self._state = value + + @property + def publish_final_grade(self): + """if the student's final grade for the course should be published to the SIS upon completion of this module.""" + return self._publish_final_grade + + @publish_final_grade.setter + def publish_final_grade(self, value): + """Setter for publish_final_grade property.""" + self.logger.warn("Setting values on publish_final_grade will NOT update the remote Canvas instance.") + self._publish_final_grade = value + + @property + def position(self): + """the position of this module in the course (1-based).""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def items_url(self): + """The API URL to retrive this module's items.""" + return self._items_url + + @items_url.setter + def items_url(self, value): + """Setter for items_url property.""" + self.logger.warn("Setting values on items_url will NOT update the remote Canvas instance.") + self._items_url = value + + @property + def id(self): + """the unique identifier for the module.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def require_sequential_progress(self): + """Whether module items must be unlocked in order.""" + return self._require_sequential_progress + + @require_sequential_progress.setter + def require_sequential_progress(self, value): + """Setter for require_sequential_progress property.""" + self.logger.warn("Setting values on require_sequential_progress will NOT update the remote Canvas instance.") + self._require_sequential_progress = value + + @property + def name(self): + """the name of this module.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class Moduleitemsequence(BaseModel): + """Moduleitemsequence Model.""" + + def __init__(self, items=None, modules=None): + """Init method for Moduleitemsequence class.""" + self._items = items + self._modules = modules + + self.logger = logging.getLogger('pycanvas.Moduleitemsequence') + + @property + def items(self): + """an array containing one hash for each appearence of the asset in the module sequence (up to 10 total).""" + return self._items + + @items.setter + def items(self, value): + """Setter for items property.""" + self.logger.warn("Setting values on items will NOT update the remote Canvas instance.") + self._items = value + + @property + def modules(self): + """an array containing each Module referenced above.""" + return self._modules + + @modules.setter + def modules(self, value): + """Setter for modules property.""" + self.logger.warn("Setting values on modules will NOT update the remote Canvas instance.") + self._modules = value + + +class Completionrequirement(BaseModel): + """Completionrequirement Model.""" + + def __init__(self, min_score=None, type=None, completed=None): + """Init method for Completionrequirement class.""" + self._min_score = min_score + self._type = type + self._completed = completed + + self.logger = logging.getLogger('pycanvas.Completionrequirement') + + @property + def min_score(self): + """minimum score required to complete (only present when type == 'min_score').""" + return self._min_score + + @min_score.setter + def min_score(self, value): + """Setter for min_score property.""" + self.logger.warn("Setting values on min_score will NOT update the remote Canvas instance.") + self._min_score = value + + @property + def type(self): + """one of 'must_view', 'must_submit', 'must_contribute', 'min_score'.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def completed(self): + """whether the calling user has met this requirement (Optional; present only if the caller is a student or if the optional parameter 'student_id' is included).""" + return self._completed + + @completed.setter + def completed(self, value): + """Setter for completed property.""" + self.logger.warn("Setting values on completed will NOT update the remote Canvas instance.") + self._completed = value + + +class Moduleitem(BaseModel): + """Moduleitem Model.""" + + def __init__(self, indent=None, title=None, url=None, completion_requirement=None, html_url=None, content_details=None, new_tab=None, external_url=None, position=None, module_id=None, content_id=None, type=None, id=None, page_url=None): + """Init method for Moduleitem class.""" + self._indent = indent + self._title = title + self._url = url + self._completion_requirement = completion_requirement + self._html_url = html_url + self._content_details = content_details + self._new_tab = new_tab + self._external_url = external_url + self._position = position + self._module_id = module_id + self._content_id = content_id + self._type = type + self._id = id + self._page_url = page_url + + self.logger = logging.getLogger('pycanvas.Moduleitem') + + @property + def indent(self): + """0-based indent level; module items may be indented to show a hierarchy.""" + return self._indent + + @indent.setter + def indent(self, value): + """Setter for indent property.""" + self.logger.warn("Setting values on indent will NOT update the remote Canvas instance.") + self._indent = value + + @property + def title(self): + """the title of this item.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def url(self): + """(Optional) link to the Canvas API object, if applicable.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def completion_requirement(self): + """Completion requirement for this module item.""" + return self._completion_requirement + + @completion_requirement.setter + def completion_requirement(self, value): + """Setter for completion_requirement property.""" + self.logger.warn("Setting values on completion_requirement will NOT update the remote Canvas instance.") + self._completion_requirement = value + + @property + def html_url(self): + """link to the item in Canvas.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def content_details(self): + """(Present only if requested through include[]=content_details) If applicable, returns additional details specific to the associated object.""" + return self._content_details + + @content_details.setter + def content_details(self, value): + """Setter for content_details property.""" + self.logger.warn("Setting values on content_details will NOT update the remote Canvas instance.") + self._content_details = value + + @property + def new_tab(self): + """(only for 'ExternalTool' type) whether the external tool opens in a new tab.""" + return self._new_tab + + @new_tab.setter + def new_tab(self, value): + """Setter for new_tab property.""" + self.logger.warn("Setting values on new_tab will NOT update the remote Canvas instance.") + self._new_tab = value + + @property + def external_url(self): + """(only for 'ExternalUrl' and 'ExternalTool' types) external url that the item points to.""" + return self._external_url + + @external_url.setter + def external_url(self, value): + """Setter for external_url property.""" + self.logger.warn("Setting values on external_url will NOT update the remote Canvas instance.") + self._external_url = value + + @property + def position(self): + """the position of this item in the module (1-based).""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def module_id(self): + """the id of the Module this item appears in.""" + return self._module_id + + @module_id.setter + def module_id(self, value): + """Setter for module_id property.""" + self.logger.warn("Setting values on module_id will NOT update the remote Canvas instance.") + self._module_id = value + + @property + def content_id(self): + """the id of the object referred to applies to 'File', 'Discussion', 'Assignment', 'Quiz', 'ExternalTool' types.""" + return self._content_id + + @content_id.setter + def content_id(self, value): + """Setter for content_id property.""" + self.logger.warn("Setting values on content_id will NOT update the remote Canvas instance.") + self._content_id = value + + @property + def type(self): + """the type of object referred to one of 'File', 'Page', 'Discussion', 'Assignment', 'Quiz', 'SubHeader', 'ExternalUrl', 'ExternalTool'.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def id(self): + """the unique identifier for the module item.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def page_url(self): + """(only for 'Page' type) unique locator for the linked wiki page.""" + return self._page_url + + @page_url.setter + def page_url(self, value): + """Setter for page_url property.""" + self.logger.warn("Setting values on page_url will NOT update the remote Canvas instance.") + self._page_url = value + + +class Moduleitemsequencenode(BaseModel): + """Moduleitemsequencenode Model.""" + + def __init__(self, current=None, prev=None, next=None): + """Init method for Moduleitemsequencenode class.""" + self._current = current + self._prev = prev + self._next = next + + self.logger = logging.getLogger('pycanvas.Moduleitemsequencenode') + + @property + def current(self): + """current.""" + return self._current + + @current.setter + def current(self, value): + """Setter for current property.""" + self.logger.warn("Setting values on current will NOT update the remote Canvas instance.") + self._current = value + + @property + def prev(self): + """prev.""" + return self._prev + + @prev.setter + def prev(self, value): + """Setter for prev property.""" + self.logger.warn("Setting values on prev will NOT update the remote Canvas instance.") + self._prev = value + + @property + def next(self): + """next.""" + return self._next + + @next.setter + def next(self, value): + """Setter for next property.""" + self.logger.warn("Setting values on next will NOT update the remote Canvas instance.") + self._next = value + + +class Moduleitemcontentdetails(BaseModel): + """Moduleitemcontentdetails Model.""" + + def __init__(self, unlock_at=None, due_at=None, points_possible=None, lock_info=None, lock_at=None, lock_explanation=None, locked_for_user=None): + """Init method for Moduleitemcontentdetails class.""" + self._unlock_at = unlock_at + self._due_at = due_at + self._points_possible = points_possible + self._lock_info = lock_info + self._lock_at = lock_at + self._lock_explanation = lock_explanation + self._locked_for_user = locked_for_user + + self.logger = logging.getLogger('pycanvas.Moduleitemcontentdetails') + + @property + def unlock_at(self): + """unlock_at.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def due_at(self): + """due_at.""" + return self._due_at + + @due_at.setter + def due_at(self, value): + """Setter for due_at property.""" + self.logger.warn("Setting values on due_at will NOT update the remote Canvas instance.") + self._due_at = value + + @property + def points_possible(self): + """points_possible.""" + return self._points_possible + + @points_possible.setter + def points_possible(self, value): + """Setter for points_possible property.""" + self.logger.warn("Setting values on points_possible will NOT update the remote Canvas instance.") + self._points_possible = value + + @property + def lock_info(self): + """lock_info.""" + return self._lock_info + + @lock_info.setter + def lock_info(self, value): + """Setter for lock_info property.""" + self.logger.warn("Setting values on lock_info will NOT update the remote Canvas instance.") + self._lock_info = value + + @property + def lock_at(self): + """lock_at.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def lock_explanation(self): + """lock_explanation.""" + return self._lock_explanation + + @lock_explanation.setter + def lock_explanation(self, value): + """Setter for lock_explanation property.""" + self.logger.warn("Setting values on lock_explanation will NOT update the remote Canvas instance.") + self._lock_explanation = value + + @property + def locked_for_user(self): + """locked_for_user.""" + return self._locked_for_user + + @locked_for_user.setter + def locked_for_user(self, value): + """Setter for locked_for_user property.""" + self.logger.warn("Setting values on locked_for_user will NOT update the remote Canvas instance.") + self._locked_for_user = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/notification_preferences.py b/venv/Lib/site-packages/pycanvas/apis/notification_preferences.py new file mode 100644 index 00000000..fd385fbb --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/notification_preferences.py @@ -0,0 +1,321 @@ +"""NotificationPreferences API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class NotificationPreferencesAPI(BaseCanvasAPI): + """NotificationPreferences API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for NotificationPreferencesAPI.""" + super(NotificationPreferencesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.NotificationPreferencesAPI") + + def list_preferences_communication_channel_id(self, user_id, communication_channel_id): + """ + List preferences. + + Fetch all preferences for the given communication channel + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - communication_channel_id + """ID""" + path["communication_channel_id"] = communication_channel_id + + self.logger.debug("GET /api/v1/users/{user_id}/communication_channels/{communication_channel_id}/notification_preferences with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/communication_channels/{communication_channel_id}/notification_preferences".format(**path), data=data, params=params, all_pages=True) + + def list_preferences_type(self, type, user_id, address): + """ + List preferences. + + Fetch all preferences for the given communication channel + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - type + """ID""" + path["type"] = type + + # REQUIRED - PATH - address + """ID""" + path["address"] = address + + self.logger.debug("GET /api/v1/users/{user_id}/communication_channels/{type}/{address}/notification_preferences with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/communication_channels/{type}/{address}/notification_preferences".format(**path), data=data, params=params, all_pages=True) + + def list_of_preference_categories(self, user_id, communication_channel_id): + """ + List of preference categories. + + Fetch all notification preference categories for the given communication channel + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - communication_channel_id + """ID""" + path["communication_channel_id"] = communication_channel_id + + self.logger.debug("GET /api/v1/users/{user_id}/communication_channels/{communication_channel_id}/notification_preference_categories with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/communication_channels/{communication_channel_id}/notification_preference_categories".format(**path), data=data, params=params, all_pages=True) + + def get_preference_communication_channel_id(self, user_id, notification, communication_channel_id): + """ + Get a preference. + + Fetch the preference for the given notification for the given communicaiton channel + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - communication_channel_id + """ID""" + path["communication_channel_id"] = communication_channel_id + + # REQUIRED - PATH - notification + """ID""" + path["notification"] = notification + + self.logger.debug("GET /api/v1/users/{user_id}/communication_channels/{communication_channel_id}/notification_preferences/{notification} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/communication_channels/{communication_channel_id}/notification_preferences/{notification}".format(**path), data=data, params=params, single_item=True) + + def get_preference_type(self, type, user_id, address, notification): + """ + Get a preference. + + Fetch the preference for the given notification for the given communicaiton channel + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - type + """ID""" + path["type"] = type + + # REQUIRED - PATH - address + """ID""" + path["address"] = address + + # REQUIRED - PATH - notification + """ID""" + path["notification"] = notification + + self.logger.debug("GET /api/v1/users/{user_id}/communication_channels/{type}/{address}/notification_preferences/{notification} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/communication_channels/{type}/{address}/notification_preferences/{notification}".format(**path), data=data, params=params, single_item=True) + + def update_preference_communication_channel_id(self, notification, communication_channel_id, notification_preferences_frequency): + """ + Update a preference. + + Change the preference for a single notification for a single communication channel + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - communication_channel_id + """ID""" + path["communication_channel_id"] = communication_channel_id + + # REQUIRED - PATH - notification + """ID""" + path["notification"] = notification + + # REQUIRED - notification_preferences[frequency] + """The desired frequency for this notification""" + data["notification_preferences[frequency]"] = notification_preferences_frequency + + self.logger.debug("PUT /api/v1/users/self/communication_channels/{communication_channel_id}/notification_preferences/{notification} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/self/communication_channels/{communication_channel_id}/notification_preferences/{notification}".format(**path), data=data, params=params, no_data=True) + + def update_preference_type(self, type, address, notification, notification_preferences_frequency): + """ + Update a preference. + + Change the preference for a single notification for a single communication channel + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - type + """ID""" + path["type"] = type + + # REQUIRED - PATH - address + """ID""" + path["address"] = address + + # REQUIRED - PATH - notification + """ID""" + path["notification"] = notification + + # REQUIRED - notification_preferences[frequency] + """The desired frequency for this notification""" + data["notification_preferences[frequency]"] = notification_preferences_frequency + + self.logger.debug("PUT /api/v1/users/self/communication_channels/{type}/{address}/notification_preferences/{notification} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/self/communication_channels/{type}/{address}/notification_preferences/{notification}".format(**path), data=data, params=params, no_data=True) + + def update_preferences_by_category(self, category, communication_channel_id, notification_preferences_frequency): + """ + Update preferences by category. + + Change the preferences for multiple notifications based on the category for a single communication channel + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - communication_channel_id + """ID""" + path["communication_channel_id"] = communication_channel_id + + # REQUIRED - PATH - category + """The name of the category. Must be parameterized (e.g. The category "Course Content" should be "course_content")""" + path["category"] = category + + # REQUIRED - notification_preferences[frequency] + """The desired frequency for each notification in the category""" + data["notification_preferences[frequency]"] = notification_preferences_frequency + + self.logger.debug("PUT /api/v1/users/self/communication_channels/{communication_channel_id}/notification_preference_categories/{category} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/self/communication_channels/{communication_channel_id}/notification_preference_categories/{category}".format(**path), data=data, params=params, no_data=True) + + def update_multiple_preferences_communication_channel_id(self, communication_channel_id, notification_preferences__frequency): + """ + Update multiple preferences. + + Change the preferences for multiple notifications for a single communication channel at once + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - communication_channel_id + """ID""" + path["communication_channel_id"] = communication_channel_id + + # REQUIRED - notification_preferences[][frequency] + """The desired frequency for notification""" + data["notification_preferences[][frequency]"] = notification_preferences__frequency + + self.logger.debug("PUT /api/v1/users/self/communication_channels/{communication_channel_id}/notification_preferences with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/self/communication_channels/{communication_channel_id}/notification_preferences".format(**path), data=data, params=params, no_data=True) + + def update_multiple_preferences_type(self, type, address, notification_preferences__frequency): + """ + Update multiple preferences. + + Change the preferences for multiple notifications for a single communication channel at once + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - type + """ID""" + path["type"] = type + + # REQUIRED - PATH - address + """ID""" + path["address"] = address + + # REQUIRED - notification_preferences[][frequency] + """The desired frequency for notification""" + data["notification_preferences[][frequency]"] = notification_preferences__frequency + + self.logger.debug("PUT /api/v1/users/self/communication_channels/{type}/{address}/notification_preferences with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/self/communication_channels/{type}/{address}/notification_preferences".format(**path), data=data, params=params, no_data=True) + + +class Notificationpreference(BaseModel): + """Notificationpreference Model.""" + + def __init__(self, category=None, notification=None, href=None, frequency=None): + """Init method for Notificationpreference class.""" + self._category = category + self._notification = notification + self._href = href + self._frequency = frequency + + self.logger = logging.getLogger('pycanvas.Notificationpreference') + + @property + def category(self): + """The category of that notification.""" + return self._category + + @category.setter + def category(self, value): + """Setter for category property.""" + self.logger.warn("Setting values on category will NOT update the remote Canvas instance.") + self._category = value + + @property + def notification(self): + """The notification this preference belongs to.""" + return self._notification + + @notification.setter + def notification(self, value): + """Setter for notification property.""" + self.logger.warn("Setting values on notification will NOT update the remote Canvas instance.") + self._notification = value + + @property + def href(self): + """href.""" + return self._href + + @href.setter + def href(self, value): + """Setter for href property.""" + self.logger.warn("Setting values on href will NOT update the remote Canvas instance.") + self._href = value + + @property + def frequency(self): + """How often to send notifications to this communication channel for the given notification. Possible values are 'immediately', 'daily', 'weekly', and 'never'.""" + return self._frequency + + @frequency.setter + def frequency(self, value): + """Setter for frequency property.""" + self.logger.warn("Setting values on frequency will NOT update the remote Canvas instance.") + self._frequency = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/outcome_groups.py b/venv/Lib/site-packages/pycanvas/apis/outcome_groups.py new file mode 100644 index 00000000..2cec83e6 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/outcome_groups.py @@ -0,0 +1,1653 @@ +"""OutcomeGroups API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class OutcomeGroupsAPI(BaseCanvasAPI): + """OutcomeGroups API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for OutcomeGroupsAPI.""" + super(OutcomeGroupsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.OutcomeGroupsAPI") + + def redirect_to_root_outcome_group_for_context_global(self): + """ + Redirect to root outcome group for context. + + Convenience redirect to find the root outcome group for a particular + context. Will redirect to the appropriate outcome group's URL. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/global/root_outcome_group with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/global/root_outcome_group".format(**path), data=data, params=params, no_data=True) + + def redirect_to_root_outcome_group_for_context_accounts(self, account_id): + """ + Redirect to root outcome group for context. + + Convenience redirect to find the root outcome group for a particular + context. Will redirect to the appropriate outcome group's URL. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/root_outcome_group with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/root_outcome_group".format(**path), data=data, params=params, no_data=True) + + def redirect_to_root_outcome_group_for_context_courses(self, course_id): + """ + Redirect to root outcome group for context. + + Convenience redirect to find the root outcome group for a particular + context. Will redirect to the appropriate outcome group's URL. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/root_outcome_group with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/root_outcome_group".format(**path), data=data, params=params, no_data=True) + + def get_all_outcome_groups_for_context_accounts(self, account_id): + """ + Get all outcome groups for context. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("GET /api/v1/accounts/{account_id}/outcome_groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/outcome_groups".format(**path), data=data, params=params, all_pages=True) + + def get_all_outcome_groups_for_context_courses(self, course_id): + """ + Get all outcome groups for context. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/outcome_groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/outcome_groups".format(**path), data=data, params=params, all_pages=True) + + def get_all_outcome_links_for_context_accounts(self, account_id, outcome_group_style=None, outcome_style=None): + """ + Get all outcome links for context. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - outcome_style + """The detail level of the outcomes. Defaults to "abbrev". + Specify "full" for more information.""" + if outcome_style is not None: + params["outcome_style"] = outcome_style + + # OPTIONAL - outcome_group_style + """The detail level of the outcome groups. Defaults to "abbrev". + Specify "full" for more information.""" + if outcome_group_style is not None: + params["outcome_group_style"] = outcome_group_style + + self.logger.debug("GET /api/v1/accounts/{account_id}/outcome_group_links with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/outcome_group_links".format(**path), data=data, params=params, all_pages=True) + + def get_all_outcome_links_for_context_courses(self, course_id, outcome_group_style=None, outcome_style=None): + """ + Get all outcome links for context. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - outcome_style + """The detail level of the outcomes. Defaults to "abbrev". + Specify "full" for more information.""" + if outcome_style is not None: + params["outcome_style"] = outcome_style + + # OPTIONAL - outcome_group_style + """The detail level of the outcome groups. Defaults to "abbrev". + Specify "full" for more information.""" + if outcome_group_style is not None: + params["outcome_group_style"] = outcome_group_style + + self.logger.debug("GET /api/v1/courses/{course_id}/outcome_group_links with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/outcome_group_links".format(**path), data=data, params=params, all_pages=True) + + def show_outcome_group_global(self, id): + """ + Show an outcome group. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/global/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/global/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def show_outcome_group_accounts(self, id, account_id): + """ + Show an outcome group. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{account_id}/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def show_outcome_group_courses(self, id, course_id): + """ + Show an outcome group. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def update_outcome_group_global(self, id, description=None, parent_outcome_group_id=None, title=None, vendor_guid=None): + """ + Update an outcome group. + + Modify an existing outcome group. Fields not provided are left as is; + unrecognized fields are ignored. + + When changing the parent outcome group, the new parent group must belong to + the same context as this outcome group, and must not be a descendant of + this outcome group (i.e. no cycles allowed). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - title + """The new outcome group title.""" + if title is not None: + data["title"] = title + + # OPTIONAL - description + """The new outcome group description.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - parent_outcome_group_id + """The id of the new parent outcome group.""" + if parent_outcome_group_id is not None: + data["parent_outcome_group_id"] = parent_outcome_group_id + + self.logger.debug("PUT /api/v1/global/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/global/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def update_outcome_group_accounts(self, id, account_id, description=None, parent_outcome_group_id=None, title=None, vendor_guid=None): + """ + Update an outcome group. + + Modify an existing outcome group. Fields not provided are left as is; + unrecognized fields are ignored. + + When changing the parent outcome group, the new parent group must belong to + the same context as this outcome group, and must not be a descendant of + this outcome group (i.e. no cycles allowed). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - title + """The new outcome group title.""" + if title is not None: + data["title"] = title + + # OPTIONAL - description + """The new outcome group description.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - parent_outcome_group_id + """The id of the new parent outcome group.""" + if parent_outcome_group_id is not None: + data["parent_outcome_group_id"] = parent_outcome_group_id + + self.logger.debug("PUT /api/v1/accounts/{account_id}/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def update_outcome_group_courses(self, id, course_id, description=None, parent_outcome_group_id=None, title=None, vendor_guid=None): + """ + Update an outcome group. + + Modify an existing outcome group. Fields not provided are left as is; + unrecognized fields are ignored. + + When changing the parent outcome group, the new parent group must belong to + the same context as this outcome group, and must not be a descendant of + this outcome group (i.e. no cycles allowed). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - title + """The new outcome group title.""" + if title is not None: + data["title"] = title + + # OPTIONAL - description + """The new outcome group description.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - parent_outcome_group_id + """The id of the new parent outcome group.""" + if parent_outcome_group_id is not None: + data["parent_outcome_group_id"] = parent_outcome_group_id + + self.logger.debug("PUT /api/v1/courses/{course_id}/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_outcome_group_global(self, id): + """ + Delete an outcome group. + + Deleting an outcome group deletes descendant outcome groups and outcome + links. The linked outcomes themselves are only deleted if all links to the + outcome were deleted. + + Aligned outcomes cannot be deleted; as such, if all remaining links to an + aligned outcome are included in this group's descendants, the group + deletion will fail. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/global/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/global/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_outcome_group_accounts(self, id, account_id): + """ + Delete an outcome group. + + Deleting an outcome group deletes descendant outcome groups and outcome + links. The linked outcomes themselves are only deleted if all links to the + outcome were deleted. + + Aligned outcomes cannot be deleted; as such, if all remaining links to an + aligned outcome are included in this group's descendants, the group + deletion will fail. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_outcome_group_courses(self, id, course_id): + """ + Delete an outcome group. + + Deleting an outcome group deletes descendant outcome groups and outcome + links. The linked outcomes themselves are only deleted if all links to the + outcome were deleted. + + Aligned outcomes cannot be deleted; as such, if all remaining links to an + aligned outcome are included in this group's descendants, the group + deletion will fail. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/outcome_groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/outcome_groups/{id}".format(**path), data=data, params=params, single_item=True) + + def list_linked_outcomes_global(self, id, outcome_style=None): + """ + List linked outcomes. + + List the immediate OutcomeLink children of the outcome group. Paginated. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - outcome_style + """The detail level of the outcomes. Defaults to "abbrev". + Specify "full" for more information.""" + if outcome_style is not None: + params["outcome_style"] = outcome_style + + self.logger.debug("GET /api/v1/global/outcome_groups/{id}/outcomes with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/global/outcome_groups/{id}/outcomes".format(**path), data=data, params=params, all_pages=True) + + def list_linked_outcomes_accounts(self, id, account_id, outcome_style=None): + """ + List linked outcomes. + + List the immediate OutcomeLink children of the outcome group. Paginated. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - outcome_style + """The detail level of the outcomes. Defaults to "abbrev". + Specify "full" for more information.""" + if outcome_style is not None: + params["outcome_style"] = outcome_style + + self.logger.debug("GET /api/v1/accounts/{account_id}/outcome_groups/{id}/outcomes with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/outcome_groups/{id}/outcomes".format(**path), data=data, params=params, all_pages=True) + + def list_linked_outcomes_courses(self, id, course_id, outcome_style=None): + """ + List linked outcomes. + + List the immediate OutcomeLink children of the outcome group. Paginated. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - outcome_style + """The detail level of the outcomes. Defaults to "abbrev". + Specify "full" for more information.""" + if outcome_style is not None: + params["outcome_style"] = outcome_style + + self.logger.debug("GET /api/v1/courses/{course_id}/outcome_groups/{id}/outcomes with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/outcome_groups/{id}/outcomes".format(**path), data=data, params=params, all_pages=True) + + def create_link_outcome_global(self, id, calculation_int=None, calculation_method=None, description=None, display_name=None, mastery_points=None, outcome_id=None, ratings_description=None, ratings_points=None, title=None, vendor_guid=None): + """ + Create/link an outcome. + + Link an outcome into the outcome group. The outcome to link can either be + specified by a PUT to the link URL for a specific outcome (the outcome_id + in the PUT URLs) or by supplying the information for a new outcome (title, + description, ratings, mastery_points) in a POST to the collection. + + If linking an existing outcome, the outcome_id must identify an outcome + available to this context; i.e. an outcome owned by this group's context, + an outcome owned by an associated account, or a global outcome. With + outcome_id present, any other parameters are ignored. + + If defining a new outcome, the outcome is created in the outcome group's + context using the provided title, description, ratings, and mastery points; + the title is required but all other fields are optional. The new outcome + is then linked into the outcome group. + + If ratings are provided when creating a new outcome, an embedded rubric + criterion is included in the new outcome. This criterion's mastery_points + default to the maximum points in the highest rating if not specified in the + mastery_points parameter. Any ratings lacking a description are given a + default of "No description". Any ratings lacking a point value are given a + default of 0. If no ratings are provided, the mastery_points parameter is + ignored. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - outcome_id + """The ID of the existing outcome to link.""" + if outcome_id is not None: + data["outcome_id"] = outcome_id + + # OPTIONAL - title + """The title of the new outcome. Required if outcome_id is absent.""" + if title is not None: + data["title"] = title + + # OPTIONAL - display_name + """A friendly name shown in reports for outcomes with cryptic titles, + such as common core standards names.""" + if display_name is not None: + data["display_name"] = display_name + + # OPTIONAL - description + """The description of the new outcome.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - mastery_points + """The mastery threshold for the embedded rubric criterion.""" + if mastery_points is not None: + data["mastery_points"] = mastery_points + + # OPTIONAL - ratings[description] + """The description of a rating level for the embedded rubric criterion.""" + if ratings_description is not None: + data["ratings[description]"] = ratings_description + + # OPTIONAL - ratings[points] + """The points corresponding to a rating level for the embedded rubric criterion.""" + if ratings_points is not None: + data["ratings[points]"] = ratings_points + + # OPTIONAL - calculation_method + """The new calculation method. Defaults to "highest"""" + if calculation_method is not None: + self._validate_enum(calculation_method, ["decaying_average", "n_mastery", "latest", "highest"]) + data["calculation_method"] = calculation_method + + # OPTIONAL - calculation_int + """The new calculation int. Only applies if the calculation_method is "decaying_average" or "n_mastery"""" + if calculation_int is not None: + data["calculation_int"] = calculation_int + + self.logger.debug("POST /api/v1/global/outcome_groups/{id}/outcomes with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/global/outcome_groups/{id}/outcomes".format(**path), data=data, params=params, single_item=True) + + def create_link_outcome_global_outcome_id(self, id, outcome_id, calculation_int=None, calculation_method=None, description=None, display_name=None, mastery_points=None, ratings_description=None, ratings_points=None, title=None, vendor_guid=None): + """ + Create/link an outcome. + + Link an outcome into the outcome group. The outcome to link can either be + specified by a PUT to the link URL for a specific outcome (the outcome_id + in the PUT URLs) or by supplying the information for a new outcome (title, + description, ratings, mastery_points) in a POST to the collection. + + If linking an existing outcome, the outcome_id must identify an outcome + available to this context; i.e. an outcome owned by this group's context, + an outcome owned by an associated account, or a global outcome. With + outcome_id present, any other parameters are ignored. + + If defining a new outcome, the outcome is created in the outcome group's + context using the provided title, description, ratings, and mastery points; + the title is required but all other fields are optional. The new outcome + is then linked into the outcome group. + + If ratings are provided when creating a new outcome, an embedded rubric + criterion is included in the new outcome. This criterion's mastery_points + default to the maximum points in the highest rating if not specified in the + mastery_points parameter. Any ratings lacking a description are given a + default of "No description". Any ratings lacking a point value are given a + default of 0. If no ratings are provided, the mastery_points parameter is + ignored. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - outcome_id + """The ID of the existing outcome to link.""" + path["outcome_id"] = outcome_id + + # OPTIONAL - title + """The title of the new outcome. Required if outcome_id is absent.""" + if title is not None: + data["title"] = title + + # OPTIONAL - display_name + """A friendly name shown in reports for outcomes with cryptic titles, + such as common core standards names.""" + if display_name is not None: + data["display_name"] = display_name + + # OPTIONAL - description + """The description of the new outcome.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - mastery_points + """The mastery threshold for the embedded rubric criterion.""" + if mastery_points is not None: + data["mastery_points"] = mastery_points + + # OPTIONAL - ratings[description] + """The description of a rating level for the embedded rubric criterion.""" + if ratings_description is not None: + data["ratings[description]"] = ratings_description + + # OPTIONAL - ratings[points] + """The points corresponding to a rating level for the embedded rubric criterion.""" + if ratings_points is not None: + data["ratings[points]"] = ratings_points + + # OPTIONAL - calculation_method + """The new calculation method. Defaults to "highest"""" + if calculation_method is not None: + self._validate_enum(calculation_method, ["decaying_average", "n_mastery", "latest", "highest"]) + data["calculation_method"] = calculation_method + + # OPTIONAL - calculation_int + """The new calculation int. Only applies if the calculation_method is "decaying_average" or "n_mastery"""" + if calculation_int is not None: + data["calculation_int"] = calculation_int + + self.logger.debug("PUT /api/v1/global/outcome_groups/{id}/outcomes/{outcome_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/global/outcome_groups/{id}/outcomes/{outcome_id}".format(**path), data=data, params=params, single_item=True) + + def create_link_outcome_accounts(self, id, account_id, calculation_int=None, calculation_method=None, description=None, display_name=None, mastery_points=None, outcome_id=None, ratings_description=None, ratings_points=None, title=None, vendor_guid=None): + """ + Create/link an outcome. + + Link an outcome into the outcome group. The outcome to link can either be + specified by a PUT to the link URL for a specific outcome (the outcome_id + in the PUT URLs) or by supplying the information for a new outcome (title, + description, ratings, mastery_points) in a POST to the collection. + + If linking an existing outcome, the outcome_id must identify an outcome + available to this context; i.e. an outcome owned by this group's context, + an outcome owned by an associated account, or a global outcome. With + outcome_id present, any other parameters are ignored. + + If defining a new outcome, the outcome is created in the outcome group's + context using the provided title, description, ratings, and mastery points; + the title is required but all other fields are optional. The new outcome + is then linked into the outcome group. + + If ratings are provided when creating a new outcome, an embedded rubric + criterion is included in the new outcome. This criterion's mastery_points + default to the maximum points in the highest rating if not specified in the + mastery_points parameter. Any ratings lacking a description are given a + default of "No description". Any ratings lacking a point value are given a + default of 0. If no ratings are provided, the mastery_points parameter is + ignored. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - outcome_id + """The ID of the existing outcome to link.""" + if outcome_id is not None: + data["outcome_id"] = outcome_id + + # OPTIONAL - title + """The title of the new outcome. Required if outcome_id is absent.""" + if title is not None: + data["title"] = title + + # OPTIONAL - display_name + """A friendly name shown in reports for outcomes with cryptic titles, + such as common core standards names.""" + if display_name is not None: + data["display_name"] = display_name + + # OPTIONAL - description + """The description of the new outcome.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - mastery_points + """The mastery threshold for the embedded rubric criterion.""" + if mastery_points is not None: + data["mastery_points"] = mastery_points + + # OPTIONAL - ratings[description] + """The description of a rating level for the embedded rubric criterion.""" + if ratings_description is not None: + data["ratings[description]"] = ratings_description + + # OPTIONAL - ratings[points] + """The points corresponding to a rating level for the embedded rubric criterion.""" + if ratings_points is not None: + data["ratings[points]"] = ratings_points + + # OPTIONAL - calculation_method + """The new calculation method. Defaults to "highest"""" + if calculation_method is not None: + self._validate_enum(calculation_method, ["decaying_average", "n_mastery", "latest", "highest"]) + data["calculation_method"] = calculation_method + + # OPTIONAL - calculation_int + """The new calculation int. Only applies if the calculation_method is "decaying_average" or "n_mastery"""" + if calculation_int is not None: + data["calculation_int"] = calculation_int + + self.logger.debug("POST /api/v1/accounts/{account_id}/outcome_groups/{id}/outcomes with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/outcome_groups/{id}/outcomes".format(**path), data=data, params=params, single_item=True) + + def create_link_outcome_accounts_outcome_id(self, id, account_id, outcome_id, calculation_int=None, calculation_method=None, description=None, display_name=None, mastery_points=None, ratings_description=None, ratings_points=None, title=None, vendor_guid=None): + """ + Create/link an outcome. + + Link an outcome into the outcome group. The outcome to link can either be + specified by a PUT to the link URL for a specific outcome (the outcome_id + in the PUT URLs) or by supplying the information for a new outcome (title, + description, ratings, mastery_points) in a POST to the collection. + + If linking an existing outcome, the outcome_id must identify an outcome + available to this context; i.e. an outcome owned by this group's context, + an outcome owned by an associated account, or a global outcome. With + outcome_id present, any other parameters are ignored. + + If defining a new outcome, the outcome is created in the outcome group's + context using the provided title, description, ratings, and mastery points; + the title is required but all other fields are optional. The new outcome + is then linked into the outcome group. + + If ratings are provided when creating a new outcome, an embedded rubric + criterion is included in the new outcome. This criterion's mastery_points + default to the maximum points in the highest rating if not specified in the + mastery_points parameter. Any ratings lacking a description are given a + default of "No description". Any ratings lacking a point value are given a + default of 0. If no ratings are provided, the mastery_points parameter is + ignored. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - outcome_id + """The ID of the existing outcome to link.""" + path["outcome_id"] = outcome_id + + # OPTIONAL - title + """The title of the new outcome. Required if outcome_id is absent.""" + if title is not None: + data["title"] = title + + # OPTIONAL - display_name + """A friendly name shown in reports for outcomes with cryptic titles, + such as common core standards names.""" + if display_name is not None: + data["display_name"] = display_name + + # OPTIONAL - description + """The description of the new outcome.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - mastery_points + """The mastery threshold for the embedded rubric criterion.""" + if mastery_points is not None: + data["mastery_points"] = mastery_points + + # OPTIONAL - ratings[description] + """The description of a rating level for the embedded rubric criterion.""" + if ratings_description is not None: + data["ratings[description]"] = ratings_description + + # OPTIONAL - ratings[points] + """The points corresponding to a rating level for the embedded rubric criterion.""" + if ratings_points is not None: + data["ratings[points]"] = ratings_points + + # OPTIONAL - calculation_method + """The new calculation method. Defaults to "highest"""" + if calculation_method is not None: + self._validate_enum(calculation_method, ["decaying_average", "n_mastery", "latest", "highest"]) + data["calculation_method"] = calculation_method + + # OPTIONAL - calculation_int + """The new calculation int. Only applies if the calculation_method is "decaying_average" or "n_mastery"""" + if calculation_int is not None: + data["calculation_int"] = calculation_int + + self.logger.debug("PUT /api/v1/accounts/{account_id}/outcome_groups/{id}/outcomes/{outcome_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/outcome_groups/{id}/outcomes/{outcome_id}".format(**path), data=data, params=params, single_item=True) + + def create_link_outcome_courses(self, id, course_id, calculation_int=None, calculation_method=None, description=None, display_name=None, mastery_points=None, outcome_id=None, ratings_description=None, ratings_points=None, title=None, vendor_guid=None): + """ + Create/link an outcome. + + Link an outcome into the outcome group. The outcome to link can either be + specified by a PUT to the link URL for a specific outcome (the outcome_id + in the PUT URLs) or by supplying the information for a new outcome (title, + description, ratings, mastery_points) in a POST to the collection. + + If linking an existing outcome, the outcome_id must identify an outcome + available to this context; i.e. an outcome owned by this group's context, + an outcome owned by an associated account, or a global outcome. With + outcome_id present, any other parameters are ignored. + + If defining a new outcome, the outcome is created in the outcome group's + context using the provided title, description, ratings, and mastery points; + the title is required but all other fields are optional. The new outcome + is then linked into the outcome group. + + If ratings are provided when creating a new outcome, an embedded rubric + criterion is included in the new outcome. This criterion's mastery_points + default to the maximum points in the highest rating if not specified in the + mastery_points parameter. Any ratings lacking a description are given a + default of "No description". Any ratings lacking a point value are given a + default of 0. If no ratings are provided, the mastery_points parameter is + ignored. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - outcome_id + """The ID of the existing outcome to link.""" + if outcome_id is not None: + data["outcome_id"] = outcome_id + + # OPTIONAL - title + """The title of the new outcome. Required if outcome_id is absent.""" + if title is not None: + data["title"] = title + + # OPTIONAL - display_name + """A friendly name shown in reports for outcomes with cryptic titles, + such as common core standards names.""" + if display_name is not None: + data["display_name"] = display_name + + # OPTIONAL - description + """The description of the new outcome.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - mastery_points + """The mastery threshold for the embedded rubric criterion.""" + if mastery_points is not None: + data["mastery_points"] = mastery_points + + # OPTIONAL - ratings[description] + """The description of a rating level for the embedded rubric criterion.""" + if ratings_description is not None: + data["ratings[description]"] = ratings_description + + # OPTIONAL - ratings[points] + """The points corresponding to a rating level for the embedded rubric criterion.""" + if ratings_points is not None: + data["ratings[points]"] = ratings_points + + # OPTIONAL - calculation_method + """The new calculation method. Defaults to "highest"""" + if calculation_method is not None: + self._validate_enum(calculation_method, ["decaying_average", "n_mastery", "latest", "highest"]) + data["calculation_method"] = calculation_method + + # OPTIONAL - calculation_int + """The new calculation int. Only applies if the calculation_method is "decaying_average" or "n_mastery"""" + if calculation_int is not None: + data["calculation_int"] = calculation_int + + self.logger.debug("POST /api/v1/courses/{course_id}/outcome_groups/{id}/outcomes with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/outcome_groups/{id}/outcomes".format(**path), data=data, params=params, single_item=True) + + def create_link_outcome_courses_outcome_id(self, id, course_id, outcome_id, calculation_int=None, calculation_method=None, description=None, display_name=None, mastery_points=None, ratings_description=None, ratings_points=None, title=None, vendor_guid=None): + """ + Create/link an outcome. + + Link an outcome into the outcome group. The outcome to link can either be + specified by a PUT to the link URL for a specific outcome (the outcome_id + in the PUT URLs) or by supplying the information for a new outcome (title, + description, ratings, mastery_points) in a POST to the collection. + + If linking an existing outcome, the outcome_id must identify an outcome + available to this context; i.e. an outcome owned by this group's context, + an outcome owned by an associated account, or a global outcome. With + outcome_id present, any other parameters are ignored. + + If defining a new outcome, the outcome is created in the outcome group's + context using the provided title, description, ratings, and mastery points; + the title is required but all other fields are optional. The new outcome + is then linked into the outcome group. + + If ratings are provided when creating a new outcome, an embedded rubric + criterion is included in the new outcome. This criterion's mastery_points + default to the maximum points in the highest rating if not specified in the + mastery_points parameter. Any ratings lacking a description are given a + default of "No description". Any ratings lacking a point value are given a + default of 0. If no ratings are provided, the mastery_points parameter is + ignored. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - outcome_id + """The ID of the existing outcome to link.""" + path["outcome_id"] = outcome_id + + # OPTIONAL - title + """The title of the new outcome. Required if outcome_id is absent.""" + if title is not None: + data["title"] = title + + # OPTIONAL - display_name + """A friendly name shown in reports for outcomes with cryptic titles, + such as common core standards names.""" + if display_name is not None: + data["display_name"] = display_name + + # OPTIONAL - description + """The description of the new outcome.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - mastery_points + """The mastery threshold for the embedded rubric criterion.""" + if mastery_points is not None: + data["mastery_points"] = mastery_points + + # OPTIONAL - ratings[description] + """The description of a rating level for the embedded rubric criterion.""" + if ratings_description is not None: + data["ratings[description]"] = ratings_description + + # OPTIONAL - ratings[points] + """The points corresponding to a rating level for the embedded rubric criterion.""" + if ratings_points is not None: + data["ratings[points]"] = ratings_points + + # OPTIONAL - calculation_method + """The new calculation method. Defaults to "highest"""" + if calculation_method is not None: + self._validate_enum(calculation_method, ["decaying_average", "n_mastery", "latest", "highest"]) + data["calculation_method"] = calculation_method + + # OPTIONAL - calculation_int + """The new calculation int. Only applies if the calculation_method is "decaying_average" or "n_mastery"""" + if calculation_int is not None: + data["calculation_int"] = calculation_int + + self.logger.debug("PUT /api/v1/courses/{course_id}/outcome_groups/{id}/outcomes/{outcome_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/outcome_groups/{id}/outcomes/{outcome_id}".format(**path), data=data, params=params, single_item=True) + + def unlink_outcome_global(self, id, outcome_id): + """ + Unlink an outcome. + + Unlinking an outcome only deletes the outcome itself if this was the last + link to the outcome in any group in any context. Aligned outcomes cannot be + deleted; as such, if this is the last link to an aligned outcome, the + unlinking will fail. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - outcome_id + """ID""" + path["outcome_id"] = outcome_id + + self.logger.debug("DELETE /api/v1/global/outcome_groups/{id}/outcomes/{outcome_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/global/outcome_groups/{id}/outcomes/{outcome_id}".format(**path), data=data, params=params, single_item=True) + + def unlink_outcome_accounts(self, id, account_id, outcome_id): + """ + Unlink an outcome. + + Unlinking an outcome only deletes the outcome itself if this was the last + link to the outcome in any group in any context. Aligned outcomes cannot be + deleted; as such, if this is the last link to an aligned outcome, the + unlinking will fail. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - outcome_id + """ID""" + path["outcome_id"] = outcome_id + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/outcome_groups/{id}/outcomes/{outcome_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/outcome_groups/{id}/outcomes/{outcome_id}".format(**path), data=data, params=params, single_item=True) + + def unlink_outcome_courses(self, id, course_id, outcome_id): + """ + Unlink an outcome. + + Unlinking an outcome only deletes the outcome itself if this was the last + link to the outcome in any group in any context. Aligned outcomes cannot be + deleted; as such, if this is the last link to an aligned outcome, the + unlinking will fail. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - outcome_id + """ID""" + path["outcome_id"] = outcome_id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/outcome_groups/{id}/outcomes/{outcome_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/outcome_groups/{id}/outcomes/{outcome_id}".format(**path), data=data, params=params, single_item=True) + + def list_subgroups_global(self, id): + """ + List subgroups. + + List the immediate OutcomeGroup children of the outcome group. Paginated. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/global/outcome_groups/{id}/subgroups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/global/outcome_groups/{id}/subgroups".format(**path), data=data, params=params, all_pages=True) + + def list_subgroups_accounts(self, id, account_id): + """ + List subgroups. + + List the immediate OutcomeGroup children of the outcome group. Paginated. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{account_id}/outcome_groups/{id}/subgroups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/outcome_groups/{id}/subgroups".format(**path), data=data, params=params, all_pages=True) + + def list_subgroups_courses(self, id, course_id): + """ + List subgroups. + + List the immediate OutcomeGroup children of the outcome group. Paginated. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/outcome_groups/{id}/subgroups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/outcome_groups/{id}/subgroups".format(**path), data=data, params=params, all_pages=True) + + def create_subgroup_global(self, id, title, description=None, vendor_guid=None): + """ + Create a subgroup. + + Creates a new empty subgroup under the outcome group with the given title + and description. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - title + """The title of the new outcome group.""" + data["title"] = title + + # OPTIONAL - description + """The description of the new outcome group.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + self.logger.debug("POST /api/v1/global/outcome_groups/{id}/subgroups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/global/outcome_groups/{id}/subgroups".format(**path), data=data, params=params, single_item=True) + + def create_subgroup_accounts(self, id, title, account_id, description=None, vendor_guid=None): + """ + Create a subgroup. + + Creates a new empty subgroup under the outcome group with the given title + and description. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - title + """The title of the new outcome group.""" + data["title"] = title + + # OPTIONAL - description + """The description of the new outcome group.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + self.logger.debug("POST /api/v1/accounts/{account_id}/outcome_groups/{id}/subgroups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/outcome_groups/{id}/subgroups".format(**path), data=data, params=params, single_item=True) + + def create_subgroup_courses(self, id, title, course_id, description=None, vendor_guid=None): + """ + Create a subgroup. + + Creates a new empty subgroup under the outcome group with the given title + and description. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - title + """The title of the new outcome group.""" + data["title"] = title + + # OPTIONAL - description + """The description of the new outcome group.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + self.logger.debug("POST /api/v1/courses/{course_id}/outcome_groups/{id}/subgroups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/outcome_groups/{id}/subgroups".format(**path), data=data, params=params, single_item=True) + + def import_outcome_group_global(self, id, source_outcome_group_id): + """ + Import an outcome group. + + Creates a new subgroup of the outcome group with the same title and + description as the source group, then creates links in that new subgroup to + the same outcomes that are linked in the source group. Recurses on the + subgroups of the source group, importing them each in turn into the new + subgroup. + + Allows you to copy organizational structure, but does not create copies of + the outcomes themselves, only new links. + + The source group must be either global, from the same context as this + outcome group, or from an associated account. The source group cannot be + the root outcome group of its context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - source_outcome_group_id + """The ID of the source outcome group.""" + data["source_outcome_group_id"] = source_outcome_group_id + + self.logger.debug("POST /api/v1/global/outcome_groups/{id}/import with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/global/outcome_groups/{id}/import".format(**path), data=data, params=params, single_item=True) + + def import_outcome_group_accounts(self, id, account_id, source_outcome_group_id): + """ + Import an outcome group. + + Creates a new subgroup of the outcome group with the same title and + description as the source group, then creates links in that new subgroup to + the same outcomes that are linked in the source group. Recurses on the + subgroups of the source group, importing them each in turn into the new + subgroup. + + Allows you to copy organizational structure, but does not create copies of + the outcomes themselves, only new links. + + The source group must be either global, from the same context as this + outcome group, or from an associated account. The source group cannot be + the root outcome group of its context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - source_outcome_group_id + """The ID of the source outcome group.""" + data["source_outcome_group_id"] = source_outcome_group_id + + self.logger.debug("POST /api/v1/accounts/{account_id}/outcome_groups/{id}/import with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/outcome_groups/{id}/import".format(**path), data=data, params=params, single_item=True) + + def import_outcome_group_courses(self, id, course_id, source_outcome_group_id): + """ + Import an outcome group. + + Creates a new subgroup of the outcome group with the same title and + description as the source group, then creates links in that new subgroup to + the same outcomes that are linked in the source group. Recurses on the + subgroups of the source group, importing them each in turn into the new + subgroup. + + Allows you to copy organizational structure, but does not create copies of + the outcomes themselves, only new links. + + The source group must be either global, from the same context as this + outcome group, or from an associated account. The source group cannot be + the root outcome group of its context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - source_outcome_group_id + """The ID of the source outcome group.""" + data["source_outcome_group_id"] = source_outcome_group_id + + self.logger.debug("POST /api/v1/courses/{course_id}/outcome_groups/{id}/import with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/outcome_groups/{id}/import".format(**path), data=data, params=params, single_item=True) + + +class Outcomegroup(BaseModel): + """Outcomegroup Model.""" + + def __init__(self, vendor_guid=None, can_edit=None, description=None, title=None, url=None, context_id=None, import_url=None, id=None, parent_outcome_group=None, outcomes_url=None, subgroups_url=None, context_type=None): + """Init method for Outcomegroup class.""" + self._vendor_guid = vendor_guid + self._can_edit = can_edit + self._description = description + self._title = title + self._url = url + self._context_id = context_id + self._import_url = import_url + self._id = id + self._parent_outcome_group = parent_outcome_group + self._outcomes_url = outcomes_url + self._subgroups_url = subgroups_url + self._context_type = context_type + + self.logger = logging.getLogger('pycanvas.Outcomegroup') + + @property + def vendor_guid(self): + """A custom GUID for the learning standard.""" + return self._vendor_guid + + @vendor_guid.setter + def vendor_guid(self, value): + """Setter for vendor_guid property.""" + self.logger.warn("Setting values on vendor_guid will NOT update the remote Canvas instance.") + self._vendor_guid = value + + @property + def can_edit(self): + """whether the current user can update the outcome group.""" + return self._can_edit + + @can_edit.setter + def can_edit(self, value): + """Setter for can_edit property.""" + self.logger.warn("Setting values on can_edit will NOT update the remote Canvas instance.") + self._can_edit = value + + @property + def description(self): + """description of the outcome group. omitted in the abbreviated form.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def title(self): + """title of the outcome group.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def url(self): + """the URL for fetching/updating the outcome group. should be treated as opaque.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def context_id(self): + """the context owning the outcome group. may be null for global outcome groups. omitted in the abbreviated form.""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + + @property + def import_url(self): + """the URL for importing another group into this outcome group. should be treated as opaque. omitted in the abbreviated form.""" + return self._import_url + + @import_url.setter + def import_url(self, value): + """Setter for import_url property.""" + self.logger.warn("Setting values on import_url will NOT update the remote Canvas instance.") + self._import_url = value + + @property + def id(self): + """the ID of the outcome group.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def parent_outcome_group(self): + """an abbreviated OutcomeGroup object representing the parent group of this outcome group, if any. omitted in the abbreviated form.""" + return self._parent_outcome_group + + @parent_outcome_group.setter + def parent_outcome_group(self, value): + """Setter for parent_outcome_group property.""" + self.logger.warn("Setting values on parent_outcome_group will NOT update the remote Canvas instance.") + self._parent_outcome_group = value + + @property + def outcomes_url(self): + """the URL for listing/creating outcome links under the outcome group. should be treated as opaque.""" + return self._outcomes_url + + @outcomes_url.setter + def outcomes_url(self, value): + """Setter for outcomes_url property.""" + self.logger.warn("Setting values on outcomes_url will NOT update the remote Canvas instance.") + self._outcomes_url = value + + @property + def subgroups_url(self): + """the URL for listing/creating subgroups under the outcome group. should be treated as opaque.""" + return self._subgroups_url + + @subgroups_url.setter + def subgroups_url(self, value): + """Setter for subgroups_url property.""" + self.logger.warn("Setting values on subgroups_url will NOT update the remote Canvas instance.") + self._subgroups_url = value + + @property + def context_type(self): + """context_type.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + +class Outcomelink(BaseModel): + """Outcomelink Model.""" + + def __init__(self, url=None, context_id=None, context_type=None, can_unlink=None, outcome_group=None, assessed=None, outcome=None): + """Init method for Outcomelink class.""" + self._url = url + self._context_id = context_id + self._context_type = context_type + self._can_unlink = can_unlink + self._outcome_group = outcome_group + self._assessed = assessed + self._outcome = outcome + + self.logger = logging.getLogger('pycanvas.Outcomelink') + + @property + def url(self): + """the URL for fetching/updating the outcome link. should be treated as opaque.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def context_id(self): + """the context owning the outcome link. will match the context owning the outcome group containing the outcome link; included for convenience. may be null for links in global outcome groups.""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + + @property + def context_type(self): + """context_type.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def can_unlink(self): + """whether this outcome link is manageable and is not the last link to an aligned outcome.""" + return self._can_unlink + + @can_unlink.setter + def can_unlink(self, value): + """Setter for can_unlink property.""" + self.logger.warn("Setting values on can_unlink will NOT update the remote Canvas instance.") + self._can_unlink = value + + @property + def outcome_group(self): + """an abbreviated OutcomeGroup object representing the group containing the outcome link.""" + return self._outcome_group + + @outcome_group.setter + def outcome_group(self, value): + """Setter for outcome_group property.""" + self.logger.warn("Setting values on outcome_group will NOT update the remote Canvas instance.") + self._outcome_group = value + + @property + def assessed(self): + """whether this outcome has been used to assess a student in the context of this outcome link. In other words, this will be set to true if the context is a course, and a student has been assessed with this outcome in that course.""" + return self._assessed + + @assessed.setter + def assessed(self, value): + """Setter for assessed property.""" + self.logger.warn("Setting values on assessed will NOT update the remote Canvas instance.") + self._assessed = value + + @property + def outcome(self): + """an abbreviated Outcome object representing the outcome linked into the containing outcome group.""" + return self._outcome + + @outcome.setter + def outcome(self, value): + """Setter for outcome property.""" + self.logger.warn("Setting values on outcome will NOT update the remote Canvas instance.") + self._outcome = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/outcome_results.py b/venv/Lib/site-packages/pycanvas/apis/outcome_results.py new file mode 100644 index 00000000..49ff482c --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/outcome_results.py @@ -0,0 +1,434 @@ +"""OutcomeResults API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class OutcomeResultsAPI(BaseCanvasAPI): + """OutcomeResults API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for OutcomeResultsAPI.""" + super(OutcomeResultsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.OutcomeResultsAPI") + + def get_outcome_results(self, course_id, include=None, outcome_ids=None, user_ids=None): + """ + Get outcome results. + + Gets the outcome results for users and outcomes in the specified context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - user_ids + """If specified, only the users whose ids are given will be included in the + results. SIS ids can be used, prefixed by "sis_user_id:". + It is an error to specify an id for a user who is not a student in + the context.""" + if user_ids is not None: + params["user_ids"] = user_ids + + # OPTIONAL - outcome_ids + """If specified, only the outcomes whose ids are given will be included in the + results. it is an error to specify an id for an outcome which is not linked + to the context.""" + if outcome_ids is not None: + params["outcome_ids"] = outcome_ids + + # OPTIONAL - include + """[String, "alignments"|"outcomes"|"outcomes.alignments"|"outcome_groups"|"outcome_links"|"outcome_paths"|"users"] + Specify additional collections to be side loaded with the result. + "alignments" includes only the alignments referenced by the returned + results. + "outcomes.alignments" includes all alignments referenced by outcomes in the + context.""" + if include is not None: + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/outcome_results with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/outcome_results".format(**path), data=data, params=params, no_data=True) + + def get_outcome_result_rollups(self, course_id, aggregate=None, include=None, outcome_ids=None, user_ids=None): + """ + Get outcome result rollups. + + Gets the outcome rollups for the users and outcomes in the specified + context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - aggregate + """If specified, instead of returning one rollup for each user, all the user + rollups will be combined into one rollup for the course that will contain + the average rollup score for each outcome.""" + if aggregate is not None: + self._validate_enum(aggregate, ["course"]) + params["aggregate"] = aggregate + + # OPTIONAL - user_ids + """If specified, only the users whose ids are given will be included in the + results or used in an aggregate result. it is an error to specify an id + for a user who is not a student in the context""" + if user_ids is not None: + params["user_ids"] = user_ids + + # OPTIONAL - outcome_ids + """If specified, only the outcomes whose ids are given will be included in the + results. it is an error to specify an id for an outcome which is not linked + to the context.""" + if outcome_ids is not None: + params["outcome_ids"] = outcome_ids + + # OPTIONAL - include + """[String, "courses"|"outcomes"|"outcomes.alignments"|"outcome_groups"|"outcome_links"|"outcome_paths"|"users"] + Specify additional collections to be side loaded with the result.""" + if include is not None: + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/outcome_rollups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/outcome_rollups".format(**path), data=data, params=params, no_data=True) + + +class Outcomeresult(BaseModel): + """Outcomeresult Model. + A student's result for an outcome""" + + def __init__(self, score=None, percent=None, id=None, links=None, submitted_or_assessed_at=None): + """Init method for Outcomeresult class.""" + self._score = score + self._percent = percent + self._id = id + self._links = links + self._submitted_or_assessed_at = submitted_or_assessed_at + + self.logger = logging.getLogger('pycanvas.Outcomeresult') + + @property + def score(self): + """The student's score.""" + return self._score + + @score.setter + def score(self, value): + """Setter for score property.""" + self.logger.warn("Setting values on score will NOT update the remote Canvas instance.") + self._score = value + + @property + def percent(self): + """score's percent of maximum points possible for outcome, scaled to reflect any custom mastery levels that differ from the learning outcome.""" + return self._percent + + @percent.setter + def percent(self, value): + """Setter for percent property.""" + self.logger.warn("Setting values on percent will NOT update the remote Canvas instance.") + self._percent = value + + @property + def id(self): + """A unique identifier for this result.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def links(self): + """Unique identifiers of objects associated with this result.""" + return self._links + + @links.setter + def links(self, value): + """Setter for links property.""" + self.logger.warn("Setting values on links will NOT update the remote Canvas instance.") + self._links = value + + @property + def submitted_or_assessed_at(self): + """The datetime the resulting OutcomeResult was submitted at, or absent that, when it was assessed.""" + return self._submitted_or_assessed_at + + @submitted_or_assessed_at.setter + def submitted_or_assessed_at(self, value): + """Setter for submitted_or_assessed_at property.""" + self.logger.warn("Setting values on submitted_or_assessed_at will NOT update the remote Canvas instance.") + self._submitted_or_assessed_at = value + + +class Outcomerolluplinks(BaseModel): + """Outcomerolluplinks Model.""" + + def __init__(self, course=None, section=None, user=None): + """Init method for Outcomerolluplinks class.""" + self._course = course + self._section = section + self._user = user + + self.logger = logging.getLogger('pycanvas.Outcomerolluplinks') + + @property + def course(self): + """If an aggregate result was requested, the course field will be present. Otherwise, the user and section field will be present (Optional) The id of the course that this rollup applies to.""" + return self._course + + @course.setter + def course(self, value): + """Setter for course property.""" + self.logger.warn("Setting values on course will NOT update the remote Canvas instance.") + self._course = value + + @property + def section(self): + """(Optional) The id of the section the user is in.""" + return self._section + + @section.setter + def section(self, value): + """Setter for section property.""" + self.logger.warn("Setting values on section will NOT update the remote Canvas instance.") + self._section = value + + @property + def user(self): + """(Optional) The id of the user that this rollup applies to.""" + return self._user + + @user.setter + def user(self, value): + """Setter for user property.""" + self.logger.warn("Setting values on user will NOT update the remote Canvas instance.") + self._user = value + + +class Outcomepathpart(BaseModel): + """Outcomepathpart Model. + An outcome or outcome group""" + + def __init__(self, name=None): + """Init method for Outcomepathpart class.""" + self._name = name + + self.logger = logging.getLogger('pycanvas.Outcomepathpart') + + @property + def name(self): + """The title of the outcome or outcome group.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class Outcomerollupscorelinks(BaseModel): + """Outcomerollupscorelinks Model.""" + + def __init__(self, outcome=None): + """Init method for Outcomerollupscorelinks class.""" + self._outcome = outcome + + self.logger = logging.getLogger('pycanvas.Outcomerollupscorelinks') + + @property + def outcome(self): + """The id of the related outcome.""" + return self._outcome + + @outcome.setter + def outcome(self, value): + """Setter for outcome property.""" + self.logger.warn("Setting values on outcome will NOT update the remote Canvas instance.") + self._outcome = value + + +class Outcomealignment(BaseModel): + """Outcomealignment Model. + An asset aligned with this outcome""" + + def __init__(self, id=None, html_url=None, name=None): + """Init method for Outcomealignment class.""" + self._id = id + self._html_url = html_url + self._name = name + + self.logger = logging.getLogger('pycanvas.Outcomealignment') + + @property + def id(self): + """A unique identifier for this alignment.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def html_url(self): + """(Optional) A URL for details about this alignment.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def name(self): + """The name of this alignment.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class Outcomerollupscore(BaseModel): + """Outcomerollupscore Model.""" + + def __init__(self, count=None, score=None, links=None): + """Init method for Outcomerollupscore class.""" + self._count = count + self._score = score + self._links = links + + self.logger = logging.getLogger('pycanvas.Outcomerollupscore') + + @property + def count(self): + """The number of alignment scores included in this rollup.""" + return self._count + + @count.setter + def count(self, value): + """Setter for count property.""" + self.logger.warn("Setting values on count will NOT update the remote Canvas instance.") + self._count = value + + @property + def score(self): + """The rollup score for the outcome, based on the student alignment scores related to the outcome. This could be null if the student has no related scores.""" + return self._score + + @score.setter + def score(self, value): + """Setter for score property.""" + self.logger.warn("Setting values on score will NOT update the remote Canvas instance.") + self._score = value + + @property + def links(self): + """links.""" + return self._links + + @links.setter + def links(self, value): + """Setter for links property.""" + self.logger.warn("Setting values on links will NOT update the remote Canvas instance.") + self._links = value + + +class Outcomerollup(BaseModel): + """Outcomerollup Model.""" + + def __init__(self, name=None, links=None, scores=None): + """Init method for Outcomerollup class.""" + self._name = name + self._links = links + self._scores = scores + + self.logger = logging.getLogger('pycanvas.Outcomerollup') + + @property + def name(self): + """The name of the resource for this rollup. For example, the user name.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def links(self): + """links.""" + return self._links + + @links.setter + def links(self, value): + """Setter for links property.""" + self.logger.warn("Setting values on links will NOT update the remote Canvas instance.") + self._links = value + + @property + def scores(self): + """an array of OutcomeRollupScore objects.""" + return self._scores + + @scores.setter + def scores(self, value): + """Setter for scores property.""" + self.logger.warn("Setting values on scores will NOT update the remote Canvas instance.") + self._scores = value + + +class Outcomepath(BaseModel): + """Outcomepath Model. + The full path to an outcome""" + + def __init__(self, parts=None, id=None): + """Init method for Outcomepath class.""" + self._parts = parts + self._id = id + + self.logger = logging.getLogger('pycanvas.Outcomepath') + + @property + def parts(self): + """an array of OutcomePathPart objects.""" + return self._parts + + @parts.setter + def parts(self, value): + """Setter for parts property.""" + self.logger.warn("Setting values on parts will NOT update the remote Canvas instance.") + self._parts = value + + @property + def id(self): + """A unique identifier for this outcome.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/outcomes.py b/venv/Lib/site-packages/pycanvas/apis/outcomes.py new file mode 100644 index 00000000..e76a5813 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/outcomes.py @@ -0,0 +1,312 @@ +"""Outcomes API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class OutcomesAPI(BaseCanvasAPI): + """Outcomes API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for OutcomesAPI.""" + super(OutcomesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.OutcomesAPI") + + def show_outcome(self, id): + """ + Show an outcome. + + Returns the details of the outcome with the given id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/outcomes/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/outcomes/{id}".format(**path), data=data, params=params, single_item=True) + + def update_outcome(self, id, calculation_int=None, calculation_method=None, description=None, display_name=None, mastery_points=None, ratings_description=None, ratings_points=None, title=None, vendor_guid=None): + """ + Update an outcome. + + Modify an existing outcome. Fields not provided are left as is; + unrecognized fields are ignored. + + If any new ratings are provided, the combination of all new ratings + provided completely replace any existing embedded rubric criterion; it is + not possible to tweak the ratings of the embedded rubric criterion. + + A new embedded rubric criterion's mastery_points default to the maximum + points in the highest rating if not specified in the mastery_points + parameter. Any new ratings lacking a description are given a default of "No + description". Any new ratings lacking a point value are given a default of + 0. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - title + """The new outcome title.""" + if title is not None: + data["title"] = title + + # OPTIONAL - display_name + """A friendly name shown in reports for outcomes with cryptic titles, + such as common core standards names.""" + if display_name is not None: + data["display_name"] = display_name + + # OPTIONAL - description + """The new outcome description.""" + if description is not None: + data["description"] = description + + # OPTIONAL - vendor_guid + """A custom GUID for the learning standard.""" + if vendor_guid is not None: + data["vendor_guid"] = vendor_guid + + # OPTIONAL - mastery_points + """The new mastery threshold for the embedded rubric criterion.""" + if mastery_points is not None: + data["mastery_points"] = mastery_points + + # OPTIONAL - ratings[description] + """The description of a new rating level for the embedded rubric criterion.""" + if ratings_description is not None: + data["ratings[description]"] = ratings_description + + # OPTIONAL - ratings[points] + """The points corresponding to a new rating level for the embedded rubric + criterion.""" + if ratings_points is not None: + data["ratings[points]"] = ratings_points + + # OPTIONAL - calculation_method + """The new calculation method.""" + if calculation_method is not None: + self._validate_enum(calculation_method, ["decaying_average", "n_mastery", "latest", "highest"]) + data["calculation_method"] = calculation_method + + # OPTIONAL - calculation_int + """The new calculation int. Only applies if the calculation_method is "decaying_average" or "n_mastery"""" + if calculation_int is not None: + data["calculation_int"] = calculation_int + + self.logger.debug("PUT /api/v1/outcomes/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/outcomes/{id}".format(**path), data=data, params=params, single_item=True) + + +class Outcome(BaseModel): + """Outcome Model.""" + + def __init__(self, vendor_guid=None, can_edit=None, display_name=None, description=None, title=None, url=None, context_id=None, points_possible=None, can_unlink=None, context_type=None, ratings=None, calculation_int=None, calculation_method=None, assessed=None, id=None, mastery_points=None): + """Init method for Outcome class.""" + self._vendor_guid = vendor_guid + self._can_edit = can_edit + self._display_name = display_name + self._description = description + self._title = title + self._url = url + self._context_id = context_id + self._points_possible = points_possible + self._can_unlink = can_unlink + self._context_type = context_type + self._ratings = ratings + self._calculation_int = calculation_int + self._calculation_method = calculation_method + self._assessed = assessed + self._id = id + self._mastery_points = mastery_points + + self.logger = logging.getLogger('pycanvas.Outcome') + + @property + def vendor_guid(self): + """A custom GUID for the learning standard.""" + return self._vendor_guid + + @vendor_guid.setter + def vendor_guid(self, value): + """Setter for vendor_guid property.""" + self.logger.warn("Setting values on vendor_guid will NOT update the remote Canvas instance.") + self._vendor_guid = value + + @property + def can_edit(self): + """whether the current user can update the outcome.""" + return self._can_edit + + @can_edit.setter + def can_edit(self, value): + """Setter for can_edit property.""" + self.logger.warn("Setting values on can_edit will NOT update the remote Canvas instance.") + self._can_edit = value + + @property + def display_name(self): + """Optional friendly name for reporting.""" + return self._display_name + + @display_name.setter + def display_name(self, value): + """Setter for display_name property.""" + self.logger.warn("Setting values on display_name will NOT update the remote Canvas instance.") + self._display_name = value + + @property + def description(self): + """description of the outcome. omitted in the abbreviated form.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def title(self): + """title of the outcome.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def url(self): + """the URL for fetching/updating the outcome. should be treated as opaque.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def context_id(self): + """the context owning the outcome. may be null for global outcomes.""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + + @property + def points_possible(self): + """maximum points possible. included only if the outcome embeds a rubric criterion. omitted in the abbreviated form.""" + return self._points_possible + + @points_possible.setter + def points_possible(self, value): + """Setter for points_possible property.""" + self.logger.warn("Setting values on points_possible will NOT update the remote Canvas instance.") + self._points_possible = value + + @property + def can_unlink(self): + """whether the outcome can be unlinked.""" + return self._can_unlink + + @can_unlink.setter + def can_unlink(self, value): + """Setter for can_unlink property.""" + self.logger.warn("Setting values on can_unlink will NOT update the remote Canvas instance.") + self._can_unlink = value + + @property + def context_type(self): + """context_type.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def ratings(self): + """possible ratings for this outcome. included only if the outcome embeds a rubric criterion. omitted in the abbreviated form.""" + return self._ratings + + @ratings.setter + def ratings(self, value): + """Setter for ratings property.""" + self.logger.warn("Setting values on ratings will NOT update the remote Canvas instance.") + self._ratings = value + + @property + def calculation_int(self): + """this defines the variable value used by the calculation_method. included only if calculation_method uses it.""" + return self._calculation_int + + @calculation_int.setter + def calculation_int(self, value): + """Setter for calculation_int property.""" + self.logger.warn("Setting values on calculation_int will NOT update the remote Canvas instance.") + self._calculation_int = value + + @property + def calculation_method(self): + """the method used to calculate a students score.""" + return self._calculation_method + + @calculation_method.setter + def calculation_method(self, value): + """Setter for calculation_method property.""" + self.logger.warn("Setting values on calculation_method will NOT update the remote Canvas instance.") + self._calculation_method = value + + @property + def assessed(self): + """whether this outcome has been used to assess a student.""" + return self._assessed + + @assessed.setter + def assessed(self, value): + """Setter for assessed property.""" + self.logger.warn("Setting values on assessed will NOT update the remote Canvas instance.") + self._assessed = value + + @property + def id(self): + """the ID of the outcome.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def mastery_points(self): + """points necessary to demonstrate mastery outcomes. included only if the outcome embeds a rubric criterion. omitted in the abbreviated form.""" + return self._mastery_points + + @mastery_points.setter + def mastery_points(self, value): + """Setter for mastery_points property.""" + self.logger.warn("Setting values on mastery_points will NOT update the remote Canvas instance.") + self._mastery_points = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/pages.py b/venv/Lib/site-packages/pycanvas/apis/pages.py new file mode 100644 index 00000000..b8407065 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/pages.py @@ -0,0 +1,1010 @@ +"""Pages API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class PagesAPI(BaseCanvasAPI): + """Pages API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for PagesAPI.""" + super(PagesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.PagesAPI") + + def show_front_page_courses(self, course_id): + """ + Show front page. + + Retrieve the content of the front page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/courses/{course_id}/front_page with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/front_page".format(**path), data=data, params=params, single_item=True) + + def show_front_page_groups(self, group_id): + """ + Show front page. + + Retrieve the content of the front page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + self.logger.debug("GET /api/v1/groups/{group_id}/front_page with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/front_page".format(**path), data=data, params=params, single_item=True) + + def update_create_front_page_courses(self, course_id, wiki_page_body=None, wiki_page_editing_roles=None, wiki_page_notify_of_update=None, wiki_page_published=None, wiki_page_title=None): + """ + Update/create front page. + + Update the title or contents of the front page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - wiki_page[title] + """The title for the new page. NOTE: changing a page's title will change its + url. The updated url will be returned in the result.""" + if wiki_page_title is not None: + data["wiki_page[title]"] = wiki_page_title + + # OPTIONAL - wiki_page[body] + """The content for the new page.""" + if wiki_page_body is not None: + data["wiki_page[body]"] = wiki_page_body + + # OPTIONAL - wiki_page[editing_roles] + """Which user roles are allowed to edit this page. Any combination + of these roles is allowed (separated by commas). + + "teachers":: Allows editing by teachers in the course. + "students":: Allows editing by students in the course. + "members":: For group wikis, allows editing by members of the group. + "public":: Allows editing by any user.""" + if wiki_page_editing_roles is not None: + self._validate_enum(wiki_page_editing_roles, ["teachers", "students", "members", "public"]) + data["wiki_page[editing_roles]"] = wiki_page_editing_roles + + # OPTIONAL - wiki_page[notify_of_update] + """Whether participants should be notified when this page changes.""" + if wiki_page_notify_of_update is not None: + data["wiki_page[notify_of_update]"] = wiki_page_notify_of_update + + # OPTIONAL - wiki_page[published] + """Whether the page is published (true) or draft state (false).""" + if wiki_page_published is not None: + data["wiki_page[published]"] = wiki_page_published + + self.logger.debug("PUT /api/v1/courses/{course_id}/front_page with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/front_page".format(**path), data=data, params=params, single_item=True) + + def update_create_front_page_groups(self, group_id, wiki_page_body=None, wiki_page_editing_roles=None, wiki_page_notify_of_update=None, wiki_page_published=None, wiki_page_title=None): + """ + Update/create front page. + + Update the title or contents of the front page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - wiki_page[title] + """The title for the new page. NOTE: changing a page's title will change its + url. The updated url will be returned in the result.""" + if wiki_page_title is not None: + data["wiki_page[title]"] = wiki_page_title + + # OPTIONAL - wiki_page[body] + """The content for the new page.""" + if wiki_page_body is not None: + data["wiki_page[body]"] = wiki_page_body + + # OPTIONAL - wiki_page[editing_roles] + """Which user roles are allowed to edit this page. Any combination + of these roles is allowed (separated by commas). + + "teachers":: Allows editing by teachers in the course. + "students":: Allows editing by students in the course. + "members":: For group wikis, allows editing by members of the group. + "public":: Allows editing by any user.""" + if wiki_page_editing_roles is not None: + self._validate_enum(wiki_page_editing_roles, ["teachers", "students", "members", "public"]) + data["wiki_page[editing_roles]"] = wiki_page_editing_roles + + # OPTIONAL - wiki_page[notify_of_update] + """Whether participants should be notified when this page changes.""" + if wiki_page_notify_of_update is not None: + data["wiki_page[notify_of_update]"] = wiki_page_notify_of_update + + # OPTIONAL - wiki_page[published] + """Whether the page is published (true) or draft state (false).""" + if wiki_page_published is not None: + data["wiki_page[published]"] = wiki_page_published + + self.logger.debug("PUT /api/v1/groups/{group_id}/front_page with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/front_page".format(**path), data=data, params=params, single_item=True) + + def list_pages_courses(self, course_id, order=None, published=None, search_term=None, sort=None): + """ + List pages. + + List the wiki pages associated with a course or group + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - sort + """Sort results by this field.""" + if sort is not None: + self._validate_enum(sort, ["title", "created_at", "updated_at"]) + params["sort"] = sort + + # OPTIONAL - order + """The sorting order. Defaults to 'asc'.""" + if order is not None: + self._validate_enum(order, ["asc", "desc"]) + params["order"] = order + + # OPTIONAL - search_term + """The partial title of the pages to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - published + """If true, include only published paqes. If false, exclude published + pages. If not present, do not filter on published status.""" + if published is not None: + params["published"] = published + + self.logger.debug("GET /api/v1/courses/{course_id}/pages with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/pages".format(**path), data=data, params=params, all_pages=True) + + def list_pages_groups(self, group_id, order=None, published=None, search_term=None, sort=None): + """ + List pages. + + List the wiki pages associated with a course or group + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - sort + """Sort results by this field.""" + if sort is not None: + self._validate_enum(sort, ["title", "created_at", "updated_at"]) + params["sort"] = sort + + # OPTIONAL - order + """The sorting order. Defaults to 'asc'.""" + if order is not None: + self._validate_enum(order, ["asc", "desc"]) + params["order"] = order + + # OPTIONAL - search_term + """The partial title of the pages to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + # OPTIONAL - published + """If true, include only published paqes. If false, exclude published + pages. If not present, do not filter on published status.""" + if published is not None: + params["published"] = published + + self.logger.debug("GET /api/v1/groups/{group_id}/pages with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/pages".format(**path), data=data, params=params, all_pages=True) + + def create_page_courses(self, course_id, wiki_page_title, wiki_page_body=None, wiki_page_editing_roles=None, wiki_page_front_page=None, wiki_page_notify_of_update=None, wiki_page_published=None): + """ + Create page. + + Create a new wiki page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - wiki_page[title] + """The title for the new page.""" + data["wiki_page[title]"] = wiki_page_title + + # OPTIONAL - wiki_page[body] + """The content for the new page.""" + if wiki_page_body is not None: + data["wiki_page[body]"] = wiki_page_body + + # OPTIONAL - wiki_page[editing_roles] + """Which user roles are allowed to edit this page. Any combination + of these roles is allowed (separated by commas). + + "teachers":: Allows editing by teachers in the course. + "students":: Allows editing by students in the course. + "members":: For group wikis, allows editing by members of the group. + "public":: Allows editing by any user.""" + if wiki_page_editing_roles is not None: + self._validate_enum(wiki_page_editing_roles, ["teachers", "students", "members", "public"]) + data["wiki_page[editing_roles]"] = wiki_page_editing_roles + + # OPTIONAL - wiki_page[notify_of_update] + """Whether participants should be notified when this page changes.""" + if wiki_page_notify_of_update is not None: + data["wiki_page[notify_of_update]"] = wiki_page_notify_of_update + + # OPTIONAL - wiki_page[published] + """Whether the page is published (true) or draft state (false).""" + if wiki_page_published is not None: + data["wiki_page[published]"] = wiki_page_published + + # OPTIONAL - wiki_page[front_page] + """Set an unhidden page as the front page (if true)""" + if wiki_page_front_page is not None: + data["wiki_page[front_page]"] = wiki_page_front_page + + self.logger.debug("POST /api/v1/courses/{course_id}/pages with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/pages".format(**path), data=data, params=params, single_item=True) + + def create_page_groups(self, group_id, wiki_page_title, wiki_page_body=None, wiki_page_editing_roles=None, wiki_page_front_page=None, wiki_page_notify_of_update=None, wiki_page_published=None): + """ + Create page. + + Create a new wiki page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - wiki_page[title] + """The title for the new page.""" + data["wiki_page[title]"] = wiki_page_title + + # OPTIONAL - wiki_page[body] + """The content for the new page.""" + if wiki_page_body is not None: + data["wiki_page[body]"] = wiki_page_body + + # OPTIONAL - wiki_page[editing_roles] + """Which user roles are allowed to edit this page. Any combination + of these roles is allowed (separated by commas). + + "teachers":: Allows editing by teachers in the course. + "students":: Allows editing by students in the course. + "members":: For group wikis, allows editing by members of the group. + "public":: Allows editing by any user.""" + if wiki_page_editing_roles is not None: + self._validate_enum(wiki_page_editing_roles, ["teachers", "students", "members", "public"]) + data["wiki_page[editing_roles]"] = wiki_page_editing_roles + + # OPTIONAL - wiki_page[notify_of_update] + """Whether participants should be notified when this page changes.""" + if wiki_page_notify_of_update is not None: + data["wiki_page[notify_of_update]"] = wiki_page_notify_of_update + + # OPTIONAL - wiki_page[published] + """Whether the page is published (true) or draft state (false).""" + if wiki_page_published is not None: + data["wiki_page[published]"] = wiki_page_published + + # OPTIONAL - wiki_page[front_page] + """Set an unhidden page as the front page (if true)""" + if wiki_page_front_page is not None: + data["wiki_page[front_page]"] = wiki_page_front_page + + self.logger.debug("POST /api/v1/groups/{group_id}/pages with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/pages".format(**path), data=data, params=params, single_item=True) + + def show_page_courses(self, url, course_id): + """ + Show page. + + Retrieve the content of a wiki page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + self.logger.debug("GET /api/v1/courses/{course_id}/pages/{url} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/pages/{url}".format(**path), data=data, params=params, single_item=True) + + def show_page_groups(self, url, group_id): + """ + Show page. + + Retrieve the content of a wiki page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + self.logger.debug("GET /api/v1/groups/{group_id}/pages/{url} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/pages/{url}".format(**path), data=data, params=params, single_item=True) + + def update_create_page_courses(self, url, course_id, wiki_page_body=None, wiki_page_editing_roles=None, wiki_page_front_page=None, wiki_page_notify_of_update=None, wiki_page_published=None, wiki_page_title=None): + """ + Update/create page. + + Update the title or contents of a wiki page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + # OPTIONAL - wiki_page[title] + """The title for the new page. NOTE: changing a page's title will change its + url. The updated url will be returned in the result.""" + if wiki_page_title is not None: + data["wiki_page[title]"] = wiki_page_title + + # OPTIONAL - wiki_page[body] + """The content for the new page.""" + if wiki_page_body is not None: + data["wiki_page[body]"] = wiki_page_body + + # OPTIONAL - wiki_page[editing_roles] + """Which user roles are allowed to edit this page. Any combination + of these roles is allowed (separated by commas). + + "teachers":: Allows editing by teachers in the course. + "students":: Allows editing by students in the course. + "members":: For group wikis, allows editing by members of the group. + "public":: Allows editing by any user.""" + if wiki_page_editing_roles is not None: + self._validate_enum(wiki_page_editing_roles, ["teachers", "students", "members", "public"]) + data["wiki_page[editing_roles]"] = wiki_page_editing_roles + + # OPTIONAL - wiki_page[notify_of_update] + """Whether participants should be notified when this page changes.""" + if wiki_page_notify_of_update is not None: + data["wiki_page[notify_of_update]"] = wiki_page_notify_of_update + + # OPTIONAL - wiki_page[published] + """Whether the page is published (true) or draft state (false).""" + if wiki_page_published is not None: + data["wiki_page[published]"] = wiki_page_published + + # OPTIONAL - wiki_page[front_page] + """Set an unhidden page as the front page (if true)""" + if wiki_page_front_page is not None: + data["wiki_page[front_page]"] = wiki_page_front_page + + self.logger.debug("PUT /api/v1/courses/{course_id}/pages/{url} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/pages/{url}".format(**path), data=data, params=params, single_item=True) + + def update_create_page_groups(self, url, group_id, wiki_page_body=None, wiki_page_editing_roles=None, wiki_page_front_page=None, wiki_page_notify_of_update=None, wiki_page_published=None, wiki_page_title=None): + """ + Update/create page. + + Update the title or contents of a wiki page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + # OPTIONAL - wiki_page[title] + """The title for the new page. NOTE: changing a page's title will change its + url. The updated url will be returned in the result.""" + if wiki_page_title is not None: + data["wiki_page[title]"] = wiki_page_title + + # OPTIONAL - wiki_page[body] + """The content for the new page.""" + if wiki_page_body is not None: + data["wiki_page[body]"] = wiki_page_body + + # OPTIONAL - wiki_page[editing_roles] + """Which user roles are allowed to edit this page. Any combination + of these roles is allowed (separated by commas). + + "teachers":: Allows editing by teachers in the course. + "students":: Allows editing by students in the course. + "members":: For group wikis, allows editing by members of the group. + "public":: Allows editing by any user.""" + if wiki_page_editing_roles is not None: + self._validate_enum(wiki_page_editing_roles, ["teachers", "students", "members", "public"]) + data["wiki_page[editing_roles]"] = wiki_page_editing_roles + + # OPTIONAL - wiki_page[notify_of_update] + """Whether participants should be notified when this page changes.""" + if wiki_page_notify_of_update is not None: + data["wiki_page[notify_of_update]"] = wiki_page_notify_of_update + + # OPTIONAL - wiki_page[published] + """Whether the page is published (true) or draft state (false).""" + if wiki_page_published is not None: + data["wiki_page[published]"] = wiki_page_published + + # OPTIONAL - wiki_page[front_page] + """Set an unhidden page as the front page (if true)""" + if wiki_page_front_page is not None: + data["wiki_page[front_page]"] = wiki_page_front_page + + self.logger.debug("PUT /api/v1/groups/{group_id}/pages/{url} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/groups/{group_id}/pages/{url}".format(**path), data=data, params=params, single_item=True) + + def delete_page_courses(self, url, course_id): + """ + Delete page. + + Delete a wiki page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + self.logger.debug("DELETE /api/v1/courses/{course_id}/pages/{url} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/pages/{url}".format(**path), data=data, params=params, single_item=True) + + def delete_page_groups(self, url, group_id): + """ + Delete page. + + Delete a wiki page + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + self.logger.debug("DELETE /api/v1/groups/{group_id}/pages/{url} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/groups/{group_id}/pages/{url}".format(**path), data=data, params=params, single_item=True) + + def list_revisions_courses(self, url, course_id): + """ + List revisions. + + List the revisions of a page. Callers must have update rights on the page in order to see page history. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + self.logger.debug("GET /api/v1/courses/{course_id}/pages/{url}/revisions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/pages/{url}/revisions".format(**path), data=data, params=params, all_pages=True) + + def list_revisions_groups(self, url, group_id): + """ + List revisions. + + List the revisions of a page. Callers must have update rights on the page in order to see page history. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + self.logger.debug("GET /api/v1/groups/{group_id}/pages/{url}/revisions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/pages/{url}/revisions".format(**path), data=data, params=params, all_pages=True) + + def show_revision_courses_latest(self, url, course_id, summary=None): + """ + Show revision. + + Retrieve the metadata and optionally content of a revision of the page. + Note that retrieving historic versions of pages requires edit rights. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + # OPTIONAL - summary + """If set, exclude page content from results""" + if summary is not None: + params["summary"] = summary + + self.logger.debug("GET /api/v1/courses/{course_id}/pages/{url}/revisions/latest with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/pages/{url}/revisions/latest".format(**path), data=data, params=params, single_item=True) + + def show_revision_groups_latest(self, url, group_id, summary=None): + """ + Show revision. + + Retrieve the metadata and optionally content of a revision of the page. + Note that retrieving historic versions of pages requires edit rights. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + # OPTIONAL - summary + """If set, exclude page content from results""" + if summary is not None: + params["summary"] = summary + + self.logger.debug("GET /api/v1/groups/{group_id}/pages/{url}/revisions/latest with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/pages/{url}/revisions/latest".format(**path), data=data, params=params, single_item=True) + + def show_revision_courses_revision_id(self, url, course_id, revision_id, summary=None): + """ + Show revision. + + Retrieve the metadata and optionally content of a revision of the page. + Note that retrieving historic versions of pages requires edit rights. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + # REQUIRED - PATH - revision_id + """ID""" + path["revision_id"] = revision_id + + # OPTIONAL - summary + """If set, exclude page content from results""" + if summary is not None: + params["summary"] = summary + + self.logger.debug("GET /api/v1/courses/{course_id}/pages/{url}/revisions/{revision_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/pages/{url}/revisions/{revision_id}".format(**path), data=data, params=params, single_item=True) + + def show_revision_groups_revision_id(self, url, group_id, revision_id, summary=None): + """ + Show revision. + + Retrieve the metadata and optionally content of a revision of the page. + Note that retrieving historic versions of pages requires edit rights. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + # REQUIRED - PATH - revision_id + """ID""" + path["revision_id"] = revision_id + + # OPTIONAL - summary + """If set, exclude page content from results""" + if summary is not None: + params["summary"] = summary + + self.logger.debug("GET /api/v1/groups/{group_id}/pages/{url}/revisions/{revision_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/pages/{url}/revisions/{revision_id}".format(**path), data=data, params=params, single_item=True) + + def revert_to_revision_courses(self, url, course_id, revision_id): + """ + Revert to revision. + + Revert a page to a prior revision. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + # REQUIRED - PATH - revision_id + """The revision to revert to (use the + {api:WikiPagesApiController#revisions List Revisions API} to see + available revisions)""" + path["revision_id"] = revision_id + + self.logger.debug("POST /api/v1/courses/{course_id}/pages/{url}/revisions/{revision_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/pages/{url}/revisions/{revision_id}".format(**path), data=data, params=params, single_item=True) + + def revert_to_revision_groups(self, url, group_id, revision_id): + """ + Revert to revision. + + Revert a page to a prior revision. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # REQUIRED - PATH - url + """ID""" + path["url"] = url + + # REQUIRED - PATH - revision_id + """The revision to revert to (use the + {api:WikiPagesApiController#revisions List Revisions API} to see + available revisions)""" + path["revision_id"] = revision_id + + self.logger.debug("POST /api/v1/groups/{group_id}/pages/{url}/revisions/{revision_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/groups/{group_id}/pages/{url}/revisions/{revision_id}".format(**path), data=data, params=params, single_item=True) + + +class Pagerevision(BaseModel): + """Pagerevision Model.""" + + def __init__(self, body=None, edited_by=None, title=None, url=None, updated_at=None, revision_id=None, latest=None): + """Init method for Pagerevision class.""" + self._body = body + self._edited_by = edited_by + self._title = title + self._url = url + self._updated_at = updated_at + self._revision_id = revision_id + self._latest = latest + + self.logger = logging.getLogger('pycanvas.Pagerevision') + + @property + def body(self): + """the historic page contents.""" + return self._body + + @body.setter + def body(self, value): + """Setter for body property.""" + self.logger.warn("Setting values on body will NOT update the remote Canvas instance.") + self._body = value + + @property + def edited_by(self): + """the User who saved this revision, if applicable (this may not be present if the page was imported from another system).""" + return self._edited_by + + @edited_by.setter + def edited_by(self, value): + """Setter for edited_by property.""" + self.logger.warn("Setting values on edited_by will NOT update the remote Canvas instance.") + self._edited_by = value + + @property + def title(self): + """the historic page title.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def url(self): + """the following fields are not included in the index action and may be omitted from the show action via summary=1 the historic url of the page.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def updated_at(self): + """the time when this revision was saved.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def revision_id(self): + """an identifier for this revision of the page.""" + return self._revision_id + + @revision_id.setter + def revision_id(self, value): + """Setter for revision_id property.""" + self.logger.warn("Setting values on revision_id will NOT update the remote Canvas instance.") + self._revision_id = value + + @property + def latest(self): + """whether this is the latest revision or not.""" + return self._latest + + @latest.setter + def latest(self, value): + """Setter for latest property.""" + self.logger.warn("Setting values on latest will NOT update the remote Canvas instance.") + self._latest = value + + +class Page(BaseModel): + """Page Model.""" + + def __init__(self, body=None, lock_info=None, title=None, url=None, created_at=None, front_page=None, hide_from_students=None, updated_at=None, editing_roles=None, published=None, lock_explanation=None, last_edited_by=None, locked_for_user=None): + """Init method for Page class.""" + self._body = body + self._lock_info = lock_info + self._title = title + self._url = url + self._created_at = created_at + self._front_page = front_page + self._hide_from_students = hide_from_students + self._updated_at = updated_at + self._editing_roles = editing_roles + self._published = published + self._lock_explanation = lock_explanation + self._last_edited_by = last_edited_by + self._locked_for_user = locked_for_user + + self.logger = logging.getLogger('pycanvas.Page') + + @property + def body(self): + """the page content, in HTML (present when requesting a single page; omitted when listing pages).""" + return self._body + + @body.setter + def body(self, value): + """Setter for body property.""" + self.logger.warn("Setting values on body will NOT update the remote Canvas instance.") + self._body = value + + @property + def lock_info(self): + """(Optional) Information for the user about the lock. Present when locked_for_user is true.""" + return self._lock_info + + @lock_info.setter + def lock_info(self, value): + """Setter for lock_info property.""" + self.logger.warn("Setting values on lock_info will NOT update the remote Canvas instance.") + self._lock_info = value + + @property + def title(self): + """the title of the page.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def url(self): + """the unique locator for the page.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def created_at(self): + """the creation date for the page.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def front_page(self): + """whether this page is the front page for the wiki.""" + return self._front_page + + @front_page.setter + def front_page(self, value): + """Setter for front_page property.""" + self.logger.warn("Setting values on front_page will NOT update the remote Canvas instance.") + self._front_page = value + + @property + def hide_from_students(self): + """(DEPRECATED) whether this page is hidden from students (note: this is always reflected as the inverse of the published value).""" + return self._hide_from_students + + @hide_from_students.setter + def hide_from_students(self, value): + """Setter for hide_from_students property.""" + self.logger.warn("Setting values on hide_from_students will NOT update the remote Canvas instance.") + self._hide_from_students = value + + @property + def updated_at(self): + """the date the page was last updated.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def editing_roles(self): + """roles allowed to edit the page; comma-separated list comprising a combination of 'teachers', 'students', 'members', and/or 'public' if not supplied, course defaults are used.""" + return self._editing_roles + + @editing_roles.setter + def editing_roles(self, value): + """Setter for editing_roles property.""" + self.logger.warn("Setting values on editing_roles will NOT update the remote Canvas instance.") + self._editing_roles = value + + @property + def published(self): + """whether the page is published (true) or draft state (false).""" + return self._published + + @published.setter + def published(self, value): + """Setter for published property.""" + self.logger.warn("Setting values on published will NOT update the remote Canvas instance.") + self._published = value + + @property + def lock_explanation(self): + """(Optional) An explanation of why this is locked for the user. Present when locked_for_user is true.""" + return self._lock_explanation + + @lock_explanation.setter + def lock_explanation(self, value): + """Setter for lock_explanation property.""" + self.logger.warn("Setting values on lock_explanation will NOT update the remote Canvas instance.") + self._lock_explanation = value + + @property + def last_edited_by(self): + """the User who last edited the page (this may not be present if the page was imported from another system).""" + return self._last_edited_by + + @last_edited_by.setter + def last_edited_by(self, value): + """Setter for last_edited_by property.""" + self.logger.warn("Setting values on last_edited_by will NOT update the remote Canvas instance.") + self._last_edited_by = value + + @property + def locked_for_user(self): + """Whether or not this is locked for the user.""" + return self._locked_for_user + + @locked_for_user.setter + def locked_for_user(self, value): + """Setter for locked_for_user property.""" + self.logger.warn("Setting values on locked_for_user will NOT update the remote Canvas instance.") + self._locked_for_user = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/poll_choices.py b/venv/Lib/site-packages/pycanvas/apis/poll_choices.py new file mode 100644 index 00000000..f21227e0 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/poll_choices.py @@ -0,0 +1,212 @@ +"""PollChoices API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class PollChoicesAPI(BaseCanvasAPI): + """PollChoices API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for PollChoicesAPI.""" + super(PollChoicesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.PollChoicesAPI") + + def list_poll_choices_in_poll(self, poll_id): + """ + List poll choices in a poll. + + Returns the list of PollChoices in this poll. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + self.logger.debug("GET /api/v1/polls/{poll_id}/poll_choices with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls/{poll_id}/poll_choices".format(**path), data=data, params=params, no_data=True) + + def get_single_poll_choice(self, id, poll_id): + """ + Get a single poll choice. + + Returns the poll choice with the given id + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/polls/{poll_id}/poll_choices/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls/{poll_id}/poll_choices/{id}".format(**path), data=data, params=params, no_data=True) + + def create_single_poll_choice(self, poll_id, poll_choices_text, poll_choices_is_correct=None, poll_choices_position=None): + """ + Create a single poll choice. + + Create a new poll choice for this poll + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - poll_choices[text] + """The descriptive text of the poll choice.""" + data["poll_choices[text]"] = poll_choices_text + + # OPTIONAL - poll_choices[is_correct] + """Whether this poll choice is considered correct or not. Defaults to false.""" + if poll_choices_is_correct is not None: + data["poll_choices[is_correct]"] = poll_choices_is_correct + + # OPTIONAL - poll_choices[position] + """The order this poll choice should be returned in the context it's sibling poll choices.""" + if poll_choices_position is not None: + data["poll_choices[position]"] = poll_choices_position + + self.logger.debug("POST /api/v1/polls/{poll_id}/poll_choices with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/polls/{poll_id}/poll_choices".format(**path), data=data, params=params, no_data=True) + + def update_single_poll_choice(self, id, poll_id, poll_choices_text, poll_choices_is_correct=None, poll_choices_position=None): + """ + Update a single poll choice. + + Update an existing poll choice for this poll + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - poll_choices[text] + """The descriptive text of the poll choice.""" + data["poll_choices[text]"] = poll_choices_text + + # OPTIONAL - poll_choices[is_correct] + """Whether this poll choice is considered correct or not. Defaults to false.""" + if poll_choices_is_correct is not None: + data["poll_choices[is_correct]"] = poll_choices_is_correct + + # OPTIONAL - poll_choices[position] + """The order this poll choice should be returned in the context it's sibling poll choices.""" + if poll_choices_position is not None: + data["poll_choices[position]"] = poll_choices_position + + self.logger.debug("PUT /api/v1/polls/{poll_id}/poll_choices/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/polls/{poll_id}/poll_choices/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_poll_choice(self, id, poll_id): + """ + Delete a poll choice. + + 204 No Content response code is returned if the deletion was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/polls/{poll_id}/poll_choices/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/polls/{poll_id}/poll_choices/{id}".format(**path), data=data, params=params, no_data=True) + + +class Pollchoice(BaseModel): + """Pollchoice Model.""" + + def __init__(self, id, poll_id, text, is_correct=None, position=None): + """Init method for Pollchoice class.""" + self._is_correct = is_correct + self._position = position + self._id = id + self._poll_id = poll_id + self._text = text + + self.logger = logging.getLogger('pycanvas.Pollchoice') + + @property + def is_correct(self): + """Specifies whether or not this poll choice is a 'correct' choice.""" + return self._is_correct + + @is_correct.setter + def is_correct(self, value): + """Setter for is_correct property.""" + self.logger.warn("Setting values on is_correct will NOT update the remote Canvas instance.") + self._is_correct = value + + @property + def position(self): + """The order of the poll choice in relation to it's sibling poll choices.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def id(self): + """The unique identifier for the poll choice.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def poll_id(self): + """The id of the poll this poll choice belongs to.""" + return self._poll_id + + @poll_id.setter + def poll_id(self, value): + """Setter for poll_id property.""" + self.logger.warn("Setting values on poll_id will NOT update the remote Canvas instance.") + self._poll_id = value + + @property + def text(self): + """The text of the poll choice.""" + return self._text + + @text.setter + def text(self, value): + """Setter for text property.""" + self.logger.warn("Setting values on text will NOT update the remote Canvas instance.") + self._text = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/poll_sessions.py b/venv/Lib/site-packages/pycanvas/apis/poll_sessions.py new file mode 100644 index 00000000..d4dd9f39 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/poll_sessions.py @@ -0,0 +1,329 @@ +"""PollSessions API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class PollSessionsAPI(BaseCanvasAPI): + """PollSessions API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for PollSessionsAPI.""" + super(PollSessionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.PollSessionsAPI") + + def list_poll_sessions_for_poll(self, poll_id): + """ + List poll sessions for a poll. + + Returns the list of PollSessions in this poll. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + self.logger.debug("GET /api/v1/polls/{poll_id}/poll_sessions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls/{poll_id}/poll_sessions".format(**path), data=data, params=params, no_data=True) + + def get_results_for_single_poll_session(self, id, poll_id): + """ + Get the results for a single poll session. + + Returns the poll session with the given id + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/polls/{poll_id}/poll_sessions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls/{poll_id}/poll_sessions/{id}".format(**path), data=data, params=params, no_data=True) + + def create_single_poll_session(self, poll_id, poll_sessions_course_id, poll_sessions_course_section_id=None, poll_sessions_has_public_results=None): + """ + Create a single poll session. + + Create a new poll session for this poll + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - poll_sessions[course_id] + """The id of the course this session is associated with.""" + data["poll_sessions[course_id]"] = poll_sessions_course_id + + # OPTIONAL - poll_sessions[course_section_id] + """The id of the course section this session is associated with.""" + if poll_sessions_course_section_id is not None: + data["poll_sessions[course_section_id]"] = poll_sessions_course_section_id + + # OPTIONAL - poll_sessions[has_public_results] + """Whether or not results are viewable by students.""" + if poll_sessions_has_public_results is not None: + data["poll_sessions[has_public_results]"] = poll_sessions_has_public_results + + self.logger.debug("POST /api/v1/polls/{poll_id}/poll_sessions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/polls/{poll_id}/poll_sessions".format(**path), data=data, params=params, no_data=True) + + def update_single_poll_session(self, id, poll_id, poll_sessions_course_id=None, poll_sessions_course_section_id=None, poll_sessions_has_public_results=None): + """ + Update a single poll session. + + Update an existing poll session for this poll + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - poll_sessions[course_id] + """The id of the course this session is associated with.""" + if poll_sessions_course_id is not None: + data["poll_sessions[course_id]"] = poll_sessions_course_id + + # OPTIONAL - poll_sessions[course_section_id] + """The id of the course section this session is associated with.""" + if poll_sessions_course_section_id is not None: + data["poll_sessions[course_section_id]"] = poll_sessions_course_section_id + + # OPTIONAL - poll_sessions[has_public_results] + """Whether or not results are viewable by students.""" + if poll_sessions_has_public_results is not None: + data["poll_sessions[has_public_results]"] = poll_sessions_has_public_results + + self.logger.debug("PUT /api/v1/polls/{poll_id}/poll_sessions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/polls/{poll_id}/poll_sessions/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_poll_session(self, id, poll_id): + """ + Delete a poll session. + + 204 No Content response code is returned if the deletion was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/polls/{poll_id}/poll_sessions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/polls/{poll_id}/poll_sessions/{id}".format(**path), data=data, params=params, no_data=True) + + def open_poll_session(self, id, poll_id): + """ + Open a poll session. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/polls/{poll_id}/poll_sessions/{id}/open with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls/{poll_id}/poll_sessions/{id}/open".format(**path), data=data, params=params, no_data=True) + + def close_opened_poll_session(self, id, poll_id): + """ + Close an opened poll session. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/polls/{poll_id}/poll_sessions/{id}/close with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls/{poll_id}/poll_sessions/{id}/close".format(**path), data=data, params=params, no_data=True) + + def list_opened_poll_sessions(self): + """ + List opened poll sessions. + + Lists all opened poll sessions available to the current user. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/poll_sessions/opened with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/poll_sessions/opened".format(**path), data=data, params=params, no_data=True) + + def list_closed_poll_sessions(self): + """ + List closed poll sessions. + + Lists all closed poll sessions available to the current user. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/poll_sessions/closed with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/poll_sessions/closed".format(**path), data=data, params=params, no_data=True) + + +class Pollsession(BaseModel): + """Pollsession Model.""" + + def __init__(self, id, poll_id, course_id, poll_submissions=None, created_at=None, course_section_id=None, has_public_results=None, results=None, is_published=None): + """Init method for Pollsession class.""" + self._poll_submissions = poll_submissions + self._created_at = created_at + self._course_section_id = course_section_id + self._has_public_results = has_public_results + self._poll_id = poll_id + self._results = results + self._course_id = course_id + self._id = id + self._is_published = is_published + + self.logger = logging.getLogger('pycanvas.Pollsession') + + @property + def poll_submissions(self): + """If the poll session has public results, this will return an array of all submissions, viewable by both students and teachers. If the results are not public, for students it will return their submission only.""" + return self._poll_submissions + + @poll_submissions.setter + def poll_submissions(self, value): + """Setter for poll_submissions property.""" + self.logger.warn("Setting values on poll_submissions will NOT update the remote Canvas instance.") + self._poll_submissions = value + + @property + def created_at(self): + """The time at which the poll session was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def course_section_id(self): + """The id of the Course Section this poll session is associated with.""" + return self._course_section_id + + @course_section_id.setter + def course_section_id(self, value): + """Setter for course_section_id property.""" + self.logger.warn("Setting values on course_section_id will NOT update the remote Canvas instance.") + self._course_section_id = value + + @property + def has_public_results(self): + """Specifies whether the results are viewable by students.""" + return self._has_public_results + + @has_public_results.setter + def has_public_results(self, value): + """Setter for has_public_results property.""" + self.logger.warn("Setting values on has_public_results will NOT update the remote Canvas instance.") + self._has_public_results = value + + @property + def poll_id(self): + """The id of the Poll this poll session is associated with.""" + return self._poll_id + + @poll_id.setter + def poll_id(self, value): + """Setter for poll_id property.""" + self.logger.warn("Setting values on poll_id will NOT update the remote Canvas instance.") + self._poll_id = value + + @property + def results(self): + """The results of the submissions of the poll. Each key is the poll choice id, and the value is the count of submissions.""" + return self._results + + @results.setter + def results(self, value): + """Setter for results property.""" + self.logger.warn("Setting values on results will NOT update the remote Canvas instance.") + self._results = value + + @property + def course_id(self): + """The id of the Course this poll session is associated with.""" + return self._course_id + + @course_id.setter + def course_id(self, value): + """Setter for course_id property.""" + self.logger.warn("Setting values on course_id will NOT update the remote Canvas instance.") + self._course_id = value + + @property + def id(self): + """The unique identifier for the poll session.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def is_published(self): + """Specifies whether or not this poll session has been published for students to participate in.""" + return self._is_published + + @is_published.setter + def is_published(self, value): + """Setter for is_published property.""" + self.logger.warn("Setting values on is_published will NOT update the remote Canvas instance.") + self._is_published = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/poll_submissions.py b/venv/Lib/site-packages/pycanvas/apis/poll_submissions.py new file mode 100644 index 00000000..a6980106 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/poll_submissions.py @@ -0,0 +1,125 @@ +"""PollSubmissions API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class PollSubmissionsAPI(BaseCanvasAPI): + """PollSubmissions API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for PollSubmissionsAPI.""" + super(PollSubmissionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.PollSubmissionsAPI") + + def get_single_poll_submission(self, id, poll_id, poll_session_id): + """ + Get a single poll submission. + + Returns the poll submission with the given id + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - poll_session_id + """ID""" + path["poll_session_id"] = poll_session_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/polls/{poll_id}/poll_sessions/{poll_session_id}/poll_submissions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls/{poll_id}/poll_sessions/{poll_session_id}/poll_submissions/{id}".format(**path), data=data, params=params, no_data=True) + + def create_single_poll_submission(self, poll_id, poll_session_id, poll_submissions_poll_choice_id): + """ + Create a single poll submission. + + Create a new poll submission for this poll session + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - poll_id + """ID""" + path["poll_id"] = poll_id + + # REQUIRED - PATH - poll_session_id + """ID""" + path["poll_session_id"] = poll_session_id + + # REQUIRED - poll_submissions[poll_choice_id] + """The chosen poll choice for this submission.""" + data["poll_submissions[poll_choice_id]"] = poll_submissions_poll_choice_id + + self.logger.debug("POST /api/v1/polls/{poll_id}/poll_sessions/{poll_session_id}/poll_submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/polls/{poll_id}/poll_sessions/{poll_session_id}/poll_submissions".format(**path), data=data, params=params, no_data=True) + + +class Pollsubmission(BaseModel): + """Pollsubmission Model.""" + + def __init__(self, id, poll_choice, created_at=None, user_id=None, poll_choice_id=None): + """Init method for Pollsubmission class.""" + self._created_at = created_at + self._user_id = user_id + self._id = id + self._poll_choice_id = poll_choice_id + + self.logger = logging.getLogger('pycanvas.Pollsubmission') + + @property + def created_at(self): + """The date and time the poll submission was submitted.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def user_id(self): + """the unique identifier of the user who submitted this poll submission.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def id(self): + """The unique identifier for the poll submission.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def poll_choice_id(self): + """The unique identifier of the poll choice chosen for this submission.""" + return self._poll_choice_id + + @poll_choice_id.setter + def poll_choice_id(self, value): + """Setter for poll_choice_id property.""" + self.logger.warn("Setting values on poll_choice_id will NOT update the remote Canvas instance.") + self._poll_choice_id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/polls.py b/venv/Lib/site-packages/pycanvas/apis/polls.py new file mode 100644 index 00000000..a1d48af5 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/polls.py @@ -0,0 +1,194 @@ +"""Polls API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class PollsAPI(BaseCanvasAPI): + """Polls API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for PollsAPI.""" + super(PollsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.PollsAPI") + + def list_polls(self): + """ + List polls. + + Returns the list of polls for the current user. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/polls with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls".format(**path), data=data, params=params, no_data=True) + + def get_single_poll(self, id): + """ + Get a single poll. + + Returns the poll with the given id + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/polls/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/polls/{id}".format(**path), data=data, params=params, no_data=True) + + def create_single_poll(self, polls_question, polls_description=None): + """ + Create a single poll. + + Create a new poll for the current user + """ + path = {} + data = {} + params = {} + + # REQUIRED - polls[question] + """The title of the poll.""" + data["polls[question]"] = polls_question + + # OPTIONAL - polls[description] + """A brief description or instructions for the poll.""" + if polls_description is not None: + data["polls[description]"] = polls_description + + self.logger.debug("POST /api/v1/polls with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/polls".format(**path), data=data, params=params, no_data=True) + + def update_single_poll(self, id, polls_question, polls_description=None): + """ + Update a single poll. + + Update an existing poll belonging to the current user + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - polls[question] + """The title of the poll.""" + data["polls[question]"] = polls_question + + # OPTIONAL - polls[description] + """A brief description or instructions for the poll.""" + if polls_description is not None: + data["polls[description]"] = polls_description + + self.logger.debug("PUT /api/v1/polls/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/polls/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_poll(self, id): + """ + Delete a poll. + + 204 No Content response code is returned if the deletion was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/polls/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/polls/{id}".format(**path), data=data, params=params, no_data=True) + + +class Poll(BaseModel): + """Poll Model.""" + + def __init__(self, id, question, user_id=None, description=None, total_results=None, created_at=None): + """Init method for Poll class.""" + self._user_id = user_id + self._description = description + self._total_results = total_results + self._created_at = created_at + self._question = question + self._id = id + + self.logger = logging.getLogger('pycanvas.Poll') + + @property + def user_id(self): + """The unique identifier for the user that created the poll.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def description(self): + """A short description of the poll.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def total_results(self): + """An aggregate of the results of all associated poll sessions, with the poll choice id as the key, and the aggregated submission count as the value.""" + return self._total_results + + @total_results.setter + def total_results(self, value): + """Setter for total_results property.""" + self.logger.warn("Setting values on total_results will NOT update the remote Canvas instance.") + self._total_results = value + + @property + def created_at(self): + """The time at which the poll was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def question(self): + """The question/title of the poll.""" + return self._question + + @question.setter + def question(self, value): + """Setter for question property.""" + self.logger.warn("Setting values on question will NOT update the remote Canvas instance.") + self._question = value + + @property + def id(self): + """The unique identifier for the poll.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/progress.py b/venv/Lib/site-packages/pycanvas/apis/progress.py new file mode 100644 index 00000000..f9305ebc --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/progress.py @@ -0,0 +1,176 @@ +"""Progress API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class ProgressAPI(BaseCanvasAPI): + """Progress API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for ProgressAPI.""" + super(ProgressAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.ProgressAPI") + + def query_progress(self, id): + """ + Query progress. + + Return completion and status information about an asynchronous job + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/progress/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/progress/{id}".format(**path), data=data, params=params, single_item=True) + + +class Progress(BaseModel): + """Progress Model.""" + + def __init__(self, completion=None, user_id=None, workflow_state=None, context_type=None, context_id=None, created_at=None, updated_at=None, url=None, tag=None, message=None, id=None): + """Init method for Progress class.""" + self._completion = completion + self._user_id = user_id + self._workflow_state = workflow_state + self._context_type = context_type + self._context_id = context_id + self._created_at = created_at + self._updated_at = updated_at + self._url = url + self._tag = tag + self._message = message + self._id = id + + self.logger = logging.getLogger('pycanvas.Progress') + + @property + def completion(self): + """percent completed.""" + return self._completion + + @completion.setter + def completion(self, value): + """Setter for completion property.""" + self.logger.warn("Setting values on completion will NOT update the remote Canvas instance.") + self._completion = value + + @property + def user_id(self): + """the id of the user who started the job.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def workflow_state(self): + """the state of the job one of 'queued', 'running', 'completed', 'failed'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def context_type(self): + """context_type.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def context_id(self): + """the context owning the job.""" + return self._context_id + + @context_id.setter + def context_id(self, value): + """Setter for context_id property.""" + self.logger.warn("Setting values on context_id will NOT update the remote Canvas instance.") + self._context_id = value + + @property + def created_at(self): + """the time the job was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def updated_at(self): + """the time the job was last updated.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def url(self): + """url where a progress update can be retrieved.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def tag(self): + """the type of operation.""" + return self._tag + + @tag.setter + def tag(self, value): + """Setter for tag property.""" + self.logger.warn("Setting values on tag will NOT update the remote Canvas instance.") + self._tag = value + + @property + def message(self): + """optional details about the job.""" + return self._message + + @message.setter + def message(self, value): + """Setter for message property.""" + self.logger.warn("Setting values on message will NOT update the remote Canvas instance.") + self._message = value + + @property + def id(self): + """the ID of the Progress object.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_assignment_overrides.py b/venv/Lib/site-packages/pycanvas/apis/quiz_assignment_overrides.py new file mode 100644 index 00000000..6e4d0595 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_assignment_overrides.py @@ -0,0 +1,192 @@ +"""QuizAssignmentOverrides API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizAssignmentOverridesAPI(BaseCanvasAPI): + """QuizAssignmentOverrides API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizAssignmentOverridesAPI.""" + super(QuizAssignmentOverridesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizAssignmentOverridesAPI") + + def retrieve_assignment_overridden_dates_for_quizzes(self, course_id, quiz_assignment_overrides_0_quiz_ids=None): + """ + Retrieve assignment-overridden dates for quizzes. + + Retrieve the actual due-at, unlock-at, and available-at dates for quizzes + based on the assignment overrides active for the current API user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - quiz_assignment_overrides[0][quiz_ids] + """An array of quiz IDs. If omitted, overrides for all quizzes available to + the operating user will be returned.""" + if quiz_assignment_overrides_0_quiz_ids is not None: + params["quiz_assignment_overrides[0][quiz_ids]"] = quiz_assignment_overrides_0_quiz_ids + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/assignment_overrides with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/assignment_overrides".format(**path), data=data, params=params, single_item=True) + + +class Quizassignmentoverride(BaseModel): + """Quizassignmentoverride Model. + Set of assignment-overridden dates for a quiz.""" + + def __init__(self, unlock_at=None, title=None, due_at=None, lock_at=None, base=None, id=None): + """Init method for Quizassignmentoverride class.""" + self._unlock_at = unlock_at + self._title = title + self._due_at = due_at + self._lock_at = lock_at + self._base = base + self._id = id + + self.logger = logging.getLogger('pycanvas.Quizassignmentoverride') + + @property + def unlock_at(self): + """Date when the quiz becomes available for taking.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def title(self): + """Title of the section this assignment override is for, if any.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def due_at(self): + """The date after which any quiz submission is considered late.""" + return self._due_at + + @due_at.setter + def due_at(self, value): + """Setter for due_at property.""" + self.logger.warn("Setting values on due_at will NOT update the remote Canvas instance.") + self._due_at = value + + @property + def lock_at(self): + """When the quiz will stop being available for taking. A value of null means it can always be taken.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def base(self): + """If this property is present, it means that dates in this structure are not based on an assignment override, but are instead for all students.""" + return self._base + + @base.setter + def base(self, value): + """Setter for base property.""" + self.logger.warn("Setting values on base will NOT update the remote Canvas instance.") + self._base = value + + @property + def id(self): + """ID of the assignment override, unless this is the base construct, in which case the 'id' field is omitted.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Quizassignmentoverridesetcontainer(BaseModel): + """Quizassignmentoverridesetcontainer Model. + Container for set of assignment-overridden dates for a quiz.""" + + def __init__(self, quiz_assignment_overrides=None): + """Init method for Quizassignmentoverridesetcontainer class.""" + self._quiz_assignment_overrides = quiz_assignment_overrides + + self.logger = logging.getLogger('pycanvas.Quizassignmentoverridesetcontainer') + + @property + def quiz_assignment_overrides(self): + """The QuizAssignmentOverrideSet.""" + return self._quiz_assignment_overrides + + @quiz_assignment_overrides.setter + def quiz_assignment_overrides(self, value): + """Setter for quiz_assignment_overrides property.""" + self.logger.warn("Setting values on quiz_assignment_overrides will NOT update the remote Canvas instance.") + self._quiz_assignment_overrides = value + + +class Quizassignmentoverrideset(BaseModel): + """Quizassignmentoverrideset Model. + Set of assignment-overridden dates for a quiz.""" + + def __init__(self, due_dates=None, quiz_id=None, all_dates=None): + """Init method for Quizassignmentoverrideset class.""" + self._due_dates = due_dates + self._quiz_id = quiz_id + self._all_dates = all_dates + + self.logger = logging.getLogger('pycanvas.Quizassignmentoverrideset') + + @property + def due_dates(self): + """An array of quiz assignment overrides. For students, this array will always contain a single item which is the set of dates that apply to that student. For teachers and staff, it may contain more.""" + return self._due_dates + + @due_dates.setter + def due_dates(self, value): + """Setter for due_dates property.""" + self.logger.warn("Setting values on due_dates will NOT update the remote Canvas instance.") + self._due_dates = value + + @property + def quiz_id(self): + """ID of the quiz those dates are for.""" + return self._quiz_id + + @quiz_id.setter + def quiz_id(self, value): + """Setter for quiz_id property.""" + self.logger.warn("Setting values on quiz_id will NOT update the remote Canvas instance.") + self._quiz_id = value + + @property + def all_dates(self): + """An array of all assignment overrides active for the quiz. This is visible only to teachers and staff.""" + return self._all_dates + + @all_dates.setter + def all_dates(self, value): + """Setter for all_dates property.""" + self.logger.warn("Setting values on all_dates will NOT update the remote Canvas instance.") + self._all_dates = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_extensions.py b/venv/Lib/site-packages/pycanvas/apis/quiz_extensions.py new file mode 100644 index 00000000..2b8c5060 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_extensions.py @@ -0,0 +1,160 @@ +"""QuizExtensions API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizExtensionsAPI(BaseCanvasAPI): + """QuizExtensions API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizExtensionsAPI.""" + super(QuizExtensionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizExtensionsAPI") + + def set_extensions_for_student_quiz_submissions(self, quiz_id, user_id, course_id, extend_from_end_at=None, extend_from_now=None, extra_attempts=None, extra_time=None, manually_unlocked=None): + """ + Set extensions for student quiz submissions. + + Responses + + * 200 OK if the request was successful + * 403 Forbidden if you are not allowed to extend quizzes for this course + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - user_id + """The ID of the user we want to add quiz extensions for.""" + data["user_id"] = user_id + + # OPTIONAL - extra_attempts + """Number of times the student is allowed to re-take the quiz over the + multiple-attempt limit. This is limited to 1000 attempts or less.""" + if extra_attempts is not None: + data["extra_attempts"] = extra_attempts + + # OPTIONAL - extra_time + """The number of extra minutes to allow for all attempts. This will + add to the existing time limit on the submission. This is limited to + 10080 minutes (1 week)""" + if extra_time is not None: + data["extra_time"] = extra_time + + # OPTIONAL - manually_unlocked + """Allow the student to take the quiz even if it's locked for + everyone else.""" + if manually_unlocked is not None: + data["manually_unlocked"] = manually_unlocked + + # OPTIONAL - extend_from_now + """The number of minutes to extend the quiz from the current time. This is + mutually exclusive to extend_from_end_at. This is limited to 1440 + minutes (24 hours)""" + if extend_from_now is not None: + data["extend_from_now"] = extend_from_now + + # OPTIONAL - extend_from_end_at + """The number of minutes to extend the quiz beyond the quiz's current + ending time. This is mutually exclusive to extend_from_now. This is + limited to 1440 minutes (24 hours)""" + if extend_from_end_at is not None: + data["extend_from_end_at"] = extend_from_end_at + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/extensions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/extensions".format(**path), data=data, params=params, no_data=True) + + +class Quizextension(BaseModel): + """Quizextension Model.""" + + def __init__(self, quiz_id, user_id, end_at=None, manually_unlocked=None, extra_attempts=None, extra_time=None): + """Init method for Quizextension class.""" + self._user_id = user_id + self._end_at = end_at + self._manually_unlocked = manually_unlocked + self._extra_attempts = extra_attempts + self._quiz_id = quiz_id + self._extra_time = extra_time + + self.logger = logging.getLogger('pycanvas.Quizextension') + + @property + def user_id(self): + """The ID of the Student that needs the quiz extension.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def end_at(self): + """The time at which the quiz submission will be overdue, and be flagged as a late submission.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def manually_unlocked(self): + """The student can take the quiz even if it's locked for everyone else.""" + return self._manually_unlocked + + @manually_unlocked.setter + def manually_unlocked(self, value): + """Setter for manually_unlocked property.""" + self.logger.warn("Setting values on manually_unlocked will NOT update the remote Canvas instance.") + self._manually_unlocked = value + + @property + def extra_attempts(self): + """Number of times the student is allowed to re-take the quiz over the multiple-attempt limit.""" + return self._extra_attempts + + @extra_attempts.setter + def extra_attempts(self, value): + """Setter for extra_attempts property.""" + self.logger.warn("Setting values on extra_attempts will NOT update the remote Canvas instance.") + self._extra_attempts = value + + @property + def quiz_id(self): + """The ID of the Quiz the quiz extension belongs to.""" + return self._quiz_id + + @quiz_id.setter + def quiz_id(self, value): + """Setter for quiz_id property.""" + self.logger.warn("Setting values on quiz_id will NOT update the remote Canvas instance.") + self._quiz_id = value + + @property + def extra_time(self): + """Amount of extra time allowed for the quiz submission, in minutes.""" + return self._extra_time + + @extra_time.setter + def extra_time(self, value): + """Setter for extra_time property.""" + self.logger.warn("Setting values on extra_time will NOT update the remote Canvas instance.") + self._extra_time = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_ip_filters.py b/venv/Lib/site-packages/pycanvas/apis/quiz_ip_filters.py new file mode 100644 index 00000000..d7eeabb6 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_ip_filters.py @@ -0,0 +1,86 @@ +"""QuizIpFilters API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizIpFiltersAPI(BaseCanvasAPI): + """QuizIpFilters API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizIpFiltersAPI.""" + super(QuizIpFiltersAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizIpFiltersAPI") + + def get_available_quiz_ip_filters(self, quiz_id, course_id): + """ + Get available quiz IP filters. + + Get a list of available IP filters for this Quiz. + + 200 OK response code is returned if the request was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/ip_filters with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/ip_filters".format(**path), data=data, params=params, no_data=True) + + +class Quizipfilter(BaseModel): + """Quizipfilter Model.""" + + def __init__(self, name, account, filter): + """Init method for Quizipfilter class.""" + self._filter = filter + self._account = account + self._name = name + + self.logger = logging.getLogger('pycanvas.Quizipfilter') + + @property + def filter(self): + """An IP address (or range mask) this filter embodies.""" + return self._filter + + @filter.setter + def filter(self, value): + """Setter for filter property.""" + self.logger.warn("Setting values on filter will NOT update the remote Canvas instance.") + self._filter = value + + @property + def account(self): + """Name of the Account (or Quiz) the IP filter is defined in.""" + return self._account + + @account.setter + def account(self, value): + """Setter for account property.""" + self.logger.warn("Setting values on account will NOT update the remote Canvas instance.") + self._account = value + + @property + def name(self): + """A unique name for the filter.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_question_groups.py b/venv/Lib/site-packages/pycanvas/apis/quiz_question_groups.py new file mode 100644 index 00000000..656a1bdf --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_question_groups.py @@ -0,0 +1,283 @@ +"""QuizQuestionGroups API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizQuestionGroupsAPI(BaseCanvasAPI): + """QuizQuestionGroups API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizQuestionGroupsAPI.""" + super(QuizQuestionGroupsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizQuestionGroupsAPI") + + def get_single_quiz_group(self, id, quiz_id, course_id): + """ + Get a single quiz group. + + Returns details of the quiz group with the given id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/groups/{id}".format(**path), data=data, params=params, single_item=True) + + def create_question_group(self, quiz_id, course_id, quiz_groups_assessment_question_bank_id=None, quiz_groups_name=None, quiz_groups_pick_count=None, quiz_groups_question_points=None): + """ + Create a question group. + + Create a new question group for this quiz + + 201 Created response code is returned if the creation was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - quiz_groups[name] + """The name of the question group.""" + if quiz_groups_name is not None: + data["quiz_groups[name]"] = quiz_groups_name + + # OPTIONAL - quiz_groups[pick_count] + """The number of questions to randomly select for this group.""" + if quiz_groups_pick_count is not None: + data["quiz_groups[pick_count]"] = quiz_groups_pick_count + + # OPTIONAL - quiz_groups[question_points] + """The number of points to assign to each question in the group.""" + if quiz_groups_question_points is not None: + data["quiz_groups[question_points]"] = quiz_groups_question_points + + # OPTIONAL - quiz_groups[assessment_question_bank_id] + """The id of the assessment question bank to pull questions from.""" + if quiz_groups_assessment_question_bank_id is not None: + data["quiz_groups[assessment_question_bank_id]"] = quiz_groups_assessment_question_bank_id + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/groups with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/groups".format(**path), data=data, params=params, no_data=True) + + def update_question_group(self, id, quiz_id, course_id, quiz_groups_name=None, quiz_groups_pick_count=None, quiz_groups_question_points=None): + """ + Update a question group. + + Update a question group + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - quiz_groups[name] + """The name of the question group.""" + if quiz_groups_name is not None: + data["quiz_groups[name]"] = quiz_groups_name + + # OPTIONAL - quiz_groups[pick_count] + """The number of questions to randomly select for this group.""" + if quiz_groups_pick_count is not None: + data["quiz_groups[pick_count]"] = quiz_groups_pick_count + + # OPTIONAL - quiz_groups[question_points] + """The number of points to assign to each question in the group.""" + if quiz_groups_question_points is not None: + data["quiz_groups[question_points]"] = quiz_groups_question_points + + self.logger.debug("PUT /api/v1/courses/{course_id}/quizzes/{quiz_id}/groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/groups/{id}".format(**path), data=data, params=params, no_data=True) + + def delete_question_group(self, id, quiz_id, course_id): + """ + Delete a question group. + + Delete a question group + + 204 No Content response code is returned if the deletion was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/quizzes/{quiz_id}/groups/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/groups/{id}".format(**path), data=data, params=params, no_data=True) + + def reorder_question_groups(self, id, quiz_id, order_id, course_id, order_type=None): + """ + Reorder question groups. + + Change the order of the quiz questions within the group + + 204 No Content response code is returned if the reorder was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - order[id] + """The associated item's unique identifier""" + data["order[id]"] = order_id + + # OPTIONAL - order[type] + """The type of item is always 'question' for a group""" + if order_type is not None: + self._validate_enum(order_type, ["question"]) + data["order[type]"] = order_type + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/groups/{id}/reorder with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/groups/{id}/reorder".format(**path), data=data, params=params, no_data=True) + + +class Quizgroup(BaseModel): + """Quizgroup Model.""" + + def __init__(self, id, quiz_id, name=None, question_points=None, position=None, pick_count=None, assessment_question_bank_id=None): + """Init method for Quizgroup class.""" + self._name = name + self._question_points = question_points + self._id = id + self._position = position + self._pick_count = pick_count + self._quiz_id = quiz_id + self._assessment_question_bank_id = assessment_question_bank_id + + self.logger = logging.getLogger('pycanvas.Quizgroup') + + @property + def name(self): + """The name of the question group.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def question_points(self): + """The amount of points allotted to each question in the group.""" + return self._question_points + + @question_points.setter + def question_points(self, value): + """Setter for question_points property.""" + self.logger.warn("Setting values on question_points will NOT update the remote Canvas instance.") + self._question_points = value + + @property + def id(self): + """The ID of the question group.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def position(self): + """The order in which the question group will be retrieved and displayed.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def pick_count(self): + """The number of questions to pick from the group to display to the student.""" + return self._pick_count + + @pick_count.setter + def pick_count(self, value): + """Setter for pick_count property.""" + self.logger.warn("Setting values on pick_count will NOT update the remote Canvas instance.") + self._pick_count = value + + @property + def quiz_id(self): + """The ID of the Quiz the question group belongs to.""" + return self._quiz_id + + @quiz_id.setter + def quiz_id(self, value): + """Setter for quiz_id property.""" + self.logger.warn("Setting values on quiz_id will NOT update the remote Canvas instance.") + self._quiz_id = value + + @property + def assessment_question_bank_id(self): + """The ID of the Assessment question bank to pull questions from.""" + return self._assessment_question_bank_id + + @assessment_question_bank_id.setter + def assessment_question_bank_id(self, value): + """Setter for assessment_question_bank_id property.""" + self.logger.warn("Setting values on assessment_question_bank_id will NOT update the remote Canvas instance.") + self._assessment_question_bank_id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_questions.py b/venv/Lib/site-packages/pycanvas/apis/quiz_questions.py new file mode 100644 index 00000000..94fd2659 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_questions.py @@ -0,0 +1,605 @@ +"""QuizQuestions API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizQuestionsAPI(BaseCanvasAPI): + """QuizQuestions API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizQuestionsAPI.""" + super(QuizQuestionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizQuestionsAPI") + + def list_questions_in_quiz_or_submission(self, quiz_id, course_id, quiz_submission_attempt=None, quiz_submission_id=None): + """ + List questions in a quiz or a submission. + + Returns the list of QuizQuestions in this quiz. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - quiz_submission_id + """If specified, the endpoint will return the questions that were presented + for that submission. This is useful if the quiz has been modified after + the submission was created and the latest quiz version's set of questions + does not match the submission's. + NOTE: you must specify quiz_submission_attempt as well if you specify this + parameter.""" + if quiz_submission_id is not None: + params["quiz_submission_id"] = quiz_submission_id + + # OPTIONAL - quiz_submission_attempt + """The attempt of the submission you want the questions for.""" + if quiz_submission_attempt is not None: + params["quiz_submission_attempt"] = quiz_submission_attempt + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/questions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/questions".format(**path), data=data, params=params, all_pages=True) + + def get_single_quiz_question(self, id, quiz_id, course_id): + """ + Get a single quiz question. + + Returns the quiz question with the given id + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """The quiz question unique identifier.""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/questions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/questions/{id}".format(**path), data=data, params=params, single_item=True) + + def create_single_quiz_question(self, quiz_id, course_id, question_answers=None, question_correct_comments=None, question_incorrect_comments=None, question_neutral_comments=None, question_points_possible=None, question_position=None, question_question_name=None, question_question_text=None, question_question_type=None, question_quiz_group_id=None, question_text_after_answers=None): + """ + Create a single quiz question. + + Create a new quiz question for this quiz + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - question[question_name] + """The name of the question.""" + if question_question_name is not None: + data["question[question_name]"] = question_question_name + + # OPTIONAL - question[question_text] + """The text of the question.""" + if question_question_text is not None: + data["question[question_text]"] = question_question_text + + # OPTIONAL - question[quiz_group_id] + """The id of the quiz group to assign the question to.""" + if question_quiz_group_id is not None: + data["question[quiz_group_id]"] = question_quiz_group_id + + # OPTIONAL - question[question_type] + """The type of question. Multiple optional fields depend upon the type of question to be used.""" + if question_question_type is not None: + self._validate_enum(question_question_type, ["calculated_question", "essay_question", "file_upload_question", "fill_in_multiple_blanks_question", "matching_question", "multiple_answers_question", "multiple_choice_question", "multiple_dropdowns_question", "numerical_question", "short_answer_question", "text_only_question", "true_false_question"]) + data["question[question_type]"] = question_question_type + + # OPTIONAL - question[position] + """The order in which the question will be displayed in the quiz in relation to other questions.""" + if question_position is not None: + data["question[position]"] = question_position + + # OPTIONAL - question[points_possible] + """The maximum amount of points received for answering this question correctly.""" + if question_points_possible is not None: + data["question[points_possible]"] = question_points_possible + + # OPTIONAL - question[correct_comments] + """The comment to display if the student answers the question correctly.""" + if question_correct_comments is not None: + data["question[correct_comments]"] = question_correct_comments + + # OPTIONAL - question[incorrect_comments] + """The comment to display if the student answers incorrectly.""" + if question_incorrect_comments is not None: + data["question[incorrect_comments]"] = question_incorrect_comments + + # OPTIONAL - question[neutral_comments] + """The comment to display regardless of how the student answered.""" + if question_neutral_comments is not None: + data["question[neutral_comments]"] = question_neutral_comments + + # OPTIONAL - question[text_after_answers] + """no description""" + if question_text_after_answers is not None: + data["question[text_after_answers]"] = question_text_after_answers + + # OPTIONAL - question[answers] + """no description""" + if question_answers is not None: + data["question[answers]"] = question_answers + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/questions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/questions".format(**path), data=data, params=params, single_item=True) + + def update_existing_quiz_question(self, id, quiz_id, course_id, question_answers=None, question_correct_comments=None, question_incorrect_comments=None, question_neutral_comments=None, question_points_possible=None, question_position=None, question_question_name=None, question_question_text=None, question_question_type=None, question_quiz_group_id=None, question_text_after_answers=None): + """ + Update an existing quiz question. + + Updates an existing quiz question for this quiz + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """The associated quiz's unique identifier.""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """The quiz question's unique identifier.""" + path["id"] = id + + # OPTIONAL - question[question_name] + """The name of the question.""" + if question_question_name is not None: + data["question[question_name]"] = question_question_name + + # OPTIONAL - question[question_text] + """The text of the question.""" + if question_question_text is not None: + data["question[question_text]"] = question_question_text + + # OPTIONAL - question[quiz_group_id] + """The id of the quiz group to assign the question to.""" + if question_quiz_group_id is not None: + data["question[quiz_group_id]"] = question_quiz_group_id + + # OPTIONAL - question[question_type] + """The type of question. Multiple optional fields depend upon the type of question to be used.""" + if question_question_type is not None: + self._validate_enum(question_question_type, ["calculated_question", "essay_question", "file_upload_question", "fill_in_multiple_blanks_question", "matching_question", "multiple_answers_question", "multiple_choice_question", "multiple_dropdowns_question", "numerical_question", "short_answer_question", "text_only_question", "true_false_question"]) + data["question[question_type]"] = question_question_type + + # OPTIONAL - question[position] + """The order in which the question will be displayed in the quiz in relation to other questions.""" + if question_position is not None: + data["question[position]"] = question_position + + # OPTIONAL - question[points_possible] + """The maximum amount of points received for answering this question correctly.""" + if question_points_possible is not None: + data["question[points_possible]"] = question_points_possible + + # OPTIONAL - question[correct_comments] + """The comment to display if the student answers the question correctly.""" + if question_correct_comments is not None: + data["question[correct_comments]"] = question_correct_comments + + # OPTIONAL - question[incorrect_comments] + """The comment to display if the student answers incorrectly.""" + if question_incorrect_comments is not None: + data["question[incorrect_comments]"] = question_incorrect_comments + + # OPTIONAL - question[neutral_comments] + """The comment to display regardless of how the student answered.""" + if question_neutral_comments is not None: + data["question[neutral_comments]"] = question_neutral_comments + + # OPTIONAL - question[text_after_answers] + """no description""" + if question_text_after_answers is not None: + data["question[text_after_answers]"] = question_text_after_answers + + # OPTIONAL - question[answers] + """no description""" + if question_answers is not None: + data["question[answers]"] = question_answers + + self.logger.debug("PUT /api/v1/courses/{course_id}/quizzes/{quiz_id}/questions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/questions/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_quiz_question(self, id, quiz_id, course_id): + """ + Delete a quiz question. + + 204 No Content response code is returned if the deletion was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """The associated quiz's unique identifier""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """The quiz question's unique identifier""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/quizzes/{quiz_id}/questions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/questions/{id}".format(**path), data=data, params=params, no_data=True) + + +class Answer(BaseModel): + """Answer Model.""" + + def __init__(self, answer_text, answer_weight, text_after_answers=None, answer_match_left=None, answer_comments=None, margin=None, matching_answer_incorrect_matches=None, approximate=None, start=None, answer_match_right=None, precision=None, numerical_answer_type=None, end=None, blank_id=None, exact=None, id=None): + """Init method for Answer class.""" + self._text_after_answers = text_after_answers + self._answer_match_left = answer_match_left + self._answer_comments = answer_comments + self._margin = margin + self._matching_answer_incorrect_matches = matching_answer_incorrect_matches + self._approximate = approximate + self._start = start + self._answer_text = answer_text + self._answer_weight = answer_weight + self._answer_match_right = answer_match_right + self._precision = precision + self._numerical_answer_type = numerical_answer_type + self._end = end + self._blank_id = blank_id + self._exact = exact + self._id = id + + self.logger = logging.getLogger('pycanvas.Answer') + + @property + def text_after_answers(self): + """Used in missing word questions. The text to follow the missing word.""" + return self._text_after_answers + + @text_after_answers.setter + def text_after_answers(self, value): + """Setter for text_after_answers property.""" + self.logger.warn("Setting values on text_after_answers will NOT update the remote Canvas instance.") + self._text_after_answers = value + + @property + def answer_match_left(self): + """Used in matching questions. The static value of the answer that will be displayed on the left for students to match for.""" + return self._answer_match_left + + @answer_match_left.setter + def answer_match_left(self, value): + """Setter for answer_match_left property.""" + self.logger.warn("Setting values on answer_match_left will NOT update the remote Canvas instance.") + self._answer_match_left = value + + @property + def answer_comments(self): + """Specific contextual comments for a particular answer.""" + return self._answer_comments + + @answer_comments.setter + def answer_comments(self, value): + """Setter for answer_comments property.""" + self.logger.warn("Setting values on answer_comments will NOT update the remote Canvas instance.") + self._answer_comments = value + + @property + def margin(self): + """Used in numerical questions of type 'exact_answer'. The margin of error allowed for the student's answer.""" + return self._margin + + @margin.setter + def margin(self, value): + """Setter for margin property.""" + self.logger.warn("Setting values on margin will NOT update the remote Canvas instance.") + self._margin = value + + @property + def matching_answer_incorrect_matches(self): + """Used in matching questions. A list of distractors, delimited by new lines ( +) that will be seeded with all the answer_match_right values.""" + return self._matching_answer_incorrect_matches + + @matching_answer_incorrect_matches.setter + def matching_answer_incorrect_matches(self, value): + """Setter for matching_answer_incorrect_matches property.""" + self.logger.warn("Setting values on matching_answer_incorrect_matches will NOT update the remote Canvas instance.") + self._matching_answer_incorrect_matches = value + + @property + def approximate(self): + """Used in numerical questions of type 'precision_answer'. The value the answer should equal.""" + return self._approximate + + @approximate.setter + def approximate(self, value): + """Setter for approximate property.""" + self.logger.warn("Setting values on approximate will NOT update the remote Canvas instance.") + self._approximate = value + + @property + def start(self): + """Used in numerical questions of type 'range_answer'. The start of the allowed range (inclusive).""" + return self._start + + @start.setter + def start(self, value): + """Setter for start property.""" + self.logger.warn("Setting values on start will NOT update the remote Canvas instance.") + self._start = value + + @property + def answer_text(self): + """The text of the answer.""" + return self._answer_text + + @answer_text.setter + def answer_text(self, value): + """Setter for answer_text property.""" + self.logger.warn("Setting values on answer_text will NOT update the remote Canvas instance.") + self._answer_text = value + + @property + def answer_weight(self): + """An integer to determine correctness of the answer. Incorrect answers should be 0, correct answers should be non-negative.""" + return self._answer_weight + + @answer_weight.setter + def answer_weight(self, value): + """Setter for answer_weight property.""" + self.logger.warn("Setting values on answer_weight will NOT update the remote Canvas instance.") + self._answer_weight = value + + @property + def answer_match_right(self): + """Used in matching questions. The correct match for the value given in answer_match_left. Will be displayed in a dropdown with the other answer_match_right values..""" + return self._answer_match_right + + @answer_match_right.setter + def answer_match_right(self, value): + """Setter for answer_match_right property.""" + self.logger.warn("Setting values on answer_match_right will NOT update the remote Canvas instance.") + self._answer_match_right = value + + @property + def precision(self): + """Used in numerical questions of type 'precision_answer'. The numerical precision that will be used when comparing the student's answer.""" + return self._precision + + @precision.setter + def precision(self, value): + """Setter for precision property.""" + self.logger.warn("Setting values on precision will NOT update the remote Canvas instance.") + self._precision = value + + @property + def numerical_answer_type(self): + """Used in numerical questions. Values can be 'exact_answer', 'range_answer', or 'precision_answer'.""" + return self._numerical_answer_type + + @numerical_answer_type.setter + def numerical_answer_type(self, value): + """Setter for numerical_answer_type property.""" + self.logger.warn("Setting values on numerical_answer_type will NOT update the remote Canvas instance.") + self._numerical_answer_type = value + + @property + def end(self): + """Used in numerical questions of type 'range_answer'. The end of the allowed range (inclusive).""" + return self._end + + @end.setter + def end(self, value): + """Setter for end property.""" + self.logger.warn("Setting values on end will NOT update the remote Canvas instance.") + self._end = value + + @property + def blank_id(self): + """Used in fill in multiple blank and multiple dropdowns questions.""" + return self._blank_id + + @blank_id.setter + def blank_id(self, value): + """Setter for blank_id property.""" + self.logger.warn("Setting values on blank_id will NOT update the remote Canvas instance.") + self._blank_id = value + + @property + def exact(self): + """Used in numerical questions of type 'exact_answer'. The value the answer should equal.""" + return self._exact + + @exact.setter + def exact(self, value): + """Setter for exact property.""" + self.logger.warn("Setting values on exact will NOT update the remote Canvas instance.") + self._exact = value + + @property + def id(self): + """The unique identifier for the answer. Do not supply if this answer is part of a new question.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Quizquestion(BaseModel): + """Quizquestion Model.""" + + def __init__(self, id, quiz_id, question_text=None, neutral_comments=None, points_possible=None, question_name=None, answers=None, question_type=None, correct_comments=None, incorrect_comments=None, position=None): + """Init method for Quizquestion class.""" + self._question_text = question_text + self._neutral_comments = neutral_comments + self._points_possible = points_possible + self._question_name = question_name + self._answers = answers + self._question_type = question_type + self._correct_comments = correct_comments + self._incorrect_comments = incorrect_comments + self._position = position + self._quiz_id = quiz_id + self._id = id + + self.logger = logging.getLogger('pycanvas.Quizquestion') + + @property + def question_text(self): + """The text of the question.""" + return self._question_text + + @question_text.setter + def question_text(self, value): + """Setter for question_text property.""" + self.logger.warn("Setting values on question_text will NOT update the remote Canvas instance.") + self._question_text = value + + @property + def neutral_comments(self): + """The comments to display regardless of how the student answered.""" + return self._neutral_comments + + @neutral_comments.setter + def neutral_comments(self, value): + """Setter for neutral_comments property.""" + self.logger.warn("Setting values on neutral_comments will NOT update the remote Canvas instance.") + self._neutral_comments = value + + @property + def points_possible(self): + """The maximum amount of points possible received for getting this question correct.""" + return self._points_possible + + @points_possible.setter + def points_possible(self, value): + """Setter for points_possible property.""" + self.logger.warn("Setting values on points_possible will NOT update the remote Canvas instance.") + self._points_possible = value + + @property + def question_name(self): + """The name of the question.""" + return self._question_name + + @question_name.setter + def question_name(self, value): + """Setter for question_name property.""" + self.logger.warn("Setting values on question_name will NOT update the remote Canvas instance.") + self._question_name = value + + @property + def answers(self): + """An array of available answers to display to the student.""" + return self._answers + + @answers.setter + def answers(self, value): + """Setter for answers property.""" + self.logger.warn("Setting values on answers will NOT update the remote Canvas instance.") + self._answers = value + + @property + def question_type(self): + """The type of the question.""" + return self._question_type + + @question_type.setter + def question_type(self, value): + """Setter for question_type property.""" + self.logger.warn("Setting values on question_type will NOT update the remote Canvas instance.") + self._question_type = value + + @property + def correct_comments(self): + """The comments to display if the student answers the question correctly.""" + return self._correct_comments + + @correct_comments.setter + def correct_comments(self, value): + """Setter for correct_comments property.""" + self.logger.warn("Setting values on correct_comments will NOT update the remote Canvas instance.") + self._correct_comments = value + + @property + def incorrect_comments(self): + """The comments to display if the student answers incorrectly.""" + return self._incorrect_comments + + @incorrect_comments.setter + def incorrect_comments(self, value): + """Setter for incorrect_comments property.""" + self.logger.warn("Setting values on incorrect_comments will NOT update the remote Canvas instance.") + self._incorrect_comments = value + + @property + def position(self): + """The order in which the question will be retrieved and displayed.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def quiz_id(self): + """The ID of the Quiz the question belongs to.""" + return self._quiz_id + + @quiz_id.setter + def quiz_id(self, value): + """Setter for quiz_id property.""" + self.logger.warn("Setting values on quiz_id will NOT update the remote Canvas instance.") + self._quiz_id = value + + @property + def id(self): + """The ID of the quiz question.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_reports.py b/venv/Lib/site-packages/pycanvas/apis/quiz_reports.py new file mode 100644 index 00000000..cc4f9dda --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_reports.py @@ -0,0 +1,328 @@ +"""QuizReports API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizReportsAPI(BaseCanvasAPI): + """QuizReports API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizReportsAPI.""" + super(QuizReportsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizReportsAPI") + + def retrieve_all_quiz_reports(self, quiz_id, course_id, includes_all_versions=None): + """ + Retrieve all quiz reports. + + Returns a list of all available reports. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - includes_all_versions + """Whether to retrieve reports that consider all the submissions or only + the most recent. Defaults to false, ignored for item_analysis reports.""" + if includes_all_versions is not None: + params["includes_all_versions"] = includes_all_versions + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/reports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/reports".format(**path), data=data, params=params, all_pages=True) + + def create_quiz_report(self, quiz_id, course_id, quiz_report_report_type, include=None, quiz_report_includes_all_versions=None): + """ + Create a quiz report. + + Create and return a new report for this quiz. If a previously + generated report matches the arguments and is still current (i.e. + there have been no new submissions), it will be returned. + + *Responses* + + * 400 Bad Request if the specified report type is invalid + * 409 Conflict if a quiz report of the specified type is already being + generated + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - quiz_report[report_type] + """The type of report to be generated.""" + self._validate_enum(quiz_report_report_type, ["student_analysis", "item_analysis"]) + data["quiz_report[report_type]"] = quiz_report_report_type + + # OPTIONAL - quiz_report[includes_all_versions] + """Whether the report should consider all submissions or only the most + recent. Defaults to false, ignored for item_analysis.""" + if quiz_report_includes_all_versions is not None: + data["quiz_report[includes_all_versions]"] = quiz_report_includes_all_versions + + # OPTIONAL - include + """Whether the output should include documents for the file and/or progress + objects associated with this report. (Note: JSON-API only)""" + if include is not None: + self._validate_enum(include, ["file", "progress"]) + data["include"] = include + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/reports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/reports".format(**path), data=data, params=params, single_item=True) + + def get_quiz_report(self, id, quiz_id, course_id, include=None): + """ + Get a quiz report. + + Returns the data for a single quiz report. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """Whether the output should include documents for the file and/or progress + objects associated with this report. (Note: JSON-API only)""" + if include is not None: + self._validate_enum(include, ["file", "progress"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/reports/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/reports/{id}".format(**path), data=data, params=params, single_item=True) + + def abort_generation_of_report_or_remove_previously_generated_one(self, id, quiz_id, course_id): + """ + Abort the generation of a report, or remove a previously generated one. + + This API allows you to cancel a previous request you issued for a report to + be generated. Or in the case of an already generated report, you'd like to + remove it, perhaps to generate it another time with an updated version that + provides new features. + + You must check the report's generation status before attempting to use this + interface. See the "workflow_state" property of the QuizReport's Progress + object for more information. Only when the progress reports itself in a + "queued" state can the generation be aborted. + + *Responses* + + - 204 No Content if your request was accepted + - 422 Unprocessable Entity if the report is not being generated + or can not be aborted at this stage + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/quizzes/{quiz_id}/reports/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/reports/{id}".format(**path), data=data, params=params, no_data=True) + + +class Quizreport(BaseModel): + """Quizreport Model.""" + + def __init__(self, file=None, progress_url=None, report_type=None, readable_type=None, url=None, created_at=None, updated_at=None, generatable=None, anonymous=None, progress=None, quiz_id=None, includes_all_versions=None, id=None): + """Init method for Quizreport class.""" + self._file = file + self._progress_url = progress_url + self._report_type = report_type + self._readable_type = readable_type + self._url = url + self._created_at = created_at + self._updated_at = updated_at + self._generatable = generatable + self._anonymous = anonymous + self._progress = progress + self._quiz_id = quiz_id + self._includes_all_versions = includes_all_versions + self._id = id + + self.logger = logging.getLogger('pycanvas.Quizreport') + + @property + def file(self): + """if the report has finished generating, a File object that represents it. refer to the Files API for more information about the format.""" + return self._file + + @file.setter + def file(self, value): + """Setter for file property.""" + self.logger.warn("Setting values on file will NOT update the remote Canvas instance.") + self._file = value + + @property + def progress_url(self): + """if the report has not yet finished generating, a URL where information about its progress can be retrieved. refer to the Progress API for more information (Note: not available in JSON-API format).""" + return self._progress_url + + @progress_url.setter + def progress_url(self, value): + """Setter for progress_url property.""" + self.logger.warn("Setting values on progress_url will NOT update the remote Canvas instance.") + self._progress_url = value + + @property + def report_type(self): + """which type of report this is possible values: 'student_analysis', 'item_analysis'.""" + return self._report_type + + @report_type.setter + def report_type(self, value): + """Setter for report_type property.""" + self.logger.warn("Setting values on report_type will NOT update the remote Canvas instance.") + self._report_type = value + + @property + def readable_type(self): + """a human-readable (and localized) version of the report_type.""" + return self._readable_type + + @readable_type.setter + def readable_type(self, value): + """Setter for readable_type property.""" + self.logger.warn("Setting values on readable_type will NOT update the remote Canvas instance.") + self._readable_type = value + + @property + def url(self): + """the API endpoint for this report.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def created_at(self): + """when the report was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def updated_at(self): + """when the report was last updated.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def generatable(self): + """boolean indicating whether the report can be generated, which is true unless the quiz is a survey one.""" + return self._generatable + + @generatable.setter + def generatable(self, value): + """Setter for generatable property.""" + self.logger.warn("Setting values on generatable will NOT update the remote Canvas instance.") + self._generatable = value + + @property + def anonymous(self): + """boolean indicating whether the report is for an anonymous survey. if true, no student names will be included in the csv.""" + return self._anonymous + + @anonymous.setter + def anonymous(self, value): + """Setter for anonymous property.""" + self.logger.warn("Setting values on anonymous will NOT update the remote Canvas instance.") + self._anonymous = value + + @property + def progress(self): + """if the report is being generated, a Progress object that represents the operation. Refer to the Progress API for more information about the format. (Note: available only in JSON-API format).""" + return self._progress + + @progress.setter + def progress(self, value): + """Setter for progress property.""" + self.logger.warn("Setting values on progress will NOT update the remote Canvas instance.") + self._progress = value + + @property + def quiz_id(self): + """the ID of the quiz.""" + return self._quiz_id + + @quiz_id.setter + def quiz_id(self, value): + """Setter for quiz_id property.""" + self.logger.warn("Setting values on quiz_id will NOT update the remote Canvas instance.") + self._quiz_id = value + + @property + def includes_all_versions(self): + """boolean indicating whether the report represents all submissions or only the most recent ones for each student.""" + return self._includes_all_versions + + @includes_all_versions.setter + def includes_all_versions(self, value): + """Setter for includes_all_versions property.""" + self.logger.warn("Setting values on includes_all_versions will NOT update the remote Canvas instance.") + self._includes_all_versions = value + + @property + def id(self): + """the ID of the quiz report.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_statistics.py b/venv/Lib/site-packages/pycanvas/apis/quiz_statistics.py new file mode 100644 index 00000000..c888945d --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_statistics.py @@ -0,0 +1,469 @@ +"""QuizStatistics API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizStatisticsAPI(BaseCanvasAPI): + """QuizStatistics API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizStatisticsAPI.""" + super(QuizStatisticsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizStatisticsAPI") + + def fetching_latest_quiz_statistics(self, quiz_id, course_id, all_versions=None): + """ + Fetching the latest quiz statistics. + + This endpoint provides statistics for all quiz versions, or for a specific + quiz version, in which case the output is guaranteed to represent the + _latest_ and most current version of the quiz. + + 200 OK response code is returned if the request was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - all_versions + """Whether the statistics report should include all submissions attempts.""" + if all_versions is not None: + params["all_versions"] = all_versions + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/statistics with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/statistics".format(**path), data=data, params=params, no_data=True) + + +class Quizstatisticsquestionstatistics(BaseModel): + """Quizstatisticsquestionstatistics Model. + Statistics for submissions made to a specific quiz question.""" + + def __init__(self, responses=None, answers=None): + """Init method for Quizstatisticsquestionstatistics class.""" + self._responses = responses + self._answers = answers + + self.logger = logging.getLogger('pycanvas.Quizstatisticsquestionstatistics') + + @property + def responses(self): + """Number of students who have provided an answer to this question. Blank or empty responses are not counted.""" + return self._responses + + @responses.setter + def responses(self, value): + """Setter for responses property.""" + self.logger.warn("Setting values on responses will NOT update the remote Canvas instance.") + self._responses = value + + @property + def answers(self): + """Statistics related to each individual pre-defined answer.""" + return self._answers + + @answers.setter + def answers(self, value): + """Setter for answers property.""" + self.logger.warn("Setting values on answers will NOT update the remote Canvas instance.") + self._answers = value + + +class Quizstatistics(BaseModel): + """Quizstatistics Model.""" + + def __init__(self, id, quiz_id, question_statistics=None, links=None, multiple_attempts_exist=None, url=None, html_url=None, submission_statistics=None, generated_at=None, includes_all_versions=None): + """Init method for Quizstatistics class.""" + self._question_statistics = question_statistics + self._links = links + self._multiple_attempts_exist = multiple_attempts_exist + self._url = url + self._html_url = html_url + self._submission_statistics = submission_statistics + self._generated_at = generated_at + self._quiz_id = quiz_id + self._includes_all_versions = includes_all_versions + self._id = id + + self.logger = logging.getLogger('pycanvas.Quizstatistics') + + @property + def question_statistics(self): + """Question-specific statistics for each question and its answers.""" + return self._question_statistics + + @question_statistics.setter + def question_statistics(self, value): + """Setter for question_statistics property.""" + self.logger.warn("Setting values on question_statistics will NOT update the remote Canvas instance.") + self._question_statistics = value + + @property + def links(self): + """JSON-API construct that contains links to media related to this quiz statistics object. +NOTE: AVAILABLE ONLY IN JSON-API REQUESTS.""" + return self._links + + @links.setter + def links(self, value): + """Setter for links property.""" + self.logger.warn("Setting values on links will NOT update the remote Canvas instance.") + self._links = value + + @property + def multiple_attempts_exist(self): + """Whether there are any students that have made mutliple submissions for this quiz.""" + return self._multiple_attempts_exist + + @multiple_attempts_exist.setter + def multiple_attempts_exist(self, value): + """Setter for multiple_attempts_exist property.""" + self.logger.warn("Setting values on multiple_attempts_exist will NOT update the remote Canvas instance.") + self._multiple_attempts_exist = value + + @property + def url(self): + """The API HTTP/HTTPS URL to this quiz statistics.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def html_url(self): + """The HTTP/HTTPS URL to the page where the statistics can be seen visually.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def submission_statistics(self): + """Question-specific statistics for each question and its answers.""" + return self._submission_statistics + + @submission_statistics.setter + def submission_statistics(self, value): + """Setter for submission_statistics property.""" + self.logger.warn("Setting values on submission_statistics will NOT update the remote Canvas instance.") + self._submission_statistics = value + + @property + def generated_at(self): + """The time at which the statistics were generated, which is usually after the occurrence of a quiz event, like a student submitting it.""" + return self._generated_at + + @generated_at.setter + def generated_at(self, value): + """Setter for generated_at property.""" + self.logger.warn("Setting values on generated_at will NOT update the remote Canvas instance.") + self._generated_at = value + + @property + def quiz_id(self): + """The ID of the Quiz the statistics report is for. +NOTE: AVAILABLE ONLY IN NON-JSON-API REQUESTS.""" + return self._quiz_id + + @quiz_id.setter + def quiz_id(self, value): + """Setter for quiz_id property.""" + self.logger.warn("Setting values on quiz_id will NOT update the remote Canvas instance.") + self._quiz_id = value + + @property + def includes_all_versions(self): + """In the presence of multiple attempts, this field describes whether the statistics describe all the submission attempts and not only the latest ones.""" + return self._includes_all_versions + + @includes_all_versions.setter + def includes_all_versions(self, value): + """Setter for includes_all_versions property.""" + self.logger.warn("Setting values on includes_all_versions will NOT update the remote Canvas instance.") + self._includes_all_versions = value + + @property + def id(self): + """The ID of the quiz statistics report.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Quizstatisticsanswerpointbiserial(BaseModel): + """Quizstatisticsanswerpointbiserial Model. + A point-biserial construct for a single pre-defined answer in a Multiple-Choice or True/False question.""" + + def __init__(self, point_biserial=None, distractor=None, correct=None, answer_id=None): + """Init method for Quizstatisticsanswerpointbiserial class.""" + self._point_biserial = point_biserial + self._distractor = distractor + self._correct = correct + self._answer_id = answer_id + + self.logger = logging.getLogger('pycanvas.Quizstatisticsanswerpointbiserial') + + @property + def point_biserial(self): + """The point biserial value for this answer. Value ranges between -1 and 1.""" + return self._point_biserial + + @point_biserial.setter + def point_biserial(self, value): + """Setter for point_biserial property.""" + self.logger.warn("Setting values on point_biserial will NOT update the remote Canvas instance.") + self._point_biserial = value + + @property + def distractor(self): + """Convenience attribute that denotes whether this is a distractor answer and not the correct one. This is mutually exclusive with the `correct` value.""" + return self._distractor + + @distractor.setter + def distractor(self, value): + """Setter for distractor property.""" + self.logger.warn("Setting values on distractor will NOT update the remote Canvas instance.") + self._distractor = value + + @property + def correct(self): + """Convenience attribute that denotes whether this is the correct answer as opposed to being a distractor. This is mutually exclusive with the `distractor` value.""" + return self._correct + + @correct.setter + def correct(self, value): + """Setter for correct property.""" + self.logger.warn("Setting values on correct will NOT update the remote Canvas instance.") + self._correct = value + + @property + def answer_id(self): + """ID of the answer the point biserial is for.""" + return self._answer_id + + @answer_id.setter + def answer_id(self, value): + """Setter for answer_id property.""" + self.logger.warn("Setting values on answer_id will NOT update the remote Canvas instance.") + self._answer_id = value + + +class Quizstatisticsanswerstatistics(BaseModel): + """Quizstatisticsanswerstatistics Model. + Statistics for a specific pre-defined answer in a Multiple-Choice or True/False quiz question.""" + + def __init__(self, text=None, id=None, weight=None, responses=None): + """Init method for Quizstatisticsanswerstatistics class.""" + self._text = text + self._id = id + self._weight = weight + self._responses = responses + + self.logger = logging.getLogger('pycanvas.Quizstatisticsanswerstatistics') + + @property + def text(self): + """The text attached to the answer.""" + return self._text + + @text.setter + def text(self, value): + """Setter for text property.""" + self.logger.warn("Setting values on text will NOT update the remote Canvas instance.") + self._text = value + + @property + def id(self): + """ID of the answer.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def weight(self): + """An integer to determine correctness of the answer. Incorrect answers should be 0, correct answers should be non-negative.""" + return self._weight + + @weight.setter + def weight(self, value): + """Setter for weight property.""" + self.logger.warn("Setting values on weight will NOT update the remote Canvas instance.") + self._weight = value + + @property + def responses(self): + """Number of students who have chosen this answer.""" + return self._responses + + @responses.setter + def responses(self, value): + """Setter for responses property.""" + self.logger.warn("Setting values on responses will NOT update the remote Canvas instance.") + self._responses = value + + +class Quizstatisticslinks(BaseModel): + """Quizstatisticslinks Model. + Links to media related to QuizStatistics.""" + + def __init__(self, quiz=None): + """Init method for Quizstatisticslinks class.""" + self._quiz = quiz + + self.logger = logging.getLogger('pycanvas.Quizstatisticslinks') + + @property + def quiz(self): + """HTTP/HTTPS API URL to the quiz this statistics describe.""" + return self._quiz + + @quiz.setter + def quiz(self, value): + """Setter for quiz property.""" + self.logger.warn("Setting values on quiz will NOT update the remote Canvas instance.") + self._quiz = value + + +class Quizstatisticssubmissionstatistics(BaseModel): + """Quizstatisticssubmissionstatistics Model. + Generic statistics for all submissions for a quiz.""" + + def __init__(self, duration_average=None, score_average=None, score_low=None, incorrect_count_average=None, unique_count=None, score_high=None, scores=None, correct_count_average=None, score_stdev=None): + """Init method for Quizstatisticssubmissionstatistics class.""" + self._duration_average = duration_average + self._score_average = score_average + self._score_low = score_low + self._incorrect_count_average = incorrect_count_average + self._unique_count = unique_count + self._score_high = score_high + self._scores = scores + self._correct_count_average = correct_count_average + self._score_stdev = score_stdev + + self.logger = logging.getLogger('pycanvas.Quizstatisticssubmissionstatistics') + + @property + def duration_average(self): + """The average time spent by students while taking the quiz.""" + return self._duration_average + + @duration_average.setter + def duration_average(self, value): + """Setter for duration_average property.""" + self.logger.warn("Setting values on duration_average will NOT update the remote Canvas instance.") + self._duration_average = value + + @property + def score_average(self): + """The mean of the student submission scores.""" + return self._score_average + + @score_average.setter + def score_average(self, value): + """Setter for score_average property.""" + self.logger.warn("Setting values on score_average will NOT update the remote Canvas instance.") + self._score_average = value + + @property + def score_low(self): + """The lowest submission score.""" + return self._score_low + + @score_low.setter + def score_low(self, value): + """Setter for score_low property.""" + self.logger.warn("Setting values on score_low will NOT update the remote Canvas instance.") + self._score_low = value + + @property + def incorrect_count_average(self): + """The mean of the number of questions answered incorrectly by each student.""" + return self._incorrect_count_average + + @incorrect_count_average.setter + def incorrect_count_average(self, value): + """Setter for incorrect_count_average property.""" + self.logger.warn("Setting values on incorrect_count_average will NOT update the remote Canvas instance.") + self._incorrect_count_average = value + + @property + def unique_count(self): + """The number of students who have taken the quiz.""" + return self._unique_count + + @unique_count.setter + def unique_count(self, value): + """Setter for unique_count property.""" + self.logger.warn("Setting values on unique_count will NOT update the remote Canvas instance.") + self._unique_count = value + + @property + def score_high(self): + """The highest submission score.""" + return self._score_high + + @score_high.setter + def score_high(self, value): + """Setter for score_high property.""" + self.logger.warn("Setting values on score_high will NOT update the remote Canvas instance.") + self._score_high = value + + @property + def scores(self): + """A percentile distribution of the student scores, each key is the percentile (ranges between 0 and 100%) while the value is the number of students who received that score.""" + return self._scores + + @scores.setter + def scores(self, value): + """Setter for scores property.""" + self.logger.warn("Setting values on scores will NOT update the remote Canvas instance.") + self._scores = value + + @property + def correct_count_average(self): + """The mean of the number of questions answered correctly by each student.""" + return self._correct_count_average + + @correct_count_average.setter + def correct_count_average(self, value): + """Setter for correct_count_average property.""" + self.logger.warn("Setting values on correct_count_average will NOT update the remote Canvas instance.") + self._correct_count_average = value + + @property + def score_stdev(self): + """Standard deviation of the submission scores.""" + return self._score_stdev + + @score_stdev.setter + def score_stdev(self, value): + """Setter for score_stdev property.""" + self.logger.warn("Setting values on score_stdev will NOT update the remote Canvas instance.") + self._score_stdev = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_submission_events.py b/venv/Lib/site-packages/pycanvas/apis/quiz_submission_events.py new file mode 100644 index 00000000..09a26cda --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_submission_events.py @@ -0,0 +1,126 @@ +"""QuizSubmissionEvents API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizSubmissionEventsAPI(BaseCanvasAPI): + """QuizSubmissionEvents API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizSubmissionEventsAPI.""" + super(QuizSubmissionEventsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizSubmissionEventsAPI") + + def submit_captured_events(self, id, quiz_id, course_id, quiz_submission_events): + """ + Submit captured events. + + Store a set of events which were captured during a quiz taking session. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - quiz_submission_events + """The submission events to be recorded""" + data["quiz_submission_events"] = quiz_submission_events + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}/events with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}/events".format(**path), data=data, params=params, no_data=True) + + def retrieve_captured_events(self, id, quiz_id, course_id, attempt=None): + """ + Retrieve captured events. + + Retrieve the set of events captured during a specific submission attempt. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - attempt + """The specific submission attempt to look up the events for. If unspecified, + the latest attempt will be used.""" + if attempt is not None: + params["attempt"] = attempt + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}/events with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}/events".format(**path), data=data, params=params, no_data=True) + + +class Quizsubmissionevent(BaseModel): + """Quizsubmissionevent Model. + An event passed from the Quiz Submission take page""" + + def __init__(self, created_at=None, event_type=None, event_data=None): + """Init method for Quizsubmissionevent class.""" + self._created_at = created_at + self._event_type = event_type + self._event_data = event_data + + self.logger = logging.getLogger('pycanvas.Quizsubmissionevent') + + @property + def created_at(self): + """a timestamp record of creation time.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def event_type(self): + """the type of event being sent.""" + return self._event_type + + @event_type.setter + def event_type(self, value): + """Setter for event_type property.""" + self.logger.warn("Setting values on event_type will NOT update the remote Canvas instance.") + self._event_type = value + + @property + def event_data(self): + """custom contextual data for the specific event type.""" + return self._event_data + + @event_data.setter + def event_data(self, value): + """Setter for event_data property.""" + self.logger.warn("Setting values on event_data will NOT update the remote Canvas instance.") + self._event_data = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_submission_files.py b/venv/Lib/site-packages/pycanvas/apis/quiz_submission_files.py new file mode 100644 index 00000000..bc3bd3aa --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_submission_files.py @@ -0,0 +1,54 @@ +"""QuizSubmissionFiles API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + + +class QuizSubmissionFilesAPI(BaseCanvasAPI): + """QuizSubmissionFiles API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizSubmissionFilesAPI.""" + super(QuizSubmissionFilesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizSubmissionFilesAPI") + + def upload_file(self, quiz_id, course_id, name=None, on_duplicate=None): + """ + Upload a file. + + Associate a new quiz submission file + + This API endpoint is the first step in uploading a quiz submission file. + See the {file:file_uploads.html File Upload Documentation} for details on + the file upload workflow as these parameters are interpreted as per the + documentation there. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - name + """The name of the quiz submission file""" + if name is not None: + data["name"] = name + + # OPTIONAL - on_duplicate + """How to handle duplicate names""" + if on_duplicate is not None: + data["on_duplicate"] = on_duplicate + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/self/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/self/files".format(**path), data=data, params=params, no_data=True) + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_submission_questions.py b/venv/Lib/site-packages/pycanvas/apis/quiz_submission_questions.py new file mode 100644 index 00000000..3033ce33 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_submission_questions.py @@ -0,0 +1,217 @@ +"""QuizSubmissionQuestions API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizSubmissionQuestionsAPI(BaseCanvasAPI): + """QuizSubmissionQuestions API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizSubmissionQuestionsAPI.""" + super(QuizSubmissionQuestionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizSubmissionQuestionsAPI") + + def get_all_quiz_submission_questions(self, quiz_submission_id, include=None): + """ + Get all quiz submission questions. + + Get a list of all the question records for this quiz submission. + + 200 OK response code is returned if the request was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - quiz_submission_id + """ID""" + path["quiz_submission_id"] = quiz_submission_id + + # OPTIONAL - include + """Associations to include with the quiz submission question.""" + if include is not None: + self._validate_enum(include, ["quiz_question"]) + params["include"] = include + + self.logger.debug("GET /api/v1/quiz_submissions/{quiz_submission_id}/questions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/quiz_submissions/{quiz_submission_id}/questions".format(**path), data=data, params=params, no_data=True) + + def answering_questions(self, attempt, validation_token, quiz_submission_id, access_code=None, quiz_questions=None): + """ + Answering questions. + + Provide or update an answer to one or more QuizQuestions. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - quiz_submission_id + """ID""" + path["quiz_submission_id"] = quiz_submission_id + + # REQUIRED - attempt + """The attempt number of the quiz submission being taken. Note that this + must be the latest attempt index, as questions for earlier attempts can + not be modified.""" + data["attempt"] = attempt + + # REQUIRED - validation_token + """The unique validation token you received when the Quiz Submission was + created.""" + data["validation_token"] = validation_token + + # OPTIONAL - access_code + """Access code for the Quiz, if any.""" + if access_code is not None: + data["access_code"] = access_code + + # OPTIONAL - quiz_questions + """Set of question IDs and the answer value. + + See {Appendix: Question Answer Formats} for the accepted answer formats + for each question type.""" + if quiz_questions is not None: + data["quiz_questions"] = quiz_questions + + self.logger.debug("POST /api/v1/quiz_submissions/{quiz_submission_id}/questions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/quiz_submissions/{quiz_submission_id}/questions".format(**path), data=data, params=params, all_pages=True) + + def flagging_question(self, id, attempt, validation_token, quiz_submission_id, access_code=None): + """ + Flagging a question. + + Set a flag on a quiz question to indicate that you want to return to it + later. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - quiz_submission_id + """ID""" + path["quiz_submission_id"] = quiz_submission_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - attempt + """The attempt number of the quiz submission being taken. Note that this + must be the latest attempt index, as questions for earlier attempts can + not be modified.""" + data["attempt"] = attempt + + # REQUIRED - validation_token + """The unique validation token you received when the Quiz Submission was + created.""" + data["validation_token"] = validation_token + + # OPTIONAL - access_code + """Access code for the Quiz, if any.""" + if access_code is not None: + data["access_code"] = access_code + + self.logger.debug("PUT /api/v1/quiz_submissions/{quiz_submission_id}/questions/{id}/flag with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/quiz_submissions/{quiz_submission_id}/questions/{id}/flag".format(**path), data=data, params=params, no_data=True) + + def unflagging_question(self, id, attempt, validation_token, quiz_submission_id, access_code=None): + """ + Unflagging a question. + + Remove the flag that you previously set on a quiz question after you've + returned to it. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - quiz_submission_id + """ID""" + path["quiz_submission_id"] = quiz_submission_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - attempt + """The attempt number of the quiz submission being taken. Note that this + must be the latest attempt index, as questions for earlier attempts can + not be modified.""" + data["attempt"] = attempt + + # REQUIRED - validation_token + """The unique validation token you received when the Quiz Submission was + created.""" + data["validation_token"] = validation_token + + # OPTIONAL - access_code + """Access code for the Quiz, if any.""" + if access_code is not None: + data["access_code"] = access_code + + self.logger.debug("PUT /api/v1/quiz_submissions/{quiz_submission_id}/questions/{id}/unflag with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/quiz_submissions/{quiz_submission_id}/questions/{id}/unflag".format(**path), data=data, params=params, no_data=True) + + +class Quizsubmissionquestion(BaseModel): + """Quizsubmissionquestion Model.""" + + def __init__(self, id, answer=None, answers=None, flagged=None): + """Init method for Quizsubmissionquestion class.""" + self._answer = answer + self._id = id + self._answers = answers + self._flagged = flagged + + self.logger = logging.getLogger('pycanvas.Quizsubmissionquestion') + + @property + def answer(self): + """The provided answer (if any) for this question. The format of this parameter depends on the type of the question, see the Appendix for more information.""" + return self._answer + + @answer.setter + def answer(self, value): + """Setter for answer property.""" + self.logger.warn("Setting values on answer will NOT update the remote Canvas instance.") + self._answer = value + + @property + def id(self): + """The ID of the QuizQuestion this answer is for.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def answers(self): + """The possible answers for this question when those possible answers are necessary. The presence of this parameter is dependent on permissions.""" + return self._answers + + @answers.setter + def answers(self, value): + """Setter for answers property.""" + self.logger.warn("Setting values on answers will NOT update the remote Canvas instance.") + self._answers = value + + @property + def flagged(self): + """Whether this question is flagged.""" + return self._flagged + + @flagged.setter + def flagged(self, value): + """Setter for flagged property.""" + self.logger.warn("Setting values on flagged will NOT update the remote Canvas instance.") + self._flagged = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_submission_user_list.py b/venv/Lib/site-packages/pycanvas/apis/quiz_submission_user_list.py new file mode 100644 index 00000000..417af535 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_submission_user_list.py @@ -0,0 +1,87 @@ +"""QuizSubmissionUserList API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizSubmissionUserListAPI(BaseCanvasAPI): + """QuizSubmissionUserList API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizSubmissionUserListAPI.""" + super(QuizSubmissionUserListAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizSubmissionUserListAPI") + + def send_message_to_unsubmitted_or_submitted_users_for_quiz(self, id, course_id, conversations=None): + """ + Send a message to unsubmitted or submitted users for the quiz. + + { + "body": { + "type": "string", + "description": "message body of the conversation to be created", + "example": "Please take the quiz." + }, + "recipients": { + "type": "string", + "description": "Who to send the message to. May be either 'submitted' or 'unsubmitted'", + "example": "submitted" + }, + "subject": { + "type": "string", + "description": "Subject of the new Conversation created", + "example": "ATTN: Quiz 101 Students" + } + } + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - conversations + """- Body and recipients to send the message to.""" + if conversations is not None: + data["conversations"] = conversations + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{id}/submission_users/message with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{id}/submission_users/message".format(**path), data=data, params=params, no_data=True) + + +class Jsonapipagination(BaseModel): + """Jsonapipagination Model.""" + + def __init__(self): + """Init method for Jsonapipagination class.""" + + self.logger = logging.getLogger('pycanvas.Jsonapipagination') + + +class Quizsubmissionuserlistmeta(BaseModel): + """Quizsubmissionuserlistmeta Model.""" + + def __init__(self): + """Init method for Quizsubmissionuserlistmeta class.""" + + self.logger = logging.getLogger('pycanvas.Quizsubmissionuserlistmeta') + + +class Quizsubmissionuserlist(BaseModel): + """Quizsubmissionuserlist Model.""" + + def __init__(self): + """Init method for Quizsubmissionuserlist class.""" + + self.logger = logging.getLogger('pycanvas.Quizsubmissionuserlist') + diff --git a/venv/Lib/site-packages/pycanvas/apis/quiz_submissions.py b/venv/Lib/site-packages/pycanvas/apis/quiz_submissions.py new file mode 100644 index 00000000..98072d55 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quiz_submissions.py @@ -0,0 +1,527 @@ +"""QuizSubmissions API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizSubmissionsAPI(BaseCanvasAPI): + """QuizSubmissions API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizSubmissionsAPI.""" + super(QuizSubmissionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizSubmissionsAPI") + + def get_all_quiz_submissions(self, quiz_id, course_id, include=None): + """ + Get all quiz submissions. + + Get a list of all submissions for this quiz. Users who can view or manage + grades for a course will have submissions from multiple users returned. A + user who can only submit will have only their own submissions returned. When + a user has an in-progress submission, only that submission is returned. When + there isn't an in-progress quiz_submission, all completed submissions, + including previous attempts, are returned. + + 200 OK response code is returned if the request was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - include + """Associations to include with the quiz submission.""" + if include is not None: + self._validate_enum(include, ["submission", "quiz", "user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions".format(**path), data=data, params=params, no_data=True) + + def get_quiz_submission(self, quiz_id, course_id, include=None): + """ + Get the quiz submission. + + Get the submission for this quiz for the current user. + + 200 OK response code is returned if the request was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - include + """Associations to include with the quiz submission.""" + if include is not None: + self._validate_enum(include, ["submission", "quiz", "user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/submission with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submission".format(**path), data=data, params=params, no_data=True) + + def get_single_quiz_submission(self, id, quiz_id, course_id, include=None): + """ + Get a single quiz submission. + + Get a single quiz submission. + + 200 OK response code is returned if the request was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """Associations to include with the quiz submission.""" + if include is not None: + self._validate_enum(include, ["submission", "quiz", "user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}".format(**path), data=data, params=params, no_data=True) + + def create_quiz_submission_start_quiz_taking_session(self, quiz_id, course_id, access_code=None, preview=None): + """ + Create the quiz submission (start a quiz-taking session). + + Start taking a Quiz by creating a QuizSubmission which you can use to answer + questions and submit your answers. + + Responses + + * 200 OK if the request was successful + * 400 Bad Request if the quiz is locked + * 403 Forbidden if an invalid access code is specified + * 403 Forbidden if the Quiz's IP filter restriction does not pass + * 409 Conflict if a QuizSubmission already exists for this user and quiz + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # OPTIONAL - access_code + """Access code for the Quiz, if any.""" + if access_code is not None: + data["access_code"] = access_code + + # OPTIONAL - preview + """Whether this should be a preview QuizSubmission and not count towards + the user's course record. Teachers only.""" + if preview is not None: + data["preview"] = preview + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions".format(**path), data=data, params=params, no_data=True) + + def update_student_question_scores_and_comments(self, id, quiz_id, attempt, course_id, fudge_points=None, questions=None): + """ + Update student question scores and comments. + + Update the amount of points a student has scored for questions they've + answered, provide comments for the student about their answer(s), or simply + fudge the total score by a specific amount of points. + + Responses + + * 200 OK if the request was successful + * 403 Forbidden if you are not a teacher in this course + * 400 Bad Request if the attempt parameter is missing or invalid + * 400 Bad Request if the specified QS attempt is not yet complete + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - attempt + """The attempt number of the quiz submission that should be updated. This + attempt MUST be already completed.""" + data["attempt"] = attempt + + # OPTIONAL - fudge_points + """Amount of positive or negative points to fudge the total score by.""" + if fudge_points is not None: + data["fudge_points"] = fudge_points + + # OPTIONAL - questions + """A set of scores and comments for each question answered by the student. + The keys are the question IDs, and the values are hashes of `score` and + `comment` entries. See {Appendix: Manual Scoring} for more on this + parameter.""" + if questions is not None: + data["questions"] = questions + + self.logger.debug("PUT /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}".format(**path), data=data, params=params, no_data=True) + + def complete_quiz_submission_turn_it_in(self, id, quiz_id, attempt, course_id, validation_token, access_code=None): + """ + Complete the quiz submission (turn it in). + + Complete the quiz submission by marking it as complete and grading it. When + the quiz submission has been marked as complete, no further modifications + will be allowed. + + Responses + + * 200 OK if the request was successful + * 403 Forbidden if an invalid access code is specified + * 403 Forbidden if the Quiz's IP filter restriction does not pass + * 403 Forbidden if an invalid token is specified + * 400 Bad Request if the QS is already complete + * 400 Bad Request if the attempt parameter is missing + * 400 Bad Request if the attempt parameter is not the latest attempt + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - attempt + """The attempt number of the quiz submission that should be completed. Note + that this must be the latest attempt index, as earlier attempts can not + be modified.""" + data["attempt"] = attempt + + # REQUIRED - validation_token + """The unique validation token you received when this Quiz Submission was + created.""" + data["validation_token"] = validation_token + + # OPTIONAL - access_code + """Access code for the Quiz, if any.""" + if access_code is not None: + data["access_code"] = access_code + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}/complete with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}/complete".format(**path), data=data, params=params, no_data=True) + + def get_current_quiz_submission_times(self, id, quiz_id, course_id): + """ + Get current quiz submission times. + + Get the current timing data for the quiz attempt, both the end_at timestamp + and the time_left parameter. + + Responses + + * 200 OK if the request was successful + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - quiz_id + """ID""" + path["quiz_id"] = quiz_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}/time with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{quiz_id}/submissions/{id}/time".format(**path), data=data, params=params, no_data=True) + + +class Quizsubmission(BaseModel): + """Quizsubmission Model.""" + + def __init__(self, id, quiz_id, submission_id=None, user_id=None, kept_score=None, time_spent=None, workflow_state=None, finished_at=None, overdue_and_needs_submission=None, end_at=None, manually_unlocked=None, score_before_regrade=None, score=None, extra_attempts=None, fudge_points=None, attempt=None, started_at=None, extra_time=None, has_seen_results=None): + """Init method for Quizsubmission class.""" + self._submission_id = submission_id + self._user_id = user_id + self._kept_score = kept_score + self._time_spent = time_spent + self._workflow_state = workflow_state + self._finished_at = finished_at + self._overdue_and_needs_submission = overdue_and_needs_submission + self._end_at = end_at + self._manually_unlocked = manually_unlocked + self._score_before_regrade = score_before_regrade + self._score = score + self._extra_attempts = extra_attempts + self._fudge_points = fudge_points + self._attempt = attempt + self._quiz_id = quiz_id + self._started_at = started_at + self._extra_time = extra_time + self._id = id + self._has_seen_results = has_seen_results + + self.logger = logging.getLogger('pycanvas.Quizsubmission') + + @property + def submission_id(self): + """The ID of the Submission the quiz submission represents.""" + return self._submission_id + + @submission_id.setter + def submission_id(self, value): + """Setter for submission_id property.""" + self.logger.warn("Setting values on submission_id will NOT update the remote Canvas instance.") + self._submission_id = value + + @property + def user_id(self): + """The ID of the Student that made the quiz submission.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def kept_score(self): + """For quizzes that allow multiple attempts, this is the score that will be used, which might be the score of the latest, or the highest, quiz submission.""" + return self._kept_score + + @kept_score.setter + def kept_score(self, value): + """Setter for kept_score property.""" + self.logger.warn("Setting values on kept_score will NOT update the remote Canvas instance.") + self._kept_score = value + + @property + def time_spent(self): + """Amount of time spent, in seconds.""" + return self._time_spent + + @time_spent.setter + def time_spent(self, value): + """Setter for time_spent property.""" + self.logger.warn("Setting values on time_spent will NOT update the remote Canvas instance.") + self._time_spent = value + + @property + def workflow_state(self): + """The current state of the quiz submission. Possible values: ['untaken'|'pending_review'|'complete'|'settings_only'|'preview'].""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def finished_at(self): + """The time at which the student submitted the quiz submission.""" + return self._finished_at + + @finished_at.setter + def finished_at(self, value): + """Setter for finished_at property.""" + self.logger.warn("Setting values on finished_at will NOT update the remote Canvas instance.") + self._finished_at = value + + @property + def overdue_and_needs_submission(self): + """Indicates whether the quiz submission is overdue and needs submission.""" + return self._overdue_and_needs_submission + + @overdue_and_needs_submission.setter + def overdue_and_needs_submission(self, value): + """Setter for overdue_and_needs_submission property.""" + self.logger.warn("Setting values on overdue_and_needs_submission will NOT update the remote Canvas instance.") + self._overdue_and_needs_submission = value + + @property + def end_at(self): + """The time at which the quiz submission will be overdue, and be flagged as a late submission.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def manually_unlocked(self): + """The student can take the quiz even if it's locked for everyone else.""" + return self._manually_unlocked + + @manually_unlocked.setter + def manually_unlocked(self, value): + """Setter for manually_unlocked property.""" + self.logger.warn("Setting values on manually_unlocked will NOT update the remote Canvas instance.") + self._manually_unlocked = value + + @property + def score_before_regrade(self): + """The original score of the quiz submission prior to any re-grading.""" + return self._score_before_regrade + + @score_before_regrade.setter + def score_before_regrade(self, value): + """Setter for score_before_regrade property.""" + self.logger.warn("Setting values on score_before_regrade will NOT update the remote Canvas instance.") + self._score_before_regrade = value + + @property + def score(self): + """The score of the quiz submission, if graded.""" + return self._score + + @score.setter + def score(self, value): + """Setter for score property.""" + self.logger.warn("Setting values on score will NOT update the remote Canvas instance.") + self._score = value + + @property + def extra_attempts(self): + """Number of times the student was allowed to re-take the quiz over the multiple-attempt limit.""" + return self._extra_attempts + + @extra_attempts.setter + def extra_attempts(self, value): + """Setter for extra_attempts property.""" + self.logger.warn("Setting values on extra_attempts will NOT update the remote Canvas instance.") + self._extra_attempts = value + + @property + def fudge_points(self): + """Number of points the quiz submission's score was fudged by.""" + return self._fudge_points + + @fudge_points.setter + def fudge_points(self, value): + """Setter for fudge_points property.""" + self.logger.warn("Setting values on fudge_points will NOT update the remote Canvas instance.") + self._fudge_points = value + + @property + def attempt(self): + """For quizzes that allow multiple attempts, this field specifies the quiz submission attempt number.""" + return self._attempt + + @attempt.setter + def attempt(self, value): + """Setter for attempt property.""" + self.logger.warn("Setting values on attempt will NOT update the remote Canvas instance.") + self._attempt = value + + @property + def quiz_id(self): + """The ID of the Quiz the quiz submission belongs to.""" + return self._quiz_id + + @quiz_id.setter + def quiz_id(self, value): + """Setter for quiz_id property.""" + self.logger.warn("Setting values on quiz_id will NOT update the remote Canvas instance.") + self._quiz_id = value + + @property + def started_at(self): + """The time at which the student started the quiz submission.""" + return self._started_at + + @started_at.setter + def started_at(self, value): + """Setter for started_at property.""" + self.logger.warn("Setting values on started_at will NOT update the remote Canvas instance.") + self._started_at = value + + @property + def extra_time(self): + """Amount of extra time allowed for the quiz submission, in minutes.""" + return self._extra_time + + @extra_time.setter + def extra_time(self, value): + """Setter for extra_time property.""" + self.logger.warn("Setting values on extra_time will NOT update the remote Canvas instance.") + self._extra_time = value + + @property + def id(self): + """The ID of the quiz submission.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def has_seen_results(self): + """Whether the student has viewed their results to the quiz.""" + return self._has_seen_results + + @has_seen_results.setter + def has_seen_results(self, value): + """Setter for has_seen_results property.""" + self.logger.warn("Setting values on has_seen_results will NOT update the remote Canvas instance.") + self._has_seen_results = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/quizzes.py b/venv/Lib/site-packages/pycanvas/apis/quizzes.py new file mode 100644 index 00000000..3d869e14 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/quizzes.py @@ -0,0 +1,909 @@ +"""Quizzes API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class QuizzesAPI(BaseCanvasAPI): + """Quizzes API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for QuizzesAPI.""" + super(QuizzesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.QuizzesAPI") + + def list_quizzes_in_course(self, course_id, search_term=None): + """ + List quizzes in a course. + + Returns the list of Quizzes in this course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - search_term + """The partial title of the quizzes to match and return.""" + if search_term is not None: + params["search_term"] = search_term + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes".format(**path), data=data, params=params, all_pages=True) + + def get_single_quiz(self, id, course_id): + """ + Get a single quiz. + + Returns the quiz with the given id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/courses/{course_id}/quizzes/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/quizzes/{id}".format(**path), data=data, params=params, single_item=True) + + def create_quiz(self, course_id, quiz_title, quiz_access_code=None, quiz_allowed_attempts=None, quiz_assignment_group_id=None, quiz_cant_go_back=None, quiz_description=None, quiz_due_at=None, quiz_hide_correct_answers_at=None, quiz_hide_results=None, quiz_ip_filter=None, quiz_lock_at=None, quiz_one_question_at_a_time=None, quiz_one_time_results=None, quiz_only_visible_to_overrides=None, quiz_published=None, quiz_quiz_type=None, quiz_scoring_policy=None, quiz_show_correct_answers=None, quiz_show_correct_answers_at=None, quiz_show_correct_answers_last_attempt=None, quiz_shuffle_answers=None, quiz_time_limit=None, quiz_unlock_at=None): + """ + Create a quiz. + + Create a new quiz for this course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - quiz[title] + """The quiz title.""" + data["quiz[title]"] = quiz_title + + # OPTIONAL - quiz[description] + """A description of the quiz.""" + if quiz_description is not None: + data["quiz[description]"] = quiz_description + + # OPTIONAL - quiz[quiz_type] + """The type of quiz.""" + if quiz_quiz_type is not None: + self._validate_enum(quiz_quiz_type, ["practice_quiz", "assignment", "graded_survey", "survey"]) + data["quiz[quiz_type]"] = quiz_quiz_type + + # OPTIONAL - quiz[assignment_group_id] + """The assignment group id to put the assignment in. Defaults to the top + assignment group in the course. Only valid if the quiz is graded, i.e. if + quiz_type is "assignment" or "graded_survey".""" + if quiz_assignment_group_id is not None: + data["quiz[assignment_group_id]"] = quiz_assignment_group_id + + # OPTIONAL - quiz[time_limit] + """Time limit to take this quiz, in minutes. Set to null for no time limit. + Defaults to null.""" + if quiz_time_limit is not None: + data["quiz[time_limit]"] = quiz_time_limit + + # OPTIONAL - quiz[shuffle_answers] + """If true, quiz answers for multiple choice questions will be randomized for + each student. Defaults to false.""" + if quiz_shuffle_answers is not None: + data["quiz[shuffle_answers]"] = quiz_shuffle_answers + + # OPTIONAL - quiz[hide_results] + """Dictates whether or not quiz results are hidden from students. + If null, students can see their results after any attempt. + If "always", students can never see their results. + If "until_after_last_attempt", students can only see results after their + last attempt. (Only valid if allowed_attempts > 1). Defaults to null.""" + if quiz_hide_results is not None: + self._validate_enum(quiz_hide_results, ["always", "until_after_last_attempt"]) + data["quiz[hide_results]"] = quiz_hide_results + + # OPTIONAL - quiz[show_correct_answers] + """Only valid if hide_results=null + If false, hides correct answers from students when quiz results are viewed. + Defaults to true.""" + if quiz_show_correct_answers is not None: + data["quiz[show_correct_answers]"] = quiz_show_correct_answers + + # OPTIONAL - quiz[show_correct_answers_last_attempt] + """Only valid if show_correct_answers=true and allowed_attempts > 1 + If true, hides correct answers from students when quiz results are viewed + until they submit the last attempt for the quiz. + Defaults to false.""" + if quiz_show_correct_answers_last_attempt is not None: + data["quiz[show_correct_answers_last_attempt]"] = quiz_show_correct_answers_last_attempt + + # OPTIONAL - quiz[show_correct_answers_at] + """Only valid if show_correct_answers=true + If set, the correct answers will be visible by students only after this + date, otherwise the correct answers are visible once the student hands in + their quiz submission.""" + if quiz_show_correct_answers_at is not None: + data["quiz[show_correct_answers_at]"] = quiz_show_correct_answers_at + + # OPTIONAL - quiz[hide_correct_answers_at] + """Only valid if show_correct_answers=true + If set, the correct answers will stop being visible once this date has + passed. Otherwise, the correct answers will be visible indefinitely.""" + if quiz_hide_correct_answers_at is not None: + data["quiz[hide_correct_answers_at]"] = quiz_hide_correct_answers_at + + # OPTIONAL - quiz[allowed_attempts] + """Number of times a student is allowed to take a quiz. + Set to -1 for unlimited attempts. + Defaults to 1.""" + if quiz_allowed_attempts is not None: + data["quiz[allowed_attempts]"] = quiz_allowed_attempts + + # OPTIONAL - quiz[scoring_policy] + """Required and only valid if allowed_attempts > 1. + Scoring policy for a quiz that students can take multiple times. + Defaults to "keep_highest".""" + if quiz_scoring_policy is not None: + self._validate_enum(quiz_scoring_policy, ["keep_highest", "keep_latest"]) + data["quiz[scoring_policy]"] = quiz_scoring_policy + + # OPTIONAL - quiz[one_question_at_a_time] + """If true, shows quiz to student one question at a time. + Defaults to false.""" + if quiz_one_question_at_a_time is not None: + data["quiz[one_question_at_a_time]"] = quiz_one_question_at_a_time + + # OPTIONAL - quiz[cant_go_back] + """Only valid if one_question_at_a_time=true + If true, questions are locked after answering. + Defaults to false.""" + if quiz_cant_go_back is not None: + data["quiz[cant_go_back]"] = quiz_cant_go_back + + # OPTIONAL - quiz[access_code] + """Restricts access to the quiz with a password. + For no access code restriction, set to null. + Defaults to null.""" + if quiz_access_code is not None: + data["quiz[access_code]"] = quiz_access_code + + # OPTIONAL - quiz[ip_filter] + """Restricts access to the quiz to computers in a specified IP range. + Filters can be a comma-separated list of addresses, or an address followed by a mask + + Examples: + "192.168.217.1" + "192.168.217.1/24" + "192.168.217.1/255.255.255.0" + + For no IP filter restriction, set to null. + Defaults to null.""" + if quiz_ip_filter is not None: + data["quiz[ip_filter]"] = quiz_ip_filter + + # OPTIONAL - quiz[due_at] + """The day/time the quiz is due. + Accepts times in ISO 8601 format, e.g. 2011-10-21T18:48Z.""" + if quiz_due_at is not None: + data["quiz[due_at]"] = quiz_due_at + + # OPTIONAL - quiz[lock_at] + """The day/time the quiz is locked for students. + Accepts times in ISO 8601 format, e.g. 2011-10-21T18:48Z.""" + if quiz_lock_at is not None: + data["quiz[lock_at]"] = quiz_lock_at + + # OPTIONAL - quiz[unlock_at] + """The day/time the quiz is unlocked for students. + Accepts times in ISO 8601 format, e.g. 2011-10-21T18:48Z.""" + if quiz_unlock_at is not None: + data["quiz[unlock_at]"] = quiz_unlock_at + + # OPTIONAL - quiz[published] + """Whether the quiz should have a draft state of published or unpublished. + NOTE: If students have started taking the quiz, or there are any + submissions for the quiz, you may not unpublish a quiz and will recieve + an error.""" + if quiz_published is not None: + data["quiz[published]"] = quiz_published + + # OPTIONAL - quiz[one_time_results] + """Whether students should be prevented from viewing their quiz results past + the first time (right after they turn the quiz in.) + Only valid if "hide_results" is not set to "always". + Defaults to false.""" + if quiz_one_time_results is not None: + data["quiz[one_time_results]"] = quiz_one_time_results + + # OPTIONAL - quiz[only_visible_to_overrides] + """Whether this quiz is only visible to overrides (Only useful if + 'differentiated assignments' account setting is on) + Defaults to false.""" + if quiz_only_visible_to_overrides is not None: + data["quiz[only_visible_to_overrides]"] = quiz_only_visible_to_overrides + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes".format(**path), data=data, params=params, single_item=True) + + def edit_quiz(self, id, course_id, quiz_notify_of_update=None): + """ + Edit a quiz. + + Modify an existing quiz. See the documentation for quiz creation. + + Additional arguments: + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - quiz[notify_of_update] + """If true, notifies users that the quiz has changed. + Defaults to true""" + if quiz_notify_of_update is not None: + data["quiz[notify_of_update]"] = quiz_notify_of_update + + self.logger.debug("PUT /api/v1/courses/{course_id}/quizzes/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/quizzes/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_quiz(self, id, course_id): + """ + Delete a quiz. + + + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/quizzes/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/quizzes/{id}".format(**path), data=data, params=params, single_item=True) + + def reorder_quiz_items(self, id, order_id, course_id, order_type=None): + """ + Reorder quiz items. + + Change order of the quiz questions or groups within the quiz + + 204 No Content response code is returned if the reorder was successful. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - order[id] + """The associated item's unique identifier""" + data["order[id]"] = order_id + + # OPTIONAL - order[type] + """The type of item is either 'question' or 'group'""" + if order_type is not None: + self._validate_enum(order_type, ["question", "group"]) + data["order[type]"] = order_type + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{id}/reorder with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{id}/reorder".format(**path), data=data, params=params, no_data=True) + + def validate_quiz_access_code(self, id, course_id, access_code): + """ + Validate quiz access code. + + Accepts an access code and returns a boolean indicating whether that access code is correct + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - access_code + """The access code being validated""" + data["access_code"] = access_code + + self.logger.debug("POST /api/v1/courses/{course_id}/quizzes/{id}/validate_access_code with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/quizzes/{id}/validate_access_code".format(**path), data=data, params=params) + + +class Quizpermissions(BaseModel): + """Quizpermissions Model. + Permissions the user has for the quiz""" + + def __init__(self, read=None, create=None, manage=None, update=None, submit=None, read_statistics=None, review_grades=None): + """Init method for Quizpermissions class.""" + self._read = read + self._create = create + self._manage = manage + self._update = update + self._submit = submit + self._read_statistics = read_statistics + self._review_grades = review_grades + + self.logger = logging.getLogger('pycanvas.Quizpermissions') + + @property + def read(self): + """whether the user can view the quiz.""" + return self._read + + @read.setter + def read(self, value): + """Setter for read property.""" + self.logger.warn("Setting values on read will NOT update the remote Canvas instance.") + self._read = value + + @property + def create(self): + """whether the user may create a new quiz.""" + return self._create + + @create.setter + def create(self, value): + """Setter for create property.""" + self.logger.warn("Setting values on create will NOT update the remote Canvas instance.") + self._create = value + + @property + def manage(self): + """whether the user may edit, update, or delete the quiz.""" + return self._manage + + @manage.setter + def manage(self, value): + """Setter for manage property.""" + self.logger.warn("Setting values on manage will NOT update the remote Canvas instance.") + self._manage = value + + @property + def update(self): + """whether the user may update the quiz.""" + return self._update + + @update.setter + def update(self, value): + """Setter for update property.""" + self.logger.warn("Setting values on update will NOT update the remote Canvas instance.") + self._update = value + + @property + def submit(self): + """whether the user may submit a submission for the quiz.""" + return self._submit + + @submit.setter + def submit(self, value): + """Setter for submit property.""" + self.logger.warn("Setting values on submit will NOT update the remote Canvas instance.") + self._submit = value + + @property + def read_statistics(self): + """whether the user may view quiz statistics for this quiz.""" + return self._read_statistics + + @read_statistics.setter + def read_statistics(self, value): + """Setter for read_statistics property.""" + self.logger.warn("Setting values on read_statistics will NOT update the remote Canvas instance.") + self._read_statistics = value + + @property + def review_grades(self): + """whether the user may review grades for all quiz submissions for this quiz.""" + return self._review_grades + + @review_grades.setter + def review_grades(self, value): + """Setter for review_grades property.""" + self.logger.warn("Setting values on review_grades will NOT update the remote Canvas instance.") + self._review_grades = value + + +class Quiz(BaseModel): + """Quiz Model.""" + + def __init__(self, time_limit=None, lock_info=None, one_question_at_a_time=None, points_possible=None, question_types=None, quiz_type=None, shuffle_answers=None, id=None, locked_for_user=None, mobile_url=None, allowed_attempts=None, title=None, show_correct_answers=None, scoring_policy=None, permissions=None, hide_correct_answers_at=None, show_correct_answers_at=None, description=None, all_dates=None, cant_go_back=None, html_url=None, speedgrader_url=None, hide_results=None, lock_explanation=None, quiz_extensions_url=None, question_count=None, ip_filter=None, show_correct_answers_last_attempt=None, version_number=None, unlock_at=None, one_time_results=None, due_at=None, preview_url=None, lock_at=None, assignment_group_id=None, published=None, access_code=None, unpublishable=None): + """Init method for Quiz class.""" + self._time_limit = time_limit + self._lock_info = lock_info + self._one_question_at_a_time = one_question_at_a_time + self._points_possible = points_possible + self._question_types = question_types + self._quiz_type = quiz_type + self._shuffle_answers = shuffle_answers + self._id = id + self._locked_for_user = locked_for_user + self._mobile_url = mobile_url + self._allowed_attempts = allowed_attempts + self._title = title + self._show_correct_answers = show_correct_answers + self._scoring_policy = scoring_policy + self._permissions = permissions + self._hide_correct_answers_at = hide_correct_answers_at + self._show_correct_answers_at = show_correct_answers_at + self._description = description + self._all_dates = all_dates + self._cant_go_back = cant_go_back + self._html_url = html_url + self._speedgrader_url = speedgrader_url + self._hide_results = hide_results + self._lock_explanation = lock_explanation + self._quiz_extensions_url = quiz_extensions_url + self._question_count = question_count + self._ip_filter = ip_filter + self._show_correct_answers_last_attempt = show_correct_answers_last_attempt + self._version_number = version_number + self._unlock_at = unlock_at + self._one_time_results = one_time_results + self._due_at = due_at + self._preview_url = preview_url + self._lock_at = lock_at + self._assignment_group_id = assignment_group_id + self._published = published + self._access_code = access_code + self._unpublishable = unpublishable + + self.logger = logging.getLogger('pycanvas.Quiz') + + @property + def time_limit(self): + """quiz time limit in minutes.""" + return self._time_limit + + @time_limit.setter + def time_limit(self, value): + """Setter for time_limit property.""" + self.logger.warn("Setting values on time_limit will NOT update the remote Canvas instance.") + self._time_limit = value + + @property + def lock_info(self): + """(Optional) Information for the user about the lock. Present when locked_for_user is true.""" + return self._lock_info + + @lock_info.setter + def lock_info(self, value): + """Setter for lock_info property.""" + self.logger.warn("Setting values on lock_info will NOT update the remote Canvas instance.") + self._lock_info = value + + @property + def one_question_at_a_time(self): + """show one question at a time?.""" + return self._one_question_at_a_time + + @one_question_at_a_time.setter + def one_question_at_a_time(self, value): + """Setter for one_question_at_a_time property.""" + self.logger.warn("Setting values on one_question_at_a_time will NOT update the remote Canvas instance.") + self._one_question_at_a_time = value + + @property + def points_possible(self): + """The total point value given to the quiz.""" + return self._points_possible + + @points_possible.setter + def points_possible(self, value): + """Setter for points_possible property.""" + self.logger.warn("Setting values on points_possible will NOT update the remote Canvas instance.") + self._points_possible = value + + @property + def question_types(self): + """List of question types in the quiz.""" + return self._question_types + + @question_types.setter + def question_types(self, value): + """Setter for question_types property.""" + self.logger.warn("Setting values on question_types will NOT update the remote Canvas instance.") + self._question_types = value + + @property + def quiz_type(self): + """type of quiz possible values: 'practice_quiz', 'assignment', 'graded_survey', 'survey'.""" + return self._quiz_type + + @quiz_type.setter + def quiz_type(self, value): + """Setter for quiz_type property.""" + self.logger.warn("Setting values on quiz_type will NOT update the remote Canvas instance.") + self._quiz_type = value + + @property + def shuffle_answers(self): + """shuffle answers for students?.""" + return self._shuffle_answers + + @shuffle_answers.setter + def shuffle_answers(self, value): + """Setter for shuffle_answers property.""" + self.logger.warn("Setting values on shuffle_answers will NOT update the remote Canvas instance.") + self._shuffle_answers = value + + @property + def id(self): + """the ID of the quiz.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def locked_for_user(self): + """Whether or not this is locked for the user.""" + return self._locked_for_user + + @locked_for_user.setter + def locked_for_user(self, value): + """Setter for locked_for_user property.""" + self.logger.warn("Setting values on locked_for_user will NOT update the remote Canvas instance.") + self._locked_for_user = value + + @property + def mobile_url(self): + """a url suitable for loading the quiz in a mobile webview. it will persiste the headless session and, for quizzes in public courses, will force the user to login.""" + return self._mobile_url + + @mobile_url.setter + def mobile_url(self, value): + """Setter for mobile_url property.""" + self.logger.warn("Setting values on mobile_url will NOT update the remote Canvas instance.") + self._mobile_url = value + + @property + def allowed_attempts(self): + """how many times a student can take the quiz -1 = unlimited attempts.""" + return self._allowed_attempts + + @allowed_attempts.setter + def allowed_attempts(self, value): + """Setter for allowed_attempts property.""" + self.logger.warn("Setting values on allowed_attempts will NOT update the remote Canvas instance.") + self._allowed_attempts = value + + @property + def title(self): + """the title of the quiz.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def show_correct_answers(self): + """show which answers were correct when results are shown? only valid if hide_results=null.""" + return self._show_correct_answers + + @show_correct_answers.setter + def show_correct_answers(self, value): + """Setter for show_correct_answers property.""" + self.logger.warn("Setting values on show_correct_answers will NOT update the remote Canvas instance.") + self._show_correct_answers = value + + @property + def scoring_policy(self): + """which quiz score to keep (only if allowed_attempts != 1) possible values: 'keep_highest', 'keep_latest'.""" + return self._scoring_policy + + @scoring_policy.setter + def scoring_policy(self, value): + """Setter for scoring_policy property.""" + self.logger.warn("Setting values on scoring_policy will NOT update the remote Canvas instance.") + self._scoring_policy = value + + @property + def permissions(self): + """Permissions the user has for the quiz.""" + return self._permissions + + @permissions.setter + def permissions(self, value): + """Setter for permissions property.""" + self.logger.warn("Setting values on permissions will NOT update the remote Canvas instance.") + self._permissions = value + + @property + def hide_correct_answers_at(self): + """prevent the students from seeing correct answers after the specified date has passed. only valid if show_correct_answers=true.""" + return self._hide_correct_answers_at + + @hide_correct_answers_at.setter + def hide_correct_answers_at(self, value): + """Setter for hide_correct_answers_at property.""" + self.logger.warn("Setting values on hide_correct_answers_at will NOT update the remote Canvas instance.") + self._hide_correct_answers_at = value + + @property + def show_correct_answers_at(self): + """when should the correct answers be visible by students? only valid if show_correct_answers=true.""" + return self._show_correct_answers_at + + @show_correct_answers_at.setter + def show_correct_answers_at(self, value): + """Setter for show_correct_answers_at property.""" + self.logger.warn("Setting values on show_correct_answers_at will NOT update the remote Canvas instance.") + self._show_correct_answers_at = value + + @property + def description(self): + """the description of the quiz.""" + return self._description + + @description.setter + def description(self, value): + """Setter for description property.""" + self.logger.warn("Setting values on description will NOT update the remote Canvas instance.") + self._description = value + + @property + def all_dates(self): + """list of due dates for the quiz.""" + return self._all_dates + + @all_dates.setter + def all_dates(self, value): + """Setter for all_dates property.""" + self.logger.warn("Setting values on all_dates will NOT update the remote Canvas instance.") + self._all_dates = value + + @property + def cant_go_back(self): + """lock questions after answering? only valid if one_question_at_a_time=true.""" + return self._cant_go_back + + @cant_go_back.setter + def cant_go_back(self, value): + """Setter for cant_go_back property.""" + self.logger.warn("Setting values on cant_go_back will NOT update the remote Canvas instance.") + self._cant_go_back = value + + @property + def html_url(self): + """the HTTP/HTTPS URL to the quiz.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def speedgrader_url(self): + """Link to Speed Grader for this quiz. Will not be present if quiz is unpublished.""" + return self._speedgrader_url + + @speedgrader_url.setter + def speedgrader_url(self, value): + """Setter for speedgrader_url property.""" + self.logger.warn("Setting values on speedgrader_url will NOT update the remote Canvas instance.") + self._speedgrader_url = value + + @property + def hide_results(self): + """let students see their quiz responses? possible values: null, 'always', 'until_after_last_attempt'.""" + return self._hide_results + + @hide_results.setter + def hide_results(self, value): + """Setter for hide_results property.""" + self.logger.warn("Setting values on hide_results will NOT update the remote Canvas instance.") + self._hide_results = value + + @property + def lock_explanation(self): + """(Optional) An explanation of why this is locked for the user. Present when locked_for_user is true.""" + return self._lock_explanation + + @lock_explanation.setter + def lock_explanation(self, value): + """Setter for lock_explanation property.""" + self.logger.warn("Setting values on lock_explanation will NOT update the remote Canvas instance.") + self._lock_explanation = value + + @property + def quiz_extensions_url(self): + """Link to endpoint to send extensions for this quiz.""" + return self._quiz_extensions_url + + @quiz_extensions_url.setter + def quiz_extensions_url(self, value): + """Setter for quiz_extensions_url property.""" + self.logger.warn("Setting values on quiz_extensions_url will NOT update the remote Canvas instance.") + self._quiz_extensions_url = value + + @property + def question_count(self): + """the number of questions in the quiz.""" + return self._question_count + + @question_count.setter + def question_count(self, value): + """Setter for question_count property.""" + self.logger.warn("Setting values on question_count will NOT update the remote Canvas instance.") + self._question_count = value + + @property + def ip_filter(self): + """IP address or range that quiz access is limited to.""" + return self._ip_filter + + @ip_filter.setter + def ip_filter(self, value): + """Setter for ip_filter property.""" + self.logger.warn("Setting values on ip_filter will NOT update the remote Canvas instance.") + self._ip_filter = value + + @property + def show_correct_answers_last_attempt(self): + """restrict the show_correct_answers option above to apply only to the last submitted attempt of a quiz that allows multiple attempts. only valid if show_correct_answers=true and allowed_attempts > 1.""" + return self._show_correct_answers_last_attempt + + @show_correct_answers_last_attempt.setter + def show_correct_answers_last_attempt(self, value): + """Setter for show_correct_answers_last_attempt property.""" + self.logger.warn("Setting values on show_correct_answers_last_attempt will NOT update the remote Canvas instance.") + self._show_correct_answers_last_attempt = value + + @property + def version_number(self): + """Current version number of the quiz.""" + return self._version_number + + @version_number.setter + def version_number(self, value): + """Setter for version_number property.""" + self.logger.warn("Setting values on version_number will NOT update the remote Canvas instance.") + self._version_number = value + + @property + def unlock_at(self): + """when to unlock the quiz.""" + return self._unlock_at + + @unlock_at.setter + def unlock_at(self, value): + """Setter for unlock_at property.""" + self.logger.warn("Setting values on unlock_at will NOT update the remote Canvas instance.") + self._unlock_at = value + + @property + def one_time_results(self): + """prevent the students from seeing their results more than once (right after they submit the quiz).""" + return self._one_time_results + + @one_time_results.setter + def one_time_results(self, value): + """Setter for one_time_results property.""" + self.logger.warn("Setting values on one_time_results will NOT update the remote Canvas instance.") + self._one_time_results = value + + @property + def due_at(self): + """when the quiz is due.""" + return self._due_at + + @due_at.setter + def due_at(self, value): + """Setter for due_at property.""" + self.logger.warn("Setting values on due_at will NOT update the remote Canvas instance.") + self._due_at = value + + @property + def preview_url(self): + """A url that can be visited in the browser with a POST request to preview a quiz as the teacher. Only present when the user may grade.""" + return self._preview_url + + @preview_url.setter + def preview_url(self, value): + """Setter for preview_url property.""" + self.logger.warn("Setting values on preview_url will NOT update the remote Canvas instance.") + self._preview_url = value + + @property + def lock_at(self): + """when to lock the quiz.""" + return self._lock_at + + @lock_at.setter + def lock_at(self, value): + """Setter for lock_at property.""" + self.logger.warn("Setting values on lock_at will NOT update the remote Canvas instance.") + self._lock_at = value + + @property + def assignment_group_id(self): + """the ID of the quiz's assignment group:.""" + return self._assignment_group_id + + @assignment_group_id.setter + def assignment_group_id(self, value): + """Setter for assignment_group_id property.""" + self.logger.warn("Setting values on assignment_group_id will NOT update the remote Canvas instance.") + self._assignment_group_id = value + + @property + def published(self): + """whether the quiz has a published or unpublished draft state.""" + return self._published + + @published.setter + def published(self, value): + """Setter for published property.""" + self.logger.warn("Setting values on published will NOT update the remote Canvas instance.") + self._published = value + + @property + def access_code(self): + """access code to restrict quiz access.""" + return self._access_code + + @access_code.setter + def access_code(self, value): + """Setter for access_code property.""" + self.logger.warn("Setting values on access_code will NOT update the remote Canvas instance.") + self._access_code = value + + @property + def unpublishable(self): + """Whether the assignment's 'published' state can be changed to false. Will be false if there are student submissions for the quiz.""" + return self._unpublishable + + @unpublishable.setter + def unpublishable(self, value): + """Setter for unpublishable property.""" + self.logger.warn("Setting values on unpublishable will NOT update the remote Canvas instance.") + self._unpublishable = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/roles.py b/venv/Lib/site-packages/pycanvas/apis/roles.py new file mode 100644 index 00000000..1498c3f3 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/roles.py @@ -0,0 +1,517 @@ +"""Roles API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class RolesAPI(BaseCanvasAPI): + """Roles API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for RolesAPI.""" + super(RolesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.RolesAPI") + + def list_roles(self, account_id, show_inherited=None, state=None): + """ + List roles. + + List the roles available to an account. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """The id of the account to retrieve roles for.""" + path["account_id"] = account_id + + # OPTIONAL - state + """Filter by role state. If this argument is omitted, only 'active' roles are + returned.""" + if state is not None: + self._validate_enum(state, ["active", "inactive"]) + params["state"] = state + + # OPTIONAL - show_inherited + """If this argument is true, all roles inherited from parent accounts will + be included.""" + if show_inherited is not None: + params["show_inherited"] = show_inherited + + self.logger.debug("GET /api/v1/accounts/{account_id}/roles with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/roles".format(**path), data=data, params=params, all_pages=True) + + def get_single_role(self, id, role_id, account_id, role=None): + """ + Get a single role. + + Retrieve information about a single role + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - account_id + """The id of the account containing the role""" + path["account_id"] = account_id + + # REQUIRED - role_id + """The unique identifier for the role""" + params["role_id"] = role_id + + # OPTIONAL - role + """The name for the role""" + if role is not None: + params["role"] = role + + self.logger.debug("GET /api/v1/accounts/{account_id}/roles/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/roles/{id}".format(**path), data=data, params=params, single_item=True) + + def create_new_role(self, label, account_id, base_role_type=None, permissions__applies_to_descendants=None, permissions__applies_to_self=None, permissions__enabled=None, permissions__explicit=None, permissions__locked=None, role=None): + """ + Create a new role. + + Create a new course-level or account-level role. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - label + """Label for the role.""" + data["label"] = label + + # OPTIONAL - role + """Deprecated alias for label.""" + if role is not None: + data["role"] = role + + # OPTIONAL - base_role_type + """Specifies the role type that will be used as a base + for the permissions granted to this role. + + Defaults to 'AccountMembership' if absent""" + if base_role_type is not None: + self._validate_enum(base_role_type, ["AccountMembership", "StudentEnrollment", "TeacherEnrollment", "TaEnrollment", "ObserverEnrollment", "DesignerEnrollment"]) + data["base_role_type"] = base_role_type + + # OPTIONAL - permissions[][explicit] + """no description""" + if permissions__explicit is not None: + data["permissions[][explicit]"] = permissions__explicit + + # OPTIONAL - permissions[][enabled] + """If explicit is 1 and enabled is 1, permission will be explicitly + granted to this role. If explicit is 1 and enabled has any other value + (typically 0), permission will be explicitly denied to this role. If + explicit is any other value (typically 0) or absent, or if enabled is + absent, the value for permission will be inherited from upstream. + Ignored if permission is locked upstream (in an ancestor account). + + May occur multiple times with unique values for . Recognized + permission names for are: + + [For Account-Level Roles Only] + become_user -- Become other users + import_sis -- Import SIS data + manage_account_memberships -- Add/remove other admins for the account + manage_account_settings -- Manage account-level settings + manage_alerts -- Manage global alerts + manage_courses -- Manage ( add / edit / delete ) courses + manage_developer_keys -- Manage developer keys + manage_global_outcomes -- Manage learning outcomes + manage_jobs -- Manage background jobs + manage_role_overrides -- Manage permissions + manage_storage_quotas -- Set storage quotas for courses, groups, and users + manage_sis -- Manage SIS data + manage_site_settings -- Manage site-wide and plugin settings + manage_user_logins -- Modify login details for users + read_course_content -- View course content + read_course_list -- View the list of courses + read_messages -- View notifications sent to users + site_admin -- Use the Site Admin section and admin all other accounts + view_error_reports -- View error reports + view_statistics -- View statistics + manage_feature_flags -- Enable or disable features at an account level + + [For both Account-Level and Course-Level roles] + Note: Applicable enrollment types for course-level roles are given in brackets: + S = student, T = teacher, A = TA, D = designer, O = observer. + Lower-case letters indicate permissions that are off by default. + A missing letter indicates the permission cannot be enabled for the role + or any derived custom roles. + change_course_state -- [ TaD ] Change course state + comment_on_others_submissions -- [sTAD ] View all students' submissions and make comments on them + create_collaborations -- [STADo] Create student collaborations + create_conferences -- [STADo] Create web conferences + manage_admin_users -- [ Tad ] Add/remove other teachers, course designers or TAs to the course + manage_assignments -- [ TADo] Manage (add / edit / delete) assignments and quizzes + manage_calendar -- [sTADo] Add, edit and delete events on the course calendar + manage_content -- [ TADo] Manage all other course content + manage_files -- [ TADo] Manage (add / edit / delete) course files + manage_grades -- [ TA ] Edit grades + manage_groups -- [ TAD ] Manage (create / edit / delete) groups + manage_interaction_alerts -- [ Ta ] Manage alerts + manage_outcomes -- [sTaDo] Manage learning outcomes + manage_sections -- [ TaD ] Manage (create / edit / delete) course sections + manage_students -- [ TAD ] Add/remove students for the course + manage_user_notes -- [ TA ] Manage faculty journal entries + manage_rubrics -- [ TAD ] Edit assessing rubrics + manage_wiki -- [ TADo] Manage (add / edit / delete) pages + read_forum -- [STADO] View discussions + moderate_forum -- [sTADo] Moderate discussions (delete/edit others' posts, lock topics) + post_to_forum -- [STADo] Post to discussions + read_announcements -- [STADO] View announcements + read_question_banks -- [ TADo] View and link to question banks + read_reports -- [ TAD ] View usage reports for the course + read_roster -- [STADo] See the list of users + read_sis -- [sTa ] Read SIS data + send_messages -- [STADo] Send messages to individual course members + send_messages_all -- [sTADo] Send messages to the entire class + view_all_grades -- [ TAd ] View all grades + view_group_pages -- [sTADo] View the group pages of all student groups + lti_add_edit -- [ TAD ] LTI add and edit + + Some of these permissions are applicable only for roles on the site admin + account, on a root account, or for course-level roles with a particular base role type; + if a specified permission is inapplicable, it will be ignored. + + Additional permissions may exist based on installed plugins.""" + if permissions__enabled is not None: + data["permissions[][enabled]"] = permissions__enabled + + # OPTIONAL - permissions[][locked] + """If the value is 1, permission will be locked downstream (new roles in + subaccounts cannot override the setting). For any other value, permission + is left unlocked. Ignored if permission is already locked + upstream. May occur multiple times with unique values for .""" + if permissions__locked is not None: + data["permissions[][locked]"] = permissions__locked + + # OPTIONAL - permissions[][applies_to_self] + """If the value is 1, permission applies to the account this role is in. + The default value is 1. Must be true if applies_to_descendants is false. + This value is only returned if enabled is true.""" + if permissions__applies_to_self is not None: + data["permissions[][applies_to_self]"] = permissions__applies_to_self + + # OPTIONAL - permissions[][applies_to_descendants] + """If the value is 1, permission cascades down to sub accounts of the + account this role is in. The default value is 1. Must be true if + applies_to_self is false.This value is only returned if enabled is true.""" + if permissions__applies_to_descendants is not None: + data["permissions[][applies_to_descendants]"] = permissions__applies_to_descendants + + self.logger.debug("POST /api/v1/accounts/{account_id}/roles with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/roles".format(**path), data=data, params=params, single_item=True) + + def deactivate_role(self, id, role_id, account_id, role=None): + """ + Deactivate a role. + + Deactivates a custom role. This hides it in the user interface and prevents it + from being assigned to new users. Existing users assigned to the role will + continue to function with the same permissions they had previously. + Built-in roles cannot be deactivated. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - role_id + """The unique identifier for the role""" + params["role_id"] = role_id + + # OPTIONAL - role + """The name for the role""" + if role is not None: + params["role"] = role + + self.logger.debug("DELETE /api/v1/accounts/{account_id}/roles/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/accounts/{account_id}/roles/{id}".format(**path), data=data, params=params, single_item=True) + + def activate_role(self, id, role_id, account_id, role=None): + """ + Activate a role. + + Re-activates an inactive role (allowing it to be assigned to new users) + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - role_id + """The unique identifier for the role""" + data["role_id"] = role_id + + # OPTIONAL - role + """The name for the role""" + if role is not None: + data["role"] = role + + self.logger.debug("POST /api/v1/accounts/{account_id}/roles/{id}/activate with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/roles/{id}/activate".format(**path), data=data, params=params, single_item=True) + + def update_role(self, id, account_id, label=None, permissions__applies_to_descendants=None, permissions__applies_to_self=None, permissions__enabled=None, permissions__explicit=None): + """ + Update a role. + + Update permissions for an existing role. + + Recognized roles are: + * TeacherEnrollment + * StudentEnrollment + * TaEnrollment + * ObserverEnrollment + * DesignerEnrollment + * AccountAdmin + * Any previously created custom role + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - label + """The label for the role. Can only change the label of a custom role that belongs directly to the account.""" + if label is not None: + data["label"] = label + + # OPTIONAL - permissions[][explicit] + """no description""" + if permissions__explicit is not None: + data["permissions[][explicit]"] = permissions__explicit + + # OPTIONAL - permissions[][enabled] + """These arguments are described in the documentation for the + {api:RoleOverridesController#add_role add_role method}.""" + if permissions__enabled is not None: + data["permissions[][enabled]"] = permissions__enabled + + # OPTIONAL - permissions[][applies_to_self] + """If the value is 1, permission applies to the account this role is in. + The default value is 1. Must be true if applies_to_descendants is false. + This value is only returned if enabled is true.""" + if permissions__applies_to_self is not None: + data["permissions[][applies_to_self]"] = permissions__applies_to_self + + # OPTIONAL - permissions[][applies_to_descendants] + """If the value is 1, permission cascades down to sub accounts of the + account this role is in. The default value is 1. Must be true if + applies_to_self is false.This value is only returned if enabled is true.""" + if permissions__applies_to_descendants is not None: + data["permissions[][applies_to_descendants]"] = permissions__applies_to_descendants + + self.logger.debug("PUT /api/v1/accounts/{account_id}/roles/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/roles/{id}".format(**path), data=data, params=params, single_item=True) + + +class Rolepermissions(BaseModel): + """Rolepermissions Model.""" + + def __init__(self, locked=False, applies_to_descendants=True, explicit=False, enabled=None, readonly=False, prior_default=None, applies_to_self=True): + """Init method for Rolepermissions class.""" + self._locked = locked + self._applies_to_descendants = applies_to_descendants + self._explicit = explicit + self._enabled = enabled + self._readonly = readonly + self._prior_default = prior_default + self._applies_to_self = applies_to_self + + self.logger = logging.getLogger('pycanvas.Rolepermissions') + + @property + def locked(self): + """Whether the permission is locked by this role.""" + return self._locked + + @locked.setter + def locked(self, value): + """Setter for locked property.""" + self.logger.warn("Setting values on locked will NOT update the remote Canvas instance.") + self._locked = value + + @property + def applies_to_descendants(self): + """Whether the permission cascades down to sub accounts of the account this role is in. Only present if enabled is true.""" + return self._applies_to_descendants + + @applies_to_descendants.setter + def applies_to_descendants(self, value): + """Setter for applies_to_descendants property.""" + self.logger.warn("Setting values on applies_to_descendants will NOT update the remote Canvas instance.") + self._applies_to_descendants = value + + @property + def explicit(self): + """Whether the value of enabled is specified explicitly by this role, or inherited from an upstream role.""" + return self._explicit + + @explicit.setter + def explicit(self, value): + """Setter for explicit property.""" + self.logger.warn("Setting values on explicit will NOT update the remote Canvas instance.") + self._explicit = value + + @property + def enabled(self): + """Whether the role has the permission.""" + return self._enabled + + @enabled.setter + def enabled(self, value): + """Setter for enabled property.""" + self.logger.warn("Setting values on enabled will NOT update the remote Canvas instance.") + self._enabled = value + + @property + def readonly(self): + """Whether the permission can be modified in this role (i.e. whether the permission is locked by an upstream role).""" + return self._readonly + + @readonly.setter + def readonly(self, value): + """Setter for readonly property.""" + self.logger.warn("Setting values on readonly will NOT update the remote Canvas instance.") + self._readonly = value + + @property + def prior_default(self): + """The value that would have been inherited from upstream if the role had not explicitly set a value. Only present if explicit is true.""" + return self._prior_default + + @prior_default.setter + def prior_default(self, value): + """Setter for prior_default property.""" + self.logger.warn("Setting values on prior_default will NOT update the remote Canvas instance.") + self._prior_default = value + + @property + def applies_to_self(self): + """Whether the permission applies to the account this role is in. Only present if enabled is true.""" + return self._applies_to_self + + @applies_to_self.setter + def applies_to_self(self, value): + """Setter for applies_to_self property.""" + self.logger.warn("Setting values on applies_to_self will NOT update the remote Canvas instance.") + self._applies_to_self = value + + +class Role(BaseModel): + """Role Model.""" + + def __init__(self, account=None, workflow_state=None, base_role_type=None, role=None, label=None, permissions=None): + """Init method for Role class.""" + self._account = account + self._workflow_state = workflow_state + self._base_role_type = base_role_type + self._role = role + self._label = label + self._permissions = permissions + + self.logger = logging.getLogger('pycanvas.Role') + + @property + def account(self): + """JSON representation of the account the role is in.""" + return self._account + + @account.setter + def account(self, value): + """Setter for account property.""" + self.logger.warn("Setting values on account will NOT update the remote Canvas instance.") + self._account = value + + @property + def workflow_state(self): + """The state of the role: 'active', 'inactive', or 'built_in'.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def base_role_type(self): + """The role type that is being used as a base for this role. For account-level roles, this is 'AccountMembership'. For course-level roles, it is an enrollment type.""" + return self._base_role_type + + @base_role_type.setter + def base_role_type(self, value): + """Setter for base_role_type property.""" + self.logger.warn("Setting values on base_role_type will NOT update the remote Canvas instance.") + self._base_role_type = value + + @property + def role(self): + """The label of the role. (Deprecated alias for 'label').""" + return self._role + + @role.setter + def role(self, value): + """Setter for role property.""" + self.logger.warn("Setting values on role will NOT update the remote Canvas instance.") + self._role = value + + @property + def label(self): + """The label of the role.""" + return self._label + + @label.setter + def label(self, value): + """Setter for label property.""" + self.logger.warn("Setting values on label will NOT update the remote Canvas instance.") + self._label = value + + @property + def permissions(self): + """A dictionary of permissions keyed by name (see permissions input parameter in the 'Create a role' API).""" + return self._permissions + + @permissions.setter + def permissions(self, value): + """Setter for permissions property.""" + self.logger.warn("Setting values on permissions will NOT update the remote Canvas instance.") + self._permissions = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/search.py b/venv/Lib/site-packages/pycanvas/apis/search.py new file mode 100644 index 00000000..656a7660 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/search.py @@ -0,0 +1,178 @@ +"""Search API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + + +class SearchAPI(BaseCanvasAPI): + """Search API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for SearchAPI.""" + super(SearchAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.SearchAPI") + + def find_recipients_conversations(self, context=None, exclude=None, from_conversation_id=None, permissions=None, search=None, type=None, user_id=None): + """ + Find recipients. + + Find valid recipients (users, courses and groups) that the current user + can send messages to. The /api/v1/search/recipients path is the preferred + endpoint, /api/v1/conversations/find_recipients is deprecated. + + Pagination is supported. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - search + """Search terms used for matching users/courses/groups (e.g. "bob smith"). If + multiple terms are given (separated via whitespace), only results matching + all terms will be returned.""" + if search is not None: + params["search"] = search + + # OPTIONAL - context + """Limit the search to a particular course/group (e.g. "course_3" or "group_4").""" + if context is not None: + params["context"] = context + + # OPTIONAL - exclude + """Array of ids to exclude from the search. These may be user ids or + course/group ids prefixed with "course_" or "group_" respectively, + e.g. exclude[]=1&exclude[]=2&exclude[]=course_3""" + if exclude is not None: + params["exclude"] = exclude + + # OPTIONAL - type + """Limit the search just to users or contexts (groups/courses).""" + if type is not None: + self._validate_enum(type, ["user", "context"]) + params["type"] = type + + # OPTIONAL - user_id + """Search for a specific user id. This ignores the other above parameters, + and will never return more than one result.""" + if user_id is not None: + params["user_id"] = user_id + + # OPTIONAL - from_conversation_id + """When searching by user_id, only users that could be normally messaged by + this user will be returned. This parameter allows you to specify a + conversation that will be referenced for a shared context -- if both the + current user and the searched user are in the conversation, the user will + be returned. This is used to start new side conversations.""" + if from_conversation_id is not None: + params["from_conversation_id"] = from_conversation_id + + # OPTIONAL - permissions + """Array of permission strings to be checked for each matched context (e.g. + "send_messages"). This argument determines which permissions may be + returned in the response; it won't prevent contexts from being returned if + they don't grant the permission(s).""" + if permissions is not None: + params["permissions"] = permissions + + self.logger.debug("GET /api/v1/conversations/find_recipients with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/conversations/find_recipients".format(**path), data=data, params=params, no_data=True) + + def find_recipients_search(self, context=None, exclude=None, from_conversation_id=None, permissions=None, search=None, type=None, user_id=None): + """ + Find recipients. + + Find valid recipients (users, courses and groups) that the current user + can send messages to. The /api/v1/search/recipients path is the preferred + endpoint, /api/v1/conversations/find_recipients is deprecated. + + Pagination is supported. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - search + """Search terms used for matching users/courses/groups (e.g. "bob smith"). If + multiple terms are given (separated via whitespace), only results matching + all terms will be returned.""" + if search is not None: + params["search"] = search + + # OPTIONAL - context + """Limit the search to a particular course/group (e.g. "course_3" or "group_4").""" + if context is not None: + params["context"] = context + + # OPTIONAL - exclude + """Array of ids to exclude from the search. These may be user ids or + course/group ids prefixed with "course_" or "group_" respectively, + e.g. exclude[]=1&exclude[]=2&exclude[]=course_3""" + if exclude is not None: + params["exclude"] = exclude + + # OPTIONAL - type + """Limit the search just to users or contexts (groups/courses).""" + if type is not None: + self._validate_enum(type, ["user", "context"]) + params["type"] = type + + # OPTIONAL - user_id + """Search for a specific user id. This ignores the other above parameters, + and will never return more than one result.""" + if user_id is not None: + params["user_id"] = user_id + + # OPTIONAL - from_conversation_id + """When searching by user_id, only users that could be normally messaged by + this user will be returned. This parameter allows you to specify a + conversation that will be referenced for a shared context -- if both the + current user and the searched user are in the conversation, the user will + be returned. This is used to start new side conversations.""" + if from_conversation_id is not None: + params["from_conversation_id"] = from_conversation_id + + # OPTIONAL - permissions + """Array of permission strings to be checked for each matched context (e.g. + "send_messages"). This argument determines which permissions may be + returned in the response; it won't prevent contexts from being returned if + they don't grant the permission(s).""" + if permissions is not None: + params["permissions"] = permissions + + self.logger.debug("GET /api/v1/search/recipients with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/search/recipients".format(**path), data=data, params=params, no_data=True) + + def list_all_courses(self, open_enrollment_only=None, public_only=None, search=None): + """ + List all courses. + + List all courses visible in the public index + """ + path = {} + data = {} + params = {} + + # OPTIONAL - search + """Search terms used for matching users/courses/groups (e.g. "bob smith"). If + multiple terms are given (separated via whitespace), only results matching + all terms will be returned.""" + if search is not None: + params["search"] = search + + # OPTIONAL - public_only + """Only return courses with public content. Defaults to false.""" + if public_only is not None: + params["public_only"] = public_only + + # OPTIONAL - open_enrollment_only + """Only return courses that allow self enrollment. Defaults to false.""" + if open_enrollment_only is not None: + params["open_enrollment_only"] = open_enrollment_only + + self.logger.debug("GET /api/v1/search/all_courses with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/search/all_courses".format(**path), data=data, params=params, no_data=True) + diff --git a/venv/Lib/site-packages/pycanvas/apis/sections.py b/venv/Lib/site-packages/pycanvas/apis/sections.py new file mode 100644 index 00000000..2d210790 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/sections.py @@ -0,0 +1,398 @@ +"""Sections API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class SectionsAPI(BaseCanvasAPI): + """Sections API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for SectionsAPI.""" + super(SectionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.SectionsAPI") + + def list_course_sections(self, course_id, include=None): + """ + List course sections. + + Returns the list of sections for this course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - include + """- "students": Associations to include with the group. Note: this is only + available if you have permission to view users or grades in the course + - "avatar_url": Include the avatar URLs for students returned. + - "enrollments": If 'students' is also included, return the section + enrollment for each student + - "total_students": Returns the total amount of active and invited students + for the course section + - "passback_status": Include the grade passback status.""" + if include is not None: + self._validate_enum(include, ["students", "avatar_url", "enrollments", "total_students", "passback_status"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/sections with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/sections".format(**path), data=data, params=params, all_pages=True) + + def create_course_section(self, course_id, course_section_end_at=None, course_section_name=None, course_section_restrict_enrollments_to_section_dates=None, course_section_sis_section_id=None, course_section_start_at=None, enable_sis_reactivation=None): + """ + Create course section. + + Creates a new section for this course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - course_section[name] + """The name of the section""" + if course_section_name is not None: + data["course_section[name]"] = course_section_name + + # OPTIONAL - course_section[sis_section_id] + """The sis ID of the section""" + if course_section_sis_section_id is not None: + data["course_section[sis_section_id]"] = course_section_sis_section_id + + # OPTIONAL - course_section[start_at] + """Section start date in ISO8601 format, e.g. 2011-01-01T01:00Z""" + if course_section_start_at is not None: + data["course_section[start_at]"] = course_section_start_at + + # OPTIONAL - course_section[end_at] + """Section end date in ISO8601 format. e.g. 2011-01-01T01:00Z""" + if course_section_end_at is not None: + data["course_section[end_at]"] = course_section_end_at + + # OPTIONAL - course_section[restrict_enrollments_to_section_dates] + """Set to true to restrict user enrollments to the start and end dates of the section.""" + if course_section_restrict_enrollments_to_section_dates is not None: + data["course_section[restrict_enrollments_to_section_dates]"] = course_section_restrict_enrollments_to_section_dates + + # OPTIONAL - enable_sis_reactivation + """When true, will first try to re-activate a deleted section with matching sis_section_id if possible.""" + if enable_sis_reactivation is not None: + data["enable_sis_reactivation"] = enable_sis_reactivation + + self.logger.debug("POST /api/v1/courses/{course_id}/sections with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/sections".format(**path), data=data, params=params, single_item=True) + + def cross_list_section(self, id, new_course_id): + """ + Cross-list a Section. + + Move the Section to another course. The new course may be in a different account (department), + but must belong to the same root account (institution). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - new_course_id + """ID""" + path["new_course_id"] = new_course_id + + self.logger.debug("POST /api/v1/sections/{id}/crosslist/{new_course_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/sections/{id}/crosslist/{new_course_id}".format(**path), data=data, params=params, single_item=True) + + def de_cross_list_section(self, id): + """ + De-cross-list a Section. + + Undo cross-listing of a Section, returning it to its original course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/sections/{id}/crosslist with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/sections/{id}/crosslist".format(**path), data=data, params=params, single_item=True) + + def edit_section(self, id, course_section_end_at=None, course_section_name=None, course_section_restrict_enrollments_to_section_dates=None, course_section_sis_section_id=None, course_section_start_at=None): + """ + Edit a section. + + Modify an existing section. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - course_section[name] + """The name of the section""" + if course_section_name is not None: + data["course_section[name]"] = course_section_name + + # OPTIONAL - course_section[sis_section_id] + """The sis ID of the section""" + if course_section_sis_section_id is not None: + data["course_section[sis_section_id]"] = course_section_sis_section_id + + # OPTIONAL - course_section[start_at] + """Section start date in ISO8601 format, e.g. 2011-01-01T01:00Z""" + if course_section_start_at is not None: + data["course_section[start_at]"] = course_section_start_at + + # OPTIONAL - course_section[end_at] + """Section end date in ISO8601 format. e.g. 2011-01-01T01:00Z""" + if course_section_end_at is not None: + data["course_section[end_at]"] = course_section_end_at + + # OPTIONAL - course_section[restrict_enrollments_to_section_dates] + """Set to true to restrict user enrollments to the start and end dates of the section.""" + if course_section_restrict_enrollments_to_section_dates is not None: + data["course_section[restrict_enrollments_to_section_dates]"] = course_section_restrict_enrollments_to_section_dates + + self.logger.debug("PUT /api/v1/sections/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/sections/{id}".format(**path), data=data, params=params, single_item=True) + + def get_section_information_courses(self, id, course_id, include=None): + """ + Get section information. + + Gets details about a specific section + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """- "students": Associations to include with the group. Note: this is only + available if you have permission to view users or grades in the course + - "avatar_url": Include the avatar URLs for students returned. + - "enrollments": If 'students' is also included, return the section + enrollment for each student + - "total_students": Returns the total amount of active and invited students + for the course section + - "passback_status": Include the grade passback status.""" + if include is not None: + self._validate_enum(include, ["students", "avatar_url", "enrollments", "total_students", "passback_status"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/sections/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/sections/{id}".format(**path), data=data, params=params, single_item=True) + + def get_section_information_sections(self, id, include=None): + """ + Get section information. + + Gets details about a specific section + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - include + """- "students": Associations to include with the group. Note: this is only + available if you have permission to view users or grades in the course + - "avatar_url": Include the avatar URLs for students returned. + - "enrollments": If 'students' is also included, return the section + enrollment for each student + - "total_students": Returns the total amount of active and invited students + for the course section + - "passback_status": Include the grade passback status.""" + if include is not None: + self._validate_enum(include, ["students", "avatar_url", "enrollments", "total_students", "passback_status"]) + params["include"] = include + + self.logger.debug("GET /api/v1/sections/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/sections/{id}".format(**path), data=data, params=params, single_item=True) + + def delete_section(self, id): + """ + Delete a section. + + Delete an existing section. Returns the former Section. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/sections/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/sections/{id}".format(**path), data=data, params=params, single_item=True) + + +class Section(BaseModel): + """Section Model.""" + + def __init__(self, integration_id=None, start_at=None, name=None, sis_course_id=None, end_at=None, sis_import_id=None, sis_section_id=None, course_id=None, nonxlist_course_id=None, total_students=None, id=None): + """Init method for Section class.""" + self._integration_id = integration_id + self._start_at = start_at + self._name = name + self._sis_course_id = sis_course_id + self._end_at = end_at + self._sis_import_id = sis_import_id + self._sis_section_id = sis_section_id + self._course_id = course_id + self._nonxlist_course_id = nonxlist_course_id + self._total_students = total_students + self._id = id + + self.logger = logging.getLogger('pycanvas.Section') + + @property + def integration_id(self): + """Optional: The integration ID of the section. This field is only included if the user has permission to view SIS information.""" + return self._integration_id + + @integration_id.setter + def integration_id(self, value): + """Setter for integration_id property.""" + self.logger.warn("Setting values on integration_id will NOT update the remote Canvas instance.") + self._integration_id = value + + @property + def start_at(self): + """the start date for the section, if applicable.""" + return self._start_at + + @start_at.setter + def start_at(self, value): + """Setter for start_at property.""" + self.logger.warn("Setting values on start_at will NOT update the remote Canvas instance.") + self._start_at = value + + @property + def name(self): + """The name of the section.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def sis_course_id(self): + """The unique SIS identifier for the course in which the section belongs. This field is only included if the user has permission to view SIS information.""" + return self._sis_course_id + + @sis_course_id.setter + def sis_course_id(self, value): + """Setter for sis_course_id property.""" + self.logger.warn("Setting values on sis_course_id will NOT update the remote Canvas instance.") + self._sis_course_id = value + + @property + def end_at(self): + """the end date for the section, if applicable.""" + return self._end_at + + @end_at.setter + def end_at(self, value): + """Setter for end_at property.""" + self.logger.warn("Setting values on end_at will NOT update the remote Canvas instance.") + self._end_at = value + + @property + def sis_import_id(self): + """The unique identifier for the SIS import if created through SIS. This field is only included if the user has permission to manage SIS information.""" + return self._sis_import_id + + @sis_import_id.setter + def sis_import_id(self, value): + """Setter for sis_import_id property.""" + self.logger.warn("Setting values on sis_import_id will NOT update the remote Canvas instance.") + self._sis_import_id = value + + @property + def sis_section_id(self): + """The sis id of the section. This field is only included if the user has permission to view SIS information.""" + return self._sis_section_id + + @sis_section_id.setter + def sis_section_id(self, value): + """Setter for sis_section_id property.""" + self.logger.warn("Setting values on sis_section_id will NOT update the remote Canvas instance.") + self._sis_section_id = value + + @property + def course_id(self): + """The unique Canvas identifier for the course in which the section belongs.""" + return self._course_id + + @course_id.setter + def course_id(self, value): + """Setter for course_id property.""" + self.logger.warn("Setting values on course_id will NOT update the remote Canvas instance.") + self._course_id = value + + @property + def nonxlist_course_id(self): + """The unique identifier of the original course of a cross-listed section.""" + return self._nonxlist_course_id + + @nonxlist_course_id.setter + def nonxlist_course_id(self, value): + """Setter for nonxlist_course_id property.""" + self.logger.warn("Setting values on nonxlist_course_id will NOT update the remote Canvas instance.") + self._nonxlist_course_id = value + + @property + def total_students(self): + """optional: the total number of active and invited students in the section.""" + return self._total_students + + @total_students.setter + def total_students(self, value): + """Setter for total_students property.""" + self.logger.warn("Setting values on total_students will NOT update the remote Canvas instance.") + self._total_students = value + + @property + def id(self): + """The unique identifier for the section.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/services.py b/venv/Lib/site-packages/pycanvas/apis/services.py new file mode 100644 index 00000000..d9a75ff6 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/services.py @@ -0,0 +1,45 @@ +"""Services API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + + +class ServicesAPI(BaseCanvasAPI): + """Services API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for ServicesAPI.""" + super(ServicesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.ServicesAPI") + + def get_kaltura_config(self): + """ + Get Kaltura config. + + Return the config information for the Kaltura plugin in json format. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/services/kaltura with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/services/kaltura".format(**path), data=data, params=params, no_data=True) + + def start_kaltura_session(self): + """ + Start Kaltura session. + + Start a new Kaltura session, so that new media can be recorded and uploaded + to this Canvas instance's Kaltura instance. + """ + path = {} + data = {} + params = {} + + self.logger.debug("POST /api/v1/services/kaltura_session with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/services/kaltura_session".format(**path), data=data, params=params, no_data=True) + diff --git a/venv/Lib/site-packages/pycanvas/apis/sis_imports.py b/venv/Lib/site-packages/pycanvas/apis/sis_imports.py new file mode 100644 index 00000000..38dbefab --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/sis_imports.py @@ -0,0 +1,670 @@ +"""SisImports API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel +import os + + +class SisImportsAPI(BaseCanvasAPI): + """SisImports API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for SisImportsAPI.""" + super(SisImportsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.SisImportsAPI") + + def get_sis_import_list(self, account_id, created_since=None): + """ + Get SIS import list. + + Returns the list of SIS imports for an account + + Example: + curl 'https:///api/v1/accounts//sis_imports' \ + -H "Authorization: Bearer " + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - created_since + """If set, only shows imports created after the specified date (use ISO8601 format)""" + if created_since is not None: + if issubclass(created_since.__class__, basestring): + created_since = self._validate_iso8601_string(created_since) + elif issubclass(created_since.__class__, date) or issubclass(created_since.__class__, datetime): + created_since = created_since.strftime('%Y-%m-%dT%H:%M:%SZ') + params["created_since"] = created_since + + self.logger.debug("GET /api/v1/accounts/{account_id}/sis_imports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/sis_imports".format(**path), data=data, params=params, data_key='sis_imports', all_pages=True) + + def import_sis_data(self, account_id, add_sis_stickiness=None, attachment=None, batch_mode=None, batch_mode_term_id=None, clear_sis_stickiness=None, diffing_data_set_identifier=None, diffing_remaster_data_set=None, extension=None, import_type=None, override_sis_stickiness=None): + """ + Import SIS data. + + Import SIS data into Canvas. Must be on a root account with SIS imports + enabled. + + For more information on the format that's expected here, please see the + "SIS CSV" section in the API docs. + """ + path = {} + data = {} + params = {} + files = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - import_type + """Choose the data format for reading SIS data. With a standard Canvas + install, this option can only be 'instructure_csv', and if unprovided, + will be assumed to be so. Can be part of the query string.""" + if import_type is not None: + data["import_type"] = import_type + + # OPTIONAL - attachment + """There are two ways to post SIS import data - either via a + multipart/form-data form-field-style attachment, or via a non-multipart + raw post request. + + 'attachment' is required for multipart/form-data style posts. Assumed to + be SIS data from a file upload form field named 'attachment'. + + Examples: + curl -F attachment=@ -H "Authorization: Bearer " \ + 'https:///api/v1/accounts//sis_imports.json?import_type=instructure_csv' + + If you decide to do a raw post, you can skip the 'attachment' argument, + but you will then be required to provide a suitable Content-Type header. + You are encouraged to also provide the 'extension' argument. + + Examples: + curl -H 'Content-Type: application/octet-stream' --data-binary @.zip \ + -H "Authorization: Bearer " \ + 'https:///api/v1/accounts//sis_imports.json?import_type=instructure_csv&extension=zip' + + curl -H 'Content-Type: application/zip' --data-binary @.zip \ + -H "Authorization: Bearer " \ + 'https:///api/v1/accounts//sis_imports.json?import_type=instructure_csv' + + curl -H 'Content-Type: text/csv' --data-binary @.csv \ + -H "Authorization: Bearer " \ + 'https:///api/v1/accounts//sis_imports.json?import_type=instructure_csv' + + curl -H 'Content-Type: text/csv' --data-binary @.csv \ + -H "Authorization: Bearer " \ + 'https:///api/v1/accounts//sis_imports.json?import_type=instructure_csv&batch_mode=1&batch_mode_term_id=15'""" + if attachment is not None: + if type(attachment) is file: + files['attachment'] = (os.path.basename(attachment.name), attachment) + elif os.path.exists(attachment): + files['attachment'] = (os.path.basename(attachment), open(attachment, 'rb')) + else: + raise ValueError('The attachment must be an open file or a path to a readable file.') + + # OPTIONAL - extension + """Recommended for raw post request style imports. This field will be used to + distinguish between zip, xml, csv, and other file format extensions that + would usually be provided with the filename in the multipart post request + scenario. If not provided, this value will be inferred from the + Content-Type, falling back to zip-file format if all else fails.""" + if extension is not None: + data["extension"] = extension + + # OPTIONAL - batch_mode + """If set, this SIS import will be run in batch mode, deleting any data + previously imported via SIS that is not present in this latest import. + See the SIS CSV Format page for details.""" + if batch_mode is not None: + data["batch_mode"] = batch_mode + + # OPTIONAL - batch_mode_term_id + """Limit deletions to only this term. Required if batch mode is enabled.""" + if batch_mode_term_id is not None: + data["batch_mode_term_id"] = batch_mode_term_id + + # OPTIONAL - override_sis_stickiness + """Many fields on records in Canvas can be marked "sticky," which means that + when something changes in the UI apart from the SIS, that field gets + "stuck." In this way, by default, SIS imports do not override UI changes. + If this field is present, however, it will tell the SIS import to ignore + "stickiness" and override all fields.""" + if override_sis_stickiness is not None: + data["override_sis_stickiness"] = override_sis_stickiness + + # OPTIONAL - add_sis_stickiness + """This option, if present, will process all changes as if they were UI + changes. This means that "stickiness" will be added to changed fields. + This option is only processed if 'override_sis_stickiness' is also provided.""" + if add_sis_stickiness is not None: + data["add_sis_stickiness"] = add_sis_stickiness + + # OPTIONAL - clear_sis_stickiness + """This option, if present, will clear "stickiness" from all fields touched + by this import. Requires that 'override_sis_stickiness' is also provided. + If 'add_sis_stickiness' is also provided, 'clear_sis_stickiness' will + overrule the behavior of 'add_sis_stickiness'""" + if clear_sis_stickiness is not None: + data["clear_sis_stickiness"] = clear_sis_stickiness + + # OPTIONAL - diffing_data_set_identifier + """If set on a CSV import, Canvas will attempt to optimize the SIS import by + comparing this set of CSVs to the previous set that has the same data set + identifier, and only appliying the difference between the two. See the + SIS CSV Format documentation for more details.""" + if diffing_data_set_identifier is not None: + data["diffing_data_set_identifier"] = diffing_data_set_identifier + + # OPTIONAL - diffing_remaster_data_set + """If true, and diffing_data_set_identifier is sent, this SIS import will be + part of the data set, but diffing will not be performed. See the SIS CSV + Format documentation for details.""" + if diffing_remaster_data_set is not None: + data["diffing_remaster_data_set"] = diffing_remaster_data_set + + self.logger.debug("POST /api/v1/accounts/{account_id}/sis_imports with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/sis_imports".format(**path), data=data, params=params, files=files, single_item=True) + + def get_sis_import_status(self, id, account_id): + """ + Get SIS import status. + + Get the status of an already created SIS import. + + Examples: + curl 'https:///api/v1/accounts//sis_imports/' \ + -H "Authorization: Bearer " + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/accounts/{account_id}/sis_imports/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/sis_imports/{id}".format(**path), data=data, params=params, single_item=True) + + def abort_sis_import(self, id, account_id): + """ + Abort SIS import. + + Abort an already created but not processed or processing SIS import. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/accounts/{account_id}/sis_imports/{id}/abort with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/sis_imports/{id}/abort".format(**path), data=data, params=params, single_item=True) + + def abort_all_pending_sis_imports(self, account_id): + """ + Abort all pending SIS imports. + + Abort already created but not processed or processing SIS imports. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + self.logger.debug("PUT /api/v1/accounts/{account_id}/sis_imports/abort_all_pending with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/accounts/{account_id}/sis_imports/abort_all_pending".format(**path), data=data, params=params) + + +class Sisimport(BaseModel): + """Sisimport Model.""" + + def __init__(self, ended_at=None, diffed_against_import_id=None, workflow_state=None, batch_mode=None, created_at=None, batch_mode_term_id=None, clear_sis_stickiness=None, updated_at=None, override_sis_stickiness=None, processing_errors=None, add_sis_stickiness=None, diffing_data_set_identifier=None, processing_warnings=None, progress=None, data=None, id=None): + """Init method for Sisimport class.""" + self._ended_at = ended_at + self._diffed_against_import_id = diffed_against_import_id + self._workflow_state = workflow_state + self._batch_mode = batch_mode + self._created_at = created_at + self._batch_mode_term_id = batch_mode_term_id + self._clear_sis_stickiness = clear_sis_stickiness + self._updated_at = updated_at + self._override_sis_stickiness = override_sis_stickiness + self._processing_errors = processing_errors + self._add_sis_stickiness = add_sis_stickiness + self._diffing_data_set_identifier = diffing_data_set_identifier + self._processing_warnings = processing_warnings + self._progress = progress + self._data = data + self._id = id + + self.logger = logging.getLogger('pycanvas.Sisimport') + + @property + def ended_at(self): + """The date the SIS import finished. Returns null if not finished.""" + return self._ended_at + + @ended_at.setter + def ended_at(self, value): + """Setter for ended_at property.""" + self.logger.warn("Setting values on ended_at will NOT update the remote Canvas instance.") + self._ended_at = value + + @property + def diffed_against_import_id(self): + """The ID of the SIS Import that this import was diffed against.""" + return self._diffed_against_import_id + + @diffed_against_import_id.setter + def diffed_against_import_id(self, value): + """Setter for diffed_against_import_id property.""" + self.logger.warn("Setting values on diffed_against_import_id will NOT update the remote Canvas instance.") + self._diffed_against_import_id = value + + @property + def workflow_state(self): + """The current state of the SIS import. - 'created': The SIS import has been created. + - 'importing': The SIS import is currently processing. + - 'cleanup_batch': The SIS import is currently cleaning up courses, sections, and enrollments not included in the batch for batch_mode imports. + - 'imported': The SIS import has completed successfully. + - 'imported_with_messages': The SIS import completed with errors or warnings. + - 'failed_with_messages': The SIS import failed with errors. + - 'failed': The SIS import failed.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def batch_mode(self): + """Whether the import was run in batch mode.""" + return self._batch_mode + + @batch_mode.setter + def batch_mode(self, value): + """Setter for batch_mode property.""" + self.logger.warn("Setting values on batch_mode will NOT update the remote Canvas instance.") + self._batch_mode = value + + @property + def created_at(self): + """The date the SIS import was created.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def batch_mode_term_id(self): + """The term the batch was limited to.""" + return self._batch_mode_term_id + + @batch_mode_term_id.setter + def batch_mode_term_id(self, value): + """Setter for batch_mode_term_id property.""" + self.logger.warn("Setting values on batch_mode_term_id will NOT update the remote Canvas instance.") + self._batch_mode_term_id = value + + @property + def clear_sis_stickiness(self): + """Whether stickiness was cleared.""" + return self._clear_sis_stickiness + + @clear_sis_stickiness.setter + def clear_sis_stickiness(self, value): + """Setter for clear_sis_stickiness property.""" + self.logger.warn("Setting values on clear_sis_stickiness will NOT update the remote Canvas instance.") + self._clear_sis_stickiness = value + + @property + def updated_at(self): + """The date the SIS import was last updated.""" + return self._updated_at + + @updated_at.setter + def updated_at(self, value): + """Setter for updated_at property.""" + self.logger.warn("Setting values on updated_at will NOT update the remote Canvas instance.") + self._updated_at = value + + @property + def override_sis_stickiness(self): + """Whether UI changes were overridden.""" + return self._override_sis_stickiness + + @override_sis_stickiness.setter + def override_sis_stickiness(self, value): + """Setter for override_sis_stickiness property.""" + self.logger.warn("Setting values on override_sis_stickiness will NOT update the remote Canvas instance.") + self._override_sis_stickiness = value + + @property + def processing_errors(self): + """An array of CSV_file/error_message pairs.""" + return self._processing_errors + + @processing_errors.setter + def processing_errors(self, value): + """Setter for processing_errors property.""" + self.logger.warn("Setting values on processing_errors will NOT update the remote Canvas instance.") + self._processing_errors = value + + @property + def add_sis_stickiness(self): + """Whether stickiness was added to the batch changes.""" + return self._add_sis_stickiness + + @add_sis_stickiness.setter + def add_sis_stickiness(self, value): + """Setter for add_sis_stickiness property.""" + self.logger.warn("Setting values on add_sis_stickiness will NOT update the remote Canvas instance.") + self._add_sis_stickiness = value + + @property + def diffing_data_set_identifier(self): + """The identifier of the data set that this SIS batch diffs against.""" + return self._diffing_data_set_identifier + + @diffing_data_set_identifier.setter + def diffing_data_set_identifier(self, value): + """Setter for diffing_data_set_identifier property.""" + self.logger.warn("Setting values on diffing_data_set_identifier will NOT update the remote Canvas instance.") + self._diffing_data_set_identifier = value + + @property + def processing_warnings(self): + """Only imports that are complete will get this data. An array of CSV_file/warning_message pairs.""" + return self._processing_warnings + + @processing_warnings.setter + def processing_warnings(self, value): + """Setter for processing_warnings property.""" + self.logger.warn("Setting values on processing_warnings will NOT update the remote Canvas instance.") + self._processing_warnings = value + + @property + def progress(self): + """The progress of the SIS import. The progress will reset when using batch_mode and have a different progress for the cleanup stage.""" + return self._progress + + @progress.setter + def progress(self, value): + """Setter for progress property.""" + self.logger.warn("Setting values on progress will NOT update the remote Canvas instance.") + self._progress = value + + @property + def data(self): + """data.""" + return self._data + + @data.setter + def data(self, value): + """Setter for data property.""" + self.logger.warn("Setting values on data will NOT update the remote Canvas instance.") + self._data = value + + @property + def id(self): + """The unique identifier for the SIS import.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Sisimportcounts(BaseModel): + """Sisimportcounts Model.""" + + def __init__(self, terms=None, users=None, batch_enrollments_deleted=None, grade_publishing_results=None, abstract_courses=None, group_memberships=None, courses=None, batch_sections_deleted=None, accounts=None, xlists=None, groups=None, enrollments=None, batch_courses_deleted=None, sections=None): + """Init method for Sisimportcounts class.""" + self._terms = terms + self._users = users + self._batch_enrollments_deleted = batch_enrollments_deleted + self._grade_publishing_results = grade_publishing_results + self._abstract_courses = abstract_courses + self._group_memberships = group_memberships + self._courses = courses + self._batch_sections_deleted = batch_sections_deleted + self._accounts = accounts + self._xlists = xlists + self._groups = groups + self._enrollments = enrollments + self._batch_courses_deleted = batch_courses_deleted + self._sections = sections + + self.logger = logging.getLogger('pycanvas.Sisimportcounts') + + @property + def terms(self): + """terms.""" + return self._terms + + @terms.setter + def terms(self, value): + """Setter for terms property.""" + self.logger.warn("Setting values on terms will NOT update the remote Canvas instance.") + self._terms = value + + @property + def users(self): + """users.""" + return self._users + + @users.setter + def users(self, value): + """Setter for users property.""" + self.logger.warn("Setting values on users will NOT update the remote Canvas instance.") + self._users = value + + @property + def batch_enrollments_deleted(self): + """the number of enrollments that were removed because they were not included in the batch for batch_mode imports. Only included if enrollments were deleted.""" + return self._batch_enrollments_deleted + + @batch_enrollments_deleted.setter + def batch_enrollments_deleted(self, value): + """Setter for batch_enrollments_deleted property.""" + self.logger.warn("Setting values on batch_enrollments_deleted will NOT update the remote Canvas instance.") + self._batch_enrollments_deleted = value + + @property + def grade_publishing_results(self): + """grade_publishing_results.""" + return self._grade_publishing_results + + @grade_publishing_results.setter + def grade_publishing_results(self, value): + """Setter for grade_publishing_results property.""" + self.logger.warn("Setting values on grade_publishing_results will NOT update the remote Canvas instance.") + self._grade_publishing_results = value + + @property + def abstract_courses(self): + """abstract_courses.""" + return self._abstract_courses + + @abstract_courses.setter + def abstract_courses(self, value): + """Setter for abstract_courses property.""" + self.logger.warn("Setting values on abstract_courses will NOT update the remote Canvas instance.") + self._abstract_courses = value + + @property + def group_memberships(self): + """group_memberships.""" + return self._group_memberships + + @group_memberships.setter + def group_memberships(self, value): + """Setter for group_memberships property.""" + self.logger.warn("Setting values on group_memberships will NOT update the remote Canvas instance.") + self._group_memberships = value + + @property + def courses(self): + """courses.""" + return self._courses + + @courses.setter + def courses(self, value): + """Setter for courses property.""" + self.logger.warn("Setting values on courses will NOT update the remote Canvas instance.") + self._courses = value + + @property + def batch_sections_deleted(self): + """the number of sections that were removed because they were not included in the batch for batch_mode imports. Only included if sections were deleted.""" + return self._batch_sections_deleted + + @batch_sections_deleted.setter + def batch_sections_deleted(self, value): + """Setter for batch_sections_deleted property.""" + self.logger.warn("Setting values on batch_sections_deleted will NOT update the remote Canvas instance.") + self._batch_sections_deleted = value + + @property + def accounts(self): + """accounts.""" + return self._accounts + + @accounts.setter + def accounts(self, value): + """Setter for accounts property.""" + self.logger.warn("Setting values on accounts will NOT update the remote Canvas instance.") + self._accounts = value + + @property + def xlists(self): + """xlists.""" + return self._xlists + + @xlists.setter + def xlists(self, value): + """Setter for xlists property.""" + self.logger.warn("Setting values on xlists will NOT update the remote Canvas instance.") + self._xlists = value + + @property + def groups(self): + """groups.""" + return self._groups + + @groups.setter + def groups(self, value): + """Setter for groups property.""" + self.logger.warn("Setting values on groups will NOT update the remote Canvas instance.") + self._groups = value + + @property + def enrollments(self): + """enrollments.""" + return self._enrollments + + @enrollments.setter + def enrollments(self, value): + """Setter for enrollments property.""" + self.logger.warn("Setting values on enrollments will NOT update the remote Canvas instance.") + self._enrollments = value + + @property + def batch_courses_deleted(self): + """the number of courses that were removed because they were not included in the batch for batch_mode imports. Only included if courses were deleted.""" + return self._batch_courses_deleted + + @batch_courses_deleted.setter + def batch_courses_deleted(self, value): + """Setter for batch_courses_deleted property.""" + self.logger.warn("Setting values on batch_courses_deleted will NOT update the remote Canvas instance.") + self._batch_courses_deleted = value + + @property + def sections(self): + """sections.""" + return self._sections + + @sections.setter + def sections(self, value): + """Setter for sections property.""" + self.logger.warn("Setting values on sections will NOT update the remote Canvas instance.") + self._sections = value + + +class Sisimportdata(BaseModel): + """Sisimportdata Model.""" + + def __init__(self, import_type=None, counts=None, supplied_batches=None): + """Init method for Sisimportdata class.""" + self._import_type = import_type + self._counts = counts + self._supplied_batches = supplied_batches + + self.logger = logging.getLogger('pycanvas.Sisimportdata') + + @property + def import_type(self): + """The type of SIS import.""" + return self._import_type + + @import_type.setter + def import_type(self, value): + """Setter for import_type property.""" + self.logger.warn("Setting values on import_type will NOT update the remote Canvas instance.") + self._import_type = value + + @property + def counts(self): + """The number of rows processed for each type of import.""" + return self._counts + + @counts.setter + def counts(self, value): + """Setter for counts property.""" + self.logger.warn("Setting values on counts will NOT update the remote Canvas instance.") + self._counts = value + + @property + def supplied_batches(self): + """Which files were included in the SIS import.""" + return self._supplied_batches + + @supplied_batches.setter + def supplied_batches(self, value): + """Setter for supplied_batches property.""" + self.logger.warn("Setting values on supplied_batches will NOT update the remote Canvas instance.") + self._supplied_batches = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/submission_comments.py b/venv/Lib/site-packages/pycanvas/apis/submission_comments.py new file mode 100644 index 00000000..9073a13d --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/submission_comments.py @@ -0,0 +1,49 @@ +"""SubmissionComments API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + + +class SubmissionCommentsAPI(BaseCanvasAPI): + """SubmissionComments API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for SubmissionCommentsAPI.""" + super(SubmissionCommentsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.SubmissionCommentsAPI") + + def upload_file(self, user_id, course_id, assignment_id): + """ + Upload a file. + + Upload a file to attach to a submission comment + + See the {file:file_uploads.html File Upload Documentation} for details on the file upload workflow. + + The final step of the file upload workflow will return the attachment data, + including the new file id. The caller can then PUT the file_id to the + submission API to attach it to a comment + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("POST /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}/comments/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}/comments/files".format(**path), data=data, params=params, no_data=True) + diff --git a/venv/Lib/site-packages/pycanvas/apis/submissions.py b/venv/Lib/site-packages/pycanvas/apis/submissions.py new file mode 100644 index 00000000..6df066c8 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/submissions.py @@ -0,0 +1,1624 @@ +"""Submissions API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class SubmissionsAPI(BaseCanvasAPI): + """Submissions API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for SubmissionsAPI.""" + super(SubmissionsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.SubmissionsAPI") + + def submit_assignment_courses(self, course_id, assignment_id, submission_submission_type, comment_text_comment=None, submission_body=None, submission_file_ids=None, submission_media_comment_id=None, submission_media_comment_type=None, submission_url=None): + """ + Submit an assignment. + + Make a submission for an assignment. You must be enrolled as a student in + the course/section to do this. + + All online turn-in submission types are supported in this API. However, + there are a few things that are not yet supported: + + * Files can be submitted based on a file ID of a user or group file. However, there is no API yet for listing the user and group files, or uploading new files via the API. A file upload API is coming soon. + * Media comments can be submitted, however, there is no API yet for creating a media comment to submit. + * Integration with Google Docs is not yet supported. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # OPTIONAL - comment[text_comment] + """Include a textual comment with the submission.""" + if comment_text_comment is not None: + data["comment[text_comment]"] = comment_text_comment + + # REQUIRED - submission[submission_type] + """The type of submission being made. The assignment submission_types must + include this submission type as an allowed option, or the submission will be rejected with a 400 error. + + The submission_type given determines which of the following parameters is + used. For instance, to submit a URL, submission [submission_type] must be + set to "online_url", otherwise the submission [url] parameter will be + ignored.""" + self._validate_enum(submission_submission_type, ["online_text_entry", "online_url", "online_upload", "media_recording", "basic_lti_launch"]) + data["submission[submission_type]"] = submission_submission_type + + # OPTIONAL - submission[body] + """Submit the assignment as an HTML document snippet. Note this HTML snippet + will be sanitized using the same ruleset as a submission made from the + Canvas web UI. The sanitized HTML will be returned in the response as the + submission body. Requires a submission_type of "online_text_entry".""" + if submission_body is not None: + data["submission[body]"] = submission_body + + # OPTIONAL - submission[url] + """Submit the assignment as a URL. The URL scheme must be "http" or "https", + no "ftp" or other URL schemes are allowed. If no scheme is given (e.g. + "www.example.com") then "http" will be assumed. Requires a submission_type + of "online_url" or "basic_lti_launch".""" + if submission_url is not None: + data["submission[url]"] = submission_url + + # OPTIONAL - submission[file_ids] + """Submit the assignment as a set of one or more previously uploaded files + residing in the submitting user's files section (or the group's files + section, for group assignments). + + To upload a new file to submit, see the submissions {api:SubmissionsApiController#create_file Upload a file API}. + + Requires a submission_type of "online_upload".""" + if submission_file_ids is not None: + data["submission[file_ids]"] = submission_file_ids + + # OPTIONAL - submission[media_comment_id] + """The media comment id to submit. Media comment ids can be submitted via + this API, however, note that there is not yet an API to generate or list + existing media comments, so this functionality is currently of limited use. + + Requires a submission_type of "media_recording".""" + if submission_media_comment_id is not None: + data["submission[media_comment_id]"] = submission_media_comment_id + + # OPTIONAL - submission[media_comment_type] + """The type of media comment being submitted.""" + if submission_media_comment_type is not None: + self._validate_enum(submission_media_comment_type, ["audio", "video"]) + data["submission[media_comment_type]"] = submission_media_comment_type + + self.logger.debug("POST /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions".format(**path), data=data, params=params, no_data=True) + + def submit_assignment_sections(self, section_id, assignment_id, submission_submission_type, comment_text_comment=None, submission_body=None, submission_file_ids=None, submission_media_comment_id=None, submission_media_comment_type=None, submission_url=None): + """ + Submit an assignment. + + Make a submission for an assignment. You must be enrolled as a student in + the course/section to do this. + + All online turn-in submission types are supported in this API. However, + there are a few things that are not yet supported: + + * Files can be submitted based on a file ID of a user or group file. However, there is no API yet for listing the user and group files, or uploading new files via the API. A file upload API is coming soon. + * Media comments can be submitted, however, there is no API yet for creating a media comment to submit. + * Integration with Google Docs is not yet supported. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # OPTIONAL - comment[text_comment] + """Include a textual comment with the submission.""" + if comment_text_comment is not None: + data["comment[text_comment]"] = comment_text_comment + + # REQUIRED - submission[submission_type] + """The type of submission being made. The assignment submission_types must + include this submission type as an allowed option, or the submission will be rejected with a 400 error. + + The submission_type given determines which of the following parameters is + used. For instance, to submit a URL, submission [submission_type] must be + set to "online_url", otherwise the submission [url] parameter will be + ignored.""" + self._validate_enum(submission_submission_type, ["online_text_entry", "online_url", "online_upload", "media_recording", "basic_lti_launch"]) + data["submission[submission_type]"] = submission_submission_type + + # OPTIONAL - submission[body] + """Submit the assignment as an HTML document snippet. Note this HTML snippet + will be sanitized using the same ruleset as a submission made from the + Canvas web UI. The sanitized HTML will be returned in the response as the + submission body. Requires a submission_type of "online_text_entry".""" + if submission_body is not None: + data["submission[body]"] = submission_body + + # OPTIONAL - submission[url] + """Submit the assignment as a URL. The URL scheme must be "http" or "https", + no "ftp" or other URL schemes are allowed. If no scheme is given (e.g. + "www.example.com") then "http" will be assumed. Requires a submission_type + of "online_url" or "basic_lti_launch".""" + if submission_url is not None: + data["submission[url]"] = submission_url + + # OPTIONAL - submission[file_ids] + """Submit the assignment as a set of one or more previously uploaded files + residing in the submitting user's files section (or the group's files + section, for group assignments). + + To upload a new file to submit, see the submissions {api:SubmissionsApiController#create_file Upload a file API}. + + Requires a submission_type of "online_upload".""" + if submission_file_ids is not None: + data["submission[file_ids]"] = submission_file_ids + + # OPTIONAL - submission[media_comment_id] + """The media comment id to submit. Media comment ids can be submitted via + this API, however, note that there is not yet an API to generate or list + existing media comments, so this functionality is currently of limited use. + + Requires a submission_type of "media_recording".""" + if submission_media_comment_id is not None: + data["submission[media_comment_id]"] = submission_media_comment_id + + # OPTIONAL - submission[media_comment_type] + """The type of media comment being submitted.""" + if submission_media_comment_type is not None: + self._validate_enum(submission_media_comment_type, ["audio", "video"]) + data["submission[media_comment_type]"] = submission_media_comment_type + + self.logger.debug("POST /api/v1/sections/{section_id}/assignments/{assignment_id}/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/sections/{section_id}/assignments/{assignment_id}/submissions".format(**path), data=data, params=params, no_data=True) + + def list_assignment_submissions_courses(self, course_id, assignment_id, grouped=None, include=None): + """ + List assignment submissions. + + Get all existing submissions for an assignment. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # OPTIONAL - include + """Associations to include with the group. "group" will add group_id and group_name.""" + if include is not None: + self._validate_enum(include, ["submission_history", "submission_comments", "rubric_assessment", "assignment", "visibility", "course", "user", "group"]) + params["include"] = include + + # OPTIONAL - grouped + """If this argument is true, the response will be grouped by student groups.""" + if grouped is not None: + params["grouped"] = grouped + + self.logger.debug("GET /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions".format(**path), data=data, params=params, all_pages=True) + + def list_assignment_submissions_sections(self, section_id, assignment_id, grouped=None, include=None): + """ + List assignment submissions. + + Get all existing submissions for an assignment. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # OPTIONAL - include + """Associations to include with the group. "group" will add group_id and group_name.""" + if include is not None: + self._validate_enum(include, ["submission_history", "submission_comments", "rubric_assessment", "assignment", "visibility", "course", "user", "group"]) + params["include"] = include + + # OPTIONAL - grouped + """If this argument is true, the response will be grouped by student groups.""" + if grouped is not None: + params["grouped"] = grouped + + self.logger.debug("GET /api/v1/sections/{section_id}/assignments/{assignment_id}/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/sections/{section_id}/assignments/{assignment_id}/submissions".format(**path), data=data, params=params, all_pages=True) + + def list_submissions_for_multiple_assignments_courses(self, course_id, assignment_ids=None, grading_period_id=None, grouped=None, include=None, order=None, order_direction=None, student_ids=None): + """ + List submissions for multiple assignments. + + Get all existing submissions for a given set of students and assignments. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - student_ids + """List of student ids to return submissions for. If this argument is + omitted, return submissions for the calling user. Students may only list + their own submissions. Observers may only list those of associated + students. The special id "all" will return submissions for all students + in the course/section as appropriate.""" + if student_ids is not None: + params["student_ids"] = student_ids + + # OPTIONAL - assignment_ids + """List of assignments to return submissions for. If none are given, + submissions for all assignments are returned.""" + if assignment_ids is not None: + params["assignment_ids"] = assignment_ids + + # OPTIONAL - grouped + """If this argument is present, the response will be grouped by student, + rather than a flat array of submissions.""" + if grouped is not None: + params["grouped"] = grouped + + # OPTIONAL - grading_period_id + """The id of the grading period in which submissions are being requested + (Requires the Multiple Grading Periods account feature turned on)""" + if grading_period_id is not None: + params["grading_period_id"] = grading_period_id + + # OPTIONAL - order + """The order submissions will be returned in. Defaults to "id". Doesn't + affect results for "grouped" mode.""" + if order is not None: + self._validate_enum(order, ["id", "graded_at"]) + params["order"] = order + + # OPTIONAL - order_direction + """Determines whether ordered results are retured in ascending or descending + order. Defaults to "ascending". Doesn't affect results for "grouped" mode.""" + if order_direction is not None: + self._validate_enum(order_direction, ["ascending", "descending"]) + params["order_direction"] = order_direction + + # OPTIONAL - include + """Associations to include with the group. `total_scores` requires the + `grouped` argument.""" + if include is not None: + self._validate_enum(include, ["submission_history", "submission_comments", "rubric_assessment", "assignment", "total_scores", "visibility", "course", "user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/students/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/students/submissions".format(**path), data=data, params=params, no_data=True) + + def list_submissions_for_multiple_assignments_sections(self, section_id, assignment_ids=None, grading_period_id=None, grouped=None, include=None, order=None, order_direction=None, student_ids=None): + """ + List submissions for multiple assignments. + + Get all existing submissions for a given set of students and assignments. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # OPTIONAL - student_ids + """List of student ids to return submissions for. If this argument is + omitted, return submissions for the calling user. Students may only list + their own submissions. Observers may only list those of associated + students. The special id "all" will return submissions for all students + in the course/section as appropriate.""" + if student_ids is not None: + params["student_ids"] = student_ids + + # OPTIONAL - assignment_ids + """List of assignments to return submissions for. If none are given, + submissions for all assignments are returned.""" + if assignment_ids is not None: + params["assignment_ids"] = assignment_ids + + # OPTIONAL - grouped + """If this argument is present, the response will be grouped by student, + rather than a flat array of submissions.""" + if grouped is not None: + params["grouped"] = grouped + + # OPTIONAL - grading_period_id + """The id of the grading period in which submissions are being requested + (Requires the Multiple Grading Periods account feature turned on)""" + if grading_period_id is not None: + params["grading_period_id"] = grading_period_id + + # OPTIONAL - order + """The order submissions will be returned in. Defaults to "id". Doesn't + affect results for "grouped" mode.""" + if order is not None: + self._validate_enum(order, ["id", "graded_at"]) + params["order"] = order + + # OPTIONAL - order_direction + """Determines whether ordered results are retured in ascending or descending + order. Defaults to "ascending". Doesn't affect results for "grouped" mode.""" + if order_direction is not None: + self._validate_enum(order_direction, ["ascending", "descending"]) + params["order_direction"] = order_direction + + # OPTIONAL - include + """Associations to include with the group. `total_scores` requires the + `grouped` argument.""" + if include is not None: + self._validate_enum(include, ["submission_history", "submission_comments", "rubric_assessment", "assignment", "total_scores", "visibility", "course", "user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/sections/{section_id}/students/submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/sections/{section_id}/students/submissions".format(**path), data=data, params=params, no_data=True) + + def get_single_submission_courses(self, user_id, course_id, assignment_id, include=None): + """ + Get a single submission. + + Get a single submission, based on user id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - include + """Associations to include with the group.""" + if include is not None: + self._validate_enum(include, ["submission_history", "submission_comments", "rubric_assessment", "visibility", "course", "user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}".format(**path), data=data, params=params, no_data=True) + + def get_single_submission_sections(self, user_id, section_id, assignment_id, include=None): + """ + Get a single submission. + + Get a single submission, based on user id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - include + """Associations to include with the group.""" + if include is not None: + self._validate_enum(include, ["submission_history", "submission_comments", "rubric_assessment", "visibility", "course", "user"]) + params["include"] = include + + self.logger.debug("GET /api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id}".format(**path), data=data, params=params, no_data=True) + + def upload_file_courses(self, user_id, course_id, assignment_id): + """ + Upload a file. + + Upload a file to a submission. + + This API endpoint is the first step in uploading a file to a submission as a student. + See the {file:file_uploads.html File Upload Documentation} for details on the file upload workflow. + + The final step of the file upload workflow will return the attachment data, + including the new file id. The caller can then POST to submit the + +online_upload+ assignment with these file ids. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("POST /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}/files".format(**path), data=data, params=params, no_data=True) + + def upload_file_sections(self, user_id, section_id, assignment_id): + """ + Upload a file. + + Upload a file to a submission. + + This API endpoint is the first step in uploading a file to a submission as a student. + See the {file:file_uploads.html File Upload Documentation} for details on the file upload workflow. + + The final step of the file upload workflow will return the attachment data, + including the new file id. The caller can then POST to submit the + +online_upload+ assignment with these file ids. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("POST /api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id}/files".format(**path), data=data, params=params, no_data=True) + + def grade_or_comment_on_submission_courses(self, user_id, course_id, assignment_id, comment_file_ids=None, comment_group_comment=None, comment_media_comment_id=None, comment_media_comment_type=None, comment_text_comment=None, include_visibility=None, rubric_assessment=None, submission_excuse=None, submission_posted_grade=None): + """ + Grade or comment on a submission. + + Comment on and/or update the grading for a student's assignment submission. + If any submission or rubric_assessment arguments are provided, the user + must have permission to manage grades in the appropriate context (course or + section). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - comment[text_comment] + """Add a textual comment to the submission.""" + if comment_text_comment is not None: + data["comment[text_comment]"] = comment_text_comment + + # OPTIONAL - comment[group_comment] + """Whether or not this comment should be sent to the entire group (defaults + to false). Ignored if this is not a group assignment or if no text_comment + is provided.""" + if comment_group_comment is not None: + data["comment[group_comment]"] = comment_group_comment + + # OPTIONAL - comment[media_comment_id] + """Add an audio/video comment to the submission. Media comments can be added + via this API, however, note that there is not yet an API to generate or + list existing media comments, so this functionality is currently of + limited use.""" + if comment_media_comment_id is not None: + data["comment[media_comment_id]"] = comment_media_comment_id + + # OPTIONAL - comment[media_comment_type] + """The type of media comment being added.""" + if comment_media_comment_type is not None: + self._validate_enum(comment_media_comment_type, ["audio", "video"]) + data["comment[media_comment_type]"] = comment_media_comment_type + + # OPTIONAL - comment[file_ids] + """Attach files to this comment that were previously uploaded using the + Submission Comment API's files action""" + if comment_file_ids is not None: + data["comment[file_ids]"] = comment_file_ids + + # OPTIONAL - include[visibility] + """Whether this assignment is visible to the owner of the submission""" + if include_visibility is not None: + data["include[visibility]"] = include_visibility + + # OPTIONAL - submission[posted_grade] + """Assign a score to the submission, updating both the "score" and "grade" + fields on the submission record. This parameter can be passed in a few + different formats: + + points:: A floating point or integral value, such as "13.5". The grade + will be interpreted directly as the score of the assignment. + Values above assignment.points_possible are allowed, for awarding + extra credit. + percentage:: A floating point value appended with a percent sign, such as + "40%". The grade will be interpreted as a percentage score on the + assignment, where 100% == assignment.points_possible. Values above 100% + are allowed, for awarding extra credit. + letter grade:: A letter grade, following the assignment's defined letter + grading scheme. For example, "A-". The resulting score will be the high + end of the defined range for the letter grade. For instance, if "B" is + defined as 86% to 84%, a letter grade of "B" will be worth 86%. The + letter grade will be rejected if the assignment does not have a defined + letter grading scheme. For more fine-grained control of scores, pass in + points or percentage rather than the letter grade. + "pass/complete/fail/incomplete":: A string value of "pass" or "complete" + will give a score of 100%. "fail" or "incomplete" will give a score of + 0. + + Note that assignments with grading_type of "pass_fail" can only be + assigned a score of 0 or assignment.points_possible, nothing inbetween. If + a posted_grade in the "points" or "percentage" format is sent, the grade + will only be accepted if the grade equals one of those two values.""" + if submission_posted_grade is not None: + data["submission[posted_grade]"] = submission_posted_grade + + # OPTIONAL - submission[excuse] + """Sets the "excused" status of an assignment.""" + if submission_excuse is not None: + data["submission[excuse]"] = submission_excuse + + # OPTIONAL - rubric_assessment + """Assign a rubric assessment to this assignment submission. The + sub-parameters here depend on the rubric for the assignment. The general + format is, for each row in the rubric: + + The points awarded for this row. + rubric_assessment[criterion_id][points] + + Comments to add for this row. + rubric_assessment[criterion_id][comments] + + For example, if the assignment rubric is (in JSON format): + !!!javascript + [ + { + 'id': 'crit1', + 'points': 10, + 'description': 'Criterion 1', + 'ratings': + [ + { 'description': 'Good', 'points': 10 }, + { 'description': 'Poor', 'points': 3 } + ] + }, + { + 'id': 'crit2', + 'points': 5, + 'description': 'Criterion 2', + 'ratings': + [ + { 'description': 'Complete', 'points': 5 }, + { 'description': 'Incomplete', 'points': 0 } + ] + } + ] + + Then a possible set of values for rubric_assessment would be: + rubric_assessment[crit1][points]=3&rubric_assessment[crit2][points]=5&rubric_assessment[crit2][comments]=Well%20Done.""" + if rubric_assessment is not None: + data["rubric_assessment"] = rubric_assessment + + self.logger.debug("PUT /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}".format(**path), data=data, params=params, no_data=True) + + def grade_or_comment_on_submission_sections(self, user_id, section_id, assignment_id, comment_file_ids=None, comment_group_comment=None, comment_media_comment_id=None, comment_media_comment_type=None, comment_text_comment=None, include_visibility=None, rubric_assessment=None, submission_excuse=None, submission_posted_grade=None): + """ + Grade or comment on a submission. + + Comment on and/or update the grading for a student's assignment submission. + If any submission or rubric_assessment arguments are provided, the user + must have permission to manage grades in the appropriate context (course or + section). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - comment[text_comment] + """Add a textual comment to the submission.""" + if comment_text_comment is not None: + data["comment[text_comment]"] = comment_text_comment + + # OPTIONAL - comment[group_comment] + """Whether or not this comment should be sent to the entire group (defaults + to false). Ignored if this is not a group assignment or if no text_comment + is provided.""" + if comment_group_comment is not None: + data["comment[group_comment]"] = comment_group_comment + + # OPTIONAL - comment[media_comment_id] + """Add an audio/video comment to the submission. Media comments can be added + via this API, however, note that there is not yet an API to generate or + list existing media comments, so this functionality is currently of + limited use.""" + if comment_media_comment_id is not None: + data["comment[media_comment_id]"] = comment_media_comment_id + + # OPTIONAL - comment[media_comment_type] + """The type of media comment being added.""" + if comment_media_comment_type is not None: + self._validate_enum(comment_media_comment_type, ["audio", "video"]) + data["comment[media_comment_type]"] = comment_media_comment_type + + # OPTIONAL - comment[file_ids] + """Attach files to this comment that were previously uploaded using the + Submission Comment API's files action""" + if comment_file_ids is not None: + data["comment[file_ids]"] = comment_file_ids + + # OPTIONAL - include[visibility] + """Whether this assignment is visible to the owner of the submission""" + if include_visibility is not None: + data["include[visibility]"] = include_visibility + + # OPTIONAL - submission[posted_grade] + """Assign a score to the submission, updating both the "score" and "grade" + fields on the submission record. This parameter can be passed in a few + different formats: + + points:: A floating point or integral value, such as "13.5". The grade + will be interpreted directly as the score of the assignment. + Values above assignment.points_possible are allowed, for awarding + extra credit. + percentage:: A floating point value appended with a percent sign, such as + "40%". The grade will be interpreted as a percentage score on the + assignment, where 100% == assignment.points_possible. Values above 100% + are allowed, for awarding extra credit. + letter grade:: A letter grade, following the assignment's defined letter + grading scheme. For example, "A-". The resulting score will be the high + end of the defined range for the letter grade. For instance, if "B" is + defined as 86% to 84%, a letter grade of "B" will be worth 86%. The + letter grade will be rejected if the assignment does not have a defined + letter grading scheme. For more fine-grained control of scores, pass in + points or percentage rather than the letter grade. + "pass/complete/fail/incomplete":: A string value of "pass" or "complete" + will give a score of 100%. "fail" or "incomplete" will give a score of + 0. + + Note that assignments with grading_type of "pass_fail" can only be + assigned a score of 0 or assignment.points_possible, nothing inbetween. If + a posted_grade in the "points" or "percentage" format is sent, the grade + will only be accepted if the grade equals one of those two values.""" + if submission_posted_grade is not None: + data["submission[posted_grade]"] = submission_posted_grade + + # OPTIONAL - submission[excuse] + """Sets the "excused" status of an assignment.""" + if submission_excuse is not None: + data["submission[excuse]"] = submission_excuse + + # OPTIONAL - rubric_assessment + """Assign a rubric assessment to this assignment submission. The + sub-parameters here depend on the rubric for the assignment. The general + format is, for each row in the rubric: + + The points awarded for this row. + rubric_assessment[criterion_id][points] + + Comments to add for this row. + rubric_assessment[criterion_id][comments] + + For example, if the assignment rubric is (in JSON format): + !!!javascript + [ + { + 'id': 'crit1', + 'points': 10, + 'description': 'Criterion 1', + 'ratings': + [ + { 'description': 'Good', 'points': 10 }, + { 'description': 'Poor', 'points': 3 } + ] + }, + { + 'id': 'crit2', + 'points': 5, + 'description': 'Criterion 2', + 'ratings': + [ + { 'description': 'Complete', 'points': 5 }, + { 'description': 'Incomplete', 'points': 0 } + ] + } + ] + + Then a possible set of values for rubric_assessment would be: + rubric_assessment[crit1][points]=3&rubric_assessment[crit2][points]=5&rubric_assessment[crit2][comments]=Well%20Done.""" + if rubric_assessment is not None: + data["rubric_assessment"] = rubric_assessment + + self.logger.debug("PUT /api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id}".format(**path), data=data, params=params, no_data=True) + + def list_gradeable_students(self, course_id, assignment_id): + """ + List gradeable students. + + List students eligible to submit the assignment. The caller must have permission to view grades. + + Section-limited instructors will only see students in their own sections. + + returns [UserDisplay] + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + self.logger.debug("GET /api/v1/courses/{course_id}/assignments/{assignment_id}/gradeable_students with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/assignments/{assignment_id}/gradeable_students".format(**path), data=data, params=params, no_data=True) + + def grade_or_comment_on_multiple_submissions_courses_submissions(self, course_id, grade_data__excuse=None, grade_data__file_ids=None, grade_data__group_comment=None, grade_data__media_comment_id=None, grade_data__media_comment_type=None, grade_data__posted_grade=None, grade_data__rubric_assessment=None, grade_data__text_comment=None): + """ + Grade or comment on multiple submissions. + + Update the grading and comments on multiple student's assignment + submissions in an asynchronous job. + + The user must have permission to manage grades in the appropriate context + (course or section). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - grade_data[][posted_grade] + """See documentation for the posted_grade argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__posted_grade is not None: + data["grade_data[][posted_grade]"] = grade_data__posted_grade + + # OPTIONAL - grade_data[][excuse] + """See documentation for the excuse argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__excuse is not None: + data["grade_data[][excuse]"] = grade_data__excuse + + # OPTIONAL - grade_data[][rubric_assessment] + """See documentation for the rubric_assessment argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__rubric_assessment is not None: + data["grade_data[][rubric_assessment]"] = grade_data__rubric_assessment + + # OPTIONAL - grade_data[][text_comment] + """no description""" + if grade_data__text_comment is not None: + data["grade_data[][text_comment]"] = grade_data__text_comment + + # OPTIONAL - grade_data[][group_comment] + """no description""" + if grade_data__group_comment is not None: + data["grade_data[][group_comment]"] = grade_data__group_comment + + # OPTIONAL - grade_data[][media_comment_id] + """no description""" + if grade_data__media_comment_id is not None: + data["grade_data[][media_comment_id]"] = grade_data__media_comment_id + + # OPTIONAL - grade_data[][media_comment_type] + """no description""" + if grade_data__media_comment_type is not None: + self._validate_enum(grade_data__media_comment_type, ["audio", "video"]) + data["grade_data[][media_comment_type]"] = grade_data__media_comment_type + + # OPTIONAL - grade_data[][file_ids] + """See documentation for the comment[] arguments in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__file_ids is not None: + data["grade_data[][file_ids]"] = grade_data__file_ids + + self.logger.debug("POST /api/v1/courses/{course_id}/submissions/update_grades with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/submissions/update_grades".format(**path), data=data, params=params, single_item=True) + + def grade_or_comment_on_multiple_submissions_courses_assignments(self, course_id, assignment_id, grade_data__excuse=None, grade_data__file_ids=None, grade_data__group_comment=None, grade_data__media_comment_id=None, grade_data__media_comment_type=None, grade_data__posted_grade=None, grade_data__rubric_assessment=None, grade_data__text_comment=None): + """ + Grade or comment on multiple submissions. + + Update the grading and comments on multiple student's assignment + submissions in an asynchronous job. + + The user must have permission to manage grades in the appropriate context + (course or section). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # OPTIONAL - grade_data[][posted_grade] + """See documentation for the posted_grade argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__posted_grade is not None: + data["grade_data[][posted_grade]"] = grade_data__posted_grade + + # OPTIONAL - grade_data[][excuse] + """See documentation for the excuse argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__excuse is not None: + data["grade_data[][excuse]"] = grade_data__excuse + + # OPTIONAL - grade_data[][rubric_assessment] + """See documentation for the rubric_assessment argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__rubric_assessment is not None: + data["grade_data[][rubric_assessment]"] = grade_data__rubric_assessment + + # OPTIONAL - grade_data[][text_comment] + """no description""" + if grade_data__text_comment is not None: + data["grade_data[][text_comment]"] = grade_data__text_comment + + # OPTIONAL - grade_data[][group_comment] + """no description""" + if grade_data__group_comment is not None: + data["grade_data[][group_comment]"] = grade_data__group_comment + + # OPTIONAL - grade_data[][media_comment_id] + """no description""" + if grade_data__media_comment_id is not None: + data["grade_data[][media_comment_id]"] = grade_data__media_comment_id + + # OPTIONAL - grade_data[][media_comment_type] + """no description""" + if grade_data__media_comment_type is not None: + self._validate_enum(grade_data__media_comment_type, ["audio", "video"]) + data["grade_data[][media_comment_type]"] = grade_data__media_comment_type + + # OPTIONAL - grade_data[][file_ids] + """See documentation for the comment[] arguments in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__file_ids is not None: + data["grade_data[][file_ids]"] = grade_data__file_ids + + self.logger.debug("POST /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/update_grades with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/update_grades".format(**path), data=data, params=params, single_item=True) + + def grade_or_comment_on_multiple_submissions_sections_submissions(self, section_id, grade_data__excuse=None, grade_data__file_ids=None, grade_data__group_comment=None, grade_data__media_comment_id=None, grade_data__media_comment_type=None, grade_data__posted_grade=None, grade_data__rubric_assessment=None, grade_data__text_comment=None): + """ + Grade or comment on multiple submissions. + + Update the grading and comments on multiple student's assignment + submissions in an asynchronous job. + + The user must have permission to manage grades in the appropriate context + (course or section). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # OPTIONAL - grade_data[][posted_grade] + """See documentation for the posted_grade argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__posted_grade is not None: + data["grade_data[][posted_grade]"] = grade_data__posted_grade + + # OPTIONAL - grade_data[][excuse] + """See documentation for the excuse argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__excuse is not None: + data["grade_data[][excuse]"] = grade_data__excuse + + # OPTIONAL - grade_data[][rubric_assessment] + """See documentation for the rubric_assessment argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__rubric_assessment is not None: + data["grade_data[][rubric_assessment]"] = grade_data__rubric_assessment + + # OPTIONAL - grade_data[][text_comment] + """no description""" + if grade_data__text_comment is not None: + data["grade_data[][text_comment]"] = grade_data__text_comment + + # OPTIONAL - grade_data[][group_comment] + """no description""" + if grade_data__group_comment is not None: + data["grade_data[][group_comment]"] = grade_data__group_comment + + # OPTIONAL - grade_data[][media_comment_id] + """no description""" + if grade_data__media_comment_id is not None: + data["grade_data[][media_comment_id]"] = grade_data__media_comment_id + + # OPTIONAL - grade_data[][media_comment_type] + """no description""" + if grade_data__media_comment_type is not None: + self._validate_enum(grade_data__media_comment_type, ["audio", "video"]) + data["grade_data[][media_comment_type]"] = grade_data__media_comment_type + + # OPTIONAL - grade_data[][file_ids] + """See documentation for the comment[] arguments in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__file_ids is not None: + data["grade_data[][file_ids]"] = grade_data__file_ids + + self.logger.debug("POST /api/v1/sections/{section_id}/submissions/update_grades with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/sections/{section_id}/submissions/update_grades".format(**path), data=data, params=params, single_item=True) + + def grade_or_comment_on_multiple_submissions_sections_assignments(self, section_id, assignment_id, grade_data__excuse=None, grade_data__file_ids=None, grade_data__group_comment=None, grade_data__media_comment_id=None, grade_data__media_comment_type=None, grade_data__posted_grade=None, grade_data__rubric_assessment=None, grade_data__text_comment=None): + """ + Grade or comment on multiple submissions. + + Update the grading and comments on multiple student's assignment + submissions in an asynchronous job. + + The user must have permission to manage grades in the appropriate context + (course or section). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # OPTIONAL - grade_data[][posted_grade] + """See documentation for the posted_grade argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__posted_grade is not None: + data["grade_data[][posted_grade]"] = grade_data__posted_grade + + # OPTIONAL - grade_data[][excuse] + """See documentation for the excuse argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__excuse is not None: + data["grade_data[][excuse]"] = grade_data__excuse + + # OPTIONAL - grade_data[][rubric_assessment] + """See documentation for the rubric_assessment argument in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__rubric_assessment is not None: + data["grade_data[][rubric_assessment]"] = grade_data__rubric_assessment + + # OPTIONAL - grade_data[][text_comment] + """no description""" + if grade_data__text_comment is not None: + data["grade_data[][text_comment]"] = grade_data__text_comment + + # OPTIONAL - grade_data[][group_comment] + """no description""" + if grade_data__group_comment is not None: + data["grade_data[][group_comment]"] = grade_data__group_comment + + # OPTIONAL - grade_data[][media_comment_id] + """no description""" + if grade_data__media_comment_id is not None: + data["grade_data[][media_comment_id]"] = grade_data__media_comment_id + + # OPTIONAL - grade_data[][media_comment_type] + """no description""" + if grade_data__media_comment_type is not None: + self._validate_enum(grade_data__media_comment_type, ["audio", "video"]) + data["grade_data[][media_comment_type]"] = grade_data__media_comment_type + + # OPTIONAL - grade_data[][file_ids] + """See documentation for the comment[] arguments in the + {api:SubmissionsApiController#update Submissions Update} documentation""" + if grade_data__file_ids is not None: + data["grade_data[][file_ids]"] = grade_data__file_ids + + self.logger.debug("POST /api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/update_grades with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/update_grades".format(**path), data=data, params=params, single_item=True) + + def mark_submission_as_read_courses(self, user_id, course_id, assignment_id): + """ + Mark submission as read. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("PUT /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_submission_as_read_sections(self, user_id, section_id, assignment_id): + """ + Mark submission as read. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("PUT /api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_submission_as_unread_courses(self, user_id, course_id, assignment_id): + """ + Mark submission as unread. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("DELETE /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}/read".format(**path), data=data, params=params, no_data=True) + + def mark_submission_as_unread_sections(self, user_id, section_id, assignment_id): + """ + Mark submission as unread. + + No request fields are necessary. + + On success, the response will be 204 No Content with an empty body. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - section_id + """ID""" + path["section_id"] = section_id + + # REQUIRED - PATH - assignment_id + """ID""" + path["assignment_id"] = assignment_id + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("DELETE /api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id}/read with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/sections/{section_id}/assignments/{assignment_id}/submissions/{user_id}/read".format(**path), data=data, params=params, no_data=True) + + +class Submissioncomment(BaseModel): + """Submissioncomment Model.""" + + def __init__(self, comment=None, author=None, created_at=None, media_comment=None, author_name=None, author_id=None, id=None): + """Init method for Submissioncomment class.""" + self._comment = comment + self._author = author + self._created_at = created_at + self._media_comment = media_comment + self._author_name = author_name + self._author_id = author_id + self._id = id + + self.logger = logging.getLogger('pycanvas.Submissioncomment') + + @property + def comment(self): + """comment.""" + return self._comment + + @comment.setter + def comment(self, value): + """Setter for comment property.""" + self.logger.warn("Setting values on comment will NOT update the remote Canvas instance.") + self._comment = value + + @property + def author(self): + """Abbreviated user object UserDisplay (see users API).""" + return self._author + + @author.setter + def author(self, value): + """Setter for author property.""" + self.logger.warn("Setting values on author will NOT update the remote Canvas instance.") + self._author = value + + @property + def created_at(self): + """created_at.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def media_comment(self): + """media_comment.""" + return self._media_comment + + @media_comment.setter + def media_comment(self, value): + """Setter for media_comment property.""" + self.logger.warn("Setting values on media_comment will NOT update the remote Canvas instance.") + self._media_comment = value + + @property + def author_name(self): + """author_name.""" + return self._author_name + + @author_name.setter + def author_name(self, value): + """Setter for author_name property.""" + self.logger.warn("Setting values on author_name will NOT update the remote Canvas instance.") + self._author_name = value + + @property + def author_id(self): + """author_id.""" + return self._author_id + + @author_id.setter + def author_id(self, value): + """Setter for author_id property.""" + self.logger.warn("Setting values on author_id will NOT update the remote Canvas instance.") + self._author_id = value + + @property + def id(self): + """id.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Submission(BaseModel): + """Submission Model.""" + + def __init__(self, body=None, attempt=None, submitted_at=None, excused=None, course=None, assignment_id=None, assignment=None, workflow_state=None, html_url=None, preview_url=None, late=None, grade=None, submission_comments=None, score=None, grade_matches_current_submission=None, url=None, grader_id=None, user_id=None, submission_type=None, assignment_visible=None, user=None): + """Init method for Submission class.""" + self._body = body + self._attempt = attempt + self._submitted_at = submitted_at + self._excused = excused + self._course = course + self._assignment_id = assignment_id + self._assignment = assignment + self._workflow_state = workflow_state + self._html_url = html_url + self._preview_url = preview_url + self._late = late + self._grade = grade + self._submission_comments = submission_comments + self._score = score + self._grade_matches_current_submission = grade_matches_current_submission + self._url = url + self._grader_id = grader_id + self._user_id = user_id + self._submission_type = submission_type + self._assignment_visible = assignment_visible + self._user = user + + self.logger = logging.getLogger('pycanvas.Submission') + + @property + def body(self): + """The content of the submission, if it was submitted directly in a text field.""" + return self._body + + @body.setter + def body(self, value): + """Setter for body property.""" + self.logger.warn("Setting values on body will NOT update the remote Canvas instance.") + self._body = value + + @property + def attempt(self): + """This is the submission attempt number.""" + return self._attempt + + @attempt.setter + def attempt(self, value): + """Setter for attempt property.""" + self.logger.warn("Setting values on attempt will NOT update the remote Canvas instance.") + self._attempt = value + + @property + def submitted_at(self): + """The timestamp when the assignment was submitted.""" + return self._submitted_at + + @submitted_at.setter + def submitted_at(self, value): + """Setter for submitted_at property.""" + self.logger.warn("Setting values on submitted_at will NOT update the remote Canvas instance.") + self._submitted_at = value + + @property + def excused(self): + """Whether the assignment is excused. Excused assignments have no impact on a user's grade.""" + return self._excused + + @excused.setter + def excused(self, value): + """Setter for excused property.""" + self.logger.warn("Setting values on excused will NOT update the remote Canvas instance.") + self._excused = value + + @property + def course(self): + """The submission's course (see the course API) (optional).""" + return self._course + + @course.setter + def course(self, value): + """Setter for course property.""" + self.logger.warn("Setting values on course will NOT update the remote Canvas instance.") + self._course = value + + @property + def assignment_id(self): + """The submission's assignment id.""" + return self._assignment_id + + @assignment_id.setter + def assignment_id(self, value): + """Setter for assignment_id property.""" + self.logger.warn("Setting values on assignment_id will NOT update the remote Canvas instance.") + self._assignment_id = value + + @property + def assignment(self): + """The submission's assignment (see the assignments API) (optional).""" + return self._assignment + + @assignment.setter + def assignment(self, value): + """Setter for assignment property.""" + self.logger.warn("Setting values on assignment will NOT update the remote Canvas instance.") + self._assignment = value + + @property + def workflow_state(self): + """The current state of the submission.""" + return self._workflow_state + + @workflow_state.setter + def workflow_state(self, value): + """Setter for workflow_state property.""" + self.logger.warn("Setting values on workflow_state will NOT update the remote Canvas instance.") + self._workflow_state = value + + @property + def html_url(self): + """URL to the submission. This will require the user to log in.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def preview_url(self): + """URL to the submission preview. This will require the user to log in.""" + return self._preview_url + + @preview_url.setter + def preview_url(self, value): + """Setter for preview_url property.""" + self.logger.warn("Setting values on preview_url will NOT update the remote Canvas instance.") + self._preview_url = value + + @property + def late(self): + """Whether the submission was made after the applicable due date.""" + return self._late + + @late.setter + def late(self, value): + """Setter for late property.""" + self.logger.warn("Setting values on late will NOT update the remote Canvas instance.") + self._late = value + + @property + def grade(self): + """The grade for the submission, translated into the assignment grading scheme (so a letter grade, for example).""" + return self._grade + + @grade.setter + def grade(self, value): + """Setter for grade property.""" + self.logger.warn("Setting values on grade will NOT update the remote Canvas instance.") + self._grade = value + + @property + def submission_comments(self): + """Associated comments for a submission (optional).""" + return self._submission_comments + + @submission_comments.setter + def submission_comments(self, value): + """Setter for submission_comments property.""" + self.logger.warn("Setting values on submission_comments will NOT update the remote Canvas instance.") + self._submission_comments = value + + @property + def score(self): + """The raw score.""" + return self._score + + @score.setter + def score(self, value): + """Setter for score property.""" + self.logger.warn("Setting values on score will NOT update the remote Canvas instance.") + self._score = value + + @property + def grade_matches_current_submission(self): + """A boolean flag which is false if the student has re-submitted since the submission was last graded.""" + return self._grade_matches_current_submission + + @grade_matches_current_submission.setter + def grade_matches_current_submission(self, value): + """Setter for grade_matches_current_submission property.""" + self.logger.warn("Setting values on grade_matches_current_submission will NOT update the remote Canvas instance.") + self._grade_matches_current_submission = value + + @property + def url(self): + """The URL of the submission (for 'online_url' submissions).""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def grader_id(self): + """The id of the user who graded the submission.""" + return self._grader_id + + @grader_id.setter + def grader_id(self, value): + """Setter for grader_id property.""" + self.logger.warn("Setting values on grader_id will NOT update the remote Canvas instance.") + self._grader_id = value + + @property + def user_id(self): + """The id of the user who created the submission.""" + return self._user_id + + @user_id.setter + def user_id(self, value): + """Setter for user_id property.""" + self.logger.warn("Setting values on user_id will NOT update the remote Canvas instance.") + self._user_id = value + + @property + def submission_type(self): + """The types of submission ex: ('online_text_entry'|'online_url'|'online_upload'|'media_recording').""" + return self._submission_type + + @submission_type.setter + def submission_type(self, value): + """Setter for submission_type property.""" + self.logger.warn("Setting values on submission_type will NOT update the remote Canvas instance.") + self._submission_type = value + + @property + def assignment_visible(self): + """Whether the assignment is visible to the user who submitted the assignment. Submissions where `assignment_visible` is false no longer count towards the student's grade and the assignment can no longer be accessed by the student. `assignment_visible` becomes false for submissions that do not have a grade and whose assignment is no longer assigned to the student's section.""" + return self._assignment_visible + + @assignment_visible.setter + def assignment_visible(self, value): + """Setter for assignment_visible property.""" + self.logger.warn("Setting values on assignment_visible will NOT update the remote Canvas instance.") + self._assignment_visible = value + + @property + def user(self): + """The submissions user (see user API) (optional).""" + return self._user + + @user.setter + def user(self, value): + """Setter for user property.""" + self.logger.warn("Setting values on user will NOT update the remote Canvas instance.") + self._user = value + + +class Mediacomment(BaseModel): + """Mediacomment Model.""" + + def __init__(self, media_id=None, display_name=None, content_type=None, url=None, media_type=None): + """Init method for Mediacomment class.""" + self._media_id = media_id + self._display_name = display_name + self._content_type = content_type + self._url = url + self._media_type = media_type + + self.logger = logging.getLogger('pycanvas.Mediacomment') + + @property + def media_id(self): + """media_id.""" + return self._media_id + + @media_id.setter + def media_id(self, value): + """Setter for media_id property.""" + self.logger.warn("Setting values on media_id will NOT update the remote Canvas instance.") + self._media_id = value + + @property + def display_name(self): + """display_name.""" + return self._display_name + + @display_name.setter + def display_name(self, value): + """Setter for display_name property.""" + self.logger.warn("Setting values on display_name will NOT update the remote Canvas instance.") + self._display_name = value + + @property + def content_type(self): + """content_type.""" + return self._content_type + + @content_type.setter + def content_type(self, value): + """Setter for content_type property.""" + self.logger.warn("Setting values on content_type will NOT update the remote Canvas instance.") + self._content_type = value + + @property + def url(self): + """url.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def media_type(self): + """media_type.""" + return self._media_type + + @media_type.setter + def media_type(self, value): + """Setter for media_type property.""" + self.logger.warn("Setting values on media_type will NOT update the remote Canvas instance.") + self._media_type = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/tabs.py b/venv/Lib/site-packages/pycanvas/apis/tabs.py new file mode 100644 index 00000000..04fa3df9 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/tabs.py @@ -0,0 +1,190 @@ +"""Tabs API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class TabsAPI(BaseCanvasAPI): + """Tabs API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for TabsAPI.""" + super(TabsAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.TabsAPI") + + def list_available_tabs_for_course_or_group_courses(self, course_id, include=None): + """ + List available tabs for a course or group. + + Returns a list of navigation tabs available in the current context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # OPTIONAL - include + """"external":: Optionally include external tool tabs in the returned list of tabs (Only has effect for courses, not groups)""" + if include is not None: + self._validate_enum(include, ["external"]) + params["include"] = include + + self.logger.debug("GET /api/v1/courses/{course_id}/tabs with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/courses/{course_id}/tabs".format(**path), data=data, params=params, no_data=True) + + def list_available_tabs_for_course_or_group_groups(self, group_id, include=None): + """ + List available tabs for a course or group. + + Returns a list of navigation tabs available in the current context. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - group_id + """ID""" + path["group_id"] = group_id + + # OPTIONAL - include + """"external":: Optionally include external tool tabs in the returned list of tabs (Only has effect for courses, not groups)""" + if include is not None: + self._validate_enum(include, ["external"]) + params["include"] = include + + self.logger.debug("GET /api/v1/groups/{group_id}/tabs with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/groups/{group_id}/tabs".format(**path), data=data, params=params, no_data=True) + + def update_tab_for_course(self, tab_id, course_id, hidden=None, position=None): + """ + Update a tab for a course. + + Home and Settings tabs are not manageable, and can't be hidden or moved + + Returns a tab object + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - PATH - tab_id + """ID""" + path["tab_id"] = tab_id + + # OPTIONAL - position + """The new position of the tab, 1-based""" + if position is not None: + data["position"] = position + + # OPTIONAL - hidden + """no description""" + if hidden is not None: + data["hidden"] = hidden + + self.logger.debug("PUT /api/v1/courses/{course_id}/tabs/{tab_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/courses/{course_id}/tabs/{tab_id}".format(**path), data=data, params=params, single_item=True) + + +class Tab(BaseModel): + """Tab Model.""" + + def __init__(self, html_url=None, visibility=None, label=None, position=None, hidden=None, type=None, id=None): + """Init method for Tab class.""" + self._html_url = html_url + self._visibility = visibility + self._label = label + self._position = position + self._hidden = hidden + self._type = type + self._id = id + + self.logger = logging.getLogger('pycanvas.Tab') + + @property + def html_url(self): + """html_url.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + @property + def visibility(self): + """possible values are: public, members, admins, and none.""" + return self._visibility + + @visibility.setter + def visibility(self, value): + """Setter for visibility property.""" + self.logger.warn("Setting values on visibility will NOT update the remote Canvas instance.") + self._visibility = value + + @property + def label(self): + """label.""" + return self._label + + @label.setter + def label(self, value): + """Setter for label property.""" + self.logger.warn("Setting values on label will NOT update the remote Canvas instance.") + self._label = value + + @property + def position(self): + """1 based.""" + return self._position + + @position.setter + def position(self, value): + """Setter for position property.""" + self.logger.warn("Setting values on position will NOT update the remote Canvas instance.") + self._position = value + + @property + def hidden(self): + """only included if true.""" + return self._hidden + + @hidden.setter + def hidden(self, value): + """Setter for hidden property.""" + self.logger.warn("Setting values on hidden will NOT update the remote Canvas instance.") + self._hidden = value + + @property + def type(self): + """type.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def id(self): + """id.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + diff --git a/venv/Lib/site-packages/pycanvas/apis/user_observees.py b/venv/Lib/site-packages/pycanvas/apis/user_observees.py new file mode 100644 index 00000000..a15f3afc --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/user_observees.py @@ -0,0 +1,145 @@ +"""UserObservees API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI + + + +class UserObserveesAPI(BaseCanvasAPI): + """UserObservees API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for UserObserveesAPI.""" + super(UserObserveesAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.UserObserveesAPI") + + def list_observees(self, user_id, include=None): + """ + List observees. + + List the users that the given user is observing. + + *Note:* all users are allowed to list their own observees. Administrators can list + other users' observees. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - include + """- "avatar_url": Optionally include avatar_url.""" + if include is not None: + self._validate_enum(include, ["avatar_url"]) + params["include"] = include + + self.logger.debug("GET /api/v1/users/{user_id}/observees with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/observees".format(**path), data=data, params=params, all_pages=True) + + def add_observee_with_credentials(self, user_id, access_token=None, observee_password=None, observee_unique_id=None): + """ + Add an observee with credentials. + + Register the given user to observe another user, given the observee's credentials. + + *Note:* all users are allowed to add their own observees, given the observee's + credentials or access token are provided. Administrators can add observees given credentials, access token or + the {api:UserObserveesController#update observee's id}. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - observee[unique_id] + """The login id for the user to observe. Required if access_token is omitted.""" + if observee_unique_id is not None: + data["observee[unique_id]"] = observee_unique_id + + # OPTIONAL - observee[password] + """The password for the user to observe. Required if access_token is omitted.""" + if observee_password is not None: + data["observee[password]"] = observee_password + + # OPTIONAL - access_token + """The access token for the user to observe. Required if observee[unique_id] or observee[password] are omitted.""" + if access_token is not None: + data["access_token"] = access_token + + self.logger.debug("POST /api/v1/users/{user_id}/observees with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/{user_id}/observees".format(**path), data=data, params=params, single_item=True) + + def show_observee(self, user_id, observee_id): + """ + Show an observee. + + Gets information about an observed user. + + *Note:* all users are allowed to view their own observees. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - observee_id + """ID""" + path["observee_id"] = observee_id + + self.logger.debug("GET /api/v1/users/{user_id}/observees/{observee_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/observees/{observee_id}".format(**path), data=data, params=params, single_item=True) + + def add_observee(self, user_id, observee_id): + """ + Add an observee. + + Registers a user as being observed by the given user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - observee_id + """ID""" + path["observee_id"] = observee_id + + self.logger.debug("PUT /api/v1/users/{user_id}/observees/{observee_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{user_id}/observees/{observee_id}".format(**path), data=data, params=params, single_item=True) + + def remove_observee(self, user_id, observee_id): + """ + Remove an observee. + + Unregisters a user as being observed by the given user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - PATH - observee_id + """ID""" + path["observee_id"] = observee_id + + self.logger.debug("DELETE /api/v1/users/{user_id}/observees/{observee_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/{user_id}/observees/{observee_id}".format(**path), data=data, params=params, single_item=True) + diff --git a/venv/Lib/site-packages/pycanvas/apis/users.py b/venv/Lib/site-packages/pycanvas/apis/users.py new file mode 100644 index 00000000..f7ff77a4 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/apis/users.py @@ -0,0 +1,2324 @@ +"""Users API Version 1.0. + +This API client was generated using a template. Make sure this code is valid before using it. +""" +import logging +from datetime import date, datetime +from base import BaseCanvasAPI +from base import BaseModel + + +class UsersAPI(BaseCanvasAPI): + """Users API Version 1.0.""" + + def __init__(self, *args, **kwargs): + """Init method for UsersAPI.""" + super(UsersAPI, self).__init__(*args, **kwargs) + self.logger = logging.getLogger("pycanvas.UsersAPI") + + def list_users_in_account(self, account_id, search_term=None): + """ + List users in account. + + Retrieve the list of users associated with this account. + + @example_request + curl https:///api/v1/accounts/self/users?search_term= \ + -X GET \ + -H 'Authorization: Bearer ' + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - search_term + """The partial name or full ID of the users to match and return in the + results list. Must be at least 3 characters. + + Note that the API will prefer matching on canonical user ID if the ID has + a numeric form. It will only search against other fields if non-numeric + in form, or if the numeric value doesn't yield any matches. Queries by + administrative users will search on SIS ID, name, or email address; non- + administrative queries will only be compared against name.""" + if search_term is not None: + params["search_term"] = search_term + + self.logger.debug("GET /api/v1/accounts/{account_id}/users with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/accounts/{account_id}/users".format(**path), data=data, params=params, all_pages=True) + + def list_activity_stream_self(self): + """ + List the activity stream. + + Returns the current user's global activity stream, paginated. + + There are many types of objects that can be returned in the activity + stream. All object types have the same basic set of shared attributes: + !!!javascript + { + 'created_at': '2011-07-13T09:12:00Z', + 'updated_at': '2011-07-25T08:52:41Z', + 'id': 1234, + 'title': 'Stream Item Subject', + 'message': 'This is the body text of the activity stream item. It is plain-text, and can be multiple paragraphs.', + 'type': 'DiscussionTopic|Conversation|Message|Submission|Conference|Collaboration|AssessmentRequest...', + 'read_state': false, + 'context_type': 'course', // course|group + 'course_id': 1, + 'group_id': null, + 'html_url': "http://..." // URL to the Canvas web UI for this stream item + } + + In addition, each item type has its own set of attributes available. + + DiscussionTopic: + + !!!javascript + { + 'type': 'DiscussionTopic', + 'discussion_topic_id': 1234, + 'total_root_discussion_entries': 5, + 'require_initial_post': true, + 'user_has_posted': true, + 'root_discussion_entries': { + ... + } + } + + For DiscussionTopic, the message is truncated at 4kb. + + Announcement: + + !!!javascript + { + 'type': 'Announcement', + 'announcement_id': 1234, + 'total_root_discussion_entries': 5, + 'require_initial_post': true, + 'user_has_posted': null, + 'root_discussion_entries': { + ... + } + } + + For Announcement, the message is truncated at 4kb. + + Conversation: + + !!!javascript + { + 'type': 'Conversation', + 'conversation_id': 1234, + 'private': false, + 'participant_count': 3, + } + + Message: + + !!!javascript + { + 'type': 'Message', + 'message_id': 1234, + 'notification_category': 'Assignment Graded' + } + + Submission: + + Returns an {api:Submissions:Submission Submission} with its Course and Assignment data. + + Conference: + + !!!javascript + { + 'type': 'Conference', + 'web_conference_id': 1234 + } + + Collaboration: + + !!!javascript + { + 'type': 'Collaboration', + 'collaboration_id': 1234 + } + + AssessmentRequest: + + !!!javascript + { + 'type': 'AssessmentRequest', + 'assessment_request_id': 1234 + } + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/users/self/activity_stream with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/activity_stream".format(**path), data=data, params=params, no_data=True) + + def list_activity_stream_activity_stream(self): + """ + List the activity stream. + + Returns the current user's global activity stream, paginated. + + There are many types of objects that can be returned in the activity + stream. All object types have the same basic set of shared attributes: + !!!javascript + { + 'created_at': '2011-07-13T09:12:00Z', + 'updated_at': '2011-07-25T08:52:41Z', + 'id': 1234, + 'title': 'Stream Item Subject', + 'message': 'This is the body text of the activity stream item. It is plain-text, and can be multiple paragraphs.', + 'type': 'DiscussionTopic|Conversation|Message|Submission|Conference|Collaboration|AssessmentRequest...', + 'read_state': false, + 'context_type': 'course', // course|group + 'course_id': 1, + 'group_id': null, + 'html_url': "http://..." // URL to the Canvas web UI for this stream item + } + + In addition, each item type has its own set of attributes available. + + DiscussionTopic: + + !!!javascript + { + 'type': 'DiscussionTopic', + 'discussion_topic_id': 1234, + 'total_root_discussion_entries': 5, + 'require_initial_post': true, + 'user_has_posted': true, + 'root_discussion_entries': { + ... + } + } + + For DiscussionTopic, the message is truncated at 4kb. + + Announcement: + + !!!javascript + { + 'type': 'Announcement', + 'announcement_id': 1234, + 'total_root_discussion_entries': 5, + 'require_initial_post': true, + 'user_has_posted': null, + 'root_discussion_entries': { + ... + } + } + + For Announcement, the message is truncated at 4kb. + + Conversation: + + !!!javascript + { + 'type': 'Conversation', + 'conversation_id': 1234, + 'private': false, + 'participant_count': 3, + } + + Message: + + !!!javascript + { + 'type': 'Message', + 'message_id': 1234, + 'notification_category': 'Assignment Graded' + } + + Submission: + + Returns an {api:Submissions:Submission Submission} with its Course and Assignment data. + + Conference: + + !!!javascript + { + 'type': 'Conference', + 'web_conference_id': 1234 + } + + Collaboration: + + !!!javascript + { + 'type': 'Collaboration', + 'collaboration_id': 1234 + } + + AssessmentRequest: + + !!!javascript + { + 'type': 'AssessmentRequest', + 'assessment_request_id': 1234 + } + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/users/activity_stream with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/activity_stream".format(**path), data=data, params=params, no_data=True) + + def activity_stream_summary(self): + """ + Activity stream summary. + + Returns a summary of the current user's global activity stream. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/users/self/activity_stream/summary with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/activity_stream/summary".format(**path), data=data, params=params, no_data=True) + + def list_todo_items(self, include=None): + """ + List the TODO items. + + Returns the current user's list of todo items, as seen on the user dashboard. + + There is a limit to the number of items returned. + + The `ignore` and `ignore_permanently` URLs can be used to update the user's + preferences on what items will be displayed. + Performing a DELETE request against the `ignore` URL will hide that item + from future todo item requests, until the item changes. + Performing a DELETE request against the `ignore_permanently` URL will hide + that item forever. + """ + path = {} + data = {} + params = {} + + # OPTIONAL - include + """"ungraded_quizzes":: Optionally include ungraded quizzes (such as practice quizzes and surveys) in the list. + These will be returned under a +quiz+ key instead of an +assignment+ key in response elements.""" + if include is not None: + self._validate_enum(include, ["ungraded_quizzes"]) + params["include"] = include + + self.logger.debug("GET /api/v1/users/self/todo with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/todo".format(**path), data=data, params=params, no_data=True) + + def list_upcoming_assignments_calendar_events(self): + """ + List upcoming assignments, calendar events. + + Returns the current user's upcoming events, i.e. the same things shown + in the dashboard 'Coming Up' sidebar. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/users/self/upcoming_events with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/upcoming_events".format(**path), data=data, params=params, no_data=True) + + def list_missing_submissions(self, user_id): + """ + List Missing Submissions. + + returns past-due assignments for which the student does not have a submission. + The user sending the request must either be an admin or a parent observer using the parent app + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """the student's ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/missing_submissions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/missing_submissions".format(**path), data=data, params=params, all_pages=True) + + def hide_stream_item(self, id): + """ + Hide a stream item. + + Hide the given stream item. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("DELETE /api/v1/users/self/activity_stream/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/self/activity_stream/{id}".format(**path), data=data, params=params, no_data=True) + + def hide_all_stream_items(self): + """ + Hide all stream items. + + Hide all stream items for the user + """ + path = {} + data = {} + params = {} + + self.logger.debug("DELETE /api/v1/users/self/activity_stream with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/self/activity_stream".format(**path), data=data, params=params, no_data=True) + + def upload_file(self, user_id): + """ + Upload a file. + + Upload a file to the user's personal files section. + + This API endpoint is the first step in uploading a file to a user's files. + See the {file:file_uploads.html File Upload Documentation} for details on + the file upload workflow. + + Note that typically users will only be able to upload files to their + own files section. Passing a user_id of +self+ is an easy shortcut + to specify the current user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("POST /api/v1/users/{user_id}/files with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/{user_id}/files".format(**path), data=data, params=params, no_data=True) + + def show_user_details(self, id): + """ + Show user details. + + Shows details for user. + + Also includes an attribute "permissions", a non-comprehensive list of permissions for the user. + Example: + !!!javascript + "permissions": { + "can_update_name": true, // Whether the user can update their name. + "can_update_avatar": false // Whether the user can update their avatar. + } + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/users/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{id}".format(**path), data=data, params=params, single_item=True) + + def create_user(self, account_id, pseudonym_unique_id, communication_channel_address=None, communication_channel_confirmation_url=None, communication_channel_skip_confirmation=None, communication_channel_type=None, enable_sis_reactivation=None, force_validations=None, pseudonym_authentication_provider_id=None, pseudonym_force_self_registration=None, pseudonym_integration_id=None, pseudonym_password=None, pseudonym_send_confirmation=None, pseudonym_sis_user_id=None, user_birthdate=None, user_locale=None, user_name=None, user_short_name=None, user_skip_registration=None, user_sortable_name=None, user_terms_of_use=None, user_time_zone=None): + """ + Create a user. + + Create and return a new user and pseudonym for an account. + + If you don't have the "Modify login details for users" permission, but + self-registration is enabled on the account, you can still use this + endpoint to register new users. Certain fields will be required, and + others will be ignored (see below). + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # OPTIONAL - user[name] + """The full name of the user. This name will be used by teacher for grading. + Required if this is a self-registration.""" + if user_name is not None: + data["user[name]"] = user_name + + # OPTIONAL - user[short_name] + """User's name as it will be displayed in discussions, messages, and comments.""" + if user_short_name is not None: + data["user[short_name]"] = user_short_name + + # OPTIONAL - user[sortable_name] + """User's name as used to sort alphabetically in lists.""" + if user_sortable_name is not None: + data["user[sortable_name]"] = user_sortable_name + + # OPTIONAL - user[time_zone] + """The time zone for the user. Allowed time zones are + {http://www.iana.org/time-zones IANA time zones} or friendlier + {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + if user_time_zone is not None: + data["user[time_zone]"] = user_time_zone + + # OPTIONAL - user[locale] + """The user's preferred language, from the list of languages Canvas supports. + This is in RFC-5646 format.""" + if user_locale is not None: + data["user[locale]"] = user_locale + + # OPTIONAL - user[birthdate] + """The user's birth date.""" + if user_birthdate is not None: + data["user[birthdate]"] = user_birthdate + + # OPTIONAL - user[terms_of_use] + """Whether the user accepts the terms of use. Required if this is a + self-registration and this canvas instance requires users to accept + the terms (on by default). + + If this is true, it will mark the user as having accepted the terms of use.""" + if user_terms_of_use is not None: + data["user[terms_of_use]"] = user_terms_of_use + + # OPTIONAL - user[skip_registration] + """Automatically mark the user as registered. + + If this is true, it is recommended to set "pseudonym[send_confirmation]" to true as well. + Otherwise, the user will not receive any messages about their account creation. + + The users communication channel confirmation can be skipped by setting + "communication_channel[skip_confirmation]" to true as well.""" + if user_skip_registration is not None: + data["user[skip_registration]"] = user_skip_registration + + # REQUIRED - pseudonym[unique_id] + """User's login ID. If this is a self-registration, it must be a valid + email address.""" + data["pseudonym[unique_id]"] = pseudonym_unique_id + + # OPTIONAL - pseudonym[password] + """User's password. Cannot be set during self-registration.""" + if pseudonym_password is not None: + data["pseudonym[password]"] = pseudonym_password + + # OPTIONAL - pseudonym[sis_user_id] + """SIS ID for the user's account. To set this parameter, the caller must be + able to manage SIS permissions.""" + if pseudonym_sis_user_id is not None: + data["pseudonym[sis_user_id]"] = pseudonym_sis_user_id + + # OPTIONAL - pseudonym[integration_id] + """Integration ID for the login. To set this parameter, the caller must be able to + manage SIS permissions. The Integration ID is a secondary + identifier useful for more complex SIS integrations.""" + if pseudonym_integration_id is not None: + data["pseudonym[integration_id]"] = pseudonym_integration_id + + # OPTIONAL - pseudonym[send_confirmation] + """Send user notification of account creation if true. + Automatically set to true during self-registration.""" + if pseudonym_send_confirmation is not None: + data["pseudonym[send_confirmation]"] = pseudonym_send_confirmation + + # OPTIONAL - pseudonym[force_self_registration] + """Send user a self-registration style email if true. + Setting it means the users will get a notification asking them + to "complete the registration process" by clicking it, setting + a password, and letting them in. Will only be executed on + if the user does not need admin approval. + Defaults to false unless explicitly provided.""" + if pseudonym_force_self_registration is not None: + data["pseudonym[force_self_registration]"] = pseudonym_force_self_registration + + # OPTIONAL - pseudonym[authentication_provider_id] + """The authentication provider this login is associated with. Logins + associated with a specific provider can only be used with that provider. + Legacy providers (LDAP, CAS, SAML) will search for logins associated with + them, or unassociated logins. New providers will only search for logins + explicitly associated with them. This can be the integer ID of the + provider, or the type of the provider (in which case, it will find the + first matching provider).""" + if pseudonym_authentication_provider_id is not None: + data["pseudonym[authentication_provider_id]"] = pseudonym_authentication_provider_id + + # OPTIONAL - communication_channel[type] + """The communication channel type, e.g. 'email' or 'sms'.""" + if communication_channel_type is not None: + data["communication_channel[type]"] = communication_channel_type + + # OPTIONAL - communication_channel[address] + """The communication channel address, e.g. the user's email address.""" + if communication_channel_address is not None: + data["communication_channel[address]"] = communication_channel_address + + # OPTIONAL - communication_channel[confirmation_url] + """Only valid for account admins. If true, returns the new user account + confirmation URL in the response.""" + if communication_channel_confirmation_url is not None: + data["communication_channel[confirmation_url]"] = communication_channel_confirmation_url + + # OPTIONAL - communication_channel[skip_confirmation] + """Only valid for site admins and account admins making requests; If true, the channel is + automatically validated and no confirmation email or SMS is sent. + Otherwise, the user must respond to a confirmation message to confirm the + channel. + + If this is true, it is recommended to set "pseudonym[send_confirmation]" to true as well. + Otherwise, the user will not receive any messages about their account creation.""" + if communication_channel_skip_confirmation is not None: + data["communication_channel[skip_confirmation]"] = communication_channel_skip_confirmation + + # OPTIONAL - force_validations + """If true, validations are performed on the newly created user (and their associated pseudonym) + even if the request is made by a privileged user like an admin. When set to false, + or not included in the request parameters, any newly created users are subject to + validations unless the request is made by a user with a 'manage_user_logins' right. + In which case, certain validations such as 'require_acceptance_of_terms' and + 'require_presence_of_name' are not enforced. Use this parameter to return helpful json + errors while building users with an admin request.""" + if force_validations is not None: + data["force_validations"] = force_validations + + # OPTIONAL - enable_sis_reactivation + """When true, will first try to re-activate a deleted user with matching sis_user_id if possible.""" + if enable_sis_reactivation is not None: + data["enable_sis_reactivation"] = enable_sis_reactivation + + self.logger.debug("POST /api/v1/accounts/{account_id}/users with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/users".format(**path), data=data, params=params, single_item=True) + + def self_register_user(self, user_name, account_id, user_terms_of_use, pseudonym_unique_id, communication_channel_address=None, communication_channel_type=None, user_birthdate=None, user_locale=None, user_short_name=None, user_sortable_name=None, user_time_zone=None): + """ + Self register a user. + + Self register and return a new user and pseudonym for an account. + + If self-registration is enabled on the account, you can use this + endpoint to self register new users. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - account_id + """ID""" + path["account_id"] = account_id + + # REQUIRED - user[name] + """The full name of the user. This name will be used by teacher for grading.""" + data["user[name]"] = user_name + + # OPTIONAL - user[short_name] + """User's name as it will be displayed in discussions, messages, and comments.""" + if user_short_name is not None: + data["user[short_name]"] = user_short_name + + # OPTIONAL - user[sortable_name] + """User's name as used to sort alphabetically in lists.""" + if user_sortable_name is not None: + data["user[sortable_name]"] = user_sortable_name + + # OPTIONAL - user[time_zone] + """The time zone for the user. Allowed time zones are + {http://www.iana.org/time-zones IANA time zones} or friendlier + {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + if user_time_zone is not None: + data["user[time_zone]"] = user_time_zone + + # OPTIONAL - user[locale] + """The user's preferred language, from the list of languages Canvas supports. + This is in RFC-5646 format.""" + if user_locale is not None: + data["user[locale]"] = user_locale + + # OPTIONAL - user[birthdate] + """The user's birth date.""" + if user_birthdate is not None: + data["user[birthdate]"] = user_birthdate + + # REQUIRED - user[terms_of_use] + """Whether the user accepts the terms of use.""" + data["user[terms_of_use]"] = user_terms_of_use + + # REQUIRED - pseudonym[unique_id] + """User's login ID. Must be a valid email address.""" + data["pseudonym[unique_id]"] = pseudonym_unique_id + + # OPTIONAL - communication_channel[type] + """The communication channel type, e.g. 'email' or 'sms'.""" + if communication_channel_type is not None: + data["communication_channel[type]"] = communication_channel_type + + # OPTIONAL - communication_channel[address] + """The communication channel address, e.g. the user's email address.""" + if communication_channel_address is not None: + data["communication_channel[address]"] = communication_channel_address + + self.logger.debug("POST /api/v1/accounts/{account_id}/self_registration with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/accounts/{account_id}/self_registration".format(**path), data=data, params=params, single_item=True) + + def update_user_settings(self, id, collapse_global_nav=None, manual_mark_as_read=None): + """ + Update user settings. + + Update an existing user's settings. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - manual_mark_as_read + """If true, require user to manually mark discussion posts as read (don't + auto-mark as read).""" + if manual_mark_as_read is not None: + params["manual_mark_as_read"] = manual_mark_as_read + + # OPTIONAL - collapse_global_nav + """If true, the user's page loads with the global navigation collapsed""" + if collapse_global_nav is not None: + params["collapse_global_nav"] = collapse_global_nav + + self.logger.debug("GET /api/v1/users/{id}/settings with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{id}/settings".format(**path), data=data, params=params, no_data=True) + + def get_custom_colors(self, id): + """ + Get custom colors. + + Returns all custom colors that have been saved for a user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/users/{id}/colors with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{id}/colors".format(**path), data=data, params=params, no_data=True) + + def get_custom_color(self, id, asset_string): + """ + Get custom color. + + Returns the custom colors that have been saved for a user for a given context. + + The asset_string parameter should be in the format 'context_id', for example + 'course_42'. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - asset_string + """ID""" + path["asset_string"] = asset_string + + self.logger.debug("GET /api/v1/users/{id}/colors/{asset_string} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{id}/colors/{asset_string}".format(**path), data=data, params=params, no_data=True) + + def update_custom_color(self, id, asset_string, hexcode=None): + """ + Update custom color. + + Updates a custom color for a user for a given context. This allows + colors for the calendar and elsewhere to be customized on a user basis. + + The asset string parameter should be in the format 'context_id', for example + 'course_42' + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - asset_string + """ID""" + path["asset_string"] = asset_string + + # OPTIONAL - hexcode + """The hexcode of the color to set for the context, if you choose to pass the + hexcode as a query parameter rather than in the request body you should + NOT include the '#' unless you escape it first.""" + if hexcode is not None: + data["hexcode"] = hexcode + + self.logger.debug("PUT /api/v1/users/{id}/colors/{asset_string} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{id}/colors/{asset_string}".format(**path), data=data, params=params, no_data=True) + + def get_dashboard_postions(self, id): + """ + Get dashboard postions. + + Returns all dashboard positions that have been saved for a user. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("GET /api/v1/users/{id}/dashboard_positions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{id}/dashboard_positions".format(**path), data=data, params=params, no_data=True) + + def update_dashboard_positions(self, id): + """ + Update dashboard positions. + + Updates the dashboard positions for a user for a given context. This allows + positions for the dashboard cards and elsewhere to be customized on a per + user basis. + + The asset string parameter should be in the format 'context_id', for example + 'course_42' + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("PUT /api/v1/users/{id}/dashboard_positions with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{id}/dashboard_positions".format(**path), data=data, params=params, no_data=True) + + def edit_user(self, id, user_avatar_token=None, user_avatar_url=None, user_email=None, user_locale=None, user_name=None, user_short_name=None, user_sortable_name=None, user_time_zone=None): + """ + Edit a user. + + Modify an existing user. To modify a user's login, see the documentation for logins. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # OPTIONAL - user[name] + """The full name of the user. This name will be used by teacher for grading.""" + if user_name is not None: + data["user[name]"] = user_name + + # OPTIONAL - user[short_name] + """User's name as it will be displayed in discussions, messages, and comments.""" + if user_short_name is not None: + data["user[short_name]"] = user_short_name + + # OPTIONAL - user[sortable_name] + """User's name as used to sort alphabetically in lists.""" + if user_sortable_name is not None: + data["user[sortable_name]"] = user_sortable_name + + # OPTIONAL - user[time_zone] + """The time zone for the user. Allowed time zones are + {http://www.iana.org/time-zones IANA time zones} or friendlier + {http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html Ruby on Rails time zones}.""" + if user_time_zone is not None: + data["user[time_zone]"] = user_time_zone + + # OPTIONAL - user[email] + """The default email address of the user.""" + if user_email is not None: + data["user[email]"] = user_email + + # OPTIONAL - user[locale] + """The user's preferred language, from the list of languages Canvas supports. + This is in RFC-5646 format.""" + if user_locale is not None: + data["user[locale]"] = user_locale + + # OPTIONAL - user[avatar][token] + """A unique representation of the avatar record to assign as the user's + current avatar. This token can be obtained from the user avatars endpoint. + This supersedes the user [avatar] [url] argument, and if both are included + the url will be ignored. Note: this is an internal representation and is + subject to change without notice. It should be consumed with this api + endpoint and used in the user update endpoint, and should not be + constructed by the client.""" + if user_avatar_token is not None: + data["user[avatar][token]"] = user_avatar_token + + # OPTIONAL - user[avatar][url] + """To set the user's avatar to point to an external url, do not include a + token and instead pass the url here. Warning: For maximum compatibility, + please use 128 px square images.""" + if user_avatar_url is not None: + data["user[avatar][url]"] = user_avatar_url + + self.logger.debug("PUT /api/v1/users/{id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{id}".format(**path), data=data, params=params, single_item=True) + + def merge_user_into_another_user_destination_user_id(self, id, destination_user_id): + """ + Merge user into another user. + + Merge a user into another user. + To merge users, the caller must have permissions to manage both users. This + should be considered irreversible. This will delete the user and move all + the data into the destination user. + + When finding users by SIS ids in different accounts the + destination_account_id is required. + + The account can also be identified by passing the domain in destination_account_id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - destination_user_id + """ID""" + path["destination_user_id"] = destination_user_id + + self.logger.debug("PUT /api/v1/users/{id}/merge_into/{destination_user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{id}/merge_into/{destination_user_id}".format(**path), data=data, params=params, single_item=True) + + def merge_user_into_another_user_accounts(self, id, destination_user_id, destination_account_id): + """ + Merge user into another user. + + Merge a user into another user. + To merge users, the caller must have permissions to manage both users. This + should be considered irreversible. This will delete the user and move all + the data into the destination user. + + When finding users by SIS ids in different accounts the + destination_account_id is required. + + The account can also be identified by passing the domain in destination_account_id. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + # REQUIRED - PATH - destination_account_id + """ID""" + path["destination_account_id"] = destination_account_id + + # REQUIRED - PATH - destination_user_id + """ID""" + path["destination_user_id"] = destination_user_id + + self.logger.debug("PUT /api/v1/users/{id}/merge_into/accounts/{destination_account_id}/users/{destination_user_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{id}/merge_into/accounts/{destination_account_id}/users/{destination_user_id}".format(**path), data=data, params=params, single_item=True) + + def split_merged_users_into_separate_users(self, id): + """ + Split merged users into separate users. + + Merged users cannot be fully restored to their previous state, but this will + attempt to split as much as possible to the previous state. + To split a merged user, the caller must have permissions to manage all of + the users logins. If there are multiple users that have been merged into one + user it will split each merge into a separate user. + A split can only happen within 90 days of a user merge. A user merge deletes + the previous user and may be permanently deleted. In this scenario we create + a new user object and proceed to move as much as possible to the new user. + The user object will not have preserved the name or settings from the + previous user. Some items may have been deleted during a user_merge that + cannot be restored, and/or the data has become stale because of other + changes to the objects since the time of the user_merge. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - id + """ID""" + path["id"] = id + + self.logger.debug("POST /api/v1/users/{id}/split with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("POST", "/api/v1/users/{id}/split".format(**path), data=data, params=params, all_pages=True) + + def get_user_profile(self, user_id): + """ + Get user profile. + + Returns user profile data, including user id, name, and profile pic. + + When requesting the profile for the user accessing the API, the user's + calendar feed URL will be returned as well. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/profile with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/profile".format(**path), data=data, params=params, single_item=True) + + def list_avatar_options(self, user_id): + """ + List avatar options. + + Retrieve the possible user avatar options that can be set with the user update endpoint. The response will be an array of avatar records. If the 'type' field is 'attachment', the record will include all the normal attachment json fields; otherwise it will include only the 'url' and 'display_name' fields. Additionally, all records will include a 'type' field and a 'token' field. The following explains each field in more detail + type:: ["gravatar"|"attachment"|"no_pic"] The type of avatar record, for categorization purposes. + url:: The url of the avatar + token:: A unique representation of the avatar record which can be used to set the avatar with the user update endpoint. Note: this is an internal representation and is subject to change without notice. It should be consumed with this api endpoint and used in the user update endpoint, and should not be constructed by the client. + display_name:: A textual description of the avatar record + id:: ['attachment' type only] the internal id of the attachment + content-type:: ['attachment' type only] the content-type of the attachment + filename:: ['attachment' type only] the filename of the attachment + size:: ['attachment' type only] the size of the attachment + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + self.logger.debug("GET /api/v1/users/{user_id}/avatars with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/avatars".format(**path), data=data, params=params, all_pages=True) + + def list_user_page_views(self, user_id, end_time=None, start_time=None): + """ + List user page views. + + Return the user's page view history in json format, similar to the + available CSV download. Pagination is used as described in API basics + section. Page views are returned in descending order, newest to oldest. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # OPTIONAL - start_time + """The beginning of the time range from which you want page views.""" + if start_time is not None: + params["start_time"] = start_time + + # OPTIONAL - end_time + """The end of the time range from which you want page views.""" + if end_time is not None: + params["end_time"] = end_time + + self.logger.debug("GET /api/v1/users/{user_id}/page_views with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/page_views".format(**path), data=data, params=params, all_pages=True) + + def store_custom_data(self, ns, data, user_id): + """ + Store custom data. + + Store arbitrary user data as JSON. + + Arbitrary JSON data can be stored for a User. + A typical scenario would be an external site/service that registers users in Canvas + and wants to capture additional info about them. The part of the URL that follows + +/custom_data/+ defines the scope of the request, and it reflects the structure of + the JSON data to be stored or retrieved. + + The value +self+ may be used for +user_id+ to store data associated with the calling user. + In order to access another user's custom data, you must be an account administrator with + permission to manage users. + + A namespace parameter, +ns+, is used to prevent custom_data collisions between + different apps. This parameter is required for all custom_data requests. + + A request with Content-Type multipart/form-data or Content-Type + application/x-www-form-urlencoded can only be used to store strings. + + Example PUT with multipart/form-data data: + curl 'https:///api/v1/users//custom_data/telephone' \ + -X PUT \ + -F 'ns=com.my-organization.canvas-app' \ + -F 'data=555-1234' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": "555-1234" + } + + Subscopes (or, generated scopes) can also be specified by passing values to + +data+[+subscope+]. + + Example PUT specifying subscopes: + curl 'https:///api/v1/users//custom_data/body/measurements' \ + -X PUT \ + -F 'ns=com.my-organization.canvas-app' \ + -F 'data[waist]=32in' \ + -F 'data[inseam]=34in' \ + -F 'data[chest]=40in' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": { + "chest": "40in", + "waist": "32in", + "inseam": "34in" + } + } + + Following such a request, subsets of the stored data to be retrieved directly from a subscope. + + Example {api:UsersController#get_custom_data GET} from a generated scope + curl 'https:///api/v1/users//custom_data/body/measurements/chest' \ + -X GET \ + -F 'ns=com.my-organization.canvas-app' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": "40in" + } + + If you want to store more than just strings (i.e. numbers, arrays, hashes, true, false, + and/or null), you must make a request with Content-Type application/json as in the following + example. + + Example PUT with JSON data: + curl 'https:///api/v1/users//custom_data' \ + -H 'Content-Type: application/json' \ + -X PUT \ + -d '{ + "ns": "com.my-organization.canvas-app", + "data": { + "a-number": 6.02e23, + "a-bool": true, + "a-string": "true", + "a-hash": {"a": {"b": "ohai"}}, + "an-array": [1, "two", null, false] + } + }' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": { + "a-number": 6.02e+23, + "a-bool": true, + "a-string": "true", + "a-hash": { + "a": { + "b": "ohai" + } + }, + "an-array": [1, "two", null, false] + } + } + + If the data is an Object (as it is in the above example), then subsets of the data can + be accessed by including the object's (possibly nested) keys in the scope of a GET request. + + Example {api:UsersController#get_custom_data GET} with a generated scope: + curl 'https:///api/v1/users//custom_data/a-hash/a/b' \ + -X GET \ + -F 'ns=com.my-organization.canvas-app' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": "ohai" + } + + + On success, this endpoint returns an object containing the data that was stored. + + Responds with status code 200 if the scope already contained data, and it was overwritten + by the data specified in the request. + + Responds with status code 201 if the scope was previously empty, and the data specified + in the request was successfully stored there. + + Responds with status code 400 if the namespace parameter, +ns+, is missing or invalid, or if + the +data+ parameter is missing. + + Responds with status code 409 if the requested scope caused a conflict and data was not stored. + This happens when storing data at the requested scope would cause data at an outer scope + to be lost. e.g., if +/custom_data+ was +{"fashion_app": {"hair": "blonde"}}+, but + you tried to +`PUT /custom_data/fashion_app/hair/style -F data=buzz`+, then for the request + to succeed,the value of +/custom_data/fashion_app/hair+ would have to become a hash, and its + old string value would be lost. In this situation, an error object is returned with the + following format: + + !!!javascript + { + "message": "write conflict for custom_data hash", + "conflict_scope": "fashion_app/hair", + "type_at_conflict": "String", + "value_at_conflict": "blonde" + } + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - ns + """The namespace under which to store the data. This should be something other + Canvas API apps aren't likely to use, such as a reverse DNS for your organization.""" + data["ns"] = ns + + # REQUIRED - data + """The data you want to store for the user, at the specified scope. If the data is + composed of (possibly nested) JSON objects, scopes will be generated for the (nested) + keys (see examples).""" + data["data"] = data + + self.logger.debug("PUT /api/v1/users/{user_id}/custom_data with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/{user_id}/custom_data".format(**path), data=data, params=params, no_data=True) + + def load_custom_data(self, ns, user_id): + """ + Load custom data. + + Load custom user data. + + Arbitrary JSON data can be stored for a User. This API call + retrieves that data for a (optional) given scope. + See {api:UsersController#set_custom_data Store Custom Data} for details and + examples. + + On success, this endpoint returns an object containing the data that was requested. + + Responds with status code 400 if the namespace parameter, +ns+, is missing or invalid, + or if the specified scope does not contain any data. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - ns + """The namespace from which to retrieve the data. This should be something other + Canvas API apps aren't likely to use, such as a reverse DNS for your organization.""" + params["ns"] = ns + + self.logger.debug("GET /api/v1/users/{user_id}/custom_data with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/{user_id}/custom_data".format(**path), data=data, params=params, no_data=True) + + def delete_custom_data(self, ns, user_id): + """ + Delete custom data. + + Delete custom user data. + + Arbitrary JSON data can be stored for a User. This API call + deletes that data for a given scope. Without a scope, all custom_data is deleted. + See {api:UsersController#set_custom_data Store Custom Data} for details and + examples of storage and retrieval. + + As an example, we'll store some data, then delete a subset of it. + + Example {api:UsersController#set_custom_data PUT} with valid JSON data: + curl 'https:///api/v1/users//custom_data' \ + -X PUT \ + -F 'ns=com.my-organization.canvas-app' \ + -F 'data[fruit][apple]=so tasty' \ + -F 'data[fruit][kiwi]=a bit sour' \ + -F 'data[veggies][root][onion]=tear-jerking' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": { + "fruit": { + "apple": "so tasty", + "kiwi": "a bit sour" + }, + "veggies": { + "root": { + "onion": "tear-jerking" + } + } + } + } + + Example DELETE: + curl 'https:///api/v1/users//custom_data/fruit/kiwi' \ + -X DELETE \ + -F 'ns=com.my-organization.canvas-app' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": "a bit sour" + } + + Example {api:UsersController#get_custom_data GET} following the above DELETE: + curl 'https:///api/v1/users//custom_data' \ + -X GET \ + -F 'ns=com.my-organization.canvas-app' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": { + "fruit": { + "apple": "so tasty" + }, + "veggies": { + "root": { + "onion": "tear-jerking" + } + } + } + } + + Note that hashes left empty after a DELETE will get removed from the custom_data store. + For example, following the previous commands, if we delete /custom_data/veggies/root/onion, + then the entire /custom_data/veggies scope will be removed. + + Example DELETE that empties a parent scope: + curl 'https:///api/v1/users//custom_data/veggies/root/onion' \ + -X DELETE \ + -F 'ns=com.my-organization.canvas-app' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": "tear-jerking" + } + + Example {api:UsersController#get_custom_data GET} following the above DELETE: + curl 'https:///api/v1/users//custom_data' \ + -X GET \ + -F 'ns=com.my-organization.canvas-app' \ + -H 'Authorization: Bearer ' + + Response: + !!!javascript + { + "data": { + "fruit": { + "apple": "so tasty" + } + } + } + + On success, this endpoint returns an object containing the data that was deleted. + + Responds with status code 400 if the namespace parameter, +ns+, is missing or invalid, + or if the specified scope does not contain any data. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - user_id + """ID""" + path["user_id"] = user_id + + # REQUIRED - ns + """The namespace from which to delete the data. This should be something other + Canvas API apps aren't likely to use, such as a reverse DNS for your organization.""" + params["ns"] = ns + + self.logger.debug("DELETE /api/v1/users/{user_id}/custom_data with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/{user_id}/custom_data".format(**path), data=data, params=params, no_data=True) + + def list_course_nicknames(self): + """ + List course nicknames. + + Returns all course nicknames you have set. + """ + path = {} + data = {} + params = {} + + self.logger.debug("GET /api/v1/users/self/course_nicknames with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/course_nicknames".format(**path), data=data, params=params, all_pages=True) + + def get_course_nickname(self, course_id): + """ + Get course nickname. + + Returns the nickname for a specific course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("GET /api/v1/users/self/course_nicknames/{course_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("GET", "/api/v1/users/self/course_nicknames/{course_id}".format(**path), data=data, params=params, single_item=True) + + def set_course_nickname(self, nickname, course_id): + """ + Set course nickname. + + Set a nickname for the given course. This will replace the course's name + in output of API calls you make subsequently, as well as in selected + places in the Canvas web user interface. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + # REQUIRED - nickname + """The nickname to set. It must be non-empty and shorter than 60 characters.""" + data["nickname"] = nickname + + self.logger.debug("PUT /api/v1/users/self/course_nicknames/{course_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("PUT", "/api/v1/users/self/course_nicknames/{course_id}".format(**path), data=data, params=params, single_item=True) + + def remove_course_nickname(self, course_id): + """ + Remove course nickname. + + Remove the nickname for the given course. + Subsequent course API calls will return the actual name for the course. + """ + path = {} + data = {} + params = {} + + # REQUIRED - PATH - course_id + """ID""" + path["course_id"] = course_id + + self.logger.debug("DELETE /api/v1/users/self/course_nicknames/{course_id} with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/self/course_nicknames/{course_id}".format(**path), data=data, params=params, single_item=True) + + def clear_course_nicknames(self): + """ + Clear course nicknames. + + Remove all stored course nicknames. + """ + path = {} + data = {} + params = {} + + self.logger.debug("DELETE /api/v1/users/self/course_nicknames with query params: {params} and form data: {data}".format(params=params, data=data, **path)) + return self.generic_request("DELETE", "/api/v1/users/self/course_nicknames".format(**path), data=data, params=params, no_data=True) + + +class Profile(BaseModel): + """Profile Model. + Profile details for a Canvas user.""" + + def __init__(self, bio=None, login_id=None, sortable_name=None, name=None, short_name=None, title=None, locale=None, sis_user_id=None, time_zone=None, avatar_url=None, primary_email=None, calendar=None, sis_login_id=None, id=None): + """Init method for Profile class.""" + self._bio = bio + self._login_id = login_id + self._sortable_name = sortable_name + self._name = name + self._short_name = short_name + self._title = title + self._locale = locale + self._sis_user_id = sis_user_id + self._time_zone = time_zone + self._avatar_url = avatar_url + self._primary_email = primary_email + self._calendar = calendar + self._sis_login_id = sis_login_id + self._id = id + + self.logger = logging.getLogger('pycanvas.Profile') + + @property + def bio(self): + """bio.""" + return self._bio + + @bio.setter + def bio(self, value): + """Setter for bio property.""" + self.logger.warn("Setting values on bio will NOT update the remote Canvas instance.") + self._bio = value + + @property + def login_id(self): + """sample_user@example.com.""" + return self._login_id + + @login_id.setter + def login_id(self, value): + """Setter for login_id property.""" + self.logger.warn("Setting values on login_id will NOT update the remote Canvas instance.") + self._login_id = value + + @property + def sortable_name(self): + """user, sample.""" + return self._sortable_name + + @sortable_name.setter + def sortable_name(self, value): + """Setter for sortable_name property.""" + self.logger.warn("Setting values on sortable_name will NOT update the remote Canvas instance.") + self._sortable_name = value + + @property + def name(self): + """Sample User.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def short_name(self): + """Sample User.""" + return self._short_name + + @short_name.setter + def short_name(self, value): + """Setter for short_name property.""" + self.logger.warn("Setting values on short_name will NOT update the remote Canvas instance.") + self._short_name = value + + @property + def title(self): + """title.""" + return self._title + + @title.setter + def title(self, value): + """Setter for title property.""" + self.logger.warn("Setting values on title will NOT update the remote Canvas instance.") + self._title = value + + @property + def locale(self): + """The users locale.""" + return self._locale + + @locale.setter + def locale(self, value): + """Setter for locale property.""" + self.logger.warn("Setting values on locale will NOT update the remote Canvas instance.") + self._locale = value + + @property + def sis_user_id(self): + """sis1.""" + return self._sis_user_id + + @sis_user_id.setter + def sis_user_id(self, value): + """Setter for sis_user_id property.""" + self.logger.warn("Setting values on sis_user_id will NOT update the remote Canvas instance.") + self._sis_user_id = value + + @property + def time_zone(self): + """Optional: This field is only returned in certain API calls, and will return the IANA time zone name of the user's preferred timezone.""" + return self._time_zone + + @time_zone.setter + def time_zone(self, value): + """Setter for time_zone property.""" + self.logger.warn("Setting values on time_zone will NOT update the remote Canvas instance.") + self._time_zone = value + + @property + def avatar_url(self): + """The avatar_url can change over time, so we recommend not caching it for more than a few hours.""" + return self._avatar_url + + @avatar_url.setter + def avatar_url(self, value): + """Setter for avatar_url property.""" + self.logger.warn("Setting values on avatar_url will NOT update the remote Canvas instance.") + self._avatar_url = value + + @property + def primary_email(self): + """sample_user@example.com.""" + return self._primary_email + + @primary_email.setter + def primary_email(self, value): + """Setter for primary_email property.""" + self.logger.warn("Setting values on primary_email will NOT update the remote Canvas instance.") + self._primary_email = value + + @property + def calendar(self): + """calendar.""" + return self._calendar + + @calendar.setter + def calendar(self, value): + """Setter for calendar property.""" + self.logger.warn("Setting values on calendar will NOT update the remote Canvas instance.") + self._calendar = value + + @property + def sis_login_id(self): + """sis1-login.""" + return self._sis_login_id + + @sis_login_id.setter + def sis_login_id(self, value): + """Setter for sis_login_id property.""" + self.logger.warn("Setting values on sis_login_id will NOT update the remote Canvas instance.") + self._sis_login_id = value + + @property + def id(self): + """The ID of the user.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Coursenickname(BaseModel): + """Coursenickname Model.""" + + def __init__(self, course_id=None, nickname=None, name=None): + """Init method for Coursenickname class.""" + self._course_id = course_id + self._nickname = nickname + self._name = name + + self.logger = logging.getLogger('pycanvas.Coursenickname') + + @property + def course_id(self): + """the ID of the course.""" + return self._course_id + + @course_id.setter + def course_id(self, value): + """Setter for course_id property.""" + self.logger.warn("Setting values on course_id will NOT update the remote Canvas instance.") + self._course_id = value + + @property + def nickname(self): + """the calling user's nickname for the course.""" + return self._nickname + + @nickname.setter + def nickname(self, value): + """Setter for nickname property.""" + self.logger.warn("Setting values on nickname will NOT update the remote Canvas instance.") + self._nickname = value + + @property + def name(self): + """the actual name of the course.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + +class Pageview(BaseModel): + """Pageview Model. + The record of a user page view access in Canvas""" + + def __init__(self, id, app_name=None, links=None, url=None, created_at=None, contributed=None, interaction_seconds=None, context_type=None, controller=None, user_request=None, http_method=None, user_agent=None, action=None, remote_ip=None, participated=None, asset_type=None, render_time=None): + """Init method for Pageview class.""" + self._app_name = app_name + self._links = links + self._url = url + self._created_at = created_at + self._contributed = contributed + self._interaction_seconds = interaction_seconds + self._id = id + self._context_type = context_type + self._controller = controller + self._user_request = user_request + self._http_method = http_method + self._user_agent = user_agent + self._action = action + self._remote_ip = remote_ip + self._participated = participated + self._asset_type = asset_type + self._render_time = render_time + + self.logger = logging.getLogger('pycanvas.Pageview') + + @property + def app_name(self): + """If the request is from an API request, the app that generated the access token.""" + return self._app_name + + @app_name.setter + def app_name(self, value): + """Setter for app_name property.""" + self.logger.warn("Setting values on app_name will NOT update the remote Canvas instance.") + self._app_name = value + + @property + def links(self): + """The page view links to define the relationships.""" + return self._links + + @links.setter + def links(self, value): + """Setter for links property.""" + self.logger.warn("Setting values on links will NOT update the remote Canvas instance.") + self._links = value + + @property + def url(self): + """The URL requested.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def created_at(self): + """When the request was made.""" + return self._created_at + + @created_at.setter + def created_at(self, value): + """Setter for created_at property.""" + self.logger.warn("Setting values on created_at will NOT update the remote Canvas instance.") + self._created_at = value + + @property + def contributed(self): + """This field is deprecated, and will always be false.""" + return self._contributed + + @contributed.setter + def contributed(self, value): + """Setter for contributed property.""" + self.logger.warn("Setting values on contributed will NOT update the remote Canvas instance.") + self._contributed = value + + @property + def interaction_seconds(self): + """An approximation of how long the user spent on the page, in seconds.""" + return self._interaction_seconds + + @interaction_seconds.setter + def interaction_seconds(self, value): + """Setter for interaction_seconds property.""" + self.logger.warn("Setting values on interaction_seconds will NOT update the remote Canvas instance.") + self._interaction_seconds = value + + @property + def id(self): + """A UUID representing the page view. This is also the unique request id.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def context_type(self): + """The type of context for the request.""" + return self._context_type + + @context_type.setter + def context_type(self, value): + """Setter for context_type property.""" + self.logger.warn("Setting values on context_type will NOT update the remote Canvas instance.") + self._context_type = value + + @property + def controller(self): + """The rails controller that handled the request.""" + return self._controller + + @controller.setter + def controller(self, value): + """Setter for controller property.""" + self.logger.warn("Setting values on controller will NOT update the remote Canvas instance.") + self._controller = value + + @property + def user_request(self): + """A flag indicating whether the request was user-initiated, or automatic (such as an AJAX call).""" + return self._user_request + + @user_request.setter + def user_request(self, value): + """Setter for user_request property.""" + self.logger.warn("Setting values on user_request will NOT update the remote Canvas instance.") + self._user_request = value + + @property + def http_method(self): + """The HTTP method such as GET or POST.""" + return self._http_method + + @http_method.setter + def http_method(self, value): + """Setter for http_method property.""" + self.logger.warn("Setting values on http_method will NOT update the remote Canvas instance.") + self._http_method = value + + @property + def user_agent(self): + """The user-agent of the browser or program that made the request.""" + return self._user_agent + + @user_agent.setter + def user_agent(self, value): + """Setter for user_agent property.""" + self.logger.warn("Setting values on user_agent will NOT update the remote Canvas instance.") + self._user_agent = value + + @property + def action(self): + """The rails action that handled the request.""" + return self._action + + @action.setter + def action(self, value): + """Setter for action property.""" + self.logger.warn("Setting values on action will NOT update the remote Canvas instance.") + self._action = value + + @property + def remote_ip(self): + """The origin IP address of the request.""" + return self._remote_ip + + @remote_ip.setter + def remote_ip(self, value): + """Setter for remote_ip property.""" + self.logger.warn("Setting values on remote_ip will NOT update the remote Canvas instance.") + self._remote_ip = value + + @property + def participated(self): + """True if the request counted as participating, such as submitting homework.""" + return self._participated + + @participated.setter + def participated(self, value): + """Setter for participated property.""" + self.logger.warn("Setting values on participated will NOT update the remote Canvas instance.") + self._participated = value + + @property + def asset_type(self): + """The type of asset in the context for the request, if any.""" + return self._asset_type + + @asset_type.setter + def asset_type(self, value): + """Setter for asset_type property.""" + self.logger.warn("Setting values on asset_type will NOT update the remote Canvas instance.") + self._asset_type = value + + @property + def render_time(self): + """How long the response took to render, in seconds.""" + return self._render_time + + @render_time.setter + def render_time(self, value): + """Setter for render_time property.""" + self.logger.warn("Setting values on render_time will NOT update the remote Canvas instance.") + self._render_time = value + + +class Pageviewlinks(BaseModel): + """Pageviewlinks Model. + The links of a page view access in Canvas""" + + def __init__(self, account=None, real_user=None, user=None, context=None, asset=None): + """Init method for Pageviewlinks class.""" + self._account = account + self._real_user = real_user + self._user = user + self._context = context + self._asset = asset + + self.logger = logging.getLogger('pycanvas.Pageviewlinks') + + @property + def account(self): + """The ID of the account context for this page view.""" + return self._account + + @account.setter + def account(self, value): + """Setter for account property.""" + self.logger.warn("Setting values on account will NOT update the remote Canvas instance.") + self._account = value + + @property + def real_user(self): + """The ID of the actual user who made this request, if the request was made by a user who was masquerading.""" + return self._real_user + + @real_user.setter + def real_user(self, value): + """Setter for real_user property.""" + self.logger.warn("Setting values on real_user will NOT update the remote Canvas instance.") + self._real_user = value + + @property + def user(self): + """The ID of the user for this page view.""" + return self._user + + @user.setter + def user(self, value): + """Setter for user property.""" + self.logger.warn("Setting values on user will NOT update the remote Canvas instance.") + self._user = value + + @property + def context(self): + """The ID of the context for the request (course id if context_type is Course, etc).""" + return self._context + + @context.setter + def context(self, value): + """Setter for context property.""" + self.logger.warn("Setting values on context will NOT update the remote Canvas instance.") + self._context = value + + @property + def asset(self): + """The ID of the asset for the request, if any.""" + return self._asset + + @asset.setter + def asset(self, value): + """Setter for asset property.""" + self.logger.warn("Setting values on asset will NOT update the remote Canvas instance.") + self._asset = value + + +class User(BaseModel): + """User Model. + A Canvas user, e.g. a student, teacher, administrator, observer, etc.""" + + def __init__(self, id, integration_id=None, login_id=None, sortable_name=None, name=None, short_name=None, bio=None, locale=None, sis_user_id=None, time_zone=None, email=None, sis_import_id=None, avatar_url=None, last_login=None, enrollments=None, sis_login_id=None): + """Init method for User class.""" + self._integration_id = integration_id + self._login_id = login_id + self._sortable_name = sortable_name + self._name = name + self._short_name = short_name + self._bio = bio + self._locale = locale + self._sis_user_id = sis_user_id + self._time_zone = time_zone + self._email = email + self._sis_import_id = sis_import_id + self._avatar_url = avatar_url + self._last_login = last_login + self._enrollments = enrollments + self._sis_login_id = sis_login_id + self._id = id + + self.logger = logging.getLogger('pycanvas.User') + + @property + def integration_id(self): + """The integration_id associated with the user. This field is only included if the user came from a SIS import and has permissions to view SIS information.""" + return self._integration_id + + @integration_id.setter + def integration_id(self, value): + """Setter for integration_id property.""" + self.logger.warn("Setting values on integration_id will NOT update the remote Canvas instance.") + self._integration_id = value + + @property + def login_id(self): + """The unique login id for the user. This is what the user uses to log in to Canvas.""" + return self._login_id + + @login_id.setter + def login_id(self, value): + """Setter for login_id property.""" + self.logger.warn("Setting values on login_id will NOT update the remote Canvas instance.") + self._login_id = value + + @property + def sortable_name(self): + """The name of the user that is should be used for sorting groups of users, such as in the gradebook.""" + return self._sortable_name + + @sortable_name.setter + def sortable_name(self, value): + """Setter for sortable_name property.""" + self.logger.warn("Setting values on sortable_name will NOT update the remote Canvas instance.") + self._sortable_name = value + + @property + def name(self): + """The name of the user.""" + return self._name + + @name.setter + def name(self, value): + """Setter for name property.""" + self.logger.warn("Setting values on name will NOT update the remote Canvas instance.") + self._name = value + + @property + def short_name(self): + """A short name the user has selected, for use in conversations or other less formal places through the site.""" + return self._short_name + + @short_name.setter + def short_name(self, value): + """Setter for short_name property.""" + self.logger.warn("Setting values on short_name will NOT update the remote Canvas instance.") + self._short_name = value + + @property + def bio(self): + """Optional: The user's bio.""" + return self._bio + + @bio.setter + def bio(self, value): + """Setter for bio property.""" + self.logger.warn("Setting values on bio will NOT update the remote Canvas instance.") + self._bio = value + + @property + def locale(self): + """Optional: This field can be requested with certain API calls, and will return the users locale in RFC 5646 format.""" + return self._locale + + @locale.setter + def locale(self, value): + """Setter for locale property.""" + self.logger.warn("Setting values on locale will NOT update the remote Canvas instance.") + self._locale = value + + @property + def sis_user_id(self): + """The SIS ID associated with the user. This field is only included if the user came from a SIS import and has permissions to view SIS information.""" + return self._sis_user_id + + @sis_user_id.setter + def sis_user_id(self, value): + """Setter for sis_user_id property.""" + self.logger.warn("Setting values on sis_user_id will NOT update the remote Canvas instance.") + self._sis_user_id = value + + @property + def time_zone(self): + """Optional: This field is only returned in certain API calls, and will return the IANA time zone name of the user's preferred timezone.""" + return self._time_zone + + @time_zone.setter + def time_zone(self, value): + """Setter for time_zone property.""" + self.logger.warn("Setting values on time_zone will NOT update the remote Canvas instance.") + self._time_zone = value + + @property + def email(self): + """Optional: This field can be requested with certain API calls, and will return the users primary email address.""" + return self._email + + @email.setter + def email(self, value): + """Setter for email property.""" + self.logger.warn("Setting values on email will NOT update the remote Canvas instance.") + self._email = value + + @property + def sis_import_id(self): + """The id of the SIS import. This field is only included if the user came from a SIS import and has permissions to manage SIS information.""" + return self._sis_import_id + + @sis_import_id.setter + def sis_import_id(self, value): + """Setter for sis_import_id property.""" + self.logger.warn("Setting values on sis_import_id will NOT update the remote Canvas instance.") + self._sis_import_id = value + + @property + def avatar_url(self): + """If avatars are enabled, this field will be included and contain a url to retrieve the user's avatar.""" + return self._avatar_url + + @avatar_url.setter + def avatar_url(self, value): + """Setter for avatar_url property.""" + self.logger.warn("Setting values on avatar_url will NOT update the remote Canvas instance.") + self._avatar_url = value + + @property + def last_login(self): + """Optional: This field is only returned in certain API calls, and will return a timestamp representing the last time the user logged in to canvas.""" + return self._last_login + + @last_login.setter + def last_login(self, value): + """Setter for last_login property.""" + self.logger.warn("Setting values on last_login will NOT update the remote Canvas instance.") + self._last_login = value + + @property + def enrollments(self): + """Optional: This field can be requested with certain API calls, and will return a list of the users active enrollments. See the List enrollments API for more details about the format of these records.""" + return self._enrollments + + @enrollments.setter + def enrollments(self, value): + """Setter for enrollments property.""" + self.logger.warn("Setting values on enrollments will NOT update the remote Canvas instance.") + self._enrollments = value + + @property + def sis_login_id(self): + """DEPRECATED: The SIS login ID associated with the user. Please use the sis_user_id or login_id. This field will be removed in a future version of the API.""" + return self._sis_login_id + + @sis_login_id.setter + def sis_login_id(self, value): + """Setter for sis_login_id property.""" + self.logger.warn("Setting values on sis_login_id will NOT update the remote Canvas instance.") + self._sis_login_id = value + + @property + def id(self): + """The ID of the user.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + +class Userdisplay(BaseModel): + """Userdisplay Model. + This mini-object is used for secondary user responses, when we just want to provide enough information to display a user.""" + + def __init__(self, avatar_image_url=None, id=None, short_name=None, html_url=None): + """Init method for Userdisplay class.""" + self._avatar_image_url = avatar_image_url + self._id = id + self._short_name = short_name + self._html_url = html_url + + self.logger = logging.getLogger('pycanvas.Userdisplay') + + @property + def avatar_image_url(self): + """If avatars are enabled, this field will be included and contain a url to retrieve the user's avatar.""" + return self._avatar_image_url + + @avatar_image_url.setter + def avatar_image_url(self, value): + """Setter for avatar_image_url property.""" + self.logger.warn("Setting values on avatar_image_url will NOT update the remote Canvas instance.") + self._avatar_image_url = value + + @property + def id(self): + """The ID of the user.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def short_name(self): + """A short name the user has selected, for use in conversations or other less formal places through the site.""" + return self._short_name + + @short_name.setter + def short_name(self, value): + """Setter for short_name property.""" + self.logger.warn("Setting values on short_name will NOT update the remote Canvas instance.") + self._short_name = value + + @property + def html_url(self): + """URL to access user, either nested to a context or directly.""" + return self._html_url + + @html_url.setter + def html_url(self, value): + """Setter for html_url property.""" + self.logger.warn("Setting values on html_url will NOT update the remote Canvas instance.") + self._html_url = value + + +class Avatar(BaseModel): + """Avatar Model. + Possible avatar for a user.""" + + def __init__(self, type, url, token, display_name, content_type=None, filename=None, id=None, size=None): + """Init method for Avatar class.""" + self._display_name = display_name + self._url = url + self._content_type = content_type + self._filename = filename + self._token = token + self._type = type + self._id = id + self._size = size + + self.logger = logging.getLogger('pycanvas.Avatar') + + @property + def display_name(self): + """A textual description of the avatar record.""" + return self._display_name + + @display_name.setter + def display_name(self, value): + """Setter for display_name property.""" + self.logger.warn("Setting values on display_name will NOT update the remote Canvas instance.") + self._display_name = value + + @property + def url(self): + """The url of the avatar.""" + return self._url + + @url.setter + def url(self, value): + """Setter for url property.""" + self.logger.warn("Setting values on url will NOT update the remote Canvas instance.") + self._url = value + + @property + def content_type(self): + """['attachment' type only] the content-type of the attachment.""" + return self._content_type + + @content_type.setter + def content_type(self, value): + """Setter for content_type property.""" + self.logger.warn("Setting values on content_type will NOT update the remote Canvas instance.") + self._content_type = value + + @property + def filename(self): + """['attachment' type only] the filename of the attachment.""" + return self._filename + + @filename.setter + def filename(self, value): + """Setter for filename property.""" + self.logger.warn("Setting values on filename will NOT update the remote Canvas instance.") + self._filename = value + + @property + def token(self): + """A unique representation of the avatar record which can be used to set the avatar with the user update endpoint. Note: this is an internal representation and is subject to change without notice. It should be consumed with this api endpoint and used in the user update endpoint, and should not be constructed by the client.""" + return self._token + + @token.setter + def token(self, value): + """Setter for token property.""" + self.logger.warn("Setting values on token will NOT update the remote Canvas instance.") + self._token = value + + @property + def type(self): + """['gravatar'|'attachment'|'no_pic'] The type of avatar record, for categorization purposes.""" + return self._type + + @type.setter + def type(self, value): + """Setter for type property.""" + self.logger.warn("Setting values on type will NOT update the remote Canvas instance.") + self._type = value + + @property + def id(self): + """['attachment' type only] the internal id of the attachment.""" + return self._id + + @id.setter + def id(self, value): + """Setter for id property.""" + self.logger.warn("Setting values on id will NOT update the remote Canvas instance.") + self._id = value + + @property + def size(self): + """['attachment' type only] the size of the attachment.""" + return self._size + + @size.setter + def size(self, value): + """Setter for size property.""" + self.logger.warn("Setting values on size will NOT update the remote Canvas instance.") + self._size = value + diff --git a/venv/Lib/site-packages/pycanvas/tests/__init__.py b/venv/Lib/site-packages/pycanvas/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/venv/Lib/site-packages/pycanvas/tests/account_domain_lookups.py b/venv/Lib/site-packages/pycanvas/tests/account_domain_lookups.py new file mode 100644 index 00000000..4b6009dc --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/account_domain_lookups.py @@ -0,0 +1,21 @@ +"""AccountDomainLookups API Tests for Version 1.0. + +This is a testing template for the generated AccountDomainLookupsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.account_domain_lookups import AccountDomainLookupsAPI + + +class TestAccountDomainLookupsAPI(unittest.TestCase): + """Tests for the AccountDomainLookupsAPI.""" + + def setUp(self): + self.client = AccountDomainLookupsAPI(secrets.instance_address, secrets.access_token) + + def test_search_account_domains(self): + """Integration test for the AccountDomainLookupsAPI.search_account_domains method.""" + + r = self.client.search_account_domains(domain=None, latitude=None, longitude=None, name=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/account_notifications.py b/venv/Lib/site-packages/pycanvas/tests/account_notifications.py new file mode 100644 index 00000000..18a79113 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/account_notifications.py @@ -0,0 +1,50 @@ +"""AccountNotifications API Tests for Version 1.0. + +This is a testing template for the generated AccountNotificationsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.account_notifications import AccountNotificationsAPI +from pycanvas.apis.account_notifications import Accountnotification + + +class TestAccountNotificationsAPI(unittest.TestCase): + """Tests for the AccountNotificationsAPI.""" + + def setUp(self): + self.client = AccountNotificationsAPI(secrets.instance_address, secrets.access_token) + + def test_index_of_active_global_notification_for_user(self): + """Integration test for the AccountNotificationsAPI.index_of_active_global_notification_for_user method.""" + account_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.index_of_active_global_notification_for_user(user_id, account_id) + + def test_show_global_notification(self): + """Integration test for the AccountNotificationsAPI.show_global_notification method.""" + account_id = None # Change me!! + user_id = None # Change me!! + id = None # Change me!! + + r = self.client.show_global_notification(id, user_id, account_id) + + def test_close_notification_for_user(self): + """Integration test for the AccountNotificationsAPI.close_notification_for_user method.""" + account_id = None # Change me!! + user_id = None # Change me!! + id = None # Change me!! + + r = self.client.close_notification_for_user(id, user_id, account_id) + + def test_create_global_notification(self): + """Integration test for the AccountNotificationsAPI.create_global_notification method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_global_notification(self): + """Integration test for the AccountNotificationsAPI.update_global_notification method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/account_reports.py b/venv/Lib/site-packages/pycanvas/tests/account_reports.py new file mode 100644 index 00000000..c8532e65 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/account_reports.py @@ -0,0 +1,52 @@ +"""AccountReports API Tests for Version 1.0. + +This is a testing template for the generated AccountReportsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.account_reports import AccountReportsAPI +from pycanvas.apis.account_reports import Report +from pycanvas.apis.account_reports import Reportparameters + + +class TestAccountReportsAPI(unittest.TestCase): + """Tests for the AccountReportsAPI.""" + + def setUp(self): + self.client = AccountReportsAPI(secrets.instance_address, secrets.access_token) + + def test_list_available_reports(self): + """Integration test for the AccountReportsAPI.list_available_reports method.""" + account_id = None # Change me!! + + r = self.client.list_available_reports(account_id) + + def test_start_report(self): + """Integration test for the AccountReportsAPI.start_report method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_index_of_reports(self): + """Integration test for the AccountReportsAPI.index_of_reports method.""" + account_id = None # Change me!! + report = None # Change me!! + + r = self.client.index_of_reports(report, account_id) + + def test_status_of_report(self): + """Integration test for the AccountReportsAPI.status_of_report method.""" + account_id = None # Change me!! + report = None # Change me!! + id = None # Change me!! + + r = self.client.status_of_report(id, report, account_id) + + def test_delete_report(self): + """Integration test for the AccountReportsAPI.delete_report method.""" + account_id = None # Change me!! + report = None # Change me!! + id = None # Change me!! + + r = self.client.delete_report(id, report, account_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/accounts.py b/venv/Lib/site-packages/pycanvas/tests/accounts.py new file mode 100644 index 00000000..064f38aa --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/accounts.py @@ -0,0 +1,62 @@ +"""Accounts API Tests for Version 1.0. + +This is a testing template for the generated AccountsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.accounts import AccountsAPI +from pycanvas.apis.accounts import Account + + +class TestAccountsAPI(unittest.TestCase): + """Tests for the AccountsAPI.""" + + def setUp(self): + self.client = AccountsAPI(secrets.instance_address, secrets.access_token) + + def test_list_accounts(self): + """Integration test for the AccountsAPI.list_accounts method.""" + + r = self.client.list_accounts(include=None) + + def test_list_accounts_for_course_admins(self): + """Integration test for the AccountsAPI.list_accounts_for_course_admins method.""" + + r = self.client.list_accounts_for_course_admins() + + def test_get_single_account(self): + """Integration test for the AccountsAPI.get_single_account method.""" + id = None # Change me!! + + r = self.client.get_single_account(id) + + def test_get_sub_accounts_of_account(self): + """Integration test for the AccountsAPI.get_sub_accounts_of_account method.""" + account_id = None # Change me!! + + r = self.client.get_sub_accounts_of_account(account_id, recursive=None) + + def test_list_active_courses_in_account(self): + """Integration test for the AccountsAPI.list_active_courses_in_account method.""" + account_id = None # Change me!! + + r = self.client.list_active_courses_in_account(account_id, by_subaccounts=None, by_teachers=None, completed=None, enrollment_term_id=None, enrollment_type=None, hide_enrollmentless_courses=None, include=None, published=None, search_term=None, state=None, with_enrollments=None) + + def test_update_account(self): + """Integration test for the AccountsAPI.update_account method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_user_from_root_account(self): + """Integration test for the AccountsAPI.delete_user_from_root_account method.""" + account_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.delete_user_from_root_account(user_id, account_id) + + def test_create_new_sub_account(self): + """Integration test for the AccountsAPI.create_new_sub_account method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/admins.py b/venv/Lib/site-packages/pycanvas/tests/admins.py new file mode 100644 index 00000000..5c2af4ec --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/admins.py @@ -0,0 +1,35 @@ +"""Admins API Tests for Version 1.0. + +This is a testing template for the generated AdminsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.admins import AdminsAPI +from pycanvas.apis.admins import Admin + + +class TestAdminsAPI(unittest.TestCase): + """Tests for the AdminsAPI.""" + + def setUp(self): + self.client = AdminsAPI(secrets.instance_address, secrets.access_token) + + def test_make_account_admin(self): + """Integration test for the AdminsAPI.make_account_admin method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_remove_account_admin(self): + """Integration test for the AdminsAPI.remove_account_admin method.""" + account_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.remove_account_admin(user_id, account_id, role=None, role_id=None) + + def test_list_account_admins(self): + """Integration test for the AdminsAPI.list_account_admins method.""" + account_id = None # Change me!! + + r = self.client.list_account_admins(account_id, user_id=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/announcement_external_feeds.py b/venv/Lib/site-packages/pycanvas/tests/announcement_external_feeds.py new file mode 100644 index 00000000..c7f32cd1 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/announcement_external_feeds.py @@ -0,0 +1,53 @@ +"""AnnouncementExternalFeeds API Tests for Version 1.0. + +This is a testing template for the generated AnnouncementExternalFeedsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.announcement_external_feeds import AnnouncementExternalFeedsAPI +from pycanvas.apis.announcement_external_feeds import Externalfeed + + +class TestAnnouncementExternalFeedsAPI(unittest.TestCase): + """Tests for the AnnouncementExternalFeedsAPI.""" + + def setUp(self): + self.client = AnnouncementExternalFeedsAPI(secrets.instance_address, secrets.access_token) + + def test_list_external_feeds_courses(self): + """Integration test for the AnnouncementExternalFeedsAPI.list_external_feeds_courses method.""" + course_id = None # Change me!! + + r = self.client.list_external_feeds_courses(course_id) + + def test_list_external_feeds_groups(self): + """Integration test for the AnnouncementExternalFeedsAPI.list_external_feeds_groups method.""" + group_id = None # Change me!! + + r = self.client.list_external_feeds_groups(group_id) + + def test_create_external_feed_courses(self): + """Integration test for the AnnouncementExternalFeedsAPI.create_external_feed_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_external_feed_groups(self): + """Integration test for the AnnouncementExternalFeedsAPI.create_external_feed_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_external_feed_courses(self): + """Integration test for the AnnouncementExternalFeedsAPI.delete_external_feed_courses method.""" + course_id = None # Change me!! + external_feed_id = None # Change me!! + + r = self.client.delete_external_feed_courses(course_id, external_feed_id) + + def test_delete_external_feed_groups(self): + """Integration test for the AnnouncementExternalFeedsAPI.delete_external_feed_groups method.""" + group_id = None # Change me!! + external_feed_id = None # Change me!! + + r = self.client.delete_external_feed_groups(group_id, external_feed_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/appointment_groups.py b/venv/Lib/site-packages/pycanvas/tests/appointment_groups.py new file mode 100644 index 00000000..189573ed --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/appointment_groups.py @@ -0,0 +1,62 @@ +"""AppointmentGroups API Tests for Version 1.0. + +This is a testing template for the generated AppointmentGroupsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.appointment_groups import AppointmentGroupsAPI +from pycanvas.apis.appointment_groups import Appointmentgroup +from pycanvas.apis.appointment_groups import Appointment + + +class TestAppointmentGroupsAPI(unittest.TestCase): + """Tests for the AppointmentGroupsAPI.""" + + def setUp(self): + self.client = AppointmentGroupsAPI(secrets.instance_address, secrets.access_token) + + def test_list_appointment_groups(self): + """Integration test for the AppointmentGroupsAPI.list_appointment_groups method.""" + + r = self.client.list_appointment_groups(context_codes=None, include=None, include_past_appointments=None, scope=None) + + def test_create_appointment_group(self): + """Integration test for the AppointmentGroupsAPI.create_appointment_group method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_single_appointment_group(self): + """Integration test for the AppointmentGroupsAPI.get_single_appointment_group method.""" + id = None # Change me!! + + r = self.client.get_single_appointment_group(id, include=None) + + def test_update_appointment_group(self): + """Integration test for the AppointmentGroupsAPI.update_appointment_group method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_appointment_group(self): + """Integration test for the AppointmentGroupsAPI.delete_appointment_group method.""" + id = None # Change me!! + + r = self.client.delete_appointment_group(id, cancel_reason=None) + + def test_list_user_participants(self): + """Integration test for the AppointmentGroupsAPI.list_user_participants method.""" + id = None # Change me!! + + r = self.client.list_user_participants(id, registration_status=None) + + def test_list_student_group_participants(self): + """Integration test for the AppointmentGroupsAPI.list_student_group_participants method.""" + id = None # Change me!! + + r = self.client.list_student_group_participants(id, registration_status=None) + + def test_get_next_appointment(self): + """Integration test for the AppointmentGroupsAPI.get_next_appointment method.""" + + r = self.client.get_next_appointment(appointment_group_ids=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/assignment_groups.py b/venv/Lib/site-packages/pycanvas/tests/assignment_groups.py new file mode 100644 index 00000000..e3db33c4 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/assignment_groups.py @@ -0,0 +1,48 @@ +"""AssignmentGroups API Tests for Version 1.0. + +This is a testing template for the generated AssignmentGroupsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.assignment_groups import AssignmentGroupsAPI +from pycanvas.apis.assignment_groups import Gradingrules +from pycanvas.apis.assignment_groups import Assignmentgroup + + +class TestAssignmentGroupsAPI(unittest.TestCase): + """Tests for the AssignmentGroupsAPI.""" + + def setUp(self): + self.client = AssignmentGroupsAPI(secrets.instance_address, secrets.access_token) + + def test_list_assignment_groups(self): + """Integration test for the AssignmentGroupsAPI.list_assignment_groups method.""" + course_id = None # Change me!! + + r = self.client.list_assignment_groups(course_id, exclude_assignment_submission_types=None, grading_period_id=None, include=None, override_assignment_dates=None, scope_assignments_to_student=None) + + def test_get_assignment_group(self): + """Integration test for the AssignmentGroupsAPI.get_assignment_group method.""" + course_id = None # Change me!! + assignment_group_id = None # Change me!! + + r = self.client.get_assignment_group(course_id, assignment_group_id, grading_period_id=None, include=None, override_assignment_dates=None) + + def test_create_assignment_group(self): + """Integration test for the AssignmentGroupsAPI.create_assignment_group method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_edit_assignment_group(self): + """Integration test for the AssignmentGroupsAPI.edit_assignment_group method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_destroy_assignment_group(self): + """Integration test for the AssignmentGroupsAPI.destroy_assignment_group method.""" + course_id = None # Change me!! + assignment_group_id = None # Change me!! + + r = self.client.destroy_assignment_group(course_id, assignment_group_id, move_assignments_to=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/assignments.py b/venv/Lib/site-packages/pycanvas/tests/assignments.py new file mode 100644 index 00000000..bc365f2e --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/assignments.py @@ -0,0 +1,127 @@ +"""Assignments API Tests for Version 1.0. + +This is a testing template for the generated AssignmentsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.assignments import AssignmentsAPI +from pycanvas.apis.assignments import Turnitinsettings +from pycanvas.apis.assignments import Assignmentoverride +from pycanvas.apis.assignments import Externaltooltagattributes +from pycanvas.apis.assignments import Assignment +from pycanvas.apis.assignments import Needsgradingcount +from pycanvas.apis.assignments import Rubriccriteria +from pycanvas.apis.assignments import Assignmentdate +from pycanvas.apis.assignments import Rubricrating +from pycanvas.apis.assignments import Lockinfo + + +class TestAssignmentsAPI(unittest.TestCase): + """Tests for the AssignmentsAPI.""" + + def setUp(self): + self.client = AssignmentsAPI(secrets.instance_address, secrets.access_token) + + def test_delete_assignment(self): + """Integration test for the AssignmentsAPI.delete_assignment method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_assignment(id, course_id) + + def test_list_assignments(self): + """Integration test for the AssignmentsAPI.list_assignments method.""" + course_id = None # Change me!! + + r = self.client.list_assignments(course_id, assignment_ids=None, bucket=None, include=None, needs_grading_count_by_section=None, override_assignment_dates=None, search_term=None) + + def test_list_assignments_for_user(self): + """Integration test for the AssignmentsAPI.list_assignments_for_user method.""" + user_id = None # Change me!! + course_id = None # Change me!! + + r = self.client.list_assignments_for_user(user_id, course_id) + + def test_get_single_assignment(self): + """Integration test for the AssignmentsAPI.get_single_assignment method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_assignment(id, course_id, all_dates=None, include=None, needs_grading_count_by_section=None, override_assignment_dates=None) + + def test_create_assignment(self): + """Integration test for the AssignmentsAPI.create_assignment method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_edit_assignment(self): + """Integration test for the AssignmentsAPI.edit_assignment method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_assignment_overrides(self): + """Integration test for the AssignmentsAPI.list_assignment_overrides method.""" + course_id = None # Change me!! + assignment_id = None # Change me!! + + r = self.client.list_assignment_overrides(course_id, assignment_id) + + def test_get_single_assignment_override(self): + """Integration test for the AssignmentsAPI.get_single_assignment_override method.""" + course_id = None # Change me!! + assignment_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_assignment_override(id, course_id, assignment_id) + + def test_redirect_to_assignment_override_for_group(self): + """Integration test for the AssignmentsAPI.redirect_to_assignment_override_for_group method.""" + group_id = None # Change me!! + assignment_id = None # Change me!! + + r = self.client.redirect_to_assignment_override_for_group(group_id, assignment_id) + + def test_redirect_to_assignment_override_for_section(self): + """Integration test for the AssignmentsAPI.redirect_to_assignment_override_for_section method.""" + course_section_id = None # Change me!! + assignment_id = None # Change me!! + + r = self.client.redirect_to_assignment_override_for_section(assignment_id, course_section_id) + + def test_create_assignment_override(self): + """Integration test for the AssignmentsAPI.create_assignment_override method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_assignment_override(self): + """Integration test for the AssignmentsAPI.update_assignment_override method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_assignment_override(self): + """Integration test for the AssignmentsAPI.delete_assignment_override method.""" + course_id = None # Change me!! + assignment_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_assignment_override(id, course_id, assignment_id) + + def test_batch_retrieve_overrides_in_course(self): + """Integration test for the AssignmentsAPI.batch_retrieve_overrides_in_course method.""" + course_id = None # Change me!! + assignment_overrides[id] = None # Change me!! + assignment_overrides[assignment_id] = None # Change me!! + + r = self.client.batch_retrieve_overrides_in_course(course_id, assignment_overrides_id, assignment_overrides_assignment_id) + + def test_batch_create_overrides_in_course(self): + """Integration test for the AssignmentsAPI.batch_create_overrides_in_course method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_batch_update_overrides_in_course(self): + """Integration test for the AssignmentsAPI.batch_update_overrides_in_course method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/authentications_log.py b/venv/Lib/site-packages/pycanvas/tests/authentications_log.py new file mode 100644 index 00000000..34c02691 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/authentications_log.py @@ -0,0 +1,35 @@ +"""AuthenticationsLog API Tests for Version 1.0. + +This is a testing template for the generated AuthenticationsLogAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.authentications_log import AuthenticationsLogAPI +from pycanvas.apis.authentications_log import Authenticationevent + + +class TestAuthenticationsLogAPI(unittest.TestCase): + """Tests for the AuthenticationsLogAPI.""" + + def setUp(self): + self.client = AuthenticationsLogAPI(secrets.instance_address, secrets.access_token) + + def test_query_by_login(self): + """Integration test for the AuthenticationsLogAPI.query_by_login method.""" + login_id = None # Change me!! + + r = self.client.query_by_login(login_id, end_time=None, start_time=None) + + def test_query_by_account(self): + """Integration test for the AuthenticationsLogAPI.query_by_account method.""" + account_id = None # Change me!! + + r = self.client.query_by_account(account_id, end_time=None, start_time=None) + + def test_query_by_user(self): + """Integration test for the AuthenticationsLogAPI.query_by_user method.""" + user_id = None # Change me!! + + r = self.client.query_by_user(user_id, end_time=None, start_time=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/calendar_events.py b/venv/Lib/site-packages/pycanvas/tests/calendar_events.py new file mode 100644 index 00000000..3d9ecde9 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/calendar_events.py @@ -0,0 +1,77 @@ +"""CalendarEvents API Tests for Version 1.0. + +This is a testing template for the generated CalendarEventsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.calendar_events import CalendarEventsAPI +from pycanvas.apis.calendar_events import Calendarevent +from pycanvas.apis.calendar_events import Assignmentevent + + +class TestCalendarEventsAPI(unittest.TestCase): + """Tests for the CalendarEventsAPI.""" + + def setUp(self): + self.client = CalendarEventsAPI(secrets.instance_address, secrets.access_token) + + def test_list_calendar_events(self): + """Integration test for the CalendarEventsAPI.list_calendar_events method.""" + + r = self.client.list_calendar_events(all_events=None, context_codes=None, end_date=None, excludes=None, start_date=None, type=None, undated=None) + + def test_list_calendar_events_for_user(self): + """Integration test for the CalendarEventsAPI.list_calendar_events_for_user method.""" + user_id = None # Change me!! + + r = self.client.list_calendar_events_for_user(user_id, all_events=None, context_codes=None, end_date=None, excludes=None, start_date=None, type=None, undated=None) + + def test_create_calendar_event(self): + """Integration test for the CalendarEventsAPI.create_calendar_event method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_single_calendar_event_or_assignment(self): + """Integration test for the CalendarEventsAPI.get_single_calendar_event_or_assignment method.""" + id = None # Change me!! + + r = self.client.get_single_calendar_event_or_assignment(id) + + def test_reserve_time_slot(self): + """Integration test for the CalendarEventsAPI.reserve_time_slot method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_reserve_time_slot_participant_id(self): + """Integration test for the CalendarEventsAPI.reserve_time_slot_participant_id method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_calendar_event(self): + """Integration test for the CalendarEventsAPI.update_calendar_event method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_calendar_event(self): + """Integration test for the CalendarEventsAPI.delete_calendar_event method.""" + id = None # Change me!! + + r = self.client.delete_calendar_event(id, cancel_reason=None) + + def test_set_course_timetable(self): + """Integration test for the CalendarEventsAPI.set_course_timetable method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_course_timetable(self): + """Integration test for the CalendarEventsAPI.get_course_timetable method.""" + course_id = None # Change me!! + + r = self.client.get_course_timetable(course_id) + + def test_create_or_update_events_directly_for_course_timetable(self): + """Integration test for the CalendarEventsAPI.create_or_update_events_directly_for_course_timetable method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/collaborations.py b/venv/Lib/site-packages/pycanvas/tests/collaborations.py new file mode 100644 index 00000000..1aefa813 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/collaborations.py @@ -0,0 +1,36 @@ +"""Collaborations API Tests for Version 1.0. + +This is a testing template for the generated CollaborationsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.collaborations import CollaborationsAPI +from pycanvas.apis.collaborations import Collaborator +from pycanvas.apis.collaborations import Collaboration + + +class TestCollaborationsAPI(unittest.TestCase): + """Tests for the CollaborationsAPI.""" + + def setUp(self): + self.client = CollaborationsAPI(secrets.instance_address, secrets.access_token) + + def test_list_collaborations_courses(self): + """Integration test for the CollaborationsAPI.list_collaborations_courses method.""" + course_id = None # Change me!! + + r = self.client.list_collaborations_courses(course_id) + + def test_list_collaborations_groups(self): + """Integration test for the CollaborationsAPI.list_collaborations_groups method.""" + group_id = None # Change me!! + + r = self.client.list_collaborations_groups(group_id) + + def test_list_members_of_collaboration(self): + """Integration test for the CollaborationsAPI.list_members_of_collaboration method.""" + id = None # Change me!! + + r = self.client.list_members_of_collaboration(id, include=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/comm_messages.py b/venv/Lib/site-packages/pycanvas/tests/comm_messages.py new file mode 100644 index 00000000..c2f6bbd8 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/comm_messages.py @@ -0,0 +1,23 @@ +"""CommMessages API Tests for Version 1.0. + +This is a testing template for the generated CommMessagesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.comm_messages import CommMessagesAPI +from pycanvas.apis.comm_messages import Commmessage + + +class TestCommMessagesAPI(unittest.TestCase): + """Tests for the CommMessagesAPI.""" + + def setUp(self): + self.client = CommMessagesAPI(secrets.instance_address, secrets.access_token) + + def test_list_of_commmessages_for_user(self): + """Integration test for the CommMessagesAPI.list_of_commmessages_for_user method.""" + user_id = None # Change me!! + + r = self.client.list_of_commmessages_for_user(user_id, end_time=None, start_time=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/communication_channels.py b/venv/Lib/site-packages/pycanvas/tests/communication_channels.py new file mode 100644 index 00000000..fd2287e1 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/communication_channels.py @@ -0,0 +1,43 @@ +"""CommunicationChannels API Tests for Version 1.0. + +This is a testing template for the generated CommunicationChannelsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.communication_channels import CommunicationChannelsAPI +from pycanvas.apis.communication_channels import Communicationchannel + + +class TestCommunicationChannelsAPI(unittest.TestCase): + """Tests for the CommunicationChannelsAPI.""" + + def setUp(self): + self.client = CommunicationChannelsAPI(secrets.instance_address, secrets.access_token) + + def test_list_user_communication_channels(self): + """Integration test for the CommunicationChannelsAPI.list_user_communication_channels method.""" + user_id = None # Change me!! + + r = self.client.list_user_communication_channels(user_id) + + def test_create_communication_channel(self): + """Integration test for the CommunicationChannelsAPI.create_communication_channel method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_communication_channel_id(self): + """Integration test for the CommunicationChannelsAPI.delete_communication_channel_id method.""" + user_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_communication_channel_id(id, user_id) + + def test_delete_communication_channel_type(self): + """Integration test for the CommunicationChannelsAPI.delete_communication_channel_type method.""" + user_id = None # Change me!! + type = None # Change me!! + address = None # Change me!! + + r = self.client.delete_communication_channel_type(type, user_id, address) + diff --git a/venv/Lib/site-packages/pycanvas/tests/conferences.py b/venv/Lib/site-packages/pycanvas/tests/conferences.py new file mode 100644 index 00000000..f909ec63 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/conferences.py @@ -0,0 +1,30 @@ +"""Conferences API Tests for Version 1.0. + +This is a testing template for the generated ConferencesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.conferences import ConferencesAPI +from pycanvas.apis.conferences import Conference +from pycanvas.apis.conferences import Conferencerecording + + +class TestConferencesAPI(unittest.TestCase): + """Tests for the ConferencesAPI.""" + + def setUp(self): + self.client = ConferencesAPI(secrets.instance_address, secrets.access_token) + + def test_list_conferences_courses(self): + """Integration test for the ConferencesAPI.list_conferences_courses method.""" + course_id = None # Change me!! + + r = self.client.list_conferences_courses(course_id) + + def test_list_conferences_groups(self): + """Integration test for the ConferencesAPI.list_conferences_groups method.""" + group_id = None # Change me!! + + r = self.client.list_conferences_groups(group_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/content_exports.py b/venv/Lib/site-packages/pycanvas/tests/content_exports.py new file mode 100644 index 00000000..c4d7a81e --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/content_exports.py @@ -0,0 +1,71 @@ +"""ContentExports API Tests for Version 1.0. + +This is a testing template for the generated ContentExportsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.content_exports import ContentExportsAPI +from pycanvas.apis.content_exports import Contentexport + + +class TestContentExportsAPI(unittest.TestCase): + """Tests for the ContentExportsAPI.""" + + def setUp(self): + self.client = ContentExportsAPI(secrets.instance_address, secrets.access_token) + + def test_list_content_exports_courses(self): + """Integration test for the ContentExportsAPI.list_content_exports_courses method.""" + course_id = None # Change me!! + + r = self.client.list_content_exports_courses(course_id) + + def test_list_content_exports_groups(self): + """Integration test for the ContentExportsAPI.list_content_exports_groups method.""" + group_id = None # Change me!! + + r = self.client.list_content_exports_groups(group_id) + + def test_list_content_exports_users(self): + """Integration test for the ContentExportsAPI.list_content_exports_users method.""" + user_id = None # Change me!! + + r = self.client.list_content_exports_users(user_id) + + def test_show_content_export_courses(self): + """Integration test for the ContentExportsAPI.show_content_export_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.show_content_export_courses(id, course_id) + + def test_show_content_export_groups(self): + """Integration test for the ContentExportsAPI.show_content_export_groups method.""" + group_id = None # Change me!! + id = None # Change me!! + + r = self.client.show_content_export_groups(id, group_id) + + def test_show_content_export_users(self): + """Integration test for the ContentExportsAPI.show_content_export_users method.""" + user_id = None # Change me!! + id = None # Change me!! + + r = self.client.show_content_export_users(id, user_id) + + def test_export_content_courses(self): + """Integration test for the ContentExportsAPI.export_content_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_export_content_groups(self): + """Integration test for the ContentExportsAPI.export_content_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_export_content_users(self): + """Integration test for the ContentExportsAPI.export_content_users method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/content_migrations.py b/venv/Lib/site-packages/pycanvas/tests/content_migrations.py new file mode 100644 index 00000000..340c6040 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/content_migrations.py @@ -0,0 +1,215 @@ +"""ContentMigrations API Tests for Version 1.0. + +This is a testing template for the generated ContentMigrationsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.content_migrations import ContentMigrationsAPI +from pycanvas.apis.content_migrations import Contentmigration +from pycanvas.apis.content_migrations import Migrationissue +from pycanvas.apis.content_migrations import Migrator + + +class TestContentMigrationsAPI(unittest.TestCase): + """Tests for the ContentMigrationsAPI.""" + + def setUp(self): + self.client = ContentMigrationsAPI(secrets.instance_address, secrets.access_token) + + def test_list_migration_issues_accounts(self): + """Integration test for the ContentMigrationsAPI.list_migration_issues_accounts method.""" + account_id = None # Change me!! + content_migration_id = None # Change me!! + + r = self.client.list_migration_issues_accounts(account_id, content_migration_id) + + def test_list_migration_issues_courses(self): + """Integration test for the ContentMigrationsAPI.list_migration_issues_courses method.""" + course_id = None # Change me!! + content_migration_id = None # Change me!! + + r = self.client.list_migration_issues_courses(course_id, content_migration_id) + + def test_list_migration_issues_groups(self): + """Integration test for the ContentMigrationsAPI.list_migration_issues_groups method.""" + group_id = None # Change me!! + content_migration_id = None # Change me!! + + r = self.client.list_migration_issues_groups(group_id, content_migration_id) + + def test_list_migration_issues_users(self): + """Integration test for the ContentMigrationsAPI.list_migration_issues_users method.""" + user_id = None # Change me!! + content_migration_id = None # Change me!! + + r = self.client.list_migration_issues_users(user_id, content_migration_id) + + def test_get_migration_issue_accounts(self): + """Integration test for the ContentMigrationsAPI.get_migration_issue_accounts method.""" + account_id = None # Change me!! + content_migration_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_migration_issue_accounts(id, account_id, content_migration_id) + + def test_get_migration_issue_courses(self): + """Integration test for the ContentMigrationsAPI.get_migration_issue_courses method.""" + course_id = None # Change me!! + content_migration_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_migration_issue_courses(id, course_id, content_migration_id) + + def test_get_migration_issue_groups(self): + """Integration test for the ContentMigrationsAPI.get_migration_issue_groups method.""" + group_id = None # Change me!! + content_migration_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_migration_issue_groups(id, group_id, content_migration_id) + + def test_get_migration_issue_users(self): + """Integration test for the ContentMigrationsAPI.get_migration_issue_users method.""" + user_id = None # Change me!! + content_migration_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_migration_issue_users(id, user_id, content_migration_id) + + def test_update_migration_issue_accounts(self): + """Integration test for the ContentMigrationsAPI.update_migration_issue_accounts method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_migration_issue_courses(self): + """Integration test for the ContentMigrationsAPI.update_migration_issue_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_migration_issue_groups(self): + """Integration test for the ContentMigrationsAPI.update_migration_issue_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_migration_issue_users(self): + """Integration test for the ContentMigrationsAPI.update_migration_issue_users method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_content_migrations_accounts(self): + """Integration test for the ContentMigrationsAPI.list_content_migrations_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_content_migrations_accounts(account_id) + + def test_list_content_migrations_courses(self): + """Integration test for the ContentMigrationsAPI.list_content_migrations_courses method.""" + course_id = None # Change me!! + + r = self.client.list_content_migrations_courses(course_id) + + def test_list_content_migrations_groups(self): + """Integration test for the ContentMigrationsAPI.list_content_migrations_groups method.""" + group_id = None # Change me!! + + r = self.client.list_content_migrations_groups(group_id) + + def test_list_content_migrations_users(self): + """Integration test for the ContentMigrationsAPI.list_content_migrations_users method.""" + user_id = None # Change me!! + + r = self.client.list_content_migrations_users(user_id) + + def test_get_content_migration_accounts(self): + """Integration test for the ContentMigrationsAPI.get_content_migration_accounts method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_content_migration_accounts(id, account_id) + + def test_get_content_migration_courses(self): + """Integration test for the ContentMigrationsAPI.get_content_migration_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_content_migration_courses(id, course_id) + + def test_get_content_migration_groups(self): + """Integration test for the ContentMigrationsAPI.get_content_migration_groups method.""" + group_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_content_migration_groups(id, group_id) + + def test_get_content_migration_users(self): + """Integration test for the ContentMigrationsAPI.get_content_migration_users method.""" + user_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_content_migration_users(id, user_id) + + def test_create_content_migration_accounts(self): + """Integration test for the ContentMigrationsAPI.create_content_migration_accounts method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_content_migration_courses(self): + """Integration test for the ContentMigrationsAPI.create_content_migration_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_content_migration_groups(self): + """Integration test for the ContentMigrationsAPI.create_content_migration_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_content_migration_users(self): + """Integration test for the ContentMigrationsAPI.create_content_migration_users method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_content_migration_accounts(self): + """Integration test for the ContentMigrationsAPI.update_content_migration_accounts method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_content_migration_courses(self): + """Integration test for the ContentMigrationsAPI.update_content_migration_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_content_migration_groups(self): + """Integration test for the ContentMigrationsAPI.update_content_migration_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_content_migration_users(self): + """Integration test for the ContentMigrationsAPI.update_content_migration_users method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_migration_systems_accounts(self): + """Integration test for the ContentMigrationsAPI.list_migration_systems_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_migration_systems_accounts(account_id) + + def test_list_migration_systems_courses(self): + """Integration test for the ContentMigrationsAPI.list_migration_systems_courses method.""" + course_id = None # Change me!! + + r = self.client.list_migration_systems_courses(course_id) + + def test_list_migration_systems_groups(self): + """Integration test for the ContentMigrationsAPI.list_migration_systems_groups method.""" + group_id = None # Change me!! + + r = self.client.list_migration_systems_groups(group_id) + + def test_list_migration_systems_users(self): + """Integration test for the ContentMigrationsAPI.list_migration_systems_users method.""" + user_id = None # Change me!! + + r = self.client.list_migration_systems_users(user_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/conversations.py b/venv/Lib/site-packages/pycanvas/tests/conversations.py new file mode 100644 index 00000000..b5c5bcb2 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/conversations.py @@ -0,0 +1,84 @@ +"""Conversations API Tests for Version 1.0. + +This is a testing template for the generated ConversationsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.conversations import ConversationsAPI +from pycanvas.apis.conversations import Conversation + + +class TestConversationsAPI(unittest.TestCase): + """Tests for the ConversationsAPI.""" + + def setUp(self): + self.client = ConversationsAPI(secrets.instance_address, secrets.access_token) + + def test_list_conversations(self): + """Integration test for the ConversationsAPI.list_conversations method.""" + + r = self.client.list_conversations(filter=None, filter_mode=None, include=None, include_all_conversation_ids=None, interleave_submissions=None, scope=None) + + def test_create_conversation(self): + """Integration test for the ConversationsAPI.create_conversation method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_running_batches(self): + """Integration test for the ConversationsAPI.get_running_batches method.""" + + r = self.client.get_running_batches() + + def test_get_single_conversation(self): + """Integration test for the ConversationsAPI.get_single_conversation method.""" + id = None # Change me!! + + r = self.client.get_single_conversation(id, auto_mark_as_read=None, filter=None, filter_mode=None, interleave_submissions=None, scope=None) + + def test_edit_conversation(self): + """Integration test for the ConversationsAPI.edit_conversation method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_all_as_read(self): + """Integration test for the ConversationsAPI.mark_all_as_read method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_conversation(self): + """Integration test for the ConversationsAPI.delete_conversation method.""" + id = None # Change me!! + + r = self.client.delete_conversation(id) + + def test_add_recipients(self): + """Integration test for the ConversationsAPI.add_recipients method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_add_message(self): + """Integration test for the ConversationsAPI.add_message method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_message(self): + """Integration test for the ConversationsAPI.delete_message method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_batch_update_conversations(self): + """Integration test for the ConversationsAPI.batch_update_conversations method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_find_recipients(self): + """Integration test for the ConversationsAPI.find_recipients method.""" + + r = self.client.find_recipients() + + def test_unread_count(self): + """Integration test for the ConversationsAPI.unread_count method.""" + + r = self.client.unread_count() + diff --git a/venv/Lib/site-packages/pycanvas/tests/course_audit_log.py b/venv/Lib/site-packages/pycanvas/tests/course_audit_log.py new file mode 100644 index 00000000..030bf4ed --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/course_audit_log.py @@ -0,0 +1,26 @@ +"""CourseAuditLog API Tests for Version 1.0. + +This is a testing template for the generated CourseAuditLogAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.course_audit_log import CourseAuditLogAPI +from pycanvas.apis.course_audit_log import Createdeventdata +from pycanvas.apis.course_audit_log import Courseevent +from pycanvas.apis.course_audit_log import Courseeventlink +from pycanvas.apis.course_audit_log import Updatedeventdata + + +class TestCourseAuditLogAPI(unittest.TestCase): + """Tests for the CourseAuditLogAPI.""" + + def setUp(self): + self.client = CourseAuditLogAPI(secrets.instance_address, secrets.access_token) + + def test_query_by_course(self): + """Integration test for the CourseAuditLogAPI.query_by_course method.""" + course_id = None # Change me!! + + r = self.client.query_by_course(course_id, end_time=None, start_time=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/course_quiz_extensions.py b/venv/Lib/site-packages/pycanvas/tests/course_quiz_extensions.py new file mode 100644 index 00000000..c8c5adbf --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/course_quiz_extensions.py @@ -0,0 +1,22 @@ +"""CourseQuizExtensions API Tests for Version 1.0. + +This is a testing template for the generated CourseQuizExtensionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.course_quiz_extensions import CourseQuizExtensionsAPI +from pycanvas.apis.course_quiz_extensions import Coursequizextension + + +class TestCourseQuizExtensionsAPI(unittest.TestCase): + """Tests for the CourseQuizExtensionsAPI.""" + + def setUp(self): + self.client = CourseQuizExtensionsAPI(secrets.instance_address, secrets.access_token) + + def test_set_extensions_for_student_quiz_submissions(self): + """Integration test for the CourseQuizExtensionsAPI.set_extensions_for_student_quiz_submissions method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/courses.py b/venv/Lib/site-packages/pycanvas/tests/courses.py new file mode 100644 index 00000000..32970dcb --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/courses.py @@ -0,0 +1,165 @@ +"""Courses API Tests for Version 1.0. + +This is a testing template for the generated CoursesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.courses import CoursesAPI +from pycanvas.apis.courses import Course +from pycanvas.apis.courses import Term +from pycanvas.apis.courses import Courseprogress +from pycanvas.apis.courses import Calendarlink + + +class TestCoursesAPI(unittest.TestCase): + """Tests for the CoursesAPI.""" + + def setUp(self): + self.client = CoursesAPI(secrets.instance_address, secrets.access_token) + + def test_list_your_courses(self): + """Integration test for the CoursesAPI.list_your_courses method.""" + + r = self.client.list_your_courses(enrollment_role=None, enrollment_role_id=None, enrollment_state=None, enrollment_type=None, include=None, state=None) + + def test_list_courses_for_user(self): + """Integration test for the CoursesAPI.list_courses_for_user method.""" + user_id = None # Change me!! + + r = self.client.list_courses_for_user(user_id, enrollment_state=None, include=None, state=None) + + def test_create_new_course(self): + """Integration test for the CoursesAPI.create_new_course method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_upload_file(self): + """Integration test for the CoursesAPI.upload_file method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_students(self): + """Integration test for the CoursesAPI.list_students method.""" + course_id = None # Change me!! + + r = self.client.list_students(course_id) + + def test_list_users_in_course_users(self): + """Integration test for the CoursesAPI.list_users_in_course_users method.""" + course_id = None # Change me!! + + r = self.client.list_users_in_course_users(course_id, enrollment_role=None, enrollment_role_id=None, enrollment_state=None, enrollment_type=None, include=None, search_term=None, user_id=None, user_ids=None) + + def test_list_users_in_course_search_users(self): + """Integration test for the CoursesAPI.list_users_in_course_search_users method.""" + course_id = None # Change me!! + + r = self.client.list_users_in_course_search_users(course_id, enrollment_role=None, enrollment_role_id=None, enrollment_state=None, enrollment_type=None, include=None, search_term=None, user_id=None, user_ids=None) + + def test_list_recently_logged_in_students(self): + """Integration test for the CoursesAPI.list_recently_logged_in_students method.""" + course_id = None # Change me!! + + r = self.client.list_recently_logged_in_students(course_id) + + def test_get_single_user(self): + """Integration test for the CoursesAPI.get_single_user method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_user(id, course_id) + + def test_preview_processed_html(self): + """Integration test for the CoursesAPI.preview_processed_html method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_course_activity_stream(self): + """Integration test for the CoursesAPI.course_activity_stream method.""" + course_id = None # Change me!! + + r = self.client.course_activity_stream(course_id) + + def test_course_activity_stream_summary(self): + """Integration test for the CoursesAPI.course_activity_stream_summary method.""" + course_id = None # Change me!! + + r = self.client.course_activity_stream_summary(course_id) + + def test_course_todo_items(self): + """Integration test for the CoursesAPI.course_todo_items method.""" + course_id = None # Change me!! + + r = self.client.course_todo_items(course_id) + + def test_conclude_course(self): + """Integration test for the CoursesAPI.conclude_course method.""" + id = None # Change me!! + event = None # Change me!! + + r = self.client.conclude_course(id, event) + + def test_get_course_settings(self): + """Integration test for the CoursesAPI.get_course_settings method.""" + course_id = None # Change me!! + + r = self.client.get_course_settings(course_id) + + def test_update_course_settings(self): + """Integration test for the CoursesAPI.update_course_settings method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_single_course_courses(self): + """Integration test for the CoursesAPI.get_single_course_courses method.""" + id = None # Change me!! + + r = self.client.get_single_course_courses(id, include=None) + + def test_get_single_course_accounts(self): + """Integration test for the CoursesAPI.get_single_course_accounts method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_course_accounts(id, account_id, include=None) + + def test_update_course(self): + """Integration test for the CoursesAPI.update_course method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_courses(self): + """Integration test for the CoursesAPI.update_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_reset_course(self): + """Integration test for the CoursesAPI.reset_course method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_effective_due_dates(self): + """Integration test for the CoursesAPI.get_effective_due_dates method.""" + course_id = None # Change me!! + + r = self.client.get_effective_due_dates(course_id, assignment_ids=None) + + def test_permissions(self): + """Integration test for the CoursesAPI.permissions method.""" + course_id = None # Change me!! + + r = self.client.permissions(course_id, permissions=None) + + def test_get_course_copy_status(self): + """Integration test for the CoursesAPI.get_course_copy_status method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_course_copy_status(id, course_id) + + def test_copy_course_content(self): + """Integration test for the CoursesAPI.copy_course_content method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/custom_gradebook_columns.py b/venv/Lib/site-packages/pycanvas/tests/custom_gradebook_columns.py new file mode 100644 index 00000000..9bd24725 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/custom_gradebook_columns.py @@ -0,0 +1,58 @@ +"""CustomGradebookColumns API Tests for Version 1.0. + +This is a testing template for the generated CustomGradebookColumnsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.custom_gradebook_columns import CustomGradebookColumnsAPI +from pycanvas.apis.custom_gradebook_columns import Columndatum +from pycanvas.apis.custom_gradebook_columns import Customcolumn + + +class TestCustomGradebookColumnsAPI(unittest.TestCase): + """Tests for the CustomGradebookColumnsAPI.""" + + def setUp(self): + self.client = CustomGradebookColumnsAPI(secrets.instance_address, secrets.access_token) + + def test_list_custom_gradebook_columns(self): + """Integration test for the CustomGradebookColumnsAPI.list_custom_gradebook_columns method.""" + course_id = None # Change me!! + + r = self.client.list_custom_gradebook_columns(course_id, include_hidden=None) + + def test_create_custom_gradebook_column(self): + """Integration test for the CustomGradebookColumnsAPI.create_custom_gradebook_column method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_custom_gradebook_column(self): + """Integration test for the CustomGradebookColumnsAPI.update_custom_gradebook_column method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_custom_gradebook_column(self): + """Integration test for the CustomGradebookColumnsAPI.delete_custom_gradebook_column method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_custom_gradebook_column(id, course_id) + + def test_reorder_custom_columns(self): + """Integration test for the CustomGradebookColumnsAPI.reorder_custom_columns method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_entries_for_column(self): + """Integration test for the CustomGradebookColumnsAPI.list_entries_for_column method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.list_entries_for_column(id, course_id, include_hidden=None) + + def test_update_column_data(self): + """Integration test for the CustomGradebookColumnsAPI.update_column_data method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/discussion_topics.py b/venv/Lib/site-packages/pycanvas/tests/discussion_topics.py new file mode 100644 index 00000000..ba97ab84 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/discussion_topics.py @@ -0,0 +1,300 @@ +"""DiscussionTopics API Tests for Version 1.0. + +This is a testing template for the generated DiscussionTopicsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.discussion_topics import DiscussionTopicsAPI +from pycanvas.apis.discussion_topics import Discussiontopic +from pycanvas.apis.discussion_topics import Fileattachment + + +class TestDiscussionTopicsAPI(unittest.TestCase): + """Tests for the DiscussionTopicsAPI.""" + + def setUp(self): + self.client = DiscussionTopicsAPI(secrets.instance_address, secrets.access_token) + + def test_list_discussion_topics_courses(self): + """Integration test for the DiscussionTopicsAPI.list_discussion_topics_courses method.""" + course_id = None # Change me!! + + r = self.client.list_discussion_topics_courses(course_id, exclude_context_module_locked_topics=None, include=None, only_announcements=None, order_by=None, scope=None, search_term=None) + + def test_list_discussion_topics_groups(self): + """Integration test for the DiscussionTopicsAPI.list_discussion_topics_groups method.""" + group_id = None # Change me!! + + r = self.client.list_discussion_topics_groups(group_id, exclude_context_module_locked_topics=None, include=None, only_announcements=None, order_by=None, scope=None, search_term=None) + + def test_create_new_discussion_topic_courses(self): + """Integration test for the DiscussionTopicsAPI.create_new_discussion_topic_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_new_discussion_topic_groups(self): + """Integration test for the DiscussionTopicsAPI.create_new_discussion_topic_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_topic_courses(self): + """Integration test for the DiscussionTopicsAPI.update_topic_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_topic_groups(self): + """Integration test for the DiscussionTopicsAPI.update_topic_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_topic_courses(self): + """Integration test for the DiscussionTopicsAPI.delete_topic_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.delete_topic_courses(topic_id, course_id) + + def test_delete_topic_groups(self): + """Integration test for the DiscussionTopicsAPI.delete_topic_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.delete_topic_groups(group_id, topic_id) + + def test_reorder_pinned_topics_courses(self): + """Integration test for the DiscussionTopicsAPI.reorder_pinned_topics_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_reorder_pinned_topics_groups(self): + """Integration test for the DiscussionTopicsAPI.reorder_pinned_topics_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_entry_courses(self): + """Integration test for the DiscussionTopicsAPI.update_entry_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_entry_groups(self): + """Integration test for the DiscussionTopicsAPI.update_entry_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_entry_courses(self): + """Integration test for the DiscussionTopicsAPI.delete_entry_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_entry_courses(id, topic_id, course_id) + + def test_delete_entry_groups(self): + """Integration test for the DiscussionTopicsAPI.delete_entry_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_entry_groups(id, group_id, topic_id) + + def test_get_single_topic_courses(self): + """Integration test for the DiscussionTopicsAPI.get_single_topic_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.get_single_topic_courses(topic_id, course_id) + + def test_get_single_topic_groups(self): + """Integration test for the DiscussionTopicsAPI.get_single_topic_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.get_single_topic_groups(group_id, topic_id) + + def test_get_full_topic_courses(self): + """Integration test for the DiscussionTopicsAPI.get_full_topic_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.get_full_topic_courses(topic_id, course_id) + + def test_get_full_topic_groups(self): + """Integration test for the DiscussionTopicsAPI.get_full_topic_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.get_full_topic_groups(group_id, topic_id) + + def test_post_entry_courses(self): + """Integration test for the DiscussionTopicsAPI.post_entry_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_post_entry_groups(self): + """Integration test for the DiscussionTopicsAPI.post_entry_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_topic_entries_courses(self): + """Integration test for the DiscussionTopicsAPI.list_topic_entries_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.list_topic_entries_courses(topic_id, course_id) + + def test_list_topic_entries_groups(self): + """Integration test for the DiscussionTopicsAPI.list_topic_entries_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.list_topic_entries_groups(group_id, topic_id) + + def test_post_reply_courses(self): + """Integration test for the DiscussionTopicsAPI.post_reply_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_post_reply_groups(self): + """Integration test for the DiscussionTopicsAPI.post_reply_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_entry_replies_courses(self): + """Integration test for the DiscussionTopicsAPI.list_entry_replies_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + entry_id = None # Change me!! + + r = self.client.list_entry_replies_courses(topic_id, entry_id, course_id) + + def test_list_entry_replies_groups(self): + """Integration test for the DiscussionTopicsAPI.list_entry_replies_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + entry_id = None # Change me!! + + r = self.client.list_entry_replies_groups(group_id, topic_id, entry_id) + + def test_list_entries_courses(self): + """Integration test for the DiscussionTopicsAPI.list_entries_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.list_entries_courses(topic_id, course_id, ids=None) + + def test_list_entries_groups(self): + """Integration test for the DiscussionTopicsAPI.list_entries_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.list_entries_groups(group_id, topic_id, ids=None) + + def test_mark_topic_as_read_courses(self): + """Integration test for the DiscussionTopicsAPI.mark_topic_as_read_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_topic_as_read_groups(self): + """Integration test for the DiscussionTopicsAPI.mark_topic_as_read_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_topic_as_unread_courses(self): + """Integration test for the DiscussionTopicsAPI.mark_topic_as_unread_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.mark_topic_as_unread_courses(topic_id, course_id) + + def test_mark_topic_as_unread_groups(self): + """Integration test for the DiscussionTopicsAPI.mark_topic_as_unread_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.mark_topic_as_unread_groups(group_id, topic_id) + + def test_mark_all_entries_as_read_courses(self): + """Integration test for the DiscussionTopicsAPI.mark_all_entries_as_read_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_all_entries_as_read_groups(self): + """Integration test for the DiscussionTopicsAPI.mark_all_entries_as_read_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_all_entries_as_unread_courses(self): + """Integration test for the DiscussionTopicsAPI.mark_all_entries_as_unread_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.mark_all_entries_as_unread_courses(topic_id, course_id, forced_read_state=None) + + def test_mark_all_entries_as_unread_groups(self): + """Integration test for the DiscussionTopicsAPI.mark_all_entries_as_unread_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.mark_all_entries_as_unread_groups(group_id, topic_id, forced_read_state=None) + + def test_mark_entry_as_read_courses(self): + """Integration test for the DiscussionTopicsAPI.mark_entry_as_read_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_entry_as_read_groups(self): + """Integration test for the DiscussionTopicsAPI.mark_entry_as_read_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_entry_as_unread_courses(self): + """Integration test for the DiscussionTopicsAPI.mark_entry_as_unread_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + entry_id = None # Change me!! + + r = self.client.mark_entry_as_unread_courses(topic_id, entry_id, course_id, forced_read_state=None) + + def test_mark_entry_as_unread_groups(self): + """Integration test for the DiscussionTopicsAPI.mark_entry_as_unread_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + entry_id = None # Change me!! + + r = self.client.mark_entry_as_unread_groups(group_id, topic_id, entry_id, forced_read_state=None) + + def test_rate_entry_courses(self): + """Integration test for the DiscussionTopicsAPI.rate_entry_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_rate_entry_groups(self): + """Integration test for the DiscussionTopicsAPI.rate_entry_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_subscribe_to_topic_courses(self): + """Integration test for the DiscussionTopicsAPI.subscribe_to_topic_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_subscribe_to_topic_groups(self): + """Integration test for the DiscussionTopicsAPI.subscribe_to_topic_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_unsubscribe_from_topic_courses(self): + """Integration test for the DiscussionTopicsAPI.unsubscribe_from_topic_courses method.""" + course_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.unsubscribe_from_topic_courses(topic_id, course_id) + + def test_unsubscribe_from_topic_groups(self): + """Integration test for the DiscussionTopicsAPI.unsubscribe_from_topic_groups method.""" + group_id = None # Change me!! + topic_id = None # Change me!! + + r = self.client.unsubscribe_from_topic_groups(group_id, topic_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/document_previews.py b/venv/Lib/site-packages/pycanvas/tests/document_previews.py new file mode 100644 index 00000000..b7355b50 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/document_previews.py @@ -0,0 +1,16 @@ +"""DocumentPreviews API Tests for Version 1.0. + +This is a testing template for the generated DocumentPreviewsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.document_previews import DocumentPreviewsAPI + + +class TestDocumentPreviewsAPI(unittest.TestCase): + """Tests for the DocumentPreviewsAPI.""" + + def setUp(self): + self.client = DocumentPreviewsAPI(secrets.instance_address, secrets.access_token) + diff --git a/venv/Lib/site-packages/pycanvas/tests/enrollment_terms.py b/venv/Lib/site-packages/pycanvas/tests/enrollment_terms.py new file mode 100644 index 00000000..26f37843 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/enrollment_terms.py @@ -0,0 +1,40 @@ +"""EnrollmentTerms API Tests for Version 1.0. + +This is a testing template for the generated EnrollmentTermsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.enrollment_terms import EnrollmentTermsAPI +from pycanvas.apis.enrollment_terms import Enrollmentterm + + +class TestEnrollmentTermsAPI(unittest.TestCase): + """Tests for the EnrollmentTermsAPI.""" + + def setUp(self): + self.client = EnrollmentTermsAPI(secrets.instance_address, secrets.access_token) + + def test_create_enrollment_term(self): + """Integration test for the EnrollmentTermsAPI.create_enrollment_term method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_enrollment_term(self): + """Integration test for the EnrollmentTermsAPI.update_enrollment_term method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_enrollment_term(self): + """Integration test for the EnrollmentTermsAPI.delete_enrollment_term method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_enrollment_term(id, account_id) + + def test_list_enrollment_terms(self): + """Integration test for the EnrollmentTermsAPI.list_enrollment_terms method.""" + account_id = None # Change me!! + + r = self.client.list_enrollment_terms(account_id, workflow_state=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/enrollments.py b/venv/Lib/site-packages/pycanvas/tests/enrollments.py new file mode 100644 index 00000000..7622c8e0 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/enrollments.py @@ -0,0 +1,65 @@ +"""Enrollments API Tests for Version 1.0. + +This is a testing template for the generated EnrollmentsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.enrollments import EnrollmentsAPI +from pycanvas.apis.enrollments import Grade +from pycanvas.apis.enrollments import Enrollment + + +class TestEnrollmentsAPI(unittest.TestCase): + """Tests for the EnrollmentsAPI.""" + + def setUp(self): + self.client = EnrollmentsAPI(secrets.instance_address, secrets.access_token) + + def test_list_enrollments_courses(self): + """Integration test for the EnrollmentsAPI.list_enrollments_courses method.""" + course_id = None # Change me!! + + r = self.client.list_enrollments_courses(course_id, grading_period_id=None, include=None, role=None, sis_account_id=None, sis_course_id=None, sis_section_id=None, sis_user_id=None, state=None, type=None, user_id=None) + + def test_list_enrollments_sections(self): + """Integration test for the EnrollmentsAPI.list_enrollments_sections method.""" + section_id = None # Change me!! + + r = self.client.list_enrollments_sections(section_id, grading_period_id=None, include=None, role=None, sis_account_id=None, sis_course_id=None, sis_section_id=None, sis_user_id=None, state=None, type=None, user_id=None) + + def test_list_enrollments_users(self): + """Integration test for the EnrollmentsAPI.list_enrollments_users method.""" + user_id = None # Change me!! + + r = self.client.list_enrollments_users(user_id, grading_period_id=None, include=None, role=None, sis_account_id=None, sis_course_id=None, sis_section_id=None, sis_user_id=None, state=None, type=None) + + def test_enrollment_by_id(self): + """Integration test for the EnrollmentsAPI.enrollment_by_id method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.enrollment_by_id(id, account_id) + + def test_enroll_user_courses(self): + """Integration test for the EnrollmentsAPI.enroll_user_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_enroll_user_sections(self): + """Integration test for the EnrollmentsAPI.enroll_user_sections method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_conclude_deactivate_or_delete_enrollment(self): + """Integration test for the EnrollmentsAPI.conclude_deactivate_or_delete_enrollment method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.conclude_deactivate_or_delete_enrollment(id, course_id, task=None) + + def test_re_activate_enrollment(self): + """Integration test for the EnrollmentsAPI.re_activate_enrollment method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/external_tools.py b/venv/Lib/site-packages/pycanvas/tests/external_tools.py new file mode 100644 index 00000000..b85056e4 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/external_tools.py @@ -0,0 +1,94 @@ +"""ExternalTools API Tests for Version 1.0. + +This is a testing template for the generated ExternalToolsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.external_tools import ExternalToolsAPI + + +class TestExternalToolsAPI(unittest.TestCase): + """Tests for the ExternalToolsAPI.""" + + def setUp(self): + self.client = ExternalToolsAPI(secrets.instance_address, secrets.access_token) + + def test_list_external_tools_courses(self): + """Integration test for the ExternalToolsAPI.list_external_tools_courses method.""" + course_id = None # Change me!! + + r = self.client.list_external_tools_courses(course_id, include_parents=None, search_term=None, selectable=None) + + def test_list_external_tools_accounts(self): + """Integration test for the ExternalToolsAPI.list_external_tools_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_external_tools_accounts(account_id, include_parents=None, search_term=None, selectable=None) + + def test_list_external_tools_groups(self): + """Integration test for the ExternalToolsAPI.list_external_tools_groups method.""" + group_id = None # Change me!! + + r = self.client.list_external_tools_groups(group_id, include_parents=None, search_term=None, selectable=None) + + def test_get_sessionless_launch_url_for_external_tool_courses(self): + """Integration test for the ExternalToolsAPI.get_sessionless_launch_url_for_external_tool_courses method.""" + course_id = None # Change me!! + + r = self.client.get_sessionless_launch_url_for_external_tool_courses(course_id, assignment_id=None, id=None, launch_type=None, module_item_id=None, url=None) + + def test_get_sessionless_launch_url_for_external_tool_accounts(self): + """Integration test for the ExternalToolsAPI.get_sessionless_launch_url_for_external_tool_accounts method.""" + account_id = None # Change me!! + + r = self.client.get_sessionless_launch_url_for_external_tool_accounts(account_id, assignment_id=None, id=None, launch_type=None, module_item_id=None, url=None) + + def test_get_single_external_tool_courses(self): + """Integration test for the ExternalToolsAPI.get_single_external_tool_courses method.""" + course_id = None # Change me!! + external_tool_id = None # Change me!! + + r = self.client.get_single_external_tool_courses(course_id, external_tool_id) + + def test_get_single_external_tool_accounts(self): + """Integration test for the ExternalToolsAPI.get_single_external_tool_accounts method.""" + account_id = None # Change me!! + external_tool_id = None # Change me!! + + r = self.client.get_single_external_tool_accounts(account_id, external_tool_id) + + def test_create_external_tool_courses(self): + """Integration test for the ExternalToolsAPI.create_external_tool_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_external_tool_accounts(self): + """Integration test for the ExternalToolsAPI.create_external_tool_accounts method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_edit_external_tool_courses(self): + """Integration test for the ExternalToolsAPI.edit_external_tool_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_edit_external_tool_accounts(self): + """Integration test for the ExternalToolsAPI.edit_external_tool_accounts method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_external_tool_courses(self): + """Integration test for the ExternalToolsAPI.delete_external_tool_courses method.""" + course_id = None # Change me!! + external_tool_id = None # Change me!! + + r = self.client.delete_external_tool_courses(course_id, external_tool_id) + + def test_delete_external_tool_accounts(self): + """Integration test for the ExternalToolsAPI.delete_external_tool_accounts method.""" + account_id = None # Change me!! + external_tool_id = None # Change me!! + + r = self.client.delete_external_tool_accounts(account_id, external_tool_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/favorites.py b/venv/Lib/site-packages/pycanvas/tests/favorites.py new file mode 100644 index 00000000..1047d213 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/favorites.py @@ -0,0 +1,59 @@ +"""Favorites API Tests for Version 1.0. + +This is a testing template for the generated FavoritesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.favorites import FavoritesAPI +from pycanvas.apis.favorites import Favorite + + +class TestFavoritesAPI(unittest.TestCase): + """Tests for the FavoritesAPI.""" + + def setUp(self): + self.client = FavoritesAPI(secrets.instance_address, secrets.access_token) + + def test_list_favorite_courses(self): + """Integration test for the FavoritesAPI.list_favorite_courses method.""" + + r = self.client.list_favorite_courses() + + def test_list_favorite_groups(self): + """Integration test for the FavoritesAPI.list_favorite_groups method.""" + + r = self.client.list_favorite_groups() + + def test_add_course_to_favorites(self): + """Integration test for the FavoritesAPI.add_course_to_favorites method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_add_group_to_favorites(self): + """Integration test for the FavoritesAPI.add_group_to_favorites method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_remove_course_from_favorites(self): + """Integration test for the FavoritesAPI.remove_course_from_favorites method.""" + id = None # Change me!! + + r = self.client.remove_course_from_favorites(id) + + def test_remove_group_from_favorites(self): + """Integration test for the FavoritesAPI.remove_group_from_favorites method.""" + id = None # Change me!! + + r = self.client.remove_group_from_favorites(id) + + def test_reset_course_favorites(self): + """Integration test for the FavoritesAPI.reset_course_favorites method.""" + + r = self.client.reset_course_favorites() + + def test_reset_group_favorites(self): + """Integration test for the FavoritesAPI.reset_group_favorites method.""" + + r = self.client.reset_group_favorites() + diff --git a/venv/Lib/site-packages/pycanvas/tests/feature_flags.py b/venv/Lib/site-packages/pycanvas/tests/feature_flags.py new file mode 100644 index 00000000..ebc238fd --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/feature_flags.py @@ -0,0 +1,111 @@ +"""FeatureFlags API Tests for Version 1.0. + +This is a testing template for the generated FeatureFlagsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.feature_flags import FeatureFlagsAPI +from pycanvas.apis.feature_flags import Featureflag +from pycanvas.apis.feature_flags import Feature + + +class TestFeatureFlagsAPI(unittest.TestCase): + """Tests for the FeatureFlagsAPI.""" + + def setUp(self): + self.client = FeatureFlagsAPI(secrets.instance_address, secrets.access_token) + + def test_list_features_courses(self): + """Integration test for the FeatureFlagsAPI.list_features_courses method.""" + course_id = None # Change me!! + + r = self.client.list_features_courses(course_id) + + def test_list_features_accounts(self): + """Integration test for the FeatureFlagsAPI.list_features_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_features_accounts(account_id) + + def test_list_features_users(self): + """Integration test for the FeatureFlagsAPI.list_features_users method.""" + user_id = None # Change me!! + + r = self.client.list_features_users(user_id) + + def test_list_enabled_features_courses(self): + """Integration test for the FeatureFlagsAPI.list_enabled_features_courses method.""" + course_id = None # Change me!! + + r = self.client.list_enabled_features_courses(course_id) + + def test_list_enabled_features_accounts(self): + """Integration test for the FeatureFlagsAPI.list_enabled_features_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_enabled_features_accounts(account_id) + + def test_list_enabled_features_users(self): + """Integration test for the FeatureFlagsAPI.list_enabled_features_users method.""" + user_id = None # Change me!! + + r = self.client.list_enabled_features_users(user_id) + + def test_get_feature_flag_courses(self): + """Integration test for the FeatureFlagsAPI.get_feature_flag_courses method.""" + course_id = None # Change me!! + feature = None # Change me!! + + r = self.client.get_feature_flag_courses(feature, course_id) + + def test_get_feature_flag_accounts(self): + """Integration test for the FeatureFlagsAPI.get_feature_flag_accounts method.""" + account_id = None # Change me!! + feature = None # Change me!! + + r = self.client.get_feature_flag_accounts(feature, account_id) + + def test_get_feature_flag_users(self): + """Integration test for the FeatureFlagsAPI.get_feature_flag_users method.""" + user_id = None # Change me!! + feature = None # Change me!! + + r = self.client.get_feature_flag_users(user_id, feature) + + def test_set_feature_flag_courses(self): + """Integration test for the FeatureFlagsAPI.set_feature_flag_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_set_feature_flag_accounts(self): + """Integration test for the FeatureFlagsAPI.set_feature_flag_accounts method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_set_feature_flag_users(self): + """Integration test for the FeatureFlagsAPI.set_feature_flag_users method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_remove_feature_flag_courses(self): + """Integration test for the FeatureFlagsAPI.remove_feature_flag_courses method.""" + course_id = None # Change me!! + feature = None # Change me!! + + r = self.client.remove_feature_flag_courses(feature, course_id) + + def test_remove_feature_flag_accounts(self): + """Integration test for the FeatureFlagsAPI.remove_feature_flag_accounts method.""" + account_id = None # Change me!! + feature = None # Change me!! + + r = self.client.remove_feature_flag_accounts(feature, account_id) + + def test_remove_feature_flag_users(self): + """Integration test for the FeatureFlagsAPI.remove_feature_flag_users method.""" + user_id = None # Change me!! + feature = None # Change me!! + + r = self.client.remove_feature_flag_users(user_id, feature) + diff --git a/venv/Lib/site-packages/pycanvas/tests/files.py b/venv/Lib/site-packages/pycanvas/tests/files.py new file mode 100644 index 00000000..79d7f381 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/files.py @@ -0,0 +1,293 @@ +"""Files API Tests for Version 1.0. + +This is a testing template for the generated FilesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.files import FilesAPI +from pycanvas.apis.files import Folder +from pycanvas.apis.files import Usagerights +from pycanvas.apis.files import License +from pycanvas.apis.files import File + + +class TestFilesAPI(unittest.TestCase): + """Tests for the FilesAPI.""" + + def setUp(self): + self.client = FilesAPI(secrets.instance_address, secrets.access_token) + + def test_get_quota_information_courses(self): + """Integration test for the FilesAPI.get_quota_information_courses method.""" + course_id = None # Change me!! + + r = self.client.get_quota_information_courses(course_id) + + def test_get_quota_information_groups(self): + """Integration test for the FilesAPI.get_quota_information_groups method.""" + group_id = None # Change me!! + + r = self.client.get_quota_information_groups(group_id) + + def test_get_quota_information_users(self): + """Integration test for the FilesAPI.get_quota_information_users method.""" + user_id = None # Change me!! + + r = self.client.get_quota_information_users(user_id) + + def test_list_files_courses(self): + """Integration test for the FilesAPI.list_files_courses method.""" + course_id = None # Change me!! + + r = self.client.list_files_courses(course_id, content_types=None, include=None, only=None, order=None, search_term=None, sort=None) + + def test_list_files_users(self): + """Integration test for the FilesAPI.list_files_users method.""" + user_id = None # Change me!! + + r = self.client.list_files_users(user_id, content_types=None, include=None, only=None, order=None, search_term=None, sort=None) + + def test_list_files_groups(self): + """Integration test for the FilesAPI.list_files_groups method.""" + group_id = None # Change me!! + + r = self.client.list_files_groups(group_id, content_types=None, include=None, only=None, order=None, search_term=None, sort=None) + + def test_list_files_folders(self): + """Integration test for the FilesAPI.list_files_folders method.""" + id = None # Change me!! + + r = self.client.list_files_folders(id, content_types=None, include=None, only=None, order=None, search_term=None, sort=None) + + def test_get_public_inline_preview_url(self): + """Integration test for the FilesAPI.get_public_inline_preview_url method.""" + id = None # Change me!! + + r = self.client.get_public_inline_preview_url(id, submission_id=None) + + def test_get_file_files(self): + """Integration test for the FilesAPI.get_file_files method.""" + id = None # Change me!! + + r = self.client.get_file_files(id, include=None) + + def test_get_file_courses(self): + """Integration test for the FilesAPI.get_file_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_file_courses(id, course_id, include=None) + + def test_get_file_groups(self): + """Integration test for the FilesAPI.get_file_groups method.""" + group_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_file_groups(id, group_id, include=None) + + def test_get_file_users(self): + """Integration test for the FilesAPI.get_file_users method.""" + user_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_file_users(id, user_id, include=None) + + def test_update_file(self): + """Integration test for the FilesAPI.update_file method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_file(self): + """Integration test for the FilesAPI.delete_file method.""" + id = None # Change me!! + + r = self.client.delete_file(id) + + def test_list_folders(self): + """Integration test for the FilesAPI.list_folders method.""" + id = None # Change me!! + + r = self.client.list_folders(id) + + def test_list_all_folders_courses(self): + """Integration test for the FilesAPI.list_all_folders_courses method.""" + course_id = None # Change me!! + + r = self.client.list_all_folders_courses(course_id) + + def test_list_all_folders_users(self): + """Integration test for the FilesAPI.list_all_folders_users method.""" + user_id = None # Change me!! + + r = self.client.list_all_folders_users(user_id) + + def test_list_all_folders_groups(self): + """Integration test for the FilesAPI.list_all_folders_groups method.""" + group_id = None # Change me!! + + r = self.client.list_all_folders_groups(group_id) + + def test_resolve_path_courses_full_path(self): + """Integration test for the FilesAPI.resolve_path_courses_full_path method.""" + course_id = None # Change me!! + + r = self.client.resolve_path_courses_full_path(course_id) + + def test_resolve_path_courses(self): + """Integration test for the FilesAPI.resolve_path_courses method.""" + course_id = None # Change me!! + + r = self.client.resolve_path_courses(course_id) + + def test_resolve_path_users_full_path(self): + """Integration test for the FilesAPI.resolve_path_users_full_path method.""" + user_id = None # Change me!! + + r = self.client.resolve_path_users_full_path(user_id) + + def test_resolve_path_users(self): + """Integration test for the FilesAPI.resolve_path_users method.""" + user_id = None # Change me!! + + r = self.client.resolve_path_users(user_id) + + def test_resolve_path_groups_full_path(self): + """Integration test for the FilesAPI.resolve_path_groups_full_path method.""" + group_id = None # Change me!! + + r = self.client.resolve_path_groups_full_path(group_id) + + def test_resolve_path_groups(self): + """Integration test for the FilesAPI.resolve_path_groups method.""" + group_id = None # Change me!! + + r = self.client.resolve_path_groups(group_id) + + def test_get_folder_courses(self): + """Integration test for the FilesAPI.get_folder_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_folder_courses(id, course_id) + + def test_get_folder_users(self): + """Integration test for the FilesAPI.get_folder_users method.""" + user_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_folder_users(id, user_id) + + def test_get_folder_groups(self): + """Integration test for the FilesAPI.get_folder_groups method.""" + group_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_folder_groups(id, group_id) + + def test_get_folder_folders(self): + """Integration test for the FilesAPI.get_folder_folders method.""" + id = None # Change me!! + + r = self.client.get_folder_folders(id) + + def test_update_folder(self): + """Integration test for the FilesAPI.update_folder method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_folder_courses(self): + """Integration test for the FilesAPI.create_folder_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_folder_users(self): + """Integration test for the FilesAPI.create_folder_users method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_folder_groups(self): + """Integration test for the FilesAPI.create_folder_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_folder_folders(self): + """Integration test for the FilesAPI.create_folder_folders method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_folder(self): + """Integration test for the FilesAPI.delete_folder method.""" + id = None # Change me!! + + r = self.client.delete_folder(id, force=None) + + def test_upload_file(self): + """Integration test for the FilesAPI.upload_file method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_copy_file(self): + """Integration test for the FilesAPI.copy_file method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_copy_folder(self): + """Integration test for the FilesAPI.copy_folder method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_set_usage_rights_courses(self): + """Integration test for the FilesAPI.set_usage_rights_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_set_usage_rights_groups(self): + """Integration test for the FilesAPI.set_usage_rights_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_set_usage_rights_users(self): + """Integration test for the FilesAPI.set_usage_rights_users method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_remove_usage_rights_courses(self): + """Integration test for the FilesAPI.remove_usage_rights_courses method.""" + course_id = None # Change me!! + file_ids = None # Change me!! + + r = self.client.remove_usage_rights_courses(file_ids, course_id, folder_ids=None) + + def test_remove_usage_rights_groups(self): + """Integration test for the FilesAPI.remove_usage_rights_groups method.""" + group_id = None # Change me!! + file_ids = None # Change me!! + + r = self.client.remove_usage_rights_groups(group_id, file_ids, folder_ids=None) + + def test_remove_usage_rights_users(self): + """Integration test for the FilesAPI.remove_usage_rights_users method.""" + user_id = None # Change me!! + file_ids = None # Change me!! + + r = self.client.remove_usage_rights_users(user_id, file_ids, folder_ids=None) + + def test_list_licenses_courses(self): + """Integration test for the FilesAPI.list_licenses_courses method.""" + course_id = None # Change me!! + + r = self.client.list_licenses_courses(course_id) + + def test_list_licenses_groups(self): + """Integration test for the FilesAPI.list_licenses_groups method.""" + group_id = None # Change me!! + + r = self.client.list_licenses_groups(group_id) + + def test_list_licenses_users(self): + """Integration test for the FilesAPI.list_licenses_users method.""" + user_id = None # Change me!! + + r = self.client.list_licenses_users(user_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/grade_change_log.py b/venv/Lib/site-packages/pycanvas/tests/grade_change_log.py new file mode 100644 index 00000000..b7cf3103 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/grade_change_log.py @@ -0,0 +1,42 @@ +"""GradeChangeLog API Tests for Version 1.0. + +This is a testing template for the generated GradeChangeLogAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.grade_change_log import GradeChangeLogAPI +from pycanvas.apis.grade_change_log import Gradechangeevent +from pycanvas.apis.grade_change_log import Gradechangeeventlinks + + +class TestGradeChangeLogAPI(unittest.TestCase): + """Tests for the GradeChangeLogAPI.""" + + def setUp(self): + self.client = GradeChangeLogAPI(secrets.instance_address, secrets.access_token) + + def test_query_by_assignment(self): + """Integration test for the GradeChangeLogAPI.query_by_assignment method.""" + assignment_id = None # Change me!! + + r = self.client.query_by_assignment(assignment_id, end_time=None, start_time=None) + + def test_query_by_course(self): + """Integration test for the GradeChangeLogAPI.query_by_course method.""" + course_id = None # Change me!! + + r = self.client.query_by_course(course_id, end_time=None, start_time=None) + + def test_query_by_student(self): + """Integration test for the GradeChangeLogAPI.query_by_student method.""" + student_id = None # Change me!! + + r = self.client.query_by_student(student_id, end_time=None, start_time=None) + + def test_query_by_grader(self): + """Integration test for the GradeChangeLogAPI.query_by_grader method.""" + grader_id = None # Change me!! + + r = self.client.query_by_grader(grader_id, end_time=None, start_time=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/gradebook_history.py b/venv/Lib/site-packages/pycanvas/tests/gradebook_history.py new file mode 100644 index 00000000..205052e2 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/gradebook_history.py @@ -0,0 +1,48 @@ +"""GradebookHistory API Tests for Version 1.0. + +This is a testing template for the generated GradebookHistoryAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.gradebook_history import GradebookHistoryAPI +from pycanvas.apis.gradebook_history import Submissionversion +from pycanvas.apis.gradebook_history import Grader +from pycanvas.apis.gradebook_history import Day +from pycanvas.apis.gradebook_history import Submissionhistory + + +class TestGradebookHistoryAPI(unittest.TestCase): + """Tests for the GradebookHistoryAPI.""" + + def setUp(self): + self.client = GradebookHistoryAPI(secrets.instance_address, secrets.access_token) + + def test_days_in_gradebook_history_for_this_course(self): + """Integration test for the GradebookHistoryAPI.days_in_gradebook_history_for_this_course method.""" + course_id = None # Change me!! + + r = self.client.days_in_gradebook_history_for_this_course(course_id) + + def test_details_for_given_date_in_gradebook_history_for_this_course(self): + """Integration test for the GradebookHistoryAPI.details_for_given_date_in_gradebook_history_for_this_course method.""" + course_id = None # Change me!! + date = None # Change me!! + + r = self.client.details_for_given_date_in_gradebook_history_for_this_course(date, course_id) + + def test_lists_submissions(self): + """Integration test for the GradebookHistoryAPI.lists_submissions method.""" + course_id = None # Change me!! + date = None # Change me!! + grader_id = None # Change me!! + assignment_id = None # Change me!! + + r = self.client.lists_submissions(date, course_id, grader_id, assignment_id) + + def test_list_uncollated_submission_versions(self): + """Integration test for the GradebookHistoryAPI.list_uncollated_submission_versions method.""" + course_id = None # Change me!! + + r = self.client.list_uncollated_submission_versions(course_id, ascending=None, assignment_id=None, user_id=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/grading_periods.py b/venv/Lib/site-packages/pycanvas/tests/grading_periods.py new file mode 100644 index 00000000..cb870dd3 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/grading_periods.py @@ -0,0 +1,55 @@ +"""GradingPeriods API Tests for Version 1.0. + +This is a testing template for the generated GradingPeriodsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.grading_periods import GradingPeriodsAPI +from pycanvas.apis.grading_periods import Gradingperiod + + +class TestGradingPeriodsAPI(unittest.TestCase): + """Tests for the GradingPeriodsAPI.""" + + def setUp(self): + self.client = GradingPeriodsAPI(secrets.instance_address, secrets.access_token) + + def test_list_grading_periods_accounts(self): + """Integration test for the GradingPeriodsAPI.list_grading_periods_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_grading_periods_accounts(account_id) + + def test_list_grading_periods_courses(self): + """Integration test for the GradingPeriodsAPI.list_grading_periods_courses method.""" + course_id = None # Change me!! + + r = self.client.list_grading_periods_courses(course_id) + + def test_get_single_grading_period(self): + """Integration test for the GradingPeriodsAPI.get_single_grading_period method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_grading_period(id, course_id) + + def test_update_single_grading_period(self): + """Integration test for the GradingPeriodsAPI.update_single_grading_period method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_grading_period_courses(self): + """Integration test for the GradingPeriodsAPI.delete_grading_period_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_grading_period_courses(id, course_id) + + def test_delete_grading_period_accounts(self): + """Integration test for the GradingPeriodsAPI.delete_grading_period_accounts method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_grading_period_accounts(id, account_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/grading_standards.py b/venv/Lib/site-packages/pycanvas/tests/grading_standards.py new file mode 100644 index 00000000..81109e57 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/grading_standards.py @@ -0,0 +1,40 @@ +"""GradingStandards API Tests for Version 1.0. + +This is a testing template for the generated GradingStandardsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.grading_standards import GradingStandardsAPI +from pycanvas.apis.grading_standards import Gradingstandard +from pycanvas.apis.grading_standards import Gradingschemeentry + + +class TestGradingStandardsAPI(unittest.TestCase): + """Tests for the GradingStandardsAPI.""" + + def setUp(self): + self.client = GradingStandardsAPI(secrets.instance_address, secrets.access_token) + + def test_create_new_grading_standard_accounts(self): + """Integration test for the GradingStandardsAPI.create_new_grading_standard_accounts method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_new_grading_standard_courses(self): + """Integration test for the GradingStandardsAPI.create_new_grading_standard_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_grading_standards_available_in_context_courses(self): + """Integration test for the GradingStandardsAPI.list_grading_standards_available_in_context_courses method.""" + course_id = None # Change me!! + + r = self.client.list_grading_standards_available_in_context_courses(course_id) + + def test_list_grading_standards_available_in_context_accounts(self): + """Integration test for the GradingStandardsAPI.list_grading_standards_available_in_context_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_grading_standards_available_in_context_accounts(account_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/group_categories.py b/venv/Lib/site-packages/pycanvas/tests/group_categories.py new file mode 100644 index 00000000..e2fc48e6 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/group_categories.py @@ -0,0 +1,73 @@ +"""GroupCategories API Tests for Version 1.0. + +This is a testing template for the generated GroupCategoriesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.group_categories import GroupCategoriesAPI +from pycanvas.apis.group_categories import Groupcategory + + +class TestGroupCategoriesAPI(unittest.TestCase): + """Tests for the GroupCategoriesAPI.""" + + def setUp(self): + self.client = GroupCategoriesAPI(secrets.instance_address, secrets.access_token) + + def test_list_group_categories_for_context_accounts(self): + """Integration test for the GroupCategoriesAPI.list_group_categories_for_context_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_group_categories_for_context_accounts(account_id) + + def test_list_group_categories_for_context_courses(self): + """Integration test for the GroupCategoriesAPI.list_group_categories_for_context_courses method.""" + course_id = None # Change me!! + + r = self.client.list_group_categories_for_context_courses(course_id) + + def test_get_single_group_category(self): + """Integration test for the GroupCategoriesAPI.get_single_group_category method.""" + group_category_id = None # Change me!! + + r = self.client.get_single_group_category(group_category_id) + + def test_create_group_category_accounts(self): + """Integration test for the GroupCategoriesAPI.create_group_category_accounts method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_group_category_courses(self): + """Integration test for the GroupCategoriesAPI.create_group_category_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_group_category(self): + """Integration test for the GroupCategoriesAPI.update_group_category method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_group_category(self): + """Integration test for the GroupCategoriesAPI.delete_group_category method.""" + group_category_id = None # Change me!! + + r = self.client.delete_group_category(group_category_id) + + def test_list_groups_in_group_category(self): + """Integration test for the GroupCategoriesAPI.list_groups_in_group_category method.""" + group_category_id = None # Change me!! + + r = self.client.list_groups_in_group_category(group_category_id) + + def test_list_users_in_group_category(self): + """Integration test for the GroupCategoriesAPI.list_users_in_group_category method.""" + group_category_id = None # Change me!! + + r = self.client.list_users_in_group_category(group_category_id, search_term=None, unassigned=None) + + def test_assign_unassigned_members(self): + """Integration test for the GroupCategoriesAPI.assign_unassigned_members method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/groups.py b/venv/Lib/site-packages/pycanvas/tests/groups.py new file mode 100644 index 00000000..3d3c4491 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/groups.py @@ -0,0 +1,144 @@ +"""Groups API Tests for Version 1.0. + +This is a testing template for the generated GroupsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.groups import GroupsAPI +from pycanvas.apis.groups import Group +from pycanvas.apis.groups import Groupmembership + + +class TestGroupsAPI(unittest.TestCase): + """Tests for the GroupsAPI.""" + + def setUp(self): + self.client = GroupsAPI(secrets.instance_address, secrets.access_token) + + def test_list_your_groups(self): + """Integration test for the GroupsAPI.list_your_groups method.""" + + r = self.client.list_your_groups(context_type=None, include=None) + + def test_list_groups_available_in_context_accounts(self): + """Integration test for the GroupsAPI.list_groups_available_in_context_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_groups_available_in_context_accounts(account_id, include=None, only_own_groups=None) + + def test_list_groups_available_in_context_courses(self): + """Integration test for the GroupsAPI.list_groups_available_in_context_courses method.""" + course_id = None # Change me!! + + r = self.client.list_groups_available_in_context_courses(course_id, include=None, only_own_groups=None) + + def test_get_single_group(self): + """Integration test for the GroupsAPI.get_single_group method.""" + group_id = None # Change me!! + + r = self.client.get_single_group(group_id, include=None) + + def test_create_group_groups(self): + """Integration test for the GroupsAPI.create_group_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_group_group_categories(self): + """Integration test for the GroupsAPI.create_group_group_categories method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_edit_group(self): + """Integration test for the GroupsAPI.edit_group method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_group(self): + """Integration test for the GroupsAPI.delete_group method.""" + group_id = None # Change me!! + + r = self.client.delete_group(group_id) + + def test_invite_others_to_group(self): + """Integration test for the GroupsAPI.invite_others_to_group method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_group_s_users(self): + """Integration test for the GroupsAPI.list_group_s_users method.""" + group_id = None # Change me!! + + r = self.client.list_group_s_users(group_id, include=None, search_term=None) + + def test_upload_file(self): + """Integration test for the GroupsAPI.upload_file method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_preview_processed_html(self): + """Integration test for the GroupsAPI.preview_processed_html method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_group_activity_stream(self): + """Integration test for the GroupsAPI.group_activity_stream method.""" + group_id = None # Change me!! + + r = self.client.group_activity_stream(group_id) + + def test_group_activity_stream_summary(self): + """Integration test for the GroupsAPI.group_activity_stream_summary method.""" + group_id = None # Change me!! + + r = self.client.group_activity_stream_summary(group_id) + + def test_list_group_memberships(self): + """Integration test for the GroupsAPI.list_group_memberships method.""" + group_id = None # Change me!! + + r = self.client.list_group_memberships(group_id, filter_states=None) + + def test_get_single_group_membership_memberships(self): + """Integration test for the GroupsAPI.get_single_group_membership_memberships method.""" + group_id = None # Change me!! + membership_id = None # Change me!! + + r = self.client.get_single_group_membership_memberships(group_id, membership_id) + + def test_get_single_group_membership_users(self): + """Integration test for the GroupsAPI.get_single_group_membership_users method.""" + group_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.get_single_group_membership_users(user_id, group_id) + + def test_create_membership(self): + """Integration test for the GroupsAPI.create_membership method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_membership_memberships(self): + """Integration test for the GroupsAPI.update_membership_memberships method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_membership_users(self): + """Integration test for the GroupsAPI.update_membership_users method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_leave_group_memberships(self): + """Integration test for the GroupsAPI.leave_group_memberships method.""" + group_id = None # Change me!! + membership_id = None # Change me!! + + r = self.client.leave_group_memberships(group_id, membership_id) + + def test_leave_group_users(self): + """Integration test for the GroupsAPI.leave_group_users method.""" + group_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.leave_group_users(user_id, group_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/live_assessments.py b/venv/Lib/site-packages/pycanvas/tests/live_assessments.py new file mode 100644 index 00000000..654f2a27 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/live_assessments.py @@ -0,0 +1,42 @@ +"""LiveAssessments API Tests for Version 1.0. + +This is a testing template for the generated LiveAssessmentsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.live_assessments import LiveAssessmentsAPI +from pycanvas.apis.live_assessments import Assessment +from pycanvas.apis.live_assessments import Result +from pycanvas.apis.live_assessments import Resultlinks + + +class TestLiveAssessmentsAPI(unittest.TestCase): + """Tests for the LiveAssessmentsAPI.""" + + def setUp(self): + self.client = LiveAssessmentsAPI(secrets.instance_address, secrets.access_token) + + def test_create_live_assessment_results(self): + """Integration test for the LiveAssessmentsAPI.create_live_assessment_results method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_live_assessment_results(self): + """Integration test for the LiveAssessmentsAPI.list_live_assessment_results method.""" + course_id = None # Change me!! + assessment_id = None # Change me!! + + r = self.client.list_live_assessment_results(course_id, assessment_id, user_id=None) + + def test_create_or_find_live_assessment(self): + """Integration test for the LiveAssessmentsAPI.create_or_find_live_assessment method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_live_assessments(self): + """Integration test for the LiveAssessmentsAPI.list_live_assessments method.""" + course_id = None # Change me!! + + r = self.client.list_live_assessments(course_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/logins.py b/venv/Lib/site-packages/pycanvas/tests/logins.py new file mode 100644 index 00000000..688739c9 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/logins.py @@ -0,0 +1,45 @@ +"""Logins API Tests for Version 1.0. + +This is a testing template for the generated LoginsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.logins import LoginsAPI + + +class TestLoginsAPI(unittest.TestCase): + """Tests for the LoginsAPI.""" + + def setUp(self): + self.client = LoginsAPI(secrets.instance_address, secrets.access_token) + + def test_list_user_logins_accounts(self): + """Integration test for the LoginsAPI.list_user_logins_accounts method.""" + account_id = None # Change me!! + + r = self.client.list_user_logins_accounts(account_id) + + def test_list_user_logins_users(self): + """Integration test for the LoginsAPI.list_user_logins_users method.""" + user_id = None # Change me!! + + r = self.client.list_user_logins_users(user_id) + + def test_create_user_login(self): + """Integration test for the LoginsAPI.create_user_login method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_edit_user_login(self): + """Integration test for the LoginsAPI.edit_user_login method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_user_login(self): + """Integration test for the LoginsAPI.delete_user_login method.""" + user_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_user_login(id, user_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/modules.py b/venv/Lib/site-packages/pycanvas/tests/modules.py new file mode 100644 index 00000000..95b98646 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/modules.py @@ -0,0 +1,114 @@ +"""Modules API Tests for Version 1.0. + +This is a testing template for the generated ModulesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.modules import ModulesAPI +from pycanvas.apis.modules import Contentdetails +from pycanvas.apis.modules import Moduleitemsequenceasset +from pycanvas.apis.modules import Moduleitemcompletionrequirement +from pycanvas.apis.modules import Module +from pycanvas.apis.modules import Moduleitemsequence +from pycanvas.apis.modules import Completionrequirement +from pycanvas.apis.modules import Moduleitem +from pycanvas.apis.modules import Moduleitemsequencenode +from pycanvas.apis.modules import Moduleitemcontentdetails + + +class TestModulesAPI(unittest.TestCase): + """Tests for the ModulesAPI.""" + + def setUp(self): + self.client = ModulesAPI(secrets.instance_address, secrets.access_token) + + def test_list_modules(self): + """Integration test for the ModulesAPI.list_modules method.""" + course_id = None # Change me!! + + r = self.client.list_modules(course_id, include=None, search_term=None, student_id=None) + + def test_show_module(self): + """Integration test for the ModulesAPI.show_module method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.show_module(id, course_id, include=None, student_id=None) + + def test_create_module(self): + """Integration test for the ModulesAPI.create_module method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_module(self): + """Integration test for the ModulesAPI.update_module method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_module(self): + """Integration test for the ModulesAPI.delete_module method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_module(id, course_id) + + def test_re_lock_module_progressions(self): + """Integration test for the ModulesAPI.re_lock_module_progressions method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_module_items(self): + """Integration test for the ModulesAPI.list_module_items method.""" + course_id = None # Change me!! + module_id = None # Change me!! + + r = self.client.list_module_items(course_id, module_id, include=None, search_term=None, student_id=None) + + def test_show_module_item(self): + """Integration test for the ModulesAPI.show_module_item method.""" + course_id = None # Change me!! + module_id = None # Change me!! + id = None # Change me!! + + r = self.client.show_module_item(id, course_id, module_id, include=None, student_id=None) + + def test_create_module_item(self): + """Integration test for the ModulesAPI.create_module_item method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_module_item(self): + """Integration test for the ModulesAPI.update_module_item method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_select_mastery_path(self): + """Integration test for the ModulesAPI.select_mastery_path method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_module_item(self): + """Integration test for the ModulesAPI.delete_module_item method.""" + course_id = None # Change me!! + module_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_module_item(id, course_id, module_id) + + def test_mark_module_item_as_done_not_done(self): + """Integration test for the ModulesAPI.mark_module_item_as_done_not_done method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_module_item_sequence(self): + """Integration test for the ModulesAPI.get_module_item_sequence method.""" + course_id = None # Change me!! + + r = self.client.get_module_item_sequence(course_id, asset_id=None, asset_type=None) + + def test_mark_module_item_read(self): + """Integration test for the ModulesAPI.mark_module_item_read method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/notification_preferences.py b/venv/Lib/site-packages/pycanvas/tests/notification_preferences.py new file mode 100644 index 00000000..37837d11 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/notification_preferences.py @@ -0,0 +1,81 @@ +"""NotificationPreferences API Tests for Version 1.0. + +This is a testing template for the generated NotificationPreferencesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.notification_preferences import NotificationPreferencesAPI +from pycanvas.apis.notification_preferences import Notificationpreference + + +class TestNotificationPreferencesAPI(unittest.TestCase): + """Tests for the NotificationPreferencesAPI.""" + + def setUp(self): + self.client = NotificationPreferencesAPI(secrets.instance_address, secrets.access_token) + + def test_list_preferences_communication_channel_id(self): + """Integration test for the NotificationPreferencesAPI.list_preferences_communication_channel_id method.""" + user_id = None # Change me!! + communication_channel_id = None # Change me!! + + r = self.client.list_preferences_communication_channel_id(user_id, communication_channel_id) + + def test_list_preferences_type(self): + """Integration test for the NotificationPreferencesAPI.list_preferences_type method.""" + user_id = None # Change me!! + type = None # Change me!! + address = None # Change me!! + + r = self.client.list_preferences_type(type, user_id, address) + + def test_list_of_preference_categories(self): + """Integration test for the NotificationPreferencesAPI.list_of_preference_categories method.""" + user_id = None # Change me!! + communication_channel_id = None # Change me!! + + r = self.client.list_of_preference_categories(user_id, communication_channel_id) + + def test_get_preference_communication_channel_id(self): + """Integration test for the NotificationPreferencesAPI.get_preference_communication_channel_id method.""" + user_id = None # Change me!! + communication_channel_id = None # Change me!! + notification = None # Change me!! + + r = self.client.get_preference_communication_channel_id(user_id, notification, communication_channel_id) + + def test_get_preference_type(self): + """Integration test for the NotificationPreferencesAPI.get_preference_type method.""" + user_id = None # Change me!! + type = None # Change me!! + address = None # Change me!! + notification = None # Change me!! + + r = self.client.get_preference_type(type, user_id, address, notification) + + def test_update_preference_communication_channel_id(self): + """Integration test for the NotificationPreferencesAPI.update_preference_communication_channel_id method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_preference_type(self): + """Integration test for the NotificationPreferencesAPI.update_preference_type method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_preferences_by_category(self): + """Integration test for the NotificationPreferencesAPI.update_preferences_by_category method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_multiple_preferences_communication_channel_id(self): + """Integration test for the NotificationPreferencesAPI.update_multiple_preferences_communication_channel_id method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_multiple_preferences_type(self): + """Integration test for the NotificationPreferencesAPI.update_multiple_preferences_type method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/outcome_groups.py b/venv/Lib/site-packages/pycanvas/tests/outcome_groups.py new file mode 100644 index 00000000..92e25407 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/outcome_groups.py @@ -0,0 +1,237 @@ +"""OutcomeGroups API Tests for Version 1.0. + +This is a testing template for the generated OutcomeGroupsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.outcome_groups import OutcomeGroupsAPI +from pycanvas.apis.outcome_groups import Outcomegroup +from pycanvas.apis.outcome_groups import Outcomelink + + +class TestOutcomeGroupsAPI(unittest.TestCase): + """Tests for the OutcomeGroupsAPI.""" + + def setUp(self): + self.client = OutcomeGroupsAPI(secrets.instance_address, secrets.access_token) + + def test_redirect_to_root_outcome_group_for_context_global(self): + """Integration test for the OutcomeGroupsAPI.redirect_to_root_outcome_group_for_context_global method.""" + + r = self.client.redirect_to_root_outcome_group_for_context_global() + + def test_redirect_to_root_outcome_group_for_context_accounts(self): + """Integration test for the OutcomeGroupsAPI.redirect_to_root_outcome_group_for_context_accounts method.""" + account_id = None # Change me!! + + r = self.client.redirect_to_root_outcome_group_for_context_accounts(account_id) + + def test_redirect_to_root_outcome_group_for_context_courses(self): + """Integration test for the OutcomeGroupsAPI.redirect_to_root_outcome_group_for_context_courses method.""" + course_id = None # Change me!! + + r = self.client.redirect_to_root_outcome_group_for_context_courses(course_id) + + def test_get_all_outcome_groups_for_context_accounts(self): + """Integration test for the OutcomeGroupsAPI.get_all_outcome_groups_for_context_accounts method.""" + account_id = None # Change me!! + + r = self.client.get_all_outcome_groups_for_context_accounts(account_id) + + def test_get_all_outcome_groups_for_context_courses(self): + """Integration test for the OutcomeGroupsAPI.get_all_outcome_groups_for_context_courses method.""" + course_id = None # Change me!! + + r = self.client.get_all_outcome_groups_for_context_courses(course_id) + + def test_get_all_outcome_links_for_context_accounts(self): + """Integration test for the OutcomeGroupsAPI.get_all_outcome_links_for_context_accounts method.""" + account_id = None # Change me!! + + r = self.client.get_all_outcome_links_for_context_accounts(account_id, outcome_group_style=None, outcome_style=None) + + def test_get_all_outcome_links_for_context_courses(self): + """Integration test for the OutcomeGroupsAPI.get_all_outcome_links_for_context_courses method.""" + course_id = None # Change me!! + + r = self.client.get_all_outcome_links_for_context_courses(course_id, outcome_group_style=None, outcome_style=None) + + def test_show_outcome_group_global(self): + """Integration test for the OutcomeGroupsAPI.show_outcome_group_global method.""" + id = None # Change me!! + + r = self.client.show_outcome_group_global(id) + + def test_show_outcome_group_accounts(self): + """Integration test for the OutcomeGroupsAPI.show_outcome_group_accounts method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.show_outcome_group_accounts(id, account_id) + + def test_show_outcome_group_courses(self): + """Integration test for the OutcomeGroupsAPI.show_outcome_group_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.show_outcome_group_courses(id, course_id) + + def test_update_outcome_group_global(self): + """Integration test for the OutcomeGroupsAPI.update_outcome_group_global method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_outcome_group_accounts(self): + """Integration test for the OutcomeGroupsAPI.update_outcome_group_accounts method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_outcome_group_courses(self): + """Integration test for the OutcomeGroupsAPI.update_outcome_group_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_outcome_group_global(self): + """Integration test for the OutcomeGroupsAPI.delete_outcome_group_global method.""" + id = None # Change me!! + + r = self.client.delete_outcome_group_global(id) + + def test_delete_outcome_group_accounts(self): + """Integration test for the OutcomeGroupsAPI.delete_outcome_group_accounts method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_outcome_group_accounts(id, account_id) + + def test_delete_outcome_group_courses(self): + """Integration test for the OutcomeGroupsAPI.delete_outcome_group_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_outcome_group_courses(id, course_id) + + def test_list_linked_outcomes_global(self): + """Integration test for the OutcomeGroupsAPI.list_linked_outcomes_global method.""" + id = None # Change me!! + + r = self.client.list_linked_outcomes_global(id, outcome_style=None) + + def test_list_linked_outcomes_accounts(self): + """Integration test for the OutcomeGroupsAPI.list_linked_outcomes_accounts method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.list_linked_outcomes_accounts(id, account_id, outcome_style=None) + + def test_list_linked_outcomes_courses(self): + """Integration test for the OutcomeGroupsAPI.list_linked_outcomes_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.list_linked_outcomes_courses(id, course_id, outcome_style=None) + + def test_create_link_outcome_global(self): + """Integration test for the OutcomeGroupsAPI.create_link_outcome_global method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_link_outcome_global_outcome_id(self): + """Integration test for the OutcomeGroupsAPI.create_link_outcome_global_outcome_id method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_link_outcome_accounts(self): + """Integration test for the OutcomeGroupsAPI.create_link_outcome_accounts method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_link_outcome_accounts_outcome_id(self): + """Integration test for the OutcomeGroupsAPI.create_link_outcome_accounts_outcome_id method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_link_outcome_courses(self): + """Integration test for the OutcomeGroupsAPI.create_link_outcome_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_link_outcome_courses_outcome_id(self): + """Integration test for the OutcomeGroupsAPI.create_link_outcome_courses_outcome_id method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_unlink_outcome_global(self): + """Integration test for the OutcomeGroupsAPI.unlink_outcome_global method.""" + id = None # Change me!! + outcome_id = None # Change me!! + + r = self.client.unlink_outcome_global(id, outcome_id) + + def test_unlink_outcome_accounts(self): + """Integration test for the OutcomeGroupsAPI.unlink_outcome_accounts method.""" + account_id = None # Change me!! + id = None # Change me!! + outcome_id = None # Change me!! + + r = self.client.unlink_outcome_accounts(id, account_id, outcome_id) + + def test_unlink_outcome_courses(self): + """Integration test for the OutcomeGroupsAPI.unlink_outcome_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + outcome_id = None # Change me!! + + r = self.client.unlink_outcome_courses(id, course_id, outcome_id) + + def test_list_subgroups_global(self): + """Integration test for the OutcomeGroupsAPI.list_subgroups_global method.""" + id = None # Change me!! + + r = self.client.list_subgroups_global(id) + + def test_list_subgroups_accounts(self): + """Integration test for the OutcomeGroupsAPI.list_subgroups_accounts method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.list_subgroups_accounts(id, account_id) + + def test_list_subgroups_courses(self): + """Integration test for the OutcomeGroupsAPI.list_subgroups_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.list_subgroups_courses(id, course_id) + + def test_create_subgroup_global(self): + """Integration test for the OutcomeGroupsAPI.create_subgroup_global method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_subgroup_accounts(self): + """Integration test for the OutcomeGroupsAPI.create_subgroup_accounts method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_subgroup_courses(self): + """Integration test for the OutcomeGroupsAPI.create_subgroup_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_import_outcome_group_global(self): + """Integration test for the OutcomeGroupsAPI.import_outcome_group_global method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_import_outcome_group_accounts(self): + """Integration test for the OutcomeGroupsAPI.import_outcome_group_accounts method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_import_outcome_group_courses(self): + """Integration test for the OutcomeGroupsAPI.import_outcome_group_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/outcome_results.py b/venv/Lib/site-packages/pycanvas/tests/outcome_results.py new file mode 100644 index 00000000..49c59a7a --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/outcome_results.py @@ -0,0 +1,36 @@ +"""OutcomeResults API Tests for Version 1.0. + +This is a testing template for the generated OutcomeResultsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.outcome_results import OutcomeResultsAPI +from pycanvas.apis.outcome_results import Outcomeresult +from pycanvas.apis.outcome_results import Outcomerolluplinks +from pycanvas.apis.outcome_results import Outcomepathpart +from pycanvas.apis.outcome_results import Outcomerollupscorelinks +from pycanvas.apis.outcome_results import Outcomealignment +from pycanvas.apis.outcome_results import Outcomerollupscore +from pycanvas.apis.outcome_results import Outcomerollup +from pycanvas.apis.outcome_results import Outcomepath + + +class TestOutcomeResultsAPI(unittest.TestCase): + """Tests for the OutcomeResultsAPI.""" + + def setUp(self): + self.client = OutcomeResultsAPI(secrets.instance_address, secrets.access_token) + + def test_get_outcome_results(self): + """Integration test for the OutcomeResultsAPI.get_outcome_results method.""" + course_id = None # Change me!! + + r = self.client.get_outcome_results(course_id, include=None, outcome_ids=None, user_ids=None) + + def test_get_outcome_result_rollups(self): + """Integration test for the OutcomeResultsAPI.get_outcome_result_rollups method.""" + course_id = None # Change me!! + + r = self.client.get_outcome_result_rollups(course_id, aggregate=None, include=None, outcome_ids=None, user_ids=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/outcomes.py b/venv/Lib/site-packages/pycanvas/tests/outcomes.py new file mode 100644 index 00000000..858411a5 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/outcomes.py @@ -0,0 +1,28 @@ +"""Outcomes API Tests for Version 1.0. + +This is a testing template for the generated OutcomesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.outcomes import OutcomesAPI +from pycanvas.apis.outcomes import Outcome + + +class TestOutcomesAPI(unittest.TestCase): + """Tests for the OutcomesAPI.""" + + def setUp(self): + self.client = OutcomesAPI(secrets.instance_address, secrets.access_token) + + def test_show_outcome(self): + """Integration test for the OutcomesAPI.show_outcome method.""" + id = None # Change me!! + + r = self.client.show_outcome(id) + + def test_update_outcome(self): + """Integration test for the OutcomesAPI.update_outcome method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/pages.py b/venv/Lib/site-packages/pycanvas/tests/pages.py new file mode 100644 index 00000000..8378271f --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/pages.py @@ -0,0 +1,154 @@ +"""Pages API Tests for Version 1.0. + +This is a testing template for the generated PagesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.pages import PagesAPI +from pycanvas.apis.pages import Pagerevision +from pycanvas.apis.pages import Page + + +class TestPagesAPI(unittest.TestCase): + """Tests for the PagesAPI.""" + + def setUp(self): + self.client = PagesAPI(secrets.instance_address, secrets.access_token) + + def test_show_front_page_courses(self): + """Integration test for the PagesAPI.show_front_page_courses method.""" + course_id = None # Change me!! + + r = self.client.show_front_page_courses(course_id) + + def test_show_front_page_groups(self): + """Integration test for the PagesAPI.show_front_page_groups method.""" + group_id = None # Change me!! + + r = self.client.show_front_page_groups(group_id) + + def test_update_create_front_page_courses(self): + """Integration test for the PagesAPI.update_create_front_page_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_create_front_page_groups(self): + """Integration test for the PagesAPI.update_create_front_page_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_pages_courses(self): + """Integration test for the PagesAPI.list_pages_courses method.""" + course_id = None # Change me!! + + r = self.client.list_pages_courses(course_id, order=None, published=None, search_term=None, sort=None) + + def test_list_pages_groups(self): + """Integration test for the PagesAPI.list_pages_groups method.""" + group_id = None # Change me!! + + r = self.client.list_pages_groups(group_id, order=None, published=None, search_term=None, sort=None) + + def test_create_page_courses(self): + """Integration test for the PagesAPI.create_page_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_create_page_groups(self): + """Integration test for the PagesAPI.create_page_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_show_page_courses(self): + """Integration test for the PagesAPI.show_page_courses method.""" + course_id = None # Change me!! + url = None # Change me!! + + r = self.client.show_page_courses(url, course_id) + + def test_show_page_groups(self): + """Integration test for the PagesAPI.show_page_groups method.""" + group_id = None # Change me!! + url = None # Change me!! + + r = self.client.show_page_groups(url, group_id) + + def test_update_create_page_courses(self): + """Integration test for the PagesAPI.update_create_page_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_create_page_groups(self): + """Integration test for the PagesAPI.update_create_page_groups method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_page_courses(self): + """Integration test for the PagesAPI.delete_page_courses method.""" + course_id = None # Change me!! + url = None # Change me!! + + r = self.client.delete_page_courses(url, course_id) + + def test_delete_page_groups(self): + """Integration test for the PagesAPI.delete_page_groups method.""" + group_id = None # Change me!! + url = None # Change me!! + + r = self.client.delete_page_groups(url, group_id) + + def test_list_revisions_courses(self): + """Integration test for the PagesAPI.list_revisions_courses method.""" + course_id = None # Change me!! + url = None # Change me!! + + r = self.client.list_revisions_courses(url, course_id) + + def test_list_revisions_groups(self): + """Integration test for the PagesAPI.list_revisions_groups method.""" + group_id = None # Change me!! + url = None # Change me!! + + r = self.client.list_revisions_groups(url, group_id) + + def test_show_revision_courses_latest(self): + """Integration test for the PagesAPI.show_revision_courses_latest method.""" + course_id = None # Change me!! + url = None # Change me!! + + r = self.client.show_revision_courses_latest(url, course_id, summary=None) + + def test_show_revision_groups_latest(self): + """Integration test for the PagesAPI.show_revision_groups_latest method.""" + group_id = None # Change me!! + url = None # Change me!! + + r = self.client.show_revision_groups_latest(url, group_id, summary=None) + + def test_show_revision_courses_revision_id(self): + """Integration test for the PagesAPI.show_revision_courses_revision_id method.""" + course_id = None # Change me!! + url = None # Change me!! + revision_id = None # Change me!! + + r = self.client.show_revision_courses_revision_id(url, course_id, revision_id, summary=None) + + def test_show_revision_groups_revision_id(self): + """Integration test for the PagesAPI.show_revision_groups_revision_id method.""" + group_id = None # Change me!! + url = None # Change me!! + revision_id = None # Change me!! + + r = self.client.show_revision_groups_revision_id(url, group_id, revision_id, summary=None) + + def test_revert_to_revision_courses(self): + """Integration test for the PagesAPI.revert_to_revision_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_revert_to_revision_groups(self): + """Integration test for the PagesAPI.revert_to_revision_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/poll_choices.py b/venv/Lib/site-packages/pycanvas/tests/poll_choices.py new file mode 100644 index 00000000..e89b2104 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/poll_choices.py @@ -0,0 +1,47 @@ +"""PollChoices API Tests for Version 1.0. + +This is a testing template for the generated PollChoicesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.poll_choices import PollChoicesAPI +from pycanvas.apis.poll_choices import Pollchoice + + +class TestPollChoicesAPI(unittest.TestCase): + """Tests for the PollChoicesAPI.""" + + def setUp(self): + self.client = PollChoicesAPI(secrets.instance_address, secrets.access_token) + + def test_list_poll_choices_in_poll(self): + """Integration test for the PollChoicesAPI.list_poll_choices_in_poll method.""" + poll_id = None # Change me!! + + r = self.client.list_poll_choices_in_poll(poll_id) + + def test_get_single_poll_choice(self): + """Integration test for the PollChoicesAPI.get_single_poll_choice method.""" + poll_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_poll_choice(id, poll_id) + + def test_create_single_poll_choice(self): + """Integration test for the PollChoicesAPI.create_single_poll_choice method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_single_poll_choice(self): + """Integration test for the PollChoicesAPI.update_single_poll_choice method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_poll_choice(self): + """Integration test for the PollChoicesAPI.delete_poll_choice method.""" + poll_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_poll_choice(id, poll_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/poll_sessions.py b/venv/Lib/site-packages/pycanvas/tests/poll_sessions.py new file mode 100644 index 00000000..e4aff6e4 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/poll_sessions.py @@ -0,0 +1,71 @@ +"""PollSessions API Tests for Version 1.0. + +This is a testing template for the generated PollSessionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.poll_sessions import PollSessionsAPI +from pycanvas.apis.poll_sessions import Pollsession + + +class TestPollSessionsAPI(unittest.TestCase): + """Tests for the PollSessionsAPI.""" + + def setUp(self): + self.client = PollSessionsAPI(secrets.instance_address, secrets.access_token) + + def test_list_poll_sessions_for_poll(self): + """Integration test for the PollSessionsAPI.list_poll_sessions_for_poll method.""" + poll_id = None # Change me!! + + r = self.client.list_poll_sessions_for_poll(poll_id) + + def test_get_results_for_single_poll_session(self): + """Integration test for the PollSessionsAPI.get_results_for_single_poll_session method.""" + poll_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_results_for_single_poll_session(id, poll_id) + + def test_create_single_poll_session(self): + """Integration test for the PollSessionsAPI.create_single_poll_session method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_single_poll_session(self): + """Integration test for the PollSessionsAPI.update_single_poll_session method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_poll_session(self): + """Integration test for the PollSessionsAPI.delete_poll_session method.""" + poll_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_poll_session(id, poll_id) + + def test_open_poll_session(self): + """Integration test for the PollSessionsAPI.open_poll_session method.""" + poll_id = None # Change me!! + id = None # Change me!! + + r = self.client.open_poll_session(id, poll_id) + + def test_close_opened_poll_session(self): + """Integration test for the PollSessionsAPI.close_opened_poll_session method.""" + poll_id = None # Change me!! + id = None # Change me!! + + r = self.client.close_opened_poll_session(id, poll_id) + + def test_list_opened_poll_sessions(self): + """Integration test for the PollSessionsAPI.list_opened_poll_sessions method.""" + + r = self.client.list_opened_poll_sessions() + + def test_list_closed_poll_sessions(self): + """Integration test for the PollSessionsAPI.list_closed_poll_sessions method.""" + + r = self.client.list_closed_poll_sessions() + diff --git a/venv/Lib/site-packages/pycanvas/tests/poll_submissions.py b/venv/Lib/site-packages/pycanvas/tests/poll_submissions.py new file mode 100644 index 00000000..fa58d0a9 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/poll_submissions.py @@ -0,0 +1,30 @@ +"""PollSubmissions API Tests for Version 1.0. + +This is a testing template for the generated PollSubmissionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.poll_submissions import PollSubmissionsAPI +from pycanvas.apis.poll_submissions import Pollsubmission + + +class TestPollSubmissionsAPI(unittest.TestCase): + """Tests for the PollSubmissionsAPI.""" + + def setUp(self): + self.client = PollSubmissionsAPI(secrets.instance_address, secrets.access_token) + + def test_get_single_poll_submission(self): + """Integration test for the PollSubmissionsAPI.get_single_poll_submission method.""" + poll_id = None # Change me!! + poll_session_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_poll_submission(id, poll_id, poll_session_id) + + def test_create_single_poll_submission(self): + """Integration test for the PollSubmissionsAPI.create_single_poll_submission method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/polls.py b/venv/Lib/site-packages/pycanvas/tests/polls.py new file mode 100644 index 00000000..b3525c4c --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/polls.py @@ -0,0 +1,44 @@ +"""Polls API Tests for Version 1.0. + +This is a testing template for the generated PollsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.polls import PollsAPI +from pycanvas.apis.polls import Poll + + +class TestPollsAPI(unittest.TestCase): + """Tests for the PollsAPI.""" + + def setUp(self): + self.client = PollsAPI(secrets.instance_address, secrets.access_token) + + def test_list_polls(self): + """Integration test for the PollsAPI.list_polls method.""" + + r = self.client.list_polls() + + def test_get_single_poll(self): + """Integration test for the PollsAPI.get_single_poll method.""" + id = None # Change me!! + + r = self.client.get_single_poll(id) + + def test_create_single_poll(self): + """Integration test for the PollsAPI.create_single_poll method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_single_poll(self): + """Integration test for the PollsAPI.update_single_poll method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_poll(self): + """Integration test for the PollsAPI.delete_poll method.""" + id = None # Change me!! + + r = self.client.delete_poll(id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/progress.py b/venv/Lib/site-packages/pycanvas/tests/progress.py new file mode 100644 index 00000000..a6b6e91d --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/progress.py @@ -0,0 +1,23 @@ +"""Progress API Tests for Version 1.0. + +This is a testing template for the generated ProgressAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.progress import ProgressAPI +from pycanvas.apis.progress import Progress + + +class TestProgressAPI(unittest.TestCase): + """Tests for the ProgressAPI.""" + + def setUp(self): + self.client = ProgressAPI(secrets.instance_address, secrets.access_token) + + def test_query_progress(self): + """Integration test for the ProgressAPI.query_progress method.""" + id = None # Change me!! + + r = self.client.query_progress(id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_assignment_overrides.py b/venv/Lib/site-packages/pycanvas/tests/quiz_assignment_overrides.py new file mode 100644 index 00000000..cbe8ec49 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_assignment_overrides.py @@ -0,0 +1,25 @@ +"""QuizAssignmentOverrides API Tests for Version 1.0. + +This is a testing template for the generated QuizAssignmentOverridesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_assignment_overrides import QuizAssignmentOverridesAPI +from pycanvas.apis.quiz_assignment_overrides import Quizassignmentoverride +from pycanvas.apis.quiz_assignment_overrides import Quizassignmentoverridesetcontainer +from pycanvas.apis.quiz_assignment_overrides import Quizassignmentoverrideset + + +class TestQuizAssignmentOverridesAPI(unittest.TestCase): + """Tests for the QuizAssignmentOverridesAPI.""" + + def setUp(self): + self.client = QuizAssignmentOverridesAPI(secrets.instance_address, secrets.access_token) + + def test_retrieve_assignment_overridden_dates_for_quizzes(self): + """Integration test for the QuizAssignmentOverridesAPI.retrieve_assignment_overridden_dates_for_quizzes method.""" + course_id = None # Change me!! + + r = self.client.retrieve_assignment_overridden_dates_for_quizzes(course_id, quiz_assignment_overrides_0_quiz_ids=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_extensions.py b/venv/Lib/site-packages/pycanvas/tests/quiz_extensions.py new file mode 100644 index 00000000..d537b1fa --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_extensions.py @@ -0,0 +1,22 @@ +"""QuizExtensions API Tests for Version 1.0. + +This is a testing template for the generated QuizExtensionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_extensions import QuizExtensionsAPI +from pycanvas.apis.quiz_extensions import Quizextension + + +class TestQuizExtensionsAPI(unittest.TestCase): + """Tests for the QuizExtensionsAPI.""" + + def setUp(self): + self.client = QuizExtensionsAPI(secrets.instance_address, secrets.access_token) + + def test_set_extensions_for_student_quiz_submissions(self): + """Integration test for the QuizExtensionsAPI.set_extensions_for_student_quiz_submissions method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_ip_filters.py b/venv/Lib/site-packages/pycanvas/tests/quiz_ip_filters.py new file mode 100644 index 00000000..a6122e45 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_ip_filters.py @@ -0,0 +1,24 @@ +"""QuizIpFilters API Tests for Version 1.0. + +This is a testing template for the generated QuizIpFiltersAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_ip_filters import QuizIpFiltersAPI +from pycanvas.apis.quiz_ip_filters import Quizipfilter + + +class TestQuizIpFiltersAPI(unittest.TestCase): + """Tests for the QuizIpFiltersAPI.""" + + def setUp(self): + self.client = QuizIpFiltersAPI(secrets.instance_address, secrets.access_token) + + def test_get_available_quiz_ip_filters(self): + """Integration test for the QuizIpFiltersAPI.get_available_quiz_ip_filters method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + + r = self.client.get_available_quiz_ip_filters(quiz_id, course_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_question_groups.py b/venv/Lib/site-packages/pycanvas/tests/quiz_question_groups.py new file mode 100644 index 00000000..05a91a32 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_question_groups.py @@ -0,0 +1,48 @@ +"""QuizQuestionGroups API Tests for Version 1.0. + +This is a testing template for the generated QuizQuestionGroupsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_question_groups import QuizQuestionGroupsAPI +from pycanvas.apis.quiz_question_groups import Quizgroup + + +class TestQuizQuestionGroupsAPI(unittest.TestCase): + """Tests for the QuizQuestionGroupsAPI.""" + + def setUp(self): + self.client = QuizQuestionGroupsAPI(secrets.instance_address, secrets.access_token) + + def test_get_single_quiz_group(self): + """Integration test for the QuizQuestionGroupsAPI.get_single_quiz_group method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_quiz_group(id, quiz_id, course_id) + + def test_create_question_group(self): + """Integration test for the QuizQuestionGroupsAPI.create_question_group method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_question_group(self): + """Integration test for the QuizQuestionGroupsAPI.update_question_group method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_question_group(self): + """Integration test for the QuizQuestionGroupsAPI.delete_question_group method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_question_group(id, quiz_id, course_id) + + def test_reorder_question_groups(self): + """Integration test for the QuizQuestionGroupsAPI.reorder_question_groups method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_questions.py b/venv/Lib/site-packages/pycanvas/tests/quiz_questions.py new file mode 100644 index 00000000..a6095221 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_questions.py @@ -0,0 +1,51 @@ +"""QuizQuestions API Tests for Version 1.0. + +This is a testing template for the generated QuizQuestionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_questions import QuizQuestionsAPI +from pycanvas.apis.quiz_questions import Answer +from pycanvas.apis.quiz_questions import Quizquestion + + +class TestQuizQuestionsAPI(unittest.TestCase): + """Tests for the QuizQuestionsAPI.""" + + def setUp(self): + self.client = QuizQuestionsAPI(secrets.instance_address, secrets.access_token) + + def test_list_questions_in_quiz_or_submission(self): + """Integration test for the QuizQuestionsAPI.list_questions_in_quiz_or_submission method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + + r = self.client.list_questions_in_quiz_or_submission(quiz_id, course_id, quiz_submission_attempt=None, quiz_submission_id=None) + + def test_get_single_quiz_question(self): + """Integration test for the QuizQuestionsAPI.get_single_quiz_question method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_quiz_question(id, quiz_id, course_id) + + def test_create_single_quiz_question(self): + """Integration test for the QuizQuestionsAPI.create_single_quiz_question method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_existing_quiz_question(self): + """Integration test for the QuizQuestionsAPI.update_existing_quiz_question method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_quiz_question(self): + """Integration test for the QuizQuestionsAPI.delete_quiz_question method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_quiz_question(id, quiz_id, course_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_reports.py b/venv/Lib/site-packages/pycanvas/tests/quiz_reports.py new file mode 100644 index 00000000..d1e02995 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_reports.py @@ -0,0 +1,45 @@ +"""QuizReports API Tests for Version 1.0. + +This is a testing template for the generated QuizReportsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_reports import QuizReportsAPI +from pycanvas.apis.quiz_reports import Quizreport + + +class TestQuizReportsAPI(unittest.TestCase): + """Tests for the QuizReportsAPI.""" + + def setUp(self): + self.client = QuizReportsAPI(secrets.instance_address, secrets.access_token) + + def test_retrieve_all_quiz_reports(self): + """Integration test for the QuizReportsAPI.retrieve_all_quiz_reports method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + + r = self.client.retrieve_all_quiz_reports(quiz_id, course_id, includes_all_versions=None) + + def test_create_quiz_report(self): + """Integration test for the QuizReportsAPI.create_quiz_report method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_quiz_report(self): + """Integration test for the QuizReportsAPI.get_quiz_report method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_quiz_report(id, quiz_id, course_id, include=None) + + def test_abort_generation_of_report_or_remove_previously_generated_one(self): + """Integration test for the QuizReportsAPI.abort_generation_of_report_or_remove_previously_generated_one method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.abort_generation_of_report_or_remove_previously_generated_one(id, quiz_id, course_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_statistics.py b/venv/Lib/site-packages/pycanvas/tests/quiz_statistics.py new file mode 100644 index 00000000..63c90212 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_statistics.py @@ -0,0 +1,29 @@ +"""QuizStatistics API Tests for Version 1.0. + +This is a testing template for the generated QuizStatisticsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_statistics import QuizStatisticsAPI +from pycanvas.apis.quiz_statistics import Quizstatisticsquestionstatistics +from pycanvas.apis.quiz_statistics import Quizstatistics +from pycanvas.apis.quiz_statistics import Quizstatisticsanswerpointbiserial +from pycanvas.apis.quiz_statistics import Quizstatisticsanswerstatistics +from pycanvas.apis.quiz_statistics import Quizstatisticslinks +from pycanvas.apis.quiz_statistics import Quizstatisticssubmissionstatistics + + +class TestQuizStatisticsAPI(unittest.TestCase): + """Tests for the QuizStatisticsAPI.""" + + def setUp(self): + self.client = QuizStatisticsAPI(secrets.instance_address, secrets.access_token) + + def test_fetching_latest_quiz_statistics(self): + """Integration test for the QuizStatisticsAPI.fetching_latest_quiz_statistics method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + + r = self.client.fetching_latest_quiz_statistics(quiz_id, course_id, all_versions=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_submission_events.py b/venv/Lib/site-packages/pycanvas/tests/quiz_submission_events.py new file mode 100644 index 00000000..9a1f32f4 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_submission_events.py @@ -0,0 +1,30 @@ +"""QuizSubmissionEvents API Tests for Version 1.0. + +This is a testing template for the generated QuizSubmissionEventsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_submission_events import QuizSubmissionEventsAPI +from pycanvas.apis.quiz_submission_events import Quizsubmissionevent + + +class TestQuizSubmissionEventsAPI(unittest.TestCase): + """Tests for the QuizSubmissionEventsAPI.""" + + def setUp(self): + self.client = QuizSubmissionEventsAPI(secrets.instance_address, secrets.access_token) + + def test_submit_captured_events(self): + """Integration test for the QuizSubmissionEventsAPI.submit_captured_events method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_retrieve_captured_events(self): + """Integration test for the QuizSubmissionEventsAPI.retrieve_captured_events method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.retrieve_captured_events(id, quiz_id, course_id, attempt=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_submission_files.py b/venv/Lib/site-packages/pycanvas/tests/quiz_submission_files.py new file mode 100644 index 00000000..029e0ec8 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_submission_files.py @@ -0,0 +1,21 @@ +"""QuizSubmissionFiles API Tests for Version 1.0. + +This is a testing template for the generated QuizSubmissionFilesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_submission_files import QuizSubmissionFilesAPI + + +class TestQuizSubmissionFilesAPI(unittest.TestCase): + """Tests for the QuizSubmissionFilesAPI.""" + + def setUp(self): + self.client = QuizSubmissionFilesAPI(secrets.instance_address, secrets.access_token) + + def test_upload_file(self): + """Integration test for the QuizSubmissionFilesAPI.upload_file method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_submission_questions.py b/venv/Lib/site-packages/pycanvas/tests/quiz_submission_questions.py new file mode 100644 index 00000000..fe64903e --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_submission_questions.py @@ -0,0 +1,38 @@ +"""QuizSubmissionQuestions API Tests for Version 1.0. + +This is a testing template for the generated QuizSubmissionQuestionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_submission_questions import QuizSubmissionQuestionsAPI +from pycanvas.apis.quiz_submission_questions import Quizsubmissionquestion + + +class TestQuizSubmissionQuestionsAPI(unittest.TestCase): + """Tests for the QuizSubmissionQuestionsAPI.""" + + def setUp(self): + self.client = QuizSubmissionQuestionsAPI(secrets.instance_address, secrets.access_token) + + def test_get_all_quiz_submission_questions(self): + """Integration test for the QuizSubmissionQuestionsAPI.get_all_quiz_submission_questions method.""" + quiz_submission_id = None # Change me!! + + r = self.client.get_all_quiz_submission_questions(quiz_submission_id, include=None) + + def test_answering_questions(self): + """Integration test for the QuizSubmissionQuestionsAPI.answering_questions method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_flagging_question(self): + """Integration test for the QuizSubmissionQuestionsAPI.flagging_question method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_unflagging_question(self): + """Integration test for the QuizSubmissionQuestionsAPI.unflagging_question method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_submission_user_list.py b/venv/Lib/site-packages/pycanvas/tests/quiz_submission_user_list.py new file mode 100644 index 00000000..eb8df5f0 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_submission_user_list.py @@ -0,0 +1,24 @@ +"""QuizSubmissionUserList API Tests for Version 1.0. + +This is a testing template for the generated QuizSubmissionUserListAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_submission_user_list import QuizSubmissionUserListAPI +from pycanvas.apis.quiz_submission_user_list import Jsonapipagination +from pycanvas.apis.quiz_submission_user_list import Quizsubmissionuserlistmeta +from pycanvas.apis.quiz_submission_user_list import Quizsubmissionuserlist + + +class TestQuizSubmissionUserListAPI(unittest.TestCase): + """Tests for the QuizSubmissionUserListAPI.""" + + def setUp(self): + self.client = QuizSubmissionUserListAPI(secrets.instance_address, secrets.access_token) + + def test_send_message_to_unsubmitted_or_submitted_users_for_quiz(self): + """Integration test for the QuizSubmissionUserListAPI.send_message_to_unsubmitted_or_submitted_users_for_quiz method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/quiz_submissions.py b/venv/Lib/site-packages/pycanvas/tests/quiz_submissions.py new file mode 100644 index 00000000..8aa16b7a --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quiz_submissions.py @@ -0,0 +1,62 @@ +"""QuizSubmissions API Tests for Version 1.0. + +This is a testing template for the generated QuizSubmissionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quiz_submissions import QuizSubmissionsAPI +from pycanvas.apis.quiz_submissions import Quizsubmission + + +class TestQuizSubmissionsAPI(unittest.TestCase): + """Tests for the QuizSubmissionsAPI.""" + + def setUp(self): + self.client = QuizSubmissionsAPI(secrets.instance_address, secrets.access_token) + + def test_get_all_quiz_submissions(self): + """Integration test for the QuizSubmissionsAPI.get_all_quiz_submissions method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + + r = self.client.get_all_quiz_submissions(quiz_id, course_id, include=None) + + def test_get_quiz_submission(self): + """Integration test for the QuizSubmissionsAPI.get_quiz_submission method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + + r = self.client.get_quiz_submission(quiz_id, course_id, include=None) + + def test_get_single_quiz_submission(self): + """Integration test for the QuizSubmissionsAPI.get_single_quiz_submission method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_quiz_submission(id, quiz_id, course_id, include=None) + + def test_create_quiz_submission_start_quiz_taking_session(self): + """Integration test for the QuizSubmissionsAPI.create_quiz_submission_start_quiz_taking_session method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_student_question_scores_and_comments(self): + """Integration test for the QuizSubmissionsAPI.update_student_question_scores_and_comments method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_complete_quiz_submission_turn_it_in(self): + """Integration test for the QuizSubmissionsAPI.complete_quiz_submission_turn_it_in method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_current_quiz_submission_times(self): + """Integration test for the QuizSubmissionsAPI.get_current_quiz_submission_times method.""" + course_id = None # Change me!! + quiz_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_current_quiz_submission_times(id, quiz_id, course_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/quizzes.py b/venv/Lib/site-packages/pycanvas/tests/quizzes.py new file mode 100644 index 00000000..035e138f --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/quizzes.py @@ -0,0 +1,58 @@ +"""Quizzes API Tests for Version 1.0. + +This is a testing template for the generated QuizzesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.quizzes import QuizzesAPI +from pycanvas.apis.quizzes import Quizpermissions +from pycanvas.apis.quizzes import Quiz + + +class TestQuizzesAPI(unittest.TestCase): + """Tests for the QuizzesAPI.""" + + def setUp(self): + self.client = QuizzesAPI(secrets.instance_address, secrets.access_token) + + def test_list_quizzes_in_course(self): + """Integration test for the QuizzesAPI.list_quizzes_in_course method.""" + course_id = None # Change me!! + + r = self.client.list_quizzes_in_course(course_id, search_term=None) + + def test_get_single_quiz(self): + """Integration test for the QuizzesAPI.get_single_quiz method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_single_quiz(id, course_id) + + def test_create_quiz(self): + """Integration test for the QuizzesAPI.create_quiz method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_edit_quiz(self): + """Integration test for the QuizzesAPI.edit_quiz method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_delete_quiz(self): + """Integration test for the QuizzesAPI.delete_quiz method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.delete_quiz(id, course_id) + + def test_reorder_quiz_items(self): + """Integration test for the QuizzesAPI.reorder_quiz_items method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_validate_quiz_access_code(self): + """Integration test for the QuizzesAPI.validate_quiz_access_code method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/roles.py b/venv/Lib/site-packages/pycanvas/tests/roles.py new file mode 100644 index 00000000..e588e73e --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/roles.py @@ -0,0 +1,55 @@ +"""Roles API Tests for Version 1.0. + +This is a testing template for the generated RolesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.roles import RolesAPI +from pycanvas.apis.roles import Rolepermissions +from pycanvas.apis.roles import Role + + +class TestRolesAPI(unittest.TestCase): + """Tests for the RolesAPI.""" + + def setUp(self): + self.client = RolesAPI(secrets.instance_address, secrets.access_token) + + def test_list_roles(self): + """Integration test for the RolesAPI.list_roles method.""" + account_id = None # Change me!! + + r = self.client.list_roles(account_id, show_inherited=None, state=None) + + def test_get_single_role(self): + """Integration test for the RolesAPI.get_single_role method.""" + id = None # Change me!! + account_id = None # Change me!! + role_id = None # Change me!! + + r = self.client.get_single_role(id, role_id, account_id, role=None) + + def test_create_new_role(self): + """Integration test for the RolesAPI.create_new_role method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_deactivate_role(self): + """Integration test for the RolesAPI.deactivate_role method.""" + account_id = None # Change me!! + id = None # Change me!! + role_id = None # Change me!! + + r = self.client.deactivate_role(id, role_id, account_id, role=None) + + def test_activate_role(self): + """Integration test for the RolesAPI.activate_role method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_role(self): + """Integration test for the RolesAPI.update_role method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/search.py b/venv/Lib/site-packages/pycanvas/tests/search.py new file mode 100644 index 00000000..a4bafa04 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/search.py @@ -0,0 +1,31 @@ +"""Search API Tests for Version 1.0. + +This is a testing template for the generated SearchAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.search import SearchAPI + + +class TestSearchAPI(unittest.TestCase): + """Tests for the SearchAPI.""" + + def setUp(self): + self.client = SearchAPI(secrets.instance_address, secrets.access_token) + + def test_find_recipients_conversations(self): + """Integration test for the SearchAPI.find_recipients_conversations method.""" + + r = self.client.find_recipients_conversations(context=None, exclude=None, from_conversation_id=None, permissions=None, search=None, type=None, user_id=None) + + def test_find_recipients_search(self): + """Integration test for the SearchAPI.find_recipients_search method.""" + + r = self.client.find_recipients_search(context=None, exclude=None, from_conversation_id=None, permissions=None, search=None, type=None, user_id=None) + + def test_list_all_courses(self): + """Integration test for the SearchAPI.list_all_courses method.""" + + r = self.client.list_all_courses(open_enrollment_only=None, public_only=None, search=None) + diff --git a/venv/Lib/site-packages/pycanvas/tests/secrets.py b/venv/Lib/site-packages/pycanvas/tests/secrets.py new file mode 100644 index 00000000..a4a7aec4 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/secrets.py @@ -0,0 +1,5 @@ +"""Secrets for testing the generated API's""" + +instance_address = "https://stmonicas.test.instructure.com" + +access_token = "6523~AJ1j8iJ26Bk99FjlrwpR59ymCoT0PLx8uAdZLAn1LWkJehiPfxNzg2k8qwiBUq4y" diff --git a/venv/Lib/site-packages/pycanvas/tests/sections.py b/venv/Lib/site-packages/pycanvas/tests/sections.py new file mode 100644 index 00000000..c85cfef1 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/sections.py @@ -0,0 +1,63 @@ +"""Sections API Tests for Version 1.0. + +This is a testing template for the generated SectionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.sections import SectionsAPI +from pycanvas.apis.sections import Section + + +class TestSectionsAPI(unittest.TestCase): + """Tests for the SectionsAPI.""" + + def setUp(self): + self.client = SectionsAPI(secrets.instance_address, secrets.access_token) + + def test_list_course_sections(self): + """Integration test for the SectionsAPI.list_course_sections method.""" + course_id = None # Change me!! + + r = self.client.list_course_sections(course_id, include=None) + + def test_create_course_section(self): + """Integration test for the SectionsAPI.create_course_section method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_cross_list_section(self): + """Integration test for the SectionsAPI.cross_list_section method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_de_cross_list_section(self): + """Integration test for the SectionsAPI.de_cross_list_section method.""" + id = None # Change me!! + + r = self.client.de_cross_list_section(id) + + def test_edit_section(self): + """Integration test for the SectionsAPI.edit_section method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_section_information_courses(self): + """Integration test for the SectionsAPI.get_section_information_courses method.""" + course_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_section_information_courses(id, course_id, include=None) + + def test_get_section_information_sections(self): + """Integration test for the SectionsAPI.get_section_information_sections method.""" + id = None # Change me!! + + r = self.client.get_section_information_sections(id, include=None) + + def test_delete_section(self): + """Integration test for the SectionsAPI.delete_section method.""" + id = None # Change me!! + + r = self.client.delete_section(id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/services.py b/venv/Lib/site-packages/pycanvas/tests/services.py new file mode 100644 index 00000000..8c78a0e8 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/services.py @@ -0,0 +1,26 @@ +"""Services API Tests for Version 1.0. + +This is a testing template for the generated ServicesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.services import ServicesAPI + + +class TestServicesAPI(unittest.TestCase): + """Tests for the ServicesAPI.""" + + def setUp(self): + self.client = ServicesAPI(secrets.instance_address, secrets.access_token) + + def test_get_kaltura_config(self): + """Integration test for the ServicesAPI.get_kaltura_config method.""" + + r = self.client.get_kaltura_config() + + def test_start_kaltura_session(self): + """Integration test for the ServicesAPI.start_kaltura_session method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/sis_imports.py b/venv/Lib/site-packages/pycanvas/tests/sis_imports.py new file mode 100644 index 00000000..842103de --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/sis_imports.py @@ -0,0 +1,47 @@ +"""SisImports API Tests for Version 1.0. + +This is a testing template for the generated SisImportsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.sis_imports import SisImportsAPI +from pycanvas.apis.sis_imports import Sisimport +from pycanvas.apis.sis_imports import Sisimportcounts +from pycanvas.apis.sis_imports import Sisimportdata + + +class TestSisImportsAPI(unittest.TestCase): + """Tests for the SisImportsAPI.""" + + def setUp(self): + self.client = SisImportsAPI(secrets.instance_address, secrets.access_token) + + def test_get_sis_import_list(self): + """Integration test for the SisImportsAPI.get_sis_import_list method.""" + account_id = None # Change me!! + + r = self.client.get_sis_import_list(account_id, created_since=None) + + def test_import_sis_data(self): + """Integration test for the SisImportsAPI.import_sis_data method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_sis_import_status(self): + """Integration test for the SisImportsAPI.get_sis_import_status method.""" + account_id = None # Change me!! + id = None # Change me!! + + r = self.client.get_sis_import_status(id, account_id) + + def test_abort_sis_import(self): + """Integration test for the SisImportsAPI.abort_sis_import method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_abort_all_pending_sis_imports(self): + """Integration test for the SisImportsAPI.abort_all_pending_sis_imports method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/submission_comments.py b/venv/Lib/site-packages/pycanvas/tests/submission_comments.py new file mode 100644 index 00000000..d3599a5c --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/submission_comments.py @@ -0,0 +1,21 @@ +"""SubmissionComments API Tests for Version 1.0. + +This is a testing template for the generated SubmissionCommentsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.submission_comments import SubmissionCommentsAPI + + +class TestSubmissionCommentsAPI(unittest.TestCase): + """Tests for the SubmissionCommentsAPI.""" + + def setUp(self): + self.client = SubmissionCommentsAPI(secrets.instance_address, secrets.access_token) + + def test_upload_file(self): + """Integration test for the SubmissionCommentsAPI.upload_file method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/submissions.py b/venv/Lib/site-packages/pycanvas/tests/submissions.py new file mode 100644 index 00000000..b2cd7b0c --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/submissions.py @@ -0,0 +1,144 @@ +"""Submissions API Tests for Version 1.0. + +This is a testing template for the generated SubmissionsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.submissions import SubmissionsAPI +from pycanvas.apis.submissions import Submissioncomment +from pycanvas.apis.submissions import Submission +from pycanvas.apis.submissions import Mediacomment + + +class TestSubmissionsAPI(unittest.TestCase): + """Tests for the SubmissionsAPI.""" + + def setUp(self): + self.client = SubmissionsAPI(secrets.instance_address, secrets.access_token) + + def test_submit_assignment_courses(self): + """Integration test for the SubmissionsAPI.submit_assignment_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_submit_assignment_sections(self): + """Integration test for the SubmissionsAPI.submit_assignment_sections method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_assignment_submissions_courses(self): + """Integration test for the SubmissionsAPI.list_assignment_submissions_courses method.""" + course_id = None # Change me!! + assignment_id = None # Change me!! + + r = self.client.list_assignment_submissions_courses(course_id, assignment_id, grouped=None, include=None) + + def test_list_assignment_submissions_sections(self): + """Integration test for the SubmissionsAPI.list_assignment_submissions_sections method.""" + section_id = None # Change me!! + assignment_id = None # Change me!! + + r = self.client.list_assignment_submissions_sections(section_id, assignment_id, grouped=None, include=None) + + def test_list_submissions_for_multiple_assignments_courses(self): + """Integration test for the SubmissionsAPI.list_submissions_for_multiple_assignments_courses method.""" + course_id = None # Change me!! + + r = self.client.list_submissions_for_multiple_assignments_courses(course_id, assignment_ids=None, grading_period_id=None, grouped=None, include=None, order=None, order_direction=None, student_ids=None) + + def test_list_submissions_for_multiple_assignments_sections(self): + """Integration test for the SubmissionsAPI.list_submissions_for_multiple_assignments_sections method.""" + section_id = None # Change me!! + + r = self.client.list_submissions_for_multiple_assignments_sections(section_id, assignment_ids=None, grading_period_id=None, grouped=None, include=None, order=None, order_direction=None, student_ids=None) + + def test_get_single_submission_courses(self): + """Integration test for the SubmissionsAPI.get_single_submission_courses method.""" + course_id = None # Change me!! + assignment_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.get_single_submission_courses(user_id, course_id, assignment_id, include=None) + + def test_get_single_submission_sections(self): + """Integration test for the SubmissionsAPI.get_single_submission_sections method.""" + section_id = None # Change me!! + assignment_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.get_single_submission_sections(user_id, section_id, assignment_id, include=None) + + def test_upload_file_courses(self): + """Integration test for the SubmissionsAPI.upload_file_courses method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_upload_file_sections(self): + """Integration test for the SubmissionsAPI.upload_file_sections method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_grade_or_comment_on_submission_courses(self): + """Integration test for the SubmissionsAPI.grade_or_comment_on_submission_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_grade_or_comment_on_submission_sections(self): + """Integration test for the SubmissionsAPI.grade_or_comment_on_submission_sections method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_list_gradeable_students(self): + """Integration test for the SubmissionsAPI.list_gradeable_students method.""" + course_id = None # Change me!! + assignment_id = None # Change me!! + + r = self.client.list_gradeable_students(course_id, assignment_id) + + def test_grade_or_comment_on_multiple_submissions_courses_submissions(self): + """Integration test for the SubmissionsAPI.grade_or_comment_on_multiple_submissions_courses_submissions method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_grade_or_comment_on_multiple_submissions_courses_assignments(self): + """Integration test for the SubmissionsAPI.grade_or_comment_on_multiple_submissions_courses_assignments method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_grade_or_comment_on_multiple_submissions_sections_submissions(self): + """Integration test for the SubmissionsAPI.grade_or_comment_on_multiple_submissions_sections_submissions method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_grade_or_comment_on_multiple_submissions_sections_assignments(self): + """Integration test for the SubmissionsAPI.grade_or_comment_on_multiple_submissions_sections_assignments method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_submission_as_read_courses(self): + """Integration test for the SubmissionsAPI.mark_submission_as_read_courses method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_submission_as_read_sections(self): + """Integration test for the SubmissionsAPI.mark_submission_as_read_sections method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_mark_submission_as_unread_courses(self): + """Integration test for the SubmissionsAPI.mark_submission_as_unread_courses method.""" + course_id = None # Change me!! + assignment_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.mark_submission_as_unread_courses(user_id, course_id, assignment_id) + + def test_mark_submission_as_unread_sections(self): + """Integration test for the SubmissionsAPI.mark_submission_as_unread_sections method.""" + section_id = None # Change me!! + assignment_id = None # Change me!! + user_id = None # Change me!! + + r = self.client.mark_submission_as_unread_sections(user_id, section_id, assignment_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/tabs.py b/venv/Lib/site-packages/pycanvas/tests/tabs.py new file mode 100644 index 00000000..658c2370 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/tabs.py @@ -0,0 +1,34 @@ +"""Tabs API Tests for Version 1.0. + +This is a testing template for the generated TabsAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.tabs import TabsAPI +from pycanvas.apis.tabs import Tab + + +class TestTabsAPI(unittest.TestCase): + """Tests for the TabsAPI.""" + + def setUp(self): + self.client = TabsAPI(secrets.instance_address, secrets.access_token) + + def test_list_available_tabs_for_course_or_group_courses(self): + """Integration test for the TabsAPI.list_available_tabs_for_course_or_group_courses method.""" + course_id = None # Change me!! + + r = self.client.list_available_tabs_for_course_or_group_courses(course_id, include=None) + + def test_list_available_tabs_for_course_or_group_groups(self): + """Integration test for the TabsAPI.list_available_tabs_for_course_or_group_groups method.""" + group_id = None # Change me!! + + r = self.client.list_available_tabs_for_course_or_group_groups(group_id, include=None) + + def test_update_tab_for_course(self): + """Integration test for the TabsAPI.update_tab_for_course method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + diff --git a/venv/Lib/site-packages/pycanvas/tests/user_observees.py b/venv/Lib/site-packages/pycanvas/tests/user_observees.py new file mode 100644 index 00000000..4760b9b9 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/user_observees.py @@ -0,0 +1,46 @@ +"""UserObservees API Tests for Version 1.0. + +This is a testing template for the generated UserObserveesAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.user_observees import UserObserveesAPI + + +class TestUserObserveesAPI(unittest.TestCase): + """Tests for the UserObserveesAPI.""" + + def setUp(self): + self.client = UserObserveesAPI(secrets.instance_address, secrets.access_token) + + def test_list_observees(self): + """Integration test for the UserObserveesAPI.list_observees method.""" + user_id = None # Change me!! + + r = self.client.list_observees(user_id, include=None) + + def test_add_observee_with_credentials(self): + """Integration test for the UserObserveesAPI.add_observee_with_credentials method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_show_observee(self): + """Integration test for the UserObserveesAPI.show_observee method.""" + user_id = None # Change me!! + observee_id = None # Change me!! + + r = self.client.show_observee(user_id, observee_id) + + def test_add_observee(self): + """Integration test for the UserObserveesAPI.add_observee method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_remove_observee(self): + """Integration test for the UserObserveesAPI.remove_observee method.""" + user_id = None # Change me!! + observee_id = None # Change me!! + + r = self.client.remove_observee(user_id, observee_id) + diff --git a/venv/Lib/site-packages/pycanvas/tests/users.py b/venv/Lib/site-packages/pycanvas/tests/users.py new file mode 100644 index 00000000..726565c0 --- /dev/null +++ b/venv/Lib/site-packages/pycanvas/tests/users.py @@ -0,0 +1,211 @@ +"""Users API Tests for Version 1.0. + +This is a testing template for the generated UsersAPI Class. +""" +import unittest +import requests +import secrets +from pycanvas.apis.users import UsersAPI +from pycanvas.apis.users import Profile +from pycanvas.apis.users import Coursenickname +from pycanvas.apis.users import Pageview +from pycanvas.apis.users import Pageviewlinks +from pycanvas.apis.users import User +from pycanvas.apis.users import Userdisplay +from pycanvas.apis.users import Avatar + + +class TestUsersAPI(unittest.TestCase): + """Tests for the UsersAPI.""" + + def setUp(self): + self.client = UsersAPI(secrets.instance_address, secrets.access_token) + + def test_list_users_in_account(self): + """Integration test for the UsersAPI.list_users_in_account method.""" + account_id = None # Change me!! + + r = self.client.list_users_in_account(account_id, search_term=None) + + def test_list_activity_stream_self(self): + """Integration test for the UsersAPI.list_activity_stream_self method.""" + + r = self.client.list_activity_stream_self() + + def test_list_activity_stream_activity_stream(self): + """Integration test for the UsersAPI.list_activity_stream_activity_stream method.""" + + r = self.client.list_activity_stream_activity_stream() + + def test_activity_stream_summary(self): + """Integration test for the UsersAPI.activity_stream_summary method.""" + + r = self.client.activity_stream_summary() + + def test_list_todo_items(self): + """Integration test for the UsersAPI.list_todo_items method.""" + + r = self.client.list_todo_items(include=None) + + def test_list_upcoming_assignments_calendar_events(self): + """Integration test for the UsersAPI.list_upcoming_assignments_calendar_events method.""" + + r = self.client.list_upcoming_assignments_calendar_events() + + def test_list_missing_submissions(self): + """Integration test for the UsersAPI.list_missing_submissions method.""" + user_id = None # Change me!! + + r = self.client.list_missing_submissions(user_id) + + def test_hide_stream_item(self): + """Integration test for the UsersAPI.hide_stream_item method.""" + id = None # Change me!! + + r = self.client.hide_stream_item(id) + + def test_hide_all_stream_items(self): + """Integration test for the UsersAPI.hide_all_stream_items method.""" + + r = self.client.hide_all_stream_items() + + def test_upload_file(self): + """Integration test for the UsersAPI.upload_file method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_show_user_details(self): + """Integration test for the UsersAPI.show_user_details method.""" + id = None # Change me!! + + r = self.client.show_user_details(id) + + def test_create_user(self): + """Integration test for the UsersAPI.create_user method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_self_register_user(self): + """Integration test for the UsersAPI.self_register_user method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_update_user_settings(self): + """Integration test for the UsersAPI.update_user_settings method.""" + id = None # Change me!! + + r = self.client.update_user_settings(id, collapse_global_nav=None, manual_mark_as_read=None) + + def test_get_custom_colors(self): + """Integration test for the UsersAPI.get_custom_colors method.""" + id = None # Change me!! + + r = self.client.get_custom_colors(id) + + def test_get_custom_color(self): + """Integration test for the UsersAPI.get_custom_color method.""" + id = None # Change me!! + asset_string = None # Change me!! + + r = self.client.get_custom_color(id, asset_string) + + def test_update_custom_color(self): + """Integration test for the UsersAPI.update_custom_color method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_dashboard_postions(self): + """Integration test for the UsersAPI.get_dashboard_postions method.""" + id = None # Change me!! + + r = self.client.get_dashboard_postions(id) + + def test_update_dashboard_positions(self): + """Integration test for the UsersAPI.update_dashboard_positions method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_edit_user(self): + """Integration test for the UsersAPI.edit_user method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_merge_user_into_another_user_destination_user_id(self): + """Integration test for the UsersAPI.merge_user_into_another_user_destination_user_id method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_merge_user_into_another_user_accounts(self): + """Integration test for the UsersAPI.merge_user_into_another_user_accounts method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_split_merged_users_into_separate_users(self): + """Integration test for the UsersAPI.split_merged_users_into_separate_users method.""" + # This method utilises the POST request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_get_user_profile(self): + """Integration test for the UsersAPI.get_user_profile method.""" + user_id = None # Change me!! + + r = self.client.get_user_profile(user_id) + + def test_list_avatar_options(self): + """Integration test for the UsersAPI.list_avatar_options method.""" + user_id = None # Change me!! + + r = self.client.list_avatar_options(user_id) + + def test_list_user_page_views(self): + """Integration test for the UsersAPI.list_user_page_views method.""" + user_id = None # Change me!! + + r = self.client.list_user_page_views(user_id, end_time=None, start_time=None) + + def test_store_custom_data(self): + """Integration test for the UsersAPI.store_custom_data method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_load_custom_data(self): + """Integration test for the UsersAPI.load_custom_data method.""" + user_id = None # Change me!! + ns = None # Change me!! + + r = self.client.load_custom_data(ns, user_id) + + def test_delete_custom_data(self): + """Integration test for the UsersAPI.delete_custom_data method.""" + user_id = None # Change me!! + ns = None # Change me!! + + r = self.client.delete_custom_data(ns, user_id) + + def test_list_course_nicknames(self): + """Integration test for the UsersAPI.list_course_nicknames method.""" + + r = self.client.list_course_nicknames() + + def test_get_course_nickname(self): + """Integration test for the UsersAPI.get_course_nickname method.""" + course_id = None # Change me!! + + r = self.client.get_course_nickname(course_id) + + def test_set_course_nickname(self): + """Integration test for the UsersAPI.set_course_nickname method.""" + # This method utilises the PUT request method and will make changes to the Canvas instance. This needs consideration. + pass + + def test_remove_course_nickname(self): + """Integration test for the UsersAPI.remove_course_nickname method.""" + course_id = None # Change me!! + + r = self.client.remove_course_nickname(course_id) + + def test_clear_course_nicknames(self): + """Integration test for the UsersAPI.clear_course_nicknames method.""" + + r = self.client.clear_course_nicknames() + diff --git a/venv/Lib/site-packages/pytube/cipher.py b/venv/Lib/site-packages/pytube/cipher.py index 73164319..63e26fee 100644 --- a/venv/Lib/site-packages/pytube/cipher.py +++ b/venv/Lib/site-packages/pytube/cipher.py @@ -35,13 +35,20 @@ def get_initial_function_name(js): """ # c&&d.set("signature", EE(c)); + #pattern = [ + # r'yt\.akamaized\.net/\)\s*\|\|\s*' + # r'.*?\s*c\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent' + # r'\s*\()?(?P[a-zA-Z0-9$]+)\(', + # r'\.sig\|\|(?P[a-zA-Z0-9$]+)\(', + # r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent' + # r'\s*\()?(?P[a-zA-Z0-9$]+)\(', + #] pattern = [ - r'yt\.akamaized\.net/\)\s*\|\|\s*' - r'.*?\s*c\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent' - r'\s*\()?(?P[a-zA-Z0-9$]+)\(', + r'(["\'])signature\1\s*,\s*(?P[a-zA-Z0-9$]+)\(', r'\.sig\|\|(?P[a-zA-Z0-9$]+)\(', - r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent' - r'\s*\()?(?P[a-zA-Z0-9$]+)\(', + r'yt\.akamaized\.net/\)\s*\|\|\s*.*?\s*c\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?(?P[a-zA-Z0-9$]+)\(', + r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*(?:encodeURIComponent\s*\()?\s*(?P[a-zA-Z0-9$]+)\(', + r'\bc\s*&&\s*d\.set\([^,]+\s*,\s*\([^)]*\)\s*\(\s*(?P[a-zA-Z0-9$]+)\(', ] logger.debug('finding initial function name') return regex_search(pattern, js, group=1) diff --git a/web2py/applications/smc/controllers/media.py b/web2py/applications/smc/controllers/media.py index 72582cc1..62bfb47c 100644 --- a/web2py/applications/smc/controllers/media.py +++ b/web2py/applications/smc/controllers/media.py @@ -1503,7 +1503,7 @@ def find_replace_step_2(): fr_options = dict( auto_youtube_tool="YouTube -> SMC Links (ONLY WORKS ONLINE)", auto_google_docs_tool="Google Docs -> SMC Links (ONLY WORKS ONLINE)", - custom_regex="Custom Search/Replace RegEx (Not Done)", + custom_regex="Custom Find/Replace", ) option_list = [] @@ -1525,7 +1525,8 @@ def find_replace_step_2(): response.flash = "Google" pass elif form2.vars.fr_option == "custom_regex": - response.flash = "RegEx" + # response.flash = "RegEx" + redirect(URL('media', 'find_replace_step_custom_regex.load')) pass else: response.flash = "Unknown Option!" @@ -1535,6 +1536,146 @@ def find_replace_step_2(): server_url=server_url) +@auth.requires(auth.has_membership('Faculty') or auth.has_membership('Administrators')) +def find_replace_post_process_text(course_id, txt): + # Deal with left over cleaup for find/replace + + # Find canvas file ids. + pattern = re.compile("") + + match = pattern.search(txt) + while match is not None: + # Lookup the found file(s) + file_name = match.group(1) + file_id = Canvas.get_id_for_filename(course_id, file_name) + + # replace the original tag w the file id + txt = txt.replace("", str(file_id)) + match = pattern.search(txt) + + return txt + + +@auth.requires(auth.has_membership('Faculty') or auth.has_membership('Administrators')) +def find_replace_step_custom_regex_run(current_course, find_pattern, replace_pattern): + ret = "" + + # Get the list of pages + pages = Canvas.get_page_list_for_course(current_course) + total_pages = len(pages) + ret += "

Searched " + str(total_pages) + " pages

Search Pattern: " + \ + find_pattern.replace(">", ">").replace("<", "<") + \ + "
Note: Local URLs may not work in this view but work find when viewed from Canvas.
" + inc = 0 + for p in pages: + inc += 1 + p_orig_text = pages[p] + p_new_text, subs = re.subn(find_pattern, replace_pattern, p_orig_text) + p_new_text = find_replace_post_process_text(current_course, p_new_text) + + style = "width: 100%; height: 800px; overflow: auto; display: none; border: 1px solid black;" + ret += "
" + p + \ + " - " + str(subs) + " replacements.
" + + ret += "
" + ret += "

OLD PAGE

" + ret += "" + p_orig_text + "" + ret += "
" + ret += "

NEW PAGE

" + ret += "" + p_new_text + "" + ret += "
" + + if subs > 0: + # Update the page in canvas + new_page = dict() + new_page["wiki_page[body]"] = p_new_text + + result = Canvas.update_page_for_course(current_course, p, new_page) + # ret += result + return ret + + +@auth.requires(auth.has_membership('Faculty') or auth.has_membership('Administrators')) +def find_replace_step_custom_regex(): + ret = "" + + form2 = None + form3 = None + + server_url = Canvas._canvas_server_url + + current_course = request.vars.current_course + current_course_name = request.vars.current_course_name + + if current_course is not None: + session.fr_current_course = current_course + else: + current_course = session.fr_current_course + + if current_course_name is not None: + session.fr_current_course_name = current_course_name + else: + current_course_name = session.fr_current_course_name + + if current_course is None: + redirect(URL("find_replace.html")) + + # Make a form with the Find and Replace boxes + form2 = FORM(TABLE(TR("Find Pattern: ", INPUT(_type="text", _name="find_pattern")), + TR("Replace Pattern: ", INPUT(_type="text", _name="replace_pattern")), + TR("", INPUT(_type="submit", _value="Next"))), + _action=URL('media', 'find_replace_step_custom_regex.load'), + _name="form2").process(keepvalues=True, formname="form2") + + pre_defined_patterns = { + "Change Host Links - (smc.sbctc... -> smc.ed)": ["smc.sbctc.correctionsed.com", "smc.ed"], + "Change Host Links - (smc.ed -> smc.sbctc...)": ["smc.ed", "smc.sbctc.correctionsed.com"], + "IDEA - Listen Audio (change media tag to correct url)": + [r'''''', + r''''''], + } + + patterns_list = [] + for p in pre_defined_patterns: + patterns_list.append(OPTION(p, _value=p)) + + pre_defined_patterns_select = SELECT(patterns_list, _name="pattern_option", _style="width: 400px;") + + form3 = FORM(TABLE(TR(pre_defined_patterns_select), + TR(INPUT(_type="submit", _value="Next")) + ), + _action=URL('media', 'find_replace_step_custom_regex.load'), + _name="form3").process(keepvalues=True, formname="form3") + + if form2.accepted: + if form2.vars.find_pattern != "" and form2.vars.replace_pattern != "": + # Run find/replace pattern + find_pattern = form2.vars.find_pattern + replace_pattern = form2.vars.replace_pattern + + ret = find_replace_step_custom_regex_run(current_course, find_pattern, replace_pattern) + + elif form2.vars.find_pattern != "" and form2.vars.replace_pattern == "": + response.flash = "Find only not done." + else: + response.flash = "Please enter a find pattern to search for." + + pass + + if form3.accepted: + if form3.vars.pattern_option != "": + # Grab the find/replace patterns + find_pattern = pre_defined_patterns[form3.vars.pattern_option][0] + replace_pattern = pre_defined_patterns[form3.vars.pattern_option][1] + + ret = find_replace_step_custom_regex_run(current_course, find_pattern, replace_pattern) + else: + response.flash = "Please select an option to search for." + + return dict(form2=form2, current_course=current_course, current_course_name=current_course_name, + server_url=server_url, find_replace_results=XML(ret), form3=form3) + + @auth.requires(auth.has_membership('Faculty') or auth.has_membership('Administrators')) def find_replace_step_youtube(): server_url = Canvas._canvas_server_url @@ -1565,7 +1706,7 @@ def find_replace_step_youtube(): total_urls += len(urls) yt_urls[p] = urls - session.yt_urls =yt_urls + session.yt_urls = yt_urls session.yt_urls_curr_pos = 0 session.yt_urls_total_len = total_urls session.yt_urls_msg = "" @@ -1596,10 +1737,13 @@ def find_replace_step_youtube_progress(): try: # Get yt video info + # session.yt_urls_error_msg += "A" yt, stream, res = find_best_yt_stream(yt_url) + # session.yt_urls_error_msg += "AB" # Start download or get current db entry for this video media_file = queue_up_yt_video(yt_url, yt, res, current_course_name) + # session.yt_urls_error_msg += "B" vid_guid = media_file.media_guid title = media_file.title description = media_file.description @@ -1617,7 +1761,8 @@ def find_replace_step_youtube_progress(): session.yt_urls_msg += msg - session.yt_urls_status = str(session.yt_urls_curr_pos) + " of " + str(session.yt_urls_total_len) + " videos processed..." + session.yt_urls_status = str(session.yt_urls_curr_pos) + " of " + str(session.yt_urls_total_len) + \ + " videos processed..." if finished is not True: response.js = "web2py_component('" + URL('media', 'find_replace_step_youtube_progress.load') +\ @@ -1710,19 +1855,28 @@ def find_best_yt_stream(yt_url): stream = None # Change out embed for watch so the link works properly - yt = YouTube(yt_url.replace("/embed/", "/watch?v=")) - s = yt.streams.filter(file_extension='mp4', progressive=True, res=res).first() - if s is None: - # Try 360p - res = '360p' - s = yt.streams.filter(file_extension='mp4', progressive=True, res=res).first() - if s is None: - # Try 720p - res = '720p' + try: + yt = YouTube(yt_url.replace("/embed/", "/watch?v=")) + except Exception as ex: + session.yt_urls_error_msg += "Bad YT URL? " + yt_url + " -- " + str(ex) + + s = None + try: s = yt.streams.filter(file_extension='mp4', progressive=True, res=res).first() - if s is None: - # If that doesn't exist, then get the first one in the list - s = yt.streams.filter(file_extension='mp4', progressive=True).first() - # s.download() # put in folder name + if s is None: + # Try 360p + res = '360p' + s = yt.streams.filter(file_extension='mp4', progressive=True, res=res).first() + if s is None: + # Try 720p + res = '720p' + s = yt.streams.filter(file_extension='mp4', progressive=True, res=res).first() + if s is None: + # If that doesn't exist, then get the first one in the list + s = yt.streams.filter(file_extension='mp4', progressive=True).first() + # s.download() # put in folder name + except Exception as ex: + session.yt_urls_error_msg += "Error grabbing yt video info! " + str(ex) + stream = s return yt, stream, res diff --git a/web2py/applications/smc/modules/ednet/canvas.py b/web2py/applications/smc/modules/ednet/canvas.py index f623f7fe..25c9dea5 100644 --- a/web2py/applications/smc/modules/ednet/canvas.py +++ b/web2py/applications/smc/modules/ednet/canvas.py @@ -23,8 +23,9 @@ import hashlib from Crypto.Hash import SHA, HMAC - class Canvas: + # When needing to do paged requests, this will get filled in after APICall + _api_next = "" # Config Values _canvas_enabled = False @@ -626,6 +627,8 @@ def APICall(server, dev_key, api_call, method="GET", params=None, files=None, he headers = dict() response_items = dict() + # Reset the next link - for paging + Canvas._api_next = "" canvas_url = server + api_call headers["Authorization"] = "Bearer " + str(dev_key) @@ -649,6 +652,23 @@ def APICall(server, dev_key, api_call, method="GET", params=None, files=None, he return None if resp is not None: + # Pull the next link out of the header + link = resp.headers.get("Link") + if link is not None: + # print("Next Page: " + link) + # Split the links + links = link.split(',') + for l in links: + if 'rel="next"' in l: + # print("Found Next: " + l) + # Found the link + p = l.split(";") + # Save the link w out the <> around it + next_link = p[0].replace("<", "").replace(">", "") + # Save the next_link so we can use it later to grab the next page + Canvas._api_next = next_link + # print(" Got Next: " + Canvas._api_next) + try: ret = resp.json() except ValueError as error_message: @@ -687,6 +707,27 @@ def get_courses_for_faculty(faculty): return current_enrollment + @staticmethod + def get_id_for_filename(course_id, file_name): + ret = "" + Canvas.Init() + + api = "/api/v1/courses/" + course_id + "/files/?search_term=" + str(file_name) + + p = dict() + p["per_page"] = 20000 + + files_list = Canvas.APICall(Canvas._canvas_server_url, Canvas._canvas_access_token, + api, params=p) + + # Should be a list of files (should be 1) + for f in files_list: + # Need to make an API call to get the page body + ret = f['id'] + break # just grab the first match + + return ret + @staticmethod def get_page_list_for_course(course_id): Canvas.Init() @@ -694,11 +735,16 @@ def get_page_list_for_course(course_id): api = "/api/v1/courses/" + str(course_id) + "/pages" p = dict() - p["per_page"] = 20000 + p["per_page"] = 50 + + next_url = "" page_list = Canvas.APICall(Canvas._canvas_server_url, Canvas._canvas_access_token, api, params=p) + # If there are more pages, _api_next should have the link to the next page + next_url = Canvas._api_next + # print("Next URL: " + next_url) # Should be a list of pages, now get individual page bodies page_bodies = dict() for p in page_list: @@ -707,6 +753,22 @@ def get_page_list_for_course(course_id): page_bodies[p['url']] = page["body"] + while next_url != '': + # Calls to get more results (and strip off https://canvas.ed/) + api = next_url.replace(Canvas._canvas_server_url, "") + # print("Next API: " + api) + page_list = Canvas.APICall(Canvas._canvas_server_url, Canvas._canvas_access_token, + api) # Note - don't send params, they are in the api url + + # If there are more pages, _api_next should have the link to the next page + next_url = Canvas._api_next + # print("Next URL: " + next_url) + + for p in page_list: + # print("P: " + str(p)) + page = Canvas.get_page_for_course(course_id, p['url']) + page_bodies[p['url']] = page["body"] + return page_bodies @staticmethod @@ -739,6 +801,8 @@ def update_page_for_course(course_id, page_url, page): page = Canvas.APICall(Canvas._canvas_server_url, Canvas._canvas_access_token, api, params=p, method="PUT") + res = str(page) + return res @staticmethod diff --git a/web2py/applications/smc/views/media/find_replace_step_custom_regex.load b/web2py/applications/smc/views/media/find_replace_step_custom_regex.load new file mode 100644 index 00000000..63063e94 --- /dev/null +++ b/web2py/applications/smc/views/media/find_replace_step_custom_regex.load @@ -0,0 +1,37 @@ + +

Regular Expression Pattern Finder

+
+Finding text/links that match a pattern in all your pages and optionally replace it with new text. +
+ +
+
+ Using Course: {{=current_course_name + " (" + current_course + ")"}} +
+ +NOTE: This uses Regular Expressions. You can experiment with regular expressions online here: +Regex101.com +

+Lookup Values - You can use some values in the replace pattern to do additional lookups:
+<CANVAS_FILE_ID__[FILE_NAME]__> - Will look up the file ID and replace it - <CANVAS_FILE_ID__my-file__> becomes 1004213 + +

+ + + + + + +
+Enter Pattern
+{{=form2}} +
+Or use pre-defined pattern
+{{=form3}} +
+ +
+{{=find_replace_results}} +
+ +