Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ labels: bug
- OS:
- Python:
- Terminal:
- Pylings version:
- Pythonlings version:
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ jobs:
python-version: ${{ matrix.python-version }}
- run: pip install -e ".[dev]"
- run: pytest -v
- run: pylings --root tests/fixtures/passing_curriculum verify
- run: pythonlings --root tests/fixtures/passing_curriculum verify
- run: python -m pip install build
- run: python -m build
- run: python -m pip install --force-reinstall dist/*.whl
- run: pylings init --path /tmp/pylings-workspace
- run: pylings --root /tmp/pylings-workspace list
- run: pythonlings init --path /tmp/pythonlings-workspace
- run: pythonlings --root /tmp/pythonlings-workspace list
12 changes: 6 additions & 6 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ jobs:
- run: python -m pip install build
- run: python -m build
- run: python -m pip install --force-reinstall dist/*.whl
- run: pylings --version
- run: pylings init --path /tmp/pylings-workspace
- run: pylings --root /tmp/pylings-workspace list
- run: pylings --root /tmp/pylings-workspace solution variables1
- run: pylings --root /tmp/pylings-workspace reset variables1 --yes
- run: pylings --root tests/fixtures/passing_curriculum verify
- run: pythonlings --version
- run: pythonlings init --path /tmp/pythonlings-workspace
- run: pythonlings --root /tmp/pythonlings-workspace list
- run: pythonlings --root /tmp/pythonlings-workspace solution variables1
- run: pythonlings --root /tmp/pythonlings-workspace reset variables1 --yes
- run: pythonlings --root tests/fixtures/passing_curriculum verify
- uses: pypa/gh-action-pypi-publish@release/v1
14 changes: 7 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,13 @@ dmypy.json
# Pyre type checker
.pyre/

# Pylings runtime state (root install and any nested fixture roots)
.pylings/
# Pythonlings runtime state (root install and any nested fixture roots)
.pythonlings/
.superpowers/
.worktrees

# Local artifacts from older pylings workspaces; not part of this package.
/pylings/.gitignore
/pylings/.git/
/pylings/.pylings.toml
/pylings/exercises/
# Local artifacts from older pythonlings workspaces; not part of this package.
/pythonlings/.gitignore
/pythonlings/.git/
/pythonlings/.pythonlings.toml
/pythonlings/exercises/
14 changes: 7 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

## Project Structure & Module Organization

`pylings/` contains the installable application package. Core exercise loading, workspace setup, state, reset, solutions, and runner logic live in `pylings/core/`; CLI entry points are in `pylings/cli.py` and `pylings/__main__.py`; Textual screens/widgets live in `pylings/screens/` and `pylings/widgets/`; `pylings/pylings.tcss` holds TUI styles.
`pythonlings/` contains the installable application package. Core exercise loading, workspace setup, state, reset, solutions, and runner logic live in `pythonlings/core/`; CLI entry points are in `pythonlings/cli.py` and `pythonlings/__main__.py`; Textual screens/widgets live in `pythonlings/screens/` and `pythonlings/widgets/`; `pythonlings/pythonlings.tcss` holds TUI styles.

Curriculum files are split between `exercises/<topic>/<exercise>.py` for learner code, `checks/<topic>/<exercise>.py` for hidden assertions, and `solutions/<exercise>.py` for reference answers. Keep these trees aligned with `info.toml`, which defines order, hints, and docs URLs. Tests live in `tests/unit/`, `tests/integration/`, and `tests/tui/`, with fixtures in `tests/fixtures/`.

## Build, Test, and Development Commands

- `pip install -e ".[dev]"`: install pylings locally with pytest dependencies.
- `pylings init --path ./learn-python`: create a self-contained learner workspace.
- `pylings`, `pylings topics`, `pylings list`: launch the TUI or inspect progress.
- `pylings run variables1`, `pylings dry-run variables1`, `pylings solution variables1`: test exercise and solution flows.
- `pylings --root tests/fixtures/passing_curriculum verify`: smoke-test a known passing fixture.
- `pip install -e ".[dev]"`: install pythonlings locally with pytest dependencies.
- `pythonlings init --path ./learn-python`: create a self-contained learner workspace.
- `pythonlings`, `pythonlings topics`, `pythonlings list`: launch the TUI or inspect progress.
- `pythonlings run variables1`, `pythonlings dry-run variables1`, `pythonlings solution variables1`: test exercise and solution flows.
- `pythonlings --root tests/fixtures/passing_curriculum verify`: smoke-test a known passing fixture.
- `python -m pytest -q`: run the full suite configured in `pyproject.toml`.
- `python -m build`: build source and wheel distributions.

Expand All @@ -22,7 +22,7 @@ Use Python 3.11+ idioms and 4-space indentation. Prefer small, typed functions w

## Testing Guidelines

Use pytest for all tests; async tests are supported by `pytest-asyncio` in auto mode. Add unit tests for core behavior, integration tests for CLI/workspace flows, and TUI tests for Textual interactions. When changing curriculum, update `exercises/`, `checks/`, `solutions/`, and `info.toml`, then run relevant pytest files plus `pylings --root tests/fixtures/passing_curriculum verify`.
Use pytest for all tests; async tests are supported by `pytest-asyncio` in auto mode. Add unit tests for core behavior, integration tests for CLI/workspace flows, and TUI tests for Textual interactions. When changing curriculum, update `exercises/`, `checks/`, `solutions/`, and `info.toml`, then run relevant pytest files plus `pythonlings --root tests/fixtures/passing_curriculum verify`.

## Commit & Pull Request Guidelines

Expand Down
14 changes: 12 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
# Changelog

All notable changes to this project are documented here. Pylings follows
All notable changes to this project are documented here. Pythonlings follows
Semantic Versioning.

## [0.3.0] - 2026-06-10

### Changed

- The project is renamed from pylings to **pythonlings**. The PyPI package
(previously `python-learnings`), the CLI command (previously `pylings`),
and the Python package are all now `pythonlings`. Existing workspaces are
migrated automatically: a legacy `.pylings/` state directory is renamed to
`.pythonlings/` on the next run, preserving progress and reset snapshots.

## [0.2.0] - 2026-05-30

### Added
Expand Down Expand Up @@ -34,7 +44,7 @@ Semantic Versioning.
- 292 Python exercises across 31 topics with mirrored hidden checks.
- Bundled local Python documentation snippets generated from official docs.
- In-app documentation modal with `F5`, `Esc`, and `O` keyboard flow.
- PyPI distribution name `python-learnings`, which installs the `pylings` command.
- PyPI distribution name `pythonlings`, which installs the `pythonlings` command.
- Contributor guide, screenshots, release flow notes, and MIT license.

### Verified
Expand Down
61 changes: 61 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Pythonlings is "Rustlings for Python": a terminal TUI (Textual) where learners fix small broken exercises and checks rerun on save. Published on PyPI as `pythonlings` (formerly `python-learnings`; the unrelated `pylings` PyPI name belongs to a different project).

## Commands

```bash
pip install -e ".[dev]" # local install with pytest deps

python -m pytest -q # full suite
python -m pytest tests/unit/test_runner.py -q # one file
python -m pytest tests/unit/test_state.py::test_name -q # one test

pylings --root tests/fixtures/passing_curriculum verify # smoke-test: all solutions pass their checks

python -m build # sdist + wheel
```

Manual testing of flows: `pylings init --path ./learn-python` (create a learner workspace), `pylings` (TUI), `pylings run variables1`, `pylings dry-run variables1`, `pylings solution variables1`, `pylings hint`, `pylings list`, `pylings topics`, `pylings reset`. `--root` points any command at an arbitrary workspace (used heavily by tests against `tests/fixtures/`).

## Architecture

Two distinct trees in this repo:

1. **The application** — `pylings/` (installable package)
2. **The curriculum** — repo-root `exercises/`, `checks/`, `solutions/`, and `info.toml`

At build time, hatch `force-include` maps the curriculum into the wheel as `pylings/curriculum/` (see `pyproject.toml`). `pylings init` copies that bundled curriculum into a self-contained learner workspace; progress lives in `<workspace>/.pylings/state.json` (written atomically, with `.bak` recovery on corruption).

### Curriculum model

Each exercise is a triple that must stay in sync, plus a manifest entry:

- `exercises/<topic>/<name>.py` — the broken code the learner edits, containing the `# I AM NOT DONE` marker (defined in `core/exercise.py`)
- `checks/<topic>/<name>.py` — hidden bare `assert` statements (not pytest)
- `solutions/<name>.py` — reference answer
- `info.toml` — ordered `[[exercises]]` entries with `name`, `path`, `hint`, `docs` URL; this file is the source of truth for exercise order and topics

When changing curriculum, update all four, then run the relevant tests plus `pylings --root tests/fixtures/passing_curriculum verify`. Exercise names are topic + ordinal (`variables1`, `collections10`).

### How checks run (`core/runner.py`)

An exercise passes when a generated runner script `exec()`s the exercise source and then the check source in a shared namespace, in a fresh subprocess with a 5s timeout. The check sees the exercise's variables directly — that's why checks are bare asserts. Passing checks alone aren't enough: the learner must also remove `# I AM NOT DONE` to advance.

### Layering

- `pylings/core/` — all filesystem, manifest, state, reset, solutions, runner, and watcher logic. No UI imports.
- `pylings/screens/` and `pylings/widgets/` — Textual UI only; `pylings/app.py` wires them up; `pylings.tcss` holds styles.
- `pylings/cli.py` — argparse subcommands; entry point `pylings = "pylings.cli:main"`.

Keep UI behavior in screens/widgets and behavior logic in core — tests depend on this split (`tests/unit/` for core, `tests/integration/` for CLI/workspace flows, `tests/tui/` for Textual pilot tests, fixtures in `tests/fixtures/`).

## Conventions

- `requires-python = ">=3.9"`: guard newer-stdlib usage (e.g. `tomllib` falls back to `tomli` in `core/manifest.py`); `from __future__ import annotations` at the top of modules.
- Async tests run under `pytest-asyncio` in auto mode (configured in `pyproject.toml`).
- Tests are named `test_<behavior>.py` / `test_<expected_behavior>`.
- Commits use conventional prefixes (`feat:`, `fix:`, `docs:`, `chore:`); work flows through `feature/*` → `dev` → `main`.
- `AGENTS.md` holds the same contributor guidelines in long form.
2 changes: 1 addition & 1 deletion CNAME
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pylings.abhik.ai
pythonlings.abhik.ai
2 changes: 1 addition & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Code of Conduct

Pylings follows the Contributor Covenant Code of Conduct, version 2.1.
Pythonlings follows the Contributor Covenant Code of Conduct, version 2.1.

## Our Standards

Expand Down
12 changes: 6 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Contributing

Pylings is actively developed and **open to contributors** — beginners welcome.
The fastest way in is a [`good first issue`](https://github.com/abhiksark/pylings/issues?q=is%3Aopen+label%3A%22good+first+issue%22).
Pythonlings is actively developed and **open to contributors** — beginners welcome.
The fastest way in is a [`good first issue`](https://github.com/abhiksark/pythonlings/issues?q=is%3Aopen+label%3A%22good+first+issue%22).

## Where the work is

- **[0.3.0 roadmap](docs/roadmap/0.3.0.md)** — the current focus (wider adoption
for beginners). Each roadmap issue is written to be picked up cold: it has
context, scope, the exact files to touch, and how to verify.
- Browse open issues by label: [`good first issue`](https://github.com/abhiksark/pylings/issues?q=is%3Aopen+label%3A%22good+first+issue%22),
[`help wanted`](https://github.com/abhiksark/pylings/issues?q=is%3Aopen+label%3A%22help+wanted%22).
- Browse open issues by label: [`good first issue`](https://github.com/abhiksark/pythonlings/issues?q=is%3Aopen+label%3A%22good+first+issue%22),
[`help wanted`](https://github.com/abhiksark/pythonlings/issues?q=is%3Aopen+label%3A%22help+wanted%22).

## Claiming an issue

Expand All @@ -23,8 +23,8 @@ No need to wait for a formal assignment; claiming by comment is enough.
## Development Setup

```bash
git clone git@github.com:abhiksark/pylings.git
cd pylings
git clone git@github.com:abhiksark/pythonlings.git
cd pythonlings
pip install -e ".[dev]" # or: uv pip install -e ".[dev]"
python -m pytest -q
```
Expand Down
24 changes: 12 additions & 12 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Release Checklist

Pylings follows Semantic Versioning. Use full `MAJOR.MINOR.PATCH` versions in
Pythonlings follows Semantic Versioning. Use full `MAJOR.MINOR.PATCH` versions in
package metadata and annotated git tags such as `v0.1.0`.

## Package Name

The PyPI name `pylings` is already owned by another project. This repository's
distribution name is `python-learnings`; installing it provides the `pylings`
console command. Do not document `pip install pylings` for this project unless
The PyPI name `pythonlings` is already owned by another project. This repository's
distribution name is `pythonlings`; installing it provides the `pythonlings`
console command. Do not document `pip install pythonlings` for this project unless
the package name is transferred.

## Pre-Release Verification
Expand All @@ -16,21 +16,21 @@ Run these checks from a clean working tree before tagging:

```bash
python -m pytest -q
pylings --root tests/fixtures/passing_curriculum verify
pythonlings --root tests/fixtures/passing_curriculum verify
python -m build
python -m pip install --force-reinstall dist/python_learnings-*.whl
pylings --version
tmp=$(mktemp -d /tmp/pylings-release.XXXXXX)
pylings init --path "$tmp"
pylings --root "$tmp" list
pylings --root "$tmp" solution variables1
pylings --root "$tmp" reset variables1 --yes
pythonlings --version
tmp=$(mktemp -d /tmp/pythonlings-release.XXXXXX)
pythonlings init --path "$tmp"
pythonlings --root "$tmp" list
pythonlings --root "$tmp" solution variables1
pythonlings --root "$tmp" reset variables1 --yes
```

Expected release version for `v0.1.0`:

```text
pylings 0.1.0
pythonlings 0.1.0
```

## Tag And Publish
Expand Down
Loading
Loading