preparing documents... done
writing output... [ 50%] home
writing output... [100%] tutorial
no targets are out of date.
build succeeded.
preparing documents... done
writing output... [100%] tutorial
!"#$%&'()*+,-./0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
`abcdefghijklmnopqrstuvwxyz{|}~
$ ls
LICENSE
Makefile
README
home.html
home.rst
tutorial.html
tutorial.rst
# Makefile
home.html: home.rst
rst2html.py $< $@
tutorial.html: tutorial.rst
rst2html.py $< $@
# Makefile
program: main.o sort.o utils.o
ld -o program main.o sort.o utils.o
main.o: main.c
cc -c $<
sort.o: sort.c
cc -c $<
tree.o: tree.c
cc -c $<
# setup.py
module1 = Extension('demo', sources=[
'main.c',
'sort.c',
'util.c',
])
Tutorial → Math Tutorial
-------- -------------
preparing documents... done
writing output... [100%] tutorial
[('main.c', 'main.o'),
('tree.c', 'tree.o'),
('main.o', 'program'),
('tree.o', 'program')]
{'main.c': {},
'tree.c': {},
'main.o': {'main.c'},
'tree.o': {'tree.c'},
'program': {'main.o', 'tree.o'}}
from os import stat
r = stat('home.rst').st_mtime
h = stat('home.html').st_mtime
if r > h:
print('Out of date!')
class Node: …
class Edge: …
class Graph: …
class Graph: …
{'main.c': {},
'tree.c': {},
'main.o': {'main.c'},
'tree.o': {'tree.c'},
'program': {'main.o', 'tree.o'}}
class Graph:
def add_edge(name1, name2): …
def remove_edge(name1, name2): …
def nodes_upstream_of(name): …
def nodes_downstream_from(name): …
text = 'Read `tutorial.in` and `guide.in`.'
pieces = text.split('`')
# 0 1 2 3 4
# ['Read ', 'tutorial.in', ' and ', 'guide.in', '.']
#
# Even index: text
# Odd index: document filename
for i in range(1, len(pieces), 2):
… # Loops over filenames!
# First idea: give framework two functions.
# One finds dependencies to build the graph,
# the other builds the output file.
def learn_dependencies(path, text):
yield 'text_of', path
t = text.split('`')
for i in range(1, len(t), 2):
yield 'title_of', t[i]
def render(text, title_dict):
t = text.split('`')
for i in range(1, len(t), 2):
t[i] = title_dict[t[i]]
return ''.join(a)
# Have you ever seen “callback” code?
def step1(sock):
sock.connect(('python.org', 80), step2)
def step2(sock):
sock.sendall('data', step3)
def step3(sock):
sock.close()
# Callbacks are SO MUCH WORK!
# All you wanted was normal
# procedural code, like:
sock.connect(('python.org', 80))
sock.sendall('data')
sock.close()
# But instead, some framework forced you to
# atomize your code into a maze of goto’s.
def step1(sock):
sock.connect(('python.org', 80), step2)
def step2(sock):
sock.sendall('data', step3)
def step3(sock):
sock.close()
def learn_dependencies(text):
yield 'text_of', path
t = text.split('`')
for i in range(1, len(t), 2):
yield 'title_of', t[i]
def render(text, title_dict):
t = text.split('`')
for i in range(1, len(t), 2):
t[i] = title_dict[t[i]]
return ''.join(a)
def step1(sock):
sock.connect(('python.org', 80), step2)
def step2(sock):
sock.sendall('data', step3)
def step3(sock):
sock.close()
sock.connect(('python.org', 80))
sock.sendall('data')
sock.close()
def render(path):
pieces = read(path).split('`')
for i in range(1, len(pieces), 2):
pieces[i] = title_of(pieces[i])
return ''.join(pieces)
def title_of(path):
return read(path).splitlines()[0]
def read(path):
return open(path).read()
@task
def read(path):
...
@task
def title_of(path):
...
@task
def render(path):
...