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
This commit is contained in:
parent
16012432a1
commit
d4a4274bc4
22
.github/workflows/test.yml
vendored
Normal file
22
.github/workflows/test.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
name: Run tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python 3.8
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.8
|
||||||
|
- name: Upgrade pip
|
||||||
|
run: python -m pip install --upgrade pip setuptools
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pip install 'tutor[dev]>=16.0.0,<17.0.0'
|
||||||
|
- name: Test lint, types, and format
|
||||||
|
run: make test
|
||||||
34
Makefile
Normal file
34
Makefile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
.DEFAULT_GOAL := help
|
||||||
|
.PHONY: docs
|
||||||
|
SRC_DIRS = ./tutornotes
|
||||||
|
BLACK_OPTS = --exclude templates ${SRC_DIRS}
|
||||||
|
|
||||||
|
# Warning: These checks are run on every PR.
|
||||||
|
test: test-lint test-types test-format # Run some static checks.
|
||||||
|
|
||||||
|
test-format: ## Run code formatting tests.
|
||||||
|
black --check --diff $(BLACK_OPTS)
|
||||||
|
|
||||||
|
test-lint: ## Run code linting tests
|
||||||
|
pylint --errors-only --enable=unused-import,unused-argument --ignore=templates --ignore=docs/_ext ${SRC_DIRS}
|
||||||
|
|
||||||
|
test-types: ## Run type checks.
|
||||||
|
mypy --exclude=templates --ignore-missing-imports --implicit-reexport --strict ${SRC_DIRS}
|
||||||
|
|
||||||
|
format: ## Format code automatically.
|
||||||
|
black $(BLACK_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
|
||||||
|
|
||||||
|
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}'
|
||||||
1
changelog.d/20231005_153517_codewithemad.md
Normal file
1
changelog.d/20231005_153517_codewithemad.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
- [Improvement] Added Makefile and test action to repository and formatted code with Black and isort. (by @CodeWithEmad)
|
||||||
@ -1,11 +1,10 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from glob import glob
|
|
||||||
import os
|
import os
|
||||||
import typing as t
|
import typing as t
|
||||||
|
from glob import glob
|
||||||
|
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
|
|
||||||
from tutor import hooks as tutor_hooks
|
from tutor import hooks as tutor_hooks
|
||||||
from tutor.__about__ import __version_suffix__
|
from tutor.__about__ import __version_suffix__
|
||||||
|
|
||||||
@ -16,11 +15,6 @@ if __version_suffix__:
|
|||||||
__version__ += "-" + __version_suffix__
|
__version__ += "-" + __version_suffix__
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
"unique": {
|
|
||||||
"MYSQL_PASSWORD": "{{ 8|random_string }}",
|
|
||||||
"SECRET_KEY": "{{ 24|random_string }}",
|
|
||||||
"OAUTH2_SECRET": "{{ 24|random_string }}",
|
|
||||||
},
|
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"VERSION": __version__,
|
"VERSION": __version__,
|
||||||
"DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/openedx-notes:{{ NOTES_VERSION }}",
|
"DOCKER_IMAGE": "{{ DOCKER_REGISTRY }}overhangio/openedx-notes:{{ NOTES_VERSION }}",
|
||||||
@ -30,14 +24,14 @@ config = {
|
|||||||
"REPOSITORY": "https://github.com/openedx/edx-notes-api",
|
"REPOSITORY": "https://github.com/openedx/edx-notes-api",
|
||||||
"REPOSITORY_VERSION": "{{ OPENEDX_COMMON_VERSION }}",
|
"REPOSITORY_VERSION": "{{ OPENEDX_COMMON_VERSION }}",
|
||||||
},
|
},
|
||||||
|
"unique": {
|
||||||
|
"MYSQL_PASSWORD": "{{ 8|random_string }}",
|
||||||
|
"SECRET_KEY": "{{ 24|random_string }}",
|
||||||
|
"OAUTH2_SECRET": "{{ 24|random_string }}",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Initialization hooks
|
# Initialization hooks
|
||||||
|
|
||||||
# To add a custom initialization task, create a bash script template under:
|
|
||||||
# tutorcodejail/templates/codejail/tasks/
|
|
||||||
# and then add it to the MY_INIT_TASKS list. Each task is in the format:
|
|
||||||
# ("<service>", ("<path>", "<to>", "<script>", "<template>"))
|
|
||||||
MY_INIT_TASKS: list[tuple[str, tuple[str, ...]]] = [
|
MY_INIT_TASKS: list[tuple[str, tuple[str, ...]]] = [
|
||||||
("mysql", ("notes", "tasks", "mysql", "init")),
|
("mysql", ("notes", "tasks", "mysql", "init")),
|
||||||
("lms", ("notes", "tasks", "lms", "init")),
|
("lms", ("notes", "tasks", "lms", "init")),
|
||||||
@ -56,23 +50,32 @@ for service, template_path in MY_INIT_TASKS:
|
|||||||
tutor_hooks.Filters.CLI_DO_INIT_TASKS.add_item((service, init_task))
|
tutor_hooks.Filters.CLI_DO_INIT_TASKS.add_item((service, init_task))
|
||||||
|
|
||||||
# Image management
|
# Image management
|
||||||
tutor_hooks.Filters.IMAGES_BUILD.add_item((
|
tutor_hooks.Filters.IMAGES_BUILD.add_item(
|
||||||
|
(
|
||||||
"notes",
|
"notes",
|
||||||
("plugins", "notes", "build", "notes"),
|
("plugins", "notes", "build", "notes"),
|
||||||
"{{ NOTES_DOCKER_IMAGE }}",
|
"{{ NOTES_DOCKER_IMAGE }}",
|
||||||
(),
|
(),
|
||||||
))
|
)
|
||||||
tutor_hooks.Filters.IMAGES_PULL.add_item((
|
)
|
||||||
|
tutor_hooks.Filters.IMAGES_PULL.add_item(
|
||||||
|
(
|
||||||
"notes",
|
"notes",
|
||||||
"{{ NOTES_DOCKER_IMAGE }}",
|
"{{ NOTES_DOCKER_IMAGE }}",
|
||||||
))
|
)
|
||||||
tutor_hooks.Filters.IMAGES_PUSH.add_item((
|
)
|
||||||
|
tutor_hooks.Filters.IMAGES_PUSH.add_item(
|
||||||
|
(
|
||||||
"notes",
|
"notes",
|
||||||
"{{ NOTES_DOCKER_IMAGE }}",
|
"{{ NOTES_DOCKER_IMAGE }}",
|
||||||
))
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@tutor_hooks.Filters.COMPOSE_MOUNTS.add()
|
@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`,
|
When mounting edx-notes-api with `--mount=/path/to/edx-notes-api`,
|
||||||
bind-mount the host repo in the notes container.
|
bind-mount the host repo in the notes container.
|
||||||
@ -85,7 +88,7 @@ def _mount_edx_notes_api(volumes, name):
|
|||||||
]
|
]
|
||||||
return volumes
|
return volumes
|
||||||
|
|
||||||
####### Boilerplate code
|
|
||||||
# Add the "templates" folder as a template root
|
# Add the "templates" folder as a template root
|
||||||
tutor_hooks.Filters.ENV_TEMPLATE_ROOTS.add_item(
|
tutor_hooks.Filters.ENV_TEMPLATE_ROOTS.add_item(
|
||||||
pkg_resources.resource_filename("tutornotes", "templates")
|
pkg_resources.resource_filename("tutornotes", "templates")
|
||||||
@ -108,26 +111,24 @@ for path in glob(
|
|||||||
tutor_hooks.Filters.ENV_PATCHES.add_item(
|
tutor_hooks.Filters.ENV_PATCHES.add_item(
|
||||||
(os.path.basename(path), patch_file.read())
|
(os.path.basename(path), patch_file.read())
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add configuration entries
|
# Add configuration entries
|
||||||
tutor_hooks.Filters.CONFIG_DEFAULTS.add_items(
|
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(
|
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(
|
tutor_hooks.Filters.CONFIG_OVERRIDES.add_items(
|
||||||
list(config.get("overrides", {}).items())
|
list(config.get("overrides", {}).items())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Notes public hosts
|
# Notes public hosts
|
||||||
@tutor_hooks.Filters.APP_PUBLIC_HOSTS.add()
|
@tutor_hooks.Filters.APP_PUBLIC_HOSTS.add()
|
||||||
def _notes_public_hosts(hosts: list[str], context_name: t.Literal["local", "dev"]) -> list[str]:
|
def _notes_public_hosts(
|
||||||
|
hosts: list[str], context_name: t.Literal["local", "dev"]
|
||||||
|
) -> list[str]:
|
||||||
if context_name == "dev":
|
if context_name == "dev":
|
||||||
hosts += ["{{ NOTES_HOST }}:8120"]
|
hosts += ["{{ NOTES_HOST }}:8120"]
|
||||||
else:
|
else:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user