The payoff of a reusable decorator is that a brand new class becomes a singleton for free. A shared Logger is a perfect fit: every part of the app should append to the same message list.
The starter decorates a Logger with your singleton from step 4. Implement its two methods:
Because Logger is a singleton, every Logger() call returns the same object and shares one messages list. Each test resets that shared list at the top so the tests stay independent within the single process the runner uses.
class Config:
_instance = None
def __init__(self):
self._data = {}
@classmethod
def instance(cls):
if cls._instance is None:
cls._instance = cls()
return cls._instance
@classmethod
def reset(cls):
cls._instance = None
def set(self, key, value):
self._data[key] = value
def get(self, key, default=None):
return self._data.get(key, default)
def has(self, key):
return key in self._data
def singleton(cls):
instances = {}
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class Database:
def __init__(self):
self.connections = 0
@singleton
class Logger:
def __init__(self):
self.messages = []
def log(self, msg):
"""Append msg to the shared message list."""
# TODO
pass
def all(self):
"""Return a copy of all logged messages."""
# TODO
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
The payoff of a reusable decorator is that a brand new class becomes a singleton for free. A shared Logger is a perfect fit: every part of the app should append to the same message list.
The starter decorates a Logger with your singleton from step 4. Implement its two methods:
Because Logger is a singleton, every Logger() call returns the same object and shares one messages list. Each test resets that shared list at the top so the tests stay independent within the single process the runner uses.
Press Run Tests or ββ© to check your solution.