Add Pretty Table project: plan, accepted documents and code

Business Case, Stakeholder Analysis, Project Plan and milestone MIL-001
with review records RC-001 to RC-003, then the Python project: PrettyTable
Pokemon table, constants, pytest tests, pyproject.toml, Doxyfile, CI
workflow and README.

Task: MIL-001#1
Task: MIL-001#2
Task: MIL-001#3
Task: MIL-001#4
Task: MIL-001#5
Task: MIL-001#6
Task: MIL-001#7
Task: MIL-001#8
This commit is contained in:
2026-10-07 12:29:40 +08:00
parent 115b6c64bf
commit c55db0e0f2
21 changed files with 1156 additions and 1 deletions
+26
View File
@@ -0,0 +1,26 @@
# Runs on Gitea Actions (Gitea reads .gitea/workflows).
name: CI
on:
push:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- name: Install
run: |
python -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -e ".[dev]"
- name: Lint
run: .venv/bin/ruff check .
- name: Type check
run: .venv/bin/mypy
- name: Test
run: .venv/bin/python -m pytest
+179
View File
@@ -0,0 +1,179 @@
# ---> Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
# Doxygen output
docs/doxygen/
+60
View File
@@ -0,0 +1,60 @@
# AGENTS.md
This project uses the SQA and QC framework mounted at `framework/`.
For any document under `docs/` (create, edit or review) use the `artifact`
skill. For planning a project or a phase into tasks, and syncing phases and
tasks to Gitea/GitHub as Milestones and Issues, use the `project-planning`
skill. For writing or reviewing source code (Python, C, C++, C#) use the
`coding-conventions` skill. Skills are read from `.agents/skills/` (this harness and Codex CLI)
and `.claude/skills/` (standalone Claude Code CLI), both copies made by
`bash framework/scripts/install-skills.sh` — re-run it after updating the
framework.
**Never commit, push or open a PR unless asked.** The user reviews changes in
the working tree first; edit, summarise and stop. The commit/PR rules below
apply once a commit has been asked for.
## Workflow order
Business Case, Stakeholder Analysis, Project Plan, milestones, tasks synced as
issues, then code, each step reviewed before the next (an artifact is done when
its `RC-*` says `Go` and its row is `Accepted`; code is reviewed against its
`qc-programming-*` checklist before the pull request). Nothing goes under `src/`
or `tests/` unless a milestone document (`MIL-*`) is accepted, its latest review
is a `Go`, and the task is a row in it (ideally a synced issue). If those are missing, plan with the `project-planning` skill, show the
dry-run output of `bash framework/scripts/sync-project.sh`, and stop. The rule
is defined once in `framework/process/plan-first-gate.md`.
A "build X" request is planning-first: produce the plan and issues, then ask
for a go-ahead. Only the user can waive the plan, in chat, for that request.
Before planning, find the Product Owner's language (the prompt, or the
`Languages` section of `docs/artifact-registry.md`); if neither states it, ask.
Each artifact type the registry marks "Written in the PO language" exists once,
in that language, under its normal name; there is no translated twin. Metadata
keys, section headings, IDs and statuses stay in English because scripts read
them.
To enforce the gate at commit time, run
`bash framework/scripts/install-git-hooks.sh --enable-plan-gate`: a commit that
changes `src/` or `tests/` then needs a `Task: MIL-NNN#N` trailer for an
accepted, reviewed milestone.
Rules that apply to every document:
1. Get the short name from `framework/registry/artifact-catalog.md` and the
next version from `docs/artifact-registry.md`. Create files with
`bash framework/scripts/new-artifact.sh <SHORT>`.
2. Owners, reviewers and RACI use stakeholder IDs from the project's
Stakeholder Analysis, never invented role names.
3. Every QC criterion is tagged with an ISO/IEC 25010:2023 characteristic.
4. Every reviewed instance gets an `RC-*` record in `docs/sqa/reviews/`.
5. Do not edit `framework/` from this project; propose changes upstream.
6. Every PR description closes the issues its work completes, one
`Closes #N` per line (`Refs #N` for partial work); see the
`project-planning` skill.
7. Every document's `## Version History` has `Change` and `Commit` columns and
keeps the two latest rows. After committing, run
`framework/scripts/resolve-pending-commits.sh` and commit the result before
opening the PR (no amend). Never ask for or perform the merge: a reviewer
merges.
+16
View File
@@ -0,0 +1,16 @@
# Doxygen configuration. Run `doxygen Doxyfile` from the repository root.
PROJECT_NAME = "Pretty Table"
PROJECT_BRIEF = "Udemy 100 Days of Code: Pokemon type table with PrettyTable"
OUTPUT_DIRECTORY = docs/doxygen
INPUT = src README.md
USE_MDFILE_AS_MAINPAGE = README.md
FILE_PATTERNS = *.py *.md
RECURSIVE = YES
OPTIMIZE_OUTPUT_JAVA = YES
EXTRACT_ALL = YES
EXTRACT_PRIVATE = NO
GENERATE_HTML = YES
GENERATE_LATEX = NO
QUIET = YES
WARN_IF_UNDOCUMENTED = YES
WARN_AS_ERROR = NO
+145 -1
View File
@@ -1,2 +1,146 @@
# 016-pretty_table
# Pretty Table
A table of Pokémon and their types, printed with the PrettyTable package from PyPI.
It is an assignment of Udemy's *100 Days of Code: The Complete Python Pro Bootcamp*
about adding Python packages. The functions use the assignment's style: `create_table`
builds the `PrettyTable` and `main` prints it. PrettyTable is the only runtime dependency.
## Requirements
- Python 3.13 or newer.
- `venv` and `pip`, which come with Python (on Debian they are separate packages).
- Git, to clone the repository.
- Optional: [Doxygen](https://www.doxygen.nl/) to build the source documentation.
`prettytable` is installed from PyPI with the project. `pytest`, `ruff` and `mypy`
are installed only for development, through the `dev` extra.
## Set up
Clone the repository and change into it:
```bash
git clone https://git.tirsystem.com/Tirsvad-Udemy-100_days_of_code/016-pretty_table.git
cd 016-pretty_table
```
Then create a local virtual environment named `.venv`, upgrade `pip` and install
the project in it.
### Windows powershell
```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
If PowerShell refuses to run the activation script, allow it for this window only
with `Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass`.
### Linux debian
```bash
sudo apt install python3 python3-venv python3-pip git
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
Debian 13 (trixie) ships Python 3.13. On an older release, install Python 3.13
first (for example with `pyenv`) and use it to create the `.venv`.
### MacOS
```bash
brew install python@3.13 git
python3.13 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
To leave the virtual environment, run `deactivate`.
## Run
With the virtual environment active:
```bash
python -m pretty_table
```
The installed command does the same:
```bash
pretty-table
```
Output:
```text
+--------------+----------+
| Pokemon Name | Type |
+--------------+----------+
| Pikachu | Electric |
| Squirtle | Water |
| Charmander | Fire |
+--------------+----------+
```
## Run the tests
With the virtual environment active:
```bash
python -m pytest
```
The linter and the strict type check that the project also uses:
```bash
ruff check .
mypy
```
## Continuous integration
The workflow in `.gitea/workflows/ci.yml` runs on Gitea Actions on every push and
pull request. It creates a virtual environment on Python 3.13, upgrades `pip`,
installs the project with the `dev` extra and runs `ruff check .`, `mypy` and
`python -m pytest`. GitHub does not read the `.gitea` folder, so a GitHub mirror
does not run it.
## Build the source documentation
The source uses Doxygen comments and the `Doxyfile` in the repository root. Install
Doxygen (`winget install DimitriVanHeesch.Doxygen` on Windows,
`sudo apt install doxygen` on Debian, `brew install doxygen` on MacOS), then run:
```bash
doxygen Doxyfile
```
The HTML documentation is written to `docs/doxygen/html/`; open `index.html` in a
browser. The output folder is ignored by git.
## Project layout
```text
.
├── src/pretty_table/ The program
│ ├── constants.py Column titles and the Pokémon rows
│ ├── main.py create_table and main
│ └── __main__.py Entry point for python -m pretty_table
├── tests/ pytest tests
├── docs/ Project documents (business case, plan, reviews)
├── .gitea/workflows/ Continuous integration workflow
├── Doxyfile Doxygen configuration
└── pyproject.toml Project configuration
```
## License
GNU Affero General Public License v3.0; see [LICENSE](LICENSE).
+58
View File
@@ -0,0 +1,58 @@
# Artifact Registry
This project's artifact state. Types, short names and `CrossReference
Candidates` come from the framework catalog
(`framework/registry/artifact-catalog.md`); this file only records where
each document lives in *this* project and the next version to use.
Delete rows for types you don't use. Add a row the first time you create a
document of a type. `Primary File` may contain a glob (e.g.
`docs/uc-*/uc.md`); `framework/scripts/find-crossreferences.sh` reads it.
| Short Name | Artifact Type | Primary File | Next Available Version |
| --- | --- | --- | --- |
| BC | Business Case | docs/business-case.md | 002 |
| SA | Stakeholder Analysis | docs/stakeholder-analysis.md | 002 |
| PP | Project Plan | docs/project-plan.md | 002 |
| MIL | Milestone / Gateway | docs/milestones/*.md | 002 |
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 004 |
## Languages
Set the PO language when the project starts; `project-planning` asks for it
if it is missing. An artifact of a type marked "Written in the PO language"
exists once, in that language, under its normal name (`business-case.md`); the
`artifact` skill ("One file per artifact") has the rule.
| Setting | Value |
| --- | --- |
| PO language | en |
| PO domain | it |
| High-level register | IT Executive English |
| Technical register | IT Professional English |
Every artifact of a type marked "Yes" below states its language and domain in
its `Language` and `Domain` Metadata rows; `new-artifact.sh` fills them from
`PO language` and `PO domain`. `Language` is a BCP 47 code (`da`, `en`).
`Domain` is a value from this list; add a row to introduce a domain, so a
reviewer can see at once which professional vocabulary a document uses.
| Domain | Meaning |
| --- | --- |
| it | Software and IT |
| medical | Healthcare and medical devices |
| construction | Construction and civil engineering |
| Artifact types | Register | Written in the PO language |
| --- | --- | --- |
| BC, KPI, PP, MIL | IT Executive English | Yes |
| SA, BMC, BPMN, UCD, US, UC, SSD, DM, RA, GOV, DICT | IT Professional English | Yes |
| OC, SD, DCD, ERD, ADR, TM, RC, QC, source code | IT Professional English | No |
## Notes
- "Next Available Version" is the zero-padded (3-digit) version to use the
*next* time a new document of that type is created. Increment it only when
a brand-new document is created, not when an existing document's
`## Version History` gets a row.
- `ADR` uses 4 digits (`0001`); `RC` is sequential across all artifact types.
+121
View File
@@ -0,0 +1,121 @@
# Business Case
## Metadata
| Key | Value |
| --- | --- |
| ID | BC-001 |
| CrossReference | [SA-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | pending |
---
## Executive Summary
This project delivers the Udemy "100 Days of Code" lesson on adding Python packages from PyPI. It is a small, runnable Python program that builds a table of Pokémon names and types with the PrettyTable package, packaged as a clean, tested and documented repository that other course participants and GitHub visitors can read and run. The effort is deliberately small, and the single runtime dependency is the one the assignment teaches.
## Methodological and Standards Foundation
The work follows the SQA and QC framework mounted at `framework/` (Business Case, Stakeholder Analysis, Project Plan, milestones, tasks as issues, then code). Quality characteristics follow ISO/IEC 25010:2023. Code follows the framework's `coding-conventions` skill for Python and is reviewed against its `qc-programming-*` checklist.
## Problem Statement
The assignment solution exists only as lesson material. Without a repository there is nothing to share, compare or reuse, and the install-and-import workflow for PyPI packages is not documented in a reproducible form (virtual environment, dependency declaration, tests).
## Business Opportunity
A clear, runnable reference solution lets other course participants compare their code, and gives GitHub viewers a tidy example of a small Python project with tests, documentation and project configuration.
## Objectives
1. O1: Provide a Python program that prints the Pokémon type table with PrettyTable, using the assignment's function names.
2. O2: Document how to create and use a local `.venv`, upgrade pip, run the program and run the tests.
3. O3: Provide pytest tests, a `pyproject.toml`, constants in `constants.py`, Doxygen comments and a Doxyfile.
4. O4: Publish the repository with a description and topics.
## Scope
### In Scope
- Python 3.13 or newer source under `src/`, tests under `tests/`, documents under `docs/`.
- `pyproject.toml`, Python `.gitignore`, `Doxyfile`, and a README built from the template.
- Repository description and topics on the git host.
### Out of Scope
- Features beyond the lesson (the PrettyTable styling exercises of later lessons).
- Publishing the package to PyPI.
- Using, importing or testing the `.env` file; it is personal and only used to reach the git host.
## Expected Benefits
### Tangible Benefits
- A runnable, tested repository that others can clone and run in minutes.
- A reproducible environment recipe for Windows, Linux and macOS.
### Intangible Benefits
- A consistent portfolio of course assignments.
- Practice with packages, PyPI and project hygiene.
## Strategic Alignment
The project supports the participant's goal of completing the bootcamp with consistent, reviewable work, and the community goal of sharing readable solutions.
## Success Criteria
| # | Criterion | Target | Measure |
| --- | --- | --- | --- |
| 1 | Program prints the Pokémon table | Exit code 0 and the expected table text | pytest test of the rendered table |
| 2 | Tests pass | 100% of tests pass in a fresh `.venv` | `python -m pytest` |
| 3 | README steps work | A new reader runs the program using only the README | Manual walkthrough on one OS |
| 4 | Repository metadata | Description and at least 3 topics set | Inspect the repository page |
## Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| PrettyTable API changes | Output or tests break | Declare a minimum version in `pyproject.toml` and test the rendered output |
| Token leaks into the repository | Credential exposure | `.env` is git-ignored and never imported or tested |
| Over-engineering a tiny assignment | Wasted effort | Keep one runtime dependency and a minimal layout |
## Assumptions
- Python 3.13 or newer is installed by the reader.
- PyPI is reachable when installing PrettyTable.
- The git host accepts a description and topics through its API.
## Constraints
- Python 3.13 or newer, `venv` for environments, pytest for tests.
- Constants live in `constants.py`; source uses Doxygen comments.
- Configuration lives in `pyproject.toml`.
- Only the user performs commits, pushes and merges.
## Cost–Benefit Assessment
| Costs | Benefits |
| --- | --- |
| A few hours of the participant's time; no licence or hosting cost | A shareable, tested reference solution and a reusable project template |
## Stakeholders
| Stakeholder ID (SA) | Interest in this project |
| --- | --- |
| S01 | Owns the work and wants an accepted, reviewed result |
| S02 | Wants readable, runnable code with the assignment's function names |
| S03 | Wants a clear description, topics and README, with no runtime dependencies beyond the lesson's |
## Recommendation
Proceed — the scope is small, the cost is minimal and the result is directly reusable.
---
[SA-001]: ./stakeholder-analysis.md
@@ -0,0 +1,81 @@
# G1 Project delivery
## Metadata
| Key | Value |
| --- | --- |
| ID | MIL-001 |
| CrossReference | [BC-001], [SA-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | pending |
---
## Purpose
Decide whether the Pretty Table project is complete enough to publish: runnable, tested, documented and described on the git host.
## Deliverable
A Python 3.13+ project with `src/`, `tests/`, `docs/`, `pyproject.toml`, `constants.py`, `Doxyfile`, a Python `.gitignore` and a README built from the template, plus a repository description and topics.
## Go / No-Go Criteria
| # | Criterion (objectively checkable) | Go | No-Go |
| --- | --- | --- | --- |
| 1 | `python -m pytest` passes in a fresh `.venv` | All tests pass | Any failure |
| 2 | The program prints the Pokémon type table | Output matches the tested table | Output differs or the run fails |
| 3 | The README follows the template and its steps work | Each section is filled and the steps run | A section is missing or a step fails |
| 4 | Runtime dependencies | Only PrettyTable | Any other runtime dependency |
| 5 | Repository description and at least 3 topics are set | Visible on the repository page | Missing |
| 6 | Code review record against `qc-programming-python` | `RC-*` says Go | No review or No-Go |
## Dependencies
| Depends on | Reason |
| --- | --- |
| [BC-001] | Scope and success criteria |
| [SA-001] | Stakeholders S01, S02, S03 |
## Traceability
| Business Case objective / KPI / user story | Reference |
| --- | --- |
| O1 Pokémon table program | Tasks 3, 4 |
| O2 Documented run, venv and tests | Tasks 1, 6 |
| O3 Tests, pyproject, constants, Doxygen | Tasks 1, 2, 4, 5 |
| O4 Repository published with description and topics | Task 8 |
## Ownership
| Role | Stakeholder ID (SA) |
| --- | --- |
| Owner | S01 |
| Approving reviewer | S01 |
## Target Date
2026-10-14 — one week from the start, consistent with the Business Case's small scope.
## Tasks
| # | Task | Summary | Needs its own Use Case/User Story? | Reference |
| --- | --- | --- | --- | --- |
| 1 | Configure project files | Create `pyproject.toml` (Python 3.13 or newer, PrettyTable runtime dependency, pytest as a dev dependency) and a Python `.gitignore` that also ignores `.env` and `.venv`. Supports O2 and O3. | No | |
| 2 | Add constants module | Create `src/constants.py` holding the Pokémon names, types and column titles so no literals are scattered in the code. Supports O3. | No | |
| 3 | Implement the Pokémon table | Create the program in `src/` that builds and prints the PrettyTable of Pokémon and their types (for example Pikachu Electric, Squirtle Water), with the assignment's function names and Doxygen comments. Supports O1. | No | |
| 4 | Add pytest tests | Create tests in `tests/` that check the rendered table and the program's output, run with `python -m pytest`. Supports O1 and O3. | No | |
| 5 | Add Doxyfile | Create a `Doxyfile` that builds the source documentation from `src/`. Supports O3. | No | |
| 6 | Write the README | Write `README.md` from the template: requirements, local `.venv` and `python -m pip install --upgrade pip` for Windows PowerShell, Linux Debian and macOS, running, testing, CI, Doxygen and layout. Supports O2. | No | |
| 7 | Describe continuous integration | Add a CI workflow that installs the project and runs pytest, and explain it in the README CI section. Supports O2. | No | |
| 8 | Set repository description and topics | Use the token from the personal `.env` (never committed, imported or tested) to set the description and topics on the git host. Supports O4. | No | |
| 9 | Review code against the Python checklist | Review the source and tests against `qc-programming-python` and record an `RC-*` before the pull request. Supports Go criterion 6. | No | |
---
[BC-001]: ../business-case.md
[SA-001]: ../stakeholder-analysis.md
+72
View File
@@ -0,0 +1,72 @@
# Project Plan
## Metadata
| Key | Value |
| --- | --- |
| ID | PP-001 |
| CrossReference | [BC-001], [SA-001], [MIL-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | pending |
---
## Purpose
Schedules the single delivery phase of the Pretty Table assignment so that the repository can be published within one week, as the Business Case's small-scope constraint implies.
## Planning Assumptions
- Week 1 starts 2026-10-07; the plan ends by 2026-10-14.
- One phase of one week; the Product Owner (S01) is the only decision maker, per [SA-001].
## Gateway Schedule
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
| --- | --- | --- | --- | --- | --- | --- | --- |
| G1 Project delivery | [MIL-001] | 2026-10-07 to 2026-10-14 | 2026-10-14 | S01 | none | Tested, documented Python project and published repository metadata | [Milestone 52] |
```plantuml
@startgantt
Project starts 2026-10-07
[G1 Project delivery] starts 2026-10-07 and ends 2026-10-14
[G1 Go/No-Go] happens 2026-10-14
@endgantt
```
## Scope Coverage
| Business Case scope item | Gateway |
| --- | --- |
| Source under `src/`, tests under `tests/`, documents under `docs/` | G1 |
| `pyproject.toml`, `.gitignore`, `Doxyfile`, README | G1 |
| Repository description and topics | G1 |
## Dependencies
```
G1 Project delivery
```
A No-Go on G1 moves the decision date until the failed criteria are fixed.
## Plan Risks
| Risk | Impact | Mitigation |
| --- | --- | --- |
| Git host API is unavailable for description and topics | Task cannot be completed | Set them by hand on the repository page |
## Open Issues
- The assignment's exact function names are not given in the task text; the code uses `create_table` and `main`, to be adjusted if S01 names others.
---
[BC-001]: ./business-case.md
[SA-001]: ./stakeholder-analysis.md
[MIL-001]: ./milestones/mil-001-pretty-table-project.md
[Milestone 52]: https://git.tirsystem.com/Tirsvad-Udemy-100_days_of_code/016-pretty_table/milestone/52
+60
View File
@@ -0,0 +1,60 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-001 |
| CrossReference | [BC-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [BC-001]
- Checklist used: none available; the `BC` reference in the `artifact` skill (`references/BC.md`)
- Scope: full review. The QC checklist named in the catalog is not present: `framework/qc/` is empty in this clone. The criteria below are the required sections and rules of the type's `references/` file.
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Executive Summary | Pass | Present and filled in the instance |
| 2 | Methodological and Standards Foundation | Pass | Present and filled in the instance |
| 3 | Problem Statement | Pass | Present and filled in the instance |
| 4 | Business Opportunity | Pass | Present and filled in the instance |
| 5 | Objectives | Pass | Present and filled in the instance |
| 6 | Scope (In/Out) | Pass | Present and filled in the instance |
| 7 | Expected Benefits (Tangible/Intangible) | Pass | Present and filled in the instance |
| 8 | Strategic Alignment | Pass | Present and filled in the instance |
| 9 | Success Criteria (measurable) | Pass | Present and filled in the instance |
| 10 | Risks (each with mitigation) | Pass | Present and filled in the instance |
| 11 | Assumptions | Pass | Present and filled in the instance |
| 12 | Constraints | Pass | Present and filled in the instance |
| 13 | Cost-Benefit Assessment | Pass | Present and filled in the instance |
| 14 | Stakeholders cite SA IDs, no re-description | Pass | Present and filled in the instance |
| 15 | Recommendation (single proceed statement) | Pass | Present and filled in the instance |
## Language and Domain Results
QC-LANG-001 is not available in this clone. Spot check: the document is in English, in the IT domain, with the `Language` and `Domain` rows set, and uses the PO's terms.
## Overall Verdict
Go — every required section is present and consistent with the Business Case and Stakeholder Analysis. The author and the reviewer are both S01, the only stakeholder with the authority; the PO explicitly instructed acceptance in chat on 2026-10-07.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Re-review against the QC checklist once `framework/qc/` is populated | S01 | when the framework provides it |
---
[BC-001]: ../../business-case.md
@@ -0,0 +1,53 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-002 |
| CrossReference | [SA-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [SA-001]
- Checklist used: none available; the `SA` reference in the `artifact` skill (`references/SA.md`)
- Scope: full review. The QC checklist named in the catalog is not present: `framework/qc/` is empty in this clone. The criteria below are the required sections and rules of the type's `references/` file.
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Purpose | Pass | Present and filled in the instance |
| 2 | Stakeholder Summary Table fully filled | Pass | Present and filled in the instance |
| 3 | Classification Rationale consistent with the table | Pass | Present and filled in the instance |
| 4 | Concerns mapped to FURPS+ | Pass | Present and filled in the instance |
| 5 | Communication Requirements | Pass | Present and filled in the instance |
| 6 | Every conflict has a mitigation | Pass | Present and filled in the instance |
| 7 | Traceability cites BC-001 objectives | Pass | Present and filled in the instance |
| 8 | Sign-Off | Pass | Present and filled in the instance |
## Language and Domain Results
QC-LANG-001 is not available in this clone. Spot check: the document is in English, in the IT domain, with the `Language` and `Domain` rows set, and uses the PO's terms.
## Overall Verdict
Go — every required section is present and consistent with the Business Case and Stakeholder Analysis. The author and the reviewer are both S01, the only stakeholder with the authority; the PO explicitly instructed acceptance in chat on 2026-10-07.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Re-review against the QC checklist once `framework/qc/` is populated | S01 | when the framework provides it |
---
[SA-001]: ../../stakeholder-analysis.md
+53
View File
@@ -0,0 +1,53 @@
# SQA Review Record
## Metadata
| Key | Value |
| --- | --- |
| ID | RC-003 |
| CrossReference | [MIL-001] |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Proposed | Jens Tirsvad Nielsen | S01 | Initial version | pending |
---
## Artifact Under Review
- Instance reviewed: [MIL-001]
- Checklist used: none available; the `MIL` reference in the `artifact` skill (`references/MIL.md`)
- Scope: full review. The QC checklist named in the catalog is not present: `framework/qc/` is empty in this clone. The criteria below are the required sections and rules of the type's `references/` file.
- Language and domain: en / it
- Language reviewer: none (S01 reads English and knows the domain)
## Checklist Results
| # | Criterion | Status | Evidence/Notes |
| --- | --- | --- | --- |
| 1 | Purpose | Pass | Present and filled in the instance |
| 2 | Deliverable is concrete | Pass | Present and filled in the instance |
| 3 | Go/No-Go criteria objectively checkable | Pass | Present and filled in the instance |
| 4 | Dependencies | Pass | Present and filled in the instance |
| 5 | Traceability to BC objectives | Pass | Present and filled in the instance |
| 6 | Ownership uses SA stakeholder IDs | Pass | Present and filled in the instance |
| 7 | Target Date consistent with BC | Pass | Present and filled in the instance |
| 8 | Tasks table: Task/Summary/Needs-UC/Reference, plain tasks marked No | Pass | Present and filled in the instance |
## Language and Domain Results
QC-LANG-001 is not available in this clone. Spot check: the document is in English, in the IT domain, with the `Language` and `Domain` rows set, and uses the PO's terms.
## Overall Verdict
Go — every required section is present and consistent with the Business Case and Stakeholder Analysis. The author and the reviewer are both S01, the only stakeholder with the authority; the PO explicitly instructed acceptance in chat on 2026-10-07.
## Action Items
| Action | Owner | Due |
| --- | --- | --- |
| Re-review against the QC checklist once `framework/qc/` is populated | S01 | when the framework provides it |
---
[MIL-001]: ../../milestones/mil-001-pretty-table-project.md
+74
View File
@@ -0,0 +1,74 @@
# Stakeholder Analysis
## Metadata
| Key | Value |
| --- | --- |
| ID | SA-001 |
| CrossReference | [BC-001] |
| Language | en |
| Domain | it |
## Version History
| Date | Status | Author | Reviewer | Change | Commit |
| --- | --- | --- | --- | --- | --- |
| 2026-10-07 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | pending |
---
## Purpose
Identify who is affected by the project and what each needs, using a power/interest grid, so the plan and the README serve them.
## Stakeholder Summary Table
| ID | Name | Role/Title | Organization | Power Level | Interest Level | Quadrant | Primary Concern (Business Language) |
| --- | --- | --- | --- | --- | --- | --- | --- |
| S01 | Jens Tirsvad Nielsen | Course participant: Product Owner, developer and reviewer | Tirsvad | HIGH | HIGH | Manage Closely | A finished, reviewed assignment that follows the framework |
| S02 | Udemy coursists | Fellow course participants | Udemy community | LOW | HIGH | Keep Informed | Readable, runnable code with the assignment's function names, and README run instructions |
| S03 | GitHub viewers | Repository browsers | Public | LOW | LOW | Monitor | A clear repository description, topics and README, and no runtime dependencies beyond the lesson's |
## Power/Interest Classification Rationale
- **Manage Closely:** S01 decides scope, writes and reviews everything.
- **Keep Informed:** S02 cannot change the project but depends on its code and README.
- **Monitor:** S03 browses for ideas and has no say; the description, topics and README are enough.
## Primary Concerns and FURPS+ Mapping
| ID | Concern | FURPS+ attribute |
| --- | --- | --- |
| S01 | Work follows the plan-first process and is verified by tests | Functionality, Supportability |
| S02 | Code is readable and runs with the documented steps | Usability, Functionality |
| S03 | Repository is self-explanatory and light | Usability, Implementation (no extra runtime dependencies) |
## Communication Requirements
| ID | Channel | Frequency | Deliverable | Phase / Milestone |
| --- | --- | --- | --- | --- |
| S01 | Chat review of the working tree | Per phase | Reviewed documents and code | All |
| S02 | README | Once, on publication | Run and test instructions | Delivery |
| S03 | Repository page | Once, on publication | Description, topics, README | Delivery |
## Conflicting Interests and Mitigations
| Conflict | Stakeholders | Mitigation |
| --- | --- | --- |
| S02 wants the assignment's exact function names; S03 wants a tidy, idiomatic project | S02, S03 | Keep the assignment's names for public functions and apply the conventions everywhere else |
## Traceability Analysis
### Business Goal Alignment
| Stakeholder | Concern | Business Case objective |
| --- | --- | --- |
| S01 | Reviewed, framework-compliant work | [BC-001] O3, O4 |
| S02 | Runnable code and instructions | [BC-001] O1, O2 |
| S03 | Clear repository presentation | [BC-001] O4 |
## Sign-Off
Accepted by S01 (RC-002).
---
[BC-001]: ./business-case.md
+39
View File
@@ -0,0 +1,39 @@
[build-system]
requires = ["setuptools>=68"]
build-backend = "setuptools.build_meta"
[project]
name = "pretty-table-pokemon"
version = "0.1.0"
description = "Pokemon type table with PrettyTable from Udemy's 100 Days of Code: The Complete Python Pro Bootcamp."
readme = "README.md"
requires-python = ">=3.13"
license = { file = "LICENSE" }
authors = [{ name = "Jens Tirsvad Nielsen" }]
# PrettyTable is the package the lesson teaches; it is the only runtime dependency.
dependencies = ["prettytable>=3.10"]
[project.optional-dependencies]
dev = ["pytest>=8", "ruff>=0.6", "mypy>=1.11"]
[project.scripts]
pretty-table = "pretty_table.main:main"
[tool.setuptools.packages.find]
where = ["src"]
[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
[tool.ruff]
line-length = 88
target-version = "py313"
[tool.ruff.lint]
select = ["E", "F", "I", "N", "UP", "B"]
[tool.mypy]
strict = true
python_version = "3.13"
files = ["src", "tests"]
+4
View File
@@ -0,0 +1,4 @@
"""!
@file __init__.py
@brief Pokemon type table built with PrettyTable.
"""
+8
View File
@@ -0,0 +1,8 @@
"""!
@file __main__.py
@brief Entry point for `python -m pretty_table`.
"""
from pretty_table.main import main
main()
+20
View File
@@ -0,0 +1,20 @@
"""!
@file constants.py
@brief Constants of the Pokemon table: column titles and the rows shown.
"""
## Title of the column holding the Pokemon name.
COLUMN_NAME: str = "Pokemon Name"
## Title of the column holding the Pokemon type.
COLUMN_TYPE: str = "Type"
## Column titles in display order.
COLUMN_TITLES: tuple[str, str] = (COLUMN_NAME, COLUMN_TYPE)
## Pokemon names in display order, paired with their type.
POKEMON: tuple[tuple[str, str], ...] = (
("Pikachu", "Electric"),
("Squirtle", "Water"),
("Charmander", "Fire"),
)
+30
View File
@@ -0,0 +1,30 @@
"""!
@file main.py
@brief Builds and prints the Pokemon type table with PrettyTable.
"""
from prettytable import PrettyTable
from pretty_table.constants import COLUMN_NAME, COLUMN_TYPE, POKEMON
def create_table() -> PrettyTable:
"""!
@brief Build the table of Pokemon names and their types.
@return A PrettyTable with one row per Pokemon in POKEMON.
"""
table = PrettyTable()
table.add_column(COLUMN_NAME, [name for name, _ in POKEMON])
table.add_column(COLUMN_TYPE, [type_ for _, type_ in POKEMON])
return table
def main() -> None:
"""!
@brief Print the Pokemon type table to standard output.
"""
print(create_table())
if __name__ == "__main__":
main()
View File
+17
View File
@@ -0,0 +1,17 @@
"""Tests for the constants."""
from pretty_table import constants
def test_column_titles_match_the_column_constants() -> None:
assert constants.COLUMN_TITLES == (constants.COLUMN_NAME, constants.COLUMN_TYPE)
def test_pokemon_includes_the_lesson_examples() -> None:
assert ("Pikachu", "Electric") in constants.POKEMON
assert ("Squirtle", "Water") in constants.POKEMON
def test_pokemon_names_are_unique() -> None:
names = [name for name, _ in constants.POKEMON]
assert len(names) == len(set(names))
+40
View File
@@ -0,0 +1,40 @@
"""Tests for the Pokemon table."""
import pytest
from prettytable import PrettyTable
from pretty_table.constants import COLUMN_TITLES, POKEMON
from pretty_table.main import create_table, main
EXPECTED_TABLE = """\
+--------------+----------+
| Pokemon Name | Type |
+--------------+----------+
| Pikachu | Electric |
| Squirtle | Water |
| Charmander | Fire |
+--------------+----------+
"""
def test_create_table_returns_prettytable() -> None:
assert isinstance(create_table(), PrettyTable)
def test_create_table_has_the_column_titles() -> None:
assert tuple(create_table().field_names) == COLUMN_TITLES
def test_create_table_has_one_row_per_pokemon() -> None:
table = create_table()
assert len(table.rows) == len(POKEMON)
assert [tuple(row) for row in table.rows] == list(POKEMON)
def test_create_table_renders_the_expected_text() -> None:
assert create_table().get_string() == EXPECTED_TABLE.rstrip("\n")
def test_main_prints_the_table(capsys: pytest.CaptureFixture[str]) -> None:
main()
assert capsys.readouterr().out == EXPECTED_TABLE