When a learner can reproduce a familiar example but a small variation causes confusion, the problem is usually an incomplete model rather than a lack of effort. The fastest useful response is to expose the hidden state and test one boundary at a time.
Python contextlib.aclosing wraps an object that provides an awaitable aclose() method so async with can await that cleanup on every exit path. It is especially useful when an async generator may stop early: its finalisation then runs in the same surrounding asynchronous context as its iteration. Mastery means identifying ownership, preserving the original exception when appropriate, testing break and cancellation paths, and not confusing asynchronous finalisation with ordinary closing(). This guide begins with that mechanism, then develops it through worked traces, deliberate mistakes, explained practice and transfer decisions.
The aim is independent reasoning. A learner should be able to predict behaviour, locate the earliest wrong assumption, use a safe diagnostic procedure and defend a design choice in a new project.
Punggol families can use the guide in short sessions around homework, CCAs and rest. The activities are proposed learning exercises, not claims about a physical branch, timetable, class size, fee, school relationship or guaranteed result.
Use disposable data and repositories, preserve backups, and check version-sensitive details against the official source. Current documentation settles a technical contract; observation and explanation turn that contract into usable knowledge.
Find your next learning step
Choose the route that matches the present difficulty. Use the complete index for a systematic course.
Build the model
Chapters 1-4 . Begin here, then continue after the learner can predict, verify and explain.
Use the core tools
Chapters 5-8 . Begin here, then continue after the learner can predict, verify and explain.
Handle boundaries
Chapters 9-12 . Begin here, then continue after the learner can predict, verify and explain.
Debug and verify
Chapters 13-16 . Begin here, then continue after the learner can predict, verify and explain.
Transfer with judgment
Chapters 17-20 . Begin here, then continue after the learner can predict, verify and explain.
Open the full chapter index . Jump to capstone practice . Use the How Studying Works hub . Read the official documentation
Complete chapter index
Chapters 1-4 . Build the model
Chapters 5-8 . Use the core tools
Chapters 9-12 . Handle boundaries
Chapters 13-16 . Debug and verify
Chapters 17-20 . Transfer with judgment
The helper yields the supplied object and awaits its aclose method in a finally clause when the async-with suite exits. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is assuming it invents cleanup for objects that have no aclose contract. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Trace entry, use and awaited exit as three separate events.
For the aclosing turns aclose into an async context chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on assuming it invents cleanup for objects that have no aclose contract. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
from contextlib import aclosing
async with aclosing(stream) as rows:
async for row in rows:
print(row)Explained result. The bound value is the original stream; aclose is awaited at exit. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: homework stream. Predict the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The helper yields the supplied object and awaits its aclose method in a finally clause when the async-with suite exits.” Apply this procedure: Trace entry, use and awaited exit as three separate events. The expected mechanism is: The bound value is the original stream; aclose is awaited at exit. For the homework stream, add one near-miss that exposes assuming it invents cleanup for objects that have no aclose contract. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: school portal. Contrast the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The helper yields the supplied object and awaits its aclose method in a finally clause when the async-with suite exits.” Apply this procedure: Trace entry, use and awaited exit as three separate events. The expected mechanism is: The bound value is the original stream; aclose is awaited at exit. For the school portal, add one near-miss that exposes assuming it invents cleanup for objects that have no aclose contract. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: CCA bot. Stress-test the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The helper yields the supplied object and awaits its aclose method in a finally clause when the async-with suite exits.” Apply this procedure: Trace entry, use and awaited exit as three separate events. The expected mechanism is: The bound value is the original stream; aclose is awaited at exit. For the CCA bot, add one near-miss that exposes assuming it invents cleanup for objects that have no aclose contract. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: library search. Explain the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The helper yields the supplied object and awaits its aclose method in a finally clause when the async-with suite exits.” Apply this procedure: Trace entry, use and awaited exit as three separate events. The expected mechanism is: The bound value is the original stream; aclose is awaited at exit. For the library search, add one near-miss that exposes assuming it invents cleanup for objects that have no aclose contract. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers assuming it invents cleanup for objects that have no aclose contract.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Trace entry, use and awaited exit as three separate events.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from aclosing turns aclose into an async context?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing assuming it invents cleanup for objects that have no aclose contract be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny cancellation lab with observing finalisation when a task is cancelled. Include one ordinary case, one boundary and one deliberate failure caused by assuming it invents cleanup for objects that have no aclose contract. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: The helper yields the supplied object and awaits its aclose method in a finally clause when the async-with suite exits. It shows a trace, not only a final value. The ordinary case should demonstrate “The bound value is the original stream; aclose is awaited at exit.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Trace entry, use and awaited exit as three separate events. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For aclosing turns aclose into an async context, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
The exit path may await work, unlike contextlib.closing, whose synchronous exit calls close immediately. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is using closing around an async generator and leaving a coroutine unawaited. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Classify the cleanup method as close or aclose before choosing the helper.
For the It is designed for asynchronous finalisation chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on using closing around an async generator and leaving a coroutine unawaited. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
from contextlib import aclosing, closing
print(aclosing, closing)Explained result. The two helpers express different protocols and cannot be substituted mechanically. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: CCA bot. Contrast the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The exit path may await work, unlike contextlib.closing, whose synchronous exit calls close immediately.” Apply this procedure: Classify the cleanup method as close or aclose before choosing the helper. The expected mechanism is: The two helpers express different protocols and cannot be substituted mechanically. For the CCA bot, add one near-miss that exposes using closing around an async generator and leaving a coroutine unawaited. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: library search. Stress-test the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The exit path may await work, unlike contextlib.closing, whose synchronous exit calls close immediately.” Apply this procedure: Classify the cleanup method as close or aclose before choosing the helper. The expected mechanism is: The two helpers express different protocols and cannot be substituted mechanically. For the library search, add one near-miss that exposes using closing around an async generator and leaving a coroutine unawaited. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: context tracking. Explain the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The exit path may await work, unlike contextlib.closing, whose synchronous exit calls close immediately.” Apply this procedure: Classify the cleanup method as close or aclose before choosing the helper. The expected mechanism is: The two helpers express different protocols and cannot be substituted mechanically. For the context tracking, add one near-miss that exposes using closing around an async generator and leaving a coroutine unawaited. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: cancellation lab. Transfer the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The exit path may await work, unlike contextlib.closing, whose synchronous exit calls close immediately.” Apply this procedure: Classify the cleanup method as close or aclose before choosing the helper. The expected mechanism is: The two helpers express different protocols and cannot be substituted mechanically. For the cancellation lab, add one near-miss that exposes using closing around an async generator and leaving a coroutine unawaited. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers using closing around an async generator and leaving a coroutine unawaited.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Classify the cleanup method as close or aclose before choosing the helper.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from It is designed for asynchronous finalisation?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing using closing around an async generator and leaving a coroutine unawaited be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny test laboratory with covering normal, break, error and cleanup-failure paths. Include one ordinary case, one boundary and one deliberate failure caused by using closing around an async generator and leaving a coroutine unawaited. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: The exit path may await work, unlike contextlib.closing, whose synchronous exit calls close immediately. It shows a trace, not only a final value. The ordinary case should demonstrate “The two helpers express different protocols and cannot be substituted mechanically.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Classify the cleanup method as close or aclose before choosing the helper. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For It is designed for asynchronous finalisation, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Breaking an async-for loop can leave generator finalisation to a later mechanism; aclosing makes the owning lexical scope await it now. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is testing only full exhaustion and missing the early-stop path. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Break after one item and record the generator finaliser before the scope continues.
For the Early break is the central use case chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on testing only full exhaustion and missing the early-stop path. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
async with aclosing(numbers()) as values:
async for value in values:
breakExplained result. The context exit awaits values.aclose() even though iteration did not exhaust the generator. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: context tracking. Stress-test the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Breaking an async-for loop can leave generator finalisation to a later mechanism; aclosing makes the owning lexical scope await it now.” Apply this procedure: Break after one item and record the generator finaliser before the scope continues. The expected mechanism is: The context exit awaits values.aclose() even though iteration did not exhaust the generator. For the context tracking, add one near-miss that exposes testing only full exhaustion and missing the early-stop path. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: cancellation lab. Explain the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Breaking an async-for loop can leave generator finalisation to a later mechanism; aclosing makes the owning lexical scope await it now.” Apply this procedure: Break after one item and record the generator finaliser before the scope continues. The expected mechanism is: The context exit awaits values.aclose() even though iteration did not exhaust the generator. For the cancellation lab, add one near-miss that exposes testing only full exhaustion and missing the early-stop path. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: test laboratory. Transfer the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Breaking an async-for loop can leave generator finalisation to a later mechanism; aclosing makes the owning lexical scope await it now.” Apply this procedure: Break after one item and record the generator finaliser before the scope continues. The expected mechanism is: The context exit awaits values.aclose() even though iteration did not exhaust the generator. For the test laboratory, add one near-miss that exposes testing only full exhaustion and missing the early-stop path. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: design review. Predict the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Breaking an async-for loop can leave generator finalisation to a later mechanism; aclosing makes the owning lexical scope await it now.” Apply this procedure: Break after one item and record the generator finaliser before the scope continues. The expected mechanism is: The context exit awaits values.aclose() even though iteration did not exhaust the generator. For the design review, add one near-miss that exposes testing only full exhaustion and missing the early-stop path. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers testing only full exhaustion and missing the early-stop path.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Break after one item and record the generator finaliser before the scope continues.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Early break is the central use case?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing testing only full exhaustion and missing the early-stop path be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny design review with choosing aclosing, async context managers, try-finally or an owning API. Include one ordinary case, one boundary and one deliberate failure caused by testing only full exhaustion and missing the early-stop path. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Breaking an async-for loop can leave generator finalisation to a later mechanism; aclosing makes the owning lexical scope await it now. It shows a trace, not only a final value. The ordinary case should demonstrate “The context exit awaits values.aclose() even though iteration did not exhaust the generator.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Break after one item and record the generator finaliser before the scope continues. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Early break is the central use case, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
aclosing follows a small protocol: the wrapped object needs an aclose attribute returning an awaitable. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is assuming any async iterable automatically has aclose. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Inspect the concrete object rather than only its AsyncIterable annotation.
For the The object must implement aclose chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on assuming any async iterable automatically has aclose. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
print(hasattr(async_generator_object, 'aclose'))Explained result. An async generator object has aclose; an arbitrary asynchronous iterator may not. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: test laboratory. Explain the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “aclosing follows a small protocol: the wrapped object needs an aclose attribute returning an awaitable.” Apply this procedure: Inspect the concrete object rather than only its AsyncIterable annotation. The expected mechanism is: An async generator object has aclose; an arbitrary asynchronous iterator may not. For the test laboratory, add one near-miss that exposes assuming any async iterable automatically has aclose. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: design review. Transfer the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “aclosing follows a small protocol: the wrapped object needs an aclose attribute returning an awaitable.” Apply this procedure: Inspect the concrete object rather than only its AsyncIterable annotation. The expected mechanism is: An async generator object has aclose; an arbitrary asynchronous iterator may not. For the design review, add one near-miss that exposes assuming any async iterable automatically has aclose. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: homework stream. Predict the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “aclosing follows a small protocol: the wrapped object needs an aclose attribute returning an awaitable.” Apply this procedure: Inspect the concrete object rather than only its AsyncIterable annotation. The expected mechanism is: An async generator object has aclose; an arbitrary asynchronous iterator may not. For the homework stream, add one near-miss that exposes assuming any async iterable automatically has aclose. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: school portal. Contrast the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “aclosing follows a small protocol: the wrapped object needs an aclose attribute returning an awaitable.” Apply this procedure: Inspect the concrete object rather than only its AsyncIterable annotation. The expected mechanism is: An async generator object has aclose; an arbitrary asynchronous iterator may not. For the school portal, add one near-miss that exposes assuming any async iterable automatically has aclose. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers assuming any async iterable automatically has aclose.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Inspect the concrete object rather than only its AsyncIterable annotation.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from The object must implement aclose?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing assuming any async iterable automatically has aclose be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny homework stream with stopping an async sequence after the first matching exercise. Include one ordinary case, one boundary and one deliberate failure caused by assuming any async iterable automatically has aclose. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: aclosing follows a small protocol: the wrapped object needs an aclose attribute returning an awaitable. It shows a trace, not only a final value. The ordinary case should demonstrate “An async generator object has aclose; an arbitrary asynchronous iterator may not.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Inspect the concrete object rather than only its AsyncIterable annotation. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For The object must implement aclose, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
The exit method executes await thing.aclose(), so a synchronous return value violates the contract. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is defining a normal aclose method that returns None. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Call and inspect the result in a disposable protocol test.
For the aclose must be awaitable chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on defining a normal aclose method that returns None. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
result = resource.aclose()
print(hasattr(result, '__await__'))Explained result. A conforming result is awaitable; None would cause a TypeError when awaited. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: homework stream. Transfer the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The exit method executes await thing.aclose(), so a synchronous return value violates the contract.” Apply this procedure: Call and inspect the result in a disposable protocol test. The expected mechanism is: A conforming result is awaitable; None would cause a TypeError when awaited. For the homework stream, add one near-miss that exposes defining a normal aclose method that returns None. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: school portal. Predict the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The exit method executes await thing.aclose(), so a synchronous return value violates the contract.” Apply this procedure: Call and inspect the result in a disposable protocol test. The expected mechanism is: A conforming result is awaitable; None would cause a TypeError when awaited. For the school portal, add one near-miss that exposes defining a normal aclose method that returns None. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: CCA bot. Contrast the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The exit method executes await thing.aclose(), so a synchronous return value violates the contract.” Apply this procedure: Call and inspect the result in a disposable protocol test. The expected mechanism is: A conforming result is awaitable; None would cause a TypeError when awaited. For the CCA bot, add one near-miss that exposes defining a normal aclose method that returns None. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: library search. Stress-test the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The exit method executes await thing.aclose(), so a synchronous return value violates the contract.” Apply this procedure: Call and inspect the result in a disposable protocol test. The expected mechanism is: A conforming result is awaitable; None would cause a TypeError when awaited. For the library search, add one near-miss that exposes defining a normal aclose method that returns None. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers defining a normal aclose method that returns None.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Call and inspect the result in a disposable protocol test.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from aclose must be awaitable?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing defining a normal aclose method that returns None be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny school portal with closing a paginated async feed after early success. Include one ordinary case, one boundary and one deliberate failure caused by defining a normal aclose method that returns None. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: The exit method executes await thing.aclose(), so a synchronous return value violates the contract. It shows a trace, not only a final value. The ordinary case should demonstrate “A conforming result is awaitable; None would cause a TypeError when awaited.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Call and inspect the result in a disposable protocol test. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For aclose must be awaitable, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
aclosing does not proxy iteration or create a replacement stream; __aenter__ returns the supplied thing. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is looking for wrapper-specific iteration methods. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Compare identity inside the context.
For the The yielded value is the original object chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on looking for wrapper-specific iteration methods. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
async with aclosing(resource) as entered:
assert entered is resourceExplained result. The assertion passes because the helper manages, rather than replaces, the object. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: CCA bot. Predict the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “aclosing does not proxy iteration or create a replacement stream; __aenter__ returns the supplied thing.” Apply this procedure: Compare identity inside the context. The expected mechanism is: The assertion passes because the helper manages, rather than replaces, the object. For the CCA bot, add one near-miss that exposes looking for wrapper-specific iteration methods. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: library search. Contrast the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “aclosing does not proxy iteration or create a replacement stream; __aenter__ returns the supplied thing.” Apply this procedure: Compare identity inside the context. The expected mechanism is: The assertion passes because the helper manages, rather than replaces, the object. For the library search, add one near-miss that exposes looking for wrapper-specific iteration methods. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: context tracking. Stress-test the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “aclosing does not proxy iteration or create a replacement stream; __aenter__ returns the supplied thing.” Apply this procedure: Compare identity inside the context. The expected mechanism is: The assertion passes because the helper manages, rather than replaces, the object. For the context tracking, add one near-miss that exposes looking for wrapper-specific iteration methods. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: cancellation lab. Explain the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “aclosing does not proxy iteration or create a replacement stream; __aenter__ returns the supplied thing.” Apply this procedure: Compare identity inside the context. The expected mechanism is: The assertion passes because the helper manages, rather than replaces, the object. For the cancellation lab, add one near-miss that exposes looking for wrapper-specific iteration methods. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers looking for wrapper-specific iteration methods.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Compare identity inside the context.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from The yielded value is the original object?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing looking for wrapper-specific iteration methods be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny CCA bot with releasing a subscription when a command ends. Include one ordinary case, one boundary and one deliberate failure caused by looking for wrapper-specific iteration methods. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: aclosing does not proxy iteration or create a replacement stream; __aenter__ returns the supplied thing. It shows a trace, not only a final value. The ordinary case should demonstrate “The assertion passes because the helper manages, rather than replaces, the object.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Compare identity inside the context. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For The yielded value is the original object, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Even when the loop finishes normally, the surrounding context exits and invokes the deterministic aclose contract. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is assuming aclose matters only after break. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Count cleanup calls during full exhaustion.
For the Normal exhaustion still closes once chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on assuming aclose matters only after break. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
events=[]
# generator finally appends 'closed'; exhaust it inside aclosingExplained result. The finalisation path is observable once and should be tested for idempotent ownership. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: context tracking. Contrast the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Even when the loop finishes normally, the surrounding context exits and invokes the deterministic aclose contract.” Apply this procedure: Count cleanup calls during full exhaustion. The expected mechanism is: The finalisation path is observable once and should be tested for idempotent ownership. For the context tracking, add one near-miss that exposes assuming aclose matters only after break. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: cancellation lab. Stress-test the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Even when the loop finishes normally, the surrounding context exits and invokes the deterministic aclose contract.” Apply this procedure: Count cleanup calls during full exhaustion. The expected mechanism is: The finalisation path is observable once and should be tested for idempotent ownership. For the cancellation lab, add one near-miss that exposes assuming aclose matters only after break. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: test laboratory. Explain the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Even when the loop finishes normally, the surrounding context exits and invokes the deterministic aclose contract.” Apply this procedure: Count cleanup calls during full exhaustion. The expected mechanism is: The finalisation path is observable once and should be tested for idempotent ownership. For the test laboratory, add one near-miss that exposes assuming aclose matters only after break. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: design review. Transfer the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Even when the loop finishes normally, the surrounding context exits and invokes the deterministic aclose contract.” Apply this procedure: Count cleanup calls during full exhaustion. The expected mechanism is: The finalisation path is observable once and should be tested for idempotent ownership. For the design review, add one near-miss that exposes assuming aclose matters only after break. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers assuming aclose matters only after break.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Count cleanup calls during full exhaustion.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Normal exhaustion still closes once?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing assuming aclose matters only after break be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny library search with ending an async generator after one useful record. Include one ordinary case, one boundary and one deliberate failure caused by assuming aclose matters only after break. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Even when the loop finishes normally, the surrounding context exits and invokes the deterministic aclose contract. It shows a trace, not only a final value. The ordinary case should demonstrate “The finalisation path is observable once and should be tested for idempotent ownership.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Count cleanup calls during full exhaustion. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Normal exhaustion still closes once, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
A finally-based context manager invokes aclose when iteration, loop-body code or later statements raise. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is adding cleanup only after the happy-path loop. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Raise deliberately inside the scope and assert that finalisation ran.
For the Exceptions from the suite trigger cleanup chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on adding cleanup only after the happy-path loop. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
async with aclosing(numbers()) as values:
async for value in values:
raise RuntimeError('lesson failed')Explained result. aclose is awaited during unwinding before the RuntimeError leaves the async-with statement. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: test laboratory. Stress-test the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A finally-based context manager invokes aclose when iteration, loop-body code or later statements raise.” Apply this procedure: Raise deliberately inside the scope and assert that finalisation ran. The expected mechanism is: aclose is awaited during unwinding before the RuntimeError leaves the async-with statement. For the test laboratory, add one near-miss that exposes adding cleanup only after the happy-path loop. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: design review. Explain the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A finally-based context manager invokes aclose when iteration, loop-body code or later statements raise.” Apply this procedure: Raise deliberately inside the scope and assert that finalisation ran. The expected mechanism is: aclose is awaited during unwinding before the RuntimeError leaves the async-with statement. For the design review, add one near-miss that exposes adding cleanup only after the happy-path loop. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: homework stream. Transfer the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A finally-based context manager invokes aclose when iteration, loop-body code or later statements raise.” Apply this procedure: Raise deliberately inside the scope and assert that finalisation ran. The expected mechanism is: aclose is awaited during unwinding before the RuntimeError leaves the async-with statement. For the homework stream, add one near-miss that exposes adding cleanup only after the happy-path loop. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: school portal. Predict the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A finally-based context manager invokes aclose when iteration, loop-body code or later statements raise.” Apply this procedure: Raise deliberately inside the scope and assert that finalisation ran. The expected mechanism is: aclose is awaited during unwinding before the RuntimeError leaves the async-with statement. For the school portal, add one near-miss that exposes adding cleanup only after the happy-path loop. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers adding cleanup only after the happy-path loop.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Raise deliberately inside the scope and assert that finalisation ran.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Exceptions from the suite trigger cleanup?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing adding cleanup only after the happy-path loop be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny context tracking with checking that cleanup sees the same context-variable state. Include one ordinary case, one boundary and one deliberate failure caused by adding cleanup only after the happy-path loop. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: A finally-based context manager invokes aclose when iteration, loop-body code or later statements raise. It shows a trace, not only a final value. The ordinary case should demonstrate “aclose is awaited during unwinding before the RuntimeError leaves the async-with statement.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Raise deliberately inside the scope and assert that finalisation ran. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Exceptions from the suite trigger cleanup, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
The helper has no truthy __aexit__ decision that converts ordinary suite failures into success. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is expecting cleanup to swallow the original error. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Catch outside the async-with block and inspect the exception type.
For the aclosing does not suppress the body exception chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on expecting cleanup to swallow the original error. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
try:
async with aclosing(numbers()) as values:
raise ValueError('bad row')
except ValueError:
print('preserved')Explained result. The ValueError remains visible after cleanup completes. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: homework stream. Explain the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The helper has no truthy __aexit__ decision that converts ordinary suite failures into success.” Apply this procedure: Catch outside the async-with block and inspect the exception type. The expected mechanism is: The ValueError remains visible after cleanup completes. For the homework stream, add one near-miss that exposes expecting cleanup to swallow the original error. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: school portal. Transfer the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The helper has no truthy __aexit__ decision that converts ordinary suite failures into success.” Apply this procedure: Catch outside the async-with block and inspect the exception type. The expected mechanism is: The ValueError remains visible after cleanup completes. For the school portal, add one near-miss that exposes expecting cleanup to swallow the original error. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: CCA bot. Predict the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The helper has no truthy __aexit__ decision that converts ordinary suite failures into success.” Apply this procedure: Catch outside the async-with block and inspect the exception type. The expected mechanism is: The ValueError remains visible after cleanup completes. For the CCA bot, add one near-miss that exposes expecting cleanup to swallow the original error. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: library search. Contrast the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The helper has no truthy __aexit__ decision that converts ordinary suite failures into success.” Apply this procedure: Catch outside the async-with block and inspect the exception type. The expected mechanism is: The ValueError remains visible after cleanup completes. For the library search, add one near-miss that exposes expecting cleanup to swallow the original error. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers expecting cleanup to swallow the original error.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Catch outside the async-with block and inspect the exception type.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from aclosing does not suppress the body exception?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing expecting cleanup to swallow the original error be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny cancellation lab with observing finalisation when a task is cancelled. Include one ordinary case, one boundary and one deliberate failure caused by expecting cleanup to swallow the original error. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: The helper has no truthy __aexit__ decision that converts ordinary suite failures into success. It shows a trace, not only a final value. The ordinary case should demonstrate “The ValueError remains visible after cleanup completes.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Catch outside the async-with block and inspect the exception type. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For aclosing does not suppress the body exception, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
If aclose itself raises while another exception is active, Python exception chaining records both, but the cleanup failure becomes the outward problem. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is losing evidence by catching every exception without chaining. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Test a body error plus aclose error and inspect __context__.
For the Cleanup failures need an explicit policy chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on losing evidence by catching every exception without chaining. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
try:
await failing_resource.aclose()
except Exception as exc:
print(type(exc.__context__).__name__ if exc.__context__ else None)Explained result. A real context-manager test reveals how both failures are connected; production policy should log without hiding evidence. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: CCA bot. Transfer the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “If aclose itself raises while another exception is active, Python exception chaining records both, but the cleanup failure becomes the outward problem.” Apply this procedure: Test a body error plus aclose error and inspect __context__. The expected mechanism is: A real context-manager test reveals how both failures are connected; production policy should log without hiding evidence. For the CCA bot, add one near-miss that exposes losing evidence by catching every exception without chaining. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: library search. Predict the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “If aclose itself raises while another exception is active, Python exception chaining records both, but the cleanup failure becomes the outward problem.” Apply this procedure: Test a body error plus aclose error and inspect __context__. The expected mechanism is: A real context-manager test reveals how both failures are connected; production policy should log without hiding evidence. For the library search, add one near-miss that exposes losing evidence by catching every exception without chaining. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: context tracking. Contrast the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “If aclose itself raises while another exception is active, Python exception chaining records both, but the cleanup failure becomes the outward problem.” Apply this procedure: Test a body error plus aclose error and inspect __context__. The expected mechanism is: A real context-manager test reveals how both failures are connected; production policy should log without hiding evidence. For the context tracking, add one near-miss that exposes losing evidence by catching every exception without chaining. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: cancellation lab. Stress-test the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “If aclose itself raises while another exception is active, Python exception chaining records both, but the cleanup failure becomes the outward problem.” Apply this procedure: Test a body error plus aclose error and inspect __context__. The expected mechanism is: A real context-manager test reveals how both failures are connected; production policy should log without hiding evidence. For the cancellation lab, add one near-miss that exposes losing evidence by catching every exception without chaining. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers losing evidence by catching every exception without chaining.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Test a body error plus aclose error and inspect __context__.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Cleanup failures need an explicit policy?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing losing evidence by catching every exception without chaining be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny test laboratory with covering normal, break, error and cleanup-failure paths. Include one ordinary case, one boundary and one deliberate failure caused by losing evidence by catching every exception without chaining. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: If aclose itself raises while another exception is active, Python exception chaining records both, but the cleanup failure becomes the outward problem. It shows a trace, not only a final value. The ordinary case should demonstrate “A real context-manager test reveals how both failures are connected; production policy should log without hiding evidence.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Test a body error plus aclose error and inspect __context__. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Cleanup failures need an explicit policy, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Deterministic lexical cleanup lets generator exit code run with the surrounding task and context variables still available. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is delegating finalisation to an unrelated later hook and expecting identical context. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Set a ContextVar, break early and record its value in the generator finally block.
For the Finalisation stays in the same task context chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on delegating finalisation to an unrelated later hook and expecting identical context. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
token=user_var.set('punggol-student')
async with aclosing(stream()) as rows:
async for row in rows: breakExplained result. The generator finaliser can observe the intended contextual state before the token is reset. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: context tracking. Predict the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Deterministic lexical cleanup lets generator exit code run with the surrounding task and context variables still available.” Apply this procedure: Set a ContextVar, break early and record its value in the generator finally block. The expected mechanism is: The generator finaliser can observe the intended contextual state before the token is reset. For the context tracking, add one near-miss that exposes delegating finalisation to an unrelated later hook and expecting identical context. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: cancellation lab. Contrast the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Deterministic lexical cleanup lets generator exit code run with the surrounding task and context variables still available.” Apply this procedure: Set a ContextVar, break early and record its value in the generator finally block. The expected mechanism is: The generator finaliser can observe the intended contextual state before the token is reset. For the cancellation lab, add one near-miss that exposes delegating finalisation to an unrelated later hook and expecting identical context. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: test laboratory. Stress-test the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Deterministic lexical cleanup lets generator exit code run with the surrounding task and context variables still available.” Apply this procedure: Set a ContextVar, break early and record its value in the generator finally block. The expected mechanism is: The generator finaliser can observe the intended contextual state before the token is reset. For the test laboratory, add one near-miss that exposes delegating finalisation to an unrelated later hook and expecting identical context. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: design review. Explain the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Deterministic lexical cleanup lets generator exit code run with the surrounding task and context variables still available.” Apply this procedure: Set a ContextVar, break early and record its value in the generator finally block. The expected mechanism is: The generator finaliser can observe the intended contextual state before the token is reset. For the design review, add one near-miss that exposes delegating finalisation to an unrelated later hook and expecting identical context. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers delegating finalisation to an unrelated later hook and expecting identical context.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Set a ContextVar, break early and record its value in the generator finally block.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Finalisation stays in the same task context?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing delegating finalisation to an unrelated later hook and expecting identical context be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny design review with choosing aclosing, async context managers, try-finally or an owning API. Include one ordinary case, one boundary and one deliberate failure caused by delegating finalisation to an unrelated later hook and expecting identical context. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Deterministic lexical cleanup lets generator exit code run with the surrounding task and context variables still available. It shows a trace, not only a final value. The ordinary case should demonstrate “The generator finaliser can observe the intended contextual state before the token is reset.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Set a ContextVar, break early and record its value in the generator finally block. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Finalisation stays in the same task context, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Nested async-with managers exit from inside to outside, so aclosing cleanup runs before outer resources disappear when written inside them. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is placing dependencies outside the lifetime they require. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Draw acquisition and reverse cleanup order before coding.
For the Context-manager nesting order matters chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on placing dependencies outside the lifetime they require. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
async with session():
async with aclosing(rows()) as stream:
passExplained result. The stream closes before the session context exits. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: test laboratory. Contrast the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Nested async-with managers exit from inside to outside, so aclosing cleanup runs before outer resources disappear when written inside them.” Apply this procedure: Draw acquisition and reverse cleanup order before coding. The expected mechanism is: The stream closes before the session context exits. For the test laboratory, add one near-miss that exposes placing dependencies outside the lifetime they require. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: design review. Stress-test the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Nested async-with managers exit from inside to outside, so aclosing cleanup runs before outer resources disappear when written inside them.” Apply this procedure: Draw acquisition and reverse cleanup order before coding. The expected mechanism is: The stream closes before the session context exits. For the design review, add one near-miss that exposes placing dependencies outside the lifetime they require. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: homework stream. Explain the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Nested async-with managers exit from inside to outside, so aclosing cleanup runs before outer resources disappear when written inside them.” Apply this procedure: Draw acquisition and reverse cleanup order before coding. The expected mechanism is: The stream closes before the session context exits. For the homework stream, add one near-miss that exposes placing dependencies outside the lifetime they require. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: school portal. Transfer the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Nested async-with managers exit from inside to outside, so aclosing cleanup runs before outer resources disappear when written inside them.” Apply this procedure: Draw acquisition and reverse cleanup order before coding. The expected mechanism is: The stream closes before the session context exits. For the school portal, add one near-miss that exposes placing dependencies outside the lifetime they require. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers placing dependencies outside the lifetime they require.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Draw acquisition and reverse cleanup order before coding.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Context-manager nesting order matters?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing placing dependencies outside the lifetime they require be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny homework stream with stopping an async sequence after the first matching exercise. Include one ordinary case, one boundary and one deliberate failure caused by placing dependencies outside the lifetime they require. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Nested async-with managers exit from inside to outside, so aclosing cleanup runs before outer resources disappear when written inside them. It shows a trace, not only a final value. The ordinary case should demonstrate “The stream closes before the session context exits.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Draw acquisition and reverse cleanup order before coding. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Context-manager nesting order matters, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
CHAPTER 13 OF 20 . Debug and verify
13. Cancellation is an exception path, not a shortcut
Task cancellation enters unwinding, but cleanup must remain cancellation-safe and should not casually consume CancelledError. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is catching broad cancellation signals and pretending the operation completed. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Cancel a task in a controlled test and assert cleanup plus propagated cancellation.
For the Cancellation is an exception path, not a shortcut chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on catching broad cancellation signals and pretending the operation completed. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
task.cancel()
try: await task
except asyncio.CancelledError: print('cancelled')Explained result. The caller still observes cancellation after the managed scope gets its cleanup opportunity. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: homework stream. Stress-test the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Task cancellation enters unwinding, but cleanup must remain cancellation-safe and should not casually consume CancelledError.” Apply this procedure: Cancel a task in a controlled test and assert cleanup plus propagated cancellation. The expected mechanism is: The caller still observes cancellation after the managed scope gets its cleanup opportunity. For the homework stream, add one near-miss that exposes catching broad cancellation signals and pretending the operation completed. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: school portal. Explain the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Task cancellation enters unwinding, but cleanup must remain cancellation-safe and should not casually consume CancelledError.” Apply this procedure: Cancel a task in a controlled test and assert cleanup plus propagated cancellation. The expected mechanism is: The caller still observes cancellation after the managed scope gets its cleanup opportunity. For the school portal, add one near-miss that exposes catching broad cancellation signals and pretending the operation completed. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: CCA bot. Transfer the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Task cancellation enters unwinding, but cleanup must remain cancellation-safe and should not casually consume CancelledError.” Apply this procedure: Cancel a task in a controlled test and assert cleanup plus propagated cancellation. The expected mechanism is: The caller still observes cancellation after the managed scope gets its cleanup opportunity. For the CCA bot, add one near-miss that exposes catching broad cancellation signals and pretending the operation completed. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: library search. Predict the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Task cancellation enters unwinding, but cleanup must remain cancellation-safe and should not casually consume CancelledError.” Apply this procedure: Cancel a task in a controlled test and assert cleanup plus propagated cancellation. The expected mechanism is: The caller still observes cancellation after the managed scope gets its cleanup opportunity. For the library search, add one near-miss that exposes catching broad cancellation signals and pretending the operation completed. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers catching broad cancellation signals and pretending the operation completed.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Cancel a task in a controlled test and assert cleanup plus propagated cancellation.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Cancellation is an exception path, not a shortcut?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing catching broad cancellation signals and pretending the operation completed be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny school portal with closing a paginated async feed after early success. Include one ordinary case, one boundary and one deliberate failure caused by catching broad cancellation signals and pretending the operation completed. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Task cancellation enters unwinding, but cleanup must remain cancellation-safe and should not casually consume CancelledError. It shows a trace, not only a final value. The ordinary case should demonstrate “The caller still observes cancellation after the managed scope gets its cleanup opportunity.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Cancel a task in a controlled test and assert cleanup plus propagated cancellation. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Cancellation is an exception path, not a shortcut, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Because aclose is awaited, slow finalisation delays completion of the context exit. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is placing unbounded network work in cleanup with no operational policy. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Measure exit time and design bounded, retryable release work where appropriate.
For the Slow cleanup affects cancellation latency chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on placing unbounded network work in cleanup with no operational policy. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
start=loop.time()
# exit aclosing scope
elapsed=loop.time()-startExplained result. The measurement includes awaited finalisation, which is part of the lifetime contract. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: CCA bot. Explain the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Because aclose is awaited, slow finalisation delays completion of the context exit.” Apply this procedure: Measure exit time and design bounded, retryable release work where appropriate. The expected mechanism is: The measurement includes awaited finalisation, which is part of the lifetime contract. For the CCA bot, add one near-miss that exposes placing unbounded network work in cleanup with no operational policy. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: library search. Transfer the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Because aclose is awaited, slow finalisation delays completion of the context exit.” Apply this procedure: Measure exit time and design bounded, retryable release work where appropriate. The expected mechanism is: The measurement includes awaited finalisation, which is part of the lifetime contract. For the library search, add one near-miss that exposes placing unbounded network work in cleanup with no operational policy. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: context tracking. Predict the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Because aclose is awaited, slow finalisation delays completion of the context exit.” Apply this procedure: Measure exit time and design bounded, retryable release work where appropriate. The expected mechanism is: The measurement includes awaited finalisation, which is part of the lifetime contract. For the context tracking, add one near-miss that exposes placing unbounded network work in cleanup with no operational policy. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: cancellation lab. Contrast the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Because aclose is awaited, slow finalisation delays completion of the context exit.” Apply this procedure: Measure exit time and design bounded, retryable release work where appropriate. The expected mechanism is: The measurement includes awaited finalisation, which is part of the lifetime contract. For the cancellation lab, add one near-miss that exposes placing unbounded network work in cleanup with no operational policy. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers placing unbounded network work in cleanup with no operational policy.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Measure exit time and design bounded, retryable release work where appropriate.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Slow cleanup affects cancellation latency?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing placing unbounded network work in cleanup with no operational policy be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny CCA bot with releasing a subscription when a command ends. Include one ordinary case, one boundary and one deliberate failure caused by placing unbounded network work in cleanup with no operational policy. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Because aclose is awaited, slow finalisation delays completion of the context exit. It shows a trace, not only a final value. The ordinary case should demonstrate “The measurement includes awaited finalisation, which is part of the lifetime contract.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Measure exit time and design bounded, retryable release work where appropriate. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Slow cleanup affects cancellation latency, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
The caller using aclosing claims responsibility for aclose; a separate owner should not race or repeat destructive shutdown. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is wrapping a stream that a library already owns and finalises. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Write one owner in the API contract and make repeated close behaviour explicit.
For the Multiple ownership creates double-close risk chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on wrapping a stream that a library already owns and finalises. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
owner = 'caller' # documented decisionExplained result. A written ownership decision prevents cleanup from becoming an accidental shared responsibility. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: context tracking. Transfer the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The caller using aclosing claims responsibility for aclose; a separate owner should not race or repeat destructive shutdown.” Apply this procedure: Write one owner in the API contract and make repeated close behaviour explicit. The expected mechanism is: A written ownership decision prevents cleanup from becoming an accidental shared responsibility. For the context tracking, add one near-miss that exposes wrapping a stream that a library already owns and finalises. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: cancellation lab. Predict the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The caller using aclosing claims responsibility for aclose; a separate owner should not race or repeat destructive shutdown.” Apply this procedure: Write one owner in the API contract and make repeated close behaviour explicit. The expected mechanism is: A written ownership decision prevents cleanup from becoming an accidental shared responsibility. For the cancellation lab, add one near-miss that exposes wrapping a stream that a library already owns and finalises. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: test laboratory. Contrast the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The caller using aclosing claims responsibility for aclose; a separate owner should not race or repeat destructive shutdown.” Apply this procedure: Write one owner in the API contract and make repeated close behaviour explicit. The expected mechanism is: A written ownership decision prevents cleanup from becoming an accidental shared responsibility. For the test laboratory, add one near-miss that exposes wrapping a stream that a library already owns and finalises. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: design review. Stress-test the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “The caller using aclosing claims responsibility for aclose; a separate owner should not race or repeat destructive shutdown.” Apply this procedure: Write one owner in the API contract and make repeated close behaviour explicit. The expected mechanism is: A written ownership decision prevents cleanup from becoming an accidental shared responsibility. For the design review, add one near-miss that exposes wrapping a stream that a library already owns and finalises. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers wrapping a stream that a library already owns and finalises.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Write one owner in the API contract and make repeated close behaviour explicit.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Multiple ownership creates double-close risk?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing wrapping a stream that a library already owns and finalises be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny library search with ending an async generator after one useful record. Include one ordinary case, one boundary and one deliberate failure caused by wrapping a stream that a library already owns and finalises. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: The caller using aclosing claims responsibility for aclose; a separate owner should not race or repeat destructive shutdown. It shows a trace, not only a final value. The ordinary case should demonstrate “A written ownership decision prevents cleanup from becoming an accidental shared responsibility.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Write one owner in the API contract and make repeated close behaviour explicit. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Multiple ownership creates double-close risk, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
When acquisition, configuration and release belong together, @asynccontextmanager or a class can express both entry and exit instead of wrapping an already-created object. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is using aclosing to hide important acquisition rules. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Compare whether the API needs only exit adaptation or a full lifecycle abstraction.
For the Async context managers may be the richer API chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on using aclosing to hide important acquisition rules. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
@asynccontextmanager
async def open_rows():
rows=make_rows()
try: yield rows
finally: await rows.aclose()Explained result. A full async context manager can own creation as well as release. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: test laboratory. Predict the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “When acquisition, configuration and release belong together, @asynccontextmanager or a class can express both entry and exit instead of wrapping an already-created object.” Apply this procedure: Compare whether the API needs only exit adaptation or a full lifecycle abstraction. The expected mechanism is: A full async context manager can own creation as well as release. For the test laboratory, add one near-miss that exposes using aclosing to hide important acquisition rules. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: design review. Contrast the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “When acquisition, configuration and release belong together, @asynccontextmanager or a class can express both entry and exit instead of wrapping an already-created object.” Apply this procedure: Compare whether the API needs only exit adaptation or a full lifecycle abstraction. The expected mechanism is: A full async context manager can own creation as well as release. For the design review, add one near-miss that exposes using aclosing to hide important acquisition rules. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: homework stream. Stress-test the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “When acquisition, configuration and release belong together, @asynccontextmanager or a class can express both entry and exit instead of wrapping an already-created object.” Apply this procedure: Compare whether the API needs only exit adaptation or a full lifecycle abstraction. The expected mechanism is: A full async context manager can own creation as well as release. For the homework stream, add one near-miss that exposes using aclosing to hide important acquisition rules. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: school portal. Explain the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “When acquisition, configuration and release belong together, @asynccontextmanager or a class can express both entry and exit instead of wrapping an already-created object.” Apply this procedure: Compare whether the API needs only exit adaptation or a full lifecycle abstraction. The expected mechanism is: A full async context manager can own creation as well as release. For the school portal, add one near-miss that exposes using aclosing to hide important acquisition rules. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers using aclosing to hide important acquisition rules.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Compare whether the API needs only exit adaptation or a full lifecycle abstraction.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Async context managers may be the richer API?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing using aclosing to hide important acquisition rules be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny context tracking with checking that cleanup sees the same context-variable state. Include one ordinary case, one boundary and one deliberate failure caused by using aclosing to hide important acquisition rules. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: When acquisition, configuration and release belong together, @asynccontextmanager or a class can express both entry and exit instead of wrapping an already-created object. It shows a trace, not only a final value. The ordinary case should demonstrate “A full async context manager can own creation as well as release.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Compare whether the API needs only exit adaptation or a full lifecycle abstraction. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Async context managers may be the richer API, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Direct try-finally is appropriate when cleanup needs arguments, ordering, logging or conditional decisions that a simple helper would obscure. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is choosing a one-line helper at the cost of important policy. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Expand the helper mentally and keep explicit code when the policy is non-trivial.
For the try-finally remains transparent chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on choosing a one-line helper at the cost of important policy. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
rows=make_rows()
try:
async for row in rows: ...
finally:
await rows.aclose()Explained result. The explicit form shows the same core mechanism and leaves room for domain-specific handling. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: homework stream. Contrast the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Direct try-finally is appropriate when cleanup needs arguments, ordering, logging or conditional decisions that a simple helper would obscure.” Apply this procedure: Expand the helper mentally and keep explicit code when the policy is non-trivial. The expected mechanism is: The explicit form shows the same core mechanism and leaves room for domain-specific handling. For the homework stream, add one near-miss that exposes choosing a one-line helper at the cost of important policy. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: school portal. Stress-test the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Direct try-finally is appropriate when cleanup needs arguments, ordering, logging or conditional decisions that a simple helper would obscure.” Apply this procedure: Expand the helper mentally and keep explicit code when the policy is non-trivial. The expected mechanism is: The explicit form shows the same core mechanism and leaves room for domain-specific handling. For the school portal, add one near-miss that exposes choosing a one-line helper at the cost of important policy. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: CCA bot. Explain the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Direct try-finally is appropriate when cleanup needs arguments, ordering, logging or conditional decisions that a simple helper would obscure.” Apply this procedure: Expand the helper mentally and keep explicit code when the policy is non-trivial. The expected mechanism is: The explicit form shows the same core mechanism and leaves room for domain-specific handling. For the CCA bot, add one near-miss that exposes choosing a one-line helper at the cost of important policy. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: library search. Transfer the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Direct try-finally is appropriate when cleanup needs arguments, ordering, logging or conditional decisions that a simple helper would obscure.” Apply this procedure: Expand the helper mentally and keep explicit code when the policy is non-trivial. The expected mechanism is: The explicit form shows the same core mechanism and leaves room for domain-specific handling. For the library search, add one near-miss that exposes choosing a one-line helper at the cost of important policy. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers choosing a one-line helper at the cost of important policy.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Expand the helper mentally and keep explicit code when the policy is non-trivial.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from try-finally remains transparent?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing choosing a one-line helper at the cost of important policy be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny cancellation lab with observing finalisation when a task is cancelled. Include one ordinary case, one boundary and one deliberate failure caused by choosing a one-line helper at the cost of important policy. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Direct try-finally is appropriate when cleanup needs arguments, ordering, logging or conditional decisions that a simple helper would obscure. It shows a trace, not only a final value. The ordinary case should demonstrate “The explicit form shows the same core mechanism and leaves room for domain-specific handling.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Expand the helper mentally and keep explicit code when the policy is non-trivial. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For try-finally remains transparent, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
A useful suite covers exhaustion, break, body exception and cancellation, plus an aclose failure when the resource can produce one. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is claiming cleanup is correct after one happy-path assertion. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Parameterise exit routes and assert order, call count and outward exception.
For the Test four exit routes chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on claiming cleanup is correct after one happy-path assertion. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
for route in ['exhaust','break','error','cancel']:
await exercise(route)Explained result. The matrix tests the lifetime contract rather than a single output. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: CCA bot. Stress-test the rule using releasing a subscription when a command ends. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A useful suite covers exhaustion, break, body exception and cancellation, plus an aclose failure when the resource can produce one.” Apply this procedure: Parameterise exit routes and assert order, call count and outward exception. The expected mechanism is: The matrix tests the lifetime contract rather than a single output. For the CCA bot, add one near-miss that exposes claiming cleanup is correct after one happy-path assertion. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: library search. Explain the rule using ending an async generator after one useful record. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A useful suite covers exhaustion, break, body exception and cancellation, plus an aclose failure when the resource can produce one.” Apply this procedure: Parameterise exit routes and assert order, call count and outward exception. The expected mechanism is: The matrix tests the lifetime contract rather than a single output. For the library search, add one near-miss that exposes claiming cleanup is correct after one happy-path assertion. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: context tracking. Transfer the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A useful suite covers exhaustion, break, body exception and cancellation, plus an aclose failure when the resource can produce one.” Apply this procedure: Parameterise exit routes and assert order, call count and outward exception. The expected mechanism is: The matrix tests the lifetime contract rather than a single output. For the context tracking, add one near-miss that exposes claiming cleanup is correct after one happy-path assertion. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: cancellation lab. Predict the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “A useful suite covers exhaustion, break, body exception and cancellation, plus an aclose failure when the resource can produce one.” Apply this procedure: Parameterise exit routes and assert order, call count and outward exception. The expected mechanism is: The matrix tests the lifetime contract rather than a single output. For the cancellation lab, add one near-miss that exposes claiming cleanup is correct after one happy-path assertion. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers claiming cleanup is correct after one happy-path assertion.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Parameterise exit routes and assert order, call count and outward exception.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Test four exit routes?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing claiming cleanup is correct after one happy-path assertion be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny test laboratory with covering normal, break, error and cleanup-failure paths. Include one ordinary case, one boundary and one deliberate failure caused by claiming cleanup is correct after one happy-path assertion. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: A useful suite covers exhaustion, break, body exception and cancellation, plus an aclose failure when the resource can produce one. It shows a trace, not only a final value. The ordinary case should demonstrate “The matrix tests the lifetime contract rather than a single output.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Parameterise exit routes and assert order, call count and outward exception. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Test four exit routes, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Deterministic cleanup should occur at the lexical boundary; object collection timing is not the resource protocol. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is dropping the last reference and assuming prompt finalisation. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. Assert events immediately after async-with instead of forcing gc.collect().
For the Avoid depending on garbage collection chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on dropping the last reference and assuming prompt finalisation. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
async with aclosing(stream()) as rows:
pass
assert events == ['closed']Explained result. The assertion relies on context exit, not implementation-dependent collection timing. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: context tracking. Explain the rule using checking that cleanup sees the same context-variable state. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Deterministic cleanup should occur at the lexical boundary; object collection timing is not the resource protocol.” Apply this procedure: Assert events immediately after async-with instead of forcing gc.collect(). The expected mechanism is: The assertion relies on context exit, not implementation-dependent collection timing. For the context tracking, add one near-miss that exposes dropping the last reference and assuming prompt finalisation. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: cancellation lab. Transfer the rule using observing finalisation when a task is cancelled. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Deterministic cleanup should occur at the lexical boundary; object collection timing is not the resource protocol.” Apply this procedure: Assert events immediately after async-with instead of forcing gc.collect(). The expected mechanism is: The assertion relies on context exit, not implementation-dependent collection timing. For the cancellation lab, add one near-miss that exposes dropping the last reference and assuming prompt finalisation. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: test laboratory. Predict the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Deterministic cleanup should occur at the lexical boundary; object collection timing is not the resource protocol.” Apply this procedure: Assert events immediately after async-with instead of forcing gc.collect(). The expected mechanism is: The assertion relies on context exit, not implementation-dependent collection timing. For the test laboratory, add one near-miss that exposes dropping the last reference and assuming prompt finalisation. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: design review. Contrast the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Deterministic cleanup should occur at the lexical boundary; object collection timing is not the resource protocol.” Apply this procedure: Assert events immediately after async-with instead of forcing gc.collect(). The expected mechanism is: The assertion relies on context exit, not implementation-dependent collection timing. For the design review, add one near-miss that exposes dropping the last reference and assuming prompt finalisation. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers dropping the last reference and assuming prompt finalisation.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “Assert events immediately after async-with instead of forcing gc.collect().” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Avoid depending on garbage collection?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing dropping the last reference and assuming prompt finalisation be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny design review with choosing aclosing, async context managers, try-finally or an owning API. Include one ordinary case, one boundary and one deliberate failure caused by dropping the last reference and assuming prompt finalisation. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Deterministic cleanup should occur at the lexical boundary; object collection timing is not the resource protocol. It shows a trace, not only a final value. The ordinary case should demonstrate “The assertion relies on context exit, not implementation-dependent collection timing.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: Assert events immediately after async-with instead of forcing gc.collect(). Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Avoid depending on garbage collection, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Choose it when an existing async-closeable object needs deterministic exit and no richer acquisition logic; otherwise use the abstraction that owns the whole lifecycle. Treat that sentence as a testable model. A secure learner can point to the relevant input, name the operation, describe the resulting state and identify one observation that would prove the model incomplete.
The high-value mistake in this chapter is wrapping every async value merely because the helper exists. It matters because the output may look reasonable while the ownership, ordering, identity or safety rule is wrong. State the object, aclose contract, owner and required exit paths before adopting it.
For the Use aclosing for a narrow adaptation chapter on Python contextlib.aclosing, use a two-column trace during a short Punggol home session. On the left, write the predicted state for this exact mechanism before the tool runs. On the right, record the observation that bears on wrapping every async value merely because the helper exists. Explain the earliest difference with one causal sentence, then repeat only the smallest changed case.
Core worked example
decision={'protocol':'aclose','owner':'caller','early_exit':True}Explained result. The decision record makes the helper a precise lifecycle choice rather than decorative syntax. Check the boundary as well as the happy path: ask what happens with an empty input, a duplicate or tied value, an unsupported type, a missing path, a NULL, or a second reference to the same object. Only the relevant boundary should be kept; the list is a prompt for judgment, not a demand to force every case into every example.
Four purposeful transfer cases
Case 1: test laboratory. Transfer the rule using covering normal, break, error and cleanup-failure paths. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Choose it when an existing async-closeable object needs deterministic exit and no richer acquisition logic; otherwise use the abstraction that owns the whole lifecycle.” Apply this procedure: State the object, aclose contract, owner and required exit paths before adopting it. The expected mechanism is: The decision record makes the helper a precise lifecycle choice rather than decorative syntax. For the test laboratory, add one near-miss that exposes wrapping every async value merely because the helper exists. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 2: design review. Predict the rule using choosing aclosing, async context managers, try-finally or an owning API. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Choose it when an existing async-closeable object needs deterministic exit and no richer acquisition logic; otherwise use the abstraction that owns the whole lifecycle.” Apply this procedure: State the object, aclose contract, owner and required exit paths before adopting it. The expected mechanism is: The decision record makes the helper a precise lifecycle choice rather than decorative syntax. For the design review, add one near-miss that exposes wrapping every async value merely because the helper exists. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 3: homework stream. Contrast the rule using stopping an async sequence after the first matching exercise. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Choose it when an existing async-closeable object needs deterministic exit and no richer acquisition logic; otherwise use the abstraction that owns the whole lifecycle.” Apply this procedure: State the object, aclose contract, owner and required exit paths before adopting it. The expected mechanism is: The decision record makes the helper a precise lifecycle choice rather than decorative syntax. For the homework stream, add one near-miss that exposes wrapping every async value merely because the helper exists. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Case 4: school portal. Stress-test the rule using closing a paginated async feed after early success. State the input grain or object graph, the chapter boundary and the intended output before choosing syntax. Change only one variable, so a wrong prediction has a single plausible cause.
Reasoned route. Begin with “Choose it when an existing async-closeable object needs deterministic exit and no richer acquisition logic; otherwise use the abstraction that owns the whole lifecycle.” Apply this procedure: State the object, aclose contract, owner and required exit paths before adopting it. The expected mechanism is: The decision record makes the helper a precise lifecycle choice rather than decorative syntax. For the school portal, add one near-miss that exposes wrapping every async value merely because the helper exists. The answer is complete only when it says why the near-miss fails and how the corrected model transfers to a different project without relying on the original variable names.
Diagnostic route
- Model check: ask the learner to draw or list the exact rows, fields, references, paths or states involved.
- Boundary check: create the smallest input that triggers wrapping every async value merely because the helper exists.
- Evidence check: separate a printed value from identity, ordering, ownership, type or repository state.
- Repair check: use the reversible procedure “State the object, aclose contract, owner and required exit paths before adopting it.” and record the first changed observation.
- Transfer check: repeat the rule in a second context and identify what remains invariant.
A parent does not need to know the final Python contextlib.aclosing syntax. For this chapter, useful prompts are: “What did you expect from Use aclosing for a narrow adaptation?”, “Which state changed first?”, “What evidence tests that prediction?”, and “Can the case exposing wrapping every async value merely because the helper exists be made smaller?” The learner, not the parent, should supply the technical explanation.
Practice with an explained answer
Question. Build a tiny homework stream with stopping an async sequence after the first matching exercise. Include one ordinary case, one boundary and one deliberate failure caused by wrapping every async value merely because the helper exists. Predict each result before using a tool, then report the first point where observation differs from prediction.
Answer guide. A strong response starts with the rule: Choose it when an existing async-closeable object needs deterministic exit and no richer acquisition logic; otherwise use the abstraction that owns the whole lifecycle. It shows a trace, not only a final value. The ordinary case should demonstrate “The decision record makes the helper a precise lifecycle choice rather than decorative syntax.” The boundary must exercise the same mechanism at an edge, and the deliberate failure must be repaired with: State the object, aclose contract, owner and required exit paths before adopting it. Other data choices are valid when the evidence supports the same causal chain.
Decision and transfer
For Use aclosing for a narrow adaptation, separate the documented Python contextlib.aclosing mechanism from the project policy. State exactly what the technical contract guarantees, then state the project choice about validation, ordering, ownership, performance or recovery. Test whether the same distinction survives one transfer case, and keep stateful experiments disposable and backed up.
Previous chapter . Contents . Next chapter
Parent guide: choose the next useful step
Start with evidence, not a label such as careless. Ask for one prediction and one trace. If the first transition is wrong, rebuild the model. If the model is sound but syntax fails, practise reference use. If routine cases are correct but boundaries fail, vary ties, defaults, unsupported inputs, ownership or missing paths. If explanations transfer, move to a small project.
Keep a weekly record with four lines: concept, prediction, observed difference and next test. Stop when fatigue replaces reasoning. A smaller case tomorrow is more useful than another hour of copying tonight.
Seek specialist help when cause and effect remain invisible after examples are reduced, when accessibility or data-loss implications are unclear, or when an important repository, database or application state may be at risk. Good support should make the learner’s reasoning more independent.
Capstone practice with explained routes
1. homework stream: model, boundary and recovery
Create a small homework stream using stopping an async sequence after the first matching exercise. Combine “aclosing turns aclose into an async context” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: The helper yields the supplied object and awaits its aclose method in a finally clause when the async-with suite exits. Apply: Trace entry, use and awaited exit as three separate events. Verify: The bound value is the original stream; aclose is awaited at exit. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
2. school portal: model, boundary and recovery
Create a small school portal using closing a paginated async feed after early success. Combine “The object must implement aclose” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: aclosing follows a small protocol: the wrapped object needs an aclose attribute returning an awaitable. Apply: Inspect the concrete object rather than only its AsyncIterable annotation. Verify: An async generator object has aclose; an arbitrary asynchronous iterator may not. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
3. CCA bot: model, boundary and recovery
Create a small CCA bot using releasing a subscription when a command ends. Combine “Normal exhaustion still closes once” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: Even when the loop finishes normally, the surrounding context exits and invokes the deterministic aclose contract. Apply: Count cleanup calls during full exhaustion. Verify: The finalisation path is observable once and should be tested for idempotent ownership. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
4. library search: model, boundary and recovery
Create a small library search using ending an async generator after one useful record. Combine “Cleanup failures need an explicit policy” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: If aclose itself raises while another exception is active, Python exception chaining records both, but the cleanup failure becomes the outward problem. Apply: Test a body error plus aclose error and inspect __context__. Verify: A real context-manager test reveals how both failures are connected; production policy should log without hiding evidence. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
5. context tracking: model, boundary and recovery
Create a small context tracking using checking that cleanup sees the same context-variable state. Combine “Cancellation is an exception path, not a shortcut” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: Task cancellation enters unwinding, but cleanup must remain cancellation-safe and should not casually consume CancelledError. Apply: Cancel a task in a controlled test and assert cleanup plus propagated cancellation. Verify: The caller still observes cancellation after the managed scope gets its cleanup opportunity. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
6. cancellation lab: model, boundary and recovery
Create a small cancellation lab using observing finalisation when a task is cancelled. Combine “Async context managers may be the richer API” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: When acquisition, configuration and release belong together, @asynccontextmanager or a class can express both entry and exit instead of wrapping an already-created object. Apply: Compare whether the API needs only exit adaptation or a full lifecycle abstraction. Verify: A full async context manager can own creation as well as release. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
7. test laboratory: model, boundary and recovery
Create a small test laboratory using covering normal, break, error and cleanup-failure paths. Combine “Avoid depending on garbage collection” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: Deterministic cleanup should occur at the lexical boundary; object collection timing is not the resource protocol. Apply: Assert events immediately after async-with instead of forcing gc.collect(). Verify: The assertion relies on context exit, not implementation-dependent collection timing. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
8. design review: model, boundary and recovery
Create a small design review using choosing aclosing, async context managers, try-finally or an owning API. Combine “It is designed for asynchronous finalisation” with one later chapter. Include an ordinary case, a boundary, a deliberate failure and a recovery. Write the expected state before each operation.
Explained route. Start with: The exit path may await work, unlike contextlib.closing, whose synchronous exit calls close immediately. Apply: Classify the cleanup method as close or aclose before choosing the helper. Verify: The two helpers express different protocols and cannot be substituted mechanically. Then add a second chapter whose boundary could change the outcome. A complete solution contains the input model, a trace, observed evidence, a correction and one transfer statement. The exact data may differ; the causal chain must be checkable.
Frequently asked questions
How long should a practice session be?
Use one complete prediction–observation–explanation cycle while attention remains good. Ten to twenty focused minutes can be enough.
Should every option or function be memorised?
No. Memorise the governing distinctions and practise retrieving the official reference. Understanding means predicting and explaining, not reciting a parameter list.
What if the result is correct but the explanation is weak?
Treat it as partial success. Ask for a trace and change one boundary. A reliable model survives controlled variation.
Is the shortest solution the best?
Not automatically. Prefer the solution whose semantics, failure modes and maintenance cost are easiest to justify for the actual project.
When should official documentation be used?
Use it whenever syntax, supported types, SQL dialect behaviour or Git version details matter. Primary documentation settles the current contract.
How can a parent help without technical expertise?
Ask what was predicted, where the first difference appeared, what evidence matters and which smaller example could isolate it.
How do we test transfer?
Change the context, vocabulary and one boundary. Require the learner to identify the invariant before using a tool.
What should be saved after practice?
Keep the corrected rule, one trace, one boundary case and the next question. Avoid storing pages of unexplained output.
Can these exercises replace backups?
No. Use disposable examples and proper backups. Learning should not endanger schoolwork, repositories or personal data.
What counts as mastery?
The learner can predict, verify, diagnose, recover and justify a choice across more than one context, while knowing when to consult the current reference.

