Open-source project
csev/py4e avatar
csev/py4e

py4e: the course site that needs a second repository, a database upgrade and a key from a person

Web site for www.py4e.com and source to the Python 3.0 textbook

3,105 stars1,844 forksJavaScriptLicense varies

At a glance

What is it?
The public py4e repository carries the Python for Everybody site and the Python 3 book source, but not the LMS it mounts, not the quiz content, and not a runnable checkout. Its own setup guide is written for one person's Macintosh.
Who is it for?
py4e is worth reading as course material and as a worked example of a Tsugi site, but a full local deployment needs three things the public repository cannot supply: the Tsugi checkout, the quiz content, and time with whoever grants access.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The site is a PHP app that expects a second repository inside it

A fresh checkout of py4e is not a running site. The setup guide asks for two clone steps, the second of them landing a different project inside the first:

bash
cd /Applications/MAMP/htdocs
git clone https://github.com/csev/py4e.git
cd py4e
git clone https://github.com/csev/tsugi.git

There is no submodule entry, no package manager step and no script that fetches the inner repository. Everything at the top level of this tree is a PHP page or an asset: `index.php`, `nav.php`, `buildmenu.php`, `editors.php`, `install.php`, `launcherror.php`, `materials.php`, `coursesredirect.php`, `booktop.php` and `bookfoot.php`. The project is labelled JavaScript as its primary language, and `media.env`, `media.yaml` and a `.well-known` directory are the only other entries at the root that hint at anything below the PHP surface. `tsugi.php` then mounts the LMS controllers, `/announcements`, `/login` and `/pages`, directly under py4e so they read as part of the course site.

Two database accounts with the password printed in the guide

The guide creates a database and two identical users, one for `localhost` and one for `127.0.0.1`, because the connection string that follows connects to the numeric address while the site itself is served from the name:

sql
CREATE DATABASE tsugi DEFAULT CHARACTER SET utf8;
CREATE USER 'ltiuser'@'localhost' IDENTIFIED BY 'ltipassword';
GRANT ALL ON tsugi.* TO 'ltiuser'@'localhost';
CREATE USER 'ltiuser'@'127.0.0.1' IDENTIFIED BY 'ltipassword';
GRANT ALL ON tsugi.* TO 'ltiuser'@'127.0.0.1';

Those credentials are then written into `config.php` as `ltiuser` and `ltipassword`, on a MAMP instance where MySQL listens on port 8889. The admin console is unlocked by `$CFG->adminpw`, and the value the guide uses for it is the word `short`. Every one of these is a sample value, which is exactly why the guide has to be read as a template rather than as something to paste unchanged. It never says so. A reader who treats the block above as a starting point ends up with a database account named ltiuser holding the password ltipassword, and an admin console guarded by short.

One config line carries a stray dot, and the paths around it disagree

Two of the sample values disagree about how a relative path is written. The lessons manifest is addressed as `$CFG->dirroot.'/../lessons.json'`, while the install folder right below it is written as `$CFG->dirroot.'./../mod'`, with a leading dot inside the quoted string and no separator after it:

php
$CFG->lessons = $CFG->dirroot.'/../lessons.json';
$CFG->tool_folders = array("admin", "../tools", "../mod");
$CFG->install_folder = $CFG->dirroot.'./../mod'; // Tsugi as a store

The third line resolves to a path with a dot segment in the middle of it, which the filesystem tolerates but which is not what the neighbouring line does. The `tool_folders` array mixes a bare `admin` entry with two paths that walk up out of the Tsugi directory, so the same array refers to three different roots depending on where the code is running. Between the samples the guide inserts bare `...` lines, and the instruction covering them is to scroll through the file and set every variable by hand. A file copied from this page is therefore a starting point that needs reading rather than trusting.

Google login is configured without a port while the site runs on 8888

Signing in is optional, and the guide treats it as a console trip. Create an OAuth Client ID as a Web Application, put `http://localhost` in Authorized JavaScript Origins, and put `http://localhost/py4e/login` in the Authorized redirect URI. It then adds a note that port numbers are not needed in either value, while every address in the surrounding instructions, from the site root to the admin console and the tools App Store, carries `:8888`. Whether the provider accepts a portless redirect for a site that only answers on 8888 is worth checking before spending an afternoon on a login that bounces. The result of the console trip goes into `config.php` as `$CFG->google_client_id` and `$CFG->google_client_secret`, and the same section offers an optional Maps key stored alongside it as `$CFG->google_map_api_key`.

