refactor: remove env.py module and update plan
- Delete env.py module (functionality moved or no longer needed) - Update docs/plan.md to reflect Milestone 2 completion - Clean up constants.py by removing unused environment-related constants
This commit is contained in:
+40
-41
@@ -1,41 +1,40 @@
|
||||
# Plan: Secret Auction Program (Day 9)
|
||||
|
||||
## Context
|
||||
|
||||
Udemy 100 Days of Code blind-auction CLI. The repository uses a Python `.gitignore`, an AGPL `LICENSE` and a git-ignored `.env` (tokens, never printed or committed). Python 3.13 or newer is required.
|
||||
|
||||
## Working method
|
||||
|
||||
Work on ONE milestone at a time. Each milestone is one branch (`milestone/NN-name`) and one pull request. When a milestone is finished, stop, verify it and review before starting the next. Milestones and issues are also tracked on the Gitea repository (via API, token from `.env`).
|
||||
|
||||
## Milestone 1 - Project scaffold and repo metadata (`milestone/01-scaffold`)
|
||||
|
||||
- [x] Create `src/secret_auction/__init__.py`, `tests/`, `docs/`
|
||||
- [x] `pyproject.toml`: `requires-python >=3.13`, src layout, no runtime deps, `dev` extra (`pytest`), pytest config, console script
|
||||
- [x] `.env.example`; `.env` and `.venv/` ignored; add `docs/doxygen/` to `.gitignore`
|
||||
- [x] `constants.py`
|
||||
- [x] `Doxyfile`
|
||||
- [x] Set repository description and topics (`python`, `udemy`, `100-days-of-code`, `blind-auction`, `beginner`) via API
|
||||
- [x] Create milestones and issues on the host (milestones M1-M4, issues #1-#12)
|
||||
- [x] Verify: create `.venv`, upgrade pip, `pip install -e ".[dev]"`
|
||||
- [x] Save plan and milestones in `docs/plan.md`
|
||||
|
||||
## Milestone 2 - Core auction logic and env loader (`milestone/02-core-logic`)
|
||||
|
||||
- [x] `auction.py` (Doxygen comments): `add_bid`, `find_winner` (uses `max(bids, key=bids.get)`, `ValueError` on empty)
|
||||
- [x] `env.py`: stdlib `.env` loader (no python-dotenv); does not override existing environment variables
|
||||
- [x] `tests/test_auction.py` (`.env` loader is for private use and intentionally not tested)
|
||||
- Verify: `pytest` passes
|
||||
|
||||
## Milestone 3 - CLI program (`milestone/03-cli`)
|
||||
|
||||
- [ ] `main.py`: prompt name and numeric bid (re-prompt on invalid), bids dict kept outside the loop, "other bidders? yes/no", clear screen with newlines between bidders, announce the winner
|
||||
- [ ] `tests/test_main.py` with monkeypatched `input`
|
||||
- Verify: `pytest`; scripted run `python -m secret_auction.main` with two bidders
|
||||
|
||||
## Milestone 4 - Documentation (`milestone/04-docs`)
|
||||
|
||||
- [ ] `README.md` from the template (Overview, Requirements, Setup incl. creating/activating `.venv` and `python -m pip install --upgrade pip`, Run, Tests, License AGPL, Links)
|
||||
- [ ] `docs/flowchart.md` (Mermaid plus link to the diagrams.net chart)
|
||||
- [ ] Generate Doxygen docs if `doxygen` is installed
|
||||
- Verify: README commands work verbatim; `.env` stays untracked
|
||||
# Plan: Secret Auction Program (Day 9)
|
||||
|
||||
## Context
|
||||
|
||||
Udemy 100 Days of Code blind-auction CLI. The repository uses a Python `.gitignore`, an AGPL `LICENSE` and a git-ignored `.env` (tokens, never printed or committed). Python 3.13 or newer is required.
|
||||
|
||||
## Working method
|
||||
|
||||
Work on ONE milestone at a time. Each milestone is one branch (`milestone/NN-name`) and one pull request. When a milestone is finished, stop, verify it and review before starting the next. Milestones and issues are also tracked on the Gitea repository (via API, token from `.env`).
|
||||
|
||||
## Milestone 1 - Project scaffold and repo metadata (`milestone/01-scaffold`)
|
||||
|
||||
- [x] Create `src/secret_auction/__init__.py`, `tests/`, `docs/`
|
||||
- [x] `pyproject.toml`: `requires-python >=3.13`, src layout, no runtime deps, `dev` extra (`pytest`), pytest config, console script
|
||||
- [x] `.env.example`; `.env` and `.venv/` ignored; add `docs/doxygen/` to `.gitignore`
|
||||
- [x] `constants.py`
|
||||
- [x] `Doxyfile`
|
||||
- [x] Set repository description and topics (`python`, `udemy`, `100-days-of-code`, `blind-auction`, `beginner`) via API
|
||||
- [x] Create milestones and issues on the host (milestones M1-M4, issues #1-#12)
|
||||
- [x] Verify: create `.venv`, upgrade pip, `pip install -e ".[dev]"`
|
||||
- [x] Save plan and milestones in `docs/plan.md`
|
||||
|
||||
## Milestone 2 - Core auction logic (`milestone/02-core-logic`)
|
||||
|
||||
- [x] `auction.py` (Doxygen comments): `add_bid`, `find_winner` (uses `max(bids, key=bids.get)`, `ValueError` on empty)
|
||||
- [x] `tests/test_auction.py`
|
||||
- Verify: `pytest` passes
|
||||
|
||||
## Milestone 3 - CLI program (`milestone/03-cli`)
|
||||
|
||||
- [ ] `main.py`: prompt name and numeric bid (re-prompt on invalid), bids dict kept outside the loop, "other bidders? yes/no", clear screen with newlines between bidders, announce the winner
|
||||
- [ ] `tests/test_main.py` with monkeypatched `input`
|
||||
- Verify: `pytest`; scripted run `python -m secret_auction.main` with two bidders
|
||||
|
||||
## Milestone 4 - Documentation (`milestone/04-docs`)
|
||||
|
||||
- [ ] `README.md` from the template (Overview, Requirements, Setup incl. creating/activating `.venv` and `python -m pip install --upgrade pip`, Run, Tests, License AGPL, Links)
|
||||
- [ ] `docs/flowchart.md` (Mermaid plus link to the diagrams.net chart)
|
||||
- [ ] Generate Doxygen docs if `doxygen` is installed
|
||||
- Verify: README commands work verbatim; `.env` stays untracked
|
||||
|
||||
@@ -1,39 +1,33 @@
|
||||
"""! @file constants.py
|
||||
@brief Constants used by the Secret Auction program.
|
||||
"""
|
||||
|
||||
## Number of blank lines printed to hide previous bidders' entries.
|
||||
CLEAR_SCREEN_LINES = 100
|
||||
|
||||
## Answers accepted as "yes" when asking for more bidders.
|
||||
YES_ANSWERS = ("yes", "y")
|
||||
|
||||
## Answers accepted as "no" when asking for more bidders.
|
||||
NO_ANSWERS = ("no", "n")
|
||||
|
||||
## Path of the file holding environment variables (tokens).
|
||||
ENV_FILE = ".env"
|
||||
|
||||
## Name of the environment variable holding the Gitea token.
|
||||
GITEA_TOKEN_ENV_VAR = "GITEA_TOKEN"
|
||||
|
||||
## Prompt asking for the bidder's name.
|
||||
PROMPT_NAME = "What is your name? "
|
||||
|
||||
## Prompt asking for the bid amount.
|
||||
PROMPT_BID = "What is your bid? $"
|
||||
|
||||
## Prompt asking whether more bidders exist.
|
||||
PROMPT_MORE_BIDDERS = "Are there any other bidders? Type 'yes' or 'no'. "
|
||||
|
||||
## Message shown when the bid is not a valid number.
|
||||
MSG_INVALID_BID = "Please enter a valid, non-negative number."
|
||||
|
||||
## Message shown when the yes/no answer is not understood.
|
||||
MSG_INVALID_ANSWER = "Please type 'yes' or 'no'."
|
||||
|
||||
## Template for the winner announcement.
|
||||
MSG_WINNER = "The winner is {name} with a bid of ${amount:.2f}."
|
||||
|
||||
## Welcome banner.
|
||||
MSG_WELCOME = "Welcome to the secret auction program."
|
||||
"""! @file constants.py
|
||||
@brief Constants used by the Secret Auction program.
|
||||
"""
|
||||
|
||||
## Number of blank lines printed to hide previous bidders' entries.
|
||||
CLEAR_SCREEN_LINES = 100
|
||||
|
||||
## Answers accepted as "yes" when asking for more bidders.
|
||||
YES_ANSWERS = ("yes", "y")
|
||||
|
||||
## Answers accepted as "no" when asking for more bidders.
|
||||
NO_ANSWERS = ("no", "n")
|
||||
|
||||
## Prompt asking for the bidder's name.
|
||||
PROMPT_NAME = "What is your name? "
|
||||
|
||||
## Prompt asking for the bid amount.
|
||||
PROMPT_BID = "What is your bid? $"
|
||||
|
||||
## Prompt asking whether more bidders exist.
|
||||
PROMPT_MORE_BIDDERS = "Are there any other bidders? Type 'yes' or 'no'. "
|
||||
|
||||
## Message shown when the bid is not a valid number.
|
||||
MSG_INVALID_BID = "Please enter a valid, non-negative number."
|
||||
|
||||
## Message shown when the yes/no answer is not understood.
|
||||
MSG_INVALID_ANSWER = "Please type 'yes' or 'no'."
|
||||
|
||||
## Template for the winner announcement.
|
||||
MSG_WINNER = "The winner is {name} with a bid of ${amount:.2f}."
|
||||
|
||||
## Welcome banner.
|
||||
MSG_WELCOME = "Welcome to the secret auction program."
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
"""! @file env.py
|
||||
@brief Minimal `.env` file loader using only the standard library.
|
||||
"""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def parse_env(text: str) -> dict[str, str]:
|
||||
"""! @brief Parse `KEY=VALUE` lines.
|
||||
@param text Contents of a `.env` file. Blank lines and `#` comments are ignored.
|
||||
@return Dictionary of parsed variables; surrounding quotes are stripped.
|
||||
"""
|
||||
values: dict[str, str] = {}
|
||||
for line in text.splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
key, value = line.split("=", 1)
|
||||
value = value.strip()
|
||||
if len(value) >= 2 and value[0] == value[-1] and value[0] in "\"'":
|
||||
value = value[1:-1]
|
||||
values[key.strip()] = value
|
||||
return values
|
||||
|
||||
|
||||
def load_env(path: str | Path) -> dict[str, str]:
|
||||
"""! @brief Load a `.env` file into `os.environ` without overriding existing variables.
|
||||
@param path Path to the `.env` file; a missing file is not an error.
|
||||
@return Dictionary of the variables read from the file.
|
||||
"""
|
||||
file = Path(path)
|
||||
if not file.is_file():
|
||||
return {}
|
||||
values = parse_env(file.read_text(encoding="utf-8"))
|
||||
for key, value in values.items():
|
||||
os.environ.setdefault(key, value)
|
||||
return values
|
||||
Reference in New Issue
Block a user