1 <?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
3 <title>Twisted Documentation: The Evolution of Finger: configuration and packaging of the finger service</title>
4 <link href="../stylesheet.css" rel="stylesheet" type="text/css"/>
8 <h1 class="title">The Evolution of Finger: configuration and packaging of the finger service</h1>
9 <div class="toc"><ol><li><a href="#auto0">Introduction</a></li><li><a href="#auto1">Plugins</a></li><li><a href="#auto2">OS Integration</a></li><ul><li><a href="#auto3">Debian</a></li><li><a href="#auto4">Red Hat / Mandrake</a></li></ul></ol></div>
14 <h2>Introduction<a name="auto0"/></h2>
16 <p> This is the eleventh part of the Twisted tutorial <a href="index.html" shape="rect">Twisted from Scratch, or The Evolution of Finger</a>.</p>
18 <p>In this part, we make it easier for non-programmers to configure a finger
19 server and show how to package it in the .deb and RPM package formats. Plugins
20 are discussed further in the <a href="../plugin.html" shape="rect">Twisted Plugin System</a>
21 howto. Writing twistd plugins is covered in <a href="../tap.html" shape="rect">Writing a
22 twistd Plugin</a>, and .tac applications are covered in <a href="../application.html" shape="rect">Using the Twisted Application Framework</a>.</p>
24 <h2>Plugins<a name="auto1"/></h2>
26 <p>So far, the user had to be somewhat of a programmer to be able to configure
27 stuff. Maybe we can eliminate even that? Move old code
28 to <code>finger/__init__.py</code> and...</p>
30 Full source code for finger module here: <div class="py-listing"><pre><p class="py-linenumber"> 1
398 </p><span class="py-src-comment"># finger.py module</span>
400 <span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Interface</span>, <span class="py-src-variable">implements</span>
402 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span>, <span class="py-src-variable">service</span>
403 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">protocol</span>, <span class="py-src-variable">reactor</span>, <span class="py-src-variable">defer</span>
404 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">words</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">irc</span>
405 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">protocols</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">basic</span>
406 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">components</span>, <span class="py-src-variable">log</span>
407 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">resource</span>, <span class="py-src-variable">server</span>, <span class="py-src-variable">xmlrpc</span>
408 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">spread</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">pb</span>
410 <span class="py-src-keyword">from</span> <span class="py-src-variable">OpenSSL</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">SSL</span>
412 <span class="py-src-keyword">class</span> <span class="py-src-identifier">IFingerService</span>(<span class="py-src-parameter">Interface</span>):
414 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">user</span>):
415 <span class="py-src-string">"""
416 Return a deferred returning a string.
417 """</span>
419 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUsers</span>():
420 <span class="py-src-string">"""
421 Return a deferred returning a list of strings.
422 """</span>
425 <span class="py-src-keyword">class</span> <span class="py-src-identifier">IFingerSetterService</span>(<span class="py-src-parameter">Interface</span>):
427 <span class="py-src-keyword">def</span> <span class="py-src-identifier">setUser</span>(<span class="py-src-parameter">user</span>, <span class="py-src-parameter">status</span>):
428 <span class="py-src-string">"""
429 Set the user's status to something.
430 """</span>
433 <span class="py-src-keyword">def</span> <span class="py-src-identifier">catchError</span>(<span class="py-src-parameter">err</span>):
434 <span class="py-src-keyword">return</span> <span class="py-src-string">"Internal error in server"</span>
437 <span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
439 <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
440 <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
441 <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">catchError</span>)
442 <span class="py-src-keyword">def</span> <span class="py-src-identifier">writeValue</span>(<span class="py-src-parameter">value</span>):
443 <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">value</span>+<span class="py-src-string">'\n'</span>)
444 <span class="py-src-variable">self</span>.<span class="py-src-variable">transport</span>.<span class="py-src-variable">loseConnection</span>()
445 <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">writeValue</span>)
448 <span class="py-src-keyword">class</span> <span class="py-src-identifier">IFingerFactory</span>(<span class="py-src-parameter">Interface</span>):
450 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">user</span>):
451 <span class="py-src-string">"""
452 Return a deferred returning a string.
453 """</span>
455 <span class="py-src-keyword">def</span> <span class="py-src-identifier">buildProtocol</span>(<span class="py-src-parameter">addr</span>):
456 <span class="py-src-string">"""
457 Return a protocol returning a string.
458 """</span>
461 <span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerFactoryFromService</span>(<span class="py-src-parameter">protocol</span>.<span class="py-src-parameter">ServerFactory</span>):
462 <span class="py-src-variable">implements</span>(<span class="py-src-variable">IFingerFactory</span>)
464 <span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerProtocol</span>
466 <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">service</span>):
467 <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span> = <span class="py-src-variable">service</span>
469 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
470 <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
472 <span class="py-src-variable">components</span>.<span class="py-src-variable">registerAdapter</span>(<span class="py-src-variable">FingerFactoryFromService</span>,
473 <span class="py-src-variable">IFingerService</span>,
474 <span class="py-src-variable">IFingerFactory</span>)
477 <span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerSetterProtocol</span>(<span class="py-src-parameter">basic</span>.<span class="py-src-parameter">LineReceiver</span>):
479 <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
480 <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span> = []
482 <span class="py-src-keyword">def</span> <span class="py-src-identifier">lineReceived</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">line</span>):
483 <span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>.<span class="py-src-variable">append</span>(<span class="py-src-variable">line</span>)
485 <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionLost</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">reason</span>):
486 <span class="py-src-keyword">if</span> <span class="py-src-variable">len</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>) == <span class="py-src-number">2</span>:
487 <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">setUser</span>(*<span class="py-src-variable">self</span>.<span class="py-src-variable">lines</span>)
490 <span class="py-src-keyword">class</span> <span class="py-src-identifier">IFingerSetterFactory</span>(<span class="py-src-parameter">Interface</span>):
492 <span class="py-src-keyword">def</span> <span class="py-src-identifier">setUser</span>(<span class="py-src-parameter">user</span>, <span class="py-src-parameter">status</span>):
493 <span class="py-src-string">"""
494 Return a deferred returning a string.
495 """</span>
497 <span class="py-src-keyword">def</span> <span class="py-src-identifier">buildProtocol</span>(<span class="py-src-parameter">addr</span>):
498 <span class="py-src-string">"""
499 Return a protocol returning a string.
500 """</span>
503 <span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerSetterFactoryFromService</span>(<span class="py-src-parameter">protocol</span>.<span class="py-src-parameter">ServerFactory</span>):
505 <span class="py-src-variable">implements</span>(<span class="py-src-variable">IFingerSetterFactory</span>)
507 <span class="py-src-variable">protocol</span> = <span class="py-src-variable">FingerSetterProtocol</span>
509 <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">service</span>):
510 <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span> = <span class="py-src-variable">service</span>
512 <span class="py-src-keyword">def</span> <span class="py-src-identifier">setUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>, <span class="py-src-parameter">status</span>):
513 <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">setUser</span>(<span class="py-src-variable">user</span>, <span class="py-src-variable">status</span>)
516 <span class="py-src-variable">components</span>.<span class="py-src-variable">registerAdapter</span>(<span class="py-src-variable">FingerSetterFactoryFromService</span>,
517 <span class="py-src-variable">IFingerSetterService</span>,
518 <span class="py-src-variable">IFingerSetterFactory</span>)
521 <span class="py-src-keyword">class</span> <span class="py-src-identifier">IRCReplyBot</span>(<span class="py-src-parameter">irc</span>.<span class="py-src-parameter">IRCClient</span>):
523 <span class="py-src-keyword">def</span> <span class="py-src-identifier">connectionMade</span>(<span class="py-src-parameter">self</span>):
524 <span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">nickname</span>
525 <span class="py-src-variable">irc</span>.<span class="py-src-variable">IRCClient</span>.<span class="py-src-variable">connectionMade</span>(<span class="py-src-variable">self</span>)
527 <span class="py-src-keyword">def</span> <span class="py-src-identifier">privmsg</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>, <span class="py-src-parameter">channel</span>, <span class="py-src-parameter">msg</span>):
528 <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">'!'</span>)[<span class="py-src-number">0</span>]
529 <span class="py-src-keyword">if</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">nickname</span>.<span class="py-src-variable">lower</span>() == <span class="py-src-variable">channel</span>.<span class="py-src-variable">lower</span>():
530 <span class="py-src-variable">d</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">factory</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">msg</span>)
531 <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">catchError</span>)
532 <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-keyword">lambda</span> <span class="py-src-variable">m</span>: <span class="py-src-string">"Status of %s: %s"</span> % (<span class="py-src-variable">msg</span>, <span class="py-src-variable">m</span>))
533 <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-keyword">lambda</span> <span class="py-src-variable">m</span>: <span class="py-src-variable">self</span>.<span class="py-src-variable">msg</span>(<span class="py-src-variable">user</span>, <span class="py-src-variable">m</span>))
536 <span class="py-src-keyword">class</span> <span class="py-src-identifier">IIRCClientFactory</span>(<span class="py-src-parameter">Interface</span>):
538 <span class="py-src-string">"""
540 """</span>
542 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">user</span>):
543 <span class="py-src-string">"""
544 Return a deferred returning a string.
545 """</span>
547 <span class="py-src-keyword">def</span> <span class="py-src-identifier">buildProtocol</span>(<span class="py-src-parameter">addr</span>):
548 <span class="py-src-string">"""
550 """</span>
553 <span class="py-src-keyword">class</span> <span class="py-src-identifier">IRCClientFactoryFromService</span>(<span class="py-src-parameter">protocol</span>.<span class="py-src-parameter">ClientFactory</span>):
555 <span class="py-src-variable">implements</span>(<span class="py-src-variable">IIRCClientFactory</span>)
557 <span class="py-src-variable">protocol</span> = <span class="py-src-variable">IRCReplyBot</span>
558 <span class="py-src-variable">nickname</span> = <span class="py-src-variable">None</span>
560 <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">service</span>):
561 <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span> = <span class="py-src-variable">service</span>
563 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
564 <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
566 <span class="py-src-variable">components</span>.<span class="py-src-variable">registerAdapter</span>(<span class="py-src-variable">IRCClientFactoryFromService</span>,
567 <span class="py-src-variable">IFingerService</span>,
568 <span class="py-src-variable">IIRCClientFactory</span>)
571 <span class="py-src-keyword">class</span> <span class="py-src-identifier">UserStatusTree</span>(<span class="py-src-parameter">resource</span>.<span class="py-src-parameter">Resource</span>):
573 <span class="py-src-variable">template</span> = <span class="py-src-string">"""<html><head><title>Users</title></head><body>
574 <h1>Users</h1>
579 </html>"""</span>
581 <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">service</span>):
582 <span class="py-src-variable">resource</span>.<span class="py-src-variable">Resource</span>.<span class="py-src-variable">__init__</span>(<span class="py-src-variable">self</span>)
583 <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span> = <span class="py-src-variable">service</span>
585 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getChild</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">path</span>, <span class="py-src-parameter">request</span>):
586 <span class="py-src-keyword">if</span> <span class="py-src-variable">path</span> == <span class="py-src-string">''</span>:
587 <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>
588 <span class="py-src-keyword">elif</span> <span class="py-src-variable">path</span> == <span class="py-src-string">'RPC2'</span>:
589 <span class="py-src-keyword">return</span> <span class="py-src-variable">UserStatusXR</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>)
590 <span class="py-src-keyword">else</span>:
591 <span class="py-src-keyword">return</span> <span class="py-src-variable">UserStatus</span>(<span class="py-src-variable">path</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>)
593 <span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
594 <span class="py-src-variable">users</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">getUsers</span>()
595 <span class="py-src-keyword">def</span> <span class="py-src-identifier">cbUsers</span>(<span class="py-src-parameter">users</span>):
596 <span class="py-src-variable">request</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">template</span> % {<span class="py-src-string">'users'</span>: <span class="py-src-string">''</span>.<span class="py-src-variable">join</span>([
597 <span class="py-src-comment"># Name should be quoted properly these uses.</span>
598 <span class="py-src-string">'<li><a href="%s">%s</a></li>'</span> % (<span class="py-src-variable">name</span>, <span class="py-src-variable">name</span>)
599 <span class="py-src-keyword">for</span> <span class="py-src-variable">name</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">users</span>])})
600 <span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()
601 <span class="py-src-variable">users</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">cbUsers</span>)
602 <span class="py-src-keyword">def</span> <span class="py-src-identifier">ebUsers</span>(<span class="py-src-parameter">err</span>):
603 <span class="py-src-variable">log</span>.<span class="py-src-variable">err</span>(<span class="py-src-variable">err</span>, <span class="py-src-string">"UserStatusTree failed"</span>)
604 <span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()
605 <span class="py-src-variable">users</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">ebUsers</span>)
606 <span class="py-src-keyword">return</span> <span class="py-src-variable">server</span>.<span class="py-src-variable">NOT_DONE_YET</span>
608 <span class="py-src-variable">components</span>.<span class="py-src-variable">registerAdapter</span>(<span class="py-src-variable">UserStatusTree</span>, <span class="py-src-variable">IFingerService</span>, <span class="py-src-variable">resource</span>.<span class="py-src-variable">IResource</span>)
611 <span class="py-src-keyword">class</span> <span class="py-src-identifier">UserStatus</span>(<span class="py-src-parameter">resource</span>.<span class="py-src-parameter">Resource</span>):
613 <span class="py-src-variable">template</span>=<span class="py-src-string">'''<html><head><title>%(title)s</title></head>
614 <body><h1>%(name)s</h1><p>%(status)s</p></body></html>'''</span>
616 <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>, <span class="py-src-parameter">service</span>):
617 <span class="py-src-variable">resource</span>.<span class="py-src-variable">Resource</span>.<span class="py-src-variable">__init__</span>(<span class="py-src-variable">self</span>)
618 <span class="py-src-variable">self</span>.<span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>
619 <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span> = <span class="py-src-variable">service</span>
621 <span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
622 <span class="py-src-variable">status</span> = <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">user</span>)
623 <span class="py-src-keyword">def</span> <span class="py-src-identifier">cbStatus</span>(<span class="py-src-parameter">status</span>):
624 <span class="py-src-variable">request</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">template</span> % {
625 <span class="py-src-string">'title'</span>: <span class="py-src-variable">self</span>.<span class="py-src-variable">user</span>,
626 <span class="py-src-string">'name'</span>: <span class="py-src-variable">self</span>.<span class="py-src-variable">user</span>,
627 <span class="py-src-string">'status'</span>: <span class="py-src-variable">status</span>})
628 <span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()
629 <span class="py-src-variable">status</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">cbStatus</span>)
630 <span class="py-src-keyword">def</span> <span class="py-src-identifier">ebStatus</span>(<span class="py-src-parameter">err</span>):
631 <span class="py-src-variable">log</span>.<span class="py-src-variable">err</span>(<span class="py-src-variable">err</span>, <span class="py-src-string">"UserStatus failed"</span>)
632 <span class="py-src-variable">request</span>.<span class="py-src-variable">finish</span>()
633 <span class="py-src-variable">status</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">ebStatus</span>)
634 <span class="py-src-keyword">return</span> <span class="py-src-variable">server</span>.<span class="py-src-variable">NOT_DONE_YET</span>
637 <span class="py-src-keyword">class</span> <span class="py-src-identifier">UserStatusXR</span>(<span class="py-src-parameter">xmlrpc</span>.<span class="py-src-parameter">XMLRPC</span>):
639 <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">service</span>):
640 <span class="py-src-variable">xmlrpc</span>.<span class="py-src-variable">XMLRPC</span>.<span class="py-src-variable">__init__</span>(<span class="py-src-variable">self</span>)
641 <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span> = <span class="py-src-variable">service</span>
643 <span class="py-src-keyword">def</span> <span class="py-src-identifier">xmlrpc_getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
644 <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">user</span>)
646 <span class="py-src-keyword">def</span> <span class="py-src-identifier">xmlrpc_getUsers</span>(<span class="py-src-parameter">self</span>):
647 <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">getUsers</span>()
650 <span class="py-src-keyword">class</span> <span class="py-src-identifier">IPerspectiveFinger</span>(<span class="py-src-parameter">Interface</span>):
652 <span class="py-src-keyword">def</span> <span class="py-src-identifier">remote_getUser</span>(<span class="py-src-parameter">username</span>):
653 <span class="py-src-string">"""
654 Return a user's status.
655 """</span>
657 <span class="py-src-keyword">def</span> <span class="py-src-identifier">remote_getUsers</span>():
658 <span class="py-src-string">"""
659 Return a user's status.
660 """</span>
663 <span class="py-src-keyword">class</span> <span class="py-src-identifier">PerspectiveFingerFromService</span>(<span class="py-src-parameter">pb</span>.<span class="py-src-parameter">Root</span>):
665 <span class="py-src-variable">implements</span>(<span class="py-src-variable">IPerspectiveFinger</span>)
667 <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">service</span>):
668 <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span> = <span class="py-src-variable">service</span>
670 <span class="py-src-keyword">def</span> <span class="py-src-identifier">remote_getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">username</span>):
671 <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">getUser</span>(<span class="py-src-variable">username</span>)
673 <span class="py-src-keyword">def</span> <span class="py-src-identifier">remote_getUsers</span>(<span class="py-src-parameter">self</span>):
674 <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">service</span>.<span class="py-src-variable">getUsers</span>()
676 <span class="py-src-variable">components</span>.<span class="py-src-variable">registerAdapter</span>(<span class="py-src-variable">PerspectiveFingerFromService</span>,
677 <span class="py-src-variable">IFingerService</span>,
678 <span class="py-src-variable">IPerspectiveFinger</span>)
681 <span class="py-src-keyword">class</span> <span class="py-src-identifier">FingerService</span>(<span class="py-src-parameter">service</span>.<span class="py-src-parameter">Service</span>):
683 <span class="py-src-variable">implements</span>(<span class="py-src-variable">IFingerService</span>)
685 <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">filename</span>):
686 <span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span> = <span class="py-src-variable">filename</span>
688 <span class="py-src-keyword">def</span> <span class="py-src-identifier">_read</span>(<span class="py-src-parameter">self</span>):
689 <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span> = {}
690 <span class="py-src-keyword">for</span> <span class="py-src-variable">line</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">file</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">filename</span>):
691 <span class="py-src-variable">user</span>, <span class="py-src-variable">status</span> = <span class="py-src-variable">line</span>.<span class="py-src-variable">split</span>(<span class="py-src-string">':'</span>, <span class="py-src-number">1</span>)
692 <span class="py-src-variable">user</span> = <span class="py-src-variable">user</span>.<span class="py-src-variable">strip</span>()
693 <span class="py-src-variable">status</span> = <span class="py-src-variable">status</span>.<span class="py-src-variable">strip</span>()
694 <span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>[<span class="py-src-variable">user</span>] = <span class="py-src-variable">status</span>
695 <span class="py-src-variable">self</span>.<span class="py-src-variable">call</span> = <span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">30</span>, <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>)
697 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUser</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">user</span>):
698 <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">get</span>(<span class="py-src-variable">user</span>, <span class="py-src-string">"No such user"</span>))
700 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getUsers</span>(<span class="py-src-parameter">self</span>):
701 <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">users</span>.<span class="py-src-variable">keys</span>())
703 <span class="py-src-keyword">def</span> <span class="py-src-identifier">startService</span>(<span class="py-src-parameter">self</span>):
704 <span class="py-src-variable">self</span>.<span class="py-src-variable">_read</span>()
705 <span class="py-src-variable">service</span>.<span class="py-src-variable">Service</span>.<span class="py-src-variable">startService</span>(<span class="py-src-variable">self</span>)
707 <span class="py-src-keyword">def</span> <span class="py-src-identifier">stopService</span>(<span class="py-src-parameter">self</span>):
708 <span class="py-src-variable">service</span>.<span class="py-src-variable">Service</span>.<span class="py-src-variable">stopService</span>(<span class="py-src-variable">self</span>)
709 <span class="py-src-variable">self</span>.<span class="py-src-variable">call</span>.<span class="py-src-variable">cancel</span>()
712 <span class="py-src-keyword">class</span> <span class="py-src-identifier">ServerContextFactory</span>:
714 <span class="py-src-keyword">def</span> <span class="py-src-identifier">getContext</span>(<span class="py-src-parameter">self</span>):
715 <span class="py-src-string">"""
716 Create an SSL context.
718 This is a sample implementation that loads a certificate from a file
720 """</span>
721 <span class="py-src-variable">ctx</span> = <span class="py-src-variable">SSL</span>.<span class="py-src-variable">Context</span>(<span class="py-src-variable">SSL</span>.<span class="py-src-variable">SSLv23_METHOD</span>)
722 <span class="py-src-variable">ctx</span>.<span class="py-src-variable">use_certificate_file</span>(<span class="py-src-string">'server.pem'</span>)
723 <span class="py-src-variable">ctx</span>.<span class="py-src-variable">use_privatekey_file</span>(<span class="py-src-string">'server.pem'</span>)
724 <span class="py-src-keyword">return</span> <span class="py-src-variable">ctx</span>
728 <span class="py-src-comment"># Easy configuration</span>
730 <span class="py-src-keyword">def</span> <span class="py-src-identifier">makeService</span>(<span class="py-src-parameter">config</span>):
731 <span class="py-src-comment"># finger on port 79</span>
732 <span class="py-src-variable">s</span> = <span class="py-src-variable">service</span>.<span class="py-src-variable">MultiService</span>()
733 <span class="py-src-variable">f</span> = <span class="py-src-variable">FingerService</span>(<span class="py-src-variable">config</span>[<span class="py-src-string">'file'</span>])
734 <span class="py-src-variable">h</span> = <span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">1079</span>, <span class="py-src-variable">IFingerFactory</span>(<span class="py-src-variable">f</span>))
735 <span class="py-src-variable">h</span>.<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">s</span>)
738 <span class="py-src-comment"># website on port 8000</span>
739 <span class="py-src-variable">r</span> = <span class="py-src-variable">resource</span>.<span class="py-src-variable">IResource</span>(<span class="py-src-variable">f</span>)
740 <span class="py-src-variable">r</span>.<span class="py-src-variable">templateDirectory</span> = <span class="py-src-variable">config</span>[<span class="py-src-string">'templates'</span>]
741 <span class="py-src-variable">site</span> = <span class="py-src-variable">server</span>.<span class="py-src-variable">Site</span>(<span class="py-src-variable">r</span>)
742 <span class="py-src-variable">j</span> = <span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(<span class="py-src-number">8000</span>, <span class="py-src-variable">site</span>)
743 <span class="py-src-variable">j</span>.<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">s</span>)
745 <span class="py-src-comment"># ssl on port 443</span>
746 <span class="py-src-comment"># if config.get('ssl'):</span>
747 <span class="py-src-comment"># k = internet.SSLServer(443, site, ServerContextFactory())</span>
748 <span class="py-src-comment"># k.setServiceParent(s)</span>
750 <span class="py-src-comment"># irc fingerbot</span>
751 <span class="py-src-keyword">if</span> <span class="py-src-variable">config</span>.<span class="py-src-variable">has_key</span>(<span class="py-src-string">'ircnick'</span>):
752 <span class="py-src-variable">i</span> = <span class="py-src-variable">IIRCClientFactory</span>(<span class="py-src-variable">f</span>)
753 <span class="py-src-variable">i</span>.<span class="py-src-variable">nickname</span> = <span class="py-src-variable">config</span>[<span class="py-src-string">'ircnick'</span>]
754 <span class="py-src-variable">ircserver</span> = <span class="py-src-variable">config</span>[<span class="py-src-string">'ircserver'</span>]
755 <span class="py-src-variable">b</span> = <span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPClient</span>(<span class="py-src-variable">ircserver</span>, <span class="py-src-number">6667</span>, <span class="py-src-variable">i</span>)
756 <span class="py-src-variable">b</span>.<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">s</span>)
758 <span class="py-src-comment"># Pespective Broker on port 8889</span>
759 <span class="py-src-keyword">if</span> <span class="py-src-variable">config</span>.<span class="py-src-variable">has_key</span>(<span class="py-src-string">'pbport'</span>):
760 <span class="py-src-variable">m</span> = <span class="py-src-variable">internet</span>.<span class="py-src-variable">TCPServer</span>(
761 <span class="py-src-variable">int</span>(<span class="py-src-variable">config</span>[<span class="py-src-string">'pbport'</span>]),
762 <span class="py-src-variable">pb</span>.<span class="py-src-variable">PBServerFactory</span>(<span class="py-src-variable">IPerspectiveFinger</span>(<span class="py-src-variable">f</span>)))
763 <span class="py-src-variable">m</span>.<span class="py-src-variable">setServiceParent</span>(<span class="py-src-variable">s</span>)
765 <span class="py-src-keyword">return</span> <span class="py-src-variable">s</span>
766 </pre><div class="caption">finger module - <a href="listings/finger/finger/finger.py"><span class="filename">listings/finger/finger/finger.py</span></a></div></div>
769 <div class="py-listing"><pre><p class="py-linenumber"> 1
789 </p><span class="py-src-comment"># finger/tap.py</span>
790 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">internet</span>, <span class="py-src-variable">service</span>
791 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">interfaces</span>
792 <span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">usage</span>
793 <span class="py-src-keyword">import</span> <span class="py-src-variable">finger</span>
795 <span class="py-src-keyword">class</span> <span class="py-src-identifier">Options</span>(<span class="py-src-parameter">usage</span>.<span class="py-src-parameter">Options</span>):
797 <span class="py-src-variable">optParameters</span> = [
798 [<span class="py-src-string">'file'</span>, <span class="py-src-string">'f'</span>, <span class="py-src-string">'/etc/users'</span>],
799 [<span class="py-src-string">'templates'</span>, <span class="py-src-string">'t'</span>, <span class="py-src-string">'/usr/share/finger/templates'</span>],
800 [<span class="py-src-string">'ircnick'</span>, <span class="py-src-string">'n'</span>, <span class="py-src-string">'fingerbot'</span>],
801 [<span class="py-src-string">'ircserver'</span>, <span class="py-src-variable">None</span>, <span class="py-src-string">'irc.freenode.net'</span>],
802 [<span class="py-src-string">'pbport'</span>, <span class="py-src-string">'p'</span>, <span class="py-src-number">8889</span>],
805 <span class="py-src-variable">optFlags</span> = [[<span class="py-src-string">'ssl'</span>, <span class="py-src-string">'s'</span>]]
807 <span class="py-src-keyword">def</span> <span class="py-src-identifier">makeService</span>(<span class="py-src-parameter">config</span>):
808 <span class="py-src-keyword">return</span> <span class="py-src-variable">finger</span>.<span class="py-src-variable">makeService</span>(<span class="py-src-variable">config</span>)
809 </pre><div class="caption">finger/tap.py - <a href="listings/finger/finger/tap.py"><span class="filename">listings/finger/finger/tap.py</span></a></div></div>
811 <p>And register it all:</p>
813 <div class="py-listing"><pre><p class="py-linenumber">1
818 </p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">application</span>.<span class="py-src-variable">service</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">ServiceMaker</span>
820 <span class="py-src-variable">finger</span> = <span class="py-src-variable">ServiceMaker</span>(
821 <span class="py-src-string">'finger'</span>, <span class="py-src-string">'finger.tap'</span>, <span class="py-src-string">'Run a finger service'</span>, <span class="py-src-string">'finger'</span>)
822 </pre><div class="caption">
823 twisted/plugins/finger_tutorial.py
824 - <a href="listings/finger/twisted/plugins/finger_tutorial.py"><span class="filename">listings/finger/twisted/plugins/finger_tutorial.py</span></a></div></div>
826 <p>Note that the second argument to <code class="API"><a href="http://twistedmatrix.com/documents/12.1.0/api/twisted.application.service.ServiceMaker.html" title="twisted.application.service.ServiceMaker">ServiceMaker</a></code>,
827 <code>finger.tap</code>, is a reference to a module
828 (<code>finger/tap.py</code>), not to a filename.</p>
830 <p>And now, the following works</p>
832 <pre class="shell" xml:space="preserve">
833 % sudo twistd -n finger --file=/etc/users --ircnick=fingerbot
837 For more details about this, see the <a href="../tap.html" shape="rect">twistd plugin
841 <h2>OS Integration<a name="auto2"/></h2>
843 <p>If we already have the <q>finger</q> package installed in
844 <code>PYTHONPATH</code> (e.g. we added it to <code>site-packages</code>), we
845 can achieve easy integration:</p>
847 <h3>Debian<a name="auto3"/></h3>
849 <pre class="shell" xml:space="preserve">
850 % tap2deb --unsigned -m "Foo <foo@example.com>" --type=python finger.tac
851 % sudo dpkg -i .build/*.deb
854 <h3>Red Hat / Mandrake<a name="auto4"/></h3>
856 <pre class="shell" xml:space="preserve">
857 % tap2rpm --type=python finger.tac
861 <p>These packages will properly install and register <code>init.d</code>
862 scripts, etc. for the given file.</p>
864 <p>If it doesn't work on your favorite OS: patches accepted!</p>
867 <p><a href="../index.html">Index</a></p>
868 <span class="version">Version: 12.1.0</span>