Welcome to canvas-core’s documentation!
canvas-core
Quickstart
First, install canvas-core
.
#> pip install canvas-core
Then, add canvas_core
to INSTALLED_APPS
in your project settings.
# settings.py
INSTALLED_APPS = [
# ...
"canvas_core",
"canvas_core.plugins",
"canvas_core.caching",
"canvas_core.calendars",
"canvas_core.commands",
"canvas_core.config",
"canvas_core.events",
"canvas_core.metrics",
"canvas_core.storage",
"canvas_core.templating",
# ...
]
Finally, add canvas_core
’s URL patterns to your project’s urls.py
.
# urls.py
from django.urls import include, path
urlpatterns = [
# ...
path("canvas_core/", include("canvas_core.urls")),
# ...
]
Contributing
If you want to contribute to the canvas-core
project, you
can open a pull request to our repository.
Getting Started
Ready to contribute? Here’s how to set up canvas-core
for local development:
Fork the
canvas-core
repo on GitHub.Clone your fork locally:
git clone git@github.com:your-github-username/canvas-core.git
Navigate to your clone:
cd canvas-core
Activate the virtualenv:
poetry shell
Install the dependencies:
poetry install
Install the pre-commit hooks:
pre-commit install --install-hooks
Create a branch for your change:
git checkout -b name-of-your-bugfix-or-feature
Start the example project, if needed for testing:
./manage.py runserver_plus
Make your changes in the editor of your choice.
Run the test suite:
pytest
Commit your changes and fix any issues reported by
pre-commit
.Push your changes:
git push --set-upstream origin name-of-your-bugfix-or-feature
Submit a pull request in GitHub.
Pull Request Guidelines
Before you submit a pull request, make sure that it meets our guidelines:
Pull requests must have tests.
Pull requests must be narrow in their scope, and ideally small in size.
If the pull request adds or changes functionality, it should include updates to the documentation in
docs/
.
Adding an SDK resource
Create a new directory at
canvas_core/api_name
Run
./manage.py startapp api_name canvas_core/api_name
git add canvas_core/api_name && git commit -nm "Generated boilerplate for api_name"
pre-commit run --files canvas_core/api_name/**/*
git add canvas_core/api_name && git commit -nm "Boilerplate pre-commit fixes"
Update the
name
attribute of the newly-generatedAppConfig
class incanvas_core/api_name/apps.py
to be a subapp ofcanvas_core
(canvas_core.api_name
).Add
canvas_core.api_name
to theINSTALLED_APPS
inexample/settings.py
Add
canvas_core.api_name
to theINSTALLED_APPS
example inREADME.md
git add canvas_core/api_name README.md example/settings.py && git commit -m "Install canvas_core.api_name into the example app"
Documentation
Short description of the purpose and responsibilities of the API
Basic interface
Auto-generated module documentation
What events does it emit?
What errors does your API emit, and when?
What state does it hold? (usually models, but possibly also cache keys, etc)
Does it provide any HTTP API endpoints/urls?
Does it provide middleware or other Django-y things?
Conventions
Define your interface in
__init__.py
firstWrite tests against your interface (in
tests.py
for small APIs, ortests/**/test_*.py
files for larger ones)Define your data model, if any
Only top-level models should be exposed (i.e. models that you’d expect to be referenced by other models in the system)
Models should be exposed via
get_modelname_model()
functions, and use the app registry to resolve them (apps.get_model("api_name.ModelName", require_ready=False)
) to avoid load order dependencies
Provide admin classes for your data model!
Usually you’ll only want admin classes for the top-level models
Use the
django.utils.translation.gettext_lazy
(aliased to_
) when writing static strings (likehelp_text
for model and form fields)Add types to everything
If a type is not used directly (i.e. it’s only used for a type annotation) put it in an
if TYPE_CHECKING:
block to prevent unnecessary importsError handling
Modules should define their own exception classes, extending from CanvasCoreException.
Module-level exceptions should be appropriately descriptive, and generic enough to avoid leaky abstractions
Exceptions should not reveal the implementation
All module exceptions should be caught and re-raised as their own exceptions
For example, an ObjectDoesNotExist error from the Django ORM should be caught and re-raised as MoreSpecificModuleLookupError.
All raised exceptions must chain the original exception.
Logging
Metrics
Use python indetifier conventions for metric names
Perfer using the metrics decorators and context managers over custom metrics
QUICKSTART
REFERENCES