MIL-005: documentation, wiki and release check #36
No files matched your search
@@ -25,6 +25,8 @@ The repository holds one small module per lecture step.
|
|||||||
|
|
||||||
Doxygen comments in the source describe every public name; `Doxyfile` builds them into `docs/doxygen/`.
|
Doxygen comments in the source describe every public name; `Doxyfile` builds them into `docs/doxygen/`.
|
||||||
|
|
||||||
|
The wiki (English, Danish and Bahasa Malaysia) explains what each lecture taught; its sources are in `docs/wiki/` and are published to the repository wiki when they are merged to `main`.
|
||||||
|
|
||||||
### Lecture steps
|
### Lecture steps
|
||||||
|
|
||||||
Each lecture has its own screenshot in `docs/images/` (made by `docs/images/capture.py` with a headless browser, so no window opens on your desktop) and a wiki page that explains what the lecture taught.
|
Each lecture has its own screenshot in `docs/images/` (made by `docs/images/capture.py` with a headless browser, so no window opens on your desktop) and a wiki page that explains what the lecture taught.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ document of a type. `Primary File` may contain a glob (e.g.
|
|||||||
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0002 |
|
| ADR | Architecture Decision Record | docs/adr/adr-NNNN-*.md | 0002 |
|
||||||
| DICT | Domain Dictionary | docs/dictionary.md | 002 |
|
| DICT | Domain Dictionary | docs/dictionary.md | 002 |
|
||||||
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
|
| TM | Traceability Matrix | docs/sqa/traceability-matrix.md | 002 |
|
||||||
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 019 |
|
| RC | SQA Review Record | docs/sqa/reviews/rc-*.md | 022 |
|
||||||
|
|
||||||
## Languages
|
## Languages
|
||||||
|
|
||||||
|
|||||||
+48
-13
@@ -50,7 +50,9 @@ body{margin:0;background:#f3f3f3;font-family:Segoe UI,Arial,sans-serif}
|
|||||||
|
|
||||||
def find_browser() -> str:
|
def find_browser() -> str:
|
||||||
for candidate in BROWSERS:
|
for candidate in BROWSERS:
|
||||||
found = shutil.which(candidate) or (candidate if os.path.exists(candidate) else None)
|
found = shutil.which(candidate) or (
|
||||||
|
candidate if os.path.exists(candidate) else None
|
||||||
|
)
|
||||||
if found:
|
if found:
|
||||||
return found
|
return found
|
||||||
raise SystemExit("No Edge or Chrome found for headless screenshots")
|
raise SystemExit("No Edge or Chrome found for headless screenshots")
|
||||||
@@ -81,20 +83,28 @@ def shot(page: Path, png: Path, width: int, height: int) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def run(cmd: list[str], cwd: Path, timeout: int = 30) -> str:
|
def run(cmd: list[str], cwd: Path, timeout: int = 30) -> str:
|
||||||
done = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, timeout=timeout) # nosemgrep
|
done = subprocess.run( # nosemgrep
|
||||||
|
cmd, cwd=cwd, capture_output=True, text=True, timeout=timeout
|
||||||
|
)
|
||||||
return (done.stdout + done.stderr).rstrip("\n")
|
return (done.stdout + done.stderr).rstrip("\n")
|
||||||
|
|
||||||
|
|
||||||
def terminal_page(title: str, entries: list[tuple[str, str]], png: Path, height: int) -> None:
|
def terminal_page(
|
||||||
|
title: str, entries: list[tuple[str, str]], png: Path, height: int
|
||||||
|
) -> None:
|
||||||
"""Render (command, output) pairs as a terminal and take the screenshot."""
|
"""Render (command, output) pairs as a terminal and take the screenshot."""
|
||||||
lines = []
|
lines = []
|
||||||
for command, output in entries:
|
for command, output in entries:
|
||||||
lines.append(f'<span class="p">$</span> <span class="c">{html.escape(command)}</span>')
|
lines.append(
|
||||||
|
f'<span class="p">$</span> <span class="c">{html.escape(command)}</span>'
|
||||||
|
)
|
||||||
if output:
|
if output:
|
||||||
lines.append(html.escape(output))
|
lines.append(html.escape(output))
|
||||||
page = (
|
page = (
|
||||||
f"<!doctype html><meta charset='utf-8'><style>{TERMINAL_CSS}</style>"
|
f"<!doctype html><meta charset='utf-8'><style>{TERMINAL_CSS}</style>"
|
||||||
f"<div class='bar'>{html.escape(title)}</div><pre>" + "\n".join(lines) + "</pre>"
|
f"<div class='bar'>{html.escape(title)}</div><pre>"
|
||||||
|
+ "\n".join(lines)
|
||||||
|
+ "</pre>"
|
||||||
)
|
)
|
||||||
SOURCES.mkdir(exist_ok=True)
|
SOURCES.mkdir(exist_ok=True)
|
||||||
src = SOURCES / (png.stem + ".html")
|
src = SOURCES / (png.stem + ".html")
|
||||||
@@ -105,7 +115,9 @@ def terminal_page(title: str, entries: list[tuple[str, str]], png: Path, height:
|
|||||||
def stop(proc: subprocess.Popen) -> None:
|
def stop(proc: subprocess.Popen) -> None:
|
||||||
"""Stop a server and its reloader child."""
|
"""Stop a server and its reloader child."""
|
||||||
if os.name == "nt":
|
if os.name == "nt":
|
||||||
subprocess.run(["taskkill", "/F", "/T", "/PID", str(proc.pid)], capture_output=True) # nosemgrep
|
subprocess.run( # nosemgrep
|
||||||
|
["taskkill", "/F", "/T", "/PID", str(proc.pid)], capture_output=True
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
proc.kill()
|
proc.kill()
|
||||||
proc.wait(timeout=10)
|
proc.wait(timeout=10)
|
||||||
@@ -140,7 +152,11 @@ def start_server() -> subprocess.Popen:
|
|||||||
def step2() -> None:
|
def step2() -> None:
|
||||||
proc = start_server()
|
proc = start_server()
|
||||||
try:
|
try:
|
||||||
body = urllib.request.urlopen(f"http://127.0.0.1:{PORT}/", timeout=3).read().decode()
|
body = (
|
||||||
|
urllib.request.urlopen(f"http://127.0.0.1:{PORT}/", timeout=3)
|
||||||
|
.read()
|
||||||
|
.decode()
|
||||||
|
)
|
||||||
page = (
|
page = (
|
||||||
f"<!doctype html><meta charset='utf-8'><style>{BROWSER_CSS}</style>"
|
f"<!doctype html><meta charset='utf-8'><style>{BROWSER_CSS}</style>"
|
||||||
f"<div class='tab'>127.0.0.1:5057</div>"
|
f"<div class='tab'>127.0.0.1:5057</div>"
|
||||||
@@ -169,14 +185,16 @@ def step3() -> None:
|
|||||||
output = run([bash, "-c", command], work)
|
output = run([bash, "-c", command], work)
|
||||||
entries.append((command, re.sub(r"/tmp/cli-demo-\w+", "~/demo", output)))
|
entries.append((command, re.sub(r"/tmp/cli-demo-\w+", "~/demo", output)))
|
||||||
shutil.rmtree(work, ignore_errors=True)
|
shutil.rmtree(work, ignore_errors=True)
|
||||||
terminal_page("Terminal - lecture 3: the command line", entries, OUT / "lecture-03.png", 330)
|
terminal_page(
|
||||||
|
"Terminal - lecture 3: the command line", entries, OUT / "lecture-03.png", 330
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def step4() -> None:
|
def step4() -> None:
|
||||||
entries = []
|
entries = []
|
||||||
cmd = "python -m flask_day_54.domain.name_demo"
|
cmd = "python -m flask_day_54.domain.name_demo"
|
||||||
entries.append((cmd, run([python(), "-m", "flask_day_54.domain.name_demo"], ROOT)))
|
entries.append((cmd, run([python(), "-m", "flask_day_54.domain.name_demo"], ROOT)))
|
||||||
imp = "python -c \"import flask_day_54.domain.name_demo as m; print(m.describe_name(m.__name__))\""
|
imp = 'python -c "import flask_day_54.domain.name_demo as m; print(m.describe_name(m.__name__))"'
|
||||||
entries.append(
|
entries.append(
|
||||||
(
|
(
|
||||||
imp,
|
imp,
|
||||||
@@ -202,23 +220,40 @@ def step4() -> None:
|
|||||||
raw = (server.stdout.read() if server.stdout else "").strip()
|
raw = (server.stdout.read() if server.stdout else "").strip()
|
||||||
# Leave out the .env tip and the random debugger PIN; they say nothing about the lecture.
|
# Leave out the .env tip and the random debugger PIN; they say nothing about the lecture.
|
||||||
kept = [
|
kept = [
|
||||||
line for line in raw.splitlines() if "Tip:" not in line and "Debugger PIN" not in line
|
line
|
||||||
|
for line in raw.splitlines()
|
||||||
|
if "Tip:" not in line and "Debugger PIN" not in line
|
||||||
]
|
]
|
||||||
out = "\n".join(kept)
|
out = "\n".join(kept)
|
||||||
entries.append(("python -m flask_day_54.presentation.hello", out + "\n^C"))
|
entries.append(("python -m flask_day_54.presentation.hello", out + "\n^C"))
|
||||||
terminal_page("Terminal - lecture 4: __name__ and __main__", entries, OUT / "lecture-04.png", 560)
|
terminal_page(
|
||||||
|
"Terminal - lecture 4: __name__ and __main__",
|
||||||
|
entries,
|
||||||
|
OUT / "lecture-04.png",
|
||||||
|
560,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def step5() -> None:
|
def step5() -> None:
|
||||||
module = "flask_day_54.domain.first_class_functions"
|
module = "flask_day_54.domain.first_class_functions"
|
||||||
entries = [(f"python -m {module}", run([python(), "-m", module], ROOT))]
|
entries = [(f"python -m {module}", run([python(), "-m", module], ROOT))]
|
||||||
terminal_page("Terminal - lecture 5: functions as first-class objects", entries, OUT / "lecture-05.png", 420)
|
terminal_page(
|
||||||
|
"Terminal - lecture 5: functions as first-class objects",
|
||||||
|
entries,
|
||||||
|
OUT / "lecture-05.png",
|
||||||
|
420,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def step6() -> None:
|
def step6() -> None:
|
||||||
module = "flask_day_54.domain.decorators"
|
module = "flask_day_54.domain.decorators"
|
||||||
entries = [(f"python -m {module}", run([python(), "-m", module], ROOT))]
|
entries = [(f"python -m {module}", run([python(), "-m", module], ROOT))]
|
||||||
terminal_page("Terminal - lecture 6: decorators and the @ syntax", entries, OUT / "lecture-06.png", 380)
|
terminal_page(
|
||||||
|
"Terminal - lecture 6: decorators and the @ syntax",
|
||||||
|
entries,
|
||||||
|
OUT / "lecture-06.png",
|
||||||
|
380,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
STEPS = {1: step1, 2: step2, 3: step3, 4: step4, 5: step5, 6: step6}
|
STEPS = {1: step1, 2: step2, 3: step3, 4: step4, 5: step5, 6: step6}
|
||||||
|
|||||||
+13
-6
@@ -11,7 +11,8 @@
|
|||||||
## Version History
|
## Version History
|
||||||
| Date | Status | Author | Reviewer | Change | Commit |
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
| --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- |
|
||||||
| 2026-11-06 | Accepted | Jens Tirsvad Nielsen | S01 | Initial version | [73a5a95] |
|
| 2026-11-06 | Deprecated | Jens Tirsvad Nielsen | S01 | Initial version | [73a5a95] |
|
||||||
|
| 2026-11-06 | Accepted | Jens Tirsvad Nielsen | S01 | Link each gateway to its synced Gitea milestone | [8cd73cc] |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -31,11 +32,11 @@ Schedule the five gateways that turn the Day 54 lectures into a tested, document
|
|||||||
|
|
||||||
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
|
| Gateway | Document | Window | Decision date | Owner | Stories | Main deliverable | Milestone |
|
||||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
| Foundation | [MIL-001] | 2026-11-06 | 2026-11-06 | S01 | none (technical tasks) | pyproject, gitignore, constants, Doxyfile, README, repo metadata | not yet synced |
|
| Foundation | [MIL-001] | 2026-11-06 | 2026-11-06 | S01 | none (technical tasks) | pyproject, gitignore, constants, Doxyfile, README, repo metadata | [Milestone 001][GM-001] |
|
||||||
| Backend and Hello Flask | [MIL-002] | 2026-11-06 to 2026-11-07 | 2026-11-07 | S01 | none (technical tasks) | hello.py, tests, screenshots 1 and 2 | not yet synced |
|
| Backend and Hello Flask | [MIL-002] | 2026-11-06 to 2026-11-07 | 2026-11-07 | S01 | none (technical tasks) | hello.py, tests, screenshots 1 and 2 | [Milestone 002][GM-002] |
|
||||||
| Command line and __main__ | [MIL-003] | 2026-11-07 to 2026-11-08 | 2026-11-08 | S01 | none (technical tasks) | main guard, name_demo, cli_basics, screenshots 3 and 4 | not yet synced |
|
| Command line and __main__ | [MIL-003] | 2026-11-07 to 2026-11-08 | 2026-11-08 | S01 | none (technical tasks) | main guard, name_demo, cli_basics, screenshots 3 and 4 | [Milestone 003][GM-003] |
|
||||||
| Functions and decorators | [MIL-004] | 2026-11-08 to 2026-11-09 | 2026-11-09 | S01 | none (technical tasks) | first_class_functions, decorators, screenshots 5 and 6 | not yet synced |
|
| Functions and decorators | [MIL-004] | 2026-11-08 to 2026-11-09 | 2026-11-09 | S01 | none (technical tasks) | first_class_functions, decorators, screenshots 5 and 6 | [Milestone 004][GM-004] |
|
||||||
| Docs and wiki | [MIL-005] | 2026-11-09 to 2026-11-10 | 2026-11-10 | S01 | none (technical tasks) | three-language wiki, Doxygen, code review | not yet synced |
|
| Docs and wiki | [MIL-005] | 2026-11-09 to 2026-11-10 | 2026-11-10 | S01 | none (technical tasks) | three-language wiki, Doxygen, code review | [Milestone 005][GM-005] |
|
||||||
|
|
||||||
```plantuml
|
```plantuml
|
||||||
@startgantt
|
@startgantt
|
||||||
@@ -96,3 +97,9 @@ A No-Go on a gateway moves every later gateway by the time needed to fix and re-
|
|||||||
[MIL-004]: ./milestones/mil-004-functions-decorators.md
|
[MIL-004]: ./milestones/mil-004-functions-decorators.md
|
||||||
[MIL-005]: ./milestones/mil-005-docs-wiki.md
|
[MIL-005]: ./milestones/mil-005-docs-wiki.md
|
||||||
[73a5a95]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/commit/73a5a95d28db041e4f27342cc552e18f7d386410
|
[73a5a95]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/commit/73a5a95d28db041e4f27342cc552e18f7d386410
|
||||||
|
[GM-001]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/milestone/342
|
||||||
|
[GM-002]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/milestone/343
|
||||||
|
[GM-003]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/milestone/344
|
||||||
|
[GM-004]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/milestone/345
|
||||||
|
[GM-005]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/milestone/346
|
||||||
|
[8cd73cc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/commit/8cd73cc46b3f791e0c23a60809a50e4140089d4e
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# Review of MIL-005
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-019 |
|
||||||
|
| CrossReference | [MIL-005], [QC-WIKI-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-11-06 | Proposed | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [8cd73cc] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [MIL-005]
|
||||||
|
- Checklist used: [QC-WIKI-001]
|
||||||
|
- Scope: full review of the wiki sources in docs/wiki/ before publishing
|
||||||
|
- Language and domain: n/a
|
||||||
|
- Language reviewer: none (the reviewer reads English and knows the IT domain)
|
||||||
|
- Mode: autonomous, not independent (AI as stand-in for S01)
|
||||||
|
|
||||||
|
## Checklist Results
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | The wiki has a `_Sidebar.md`, because the host lists subpages only through it | Pass | docs/wiki/_Sidebar.md exists. |
|
||||||
|
| 2 | The sidebar starts with the wiki's title in bold, then one list of the pages in the primary language (English), `Home` first | Pass | Starts with **Flask Day 54**, then one English page list with Home first. |
|
||||||
|
| 3 | The page list holds a link to every English page of the wiki, and no link points to a page that does not exist | Pass | Eight English pages are all linked; check_wiki.py found no dead link. |
|
||||||
|
| 4 | A `**Related**` section follows the page list only when the wiki has related wikis (for example the checklists wiki for a framework wiki); each entry is a link to that wiki's Home. A wiki with nothing related has no such section | N-A | The wiki has no related wikis, so there is no Related section. |
|
||||||
|
| 5 | A `**Languages**` section is the last section of the sidebar. It has one line per language, the language written in that language, linking to that language's `Home` page | Pass | Languages section is last: English, Dansk and Bahasa Melayu, each linking to its Home page. |
|
||||||
|
| 6 | The sidebar does not repeat the page list per language | Pass | The page list appears once. |
|
||||||
|
| 7 | A sidebar produced by a generator carries a comment that says so and names the generator; the generator is changed, not the page | N-A | The sidebar is written by hand, not generated. |
|
||||||
|
| 8 | The wiki has a `Languages` line on each page (criterion 11), so the sidebar is not the only way to switch language | Pass | Every page has the language line. |
|
||||||
|
| 9 | Every wiki exists in English and, as a minimum, in the language the project's registry names as the PO language; further languages are added on top, never instead of English | Pass | English plus Danish and Bahasa Malaysia; the PO language is English. |
|
||||||
|
| 10 | Every English page has a page in each other language of the wiki: the page sets are identical | Pass | Eight pages in each of the three languages (24 files); check_wiki.py confirms parity. |
|
||||||
|
| 11 | Every page starts with the language line, with the current language in bold and a link to the same page in each other language | Pass | Line 3 of every page has the bold current language and links to the other two. |
|
||||||
|
| 12 | A page in a language other than English is named `<Page>-<code>.md`, with a BCP 47 code; English has no suffix | Pass | Files are <Page>-da.md and <Page>-ms.md; English has no suffix. |
|
||||||
|
| 13 | Code blocks, commands, file names and IDs stay in English in every language | Pass | check_wiki.py: code blocks and image links are identical in all three languages. |
|
||||||
|
| 14 | The sidebar, every page and every link were checked on the published wiki after the change, not only in the repository | Pending | The wiki can only be published by the merge to main; the published sidebar, pages and links are checked after the merge and recorded in a follow-up review. |
|
||||||
|
| 15 | A change to the layout rules (sections, order, naming) is made in the generator or template and in this checklist's source rules together | N-A | No layout rule is changed. |
|
||||||
|
| 16 | The wiki folder (`docs/wiki/`) is flat: every page, `Home.md` and `_Sidebar.md` included, is directly in it, and languages are told apart by file name, never by a subfolder | Pass | docs/wiki/ is flat; no subfolder. |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go-with-conditions — Every criterion that can be checked before publishing passes; criterion 14 is Pending until the merge publishes the wiki. The Danish and Bahasa Malaysia pages were translated and checked by the AI only, not by a native speaker.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Check the published sidebar, pages and links on the host and record a follow-up review | S01 | 2026-11-07 |
|
||||||
|
| Have a native reader confirm the Danish and Bahasa Malaysia wording (not independent so far) | S01 | 2026-11-10 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[MIL-005]: ../../milestones/mil-005-docs-wiki.md
|
||||||
|
[QC-WIKI-001]: ../../../framework/qc/artifacts/qc-wiki.md
|
||||||
|
[8cd73cc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/commit/8cd73cc46b3f791e0c23a60809a50e4140089d4e
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
# Review of MIL-005
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-020 |
|
||||||
|
| CrossReference | [MIL-005], [QC-PY-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-11-06 | Proposed | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [8cd73cc] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [MIL-005]
|
||||||
|
- Checklist used: [QC-PY-001]
|
||||||
|
- Scope: full review of all source and tests in src/ and tests/ at the end of the project
|
||||||
|
- Language and domain: n/a
|
||||||
|
- Language reviewer: none (the reviewer reads English and knows the IT domain)
|
||||||
|
- Mode: autonomous, not independent (AI as stand-in for S01)
|
||||||
|
|
||||||
|
## Checklist Results
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | Packages, modules, functions, variables, classes and constants follow PEP 8 casing (`snake_case`, `PascalCase`, `UPPER_SNAKE`) | Pass | Modules, functions and constants use snake_case / UPPER_SNAKE; classes none or PascalCase. |
|
||||||
|
| 2 | Names state purpose in the domain's language; no unexplained abbreviations, no single-letter names outside tiny scopes | Pass | Names follow the lecture and the domain dictionary. |
|
||||||
|
| 3 | Code is produced by the project's formatter and passes its linter with no unexplained suppressions | Pass | `ruff format` leaves files unchanged and `ruff check` (E, F, I, B, UP) passes; configured in pyproject.toml. |
|
||||||
|
| 4 | Every function and method signature is type-annotated, including `-> None` | Pass | Every function signature is annotated, including `-> None`. |
|
||||||
|
| 5 | No bare `except:`, no swallowed exceptions; specific exceptions are raised and the cause is kept (`raise ... from`) | Pass | No bare except and no swallowed exception. |
|
||||||
|
| 6 | No mutable default arguments and no shadowed builtins | Pass | No mutable defaults; no builtin shadowed. |
|
||||||
|
| 7 | Files, locks and connections are managed with context managers | N-A | No file, lock or connection is opened. |
|
||||||
|
| 8 | Public modules, classes and functions have docstrings that say what, not how | Pass | Module and public names carry docstrings plus Doxygen comments. |
|
||||||
|
| 9 | Logging uses `logging`, not `print`; no secrets or personal data in log output | N-A | Console output of the demo entry points (print under the __main__ guard) is the program's result, not diagnostic logging; no secrets handled. |
|
||||||
|
| 10 | Classes and operations trace to the Design Class Diagram they implement; deviations are recorded | N-A | No DCD exists in this project; the layered layout is recorded in ADR-0001. |
|
||||||
|
| 11 | Tests exist for new behaviour, are named for the behaviour, and do not depend on order or the network | Pass | pytest tests named for behaviour; no order or network dependence. |
|
||||||
|
| 12 | Type checker runs in strict mode without errors; `Any` is justified in a comment | N-A | No type checker is configured (optional criterion). |
|
||||||
|
| 13 | Dependencies are declared and pinned in the project's dependency file, none unused | Pass | Dependencies are declared in pyproject.toml; none unused (Flask is the optional `web` extra). |
|
||||||
|
| 14 | Each piece of knowledge (a business rule, constant, format, validation or query) is defined in one place; code is merged only where it expresses the same knowledge, not where it merely looks alike | Pass | Each constant is defined once in the constants.py of its layer. |
|
||||||
|
| 15 | Imports point inward: business-rule modules import no framework, database, UI or delivery-mechanism code, and there are no import cycles | Pass | `domain` imports no framework or outer layer; imports point inward; no cycles. |
|
||||||
|
| 16 | SOLID holds: a class or module has one reason to change; new behaviour is added by extension, not by editing a type test in several places; subclasses honour the contract of their base; protocols are narrow; high-level code depends on protocols or abstract types and receives its implementations | Pass | Small modules with one reason to change; no type tests or subclass hierarchies. |
|
||||||
|
| 17 | Source is laid out in the layers and folders of the clean architecture folder structure (`domain`, `application`, `infrastructure`, `presentation` packages under `src/`, and `unit`, `integration` and `e2e` under `tests/`), in `snake_case`, and imports between the layers point inward | Pass | Layers domain, application, infrastructure, presentation under src/flask_day_54; tests in unit and e2e (ADR-0001); no layer merged. |
|
||||||
|
| 18 | File and folder names are English, contain no space and no character outside letters, digits, `-`, `_` and `.`, and follow the casing of the language for files | Pass | English snake_case file names without spaces. |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — All applicable mandatory criteria pass.
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[MIL-005]: ../../milestones/mil-005-docs-wiki.md
|
||||||
|
[QC-PY-001]: ../../../framework/qc/code/qc-programming-python.md
|
||||||
|
[8cd73cc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/commit/8cd73cc46b3f791e0c23a60809a50e4140089d4e
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# Review of PP-001
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
| Key | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| ID | RC-021 |
|
||||||
|
| CrossReference | [PP-001], [QC-PP-001] |
|
||||||
|
|
||||||
|
## Version History
|
||||||
|
| Date | Status | Author | Reviewer | Change | Commit |
|
||||||
|
| --- | --- | --- | --- | --- | --- |
|
||||||
|
| 2026-11-06 | Proposed | Jens Tirsvad Nielsen | AI as stand-in for S01 | Initial version | [8cd73cc] |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Artifact Under Review
|
||||||
|
|
||||||
|
- Instance reviewed: [PP-001]
|
||||||
|
- Checklist used: [QC-PP-001]
|
||||||
|
- Scope: full review (re-review after the change)
|
||||||
|
- Language and domain: en / it
|
||||||
|
- Language reviewer: none (the reviewer reads English and knows the IT domain)
|
||||||
|
- Mode: autonomous, not independent (AI as stand-in for S01)
|
||||||
|
|
||||||
|
## Checklist Results
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | The plan states its start date, end date and the constraint it must fit | Pass | Start 2026-11-06, end 2026-11-10, constraint: one PR per milestone (BC-001 Constraints). |
|
||||||
|
| 2 | Every milestone or gateway is listed once with its document, decision date and owner | Pass | Five gateways, each with document, decision date and owner S01. |
|
||||||
|
| 3 | Every decision date lies inside the plan's window and is consistent with the dates in the linked `MIL-*` document | Pass | Decision dates equal the Target Date of each MIL document and lie inside the window. |
|
||||||
|
| 4 | Every in-scope item of the Business Case is delivered at a named gateway (scope coverage) | Pass | Scope Coverage table maps every In Scope item to a gateway. |
|
||||||
|
| 5 | Dependencies between gateways are stated, acyclic and consistent with the schedule order | Pass | Chain MIL-001 to MIL-005 is acyclic and matches the dates. |
|
||||||
|
| 6 | The plan states what happens to later gateways and to the end date when a gateway is No-Go | Pass | Dependencies section: later gateways shift; S01 decides the end date. |
|
||||||
|
| 7 | Owners, reviewers and escalation roles use Stakeholder Analysis IDs and match the governance RACI | N-A | Owners and reviewers use S01; no governance document (GOV) exists in this small project, so no RACI to match. |
|
||||||
|
| 8 | Planning assumptions are listed with their source, and a changed baseline is recorded with its reason | Pass | Planning Assumptions lists sources; changes will be recorded in Version History. |
|
||||||
|
| 9 | Plan risks are listed with impact and a mitigation, and trace to Business Case risks where they come from there | Pass | Three plan risks with mitigation; two trace to BC-001 risks. |
|
||||||
|
| 10 | Open issues are listed, and none contradicts a statement elsewhere in the plan | Pass | Open Issues remain current. |
|
||||||
|
| 11 | Each gateway's main deliverable is stated and matches the deliverable of its `MIL-*` document | Pass | Main deliverables match the Deliverable sections of the MIL documents. |
|
||||||
|
| 12 | Gateways that deliver user stories name them, and those that do not say why | Pass | Stories column says `none (technical tasks)`. |
|
||||||
|
| 13 | The schedule view (table, Gantt) and the dependency view agree with each other | Pass | Gantt bars match the table; chain matches Dependencies. |
|
||||||
|
| 14 | Each gateway is linked to its issue-tracker milestone, or marked as not yet synced | Pass | Every gateway row links its Gitea milestone (342 to 346) with a reference-style link. |
|
||||||
|
| 15 | The plan is a singleton: one Project Plan per project, changes recorded in Version History | Pass | Single plan; Version History present. |
|
||||||
|
|
||||||
|
## Language and Domain Results
|
||||||
|
|
||||||
|
| # | Criterion | Status | Evidence/Notes |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| 1 | The Metadata table has a `Language` row and a `Domain` row, and neither is a placeholder | Pass | Checked against the document and the registry. |
|
||||||
|
| 2 | `Language` is a BCP 47 code and `Domain` is a value from the registry's domain list | Pass | Checked against the document and the registry. |
|
||||||
|
| 3 | The content (prose and table cells) is written in the stated language | Pass | All prose and table cells are English, the PO language (registry `PO language` = en). |
|
||||||
|
| 4 | The register matches the one the registry gives for the artifact type | Pass | Register: IT Executive English for BC/PP/MIL, IT Professional English for SA/DICT; no implementation detail in the executive documents beyond file names. |
|
||||||
|
| 5 | Domain terms are the PO terms of the domain's dictionary, with no synonyms | Pass | Terms follow `docs/dictionary.md` (DICT-001): greeting, home page, lecture step, local environment, wrapper. |
|
||||||
|
| 6 | Metadata keys, section headings, IDs and statuses are in English | Pass | Checked against the document and the registry. |
|
||||||
|
| 7 | No translated twin (`<name>.<language>.md`) exists beside the document | Pass | No `*.en.md` or other translated twin exists. |
|
||||||
|
| 8 | A change of language or domain since the previous accepted version has a Version History row and was reviewed again | Pass | First version; no earlier language to compare. |
|
||||||
|
| 9 | A reviewer competent in the domain, and in the language, has confirmed that the domain terms are used correctly | Pass | Reviewer S01 reads English and works in the IT domain (stand-in, not independent). |
|
||||||
|
| 10 | Abbreviations are spelled out on first use, in the stated language | Pass | FURPS+, BC, SA etc. are defined by the framework; ISO/IEC 25010 named in full. |
|
||||||
|
|
||||||
|
## Overall Verdict
|
||||||
|
|
||||||
|
Go — Re-review of the whole checklist after the milestone links were added; all mandatory criteria pass (7 is not applicable).
|
||||||
|
|
||||||
|
## Action Items
|
||||||
|
|
||||||
|
| Action | Owner | Due |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| None | S01 | - |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[PP-001]: ../../project-plan.md
|
||||||
|
[QC-PP-001]: ../../../framework/qc/artifacts/qc-project-plan.md
|
||||||
|
[QC-LANG-001]: ../../../framework/qc/artifacts/qc-language-domain.md
|
||||||
|
[8cd73cc]: https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/commit/8cd73cc46b3f791e0c23a60809a50e4140089d4e
|
||||||
@@ -25,14 +25,14 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
| --- | --- | --- | --- | --- | --- | --- |
|
| --- | --- | --- | --- | --- | --- | --- |
|
||||||
| [BC-001] | BC | en | it | - | [SA-001], [PP-001] | [RC-001] |
|
| [BC-001] | BC | en | it | - | [SA-001], [PP-001] | [RC-001] |
|
||||||
| [SA-001] | SA | en | it | [BC-001] | [BC-001] | [RC-002] |
|
| [SA-001] | SA | en | it | [BC-001] | [BC-001] | [RC-002] |
|
||||||
| [PP-001] | PP | en | it | [BC-001], [SA-001] | [MIL-001] to [MIL-005] | [RC-003] |
|
| [PP-001] | PP | en | it | [BC-001], [SA-001] | [MIL-001] to [MIL-005] | [RC-021] |
|
||||||
| [ADR-0001] | ADR | - | - | [BC-001], [PP-001] | [MIL-001] to [MIL-004] | [RC-010] |
|
| [ADR-0001] | ADR | - | - | [BC-001], [PP-001] | [MIL-001] to [MIL-004] | [RC-010] |
|
||||||
| [DICT-001] | DICT | en | it | [BC-001], [SA-001] | - | [RC-004] |
|
| [DICT-001] | DICT | en | it | [BC-001], [SA-001] | - | [RC-004] |
|
||||||
| [MIL-001] | MIL | en | it | [BC-001], [PP-001], [ADR-0001] | - | [RC-011] |
|
| [MIL-001] | MIL | en | it | [BC-001], [PP-001], [ADR-0001] | - | [RC-011], [RC-015] |
|
||||||
| [MIL-002] | MIL | en | it | [BC-001], [PP-001], [ADR-0001] | - | [RC-012] |
|
| [MIL-002] | MIL | en | it | [BC-001], [PP-001], [ADR-0001] | - | [RC-012], [RC-016] |
|
||||||
| [MIL-003] | MIL | en | it | [BC-001], [PP-001], [ADR-0001] | - | [RC-013] |
|
| [MIL-003] | MIL | en | it | [BC-001], [PP-001], [ADR-0001] | - | [RC-013], [RC-017] |
|
||||||
| [MIL-004] | MIL | en | it | [BC-001], [PP-001], [ADR-0001] | - | [RC-014] |
|
| [MIL-004] | MIL | en | it | [BC-001], [PP-001], [ADR-0001] | - | [RC-014], [RC-018] |
|
||||||
| [MIL-005] | MIL | en | it | [BC-001], [PP-001] | - | [RC-009] |
|
| [MIL-005] | MIL | en | it | [BC-001], [PP-001] | - | [RC-009], [RC-019], [RC-020] |
|
||||||
|
|
||||||
## Concern Coverage
|
## Concern Coverage
|
||||||
|
|
||||||
@@ -54,8 +54,6 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
[BC-001]: ../business-case.md
|
[BC-001]: ../business-case.md
|
||||||
[SA-001]: ../stakeholder-analysis.md
|
[SA-001]: ../stakeholder-analysis.md
|
||||||
[PP-001]: ../project-plan.md
|
[PP-001]: ../project-plan.md
|
||||||
@@ -80,3 +78,10 @@ updated whenever an artifact instance is created or reviewed.
|
|||||||
[RC-012]: ./reviews/rc-012-mil-002-hello-flask-delta.md
|
[RC-012]: ./reviews/rc-012-mil-002-hello-flask-delta.md
|
||||||
[RC-013]: ./reviews/rc-013-mil-003-cli-and-main-delta.md
|
[RC-013]: ./reviews/rc-013-mil-003-cli-and-main-delta.md
|
||||||
[RC-014]: ./reviews/rc-014-mil-004-functions-decorators-delta.md
|
[RC-014]: ./reviews/rc-014-mil-004-functions-decorators-delta.md
|
||||||
|
[RC-015]: ./reviews/rc-015-code-mil-001-foundation.md
|
||||||
|
[RC-016]: ./reviews/rc-016-code-mil-002-hello-flask.md
|
||||||
|
[RC-017]: ./reviews/rc-017-code-mil-003-cli-and-main.md
|
||||||
|
[RC-018]: ./reviews/rc-018-code-mil-004-functions-decorators.md
|
||||||
|
[RC-019]: ./reviews/rc-019-wiki-mil-005.md
|
||||||
|
[RC-020]: ./reviews/rc-020-code-mil-005-docs-wiki.md
|
||||||
|
[RC-021]: ./reviews/rc-021-project-plan-delta.md
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Flask dag 54: 100 Days of Code
|
||||||
|
|
||||||
|
[English](Home) · **Dansk** · [Bahasa Malaysia](Home-ms)
|
||||||
|
|
||||||
|
Kørbare, testede løsninger til dag 54 i Udemys "100 Days of Code: The Complete Python Pro Bootcamp". Wikien forklarer forelæsning for forelæsning, hvad koden gør, og hvad vi fik ud af forelæsningen.
|
||||||
|
|
||||||
|
## Forelæsninger
|
||||||
|
|
||||||
|
| Trin | Side | Emne |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 1 | [Forelæsning 1](Lecture-1-Backend-Overview-da) | Frontend, backend og request-response-cyklussen |
|
||||||
|
| 2 | [Forelæsning 2](Lecture-2-Hello-Flask-da) | Den første Flask-server |
|
||||||
|
| 3 | [Forelæsning 3](Lecture-3-Command-Line-da) | Kommandolinjen |
|
||||||
|
| 4 | [Forelæsning 4](Lecture-4-Name-and-Main-da) | `__name__` og `__main__` |
|
||||||
|
| 5 | [Forelæsning 5](Lecture-5-First-Class-Functions-da) | Funktioner som førsteklasses objekter |
|
||||||
|
| 6 | [Forelæsning 6](Lecture-6-Decorators-da) | Dekoratører og `@`-syntaksen |
|
||||||
|
|
||||||
|
Start med [Opsætning og kørsel](Setup-and-Run-da) for at oprette et lokalt `.venv` og køre koden og testene.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- [Repository](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask)
|
||||||
|
- [Issue tracker](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/issues)
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Flask Hari 54: 100 Days of Code
|
||||||
|
|
||||||
|
[English](Home) · [Dansk](Home-da) · **Bahasa Malaysia**
|
||||||
|
|
||||||
|
Penyelesaian Hari 54 bagi kursus Udemy "100 Days of Code: The Complete Python Pro Bootcamp" yang boleh dijalankan dan telah diuji. Wiki ini menerangkan, kuliah demi kuliah, apa yang dilakukan oleh kod dan apa yang kita pelajari daripada setiap kuliah.
|
||||||
|
|
||||||
|
## Kuliah
|
||||||
|
|
||||||
|
| Langkah | Halaman | Topik |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 1 | [Kuliah 1](Lecture-1-Backend-Overview-ms) | Bahagian hadapan, bahagian belakang dan kitaran permintaan-respons |
|
||||||
|
| 2 | [Kuliah 2](Lecture-2-Hello-Flask-ms) | Pelayan Flask yang pertama |
|
||||||
|
| 3 | [Kuliah 3](Lecture-3-Command-Line-ms) | Baris arahan |
|
||||||
|
| 4 | [Kuliah 4](Lecture-4-Name-and-Main-ms) | `__name__` dan `__main__` |
|
||||||
|
| 5 | [Kuliah 5](Lecture-5-First-Class-Functions-ms) | Fungsi sebagai objek kelas pertama |
|
||||||
|
| 6 | [Kuliah 6](Lecture-6-Decorators-ms) | Penghias (decorator) dan sintaks `@` |
|
||||||
|
|
||||||
|
Mulakan dengan [Persediaan dan Jalankan](Setup-and-Run-ms) untuk mencipta `.venv` setempat serta menjalankan kod dan ujian.
|
||||||
|
|
||||||
|
## Pautan
|
||||||
|
|
||||||
|
- [Repositori](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask)
|
||||||
|
- [Penjejak isu](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/issues)
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Flask Day 54: 100 Days of Code
|
||||||
|
|
||||||
|
**English** · [Dansk](Home-da) · [Bahasa Malaysia](Home-ms)
|
||||||
|
|
||||||
|
Runnable, tested solutions for Day 54 of Udemy's "100 Days of Code: The Complete Python Pro Bootcamp". The wiki explains, lecture by lecture, what the code does and what we gained from the lecture.
|
||||||
|
|
||||||
|
## Lectures
|
||||||
|
|
||||||
|
| Step | Page | Topic |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 1 | [Lecture 1](Lecture-1-Backend-Overview) | Frontend, backend and the request-response cycle |
|
||||||
|
| 2 | [Lecture 2](Lecture-2-Hello-Flask) | The first Flask server |
|
||||||
|
| 3 | [Lecture 3](Lecture-3-Command-Line) | The command line |
|
||||||
|
| 4 | [Lecture 4](Lecture-4-Name-and-Main) | `__name__` and `__main__` |
|
||||||
|
| 5 | [Lecture 5](Lecture-5-First-Class-Functions) | Functions as first-class objects |
|
||||||
|
| 6 | [Lecture 6](Lecture-6-Decorators) | Decorators and the `@` syntax |
|
||||||
|
|
||||||
|
Start with [Setup and Run](Setup-and-Run) to create a local `.venv` and run the code and the tests.
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- [Repository](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask)
|
||||||
|
- [Issue tracker](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask/issues)
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Forelæsning 1: Frontend, backend og request-response-cyklussen
|
||||||
|
|
||||||
|
[English](Lecture-1-Backend-Overview) · **Dansk** · [Bahasa Malaysia](Lecture-1-Backend-Overview-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Hvad forelæsningen handler om
|
||||||
|
|
||||||
|
Forelæsningen adskiller det, brugeren ser (frontend: HTML, CSS og JavaScript), fra det, applikationen gør bag kulisserne (backend: Python, Java, Ruby og andre). En backend har tre dele: klienten, serveren og databasen. En restaurant er en god analogi: spisesalen er klienten, køkkenet er serveren, og spisekammeret er databasen. I request-response-cyklussen spørger klienten, serveren forbereder og henter data fra databasen, og svaret sendes tilbage til klienten. Flask anbefales til begyndere og små projekter; Django er det andet velkendte valg.
|
||||||
|
|
||||||
|
## Hvad vi fik ud af det
|
||||||
|
|
||||||
|
- Et ordforråd til at tale om webapplikationer: klient, server, database, request, response.
|
||||||
|
- En grund til at vælge Flask: det er småt og lader os se hver del af cyklussen.
|
||||||
|
- Viden om, at resten af kurset bygger hver af disse dele op trin for trin.
|
||||||
|
|
||||||
|
## I dette repository
|
||||||
|
|
||||||
|
Diagrammet er tegnet ud fra `docs/images/sources/lecture-01.html`; der er ingen kode til denne forelæsning.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Kuliah 1: Bahagian hadapan, bahagian belakang dan kitaran permintaan-respons
|
||||||
|
|
||||||
|
[English](Lecture-1-Backend-Overview) · [Dansk](Lecture-1-Backend-Overview-da) · **Bahasa Malaysia**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Apa yang dibincangkan dalam kuliah
|
||||||
|
|
||||||
|
Kuliah ini membezakan apa yang dilihat oleh pengguna (bahagian hadapan: HTML, CSS dan JavaScript) daripada apa yang dilakukan oleh aplikasi di sebalik tabir (bahagian belakang: Python, Java, Ruby dan lain-lain). Bahagian belakang mempunyai tiga komponen: klien, pelayan dan pangkalan data. Analoginya ialah sebuah restoran: ruang makan ialah klien, dapur ialah pelayan dan stor makanan ialah pangkalan data. Dalam kitaran permintaan-respons, klien membuat permintaan, pelayan menyediakan dan mengambil data daripada pangkalan data, dan respons dihantar kembali kepada klien. Flask disyorkan untuk pemula dan projek kecil; Django ialah pilihan lain yang terkenal.
|
||||||
|
|
||||||
|
## Apa yang kita peroleh
|
||||||
|
|
||||||
|
- Kosa kata untuk bercakap tentang aplikasi web: klien, pelayan, pangkalan data, permintaan, respons.
|
||||||
|
- Sebab untuk memilih Flask: ia kecil dan membolehkan kita melihat setiap bahagian kitaran itu.
|
||||||
|
- Pengetahuan bahawa seluruh kursus membina setiap komponen ini langkah demi langkah.
|
||||||
|
|
||||||
|
## Dalam repositori ini
|
||||||
|
|
||||||
|
Gambar rajah dilukis daripada `docs/images/sources/lecture-01.html`; tiada kod untuk kuliah ini.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Lecture 1: Frontend, backend and the request-response cycle
|
||||||
|
|
||||||
|
**English** · [Dansk](Lecture-1-Backend-Overview-da) · [Bahasa Malaysia](Lecture-1-Backend-Overview-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What the lecture covers
|
||||||
|
|
||||||
|
The lecture separates what the user sees (the frontend: HTML, CSS and JavaScript) from what the application does behind the scenes (the backend: Python, Java, Ruby and others). A backend has three parts: the client, the server and the database. A restaurant is the analogy: the dining area is the client, the kitchen is the server and the pantry is the database. In the request-response cycle the client asks, the server prepares and fetches data from the database, and the response goes back to the client. Flask is recommended for beginners and small projects; Django is the other well-known choice.
|
||||||
|
|
||||||
|
## What we gained
|
||||||
|
|
||||||
|
- A vocabulary for talking about web applications: client, server, database, request, response.
|
||||||
|
- A reason to choose Flask: it is small and lets us see every part of the cycle.
|
||||||
|
- The knowledge that the rest of the course builds each of these parts step by step.
|
||||||
|
|
||||||
|
## In this repository
|
||||||
|
|
||||||
|
The diagram is drawn from `docs/images/sources/lecture-01.html`; there is no code for this lecture.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Forelæsning 2: Den første Flask-server
|
||||||
|
|
||||||
|
[English](Lecture-2-Hello-Flask) · **Dansk** · [Bahasa Malaysia](Lecture-2-Hello-Flask-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Hvad forelæsningen handler om
|
||||||
|
|
||||||
|
Et bibliotek bliver kaldt af din kode, men et framework kalder din kode og bestemmer strukturen. Forelæsningen opretter den mindste mulige Flask-applikation i en fil med navnet `hello.py` (aldrig `flask.py`, som ville skjule biblioteket), installerer Flask med `pip`, peger `FLASK_APP` på filen og starter serveren med `flask run`. Browseren viser derefter "Hello, World!" fra den lokale adresse. `Ctrl+C` stopper serveren, så to applikationer ikke kæmper om den samme port.
|
||||||
|
|
||||||
|
## Hvad vi fik ud af det
|
||||||
|
|
||||||
|
- Forskellen mellem et bibliotek og et framework.
|
||||||
|
- En fungerende webserver på seks linjer: `app = Flask(__name__)`, en rute til `/` og en funktion, der returnerer tekst.
|
||||||
|
- Hvordan `FLASK_APP` fortæller Flask, hvilken fil der skal køres.
|
||||||
|
- En vane med at teste ruten med Flasks testklient i stedet for en browser.
|
||||||
|
|
||||||
|
## I dette repository
|
||||||
|
|
||||||
|
Kode: `src/flask_day_54/presentation/hello.py` (ruten `hello_world`), use casen `application/get_greeting.py` og konstanten `GREETING`. Tests: `tests/e2e/test_hello_app.py`.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Kuliah 2: Pelayan Flask yang pertama
|
||||||
|
|
||||||
|
[English](Lecture-2-Hello-Flask) · [Dansk](Lecture-2-Hello-Flask-da) · **Bahasa Malaysia**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Apa yang dibincangkan dalam kuliah
|
||||||
|
|
||||||
|
Sebuah pustaka dipanggil oleh kod anda, tetapi sebuah rangka kerja (framework) memanggil kod anda dan menentukan strukturnya. Kuliah ini mencipta aplikasi Flask yang paling kecil dalam fail bernama `hello.py` (jangan sekali-kali `flask.py`, kerana ia akan menyembunyikan pustaka itu), memasang Flask dengan `pip`, menunjukkan fail itu melalui `FLASK_APP` dan memulakan pelayan dengan `flask run`. Pelayar kemudian memaparkan "Hello, World!" daripada alamat setempat. `Ctrl+C` menghentikan pelayan supaya dua aplikasi tidak berebut port yang sama.
|
||||||
|
|
||||||
|
## Apa yang kita peroleh
|
||||||
|
|
||||||
|
- Perbezaan antara pustaka dan rangka kerja.
|
||||||
|
- Pelayan web yang berfungsi dalam enam baris: `app = Flask(__name__)`, satu laluan (route) untuk `/` dan satu fungsi yang memulangkan teks.
|
||||||
|
- Cara `FLASK_APP` memberitahu Flask fail mana yang hendak dijalankan.
|
||||||
|
- Tabiat menguji laluan dengan klien ujian Flask dan bukannya pelayar.
|
||||||
|
|
||||||
|
## Dalam repositori ini
|
||||||
|
|
||||||
|
Kod: `src/flask_day_54/presentation/hello.py` (laluan `hello_world`), kes guna `application/get_greeting.py` dan pemalar `GREETING`. Ujian: `tests/e2e/test_hello_app.py`.
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Lecture 2: The first Flask server
|
||||||
|
|
||||||
|
**English** · [Dansk](Lecture-2-Hello-Flask-da) · [Bahasa Malaysia](Lecture-2-Hello-Flask-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What the lecture covers
|
||||||
|
|
||||||
|
A library is called by your code, but a framework calls your code and decides the structure. The lecture creates the smallest Flask application in a file named `hello.py` (never `flask.py`, which would hide the library), installs Flask with `pip`, points `FLASK_APP` at the file and starts the server with `flask run`. The browser then shows "Hello, World!" from the local address. `Ctrl+C` stops the server so that two applications do not fight over the same port.
|
||||||
|
|
||||||
|
## What we gained
|
||||||
|
|
||||||
|
- The difference between a library and a framework.
|
||||||
|
- A working web server in six lines: `app = Flask(__name__)`, a route for `/` and a function that returns text.
|
||||||
|
- How `FLASK_APP` tells Flask which file to run.
|
||||||
|
- A habit of testing the route with Flask's test client instead of a browser.
|
||||||
|
|
||||||
|
## In this repository
|
||||||
|
|
||||||
|
Code: `src/flask_day_54/presentation/hello.py` (route `hello_world`), the use case `application/get_greeting.py` and the constant `GREETING`. Tests: `tests/e2e/test_hello_app.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Forelæsning 3: Kommandolinjen
|
||||||
|
|
||||||
|
[English](Lecture-3-Command-Line) · **Dansk** · [Bahasa Malaysia](Lecture-3-Command-Line-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Hvad forelæsningen handler om
|
||||||
|
|
||||||
|
Terminalen taler med operativsystemets kerne (kernel) gennem skallen (shell) (en pistacienød: kernen er nødden, skallen er den ydre skal). Den giver udviklere kontrol og hastighed. Forelæsningen viser `pwd` (hvor er jeg), `ls` (hvad er her), `cd` (gå derhen), `mkdir` (ny mappe), `touch` (ny fil) og `rm` (slet). `rm -rf` fjerner en mappe og alt i den uden at spørge, så den kræver forsigtighed. Windows har lignende kommandoer: `cd`, `dir`, `type nul > file`, `del`, `rmdir /s /q`.
|
||||||
|
|
||||||
|
## Hvad vi fik ud af det
|
||||||
|
|
||||||
|
- De seks kommandoer, vi bruger hver dag til at bevæge os rundt og administrere filer.
|
||||||
|
- En tydelig advarsel om de to destruktive kommandoer, skrevet ind i koden som data.
|
||||||
|
- Selvtillid til at bruge terminalen i stedet for kun grafiske værktøjer.
|
||||||
|
|
||||||
|
## I dette repository
|
||||||
|
|
||||||
|
Kode: `src/flask_day_54/domain/cli_basics.py` angiver kommandoerne med deres Windows-former. Skærmbilledet viser rigtige kommandoer kørt i en midlertidig mappe. Tests: `tests/unit/test_cli_basics.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Kuliah 3: Baris arahan
|
||||||
|
|
||||||
|
[English](Lecture-3-Command-Line) · [Dansk](Lecture-3-Command-Line-da) · **Bahasa Malaysia**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Apa yang dibincangkan dalam kuliah
|
||||||
|
|
||||||
|
Terminal berinteraksi dengan kernel sistem pengendalian melalui shell (seperti buah pistachio: kernel ialah isinya, shell ialah kulit luarnya). Ia memberi pembangun kawalan dan kelajuan. Kuliah ini menunjukkan `pwd` (di mana saya), `ls` (apa yang ada di sini), `cd` (pergi ke sana), `mkdir` (folder baharu), `touch` (fail baharu) dan `rm` (padam). `rm -rf` membuang sebuah folder dan segala isinya tanpa bertanya, jadi ia perlu digunakan dengan berhati-hati. Windows mempunyai arahan yang serupa: `cd`, `dir`, `type nul > file`, `del`, `rmdir /s /q`.
|
||||||
|
|
||||||
|
## Apa yang kita peroleh
|
||||||
|
|
||||||
|
- Enam arahan yang kita gunakan setiap hari untuk bergerak dan mengurus fail.
|
||||||
|
- Amaran yang jelas untuk dua arahan yang memusnahkan, ditulis dalam kod sebagai data.
|
||||||
|
- Keyakinan untuk menggunakan terminal dan bukan hanya alat bergrafik.
|
||||||
|
|
||||||
|
## Dalam repositori ini
|
||||||
|
|
||||||
|
Kod: `src/flask_day_54/domain/cli_basics.py` menyenaraikan arahan beserta bentuknya dalam Windows. Tangkapan skrin menunjukkan arahan sebenar yang dijalankan dalam folder sementara. Ujian: `tests/unit/test_cli_basics.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Lecture 3: The command line
|
||||||
|
|
||||||
|
**English** · [Dansk](Lecture-3-Command-Line-da) · [Bahasa Malaysia](Lecture-3-Command-Line-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What the lecture covers
|
||||||
|
|
||||||
|
The terminal talks to the operating system's kernel through the shell (a pistachio: the kernel is the nut, the shell is the outer shell). It gives developers control and speed. The lecture shows `pwd` (where am I), `ls` (what is here), `cd` (go there), `mkdir` (new folder), `touch` (new file) and `rm` (delete). `rm -rf` removes a folder and everything in it without asking, so it needs care. Windows has similar commands: `cd`, `dir`, `type nul > file`, `del`, `rmdir /s /q`.
|
||||||
|
|
||||||
|
## What we gained
|
||||||
|
|
||||||
|
- The six commands we use every day to move around and manage files.
|
||||||
|
- A clear warning for the two destructive commands, written into the code as data.
|
||||||
|
- Confidence to use the terminal instead of only graphical tools.
|
||||||
|
|
||||||
|
## In this repository
|
||||||
|
|
||||||
|
Code: `src/flask_day_54/domain/cli_basics.py` lists the commands with their Windows forms. The screenshot shows real commands run in a temporary folder. Tests: `tests/unit/test_cli_basics.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Forelæsning 4: __name__ og __main__
|
||||||
|
|
||||||
|
[English](Lecture-4-Name-and-Main) · **Dansk** · [Bahasa Malaysia](Lecture-4-Name-and-Main-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Hvad forelæsningen handler om
|
||||||
|
|
||||||
|
`__name__` er en indbygget variabel, der indeholder navnet på det aktuelle modul. Når en fil køres direkte, sætter Python den til `"__main__"`; når filen importeres, indeholder den modulets navn. Med `if __name__ == "__main__":` kan en fil bestemme, hvad der kun kører, når den er hovedprogrammet, for eksempel `app.run()`. Det giver en anden måde at starte Flask-serveren på ved siden af `flask run`, og det gør det nemt at starte og stoppe under udvikling.
|
||||||
|
|
||||||
|
## Hvad vi fik ud af det
|
||||||
|
|
||||||
|
- Reglen om, at kode kører korrekt, uanset om en fil køres eller importeres.
|
||||||
|
- En `main()`-funktion i `hello.py`, der kun kaldes under `__main__`-tjekket, så import aldrig starter en server.
|
||||||
|
- Et testet eksempel (`describe_name`), der forklarer de to tilfælde med ord.
|
||||||
|
|
||||||
|
## I dette repository
|
||||||
|
|
||||||
|
Kode: `src/flask_day_54/presentation/hello.py` (`main`) og `src/flask_day_54/domain/name_demo.py`. Tests: `tests/unit/test_name_demo.py` og `tests/e2e/test_hello_main.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Kuliah 4: __name__ dan __main__
|
||||||
|
|
||||||
|
[English](Lecture-4-Name-and-Main) · [Dansk](Lecture-4-Name-and-Main-da) · **Bahasa Malaysia**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Apa yang dibincangkan dalam kuliah
|
||||||
|
|
||||||
|
`__name__` ialah pemboleh ubah terbina dalam yang menyimpan nama modul semasa. Apabila sesebuah fail dijalankan terus, Python menetapkannya kepada `"__main__"`; apabila fail itu diimport, ia menyimpan nama modul. Semakan `if __name__ == "__main__":` membolehkan sesebuah fail menentukan apa yang dijalankan hanya apabila ia ialah atur cara utama, contohnya `app.run()`. Ini memberi cara kedua untuk memulakan pelayan Flask, selain `flask run`, dan memudahkan memulakan serta menghentikan pelayan semasa pembangunan.
|
||||||
|
|
||||||
|
## Apa yang kita peroleh
|
||||||
|
|
||||||
|
- Peraturan bahawa kod berjalan dengan betul sama ada fail dijalankan atau diimport.
|
||||||
|
- Fungsi `main()` dalam `hello.py` yang hanya dipanggil di bawah semakan `__main__`, jadi mengimportnya tidak akan memulakan pelayan.
|
||||||
|
- Contoh yang telah diuji (`describe_name`) yang menerangkan kedua-dua kes dengan kata-kata.
|
||||||
|
|
||||||
|
## Dalam repositori ini
|
||||||
|
|
||||||
|
Kod: `src/flask_day_54/presentation/hello.py` (`main`) dan `src/flask_day_54/domain/name_demo.py`. Ujian: `tests/unit/test_name_demo.py` dan `tests/e2e/test_hello_main.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Lecture 4: __name__ and __main__
|
||||||
|
|
||||||
|
**English** · [Dansk](Lecture-4-Name-and-Main-da) · [Bahasa Malaysia](Lecture-4-Name-and-Main-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What the lecture covers
|
||||||
|
|
||||||
|
`__name__` is a built-in variable that holds the name of the current module. When a file is run directly Python sets it to `"__main__"`; when the file is imported it holds the module name. Checking `if __name__ == "__main__":` lets a file decide what runs only when it is the main program, for example `app.run()`. That gives a second way to start the Flask server, next to `flask run`, and it makes starting and stopping easy during development.
|
||||||
|
|
||||||
|
## What we gained
|
||||||
|
|
||||||
|
- The rule that code runs correctly whether a file is run or imported.
|
||||||
|
- A `main()` function in `hello.py` that is only called under the `__main__` check, so importing it never starts a server.
|
||||||
|
- A tested example (`describe_name`) that explains the two cases in words.
|
||||||
|
|
||||||
|
## In this repository
|
||||||
|
|
||||||
|
Code: `src/flask_day_54/presentation/hello.py` (`main`) and `src/flask_day_54/domain/name_demo.py`. Tests: `tests/unit/test_name_demo.py` and `tests/e2e/test_hello_main.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Forelæsning 5: Funktioner som førsteklasses objekter
|
||||||
|
|
||||||
|
[English](Lecture-5-First-Class-Functions) · **Dansk** · [Bahasa Malaysia](Lecture-5-First-Class-Functions-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Hvad forelæsningen handler om
|
||||||
|
|
||||||
|
I Python er en funktion et objekt ligesom et heltal eller en streng: den kan sendes som argument, defineres inde i en anden funktion og returneres fra den. Funktionen `calculate` tager to tal og en anden funktion (`add` eller `subtract`) og anvender den. En indlejret funktion kan kaldes af sin overordnede funktion, men ikke udefra. En funktion kan returnere en indlejret funktion, og den, der kalder, gemmer den i en variabel og kalder den senere. Værktøjet Python Tutor viser trinnene visuelt.
|
||||||
|
|
||||||
|
## Hvad vi fik ud af det
|
||||||
|
|
||||||
|
- Ideen bag dekoratører: en funktion, der modtager en funktion og returnerer en funktion.
|
||||||
|
- Reglen for scope ved indlejrede funktioner, bekræftet af en test af, at det indlejrede navn ikke kan nås udefra.
|
||||||
|
- Opgavens navne (`add`, `subtract`, `calculate`) i kode, som andre kursister kan læse og køre.
|
||||||
|
|
||||||
|
## I dette repository
|
||||||
|
|
||||||
|
Kode: `src/flask_day_54/domain/first_class_functions.py`. Tests: `tests/unit/test_first_class_functions.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Kuliah 5: Fungsi sebagai objek kelas pertama
|
||||||
|
|
||||||
|
[English](Lecture-5-First-Class-Functions) · [Dansk](Lecture-5-First-Class-Functions-da) · **Bahasa Malaysia**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Apa yang dibincangkan dalam kuliah
|
||||||
|
|
||||||
|
Dalam Python, fungsi ialah objek seperti integer atau rentetan: ia boleh dihantar sebagai argumen, ditakrifkan di dalam fungsi lain dan dipulangkan daripadanya. Fungsi `calculate` menerima dua nombor dan satu fungsi lain (`add` atau `subtract`) lalu menggunakannya. Fungsi bersarang boleh dipanggil oleh fungsi induknya tetapi tidak dari luar. Sesebuah fungsi boleh memulangkan fungsi bersarang, dan pemanggil menyimpannya dalam pemboleh ubah serta memanggilnya kemudian. Alat Python Tutor menunjukkan langkah-langkahnya secara visual.
|
||||||
|
|
||||||
|
## Apa yang kita peroleh
|
||||||
|
|
||||||
|
- Idea di sebalik penghias (decorator): fungsi yang menerima fungsi dan memulangkan fungsi.
|
||||||
|
- Peraturan skop untuk fungsi bersarang, disahkan oleh ujian bahawa nama fungsi bersarang tidak boleh dicapai dari luar.
|
||||||
|
- Nama-nama dalam tugasan (`add`, `subtract`, `calculate`) dalam kod yang boleh dibaca dan dijalankan oleh peserta kursus yang lain.
|
||||||
|
|
||||||
|
## Dalam repositori ini
|
||||||
|
|
||||||
|
Kod: `src/flask_day_54/domain/first_class_functions.py`. Ujian: `tests/unit/test_first_class_functions.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Lecture 5: Functions as first-class objects
|
||||||
|
|
||||||
|
**English** · [Dansk](Lecture-5-First-Class-Functions-da) · [Bahasa Malaysia](Lecture-5-First-Class-Functions-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What the lecture covers
|
||||||
|
|
||||||
|
In Python a function is an object like an integer or a string: it can be passed as an argument, defined inside another function and returned from it. The `calculate` function takes two numbers and another function (`add` or `subtract`) and applies it. A nested function can be called by its parent but not from outside. A function can return a nested function, and the caller stores it in a variable and calls it later. The tool Python Tutor shows the steps visually.
|
||||||
|
|
||||||
|
## What we gained
|
||||||
|
|
||||||
|
- The idea behind decorators: a function that receives a function and returns a function.
|
||||||
|
- The scope rule for nested functions, confirmed by a test that the nested name is not reachable from outside.
|
||||||
|
- The assignment's names (`add`, `subtract`, `calculate`) in code that other course participants can read and run.
|
||||||
|
|
||||||
|
## In this repository
|
||||||
|
|
||||||
|
Code: `src/flask_day_54/domain/first_class_functions.py`. Tests: `tests/unit/test_first_class_functions.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Forelæsning 6: Dekoratører og @-syntaksen
|
||||||
|
|
||||||
|
[English](Lecture-6-Decorators) · **Dansk** · [Bahasa Malaysia](Lecture-6-Decorators-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Hvad forelæsningen handler om
|
||||||
|
|
||||||
|
En dekoratør tilføjer adfærd til en eksisterende funktion uden at redigere den. Forelæsningen opsummerer først førsteklasses funktioner samt indlejring og returnering af funktioner og introducerer derefter `@`-syntaksen: at skrive `@make_bold` over en funktion er det samme som `say_hello = make_bold(say_hello)`. Flask bruger den samme idé til sine ruter: `@app.route("/")`. Med `functools.wraps` beholder den indpakkede funktion sit navn.
|
||||||
|
|
||||||
|
## Hvad vi fik ud af det
|
||||||
|
|
||||||
|
- `@`-syntaksen som genvej til at sende en funktion til en wrapper.
|
||||||
|
- Stabling af dekoratører: den nærmest funktionen kører først, så `@make_bold @make_emphasis @make_underlined` giver `<b><em><u>...</u></em></b>`.
|
||||||
|
- En forståelse af, hvad `@app.route("/")` gør i de næste forelæsninger.
|
||||||
|
|
||||||
|
## I dette repository
|
||||||
|
|
||||||
|
Kode: `src/flask_day_54/domain/decorators.py`. Tests: `tests/unit/test_decorators.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Kuliah 6: Penghias (decorator) dan sintaks @
|
||||||
|
|
||||||
|
[English](Lecture-6-Decorators) · [Dansk](Lecture-6-Decorators-da) · **Bahasa Malaysia**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Apa yang dibincangkan dalam kuliah
|
||||||
|
|
||||||
|
Penghias (decorator) menambah tingkah laku pada fungsi sedia ada tanpa mengubah suai fungsi itu. Kuliah ini mula-mula mengulang kaji fungsi kelas pertama, fungsi bersarang dan pemulangan fungsi, kemudian memperkenalkan sintaks `@`: menulis `@make_bold` di atas sesebuah fungsi sama dengan `say_hello = make_bold(say_hello)`. Flask menggunakan idea yang sama untuk laluan (route)nya: `@app.route("/")`. Dengan `functools.wraps`, fungsi yang dibalut mengekalkan namanya.
|
||||||
|
|
||||||
|
## Apa yang kita peroleh
|
||||||
|
|
||||||
|
- Sintaks `@` sebagai jalan pintas untuk menghantar fungsi kepada pembalut.
|
||||||
|
- Penghias bertindan: yang paling hampir dengan fungsi dijalankan dahulu, maka `@make_bold @make_emphasis @make_underlined` menghasilkan `<b><em><u>...</u></em></b>`.
|
||||||
|
- Kefahaman tentang apa yang dilakukan oleh `@app.route("/")` dalam kuliah-kuliah seterusnya.
|
||||||
|
|
||||||
|
## Dalam repositori ini
|
||||||
|
|
||||||
|
Kod: `src/flask_day_54/domain/decorators.py`. Ujian: `tests/unit/test_decorators.py`.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Lecture 6: Decorators and the @ syntax
|
||||||
|
|
||||||
|
**English** · [Dansk](Lecture-6-Decorators-da) · [Bahasa Malaysia](Lecture-6-Decorators-ms)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## What the lecture covers
|
||||||
|
|
||||||
|
A decorator adds behaviour to an existing function without editing it. The lecture first recaps first-class functions, nesting and returning functions, then introduces the `@` syntax: writing `@make_bold` above a function is the same as `say_hello = make_bold(say_hello)`. Flask uses the same idea for its routes: `@app.route("/")`. With `functools.wraps` the wrapped function keeps its name.
|
||||||
|
|
||||||
|
## What we gained
|
||||||
|
|
||||||
|
- The `@` syntax as shorthand for passing a function to a wrapper.
|
||||||
|
- Stacking decorators: the one nearest the function runs first, so `@make_bold @make_emphasis @make_underlined` gives `<b><em><u>...</u></em></b>`.
|
||||||
|
- An understanding of what `@app.route("/")` does in the next lectures.
|
||||||
|
|
||||||
|
## In this repository
|
||||||
|
|
||||||
|
Code: `src/flask_day_54/domain/decorators.py`. Tests: `tests/unit/test_decorators.py`.
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Opsætning og kørsel
|
||||||
|
|
||||||
|
[English](Setup-and-Run) · **Dansk** · [Bahasa Malaysia](Setup-and-Run-ms)
|
||||||
|
|
||||||
|
## Krav
|
||||||
|
|
||||||
|
Python 3.13 eller nyere. Flask er kun nødvendigt til webforelæsningerne (det valgfrie tillæg `web`); pytest ligger i tillægget `dev`.
|
||||||
|
|
||||||
|
## Opret og brug et lokalt `.venv`
|
||||||
|
|
||||||
|
Windows (PowerShell):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python -m venv .venv
|
||||||
|
.\.venv\Scripts\Activate.ps1
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
macOS og Linux:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Kør serveren
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flask --app flask_day_54.presentation.hello run
|
||||||
|
python -m flask_day_54.presentation.hello
|
||||||
|
```
|
||||||
|
|
||||||
|
Åbn `http://127.0.0.1:5000/` og stop serveren med `Ctrl+C`.
|
||||||
|
|
||||||
|
## Kør testene
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Hvad vi fik ud af det
|
||||||
|
|
||||||
|
- Én gentagelig måde at starte på fra en ren udgave af koden: et lokalt `.venv`, en opdateret pip og en redigerbar installation.
|
||||||
|
- To måder at starte Flask-serveren på og en testsuite, der kører uden en browser.
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Persediaan dan Jalankan
|
||||||
|
|
||||||
|
[English](Setup-and-Run) · [Dansk](Setup-and-Run-da) · **Bahasa Malaysia**
|
||||||
|
|
||||||
|
## Keperluan
|
||||||
|
|
||||||
|
Python 3.13 atau lebih baharu. Flask hanya diperlukan untuk kuliah web (tambahan `web` yang pilihan); pytest terdapat dalam tambahan `dev`.
|
||||||
|
|
||||||
|
## Cipta dan gunakan `.venv` setempat
|
||||||
|
|
||||||
|
Windows (PowerShell):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python -m venv .venv
|
||||||
|
.\.venv\Scripts\Activate.ps1
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
macOS dan Linux:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Jalankan pelayan
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flask --app flask_day_54.presentation.hello run
|
||||||
|
python -m flask_day_54.presentation.hello
|
||||||
|
```
|
||||||
|
|
||||||
|
Buka `http://127.0.0.1:5000/` dan hentikan pelayan dengan `Ctrl+C`.
|
||||||
|
|
||||||
|
## Jalankan ujian
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Apa yang kita peroleh
|
||||||
|
|
||||||
|
- Satu cara yang boleh diulang untuk bermula daripada salinan kerja yang bersih: `.venv` setempat, pip yang dikemas kini dan pemasangan boleh suntingan (editable).
|
||||||
|
- Dua cara untuk memulakan pelayan Flask, dan satu set ujian yang berjalan tanpa pelayar.
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Setup and Run
|
||||||
|
|
||||||
|
**English** · [Dansk](Setup-and-Run-da) · [Bahasa Malaysia](Setup-and-Run-ms)
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
Python 3.13 or newer. Flask is only needed for the web lectures (the optional `web` extra); pytest is in the `dev` extra.
|
||||||
|
|
||||||
|
## Create and use a local `.venv`
|
||||||
|
|
||||||
|
Windows (PowerShell):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
python -m venv .venv
|
||||||
|
.\.venv\Scripts\Activate.ps1
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
macOS and Linux:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -e ".[dev]"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run the server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
flask --app flask_day_54.presentation.hello run
|
||||||
|
python -m flask_day_54.presentation.hello
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `http://127.0.0.1:5000/` and stop the server with `Ctrl+C`.
|
||||||
|
|
||||||
|
## Run the tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m pytest
|
||||||
|
```
|
||||||
|
|
||||||
|
## What we gained
|
||||||
|
|
||||||
|
- One repeatable way to start from a clean checkout: a local `.venv`, an upgraded pip and an editable install.
|
||||||
|
- Two ways to start the Flask server, and a test suite that runs without a browser.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Flask Day 54 - Udemy 100 Days of Code. Code, tests and project documents: [repository](https://git.tirsystem.com/Tirsvad-Udemy-100-days-of-code/054-flask).
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
**Flask Day 54**
|
||||||
|
|
||||||
|
- [Home](Home)
|
||||||
|
- [Setup and Run](Setup-and-Run)
|
||||||
|
- [Lecture 1: Backend overview](Lecture-1-Backend-Overview)
|
||||||
|
- [Lecture 2: Hello Flask](Lecture-2-Hello-Flask)
|
||||||
|
- [Lecture 3: Command line](Lecture-3-Command-Line)
|
||||||
|
- [Lecture 4: __name__ and __main__](Lecture-4-Name-and-Main)
|
||||||
|
- [Lecture 5: First-class functions](Lecture-5-First-Class-Functions)
|
||||||
|
- [Lecture 6: Decorators](Lecture-6-Decorators)
|
||||||
|
|
||||||
|
**Languages**
|
||||||
|
|
||||||
|
- English: [Home](Home)
|
||||||
|
- Dansk: [Hjem](Home-da)
|
||||||
|
- Bahasa Melayu: [Utama](Home-ms)
|
||||||
@@ -26,7 +26,10 @@ def subtract(n1: float, n2: float) -> float:
|
|||||||
|
|
||||||
|
|
||||||
## @brief Apply a function passed as argument to two numbers.
|
## @brief Apply a function passed as argument to two numbers.
|
||||||
|
# @param n1 The first number.
|
||||||
|
# @param n2 The second number.
|
||||||
# @param func The function to call with `n1` and `n2`.
|
# @param func The function to call with `n1` and `n2`.
|
||||||
|
# @return The result of `func(n1, n2)`.
|
||||||
def calculate(n1: float, n2: float, func: Callable[[float, float], float]) -> float:
|
def calculate(n1: float, n2: float, func: Callable[[float, float], float]) -> float:
|
||||||
"""Return `func(n1, n2)`."""
|
"""Return `func(n1, n2)`."""
|
||||||
return func(n1, n2)
|
return func(n1, n2)
|
||||||
|
|||||||
Reference in new issue
Block a user