The Wayback Machine - https://web.archive.org/web/20200909112437/https://github.com/huangsam/ultimate-python/commit/d2993749ceb2b97aa34da40438197d759f548b56
Skip to content
Permalink
Browse files

Remove print statements (#5)

  • Loading branch information
huangsam committed Sep 7, 2020
1 parent 2bcc823 commit d2993749ceb2b97aa34da40438197d759f548b56
@@ -7,6 +7,7 @@ exclude_lines =
def __repr__
raise NotImplementedError
if __name__ == .__main__.:
any\(
fail_under = 80
omit =
venv/**
@@ -30,17 +30,13 @@ def _current_time():
async def start_job(delay, job_id):
"""Start job_id after a certain delay in seconds."""
queue_time = _current_time()
print(f"{queue_time} -> Queue job {job_id[:16]}...")
await asyncio.sleep(delay)
start_time = _current_time()
print(f"{start_time} -> Start job {job_id[:16]}...")
return JobRecord(job_id, queue_time, start_time)


async def schedule_jobs():
"""Schedule jobs concurrently."""
print(f"{_current_time()} -> Send kickoff email")

# Create a job which also represents a coroutine
single_job = start_job(_MILLISECOND, uuid4().hex)
assert asyncio.iscoroutine(single_job)
@@ -70,8 +66,6 @@ async def schedule_jobs():
for batch_record in batch_records:
assert _is_valid_record(batch_record)

print(f"{_current_time()} -> Send confirmation email")


def main():
asyncio.run(schedule_jobs())
@@ -3,6 +3,8 @@
import time

# Module-level constants
from io import StringIO

_SLEEP_DURATION = .001


@@ -34,7 +36,8 @@ def main():
# There are other ways to sort the stats by, but this is the most
# common way of doing so. For more info, please consult Python docs:
# https://docs.python.org/3/library/profile.html
ps = pstats.Stats(profile).sort_stats("cumulative")
bytes_obj = StringIO()
ps = pstats.Stats(profile, stream=bytes_obj).sort_stats("cumulative")

# Notice how many times each function was called. In this case, the main
# bottleneck for `finish_slower` and `finish_faster` is `time.sleep`
@@ -46,6 +49,11 @@ def main():
# classes and functions
ps.print_stats()

lines = bytes_obj.getvalue().split("\n")
time_sleep_called = any("60" in line and "time.sleep" in line
for line in lines)
assert time_sleep_called is True


if __name__ == "__main__":
main()
@@ -1,34 +1,5 @@
from contextlib import contextmanager
from functools import wraps

# Module-level constants
_HEADER = "---"


@contextmanager
def header_section():
"""Print header line first before running anything.
Notice a context manager is used so that we enter a block where a header
is printed out before proceeding with the function call at the point
of yielding.
Also notice that `header_section` is a coroutine that is wrapped by
`contextmanager`. The `contextmanager` handles entering and exiting a
section of code without defining a full-blown class to handle `__enter__`
and `__exit__` use cases.
There are many more use cases for context managers, like
writing / reading data from a file. Another one is protecting database
integrity while sending CREATE / UPDATE / DELETE statements over the
network. For more on how context managers work, please consult the
Python docs for more information.
https://docs.python.org/3/library/contextlib.html
"""
print(_HEADER)
yield


def run_with_stringy(fn):
"""Run a string function with a string or a collection of strings.
@@ -108,16 +79,15 @@ def main():

# See what changed between the insecure data and the secure data
for insecure_item, secure_item in zip(insecure_data, secure_data):
with header_section():
print("Insecure item", insecure_item)
print("Secure item", secure_item)
assert insecure_item != secure_item

# Throw an error on a collection with non-string objects
input_fails = False
try:
hide_content([1])
except ValueError as e:
with header_section():
print(e)
except ValueError:
input_fails = True
assert input_fails is True


if __name__ == "__main__":
@@ -133,15 +133,12 @@ class AddressModel(BaseModel):

def main():
# Each model was modified at runtime with ModelMeta
for real_model in BaseModel.__subclasses__():
assert real_model.is_registered
print("Real model name", real_model.model_name)
print("Real model fields", real_model.model_fields)
print("Real model table", real_model.model_table)
assert UserModel.model_name == "user_rocks"
assert AddressModel.model_name == "address"

# Each model was registered at runtime with ModelMeta
for meta_table in ModelMeta.tables.values():
print("ModelMeta table", meta_table)
assert UserModel.model_name in ModelMeta.tables
assert AddressModel.model_name in ModelMeta.tables

# Base model was given special treatment, as expected
assert not BaseModel.is_registered
@@ -2,17 +2,17 @@ class BasePlayer:
"""Base player."""

def ping(self):
print("ping", self)
return f"ping {type(self).__name__}"

def pong(self):
print("pong", self)
return f"pong {type(self).__name__}"


class PongPlayer(BasePlayer):
"""Pong player."""

def pong(self):
print("PONG", self)
return f"PONG {type(self).__name__}"


class NeutralPlayer(BasePlayer):
@@ -37,14 +37,16 @@ class ConfusedPlayer(PongPlayer, NeutralPlayer):

def ping(self):
"""Override `ping` method."""
print("pINg", self)
return f"pINg {type(self).__name__}"

def ping_pong(self):
"""Run `ping` and `pong` in different ways."""
self.ping()
super().ping()
self.pong()
super().pong()
return [
self.ping(),
super().ping(),
self.pong(),
super().pong()
]


class IndecisivePlayer(NeutralPlayer, PongPlayer):
@@ -61,14 +63,16 @@ class IndecisivePlayer(NeutralPlayer, PongPlayer):

def pong(self):
"""Override `pong` method."""
print("pONg", self)
return f"pONg {type(self).__name__}"

def ping_pong(self):
"""Run `ping` and `pong` in different ways."""
self.ping()
super().ping()
self.pong()
super(PongPlayer, self).pong() # bypass MRO to `BasePlayer`
return [
self.ping(),
super().ping(),
self.pong(),
super(PongPlayer, self).pong() # bypass MRO to `BasePlayer`
]


def main():
@@ -86,14 +90,16 @@ def main():
# Show `IndecisivePlayer` method resolution in action
IndecisivePlayer().ping_pong()

class_creation_fails = False
try:
# Creating a new class `ConfusedPlayer` and `IndecisivePlayer`
# result in a `TypeError` because both classes have mismatched
# MRO outputs. This means that they cannot be reconciled as
# one class. Hence `MissingPlayer` will not be created
type("MissingPlayer", (ConfusedPlayer, IndecisivePlayer), {})
except TypeError as e:
print(e)
except TypeError:
class_creation_fails = True
assert class_creation_fails is True


if __name__ == '__main__':
@@ -63,9 +63,6 @@ def setup_and_teardown_servers(registry):
for server in servers])
)

# Print server count as proof
print("Server count", registry.server_count)

# What's really interesting is that servers go away when we leave the
# scope of this function. In this function, each server is created and
# strongly referenced by the `app_servers` variable. When we leave this
@@ -90,9 +87,6 @@ def main():
assert registry.servers == set()
assert registry.server_count == 0

# Print server count as proof
print("Server count", registry.server_count)


if __name__ == '__main__':
main()
@@ -18,21 +18,14 @@ def __init__(self, name, title):
self.title = title

def __str__(self):
return f"{self.name} ({self.title})"

def __repr__(self):
return f"<{type(self).__name__} name={self.name}>"
return self.name

@abstractmethod
def do_work(self):
raise NotImplementedError

@abstractmethod
def join_meeting(self):
raise NotImplementedError

@abstractmethod
def relax(self):
def do_relax(self):
raise NotImplementedError


@@ -52,17 +45,14 @@ def __init__(self, name, title, skill):
self.skill = skill

def do_work(self):
print(f"{self} is coding in {self.skill}")

def join_meeting(self):
print(f"{self} is joining a meeting on {self.skill}")
return f"{self} is coding in {self.skill}"

def relax(self):
print(f"{self} is relaxing by watching YouTube")
def do_relax(self):
return f"{self} is watching YouTube"

def do_refactor(self):
"""Do the hard work of refactoring code, unlike managers."""
print(f"{self} is refactoring code")
return f"{self} is refactoring code"


class Manager(Employee):
@@ -79,46 +69,37 @@ def __init__(self, name, title, direct_reports):
self.direct_reports = direct_reports

def do_work(self):
print(f"{self} is meeting up with {self.direct_reports}")
return f"{self} is meeting up with {len(self.direct_reports)} reports"

def join_meeting(self):
print(f"{self} is joining a meeting with {self.direct_reports}")

def relax(self):
print(f"{self} is taking a trip to the Bahamas")
def do_relax(self):
return f"{self} is taking a trip to the Bahamas"

def do_hire(self):
"""Do the hard work of hiring employees, unlike engineers."""
print(f"{self} is hiring employees")
return f"{self} is hiring employees"


def main():
# Declare two engineers
engineer_john = Engineer("John Doe", "Software Engineer", "Android")
engineer_jane = Engineer("Jane Doe", "Software Engineer", "iOS")

engineers = [engineer_john, engineer_jane]
for engineer in engineers:
assert isinstance(engineer, (Engineer, Employee))
assert not isinstance(engineer, Manager)
print("Created", repr(engineer))

engineer.do_work()
engineer.join_meeting()
engineer.relax()
engineer.do_refactor()
assert isinstance(engineer_john, (Engineer, Employee))
assert not isinstance(engineer_john, Manager)
assert engineer_john.do_work() == "John Doe is coding in Android"
assert engineer_john.do_relax() == "John Doe is watching YouTube"
assert engineer_john.do_refactor() == "John Doe is refactoring code"

# Declare manager with engineers as direct reports
engineers = [engineer_john, engineer_jane]
manager_max = Manager("Max Doe", "Engineering Manager", engineers)

assert isinstance(manager_max, (Manager, Employee))
assert not isinstance(manager_max, Engineer)
print("Created", repr(manager_max))

manager_max.do_work()
manager_max.join_meeting()
manager_max.relax()
manager_max.do_hire()
assert manager_max.do_work() == "Max Doe is meeting up with 2 reports"
assert manager_max.do_relax() == "Max Doe is taking a trip to the Bahamas"
assert manager_max.do_hire() == "Max Doe is hiring employees"


if __name__ == '__main__':
@@ -27,7 +27,7 @@ def __str__(self):

def drive(self, rate_in_mph):
"""Drive car at a certain rate."""
print(f"{self} is driving at {rate_in_mph} MPH")
return f"{self} is driving at {rate_in_mph} MPH"


def main():
@@ -38,7 +38,7 @@ def main():
assert repr(car) != str(car)

# Call a method on the class constructor
car.drive(75)
assert car.drive(75) == "Bumble Bee (2000) is driving at 75 MPH"

# As a reminder: everything in Python is an object! And that applies
# to classes in the most interesting way - because they're not only
@@ -59,9 +59,11 @@ def main():
try:
divide_positive_numbers(dividend, divisor)
except DivisionError as e:
print(e)
assert str(e).startswith("Cannot have a")

# Now let's do it correctly to skip all the exceptions
result = divide_positive_numbers(1, 1)
print(f"Divide(1, 1) = {result}")
assert result == 1


if __name__ == '__main__':

0 comments on commit d299374

Please sign in to comment.
You can’t perform that action at this time.