Compare commits

...

68 Commits

Author SHA1 Message Date
Florian du Garage Num
ab18396e89 remove hard-coded uid 1000
Some checks failed
Sync with private repo / sync (push) Has been cancelled
Run tests / tests (3.12) (push) Has been cancelled
Run tests / tests (3.9) (push) Has been cancelled
2025-09-30 21:47:30 +02:00
Syed Muhammad Dawoud Sheraz Ali
ae4e3f20ac
feat: migrate to ruff for linting and formatting checks (#50) 2025-09-24 10:30:18 +05:00
Ahmed Khalid
4fde7e355b
Merge pull request #49 from overhangio/teak 2025-06-27 17:04:20 +05:00
Syed Muhammad Dawoud Sheraz Ali
1ff9c0bd77 chore: generate changelog for v20 2025-06-05 17:50:09 +05:00
jfavellar90
3fe46bc278 feat: upgrade to teak 2025-04-04 12:44:52 -05:00
Syed Muhammad Dawoud Sheraz Ali
cde10c2f97
v19.0.2 (#48) 2025-03-12 15:17:38 +05:00
Syed Muhammad Dawoud Sheraz Ali
97aed60b38
build: Add hatch_build in sdist to fix installation issues (#47)
* build: Add hatch_build in sdist to fix installation issues
2025-03-12 15:13:12 +05:00
jfavellar90
1465402bfa v19.0.1 2025-03-11 13:14:03 -05:00
Jhony Avella
8540aef9b8
feat: migrate from setup.py to pyproject.toml (#46)
* feat: migrate from setup.py to pyproject.toml

* chore: fixes

* chore: addressing PR comments

* chore: addressing more comments
2025-03-11 13:09:00 -05:00
Régis Behmo
9d91f7499d
fix: broken feature in dev mode (#43)
Student notes were simply not working in dev mode because the dev server
hostname was not whitelisted in ALLOWED_HOSTS.
2025-02-13 20:34:56 -05:00
Syed Muhammad Dawoud Sheraz Ali
3f0ff01105
build: re-add auto-add for PRs with a different target (#45) 2025-01-17 11:31:04 +05:00
Régis Behmo
e61f3cea5f
feat: Upgrade to Sumac 2024-12-16 21:58:16 +01:00
Syed Muhammad Dawoud Sheraz Ali
0267ffde12 chore: update changelog 2024-12-09 18:52:20 +05:00
Régis Behmo
6e8bc34475 feat: migrate to Meilisearch
We make use of a new search engine to search annotations. The index will
automatically be created and filled during init. This is considered a
breaking change if you have customised your notes index.
2024-11-29 22:28:03 +05:00
Régis Behmo
a61e09c11e fix: actually mount notes directory
Notes directory could be added via `tutor mounts add ./edx-notes-api`,
but it was not actually being mounted.
2024-11-29 22:28:03 +05:00
jfavellar90
e5fedc2d83 feat: upgrade to sumac 2024-11-29 22:28:01 +05:00
Régis Behmo
e52064fe64 Merge branch 'release' 2024-11-27 18:35:01 +01:00
Syed Muhammad Dawoud Sheraz Ali
75e64f5065 feat!: Rename branches master->release, nightly->main 2024-11-27 22:34:13 +05:00
Overhang.IO
7d16414908 Merge remote-tracking branch 'origin/master' into nightly 2024-11-14 16:25:16 +00:00
Syed Muhammad Dawoud Sheraz Ali
5515eda18b
chore: remove python 3.8 references and set py39 as minimum version (#42) 2024-11-14 21:19:20 +05:00
Jhony Avella
fdf73b62e3
Ubuntu 24.04 Upgrade (#39)
* chore: notes service now uses ubuntu 24.04 as base image

* chore: using 1000 UID. Updating setuptools

* chore: adding changelog entry
2024-10-22 16:07:32 -05:00
Régis Behmo
f9fcbf26f4 docs: *.local.edly.io -> *.local.openedx.io
The default URL to run a local platform switched from local.edly.io to
local.openedx.io. This changes makes it clearer for everyone that Tutor
is to run Open edX.

See: https://github.com/overhangio/tutor/issues/1120
2024-10-17 08:36:40 +02:00
Régis Behmo
dbf48674f9 ci: upgrade vendor actions 2024-10-03 11:16:24 +02:00
Régis Behmo
28113792f3 docs: fix author domain name 2024-10-01 09:08:48 +02:00
Régis Behmo
7801778112 build: fix readme content type warning 2024-07-23 10:37:35 +02:00
Régis Behmo
9671824e1f fix: docker build deprecation warnings
With the latest Docker upgrade, we got the following warnings during
build:

	FromAsCasing: 'as' and 'FROM' keywords' casing do not match
	LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format
2024-06-21 17:12:57 +02:00
Régis Behmo
06fd645d44
Merge pull request #37 from overhangio/redwood
* feat: adding python 3.12 support (#36)

* feat: adding first version of Dockerfile Python3.12 compatible

* ci: add python 3.12 checks

* feat: upgrade to redwood
2024-06-20 03:12:10 +02:00
jfavellar90
6d3685a573 feat: upgrade to redwood 2024-06-20 01:13:57 +02:00
Jhony Avella
20ec2c8b99
feat: adding python 3.12 support (#36)
* feat: adding first version of Dockerfile Python3.12 compatible

* ci: add python 3.12 checks
2024-04-29 11:28:19 -05:00
Régis Behmo
f68719de86 ci: don't even try to auto-add PRs to github project
Auto-adding PRs to the Github project is not working because the
github-token is not available there.
2024-03-05 12:03:03 +05:00
Régis Behmo
8b1c93d900 ci: remove now useless OPENEDX_RELEASE variable 2024-02-20 15:15:40 +01:00
Régis Behmo
c5bd0acab1 fix: remove pkg_resources for compatibility with python 3.12
pkg_resources is a package that is unavailable in python 3.12, unless
setuptools is explicitely installed. Turns out, there are replacement
functions coming from importlib_resources, which can be obtained from
the importlib-resources pypi package. This package will be installed
with tutor starting from 17.0.2.
2024-02-12 11:57:51 +01:00
Régis Behmo
795ea5966e ci: auto-add issues and items to github project 2024-01-12 12:33:35 +01:00
jfavellar90
0d0128210c feat: upgrade to Quince 2023-12-11 18:12:10 +01:00
Régis Behmo
0751918e6a local.overhang.io -> local.edly.io
This is related to https://github.com/overhangio/tutor/issues/945
2023-12-09 15:54:28 +01:00
Overhang.IO
74c85b1edd Merge remote-tracking branch 'origin/master' into nightly 2023-12-08 18:37:47 +00:00
Emad Rad
58f8abc339
fix: dev dependency 2023-12-08 19:32:56 +01:00
Overhang.IO
2d32da1245 Merge remote-tracking branch 'origin/master' into nightly 2023-12-06 15:17:43 +00:00
Régis Behmo
1c349e00c2 chore: format 2023-12-06 16:13:29 +01:00
Régis Behmo
305e008ea0 Merge branch 'master' into nightly 2023-12-05 12:10:56 +01:00
Régis Behmo
98a00ecb58 docs: docs.tutor.overhang.io -> docs.tutor.edly.io
See: https://github.com/overhangio/tutor/issues/945
2023-12-05 11:45:48 +01:00
Emad Rad
727d500bf5 Feat: Testing and Linting (#31)
* ci: test action added

* chore: changelog entry added

* feat: Makefile added

* fix: typing added

* chore: cleanup with isort and black
2023-11-24 08:25:04 +01:00
Régis Behmo
f88afe05c3 feat: simplify nightly version management
By pulling the version suffix from tutor, we avoid git conflicts when
merging the release branch in nightly.
2023-11-24 08:25:02 +01:00
Emad Rad
d4a4274bc4
Feat: Testing and Linting (#31)
* ci: test action added

* chore: changelog entry added

* feat: Makefile added

* fix: typing added

* chore: cleanup with isort and black
2023-11-23 18:05:41 -05:00
Régis Behmo
cb08b63217
fix: add missing pkg-config package (#30)
Build fails in nightly with the following error:

	#27 4.029   × Getting requirements to build wheel did not run
	    successfully.
	#27 4.029   │ exit code: 1
	#27 4.029   ╰─> [24 lines of output]
	#27 4.029       /bin/sh: 1: pkg-config: not found
	#27 4.029       /bin/sh: 1: pkg-config: not found
	#27 4.029       Trying pkg-config --exists mysqlclient
	#27 4.029       Command 'pkg-config --exists mysqlclient' returned
	    non-zero exit status 127.
	#27 4.029       Trying pkg-config --exists mariadb
	#27 4.029       Command 'pkg-config --exists mariadb' returned non-zero
	    exit status 127.
	#27 4.029       Traceback (most recent call last):
	#27 4.029         File
	    "/app/venv/lib/python3.8/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py",
	line 353, in <module>
	#27 4.029           main()
	#27 4.029         File
	    "/app/venv/lib/python3.8/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py",
	line 335, in main
	#27 4.029           json_out['return_val'] =
	    hook(**hook_input['kwargs'])
	#27 4.029         File
	    "/app/venv/lib/python3.8/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py",
	line 118, in get_requires_for_build_wheel
	#27 4.029           return hook(config_settings)
	#27 4.029         File
	    "/tmp/pip-build-env-td0z_pds/overlay/lib/python3.8/site-packages/setuptools/build_meta.py",
	line 355, in get_requires_for_build_wheel
	#27 4.029           return self._get_build_requires(config_settings,
	    requirements=['wheel'])
	#27 4.029         File
	    "/tmp/pip-build-env-td0z_pds/overlay/lib/python3.8/site-packages/setuptools/build_meta.py",
	line 325, in _get_build_requires
	#27 4.029           self.run_setup()
	#27 4.029         File
	    "/tmp/pip-build-env-td0z_pds/overlay/lib/python3.8/site-packages/setuptools/build_meta.py",
	line 341, in run_setup
	#27 4.029           exec(code, locals())
	#27 4.029         File "<string>", line 154, in <module>
	#27 4.029         File "<string>", line 48, in get_config_posix
	#27 4.029         File "<string>", line 27, in find_package_name
	#27 4.029       Exception: Can not find valid pkg-config name.
	#27 4.029       Specify MYSQLCLIENT_CFLAGS and MYSQLCLIENT_LDFLAGS env
	    vars manually
2023-11-21 06:40:11 -05:00
Régis Behmo
16012432a1 feat: simplify nightly version management
By pulling the version suffix from tutor, we avoid git conflicts when
merging the release branch in nightly.
2023-11-20 17:39:47 +01:00
Overhang.IO
0768eafd7e Merge remote-tracking branch 'origin/master' into nightly 2023-11-15 00:23:49 +00:00
jfavellar90
43af20751e v16.0.2 2023-11-14 19:19:45 -05:00
Overhang.IO
8c4f872756 Merge remote-tracking branch 'origin/master' into nightly 2023-10-03 06:34:28 +00:00
Régis Behmo
87007e4d69 chore: mark compatibility with python 3.12 2023-10-03 08:23:48 +02:00
Overhang.IO
3ca1417597 Merge remote-tracking branch 'origin/master' into nightly 2023-09-07 16:50:48 +00:00
Régis Behmo
56696de37f fix: nightly package version
The package version may not include the "-nightly" suffix. Otherwise,
`pip install .` fails with:

    setuptools.extern.packaging.version.InvalidVersion: Invalid version: '...-nightly'
2023-09-07 18:39:53 +02:00
Overhang.IO
2b78e58e8a Merge remote-tracking branch 'origin/master' into nightly 2023-08-28 09:52:26 +00:00
Serkan Özdemir
ebee348f04
docs: remind to run local launch after installation 2023-08-28 11:48:23 +02:00
Régis Behmo
f8c28346a5 Merge branch 'master' into nightly 2023-08-09 10:35:26 +02:00
jfavellar90
73b0e10df0 v16.0.1 2023-08-04 08:14:55 -05:00
Overhang.IO
0093976541 Merge remote-tracking branch 'origin/master' into nightly 2023-07-31 13:39:25 +00:00
Jhony Avella
fcffe6f3ed
chore: remove notes permissions container. (#24)
chore: remove notes permissions container

There is now a single "permissions" container that makes all permission changes in Tutor core
2023-07-31 15:34:52 +02:00
Régis Behmo
581f986729 Merge branch 'master' into nightly 2023-06-15 01:09:31 +02:00
Jhony Avella
702e029d55
feat: upgrade to Palm 2023-06-15 01:03:44 +02:00
Régis Behmo
a7ad3758b5 fix: nightly package version
The package version number may not include the "-nightly" suffix.
Otherwise, installation fails with:

   setuptools.extern.packaging.version.InvalidVersion: Invalid version: '15.0.7-nightly'
2023-05-26 18:47:48 +02:00
Régis Behmo
5d6580c82b feat: label nightly version
This is to address https://github.com/overhangio/tutor-mfe/issues/122
As a consequence of this change, images will be tagged with a "-nightly"
suffix. Next, we'll probably have to build them periodically in CI.
2023-05-26 18:26:28 +02:00
Régis Behmo
2da25c576c ci: improve compatibility with main & nightly 2023-05-26 16:49:26 +02:00
Régis Behmo
f38f473fd4 chore: handle nightly version numbers
Here, we make it possible to add a "-nightly" suffix to the package
version. This suffix will find its way to the Docker image tags. Thus,
the nightly branch will have different image tags. This will resolve
some confusion, as image tags are currently identical in nightly and
master.
2023-05-26 16:28:10 +02:00
Régis Behmo
6769141f8d docs: fix lingering i char in changelog
Damn you vim!
2023-05-22 09:38:30 +02:00
Régis Behmo
3f65c71cc2 docs: add a scriv-managed changelog
This will be useful for tracking changes across releases.

This partly addresses https://github.com/overhangio/tutor/issues/746
2023-05-19 16:19:56 +02:00
Régis Behmo
3358ee7e1d fix: build-time warning
Installing from source triggers a warning on pip 23.0.1 if
pyproject.toml is not present. Building does not require any special
dependencies, so we just add a simple pyproject.toml file.

See: https://github.com/overhangio/tutor/issues/836
2023-05-17 10:24:21 +02:00
Régis Behmo
7944ea3c91 docs: instruct to install from index 2023-05-16 10:08:58 +02:00
23 changed files with 438 additions and 146 deletions

View File

@ -0,0 +1,20 @@
name: Auto Add Issues and Pull Requests to Project
on:
issues:
types:
- opened
pull_request_target:
types:
- opened
jobs:
# https://github.com/actions/add-to-project
add-to-project:
name: Add issue and bugs to project
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@v1.0.2
with:
project-url: https://github.com/orgs/overhangio/projects/4
github-token: ${{ secrets.GH_PROJECT_PERSONAL_ACCESS_TOKEN }}

View File

@ -2,16 +2,16 @@ name: Sync with private repo
on:
push:
branches: [ master ]
branches: [ release, main ]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Add remote
run: git remote add overhangio https://${{ secrets.GIT_USERNAME }}:${{ secrets.GIT_PASSWORD }}@git.overhang.io/core/tutor-notes.git
- name: Push
run: git push overhangio master
run: git push overhangio $GITHUB_REF

25
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: Run tests
on:
pull_request:
branches: [ release, main ]
push:
branches: [ release, main ]
jobs:
tests:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.9', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install .[dev]
- name: Test lint, types, and format
run: make test

View File

@ -2,7 +2,6 @@ variables:
TUTOR_PLUGIN: notes
TUTOR_IMAGES: notes
TUTOR_PYPI_PACKAGE: tutor-notes
OPENEDX_RELEASE: olive
GITHUB_REPO: overhangio/tutor-notes
include:

21
.hatch_build.py Normal file
View File

@ -0,0 +1,21 @@
# https://hatch.pypa.io/latest/how-to/config/dynamic-metadata/
import os
import typing as t
from hatchling.metadata.plugin.interface import MetadataHookInterface
HERE = os.path.dirname(__file__)
class MetaDataHook(MetadataHookInterface):
def update(self, metadata: dict[str, t.Any]) -> None:
about = load_about()
metadata["version"] = about["__version__"]
def load_about() -> dict[str, str]:
about: dict[str, str] = {}
with open(os.path.join(HERE, "tutornotes", "__about__.py"), "rt", encoding="utf-8") as f:
exec(f.read(), about)
return about

73
CHANGELOG.md Normal file
View File

@ -0,0 +1,73 @@
# Changelog
This file includes a history of past releases. Changes that were not yet added to a release are in the [changelog.d/](./changelog.d) folder.
<!--
⚠️ DO NOT ADD YOUR CHANGES TO THIS FILE! (unless you want to modify existing changelog entries in this file)
Changelog entries are managed by scriv. After you have made some changes to this plugin, create a changelog entry with:
scriv create
Edit and commit the newly-created file in changelog.d.
If you need to create a new release, create a separate commit just for that. It is important to respect these
instructions, because git commits are used to generate release notes:
- Modify the version number in `__about__.py`.
- Collect changelog entries with `scriv collect`
- The title of the commit should be the same as the new version: "vX.Y.Z".
-->
<!-- scriv-insert-here -->
<a id='changelog-20.0.0'></a>
## v20.0.0 (2025-06-05)
- 💥[Feature] Upgrade to Teak. (by @jfavellar90)
<a id='changelog-19.0.2'></a>
## v19.0.2 (2025-03-12)
- [Improvement] Add hatch_build.py in sdist target to fix the installation issues (by @dawoudsheraz)
<a id='changelog-19.0.1'></a>
## v19.0.1 (2025-03-11)
- [Bugfix] Fix broken feature in `dev` mode, where the frontend is reporting a CORS error on loading the notes. (by @regisb)
- [Improvement] Migrate from `setup.py` (setuptools) to `pyproject.toml` (hatch). (by @jfavellar90)
<a id='changelog-19.0.0'></a>
## v19.0.0 (2024-10-24)
- [Bugfix] Fix legacy warnings during Docker build. (by @regisb)
- 💥[Feature] Update Notes Image to use Ubuntu 24.04 as base OS. (by @jfavellar90)
- [Bugfix] Actually mount edx-notes-api repositories from host on `tutor mounts add /path/to/edx-notes-api`. (by @regisb)
- 💥[Feature] Replace Elasticsearch by Meilisearch. The implementation is much more compact and readable. All content will be automatically re-indexed during init. (by @regisb)
- 💥 [Deprecation] Drop support for python 3.8 and set Python 3.9 as the minimum supported python version. (by @DawoudSheraz)
- 💥[Improvement] Rename Tutor's two branches (by @DawoudSheraz):
* Rename **master** to **release**, as this branch runs the latest official Open edX release tag.
* Rename **nightly** to **main**, as this branch runs the Open edX master branches, which are the basis for the next Open edX release.
- 💥[Feature] Upgrade to Sumac. (by @jfavellar90)
<a id='changelog-18.0.0'></a>
## v18.0.0 (2024-05-09)
- [Bugfix] Make plugin compatible with Python 3.12 by removing dependency on `pkg_resources`. (by @regisb)
- 💥[Feature] Upgrade Python version to 3.12.3. (by @jfavellar90)
- 💥[Feature] Upgrade to Redwood. (by @jfavellar90)
<a id='changelog-17.0.0'></a>
## v17.0.0 (2023-12-09)
- 💥 [Feature] Upgrade to Quince.
- [Improvement] Add a scriv-compliant changelog. (by @regisb)
- [Improvement] Removing the notes permissions container in favor of a global single permissions container. (by @jfavellar90)
- [Improvement] Added Makefile and test action to repository and formatted code with Black and isort. (by @CodeWithEmad)

View File

@ -1,2 +0,0 @@
recursive-include tutornotes/patches *
recursive-include tutornotes/templates *

46
Makefile Normal file
View File

@ -0,0 +1,46 @@
.DEFAULT_GOAL := help
.PHONY: docs
SRC_DIRS = ./tutornotes
RUFF_OPTS = --exclude templates ${SRC_DIRS}
# Warning: These checks are run on every PR.
test: test-lint test-types test-format test-pythonpackage
test-format: ## Run code formatting tests.
ruff format --check --diff $(RUFF_OPTS)
test-lint:
ruff check ${SRC_DIRS}
test-types: ## Run type checks.
mypy --exclude=templates --ignore-missing-imports --implicit-reexport --strict ${SRC_DIRS}
build-pythonpackage:
python -m build --sdist
test-pythonpackage: build-pythonpackage
twine check dist/tutor_notes-$(shell make version).tar.gz
format: ## Format code automatically.
ruff format $(RUFF_OPTS)
fix-lint: ## Fix linting issues automatically.
ruff check --fix $(RUFF_OPTS)
isort: ## Sort imports. This target is not mandatory because the output may be incompatible with black formatting. Provided for convenience purposes.
isort --skip=templates ${SRC_DIRS}
changelog-entry: ## Create a new changelog entry.
scriv create
changelog: ## Collect changelog entries in the CHANGELOG.md file.
scriv collect
version: ## Print the current tutor-notes version
@python -c 'import io, os; about = {}; exec(io.open(os.path.join("tutornotes", "__about__.py"), "rt", encoding="utf-8").read(), about); print(about["__version__"])'
ESCAPE = 
help: ## Print this help.
@grep -E '^([a-zA-Z_-]+:.*?## .*|######* .+)$$' Makefile \
| sed 's/######* \(.*\)/@ $(ESCAPE)[1;31m\1$(ESCAPE)[0m/g' | tr '@' '\n' \
| awk 'BEGIN {FS = ":.*?## "}; {printf "\033[33m%-30s\033[0m %s\n", $$1, $$2}'

View File

@ -1,9 +1,9 @@
Students notes plugin for `Tutor <https://docs.tutor.overhang.io>`_
Students notes plugin for `Tutor <https://docs.tutor.edly.io>`_
===================================================================
This is a plugin for `Tutor <https://docs.tutor.overhang.io>`_ to easily add the `Open edX note-taking app <https://github.com/openedx/edx-notes-api>`_ to an Open edX platform. This app allows students to annotate portions of the courseware (see `the official documentation <https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-olive.master/exercises_tools/notes.html>`_).
This is a plugin for `Tutor <https://docs.tutor.edly.io>`_ to easily add the `Open edX note-taking app <https://github.com/openedx/edx-notes-api>`_ to an Open edX platform. This app allows students to annotate portions of the courseware (see `the official documentation <https://docs.openedx.org/en/latest/educators/how-tos/course_development/exercise_tools/enable_notes.html>`_).
.. image:: https://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/open-release-olive.master/_images/SFD_SN_bodyexample.png
.. image:: https://docs.openedx.org/en/latest/_images/SFD_SN_bodyexample.png
:alt: Notes in action
Installation
@ -11,15 +11,19 @@ Installation
The plugin is currently bundled with the `binary releases of Tutor <https://github.com/overhangio/tutor/releases>`_. If you have installed Tutor from source, you will have to install this plugin from source, too::
pip install tutor-notes
tutor plugins install notes
Then, to enable this plugin, run::
tutor plugins enable notes
Then, to make migrations & tasks::
tutor local launch
You should beware that the ``notes.<LMS_HOST>`` domain name should exist and point to your server. For instance, if your LMS is hosted at http://myopenedx.com, the notes service should be found at http://notes.myopenedx.com.
If you would like to host the notes service at a different domain name, you can set the ``NOTES_HOST`` configuration variable (see below). When testing Tutor on a local computer, this will be automatically set to notes.local.overhang.io.
If you would like to host the notes service at a different domain name, you can set the ``NOTES_HOST`` configuration variable (see below). When testing Tutor on a local computer, this will be automatically set to notes.local.openedx.io.
To enable student notes for a specific course, you should go to the course advanced settings in the studio, and set "Enable Student Notes" to "true". Then, hit "save changes".
@ -50,9 +54,9 @@ Feel free to add breakpoints (``breakpoint()``) anywhere in your source code to
Troubleshooting
---------------
This Tutor plugin is maintained by Jhony Avella from `eduNEXT <https://www.edunext.co/>`__. Community support is available from the official `Open edX forum <https://discuss.openedx.org>`__. Do you need help with this plugin? See the `troubleshooting <https://docs.tutor.overhang.io/troubleshooting.html>`__ section from the Tutor documentation.
This Tutor plugin is maintained by Jhony Avella from `eduNEXT <https://www.edunext.co/>`__. Community support is available from the official `Open edX forum <https://discuss.openedx.org>`__. Do you need help with this plugin? See the `troubleshooting <https://docs.tutor.edly.io/troubleshooting.html>`__ section from the Tutor documentation.
License
-------
This software is licensed under the terms of the `GNU Affero General Public License (AGPL) <https://github.com/overhangio/tutor-notes/blob/master/LICENSE.txt>`_.
This software is licensed under the terms of the `GNU Affero General Public License (AGPL) <https://github.com/overhangio/tutor-notes/blob/release/LICENSE.txt>`_.

View File

@ -0,0 +1,2 @@
- [Improvement] Migrate from pylint and black to ruff. (by @dawoudsheraz)
- [Improvement] Test python package distribution build when running make-test. (by @dawoudsheraz)

18
changelog.d/scriv.ini Normal file
View File

@ -0,0 +1,18 @@
[scriv]
version = literal: tutornotes/__about__.py: __version__
categories =
format = md
md_header_level = 2
new_fragment_template =
<!--
Create a changelog entry for every new user-facing change. Please respect the following instructions:
- Indicate breaking changes by prepending an explosion 💥 character.
- Prefix your changes with either [Bugfix], [Improvement], [Feature], [Security], [Deprecation].
- You may optionally append "(by @<author>)" at the end of the line, where "<author>" is either one (just one)
of your GitHub username, real name or affiliated organization. These affiliations will be displayed in
the release notes for every release.
-->
<!-- - 💥[Feature] Foobarize the blorginator. This breaks plugins by renaming the `FOO_DO` filter to `BAR_DO`. (by @regisb) -->
<!-- - [Improvement] This is a non-breaking change. Life is good. (by @billgates) -->
entry_title_template = {%% if version %%}v{{ version }} {%% endif %%}({{ date.strftime('%%Y-%%m-%%d') }})

87
pyproject.toml Normal file
View File

@ -0,0 +1,87 @@
# https://packaging.python.org/en/latest/tutorials/packaging-projects/
# https://hatch.pypa.io/latest/config/build/
[project]
name = "tutor-notes"
description = "A Tutor plugin for student notes"
authors = [
{ name = "Edly" },
{ email = "hello@edly.io"},
]
maintainers = [
{ name = "Jhony Avella" },
{ email = "jhony.avella@edunext.co" },
]
license = {text = "AGPL-3.0-only"}
readme = {file = "README.rst", content-type = "text/x-rst"}
requires-python = ">=3.9"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"tutor>=20.0.0,<21.0.0",
]
# These fields will be set by hatch_build.py
dynamic = ["version"]
[project.optional-dependencies]
dev = [
"tutor[dev]>=20.0.0,<21.0.0",
"ruff"
]
# https://packaging.python.org/en/latest/specifications/well-known-project-urls/#well-known-labels
[project.urls]
Homepage = "https://docs.tutor.edly.io/"
Documentation = "https://github.com/overhangio/tutor-notes#readme"
Issues = "https://github.com/overhangio/tutor-notes/issues"
Source = "https://github.com/overhangio/tutor-notes"
Changelog = "https://github.com/overhangio/tutor-notes/blob/release/CHANGELOG.md"
Community = "https://discuss.openedx.org/tag/tutor"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# hatch-specific configuration
[tool.hatch.metadata.hooks.custom]
path = ".hatch_build.py"
[tool.hatch.build.targets.wheel]
packages = ["tutornotes"]
[tool.hatch.build.targets.sdist]
# Disable strict naming, otherwise twine is not able to detect name/version
strict-naming = false
include = [ "/tutornotes", ".hatch_build.py"]
exclude = ["tests*"]
[project.entry-points."tutor.plugin.v1"]
notes = "tutornotes.plugin"
[tool.ruff]
exclude = ["templates", "docs/_ext"]
[tool.ruff.lint]
# E: pycodestyle errors
# I: isort
# N: pep8-naming
select = ["E", "I", "N"]
# F401: unused-import
# F841: unused-variable
# W292: missing-newline-at-end-of-file
extend-select = ["F401", "F841", "W292"]
[tool.ruff.format]
# Default config is automatically taken from https://docs.astral.sh/ruff/configuration/

View File

@ -1,48 +0,0 @@
import io
import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
with io.open(os.path.join(here, "README.rst"), "rt", encoding="utf8") as f:
readme = f.read()
about = {}
with io.open(
os.path.join(here, "tutornotes", "__about__.py"), "rt", encoding="utf-8"
) as f:
exec(f.read(), about)
setup(
name="tutor-notes",
version=about["__version__"],
url="https://docs.tutor.overhang.io/",
project_urls={
"Documentation": "https://docs.tutor.overhang.io/",
"Code": "https://github.com/overhangio/tutor-notes",
"Issue tracker": "https://github.com/overhangio/tutor-notes/issues",
"Community": "https://discuss.openedx.org",
},
license="AGPLv3",
author="Overhang.IO",
author_email="contact@overhang.io",
maintainer="eduNEXT",
description="A Tutor plugin for student notes",
long_description=readme,
packages=find_packages(exclude=["tests*"]),
include_package_data=True,
python_requires=">=3.7",
install_requires=["tutor>=15.0.0,<16.0.0"],
entry_points={"tutor.plugin.v1": ["notes = tutornotes.plugin"]},
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
],
)

View File

@ -1 +1 @@
__version__ = "15.0.4"
__version__ = "20.0.0"

View File

@ -15,8 +15,8 @@ spec:
app.kubernetes.io/name: notes
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
runAsUser: {{ APP_USER_ID }}
runAsGroup: {{ APP_USER_ID }}
containers:
- name: notes
image: {{ NOTES_DOCKER_IMAGE }}

View File

@ -4,4 +4,7 @@ notes-job:
DJANGO_SETTINGS_MODULE: notesserver.settings.tutor
volumes:
- ../plugins/notes/apps/settings/tutor.py:/app/edx-notes-api/notesserver/settings/tutor.py:ro
{%- for mount in iter_mounts(MOUNTS, "notes") %}
- {{ mount }}
{%- endfor %}
depends_on: {{ [("mysql", RUN_MYSQL)]|list_if }}

View File

@ -0,0 +1 @@
setowner {{ APP_USER_ID }} /mounts/notes

View File

@ -0,0 +1 @@
- ../../data/notes:/mounts/notes

View File

@ -6,14 +6,8 @@ notes:
volumes:
- ../plugins/notes/apps/settings/tutor.py:/app/edx-notes-api/notesserver/settings/tutor.py:ro
- ../../data/notes:/app/data
{%- for mount in iter_mounts(MOUNTS, "notes") %}
- {{ mount }}
{%- endfor %}
restart: unless-stopped
depends_on:
- notes-permissions
{% if RUN_MYSQL %}- mysql{% endif %}
notes-permissions:
image: {{ DOCKER_IMAGE_PERMISSIONS }}
command: ["1000", "/app/notes"]
restart: on-failure
volumes:
- ../../data/notes:/app/notes
depends_on: {{ [("mysql", RUN_MYSQL)]|list_if }}

View File

@ -1,62 +1,79 @@
from glob import glob
from __future__ import annotations
import os
import typing as t
from glob import glob
import pkg_resources
import importlib_resources
from tutor import hooks as tutor_hooks
from tutor.__about__ import __version_suffix__
from .__about__ import __version__
# Handle version suffix in main mode, just like tutor core
if __version_suffix__:
__version__ += "-" + __version_suffix__
config = {
"unique": {
"MYSQL_PASSWORD": "{{ 8|random_string }}",
"SECRET_KEY": "{{ 24|random_string }}",
"OAUTH2_SECRET": "{{ 24|random_string }}",
},
"defaults": {
"VERSION": __version__,
"DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/openedx-notes:{{ NOTES_VERSION }}",
"DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/openedx-notes:{{ NOTES_VERSION }}", # noqa: E501
"HOST": "notes.{{ LMS_HOST }}",
"MYSQL_DATABASE": "notes",
"MYSQL_USERNAME": "notes",
"REPOSITORY": "https://github.com/openedx/edx-notes-api",
"REPOSITORY_VERSION": "{{ OPENEDX_COMMON_VERSION }}",
},
"unique": {
"MYSQL_PASSWORD": "{{ 8|random_string }}",
"SECRET_KEY": "{{ 24|random_string }}",
"OAUTH2_SECRET": "{{ 24|random_string }}",
},
}
# Initialization hooks
tutor_hooks.Filters.COMMANDS_INIT.add_item((
"mysql",
("notes", "tasks", "mysql", "init"),
))
tutor_hooks.Filters.COMMANDS_INIT.add_item((
"lms",
("notes", "tasks", "lms", "init"),
))
tutor_hooks.Filters.COMMANDS_INIT.add_item((
"notes",
("notes", "tasks", "notes", "init"),
))
# For each service, we load the task template
# and add it to the CLI_DO_INIT_TASKS filter, which tells Tutor to
# run it as part of the `init` job.
for service in ["mysql", "lms", "notes"]:
full_path: str = str(
importlib_resources.files("tutornotes")
/ "templates"
/ "notes"
/ "tasks"
/ service
/ "init"
)
with open(full_path, encoding="utf-8") as init_task_file:
init_task: str = init_task_file.read()
tutor_hooks.Filters.CLI_DO_INIT_TASKS.add_item((service, init_task))
# Image management
tutor_hooks.Filters.IMAGES_BUILD.add_item((
"notes",
("plugins", "notes", "build", "notes"),
"{{ NOTES_DOCKER_IMAGE }}",
(),
))
tutor_hooks.Filters.IMAGES_PULL.add_item((
"notes",
"{{ NOTES_DOCKER_IMAGE }}",
))
tutor_hooks.Filters.IMAGES_PUSH.add_item((
"notes",
"{{ NOTES_DOCKER_IMAGE }}",
))
tutor_hooks.Filters.IMAGES_BUILD.add_item(
(
"notes",
("plugins", "notes", "build", "notes"),
"{{ NOTES_DOCKER_IMAGE }}",
(),
)
)
tutor_hooks.Filters.IMAGES_PULL.add_item(
(
"notes",
"{{ NOTES_DOCKER_IMAGE }}",
)
)
tutor_hooks.Filters.IMAGES_PUSH.add_item(
(
"notes",
"{{ NOTES_DOCKER_IMAGE }}",
)
)
@tutor_hooks.Filters.COMPOSE_MOUNTS.add()
def _mount_edx_notes_api(volumes, name):
def _mount_edx_notes_api(
volumes: list[tuple[str, str]], name: str
) -> list[tuple[str, str]]:
"""
When mounting edx-notes-api with `--mount=/path/to/edx-notes-api`,
bind-mount the host repo in the notes container.
@ -69,10 +86,10 @@ def _mount_edx_notes_api(volumes, name):
]
return volumes
####### Boilerplate code
# Add the "templates" folder as a template root
tutor_hooks.Filters.ENV_TEMPLATE_ROOTS.add_item(
pkg_resources.resource_filename("tutornotes", "templates")
str(importlib_resources.files("tutornotes") / "templates")
)
# Render the "build" and "apps" folders
tutor_hooks.Filters.ENV_TEMPLATE_TARGETS.add_items(
@ -82,25 +99,31 @@ tutor_hooks.Filters.ENV_TEMPLATE_TARGETS.add_items(
],
)
# Load patches from files
for path in glob(
os.path.join(
pkg_resources.resource_filename("tutornotes", "patches"),
"*",
)
):
for path in glob(str(importlib_resources.files("tutornotes") / "patches" / "*")):
with open(path, encoding="utf-8") as patch_file:
tutor_hooks.Filters.ENV_PATCHES.add_item((os.path.basename(path), patch_file.read()))
tutor_hooks.Filters.ENV_PATCHES.add_item(
(os.path.basename(path), patch_file.read())
)
# Add configuration entries
tutor_hooks.Filters.CONFIG_DEFAULTS.add_items(
[
(f"NOTES_{key}", value)
for key, value in config.get("defaults", {}).items()
]
[(f"NOTES_{key}", value) for key, value in config.get("defaults", {}).items()]
)
tutor_hooks.Filters.CONFIG_UNIQUE.add_items(
[
(f"NOTES_{key}", value)
for key, value in config.get("unique", {}).items()
]
[(f"NOTES_{key}", value) for key, value in config.get("unique", {}).items()]
)
tutor_hooks.Filters.CONFIG_OVERRIDES.add_items(list(config.get("overrides", {}).items()))
tutor_hooks.Filters.CONFIG_OVERRIDES.add_items(
list(config.get("overrides", {}).items())
)
# Notes public hosts
@tutor_hooks.Filters.APP_PUBLIC_HOSTS.add()
def _notes_public_hosts(
hosts: list[str], context_name: t.Literal["local", "dev"]
) -> list[str]:
if context_name == "dev":
hosts += ["{{ NOTES_HOST }}:8120"]
else:
hosts += ["{{ NOTES_HOST }}"]
return hosts

View File

@ -4,13 +4,14 @@ SECRET_KEY = "{{ NOTES_SECRET_KEY }}"
ALLOWED_HOSTS = [
"notes",
"{{ NOTES_HOST }}",
"{{ NOTES_HOST }}:8120",
]
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"HOST": "{{ MYSQL_HOST }}",
"PORT": {{MYSQL_PORT}},
"PORT": {{ MYSQL_PORT }},
"NAME": "{{ NOTES_MYSQL_DATABASE }}",
"USER": "{{ NOTES_MYSQL_USERNAME }}",
"PASSWORD": "{{ NOTES_MYSQL_PASSWORD }}",
@ -23,11 +24,12 @@ DATABASES = {
CLIENT_ID = "notes"
CLIENT_SECRET = "{{ NOTES_OAUTH2_SECRET }}"
ELASTICSEARCH_DSL = {
'default': {
'hosts': '{{ ELASTICSEARCH_SCHEME }}://{{ ELASTICSEARCH_HOST }}:{{ ELASTICSEARCH_PORT }}'
}
}
# Meilisearch credentials
ES_DISABLED = True
MEILISEARCH_ENABLED = True
MEILISEARCH_URL = "{{ MEILISEARCH_URL }}"
MEILISEARCH_API_KEY = "{{ MEILISEARCH_API_KEY }}"
MEILISEARCH_INDEX = "{{ MEILISEARCH_INDEX_PREFIX }}student_notes"
LOGGING = {
"version": 1,

View File

@ -1,25 +1,46 @@
FROM docker.io/ubuntu:20.04
# syntax=docker/dockerfile:1
FROM docker.io/ubuntu:24.04
RUN apt update && \
apt upgrade -y && \
# python 3.8
apt install -y language-pack-en git python3 python3-pip python3-venv libmysqlclient-dev
ENV DEBIAN_FRONTEND=noninteractive
# Delete default UID=1000 `ubuntu` user to ensure we can use id 1000 for app user
RUN userdel -r ubuntu
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt update && \
apt upgrade -y && \
apt install -y \
language-pack-en \
git \
python3 \
python3-pip \
python3-venv \
libmysqlclient-dev \
pkg-config
RUN ln -s /usr/bin/python3 /usr/bin/python
ARG APP_USER_ID=1000
###### Git-clone Notes repo ######
ARG APP_USER_ID={{ HOST_USER_ID }}
RUN useradd --home-dir /app --create-home --shell /bin/bash --uid ${APP_USER_ID} app
USER ${APP_USER_ID}
RUN git clone {{ NOTES_REPOSITORY }} --branch {{ NOTES_REPOSITORY_VERSION }} --depth 1 /app/edx-notes-api
WORKDIR /app/edx-notes-api
###### Install python venv ######
RUN python -m venv /app/venv
ENV PATH /app/venv/bin:${PATH}
ENV PATH=/app/venv/bin:${PATH}
# https://pypi.org/project/setuptools/
# https://pypi.org/project/pip/
# https://pypi.org/project/wheel/
RUN pip install setuptools==65.5.1 pip==22.3.1 wheel==0.38.4
RUN pip install -r requirements/base.txt
RUN --mount=type=cache,target=/app/.cache/pip,sharing=shared pip install setuptools==78.1.0 pip==25.0.1 wheel==0.46.0
RUN --mount=type=cache,target=/app/.cache/pip,sharing=shared pip install -r requirements/base.txt
EXPOSE 8000
CMD gunicorn --workers=2 --name notes --bind=0.0.0.0:8000 --max-requests=1000 notesserver.wsgi:application
CMD ["gunicorn", \
"--workers=2", \
"--name", "notes", \
"--bind=0.0.0.0:8000", \
"--max-requests=1000", \
"notesserver.wsgi:application"]

View File

@ -1,2 +1,4 @@
./manage.py migrate
./manage.py search_index --rebuild -f
# Re-index with meilisearch
./manage.py shell -c "from notesapi.v1.views.meilisearch import reindex; reindex()"