Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 5 additions & 19 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,24 +1,10 @@
# Task 4: Write a cache-friendly Dockerfile.
#
# Requirements (in order):
# 1. Use python:3.11-slim as the base image.
# 2. Copy requirements.txt BEFORE copying source code.
# 3. Install dependencies from requirements.txt.
# 4. Copy src/ into the image.
# 5. Set the CMD to run the pipeline: python -m src.pipeline
#
# Replace each TODO comment with the correct Dockerfile instruction.

# TODO: set the base image
FROM TODO
FROM python:3.11-slim

WORKDIR /app

# TODO: copy requirements.txt (before source — this keeps the install layer cached)

# TODO: install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# TODO: copy source code
COPY . .

# TODO: set the command that runs when the container starts
CMD ["TODO"]
CMD ["python", "-m", "src.pipeline"]
43 changes: 30 additions & 13 deletions src/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""

import logging
import os
from pathlib import Path

logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
Expand All @@ -21,40 +22,56 @@ def get_config() -> dict:

Required variable: API_KEY
Optional variable: OUTPUT_DIR (default "output")

Raise RuntimeError with a clear message if a required variable is missing.
"""
raise NotImplementedError("Task 5: read API_KEY and OUTPUT_DIR from the environment")
api_key = os.getenv("API_KEY")

if not api_key:
raise RuntimeError("API_KEY is missing")

output_dir = os.getenv("OUTPUT_DIR", "output")

return {
"api_key": api_key,
"output_dir": output_dir,
}


def fetch_data(api_key: str) -> list[dict]:
"""
Simulate fetching records from an external API.

Return a list of at least one dict representing a record.
In a real pipeline you would call requests.get(...) here.
"""
raise NotImplementedError("Task 1: return at least one sample record")
return [
{"id": 1, "name": "Muna", "city": "Amsterdam"},
{"id": 2, "name": "Ali", "city": "Rotterdam"},
]


def save_results(records: list[dict], output_dir: Path) -> None:
"""
Write each record as a line to output_dir/results.txt.

Create output_dir if it does not exist.
Log the number of records written.
Write each record as a line to output_dir/results.txt
"""
raise NotImplementedError("Task 1: write records to output_dir/results.txt")
output_dir.mkdir(parents=True, exist_ok=True)

file_path = output_dir / "results.txt"

with open(file_path, "w", encoding="utf-8") as f:
for record in records:
f.write(f"{record}\n")

logger.info("%s records written", len(records))


def run() -> None:
config = get_config()
logger.info("starting pipeline")

records = fetch_data(config["api_key"])
output_dir = Path(config["output_dir"])

save_results(records, output_dir)

logger.info("pipeline complete")


if __name__ == "__main__":
run()
run()
Loading