openedx-plugin-sample 3.4.0__tar.gz → 3.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. openedx_plugin_sample-3.6.0/PKG-INFO +65 -0
  2. openedx_plugin_sample-3.6.0/README.md +36 -0
  3. openedx_plugin_sample-3.6.0/src/openedx_plugin_sample.egg-info/PKG-INFO +65 -0
  4. openedx_plugin_sample-3.4.0/PKG-INFO +0 -606
  5. openedx_plugin_sample-3.4.0/README.md +0 -577
  6. openedx_plugin_sample-3.4.0/src/openedx_plugin_sample.egg-info/PKG-INFO +0 -606
  7. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/.annotation_safe_list.yml +0 -0
  8. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/.coveragerc +0 -0
  9. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/.editorconfig +0 -0
  10. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/.gitignore +0 -0
  11. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/.pii_annotations.yml +0 -0
  12. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/.readthedocs.yaml +0 -0
  13. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/LICENSE.txt +0 -0
  14. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/Makefile +0 -0
  15. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/codecov.yml +0 -0
  16. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/Makefile +0 -0
  17. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/_static/theme_overrides.css +0 -0
  18. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/concepts/index.rst +0 -0
  19. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/conf.py +0 -0
  20. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/decisions/0001-purpose-of-this-repo.rst +0 -0
  21. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/decisions/README.rst +0 -0
  22. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/decisions.rst +0 -0
  23. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/getting_started.rst +0 -0
  24. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/how-tos/index.rst +0 -0
  25. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/index.rst +0 -0
  26. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/internationalization.rst +0 -0
  27. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/make.bat +0 -0
  28. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/openedx_plugin_sample.rst +0 -0
  29. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/quickstarts/index.rst +0 -0
  30. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/references/index.rst +0 -0
  31. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/docs/testing.rst +0 -0
  32. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/manage.py +0 -0
  33. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/pylintrc +0 -0
  34. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/pylintrc_tweaks +0 -0
  35. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/pyproject.toml +0 -0
  36. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/setup.cfg +0 -0
  37. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/__init__.py +0 -0
  38. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/admin.py +0 -0
  39. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/apps.py +0 -0
  40. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/conf/locale/config.yaml +0 -0
  41. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/migrations/0001_initial.py +0 -0
  42. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/migrations/__init__.py +0 -0
  43. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/models.py +0 -0
  44. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/pipeline.py +0 -0
  45. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/py.typed +0 -0
  46. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/serializers.py +0 -0
  47. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/settings/common.py +0 -0
  48. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/settings/production.py +0 -0
  49. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/settings/test.py +0 -0
  50. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/signals.py +0 -0
  51. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/templates/openedx_plugin_sample/base.html +0 -0
  52. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/urls.py +0 -0
  53. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample/views.py +0 -0
  54. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample.egg-info/SOURCES.txt +0 -0
  55. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample.egg-info/dependency_links.txt +0 -0
  56. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample.egg-info/entry_points.txt +0 -0
  57. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample.egg-info/requires.txt +0 -0
  58. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/src/openedx_plugin_sample.egg-info/top_level.txt +0 -0
  59. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/test_settings.py +0 -0
  60. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/test_utils/__init__.py +0 -0
  61. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/tests/test_api.py +0 -0
  62. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/tests/test_models.py +0 -0
  63. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/tests/test_pipeline.py +0 -0
  64. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/tests/test_plugin_integration.py +0 -0
  65. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/tests/test_signals.py +0 -0
  66. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/tests/urls.py +0 -0
  67. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/tox.ini +0 -0
  68. {openedx_plugin_sample-3.4.0 → openedx_plugin_sample-3.6.0}/uv.lock +0 -0
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: openedx-plugin-sample
3
+ Version: 3.6.0
4
+ Summary: A sample backend plugin for the Open edX Platform
5
+ Author-email: Open edX Project <oscm@openedx.org>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://openedx.org/openedx/sample-plugin
8
+ Project-URL: Repository, https://openedx.org/openedx/sample-plugin
9
+ Keywords: Python,edx
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: Django
12
+ Classifier: Framework :: Django :: 4.2
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Natural Language :: English
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Requires-Python: >=3.12
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE.txt
20
+ Requires-Dist: Django
21
+ Requires-Dist: djangorestframework
22
+ Requires-Dist: django-filter
23
+ Requires-Dist: edx-opaque-keys
24
+ Requires-Dist: openedx-core
25
+ Requires-Dist: openedx-events
26
+ Requires-Dist: openedx-filters
27
+ Requires-Dist: openedx-atlas
28
+ Dynamic: license-file
29
+
30
+ # backend-plugin-sample
31
+
32
+ A Django app plugin for edx-platform that adds a small course-archiving feature: learners can mark courses as archived (hidden from their active list) and unarchive them later. It demonstrates three backend extension points working together:
33
+
34
+ - A model + REST API (`CourseArchiveStatus`), consumed by [`frontend-plugin-sample`](../frontend-plugin-sample/)
35
+ - An [Open edX Events](https://docs.openedx.org/projects/openedx-events/en/latest/) handler that auto-unarchives on verified upgrade
36
+ - An [Open edX Filters](https://docs.openedx.org/projects/openedx-filters/en/latest/) pipeline step that rewrites the course-about URL
37
+
38
+ ## How to use it
39
+
40
+ See the root [README](../README.md) for setup instructions. With Tutor, [`tutor-contrib-sample`](../tutor-contrib-sample/) installs this plugin automatically (or bind-mounts your local checkout if you `tutor mounts add` it). Without Tutor, `pip install -e .` into your edx-platform environment and run migrations.
41
+
42
+ ## How it works
43
+
44
+ **Plugin registration.** [`apps.py`](./src/openedx_plugin_sample/apps.py) declares the Django app to edx-platform via the `plugin_app` config (URL routing, settings, signal registration). The entry points in [`pyproject.toml`](./pyproject.toml) make the platform discover the app automatically — no `INSTALLED_APPS` edit needed. See [How to create a plugin app](https://docs.openedx.org/projects/edx-django-utils/en/latest/plugins/how_tos/how_to_create_a_plugin_app.html).
45
+
46
+ **Model.** [`models.py`](./src/openedx_plugin_sample/models.py) defines `CourseArchiveStatus(user, course_id, is_archived, archive_date)`, indexed for the lookups the API performs. Registered in Django admin via [`admin.py`](./src/openedx_plugin_sample/admin.py).
47
+
48
+ **REST API.** [`views.py`](./src/openedx_plugin_sample/views.py) exposes the model as a DRF `ModelViewSet` at `/sample-plugin/api/v1/course-archive-status/`, with per-user permissions, throttling, and pagination. Serializer in [`serializers.py`](./src/openedx_plugin_sample/serializers.py); URLs in [`urls.py`](./src/openedx_plugin_sample/urls.py). Business logic (e.g. setting `archive_date` when `is_archived` becomes true) lives in `perform_create`/`perform_update` rather than in the serializer.
49
+
50
+ **Event handler.** [`signals.py`](./src/openedx_plugin_sample/signals.py) listens for `COURSE_ENROLLMENT_CHANGED` and unarchives a learner's course when they upgrade to the verified track. An event (not a filter) is the right shape here because we want a one-time nudge at the moment of upgrade — if the learner re-archives the course later, we respect that. A filter would re-impose the rule on every render.
51
+
52
+ **Filter.** [`pipeline.py`](./src/openedx_plugin_sample/pipeline.py) implements `ChangeCourseAboutPageUrl`, a `PipelineStep` for `org.openedx.learning.course.about.render.started.v1` that rewrites course-about URLs to an external host. Registered via `OPEN_EDX_FILTERS_CONFIG` in [`settings/common.py`](./src/openedx_plugin_sample/settings/common.py).
53
+
54
+ **Settings.** Per-environment settings live in [`settings/`](./src/openedx_plugin_sample/settings/) (`common.py`, `production.py`, `test.py`). The plugin app loads these via its `plugin_app` config in `apps.py`.
55
+
56
+ ## Testing and quality
57
+
58
+ ```bash
59
+ cd backend-plugin-sample
60
+ make requirements # install test deps
61
+ make test # pytest
62
+ make quality # lint
63
+ ```
64
+
65
+ Tests live in [`tests/`](./tests/).
@@ -0,0 +1,36 @@
1
+ # backend-plugin-sample
2
+
3
+ A Django app plugin for edx-platform that adds a small course-archiving feature: learners can mark courses as archived (hidden from their active list) and unarchive them later. It demonstrates three backend extension points working together:
4
+
5
+ - A model + REST API (`CourseArchiveStatus`), consumed by [`frontend-plugin-sample`](../frontend-plugin-sample/)
6
+ - An [Open edX Events](https://docs.openedx.org/projects/openedx-events/en/latest/) handler that auto-unarchives on verified upgrade
7
+ - An [Open edX Filters](https://docs.openedx.org/projects/openedx-filters/en/latest/) pipeline step that rewrites the course-about URL
8
+
9
+ ## How to use it
10
+
11
+ See the root [README](../README.md) for setup instructions. With Tutor, [`tutor-contrib-sample`](../tutor-contrib-sample/) installs this plugin automatically (or bind-mounts your local checkout if you `tutor mounts add` it). Without Tutor, `pip install -e .` into your edx-platform environment and run migrations.
12
+
13
+ ## How it works
14
+
15
+ **Plugin registration.** [`apps.py`](./src/openedx_plugin_sample/apps.py) declares the Django app to edx-platform via the `plugin_app` config (URL routing, settings, signal registration). The entry points in [`pyproject.toml`](./pyproject.toml) make the platform discover the app automatically — no `INSTALLED_APPS` edit needed. See [How to create a plugin app](https://docs.openedx.org/projects/edx-django-utils/en/latest/plugins/how_tos/how_to_create_a_plugin_app.html).
16
+
17
+ **Model.** [`models.py`](./src/openedx_plugin_sample/models.py) defines `CourseArchiveStatus(user, course_id, is_archived, archive_date)`, indexed for the lookups the API performs. Registered in Django admin via [`admin.py`](./src/openedx_plugin_sample/admin.py).
18
+
19
+ **REST API.** [`views.py`](./src/openedx_plugin_sample/views.py) exposes the model as a DRF `ModelViewSet` at `/sample-plugin/api/v1/course-archive-status/`, with per-user permissions, throttling, and pagination. Serializer in [`serializers.py`](./src/openedx_plugin_sample/serializers.py); URLs in [`urls.py`](./src/openedx_plugin_sample/urls.py). Business logic (e.g. setting `archive_date` when `is_archived` becomes true) lives in `perform_create`/`perform_update` rather than in the serializer.
20
+
21
+ **Event handler.** [`signals.py`](./src/openedx_plugin_sample/signals.py) listens for `COURSE_ENROLLMENT_CHANGED` and unarchives a learner's course when they upgrade to the verified track. An event (not a filter) is the right shape here because we want a one-time nudge at the moment of upgrade — if the learner re-archives the course later, we respect that. A filter would re-impose the rule on every render.
22
+
23
+ **Filter.** [`pipeline.py`](./src/openedx_plugin_sample/pipeline.py) implements `ChangeCourseAboutPageUrl`, a `PipelineStep` for `org.openedx.learning.course.about.render.started.v1` that rewrites course-about URLs to an external host. Registered via `OPEN_EDX_FILTERS_CONFIG` in [`settings/common.py`](./src/openedx_plugin_sample/settings/common.py).
24
+
25
+ **Settings.** Per-environment settings live in [`settings/`](./src/openedx_plugin_sample/settings/) (`common.py`, `production.py`, `test.py`). The plugin app loads these via its `plugin_app` config in `apps.py`.
26
+
27
+ ## Testing and quality
28
+
29
+ ```bash
30
+ cd backend-plugin-sample
31
+ make requirements # install test deps
32
+ make test # pytest
33
+ make quality # lint
34
+ ```
35
+
36
+ Tests live in [`tests/`](./tests/).
@@ -0,0 +1,65 @@
1
+ Metadata-Version: 2.4
2
+ Name: openedx-plugin-sample
3
+ Version: 3.6.0
4
+ Summary: A sample backend plugin for the Open edX Platform
5
+ Author-email: Open edX Project <oscm@openedx.org>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://openedx.org/openedx/sample-plugin
8
+ Project-URL: Repository, https://openedx.org/openedx/sample-plugin
9
+ Keywords: Python,edx
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: Django
12
+ Classifier: Framework :: Django :: 4.2
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Natural Language :: English
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Requires-Python: >=3.12
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE.txt
20
+ Requires-Dist: Django
21
+ Requires-Dist: djangorestframework
22
+ Requires-Dist: django-filter
23
+ Requires-Dist: edx-opaque-keys
24
+ Requires-Dist: openedx-core
25
+ Requires-Dist: openedx-events
26
+ Requires-Dist: openedx-filters
27
+ Requires-Dist: openedx-atlas
28
+ Dynamic: license-file
29
+
30
+ # backend-plugin-sample
31
+
32
+ A Django app plugin for edx-platform that adds a small course-archiving feature: learners can mark courses as archived (hidden from their active list) and unarchive them later. It demonstrates three backend extension points working together:
33
+
34
+ - A model + REST API (`CourseArchiveStatus`), consumed by [`frontend-plugin-sample`](../frontend-plugin-sample/)
35
+ - An [Open edX Events](https://docs.openedx.org/projects/openedx-events/en/latest/) handler that auto-unarchives on verified upgrade
36
+ - An [Open edX Filters](https://docs.openedx.org/projects/openedx-filters/en/latest/) pipeline step that rewrites the course-about URL
37
+
38
+ ## How to use it
39
+
40
+ See the root [README](../README.md) for setup instructions. With Tutor, [`tutor-contrib-sample`](../tutor-contrib-sample/) installs this plugin automatically (or bind-mounts your local checkout if you `tutor mounts add` it). Without Tutor, `pip install -e .` into your edx-platform environment and run migrations.
41
+
42
+ ## How it works
43
+
44
+ **Plugin registration.** [`apps.py`](./src/openedx_plugin_sample/apps.py) declares the Django app to edx-platform via the `plugin_app` config (URL routing, settings, signal registration). The entry points in [`pyproject.toml`](./pyproject.toml) make the platform discover the app automatically — no `INSTALLED_APPS` edit needed. See [How to create a plugin app](https://docs.openedx.org/projects/edx-django-utils/en/latest/plugins/how_tos/how_to_create_a_plugin_app.html).
45
+
46
+ **Model.** [`models.py`](./src/openedx_plugin_sample/models.py) defines `CourseArchiveStatus(user, course_id, is_archived, archive_date)`, indexed for the lookups the API performs. Registered in Django admin via [`admin.py`](./src/openedx_plugin_sample/admin.py).
47
+
48
+ **REST API.** [`views.py`](./src/openedx_plugin_sample/views.py) exposes the model as a DRF `ModelViewSet` at `/sample-plugin/api/v1/course-archive-status/`, with per-user permissions, throttling, and pagination. Serializer in [`serializers.py`](./src/openedx_plugin_sample/serializers.py); URLs in [`urls.py`](./src/openedx_plugin_sample/urls.py). Business logic (e.g. setting `archive_date` when `is_archived` becomes true) lives in `perform_create`/`perform_update` rather than in the serializer.
49
+
50
+ **Event handler.** [`signals.py`](./src/openedx_plugin_sample/signals.py) listens for `COURSE_ENROLLMENT_CHANGED` and unarchives a learner's course when they upgrade to the verified track. An event (not a filter) is the right shape here because we want a one-time nudge at the moment of upgrade — if the learner re-archives the course later, we respect that. A filter would re-impose the rule on every render.
51
+
52
+ **Filter.** [`pipeline.py`](./src/openedx_plugin_sample/pipeline.py) implements `ChangeCourseAboutPageUrl`, a `PipelineStep` for `org.openedx.learning.course.about.render.started.v1` that rewrites course-about URLs to an external host. Registered via `OPEN_EDX_FILTERS_CONFIG` in [`settings/common.py`](./src/openedx_plugin_sample/settings/common.py).
53
+
54
+ **Settings.** Per-environment settings live in [`settings/`](./src/openedx_plugin_sample/settings/) (`common.py`, `production.py`, `test.py`). The plugin app loads these via its `plugin_app` config in `apps.py`.
55
+
56
+ ## Testing and quality
57
+
58
+ ```bash
59
+ cd backend-plugin-sample
60
+ make requirements # install test deps
61
+ make test # pytest
62
+ make quality # lint
63
+ ```
64
+
65
+ Tests live in [`tests/`](./tests/).