Paper 2 Lab Skills Answers

These answers correspond to Paper 2 Lab Skills Drills.

Verification note: every Python code block in this answer file has been executed locally.

Answer 1: Folder Setup

Model answer:

def required_paths():
    return ["app.py", "templates/books.html", "static/style.css", "data/books.csv", "library.db"]
 
 
print(required_paths())

Expected output:

['app.py', 'templates/books.html', 'static/style.css', 'data/books.csv', 'library.db']

Mark points:

  • includes app.py;
  • includes the template path;
  • includes the static path;
  • includes the CSV data path;
  • includes the database file.

Common weak answer:

  • listing only folders and not the actual required files.

Answer 2: Smoke Test

Model answer:

def smoke_test():
    return "APP STARTED"
 
 
print(smoke_test())

Expected output:

APP STARTED

Mark points:

  • defines a small runnable function;
  • returns a known message;
  • prints the exact smoke-test output.

Common weak answer:

  • starting with a large feature before proving the script runs.

Answer 3: Function Test

Model answer:

def valid_category(category):
    return category in ("Books", "Stationery")
 
 
def run_validation_tests():
    assert valid_category("Books") == True
    assert valid_category("Stationery") == True
    assert valid_category("Food") == False
    return "TESTS PASSED"
 
 
print(run_validation_tests())

Expected output:

TESTS PASSED

Mark points:

  • implements the validation rule;
  • tests "Books";
  • tests "Stationery";
  • tests invalid "Food";
  • returns the pass message only after assertions.

Common weak answer:

  • testing only valid categories.

Answer 4: File Inspection

Model answer:

import csv
 
 
def first_csv_row(filename):
    with open(filename, "r", encoding="utf-8", newline="") as f:
        reader = csv.DictReader(f)
        return next(reader)
 
 
# Test setup: create the supplied CSV file.
with open("products.csv", "w", encoding="utf-8", newline="") as f:
    f.write("product_id,name,price,category\n")
    f.write("P01,Pen,1.50,Stationery\n")
 
print(first_csv_row("products.csv"))

Expected output:

{'product_id': 'P01', 'name': 'Pen', 'price': '1.50', 'category': 'Stationery'}

Mark points:

  • opens the CSV file;
  • uses the header row;
  • reads the first data row;
  • returns a dictionary with correct keys;
  • returns the exact first record.

Common weak answer:

  • hard-coding guessed field names without reading the header.

Answer 5: JSON Inspection

Model answer:

import json
 
 
def json_summary(filename):
    with open(filename, "r", encoding="utf-8") as f:
        data = json.load(f)
    return (type(data).__name__, data[0])
 
 
# Test setup: create the supplied JSON file.
with open("items.json", "w", encoding="utf-8") as f:
    json.dump([{"id": "B01", "title": "Algorithms"}, {"id": "B02", "title": "Networks"}], f)
 
print(json_summary("items.json"))

Expected output:

('list', {'id': 'B01', 'title': 'Algorithms'})

Mark points:

  • imports/uses json;
  • opens the JSON file;
  • loads JSON into Python data;
  • reports top-level type name;
  • returns the first record.

Common weak answer:

  • assuming JSON is always a dictionary. The supplied file is a list.

Answer 6: DB Path Check

Model answer:

from pathlib import Path
 
 
def db_path(filename):
    return str(Path(filename).resolve())
 
 
print(db_path("library.db").endswith("library.db"))

Expected output:

True

Mark points:

  • uses Path;
  • resolves the absolute path;
  • keeps the filename library.db;
  • prints a checkable result.

Common weak answer:

  • printing only "library.db" without proving which directory is being used.

Answer 7: Route Check

This assumes Flask is available in the lab environment.

Model answer:

from flask import Flask
 
 
app = Flask(__name__)
 
 
@app.route("/")
def home():
    return "OK"
 
 
client = app.test_client()
response = client.get("/")
print(response.get_data(as_text=True))

Expected output:

OK

Mark points:

  • creates a Flask app;
  • defines route /;
  • returns OK;
  • uses a test client or equivalent local check;
  • prints the response text.

Common weak answer:

  • defining the route but never testing that it responds.

Answer 8: Submission Script

Model answer:

import tempfile
from pathlib import Path
 
 
def missing_files(required):
    missing = []
    for path in required:
        if not Path(path).exists():
            missing.append(path)
    return missing
 
 
with tempfile.TemporaryDirectory() as folder:
    task = Path(folder)
 
    # Test setup: create only the files stated in the question.
    (task / "templates").mkdir()
    (task / "app.py").write_text("")
    (task / "templates/books.html").write_text("")
 
    required = ["app.py", "templates/books.html", "static/style.css", "data/books.csv"]
    required = [str(task / path) for path in required]
    missing = missing_files(required)
    print([Path(path).relative_to(task).as_posix() for path in missing])

Expected output:

['static/style.css', 'data/books.csv']

Mark points:

  • accepts a required-path list;
  • loops through required paths;
  • checks existence;
  • appends missing paths;
  • returns both missing paths;
  • does not falsely report existing files as missing.

Common weak answer:

  • checking only app.py, even though templates and data files are also required.

Answer 9: Debug Print

Model answer:

def debug_value(value):
    return repr(value)
 
 
print(debug_value("  Books  "))

Expected output:

'  Books  '

Mark points:

  • uses repr;
  • preserves visible quotes/spaces;
  • prints the exact debug representation.

Common weak answer:

  • using ordinary print(value), which can hide leading and trailing spaces.

Answer 10: Final Test Plan

Model answer:

def final_dry_run_report(checks):
    for name in checks:
        if not checks[name]:
            return "FIX BEFORE SUBMISSION"
    return "READY"
 
 
print(final_dry_run_report({"starts": True, "route_ok": True, "db_ok": True}))
print(final_dry_run_report({"starts": True, "route_ok": False, "db_ok": True}))

Expected output:

READY
FIX BEFORE SUBMISSION

Mark points:

  • checks every item in the dry-run dictionary;
  • returns READY only when all values are true;
  • detects a failed route check;
  • returns the fix-before-submission message;
  • produces both expected outputs;
  • keeps the final decision clear.

Common weak answer:

  • returning READY if only the app starts, while route or database checks may still fail.