Skip to content

Instantly share code, notes, and snippets.

@jeremyblow
Last active December 25, 2015 23:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jeremyblow/7060658 to your computer and use it in GitHub Desktop.
Save jeremyblow/7060658 to your computer and use it in GitHub Desktop.
Mavis Bacon.. mmm.. bacon.
import urllib2
import random
import difflib
import datetime
def fetch(url):
"""Fetches requested url, returns lines in list"""
response = urllib2.urlopen(url)
lines = response.readlines()
return lines
def parse(lines):
"""Parses lines, returning code grouped by block in dictionary"""
block_tags = ['def']
ignore_tags = ['#']
docstring_tags = ['"""', "'''"]
block_depth = 0
result = {}
key = None
is_docstring = False
for line in lines:
# Strip trailing CR/LF/spaces
line = line.rstrip()
# Skip comments, etc
if search_start(line, ignore_tags):
continue
# Handle docstrings
if any(line.strip() == docstring_tag for docstring_tag in docstring_tags):
# For lines who only content is a docstring tag, open or close the docstring toggle
is_docstring = not is_docstring
continue
elif search_start(line, docstring_tags) and search_end(line, docstring_tags):
# For single line docstrings (lines that start and end with a docstring tag), skip
continue
elif search_start(line, docstring_tags) and not search_end(line, docstring_tags):
# For lines that start with docstring tag, but doesn't end with tag
is_docstring = not is_docstring
continue
# If docstring is true, line is part of a docstring block... skip.
if is_docstring:
continue
# Get the line's whitespace depth
line_depth = len(line) - len(line.lstrip())
# If is new block definition, grab the line text to use as key
if search_start(line, block_tags):
block_depth = len(line) - len(line.lstrip())
key = line.strip()
result[key] = [line[block_depth:]]
if line_depth > block_depth and key is not None:
# Remove block_depth leading whitespace, and append line to block
result[key].append(line[block_depth:])
return result
def search_start(line, tags):
"""Returns boolean set if line starts with any tag."""
# Strip the line
line = line.strip()
# Test if starts with any tag
starts = any(line.startswith(tag) for tag in tags)
return starts
def search_end(line, tags):
"""Returns boolean set if line ends with any tag."""
# Strip the line
line = line.strip()
# Test if ends with any tag
ends = any(line.endswith(tag) for tag in tags)
return ends
def torture_someone(functions):
# Choose random function from list of functions
function = random.choice(functions.values())
# Get index of random line in function
target_index = random.choice(range(len(function)))
# Make them do it until they get it right
accuracy = 0.00
while accuracy != 1.0:
# Create a visual separator
print "=" * 60
# Print lines from function, highlighting line to type
for line_index, line in enumerate(function):
if line_index == target_index:
result = "type this->{}".format(line)
else:
result = " |{}".format(line)
print result
# Make someone type it in, record the time to the timer.
start_time = datetime.datetime.now()
submission = raw_input("your turn >")
# Replace tabs with 4 whitespaces
submission = submission.replace("\t", " ")
duration = datetime.datetime.now() - start_time
# Judge the puny human
accuracy = difflib.SequenceMatcher(None, submission, function[target_index]).ratio()
print "-" * 60
# Report their success
if accuracy == 1.0:
print "Nicely done, 100% match in {} seconds.".format(duration.seconds)
else:
print "Nope...{0:.0%} accuracy in {1} seconds. Try again.".format(accuracy, duration.seconds)
print "Me >{}".format(function[target_index])
print "You >{}".format(submission)
def main():
url = 'https://raw.github.com/django/django/master/django/core/servers/basehttp.py'
print "Pulling sample code from {}".format(url)
lines = fetch(url)
functions = parse(lines)
while True:
torture_someone(functions)
if __name__ == "__main__":
main()
@manonthemat
Copy link

What does Line 68 do?

starts = any(line.startswith(tag) for tag in tags)

I thought I knew what it does, but when running with python 3, I get this confusing error message:

TypeError: startswith first arg must be bytes or a tuple of bytes, not str

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment