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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 18 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
name: Bug report
about: Report a reproducible problem
labels: bug
---

## What Happened?

## Steps To Reproduce

## Expected Behavior

## Environment

- OS:
- Python:
- Terminal:
- Pylings version:
11 changes: 11 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
name: Feature request
about: Suggest an improvement
labels: enhancement
---

## Problem

## Proposed Behavior

## Alternatives Considered
11 changes: 11 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## Summary

## Tests

## Screenshots

## Checklist

- [ ] Updated docs when behavior changed
- [ ] Added or updated tests
- [ ] Verified `python -m pytest -q`
5 changes: 5 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,8 @@ jobs:
- run: pip install -e ".[dev]"
- run: pytest -v
- run: pylings --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
38 changes: 38 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: publish

on:
release:
types: [published]

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Check release tag matches project version
run: |
version=$(python - <<'PY'
import tomllib
from pathlib import Path

data = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
print(data["project"]["version"])
PY
)
test "${GITHUB_REF_NAME}" = "v${version}"
- 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
- uses: pypa/gh-action-pypi-publish@release/v1
22 changes: 11 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@

## Project Structure & Module Organization

`pylings/` contains the installable application package. Core exercise loading, state, reset, and runner logic lives in `pylings/core/`; CLI entry points are in `pylings/cli.py` and `pylings/__main__.py`; Textual screens and widgets live in `pylings/screens/` and `pylings/widgets/`; `pylings/pylings.tcss` holds TUI styles.
`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.

Curriculum files are split between `exercises/<topic>/<exercise>.py` for learner-editable code and `checks/<topic>/<exercise>.py` for hidden assertions. Keep these trees mirrored. `info.toml` defines exercise order and hints. Tests are under `tests/unit/`, `tests/integration/`, and `tests/tui/`, with reusable sample curricula in `tests/fixtures/`.
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`: launch the Textual app in watch mode.
- `pylings list`, `pylings hint variables1`, `pylings run variables1`: exercise common CLI paths.
- `pylings --root tests/fixtures/passing_curriculum verify`: smoke-test curriculum verification against a known passing fixture.
- `pytest`: run the full test suite configured in `pyproject.toml`.
- `pytest tests/unit` or `pytest tests/integration/test_cli_run.py`: run focused tests while developing.
- `python -m build`: build distribution artifacts when the `build` package is available.
- `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.
- `python -m pytest -q`: run the full suite configured in `pyproject.toml`.
- `python -m build`: build source and wheel distributions.

## Coding Style & Naming Conventions

Use Python 3.11+ idioms and standard 4-space indentation. Prefer small, typed functions where practical, and keep UI-specific behavior inside `screens` or `widgets` instead of `core`. Name tests `test_<behavior>.py` and test functions `test_<expected_behavior>`. Curriculum exercise/check filenames use the topic prefix plus an ordinal, such as `variables1.py` or `collections10.py`.
Use Python 3.11+ idioms and 4-space indentation. Prefer small, typed functions where practical. Keep UI behavior in `screens` or `widgets`; keep filesystem, manifest, reset, and runner behavior in `core`. Name tests `test_<behavior>.py` and test functions `test_<expected_behavior>`. Curriculum names use topic plus ordinal, such as `variables1.py` or `collections10.py`.

## Testing Guidelines

Use pytest for all tests; async tests are supported by `pytest-asyncio` with auto mode. Add unit tests for core behavior, integration tests for CLI flows, and TUI tests for Textual interactions. When adding or changing curriculum, update both `exercises/`, `checks/`, and `info.toml`, then run the verification fixture command plus relevant pytest files.
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`.

## Commit & Pull Request Guidelines

Recent history uses conventional prefixes such as `feat:`, `fix:`, and `docs:`. Keep commits focused and imperative, for example `fix: reset hints between exercises`. Pull requests should explain the user-facing change, list tests run, link related issues when applicable, and include screenshots or terminal output for TUI/CLI behavior changes.
Recent history uses conventional prefixes such as `feat:`, `fix:`, `docs:`, `chore:`, and merge commits between `feature/*`, `dev`, and `main`. Keep commits focused and imperative, for example `fix: reset exercise originals`. Pull requests should explain the user-facing change, list tests run, link issues when applicable, and include screenshots or terminal output for TUI/CLI changes.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
All notable changes to this project are documented here. Pylings follows
Semantic Versioning.

## [0.1] - 2026-05-25
## [0.1.0] - 2026-05-25

### Added

Expand All @@ -14,10 +14,11 @@ 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.
- Contributor guide, screenshots, release flow notes, and MIT license.

### Verified

- Full test suite: `105 passed`.
- Full test suite: `125 passed`.
- Curriculum/docs audit: every exercise has a configured docs URL and a bundled
local snippet.
13 changes: 13 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Code of Conduct

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

## Our Standards

Use welcoming and inclusive language, respect different experience levels, accept constructive feedback, and focus on what is best for the community.

Unacceptable behavior includes harassment, personal attacks, sexualized language or imagery, publishing private information, or sustained disruption of project work.

## Enforcement

Report unacceptable behavior through GitHub Security Advisories. Maintainers may remove comments, close issues, block users, or take other appropriate action.
16 changes: 16 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Contributing

## Development Setup

```bash
pip install -e ".[dev]"
python -m pytest -q
```

## Curriculum Changes

Update `info.toml`, `exercises/`, `checks/`, and `solutions/` together. Exercise and check paths must mirror each other, and every exercise must have a passing reference solution.

## Pull Requests

Use focused branches named `feature/<name>` or `fix/<name>`. Include a short description, test output, and screenshots for TUI changes.
44 changes: 44 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Release Checklist

Pylings 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 package name is transferred.

## Pre-Release Verification

Run these checks from a clean working tree before tagging:

```bash
python -m pytest -q
pylings --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
```

Expected release version for `v0.1.0`:

```text
pylings 0.1.0
```

## Tag And Publish

1. Commit the release changes.
2. Create an annotated tag, for example `git tag -a v0.1.0 -m "Release v0.1.0"`.
3. Push the branch and tag.
4. Create a GitHub Release from the tag.
5. The `publish` workflow builds the package, checks that the release tag
matches `pyproject.toml`, smoke-tests the installed wheel, then publishes to
PyPI through trusted publishing.
50 changes: 34 additions & 16 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Pylings

[![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776AB)](https://www.python.org/)
[![Version](https://img.shields.io/badge/version-0.1-blue)](https://semver.org/)
[![Version](https://img.shields.io/badge/version-0.1.0-blue)](https://semver.org/)
[![SemVer](https://img.shields.io/badge/semver-2.0.0-brightgreen)](https://semver.org/)
[![Tests](https://img.shields.io/badge/tests-105%20passing-brightgreen)](#development)
[![Tests](https://img.shields.io/badge/tests-125%20passing-brightgreen)](#development)
[![License: MIT](https://img.shields.io/badge/license-MIT-yellow)](LICENSE)

Rustlings-style interactive Python exercises in a live terminal TUI.
Python learnings, Rustlings-style, in a live terminal TUI.

Pylings helps you learn Python by fixing small broken programs and watching
checks rerun as you type. It is built for beginner Python practice, coding
Expand All @@ -27,15 +27,28 @@ Python documentation snippets so learners can work without leaving the terminal.

## Install

The `pylings` command is installed from this repository. The PyPI project name
`pylings` is already used by another package, so install this project from
GitHub until a package release is published under its distribution name,
`pylings-tui`.
The `pylings` command is installed by the `python-learnings` package. The PyPI
project name `pylings` is already used by another package, so do not use
`pip install pylings` for this project.

```bash
pipx install python-learnings
```

For unreleased development builds from GitHub:

```bash
pipx install git+https://github.com/abhiksark/pylings.git
```

Create a learner workspace before starting:

```bash
pylings init --path ~/pylings-workspace
cd ~/pylings-workspace
pylings
```

For local development:

```bash
Expand All @@ -47,13 +60,16 @@ pip install -e ".[dev]"
## Quick Start

```bash
pylings # open the TUI on the first pending exercise
pylings topics # open the topic picker
pylings list # show topic progress
pylings hint variables1 # print a hint and docs link
pylings run variables1 # run one exercise check
pylings reset variables1 --yes # restore an exercise from its snapshot
pylings verify # run every exercise check
pylings init --path ./learn-python # create a self-contained workspace
cd learn-python
pylings # open the TUI on the first pending exercise
pylings topics # open the topic picker
pylings list # show topic progress
pylings hint variables1 # print a hint and docs link
pylings run variables1 # run one exercise check
pylings dry-run variables1 # run one exercise non-interactively
pylings reset variables1 --yes # restore an exercise from its original
pylings update # refresh checks/docs after upgrading pylings
```

Each exercise contains a `# I AM NOT DONE` marker. Fix the code, remove the
Expand Down Expand Up @@ -84,6 +100,7 @@ pylings/ # application package
screens/ # Textual screens
widgets/ # reusable TUI widgets
docs/ # bundled Python documentation snippets
pylings/curriculum/ # packaged copy in built wheels
exercises/<topic>/ # learner-editable exercise files
checks/<topic>/ # hidden assertions for each exercise
tests/ # unit, integration, and TUI tests
Expand Down Expand Up @@ -120,11 +137,12 @@ Pylings uses Semantic Versioning:
Branch flow is feature-first:

```text
feature/<name> -> dev -> main -> vMAJOR.MINOR
feature/<name> -> dev -> main -> vMAJOR.MINOR.PATCH
```

Feature branches are merged into `dev`. A verified `dev` branch is then merged
into `main` and tagged with an annotated release tag such as `v0.1`.
into `main` and tagged with an annotated release tag such as `v0.1.0`.
See [RELEASE.md](RELEASE.md) for the release checklist.

## Attribution

Expand Down
5 changes: 5 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Security Policy

Report security issues privately through GitHub Security Advisories. Do not open public issues for vulnerabilities.

Supported versions: the latest released `0.x` version and current `main`.
Loading
Loading