adapted to realpython v5