Typorithm · medium

Parsing, validation and narrow exception handling

pythonscriptingdata-boundariesindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

Parsing, validation and narrow exception handling

0%

Concept and contract

Convert only the representations the contract accepts and report invalid data without inventing success.

A parser turns an accepted external representation into a domain value. The worked function accepts exact integers and strings understood by int, then requires the result to be between one and three. It rejects booleans and floats rather than silently treating them as ordinary integer representations.

This is intentionally a different boundary from the earlier classifier, which rejected every string. Allowing conversion is an explicit new requirement, not a reason to weaken all later numeric computations. Whitespace and a sign in an accepted integer string follow the documented int conversion semantics.

Mechanism and worked example

The function separates representation choice, conversion and range validation.

The function separates representation choice, conversion and range validation. Only the string-conversion branch catches ValueError and raises a domain message with the original exception as its cause. Unsupported types and out-of-range values also produce ValueError under the chosen public error contract.

An exception cause preserves useful diagnostic context without turning invalid input into a default success value. A caller can catch the documented error at an appropriate interface. The parser itself should not print an error and then quietly return a valid-looking page limit.

Complete worked example

python

def parse_limit(raw):
    if type(raw) is int:
        value = raw
    elif isinstance(raw, str):
        try:
            value = int(raw)
        except ValueError as error:
            raise ValueError("Expected an integer") from error
    else:
        raise ValueError("Unsupported representation")
    if not 1 <= value <= 3:
        raise ValueError("Outside range")
    return value
Reasoning
Representation, conversion and inclusive range checks have separate responsibilities.

Counterexamples and common mistakes

The counterexample catches every exception, returns one on failure and clamps all other results into range.

The counterexample catches every exception, returns one on failure and clamps all other results into range. That hides invalid strings, admits booleans and truncates fractions. It can make a broken input look like a successful request, preventing the caller from explaining or correcting the problem.

Do not broadly catch errors merely to keep a program green. Catch the failure you expect at the conversion boundary and let unexpected programming errors remain visible. A fallback is appropriate only when the product contract actually authorizes it and exposes its meaning.

Counterexample: a plausible but incorrect implementation

python

def parse_limit(raw):
    try:
        value = int(raw)
    except Exception:
        return 1
    return max(1, min(3, value))
Reasoning
A broad fallback and clamp convert invalid input into invented success.

Independent practice: small Python task

Adapt the same parser to inclusive integers zero through five, keeping the accepted representations and ValueError policy.

Adapt the same parser to inclusive integers zero through five, keeping the accepted representations and ValueError policy. Predict valid zero from either an exact integer or the string zero. Reject negative one, six, booleans, fractions, None and nonnumeric text.

Change only the range after the representation boundary. The first step is preserving exact-type and string branches; the second is updating the bounds. Do not use a truthiness check that would reject the newly valid zero or a clamp that would fabricate a permitted result.

Step 1: Keep the exact-int and string-conversion branches. Step 2: Apply inclusive zero and five bounds after conversion.

Practice starter: solve before reading the solution

python

def parse_limit(raw):
    # Keep strict representations, but accept zero through five.
    raise NotImplementedError
Reasoning
Preserve the boundary and change only the permitted numeric interval.
  • Hint 1: A boolean must still be rejected.
  • Hint 2: Do not clamp invalid values or treat zero as missing.

Solution, tests and trade-offs

The solution preserves the narrow conversion error handling and changes the domain range.

The solution preserves the narrow conversion error handling and changes the domain range. The zero cases demonstrate that successful conversion and valid magnitude are separate decisions. The tests require the declared error type for invalid inputs rather than accepting any crash as adequate validation.

This lab accepts the normal int string grammar instead of claiming an ASCII-only protocol. A real wire format may need a narrower character policy, maximum input length or locale rule. Those are separate boundary requirements that should be stated and tested explicitly.

Practice solution and acceptance checks

python

def parse_limit(raw):
    if type(raw) is int:
        value = raw
    elif isinstance(raw, str):
        try:
            value = int(raw)
        except ValueError as error:
            raise ValueError("Expected an integer") from error
    else:
        raise ValueError("Unsupported representation")
    if not 0 <= value <= 5:
        raise ValueError("Outside range")
    return value
Reasoning
Invalid inputs must raise ValueError; zero is valid under the revised interval.

Interview reasoning and next step

In an interview, distinguish parsing from validation and an expected user-input error from an unexpected programming exception.

In an interview, distinguish parsing from validation and an expected user-input error from an unexpected programming exception. Explain what is accepted, what is converted, what is rejected and which error the caller can rely on. That is more useful than a universal recommendation to catch everything.

Next, examine lazy iteration. A generator can delay when an error or side effect occurs, so understanding the boundary between constructing a computation and consuming it is important for both correctness and diagnostics.

Optional stretch — after the core task works: Add an explicit ASCII-only protocol rule and compare it with the broader built-in int string grammar.

Computer practice: https://applydjinn.com/typorithm/python-lab-20261105.zip. Run verify.py with your selected Python interpreter, then complete an exercise and check it with --practice followed by the lesson id. The lab uses only the standard library and disposable local fixtures; it never connects to the production database or company feeds.

Convert only the representations the contract accepts and report invalid data without inventing success.