Skip to content

Commit e9f53bb

Browse files
committed
Chapter 19
1 parent c11f37c commit e9f53bb

11 files changed

Lines changed: 201 additions & 0 deletions

File tree

Ch19/basic_warning.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import warnings
2+
3+
thumbs = "pricking"
4+
5+
if thumbs == "pricking":
6+
warnings.warn("Something wicked this way comes.", FutureWarning)
7+
8+
with open('locks.txt', 'w') as file:
9+
file.write("Whoever knocks")

Ch19/empty.txt

Whitespace-only changes.

Ch19/letter_counter/__init__.py

Whitespace-only changes.

Ch19/letter_counter/__main__.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import pathlib
2+
import argparse
3+
import logging
4+
5+
from letter_counter.common import scrub_string
6+
from letter_counter.letters import most_common_consonant, most_common_vowel
7+
8+
logger = logging.getLogger('letter_counter')
9+
stream_handler = logging.StreamHandler()
10+
logger.addHandler(stream_handler)
11+
12+
parser = argparse.ArgumentParser(description="Find which letters appear most.")
13+
parser.add_argument("-v", help="Show all messages.", action="store_true")
14+
parser.add_argument("raw_path", metavar="P", type=str, help="The file to read.")
15+
16+
17+
def main():
18+
args = parser.parse_args()
19+
if args.v:
20+
logger.setLevel(logging.INFO)
21+
else:
22+
logger.setLevel(logging.WARNING)
23+
24+
path = pathlib.Path(args.raw_path).resolve()
25+
logger.info(f"Opening {path}")
26+
27+
if not path.exists():
28+
logger.warning("File does not exist.")
29+
return
30+
31+
with path.open('r') as file:
32+
string = scrub_string(file.read())
33+
print(f"Most common vowel: {most_common_vowel(string)}")
34+
print(f"Most common consonant: {most_common_consonant(string)}")
35+
36+
37+
if __name__ == "__main__":
38+
main()

Ch19/letter_counter/common.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import logging
2+
3+
logger = logging.getLogger(__name__)
4+
5+
6+
def scrub_string(string):
7+
string = string.lower()
8+
string = ''.join(filter(str.isalpha, string))
9+
logger.debug(f"{len(string)} letters detected.")
10+
return string

Ch19/letter_counter/letters.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import logging
2+
from collections import defaultdict
3+
4+
logger = logging.getLogger(__name__)
5+
consonants = 'bcdfghjklmnpqrstvwxyz'
6+
vowels = 'aeiou'
7+
8+
9+
def count_letters(string, letter_set):
10+
counts = defaultdict(lambda: 0)
11+
for ch in string:
12+
if ch in letter_set:
13+
counts[ch] += 1
14+
return counts
15+
16+
17+
def most_common_consonant(string):
18+
if not len(string):
19+
logger.info("No consonants in empty string.")
20+
return ""
21+
counts = count_letters(string, consonants)
22+
return max(counts, key=counts.get).upper()
23+
24+
25+
def most_common_vowel(string):
26+
if not len(string):
27+
logger.info("No vowels in empty string.")
28+
return ""
29+
counts = count_letters(string, vowels)
30+
return max(counts, key=counts.get).upper()

Ch19/magic_calculator.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env python3
2+
import ast
3+
4+
equation = input("Enter an equation: ")
5+
result = ast.literal_eval(equation)
6+
print(f"{equation} = {result}")

Ch19/segfault.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import ctypes
2+
3+
import faulthandler; faulthandler.enable()
4+
5+
ctypes.memset(0, 254, 1)

Ch19/train_timetable.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from datetime import time
2+
3+
4+
def get_timetable(train):
5+
# Pretend this gets data from a server.
6+
return [
7+
{"station": "target_field", "arrives": time(hour=16, minute=27)},
8+
{"station": "fridley", "arrives": time(hour=16, minute=41)},
9+
{"station": "coon_rapids_fridley", "arrives": time(hour=16, minute=50)},
10+
{"station": "anoka", "arrives": time(hour=16, minute=54)},
11+
{"station": "ramsey", "arrives": time(hour=16, minute=59)},
12+
{"station": "elk_river", "arrives": time(hour=17, minute=4)},
13+
{"station": "big_lake", "arrives": time(hour=17, minute=17)},
14+
]
15+
16+
17+
def next_station(now, timetable):
18+
"""Return the name of the next station."""
19+
station = None
20+
for stop in timetable:
21+
if stop['arrives'] > now:
22+
station = stop
23+
break
24+
station['station'] = station['station'].replace('_', ' ').title()
25+
return station
26+
27+
28+
def arrives_at(station, timetable):
29+
for stop in timetable:
30+
if station == stop['station']:
31+
return stop
32+
33+
34+
timetable = get_timetable('nstar_northbound')
35+
36+
station = next_station(time(hour=16, minute=43), timetable)
37+
print(f"Next station is {station['station']}.")
38+
39+
stop = arrives_at('coon_rapids_fridley', timetable)
40+
print(f"Arrives at {stop['arrives']}.")

Ch19/vinyl_collector.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
THICKNESS = 0.125 # must be a positive number
2+
assert THICKNESS > 0, "Vinyl must have a positive thickness!"
3+
4+
5+
def fit_records(width, shelves):
6+
records_per_shelf = width / THICKNESS
7+
records = records_per_shelf * shelves
8+
return int(records)
9+
10+
11+
def get_number(prompt):
12+
while True:
13+
value = input(prompt)
14+
try:
15+
value = int(value)
16+
except ValueError:
17+
print("You must enter a whole number.")
18+
continue
19+
20+
if value <= 0:
21+
print("You must enter a positive number.")
22+
continue
23+
24+
return value
25+
26+
27+
def main():
28+
width = get_number("What is the bookcase shelf width (in inches)? ")
29+
print("How many shelves are...")
30+
shelves_lp = get_number(" 12+ inches high? ")
31+
shelves_78 = get_number(" 10-11.5 inches high? ")
32+
shelves_single = get_number(" 7-9.5 inches high? ")
33+
34+
records_lp = fit_records(width, shelves_lp)
35+
records_single = fit_records(width, shelves_single)
36+
records_78 = fit_records(width, shelves_78)
37+
38+
print(f"You can fit {records_lp}, "
39+
f"{records_single} singles, and "
40+
f"{records_78} 78s.")
41+
42+
43+
if __name__ == "__main__":
44+
main()

0 commit comments

Comments
 (0)