Initial import to Tizen
[profile/ivi/python-twisted.git] / doc / historic / 2003 / pycon / applications / applications
1 #!/usr/bin/python
2 from slides import Slide, Bullet, SubBullet, URL, Image, PRE
3 from twslides import Lecture
4
5 class PythonSource:
6     def __init__(self, content):
7         self.content = content 
8     def toHTML(self):
9         return '<pre class="python">%s</pre>' % (self.content,)
10
11 class Raw:
12     def __init__(self, content):
13         self.content = content
14     def toHTML(self):
15         return self.content + '\n'
16
17 lecture = Lecture(
18     "Applications of Twisted",
19     Slide("Twisted.names",
20         Bullet("Domain Name Server", SubBullet(
21             Bullet("Authoritative"),
22             Bullet("Caching"),
23             Bullet("Other!"),
24         )),
25         Bullet("Domain Name Client"),
26     ),
27     Slide("Mostly Functional",
28         Bullet("All common records support; 22 supported total", SubBullet(
29             Bullet("A, NS, CNAME, SOA, PTR, HINFO, MX, TXT"),
30             Bullet("IPv6 records AAAA and A6"),
31         )),
32         Bullet("No DNSSEC support"),
33         Bullet("Server and Client functionality"),
34     ),
35     Slide("Rapidly Developed",
36         Bullet("One month initial development period", SubBullet(
37             Bullet("Python is good for rapid development"),
38             Bullet("Twisted handles all the boring network details"),
39         )),
40         Bullet("Easily extended", SubBullet(
41             Bullet("Doesn't choke on unrecognized record types"),
42             Bullet("Support for a new record type can be added in "
43                       "just a few minutes"),
44             Bullet(PythonSource("""\
45 from twisted.protocols import dns
46
47 class Record_A:
48     __implements__ = (dns.IEncodable,)
49     TYPE = dns.QUERY_TYPES['A'] = 1
50
51     def __init__(self, address = '0.0.0.0'):
52         self.address = socket.inet_aton(address)
53
54     def encode(self, strio, compDict = None):
55         strio.write(self.address)
56
57     def decode(self, strio, length = None):
58         self.address = readPrecisely(strio, 4)
59 """
60             )),
61         )),
62     ),
63     Slide("Easily Configured",
64         Bullet("BIND zonefile syntax"),
65         Bullet("Python source", SubBullet(
66             Bullet(PythonSource("""\
67 zone = [
68     AAAA('intarweb.us', '3ffe:b80:1886:1::1'),
69     SRV('_http._tcp.www.intarweb.us', 0, 0, 8080, 'intarweb.us'),
70     MX('intarweb.us', 10, 'mail.intarweb.us')
71 ]
72 """
73             )),
74         )),
75         Bullet("Twisted's mktap and twistd tools", SubBullet(
76             PRE("mktap dns --pyzone a.domain.zonefile --recursive --cache"),
77             PRE("twistd -f dns.tap"),
78         )),
79     ),
80     Slide("Client API",
81         Bullet("Asynchronous", SubBullet(
82             Bullet("All lookup functions return Deferred objects"),
83             Bullet(PythonSource(
84 """\
85 import random
86 from twisted.names import client
87
88 def addressFor(service, protocol, domain):
89     d = client.theResolver.lookupService(
90         '_%s._%s.%s' % (service, protocol, domain)
91     )
92
93     def grabPayload((answers, authority, additional)):
94         return [r.payload for r in answers]
95
96     def randomAnswer(results):
97         if len(results) == 1 and results[0] == '.':
98             raise RuntimeException, "No service records found"
99         return random.choice(results)
100
101     return d.addCallback(grabPayload).addCallback(randomAnswer)
102 """
103             )),
104         )),
105     ),
106     Slide("Uses",
107         Bullet("Service Records", SubBullet(
108             Bullet("Potential to simplify user experience"),
109             Bullet("Not widely accessible"),
110             Bullet("Names' client API makes accessing them trivial"),
111         )),
112     ),
113     Slide("Pynfo: A Network Information 'Bot",
114         Bullet("A 'bot with the goal of integrating access to miscellaneous data inputs"),
115     ),
116     Slide("Architecture",
117         Bullet("Factories", SubBullet(
118             Bullet("Takes care of connecting to different services"),
119             Bullet("Acts as a central storage for shared data"),
120             Bullet("Currently only IRC is supported"),
121             Bullet("Planned support for web, IM, and PB interfaces")
122         )),
123         Bullet("Protocols", SubBullet(
124             Bullet("Created by Factories"),
125             Bullet("Handles all service-specific interaction"),
126             Bullet("Refers back to the factory for shared data"),
127             Bullet("Current support for IRC only")
128         )),
129         Image("pynfo-chart.png"),
130         Bullet("Separation of Factory and Protocols", SubBullet(
131             Bullet("Per-protocol data separate, per-robot data shared"),
132             Bullet("Protocols destroyed on disconnect, factory manage reconnecting"),
133         )),
134     ),
135     Slide("Plugins",
136         Bullet("Plugins are modules plus some metadata", SubBullet(
137             Bullet("A plugin name"),
138             Bullet("A plugin description"),
139             Bullet("A plugin type"),
140             Bullet("Any other data appropriate for the type"),
141         )),
142         Bullet("Initialization / Finalization hooks"),
143         Bullet("Input filtering, for behaviors like ignore"),
144         Bullet("An example", SubBullet(
145             Bullet(PythonSource("""
146 from twisted.names import client
147 def info_LOOKUP(bot, user, channel, query):
148     def tellUserResponse((ans, auth, add)):
149         bot.reply(user, "%s: %s" % (query, [str(a.payload) for a in ans]))
150
151     def tellUserError(failure):
152         bot.reply(user, "Host lookup failed.")
153
154     client.lookupAddress(query).addCallbacks(
155         tellUserResponse, tellUserError
156     )
157 """
158             )),
159         )),
160     ),
161     Slide("But where do they come from?",
162         Bullet("Twisted's plugin module", SubBullet(
163             Bullet(PythonSource("""\
164 from twisted.python import plugin
165 class InfoBotFactory:
166     ...
167     def loadPlugins(self):
168         ...
169         p = plugin.getPlugIns('infobot')
170         ....
171 """
172             )),
173         )),
174     ),
175     Slide("Persistence",
176         Bullet("Addresses to connect to and protocols to use"),
177         Bullet("Administrators, passwords, keys"),
178         Bullet("Connection statistics"),
179         Bullet("Plugins can store objects for later retrieval")
180     ),
181     Slide("Components",
182         Bullet("Shared and pluggable behavior is implemented as Adapters for Interfaces", SubBullet(
183             Bullet("IScheduler, IStorage, IAuthenticator"),
184         )),
185         Bullet("Plugins can register their own adapters for the factory", SubBullet(
186             Bullet("Gracefully add new capabilities without __class__ hacks"),
187             Bullet("Share capabilities with other plugins"),
188             Bullet("Avoids namespace collisions"),
189         )),
190     ),
191     Slide("Interaction",
192         Bullet("Commands and responses are issued through normal protocol actions"),
193         Bullet('Three levels of command "security"'),
194         Bullet("Access to some commands is unrestricted",
195             Raw("<code>"),
196             SubBullet("<exarkun> pyn: networks"),
197             SubBullet("<pyn> Connected to: oftc -> ('irc.oftc.net', 6667), fn -> ('irc.freenode.net', 6667)"),
198             Raw("</code>"),
199         ),
200         Bullet("Access to others is granted via an ACL",
201             Raw("<code>"),
202             SubBullet("<exarkun> pyn: rebuild"),
203             SubBullet("<pyn> You aren't allowed to do that."),
204             Raw("</code>"),
205         ),
206         Bullet("Still further access is granted by the possession of a secret key",
207             Raw("<code>"),
208             SubBullet("<exarkun> pyn: spill self.transport.getHost()"),
209             SubBullet("<pyn> Command queued.  Challenge: BBKSkYCRCGQETx4kTmceUg==%"),
210             SubBullet("<exarkun> pyn: respond 2lwcgSVnJPzrW6Yvq7sg+g==%"), 
211             SubBullet("<pyn> ('INET', '192.168.123.137', 45539)"),
212             Raw("</code>"),
213         )
214     ),
215     Slide("Network Bridging",
216         Bullet("Pass messages between networks",
217             Raw("<code>"),
218             SubBullet("<pyn> Yosomono (~fake@hostmask) has joined on efnet"),
219             SubBullet("<pyn> <Yosomono@efnet> hello"),
220             Raw("</code>"),
221         ),
222         Bullet("Requesting user information across networks",
223             Raw("<code>"),
224             SubBullet("<exarkun> pyn: whois Yosomono@efnet"),
225             SubBullet("<pyn> Hostmask: Yosomono!fake@hostmask"),
226             SubBullet("<pyn> Channels: @#python"),
227             Raw("</code>"),
228         ),
229     ),
230     Slide("Conversation Logging",
231         Bullet("The 'conversation' command", SubBullet(
232             Raw("<code>"),
233             SubBullet("<exar[con]> pyn: conversation begin PyCon example conversation"),
234             SubBullet("<pyn> Beginning tagged conversation 'PyCon example conversation'."),
235             SubBullet("<exar[con]> Hello, PyCon"),
236             SubBullet("<exar[con]> Enjoy the example!"),
237             SubBullet("<exar[con]> pyn: conversation end PyCon example conversation"),
238             SubBullet("<pyn> Ended tagged conversation 'PyCon example conversation'."),
239             Raw("</code>"),
240         )),
241         Bullet("Web interface", SubBullet(
242             URL("http://c.intarweb.us:8008/%23tanstaafl/PyCon%20example%20conversation"),
243         )),
244         Bullet("Search previous logs and add conversation tags"),
245     ),
246     Slide("Various other plugins",
247         Bullet("PyPI monitor and querying"),
248         Bullet("Network specific operations - IRC operator module"),
249         Bullet("Freshmeat and Google querying"),
250         Bullet("Link shortener"),
251         Bullet("PyMetar plugin"),
252         Bullet("Manhole"),
253     ),
254     Slide("Questions?"),
255 )
256
257 lecture.renderHTML(".", "applications-%d.html", css="stylesheet.css")