Template methods often expose a hook: an optional step with a do-nothing default that subclasses may override to customize the outcome. The skeleton calls it, but subclasses that do not care simply inherit the no-op.
The base Pipeline now defines after_load(result), which returns result unchanged, and run() already calls it as its final step: extract, transform, load, then after_load. Because the default is a no-op, every pipeline from the earlier steps behaves exactly as before.
Implement WrapPipeline, a subclass that overrides after_load(result) to wrap the loaded result in a dict of the form with keys "result" (the loaded list) and "count" (its length). WrapPipeline inherits run() and every step except this one, the hook alone changes the final output.
class Pipeline:
def __init__(self, source):
self.source = source
def extract(self):
return list(self.source)
def transform(self, data):
return data
def load(self, data):
return data
def after_load(self, result):
return result
def run(self):
data = self.extract()
data = self.transform(data)
result = self.load(data)
result = self.after_load(result)
return result
class UpperPipeline(Pipeline):
def transform(self, data):
return [s.upper() for s in data]
class SumPipeline(Pipeline):
def transform(self, data):
return [sum(data)]
class WrapPipeline(Pipeline):
def after_load(self, result):
"""Wrap the loaded result in a dict with its element count (overrides the no-op hook)."""
# TODO: return {"result": result, "count": len(result)}
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
Template methods often expose a hook: an optional step with a do-nothing default that subclasses may override to customize the outcome. The skeleton calls it, but subclasses that do not care simply inherit the no-op.
The base Pipeline now defines after_load(result), which returns result unchanged, and run() already calls it as its final step: extract, transform, load, then after_load. Because the default is a no-op, every pipeline from the earlier steps behaves exactly as before.
Implement WrapPipeline, a subclass that overrides after_load(result) to wrap the loaded result in a dict of the form with keys "result" (the loaded list) and "count" (its length). WrapPipeline inherits run() and every step except this one, the hook alone changes the final output.
Press Run Tests or ββ© to check your solution.