Foundations: Python, Git and toolsLoading progress…

A small API

Build a small HTTP service with clear boundaries, tests, logs and a repeatable runtime.

A handler is a small, honest function

An API endpoint is a function that receives a request and returns a response. Keep it to four jobs in this order: check the input, call the domain logic, store or fetch, report the outcome. The domain logic (like subtotal) stays a plain function from the previous lesson; the handler is the adapter around it.

def get_order(request):
    # request = {"method": "GET", "params": {"id": "1"}, "json": None}
    ...
    return 200, {"id": 1, "total": 370}      # (status, body)

Who is at fault decides the status

A good response says what happened. Follow a request through the stages below. The earliest stage that can reject it does, and each rejection has its own status. Try all nine scenarios.

POST /orders body: {"items":[{"qty":2,"price":125},{"qty":3,"price":40}]}

1. route: is there a handler for this method and path?passed
2. parse: is the body valid JSON?passed
3. validate: right shape and types?passed
4. handler: do the work, look things upstops here: 201
5. safety net: any unexpected exception
201 {"id":2,"total":370}

The status says who is at fault: 4xx means the caller can change something and retry, 5xx means the service failed. The crash scenario shows why the safety net must not copy the exception text into the body.

Each request stops at the first stage that cannot continue.
  • Malformed: the body is not JSON, or an id is not a number. The caller must send something different (400).
  • Invalid: well-formed JSON with unacceptable values (422 in this design).
  • Missing: everything is fine but nothing is there (404).
  • Our fault: something unexpected broke (500).

Predict first. An unexpected exception happens while handling a request. What should the response be?

Validation traps

In Python True is an instance of int, so isinstance(True, int) is True. A validator that only checks isinstance(qty, int) will accept true from JSON as a quantity of 1. Decide your rules explicitly, test them with bad values, and make sure nothing is stored before validation succeeds.

Chapter context

Engineering makes a program understandable when it fails or changes. Separate pure calculations from external I/O so behavior can be checked cheaply and errors can be connected to specific inputs.

Chapter reference: math, worked example & code

This section belongs to the whole chapter, so it is the same on every lesson in it and may cover a different lesson's topic. The code for the experiment you just ran is inside the experiment itself.

Math and notation

For money examples, use integer minor units rather than binary floating point. The subtotal is sum(quantity × unit_price), and the domain must specify rounding and tax rules before those operations are implemented.

Worked example

Two items cost 125 minor units each and three cost 40 each. The subtotal is 2×125 + 3×40 = 370. A test can exercise this calculation without starting an HTTP server. Request parsing and response formatting need separate checks.

Reference code

The following example uses the Python standard library and does not call a remote service.

def subtotal(items):
    return sum(quantity * price for quantity, price in items)
assert subtotal([(2, 125), (3, 40)]) == 370
assert subtotal([]) == 0

Python examples are provided for study and local execution; this page does not execute Python.

Common mistakes

Test coverage counts executed lines, not verified requirements. A container does not turn an unsafe operation into a safe one. JSON validity alone does not establish application validity.