Cadence — live student progress dashboards for Jupyter teaching
Project description
Cadence — live student progress dashboards for Jupyter
cadence-edu is the Jupyter-side half of Cadence: a tiny set of magics and helpers that let a teacher register checkpoints in a notebook, students answer them inline from their own notebooks with check("id", value), and a teacher dashboard shows live solve counts, attempts-to-first-correct, and the most common wrong answers in real time.
No grader. No autograder pipeline. No login required for quick one-off lessons. Just pip install, %load_ext cadence, and a join code on the projector.
pip install cadence-edu
Quickstart (5 minutes)
You already have (or are writing) a Jupyter teaching notebook with worked solutions. The fastest path to a live class is two magics:
# Cell 1 (first cell of your authoring notebook):
%load_ext cadence
# ... your normal teaching content: markdown headings, code cells with
# the reference solutions you'd already write to teach the lesson ...
# Cell N (last cell, once you've Run All from the top):
%cadence_autoregister
%cadence_autoregister walks the notebook, finds your exercises (heading +
solution-cell pairs, or cells you explicitly tagged with # cadence:
markers), reads each answer value from the live kernel, infers the
comparator from its type, and writes a registered copy of your notebook.
Then you Run-All that registered copy and it builds the student notebook
for you.
Three notebooks, one source of truth
You end up with three files on disk, each playing a different role:
(1) teacher.ipynb ← what you author. Plain teaching notebook
│ + a handful of `# cadence:` comments to
│ label exercises (or none at all if your
│ notebook already has clear heading +
│ code-cell structure).
│ %cadence_autoregister (run once you're happy with (1))
▼
(2) teacher_registered.ipynb ← auto-generated. Same content as (1), but
│ with `%cadence_register` magics wired
│ into each exercise. Running it registers
│ the lesson on the dashboard and produces
│ (3). Safe to commit to git — this is
│ your canonical "what's registered" record.
│ %cadence_scaffold (already at the bottom of (2))
▼
(3) teacher_registered_student.ipynb ← what you share with students.
Exercises stubbed, your reference
solution removed, `%cadence_session`
+ the package install pre-filled.
Why three and not one? The split lets each file have a single, clear lifetime:
- (1) is the file you keep editing as the lesson evolves.
- (2) is the snapshot that backs the live lesson on the dashboard. Re-run it to re-register after edits.
- (3) is the deliverable. You only ever hand this one to students.
You only ever author file (1). The other two are derived from it — every
%cadence_autoregister regenerates them cleanly.
First cell of every Cadence-aware notebook should be
%load_ext cadence. Magics, tab-completion, the# cadence:starterinput transformer that lets you write free-form prose inside starter stubs, and the bare-namecheck/show_hint/ etc. all register at extension-load time. Cells that run before%load_ext cadenceskip everything.
Discovering commands as you go: type
%cadence_<Tab>for autocompletion,%cadence_register?for argparse-style help on any magic, or%cadence_helpfor a one-page cheatsheet of every Cadence magic with its exact syntax. After typing%cadence_lesson(or%cadence_course) the names cached in~/.cadence/lessons.yamltab-complete too.
Concepts
| Term | What it is |
|---|---|
| Lesson | One notebook's worth of checkpoints. Created with %cadence_create_lesson. Has its own join code + teacher token. Anyone can create one — no account required. |
| Course | A named group of notebook lessons (e.g. "Fall 2026"). Created with %cadence_create_course. Requires %cadence_login. Students join the course with one code, then pick a notebook. |
| Checkpoint | One expected answer in a lesson. Has an ID, a comparator (exact/numeric/set/regex/manual), an optional hint, and an optional worked solution. Registered with %cadence_register. |
| Session | A student's enrollment in a lesson or course. Started with %cadence_session <code> "<name>". |
Markers vs magics — the discipline
Cadence has two kinds of syntax. The rule is simple and worth holding in mind because every other detail follows from it.
| Form | Purpose | Examples | |
|---|---|---|---|
| Markers | Comments — # cadence:foo in code cells, <!-- cadence:foo --> in markdown cells |
Static metadata. They label what a cell IS. They never do anything when you run the cell — they sit there waiting for tools to read them. | # cadence:checkpoint setup.arange# cadence:solution# cadence:hint try ...<!-- cadence:task setup.arange --> |
| Magics | Jupyter line/cell magics — %cadence_foo / %%cadence_foo |
Actions. They DO something now: talk to the server, read your notebook, write a file. | %cadence_create_lesson "..."%cadence_autoregister%cadence_scaffold%%cadence_register_yaml |
So when you see # cadence:checkpoint mean.basic, it doesn't talk to any
server — it just labels the cell. When you see %cadence_autoregister, it's
doing work in real time and might prompt you.
Teacher workflow
The recommended path: %cadence_autoregister
You already have (or are writing) a notebook with worked solutions. The
fastest path from "I have a teaching notebook" to "I have a live class"
is one magic and one prompt-walkthrough — %cadence_autoregister.
Concretely: in your existing teaching notebook, run all cells end-to-end so your answer variables exist in the kernel, then in a new cell at the bottom run:
%load_ext cadence
%cadence_autoregister
It walks you through four prompts:
- Auto-reveal solutions after N wrong attempts? Empty → default of 3.
Type
0(or pass--no-solutions) to disable reveals notebook-wide. When reveals are on, the teacher's reference code in each exercise cell becomes the worked solution students see when they unlock. - Sign in to track this lesson under your account? (Only asked if you aren't already signed in.) Required for courses, optional otherwise.
- Add this lesson to a course? Only asked if you're signed in. Empty
for standalone; a course name to attach to an existing one; or
new: <name>to create a new course. - How many days to keep each student's data? Empty → 7 days for a standalone lesson, 90 days for a course.
It writes <your_notebook>_registered.ipynb. Open it, do "Run All", and
the final cell — also generated for you — calls %cadence_scaffold,
which writes <your_notebook>_registered_student.ipynb. That's the file
you share with students.
Two ways to tell autoregister which cells are exercises, and you can mix them:
- Explicit (recommended for control): put
# cadence:checkpoint <id>at the top of each solution cell. - Implicit (works on a vanilla notebook): if you have no checkpoint
markers, autoregister pairs every markdown-heading cell with the code
cell that follows it as an exercise. The id is slugified from the
heading. Pass
--allto force this even when manual markers exist.
In either case, the answer value is read from the kernel namespace, the
comparator is inferred from its type, and a %cadence_register … line
gets injected at the top of the exercise cell — so when you scroll past
an exercise the registration sits right above the code that produced it.
No giant YAML block at the top to maintain.
Comparator inference:
| Value | Comparator | Notes |
|---|---|---|
int, float, numpy scalar |
numeric (tolerance 0.001) |
|
str |
exact |
text answers — punctuation matters |
bool |
exact |
|
list, tuple, numpy array |
set (order-insensitive) |
override per-exercise with # cadence:checkpoint <id> exact for ordered match |
set |
set |
|
| (override) | manual |
# cadence:checkpoint <id> manual — free-text reflection, no value extracted, student self-attests with mark_done |
How autoregister decides — the rules
Two questions per cell: is this an exercise? and what's the answer? Stated explicitly so you can tell at a glance whether your notebook is going to autoregister cleanly or whether you need explicit markers.
Is this cell an exercise?
- Explicit mode (any cell has
# cadence:checkpoint): exercise iff the cell has that marker. Every other code cell is treated as setup and copied verbatim. The markdown cell directly above an exercise becomes its task description (if there is one). - Auto mode (no checkpoint markers in the notebook): exercise iff
(a) a markdown cell with a heading sits above it, claimed by no
earlier code cell, and (b) its extracted value is a "primitive
answer type" (
int,float,str,bool, list/tuple/set of those, numpy scalar / array). If either fails, the cell is treated as setup and copied verbatim. - Pure-import cells and magic-only cells are always treated as setup regardless of mode.
- Pass
--allto autoregister to force auto mode even when manual markers exist (useful for a quick first pass on a notebook you're about to add markers to).
What's the answer?
Autoregister parses the cell's AST and looks at the last statement:
| Last statement | What gets used as the answer |
|---|---|
A bare expression (Jupyter display style) — e.g. arr.mean() on its own line |
The value of that expression, looked up in the live kernel namespace. |
An assignment to a single name — e.g. mean_value = arr.mean() |
The current value of mean_value in the kernel namespace. |
An augmented assignment — total += 1 |
The current value of total in the kernel. |
Anything else (an if/for/def/import-only ending, multi-target assignment, etc.) |
Autoregister errors with a teacher-friendly message asking you to end the cell with the answer on its own line. |
In all cases the value comes from the live kernel — you must have
run the cell (and the cells before it) end-to-end before invoking
%cadence_autoregister. If a referenced variable isn't defined, you
get a clear error pointing at which cell and which variable.
Common notebook shapes and what happens:
| Shape | Outcome |
|---|---|
| Heading → markdown explanation → solution cell → heading → solution cell ... | Clean pairing in auto mode; one exercise per heading. |
| Multiple solution cells under one heading | Only the first code cell under each heading becomes the exercise; the rest are treated as setup (copied verbatim). Add explicit # cadence:checkpoint markers if you want each one to be a separate checkpoint. |
| Code cells without any preceding heading | Treated as setup, copied verbatim. Most often this is imports, helper functions, or data loading — exactly the right outcome. |
| Lots of cells with no clear heading structure | Auto mode will find few or no exercises and emit "⚠ Found no exercise cells." Drop # cadence:checkpoint <id> markers on the cells you want, and re-run. Manual mode doesn't need any heading at all. |
| A "Setup" or "Imports" section under a heading | Auto-mode silently treats it as setup because the value isn't a primitive (a Generator / DataFrame / module). No special syntax needed. |
| Exercise that should be free-text (a reflection) | Mark explicitly: # cadence:checkpoint reflect manual. Autoregister skips value extraction and registers as manual. |
Validating the result. The card autoregister prints lists every
detected checkpoint with its inferred id / comparator / expected. Read
it before opening the registered notebook — if anything looks wrong
(an id slugged oddly, a comparator inferred the wrong way), the fix is
usually one explicit # cadence:checkpoint <id> [<comparator>] marker
on the offending cell. Re-running autoregister is cheap and
idempotent.
The marker toolkit
All markers are comments (so they're inert at runtime — Cadence just
reads them when scaffolding). They label what a cell is for tooling;
magics (%cadence_*) are what do something. The set you can reach for:
| Marker | Where | What it does |
|---|---|---|
# cadence:checkpoint <id> [<comparator>] |
Top of a code cell | Marks this cell as exercise <id>. Optional second word overrides the inferred comparator (e.g. manual, exact). |
<!-- cadence:task [<id>] --> |
Markdown cell | Marks the markdown as task prose. If an id is given, the next code cell becomes the exercise stub for that id (and # cadence:checkpoint isn't needed). |
# cadence:hint <text> |
Inside an exercise cell | Becomes the hint for that checkpoint. Markdown allowed — backticks, code fences, **bold**. (The older # cadence:hint: <text> form with a trailing colon also still works, for back-compat with existing notebooks.) |
# cadence:starter … # cadence:end |
Inside an exercise code cell | The region between becomes the student stub body (instead of # Your code here). The kernel comments this region out at execution time, so it can contain prose / pseudocode / unfilled placeholders that wouldn't otherwise parse as Python. Anything outside the markers is treated as the teacher's reference and stripped from the student notebook. |
# cadence:given … # cadence:end |
Inside an exercise code cell | Setup code (loaded data, seeded RNG draws, problem inputs) that the student also needs to see. Runs in the teacher kernel (no comment-out) and is copied verbatim into the student notebook above the starter stub. Use when the teacher's reference solution needs variables that students should start with too. |
# cadence:no-solution |
Inside an exercise code cell | Suppress the auto-revealed worked solution for this one checkpoint, even when reveals are globally on. For exercises where the answer is short enough that revealing it gives the whole question away. |
# cadence:reveal-after N |
Inside an exercise code cell | Per-checkpoint override of the global --reveal-after-attempts value. Use for a harder exercise you want students to wrestle with longer. |
# cadence:hint-after N |
Inside an exercise code cell | Same idea, for the hint-unlock threshold (default 2 — students get one try on their own before the hint button appears). |
# cadence:solution |
Top of a code cell | Copy this whole code cell verbatim into the student notebook. Use for shared setup, an explainer snippet, or a worked solution you want students to see. Mutually exclusive with # cadence:checkpoint — solution means "show this to students," checkpoint means "stub it out." Don't mix them in the same cell. |
# cadence:hide … # cadence:end |
Inside a code cell | The region between is stripped from both the registered teacher notebook and the student notebook — purely teacher-side authoring notes. |
<!-- cadence:hide --> … <!-- cadence:end --> |
Inside a markdown cell | Same — strips a private aside from inside an otherwise-public markdown cell (e.g. "this trips up students because…" inside an exercise description). |
Solutions are revealed by default. As of 0.2.8, every auto-checked checkpoint registers with the teacher's reference code as the worked solution, unlocked after 3 wrong attempts. Pass
--no-solutionsto%cadence_autoregisterto suppress reveals notebook-wide, or drop# cadence:no-solutionin any cell to suppress just that one.
The "ad hoc content for students" cases all fall out of this toolkit:
- Extra code only the student sees → put it in its own cell, top-tag it
# cadence:solution. - Setup data students need + teacher kernel also needs → wrap in
cadence:given/cadence:end. - Extra prose only the student sees → markdown cell with
<!-- cadence:task -->(no id needed) or just a heading. - Stuff only the teacher sees → wrap in
cadence:hide(in either code or markdown). - Starter code inside an exercise stub → wrap your scaffolded structure in
cadence:starter/cadence:end.
Alternative registration paths
%cadence_autoregister is the recommended path. The original mechanisms
all still work, in case one of them fits your workflow better:
-
YAML in a cell —
%%cadence_register_yamlfollowed by a YAML list of checkpoints. Good when you want to type expected values explicitly rather than have them inferred from kernel state, or when you have no obvious "answer variable" to extract:%%cadence_register_yaml - id: setup.mean-value comparator: numeric expected: {value: 49.5, tolerance: 0.001} hint: "average of 0..99" - id: discovery.higgs-peak comparator: exact expected: 125 reveal_after: 3 solution_code: | bin_edges = np.arange(100, 151) counts, _ = np.histogram(m_gg, bins=bin_edges) int(bin_edges[np.argmax(counts)]) allow_submissions: true
-
YAML in a file —
%cadence_register_yaml_file checkpoints/week3.yaml. Use when checkpoint definitions belong in version control alongside the notebook (PR-reviewable rubric changes; many notebooks sharing one rubric). -
Inline per-checkpoint —
%cadence_register <id> --comparator … --expected …. Useful for quick fixes mid-class or one-checkpoint demos. The full flag set:%cadence_register fib-10 \ --comparator numeric \ --expected '{"value": 55, "tolerance": 0.001}' \ --hint "Remember: fib(0)=0, fib(1)=1." \ --reveal-after 3 \ --solution-value "55" \ --order 2
-
Python API —
cadence.api.CadenceAPI().register_checkpoint(...). Use when generating checkpoints programmatically (per-student randomized variants; CI lesson-prep scripts).
Comparators across all forms:
| Comparator | --expected / expected: |
Match rule |
|---|---|---|
exact |
'"hello"' or {value: "hello"} |
str(submitted).strip() == str(value).strip() |
numeric |
{value: 55} or {value: 3.14, tolerance: 0.001} |
abs(submitted - value) <= tolerance |
set |
{value: [1, 2, 3]} |
set(submitted) == set(value) (order-independent) |
regex |
{pattern: "^[A-Z].*"} |
re.match(pattern, str(submitted)) |
manual |
(none) | Student self-attests with mark_done("id") |
Creating courses
%cadence_autoregister's third prompt covers the common case (attach this
lesson to a course, or create a new one). If you'd rather do it explicitly:
%load_ext cadence
%cadence_login # required for courses
%cadence_create_course "Fall 2026 Statistics"
%cadence_add_notebook "Week 1 — Variables"
%cadence_add_notebook "Week 2 — Distributions"
%cadence_add_notebook creates a fresh lesson inside the active course
and inherits the course's retention. To pull in a lesson you already
created standalone, use
%cadence_attach_lesson "My Lesson" --to "Fall 2026 Statistics".
Generating the student notebook (%cadence_scaffold)
If you used %cadence_autoregister, the generated registered notebook
already has a %cadence_scaffold cell at the bottom — running it
produces the student version. You can also run scaffold directly on any
notebook with the marker toolkit applied:
%cadence_scaffold # auto-detects the current notebook
%cadence_scaffold teacher.ipynb # or pass it explicitly
Or from the shell:
cadence-cli scaffold teacher.ipynb
Auto-detection works in VSCode's Jupyter extension and in JupyterLab /
classic Notebook served by jupyter_server ≥ 2. If it can't figure out
the path, you'll see a clear error asking you to pass it.
The output <teacher>_student.ipynb contains:
- A boxed welcome panel summarising the student-side API (
check,submit_image,mark_done,show_hint,show_solution). - A
%load_ext cadence+%cadence_session <code> "your name"header, join code auto-filled from~/.cadence/lessons.yaml. - All markdowns with
<!-- cadence:task -->or a heading, copied through (so section structure is preserved). - One stub per exercise — placeholder body plus
check("id", ...). Override the placeholder with a# cadence:starterblock. - Any code cell tagged
# cadence:solution, copied verbatim. - Nothing inside any
cadence:hideblock — those are teacher-only.
Pass --join-code <code> to override the lookup, --out path for a
custom path, or --force to overwrite an existing student notebook.
Verifying before class
%cadence_self_test
Submits each checkpoint's own expected answer and prints a pass/fail table. Catches typos in --expected and bad tolerance bounds. Regex checkpoints are skipped (can't auto-synthesize a matching string).
Displaying the join code
%cadence_show_join
Big-text rendering of the active lesson or course's join code — designed for projector / screen share.
Managing existing lessons and courses
%cadence_lesson "Week 3: Fibonacci" # reactivate a cached lesson
%cadence_course "Fall 2026 Statistics" # reactivate a cached course
%cadence_clone_lesson "Fall 2026 Week 3" --as "Spring 2027 Week 3"
# duplicate (fresh code + token)
%cadence_attach_lesson "Lab 1" --to "Fall 2026 Statistics"
%cadence_detach_lesson "Lab 1" --from "Fall 2026 Statistics"
%cadence_delete_lesson "Old test lesson" --yes # wipes the lesson + ALL student data
%cadence_delete_course "Fall 2025" --yes # wipes the course; attached lessons survive
Rotating a leaked teacher token
%cadence_rotate_token # mints a fresh teacher_token
%cadence_rotate_token --also-join-code # full revocation: also reissues the join code
# (existing student notebooks break)
%cadence_rotate_token --course # rotate the active course's token
The local ~/.cadence/lessons.yaml is updated in place and a fresh dashboard URL is printed.
Code submissions (optional)
For checkpoints registered with --allow-submissions, students can use %%cadence_submit <id> to send the cell's source code to your dashboard for review:
%%cadence_submit fib-recursive
def fib(n):
return n if n <= 1 else fib(n-1) + fib(n-2)
fib(10)
The cell still runs normally — the student sees their output. The source is sent alongside.
Retention controls
%cadence_set_retention --days 30 # active lesson
%cadence_set_retention --days 90 --course # active course
Retention can only be shortened, never extended. To lengthen it you'd clone the lesson and migrate fresh students over — a design constraint, not a bug.
Student workflow
Joining
%load_ext cadence
%cadence_session soup-river-42 "Alice Smith"
If the join code belongs to a course, the magic prints the list of notebooks and reminds you to pick one:
%cadence_notebook "Week 1 — Variables"
Answering checkpoints
from cadence import check, show_hint, show_solution, mark_done, submit_image
result = check("fib-10", fib(10)) # returns a CheckResult
# result.is_correct, result.attempt_num, result.hint
# Also renders in the cell as a coloured ✅/❌ chip.
show_hint("fib-10") # fetches the teacher's hint
show_solution("fib-10") # fetches the worked solution if revealed
mark_done("manual-checkpoint") # self-attest a manual checkpoint
submit_image("plot-1", fig) # for `--allow-submissions` image checkpoints
Timed answers
%%cadence_time fib-10
def fib(n):
return n if n <= 1 else fib(n-1) + fib(n-2)
fib(10)
Measures wall-clock time and submits the last-expression value as the answer. Only the first correct attempt's time contributes to the dashboard histogram, so re-running a known-good cell doesn't pollute the stats. If the cell raises, nothing is submitted.
Your data rights (GDPR)
cadence-edu ships explicit support for the three Article-15/17/20 rights:
%cadence_my_data # Article 15 — see everything stored about this session
%cadence_export_my_data # Article 20 — dump it as JSON
%cadence_export_my_data --path ~/my-cadence-data.json
%cadence_delete_my_data --yes # Article 17 — wipe attempts, submissions, the session itself
%cadence_delete_my_data cannot be undone and clears the active session from the kernel afterwards.
CLI helpers
The package also installs a cadence-cli for two jobs from the shell:
Scaffold a starter notebook. Drops a pre-wired .ipynb in the current
directory so you don't start from a blank cell:
cadence-cli new teacher --name "Week 3: Fibonacci" # writes ./teacher-setup.ipynb
cadence-cli new student --name "Week 3: Fibonacci" # writes ./student.ipynb
cadence-cli new teacher --out path/to/setup.ipynb --force # custom location, overwrite
The teacher scaffold has %load_ext cadence → %cadence_login →
%cadence_create_lesson → a YAML registration block → %cadence_self_test
in order. The student scaffold has a placeholder %cadence_session line and
one example check(...). Both are tiny on purpose — they're a launching
pad, not a tutorial. The longer-form particle-physics demos live at
cadence-dash.com/demo.
Generate the student notebook from a teacher notebook. Same logic as
%cadence_scaffold (see above)
but runnable from the shell — handy in CI or when prepping multiple lessons
at once:
cadence-cli scaffold teacher.ipynb # writes ./teacher_student.ipynb
cadence-cli scaffold teacher.ipynb --out wk3.ipynb # custom output path
cadence-cli scaffold teacher.ipynb --join-code abc-def # override the cached lookup
cadence-cli scaffold teacher.ipynb --force # overwrite
Manage locally-cached teacher credentials — useful when the server-side lesson has been deleted but the local YAML is stale, or when you suspect a token leak:
cadence-cli lessons list # every cached lesson + course, tokens masked
cadence-cli lessons forget "Week 3: Fibonacci" # drop a stale row (local only)
cadence-cli lessons forget "Week 3: Fibonacci" --yes # skip the confirmation prompt
cadence-cli lessons rotate "Week 3: Fibonacci" # mint a new teacher_token
cadence-cli lessons rotate "Spring 2026" --also-join-code # full revocation
forget only touches the local YAML. rotate calls the backend and updates the cache in place.
Configuration
Files
| Path | What it holds |
|---|---|
~/.cadence/lessons.yaml |
Cached teacher tokens + join codes for lessons and courses (mode 0600) |
~/.cadence/credentials.yaml |
Teacher JWT from %cadence_login (mode 0600) |
~/.cadence/terms.yaml |
Recorded ToS acceptance from %cadence_accept_terms |
Environment variables
| Variable | Default | Purpose |
|---|---|---|
CADENCE_API_URL |
https://api.cadence-dash.com |
Backend API base URL. Set to http://localhost:8000 for local dev. |
CADENCE_DASHBOARD_URL |
(falls back to CADENCE_WEB_URL, then http://localhost:3000) |
Where the teacher dashboard lives. Used to build the URLs printed by create-lesson. |
CADENCE_WEB_URL |
https://cadence-dash.com |
Public web URL — used for legal-page links. |
For self-hosted setups, set CADENCE_API_URL + CADENCE_DASHBOARD_URL to your own deployment.
Troubleshooting
"API not available" / SSL errors on first magic. The package defaults to the hosted backend at api.cadence-dash.com. If you're running locally, point it at your own instance:
export CADENCE_API_URL=http://localhost:8000
export CADENCE_DASHBOARD_URL=http://localhost:3000
Extension didn't load. Confirm the install with:
jupyter server extension list # Notebook 7 / JupyterLab
Then re-run %load_ext cadence in the kernel.
Stale cached lesson. If you docker compose down -v'd your local backend, your ~/.cadence/lessons.yaml will reference lessons that no longer exist. Drop them with cadence-cli lessons forget "<name>".
Teacher token leaked. %cadence_rotate_token mints a new one and invalidates the old. Add --also-join-code if you also need to lock out existing students.
Other primitives
A few legacy helpers are still exposed for the original code-submission flow:
CadenceAPI— direct API client (from cadence import CadenceAPI)ProblemNotebook/create_problem_notebook— pre-formatted problem-notebook templates with embedded metadata and test cases
These predate the live-progress flow and aren't on the happy path; use them only if you're integrating with an external grader.
Links
- Hosted dashboard & docs: https://cadence-dash.com
- Setup guide: https://cadence-dash.com/guide
- Source: https://github.com/livaage/cadence
- Issues: https://github.com/livaage/cadence/issues
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cadence_edu-0.2.26.tar.gz.
File metadata
- Download URL: cadence_edu-0.2.26.tar.gz
- Upload date:
- Size: 104.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38a17b6f9ac4ad0e4f53caf808d5d8edbe9affd7232d407b6271992ae5fc2a58
|
|
| MD5 |
6beb259d5da92b743a7f294e3f946b52
|
|
| BLAKE2b-256 |
ff8b960a8de6673f36ddcce9baa02c50fd9ce32e132131fae9affd35c3847d92
|
File details
Details for the file cadence_edu-0.2.26-py3-none-any.whl.
File metadata
- Download URL: cadence_edu-0.2.26-py3-none-any.whl
- Upload date:
- Size: 98.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0d0beef6f4cb21b8f743ee84e396f31cde7b00847a878937afb7bef338691fd
|
|
| MD5 |
bd63f21d63ddb1e140ebe1849f722ebf
|
|
| BLAKE2b-256 |
f06d38161028011491a093c7087835c876ad7f5d1cbe2a5b9f39fd141e1106e2
|