The first page load fails on purpose, then needs an upgrade run

Starting the application is documented as a sequence of complaints. Opening `/py4e/tsugi/` reports that tables have not been created and points at the admin console, which asks for the adminpw value before it will unlock. From there, the Upgrade Database option builds the tables and the red warning clears, or the same work happens on the command line with `cd py4e/tsugi/admin` followed by `php upgrade.php`. The guide then tells you to keep refreshing the page until the error messages go away. Two more steps follow the same pattern: installing the peer grading tool from https://github.com/tsugitools/peer-grade through the admin interface, and installing the Gift Quiz tool, each of which needs the database upgrade run again afterwards. In other words, the schema changes as tools arrive, and a partially upgraded site looks identical to a broken one.

The LTI secret may be any value at all, and the test key is 12345

One instruction is worth reading twice. After the upgrade, you are told to open the `lti_key` table, find the row whose `key_key` is `google.com`, and put a value in the `secret` column: anything will do, as long as it is not empty, or the internal LTI tools will not launch. That is the credential that ties this site's LTI launches to Google, and the guide is content for it to be arbitrary. A second fixed value appears at the end of the same section. The tools App Store at `/py4e/tools/` lets you run test launches as instructor and student in a test environment using the key `12345`, published in the guide itself. Both are fine on a laptop that nobody else can reach and indefensible anywhere else.

The quizzes are not in this repository and cannot be fetched

The course cannot be completed from what is published here. The quiz content lives in a separate private repository, `py4e-private`, which the guide says requires being added by the maintainer, and the quiz unlock password comes from the same person. The stated policy is that access goes only to those verified as teaching the course and adopting the materials. The wiring is one line in `config.php`, pointing the gift quizzes at the private checkout:

php
$CFG->giftquizzes = $CFG->dirroot.'/../py4e-private/quiz';

The other two required LTI tools do ship here, in the `py4e/tools` folder. So the split is deliberate: the public tree holds the site, the book and the exercises, while the assessed material and the ability to unlock it stay behind a request to a person. Anyone planning a deployment needs to know that before they start, not after the site is running and empty.

Three generations of the book sit side by side, and the release names look backwards

The tree carries the same material at three ages: `book.php`, `book2.php` and `book3/`, `code/`, `code2/` and `code3/`, `lectures/` and `lectures3/`, plus an `old/` directory. The guide points readers at `code3` for the Python 3 versions and sends them to `book3/README.md` for detail, which makes the older directories a question rather than an answer. The releases read the same way. v2.0 is named Prior to the big Tsugi Merge and v2.1 is named Before major cleanup, both labels describing the state that came after the tag, and they were published in 2016 and 2017. The next tag is 26.07.1, named Pre Accessibility Fixes, published 2026-07-28, with a version scheme that switched from two-component to date based. Nine years separate v2.1 from the current tag.

Editorial conclusion

py4e is worth reading as course material and as a worked example of a Tsugi site, but a full local deployment needs three things the public repository cannot supply: the Tsugi checkout, the quiz content, and time with whoever grants access. If you are setting it up, fix the install_folder line before the first page load, change the ltiuser password and the adminpw value before the machine is reachable by anyone else, and expect a first run that only stops complaining after the database upgrade. If you are only after the Python 3 exercises, the code3 folder is the part that needs none of this.

Frequently asked questions

What programming language does py4e teach?

Python 3. The repository presents itself as the source to the Python 3.0 textbook and states that the Python3 versions of the code are all in the code3 folder.

Does the py4e repository state a license for the course materials?

No license appears in the packaging data, and no LICENSE file sits at the root of the tree. What is there is an OER.md file, alongside TRANSLATION.md and an ISO-639-2_utf-8.txt language code table.

What does py4e need before it will run on a local machine?

A second repository. The guide has you clone csev/tsugi inside the py4e checkout, copy config-dist.php to config.php, create a tsugi database with an ltiuser account, and then run the database upgrade from the admin console or with php upgrade.php.

Can a teacher run the whole py4e course from the public repository?

No. The quiz content lives in a private repository, py4e-private, which the guide says requires being added by the maintainer, and the quiz unlock password comes from the same person. Access is described as granted only to verified teachers who adopt the materials.

What test key does the py4e tools App Store use?

The key '12345', printed in the guide so you can run test launches as both instructor and student in a test environment. It is one fixed value for every installation.

Official sources

  1. csev/py4e on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/csev-py4e.svg)](https://hysenlabs.com/projects/csev-py4e)