Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
185 lines (125 sloc) 5.1 KB
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at
"""05 - Debug the Method Resolution Order of Python.
Use a metaclass to decorate methods of Person and its subclasses.
import contextlib
import typing
import wrapt
def log_call(wrapped_method, instance, args, kwargs) -> typing.Any:
"""Print when the decorated method is called."""
method_name = wrapped_method.__qualname__
class_name = instance.__class__.__qualname__
print(f"Calling method {method_name} for {class_name}.")
return wrapped_method(*args, **kwargs)
class LogMethods(type):
"""Metaclass that decorates methods with log_call."""
def __new__(cls, name, bases, attrs, **kwargs):
for attr, value in attrs.items():
if not callable(value):
attrs[attr] = log_call(value)
return super().__new__(cls, name, bases, attrs, **kwargs)
class Person(metaclass=LogMethods):
"""A person has a name and likes to do things."""
def __init__(self, *, name: str, **kwargs: typing.Any): = name
def __str__(self) -> str:
return f"{}"
def stay_hydrated(self) -> None:
print(f"{self} drinks some water. 🚰")
def go_to_the_movies(self) -> None:
print(f"{self} goes to the movies. 🍿")
def go_hiking(self) -> None:
print(f"{self} goes hiking. β›°")
def build_a_robot(self) -> None:
print(f"{self} builds a robot. πŸ€–")
class TeaPerson(Person):
"""A person who prefers tea over water."""
def stay_hydrated(self) -> None:
print(f"{self} drinks tea. 🍡")
class Project:
"""A project has a board_name and a description."""
def __init__(self, board_name: str, description: str):
self.board_name = board_name
self.description = description
def __str__(self) -> str:
return f"Project '{self.board_name}'"
class TeamMember(Person):
"""A team member is a person, who works on projects, and may have
specialized in a specific field.
expertise: typing.Optional[str] = None
def __str__(self) -> str:
# Get default string representation from the super class
default = super().__str__()
if self.expertise is None:
return f"{default}"
return f"{self.expertise} {default}"
def commute(self) -> typing.Generator:
"""Commute to the office and back."""
print(f"{self} commutes to the office. 🏒")
print(f"{self} commutes home. 🏑")
def work_on_project(self, project) -> None:
"""Start working on the given project."""
with self.commute():
print(f"{self} is now working on {project}. πŸ“‹")
class MobileEngineer(TeamMember):
"""Team member specialized in developing for mobile platforms."""
expertise = "πŸ“±"
class DataScientist(TeamMember):
"""Team member specialized in data science."""
expertise = "πŸ“ˆ"
class ProjectManager(TeamMember):
"""Team member specialized in project management."""
expertise = "πŸ“"
class OperationsEngineer(TeamMember):
"""Team member specialized in running cloud infrastructure."""
expertise = "πŸ“¦"
class RemoteTeamMember(TeamMember):
"""Team member who works remotely."""
def __init__(self, *, workplace: str, **kwargs: typing.Any):
self.workplace = workplace
# Forward kwargs to super class
def commute(self) -> typing.Generator:
"""Stay at home or commute to the workplace and back."""
if self.workplace == "home":
print(f"{self} works from home. 🏑")
print(f"{self} commutes to {self.workplace}. 🚌")
print(f"{self} commutes home. 🏑")
class DataScientistWhoLikesTea(DataScientist, TeaPerson):
"""Data scientist who prefers tea over water."""
class ProjectManagerWhoWorksRemotely(ProjectManager, RemoteTeamMember):
"""Project manager who works remotely."""
class MobileEngineerWhoWorksRemotelyAndLikesTea(
MobileEngineer, RemoteTeamMember, TeaPerson
"""Mobile engineer who works remotely and prefers tea over water."""
if __name__ == "__main__":
simone = OperationsEngineer(name="Simone")
chelsea = DataScientistWhoLikesTea(name="Chelsea")
dave = ProjectManagerWhoWorksRemotely(name="Dave", workplace="a local coffee shop")
marlene = MobileEngineerWhoWorksRemotelyAndLikesTea(
name="Marlene", workplace="home"
data_platform = Project(
board_name="Data Platform",
description="Platform providing datasets and data viewing tools.",
You can’t perform that action at this time.