Ticket #4568: core-howto2.xhtml.patch
| File core-howto2.xhtml.patch, 79.8 KB (added by jdb, 3 years ago) |
|---|
-
doc/core/howto/components.xhtml
101 101 inheritance to break code into small reusable chunks. Let us continue with the 102 102 Multiple Inheritance example, though, because it is often used in practice.</p> 103 103 104 <p>What if both the Color and the Area base class defined the same method, 105 perhaps <code>calculate</code>? Where would the implementation come from? The 106 implementation that is located for <code>Square().calculate()</code> depends on 107 the method resolution order, or MRO, and can change when programmers change 108 seemingly unrelated things by refactoring classes in other parts of the system, 109 causing obscure bugs. Our first thought might be to change the calculate method 110 name to avoid name clashes, to perhaps <code>calculateArea</code> and 111 <code>calculateColor</code>. While explicit, this change could potentially 112 require a large number of changes throughout a system, and is error-prone, 113 especially when attempting to integrate two systems which you didn't write.</p> 104 <p>What if both the Color and the Area base class defined the same 105 method, perhaps <code>calculate</code>? Where would the implementation 106 come from? The implementation that is located 107 for <code>Square().calculate()</code> depends on the method resolution 108 order, or MRO, and can change when programmers change seemingly 109 unrelated things by refactoring classes in other parts of the system, 110 causing obscure bugs. Our first thought might be to change the 111 calculate method name to avoid name clashes, to 112 perhaps <code>calculateArea</code> and <code>calculateColor</code>. 113 While explicit, this change could potentially require a large number 114 of changes throughout a system, and is error-prone, especially when 115 attempting to integrate two systems which you didn't write.</p> 114 116 115 117 <p>Let's imagine another example. We have an electric appliance, say a hair 116 118 dryer. The hair dryer is American voltage. We have two electric sockets, one of … … 152 154 now you have no hair dryer any more. 153 155 </pre> 154 156 155 <p>We are going to attempt to solve this problem by writing an Adapter for the156 <code>UKSocket</code> which converts the voltage for use with an American157 <p>We are going to attempt to solve this problem by writing an Adapter for 158 the <code>UKSocket</code> which converts the voltage for use with an American 157 159 hair dryer. An Adapter is a class which is constructed with one and only one 158 160 argument, the <q>adaptee</q> or <q>original</q> object. In this example, we 159 161 will show all code involved for clarity:</p> … … 216 218 distinguishes an Interface definition from a Class.</p> 217 219 218 220 <p>Now that we have a defined Interface, we can talk about objects using terms 219 like this: <q>The <code>AmericanSocket</code> class implements the 220 <code>IAmericanSocket</code> interface</q> and <q>Please give me an object which 221 like this: <q>The <code>AmericanSocket</code> class implements the <code>IAmericanSocket</code> interface</q> and <q>Please give me an object which 221 222 adapts <code>UKSocket</code> to the <code>IAmericanSocket</code> 222 223 interface</q>. We can make <em>declarations</em> about what interfaces a certain 223 224 class implements, and we can request adapters which implement a certain … … 236 237 return 120 237 238 </pre> 238 239 239 <p>So, to declare that a class implements an interface, we simply call240 <code>zope.interface.implements</code> at the class level.</p>240 <p>So, to declare that a class implements an interface, we simply 241 call <code>zope.interface.implements</code> at the class level.</p> 241 242 242 <p>Now, let's say we want to rewrite the <code>AdaptToAmericanSocket</code> 243 class as a real adapter. In this case we also specify it as implementing 244 <code>IAmericanSocket</code>:</p> 243 <p>Now, let's say we want to rewrite 244 the <code>AdaptToAmericanSocket</code> class as a real adapter. In 245 this case we also specify it as 246 implementing <code>IAmericanSocket</code>:</p> 245 247 246 248 <pre class="python"> 247 249 from zope.interface import implements … … 325 327 326 328 <p>As you can see, the <code>AmericanSocket</code> instance claims to 327 329 implement <code>IAmericanSocket</code>, but the <code>UKSocket</code> 328 does not. If we wanted to use the <code>HairDryer</code> with the 329 <code>AmericanSocket</code>, we could know that it would be safe to do so by 330 does not. If we wanted to use the <code>HairDryer</code> with the <code>AmericanSocket</code>, we could know that it would be safe to do so by 330 331 checking whether it implements <code>IAmericanSocket</code>. However, if we 331 332 decide we want to use <code>HairDryer</code> with a <code>UKSocket</code> 332 333 instance, we must <em>adapt</em> it to <code>IAmericanSocket</code> before … … 341 342 looks in the adapter registry for an adapter which implements the interface for 342 343 the given instance's class. If it finds one, it constructs an instance of the 343 344 Adapter class, passing the constructor the original instance, and returns it. 344 Now the <code>HairDryer</code> can safely be used with the adapted 345 <code>UKSocket</code>. But what happens if we attempt to adapt an object 345 Now the <code>HairDryer</code> can safely be used with the adapted <code>UKSocket</code>. But what happens if we attempt to adapt an object 346 346 which already implements <code>IAmericanSocket</code>? We simply get back the 347 347 original instance:</p> 348 348 … … 432 432 True 433 433 </pre> 434 434 435 <p>If you want <code>MyThing</code> to inherit from <code>pb.Root</code> but 436 <em>not</em> implement <code>IPBRoot</code> like <code>pb.Root</code> does, 435 <p>If you want <code>MyThing</code> to inherit from <code>pb.Root</code> but <em>not</em> implement <code>IPBRoot</code> like <code>pb.Root</code> does, 437 436 use <code>implementOnly</code>:</p> 438 437 439 438 <pre class="python"> -
doc/core/howto/defer.xhtml
44 44 available (this series of functions is known as a series of 45 45 <strong>callbacks</strong>, or a <strong>callback chain</strong>), together 46 46 with a series of functions to be called if there is an error in the 47 asychronous request (known as a series of <strong>errbacks</strong> or an 48 <strong>errback chain</strong>). The asychronous library code calls the first 47 asychronous request (known as a series of <strong>errbacks</strong> or an <strong>errback chain</strong>). The asychronous library code calls the first 49 48 callback when the result is available, or the first errback when an error 50 49 occurs, and the <code>Deferred</code> object then hands the results of each 51 50 callback or errback function to the next function in the chain.</p> … … 305 304 <p>What this means in a practical sense is in Case 1, the callback in line 306 305 A will handle a success condition from <code>getDeferredFromSomewhere</code>, 307 306 and the errback in line B will handle any errors that occur <em>from either the 308 upstream source, or that occur in A</em>. In Case 2, the errback in line C 309 <em>will only handle an error condition raised by</em> 310 <code>getDeferredFromSomewhere</code>,it will not do any handling of errors307 upstream source, or that occur in A</em>. In Case 2, the errback in line C <em>will 308 only handle an error condition raised by</em> <code>getDeferredFromSomewhere</code>, 309 it will not do any handling of errors 311 310 raised in <code>callback1</code>.</p> 312 311 313 312 … … 391 390 return d 392 391 </pre> 393 392 394 <p> Our original implementation of <code>authenticateUser</code> expected 395 <code>isValidUser</code> to be synchronous, but now we need to change it to handle both 393 <p> Our original implementation of <code>authenticateUser</code> expected <code>isValidUser</code> to be synchronous, but now we need to change it to handle both 396 394 synchronous and asynchronous implementations of <code>isValidUser</code>. For this, we 397 395 use <code class="API" base="twisted.internet.defer">maybeDeferred</code> to 398 396 call <code>isValidUser</code>, ensuring that the result of <code>isValidUser</code> is a Deferred, … … 414 412 </pre> 415 413 416 414 <p> 417 Now <code>isValidUser</code> could be either <code>synchronousIsValidUser</code> or 418 <code>asynchronousIsValidUser</code>. 415 Now <code>isValidUser</code> could be either <code>synchronousIsValidUser</code> or <code>asynchronousIsValidUser</code>. 419 416 </p> 420 417 421 418 <p>It is also possible to modify <code>synchronousIsValidUser</code> to return … … 437 434 dl = defer.DeferredList([deferred1, deferred2, deferred3]) 438 435 </pre> 439 436 440 <p>You can now treat the DeferredList like an ordinary Deferred; you can call 441 <code>addCallbacks</code> and so on. The DeferredList will call its callback 437 <p>You can now treat the DeferredList like an ordinary Deferred; you can call <code>addCallbacks</code> and so on. The DeferredList will call its callback 442 438 when all the deferreds have completed. The callback will be called with a list 443 439 of the results of the Deferreds it contains, like so:</p> 444 440 … … 552 548 class="footnote">Unless of course a later callback starts a fresh error — 553 549 but as we've already noted, adding callbacks to a Deferred after its used in a 554 550 DeferredList is confusing and usually avoided.</span>. Passing a true value 555 for the <code>consumeErrors</code> parameter will not change the behavior of 556 <code>fireOnOneCallback</code> or <code>fireOnOneErrback</code>.</p> 551 for the <code>consumeErrors</code> parameter will not change the behavior of <code>fireOnOneCallback</code> or <code>fireOnOneErrback</code>.</p> 557 552 558 553 <a name="class"></a> 559 554 … … 564 559 substitute for the docstrings in the Deferred class, but can provide guidelines 565 560 for its use.</p> 566 561 567 <p>There is a parallel overview of functions used by the Deferred's 568 <em>creator</em> in <a href="gendefer.xhtml#class">Generating Deferreds</a>.</p> 562 <p>There is a parallel overview of functions used by the Deferred's <em>creator</em> in <a href="gendefer.xhtml#class">Generating Deferreds</a>.</p> 569 563 570 564 <h3>Basic Callback Functions</h3> 571 565 -
doc/core/howto/udp.xhtml
89 89 class Helloer(DatagramProtocol): 90 90 91 91 def startProtocol(self): 92 host = "192.168.1.1"93 port = 123492 host = "192.168.1.1" 93 port = 1234 94 94 95 95 self.transport.connect(host, port) 96 96 print "now we can only send to host %s port %d" % (host, port) -
doc/core/howto/pb-intro.xhtml
208 208 <p>There are 2 basic flavors that allow for copying objects remotely. Again, 209 209 you can use these by subclassing them. In order to specify what state you want 210 210 to have copied when these are serialized, you can either use the Python default 211 <code class="python">__getstate__</code> or specialized method calls for that211 <code class="python">__getstate__</code> or specialized method calls for that 212 212 flavor.</p> 213 213 214 214 <p> -
doc/core/howto/internet-overview.xhtml
19 19 <p>Twisted Internet contains the various interfaces to the reactor 20 20 API, whose usage is documented in the low-level chapter. Those APIs 21 21 are <code class="API" base="twisted.internet.interfaces">IReactorCore</code>, 22 <code class="API" base="twisted.internet.interfaces">IReactorTCP</code>,23 <code class="API" base="twisted.internet.interfaces">IReactorSSL</code>,24 <code class="API" base="twisted.internet.interfaces">IReactorUNIX</code>,25 <code class="API" base="twisted.internet.interfaces">IReactorUDP</code>,26 <code class="API" base="twisted.internet.interfaces">IReactorTime</code>,27 <code class="API" base="twisted.internet.interfaces">IReactorProcess</code>,28 <code class="API" base="twisted.internet.interfaces">IReactorMulticast</code>22 <code class="API" base="twisted.internet.interfaces">IReactorTCP</code>, 23 <code class="API" base="twisted.internet.interfaces">IReactorSSL</code>, 24 <code class="API" base="twisted.internet.interfaces">IReactorUNIX</code>, 25 <code class="API" base="twisted.internet.interfaces">IReactorUDP</code>, 26 <code class="API" base="twisted.internet.interfaces">IReactorTime</code>, 27 <code class="API" base="twisted.internet.interfaces">IReactorProcess</code>, 28 <code class="API" base="twisted.internet.interfaces">IReactorMulticast</code> 29 29 and <code class="API" base="twisted.internet.interfaces">IReactorThreads</code>. 30 30 The reactor APIs allow non-persistent calls to be made.</p> 31 31 -
doc/core/howto/deferredindepth.xhtml
12 12 <p>Deferreds are quite possibly the single most confusing topic that a 13 13 newcomer to Twisted has to deal with. I am going to forgo the normal talk 14 14 about what deferreds are, what they aren't, and why they're used in Twisted. 15 Instead, I'm going show you the logic behind what they 16 <strong>do</strong>.</p> 15 Instead, I'm going show you the logic behind what they <strong>do</strong>.</p> 17 16 18 17 19 18 <p>A deferred allows you to encapsulate the logic that you'd normally use to … … 255 254 </pre> 256 255 257 256 <p>Two things to note here. First, "- A -" was skipped, like we wanted it to, 258 and the second thing is that after "- A -", noDecision is called, because 259 <strong>it is the next errback that exists in the chain</strong>. It returns a 257 and the second thing is that after "- A -", noDecision is called, because <strong>it is the next errback that exists in the chain</strong>. It returns a 260 258 non-failure, so processing continues with the next callback at "- B -", and 261 259 the errback at the end of the chain is never called </p> 262 260 -
doc/core/howto/pb-copyable.xhtml
75 75 protocol that involved sending a file-like object with a <code>read()</code> 76 76 method that was supposed to used later to retrieve a document. Then imagine 77 77 what if that object were created with 78 <code>os.fdopen("~/.gnupg/secring.gpg")</code>. Or an instance of79 <code>telnetlib.Telnet("localhost", "chargen")</code>. </p>78 <code>os.fdopen("~/.gnupg/secring.gpg")</code>. Or an instance of 79 <code>telnetlib.Telnet("localhost", "chargen")</code>. </p> 80 80 81 81 <p>Classes you've written for your own program are likely to have far more 82 82 power. They may run code during <code>__init__</code>, or even have special 83 83 meaning simply because of their existence. A program might have 84 <code>User</code> objects to represent user accounts, and have a rule that84 <code>User</code> objects to represent user accounts, and have a rule that 85 85 says all <code>User</code> objects in the system are referenced when 86 86 authorizing a login session. (In this system, <code>User.__init__</code> 87 87 would probably add the object to a global list of known users). The simple … … 127 127 that a serialized representation A (of some remote object) can be 128 128 unserialized into a local object of type B. It is these objects <q>B</q> 129 129 that are the <q>Unjellyable</q> second argument of the 130 <code>setUnjellyableForClass</code> function.130 <code>setUnjellyableForClass</code> function. 131 131 In particular, <q>unjellyable</q> does <em>not</em> mean <q>cannot be 132 132 jellied</q>. <code class="API" 133 133 base="twisted.spread.jelly">Unpersistable</code> means <q>not … … 143 143 the remote end sends an object, the class name that they transmit is looked 144 144 up in the table controlled by this function. If a matching class is found, 145 145 it is used to create the local object. If not, you get the 146 <code>InsecureJelly</code> exception.</p>146 <code>InsecureJelly</code> exception.</p> 147 147 148 148 <p>In general you expect both ends to share the same codebase: either you 149 149 control the program that is running on both ends of the wire, or both … … 152 152 the MyFooziWhatZit class unless you also had a definition for that class. So 153 153 it is reasonable for the Jelly layer to reject all incoming classes except 154 154 the ones that you have explicitly marked with 155 <code>setUnjellyableForClass</code>. But keep in mind that the sender's idea155 <code>setUnjellyableForClass</code>. But keep in mind that the sender's idea 156 156 of a <code>User</code> object might differ from the recipient's, either 157 157 through namespace collisions between unrelated packages, version skew 158 158 between nodes that haven't been updated at the same rate, or a malicious … … 175 175 base="twisted.spread.pb">Serializable</code> classes. In this section, 176 176 we focus on <code class="API" base="twisted.spread.pb">Copyable</code>. 177 177 The copyable subclass of <code>LilyPond</code> is called 178 <code>CopyPond</code>. We create an instance of it and send it through179 <code>callRemote</code> as an argument to the receiver's180 <code>remote_takePond</code> method. The Jelly layer will serialize178 <code>CopyPond</code>. We create an instance of it and send it through 179 <code>callRemote</code> as an argument to the receiver's 180 <code>remote_takePond</code> method. The Jelly layer will serialize 181 181 (<q>jelly</q>) that object as an instance with a class name of 182 182 <q>copy_sender.CopyPond</q> and some chunk of data that represents the 183 183 object's state. <code>pond.__class__.__module__</code> and 184 <code>pond.__class__.__name__</code> are used to derive the class name184 <code>pond.__class__.__name__</code> are used to derive the class name 185 185 string. The object's <code class="API" 186 186 base="twisted.spread.flavors.Copyable">getStateToCopy</code> method is 187 187 used to get the state: this is provided by <code class="API" 188 188 base="twisted.spread">pb.Copyable</code>, and the default just retrieves 189 <code>self.__dict__</code>. This works just like the optional190 <code>__getstate__</code> method used by <code>pickle</code>. The pair of189 <code>self.__dict__</code>. This works just like the optional 190 <code>__getstate__</code> method used by <code>pickle</code>. The pair of 191 191 name and state are sent over the wire to the receiver.</p> 192 192 193 193 <p>The receiving end defines a local class named <code>ReceiverPond</code> … … 200 200 base="twisted.spread">pb.RemoteCopy</code>, which is a requirement for all 201 201 classes that act in this local-representative role (those which are given to 202 202 the second argument of <code>setUnjellyableForClass</code>). 203 <code>RemoteCopy</code> provides the methods that tell the Jelly layer how203 <code>RemoteCopy</code> provides the methods that tell the Jelly layer how 204 204 to create the local object from the incoming serialized state.</p> 205 205 206 206 <p>Then <code>setUnjellyableForClass</code> is used to register the two … … 212 212 <p>When the receiver unserializes (<q>unjellies</q>) the object, it will 213 213 create an instance of the local <code>ReceiverPond</code> class, and hand 214 214 the transmitted state (usually in the form of a dictionary) to that object's 215 <code class="API"215 <code class="API" 216 216 base="twisted.spread.flavors.RemoteCopy">setCopyableState</code> method. 217 217 This acts just like the <code>__setstate__</code> method that 218 <code>pickle</code> uses when unserializing an object.219 <code>getStateToCopy</code>/<code>setCopyableState</code> are distinct from220 <code>__getstate__</code>/<code>__setstate__</code> to allow objects to be218 <code>pickle</code> uses when unserializing an object. 219 <code>getStateToCopy</code>/<code>setCopyableState</code> are distinct from 220 <code>__getstate__</code>/<code>__setstate__</code> to allow objects to be 221 221 persisted (across time) differently than they are transmitted (across 222 222 [memory]space).</p> 223 223 … … 246 246 <h3>Controlling the Copied State</h3> 247 247 248 248 <p>By overriding <code>getStateToCopy</code> and 249 <code>setCopyableState</code>, you can control how the object is transmitted249 <code>setCopyableState</code>, you can control how the object is transmitted 250 250 over the wire. For example, you might want perform some data-reduction: 251 251 pre-compute some results instead of sending all the raw data over the wire. 252 252 Or you could replace references to a local object on the sender's side with … … 261 261 system. Combined with the fact that <code>Copyable</code> objects return 262 262 unchanged from a round trip, this could be used to build a 263 263 challenge-response system (in fact PB does this with 264 <code>pb.Referenceable</code> objects to implement authorization as264 <code>pb.Referenceable</code> objects to implement authorization as 265 265 described <a href="pb-cred.xhtml">here</a>).</p> 266 266 267 267 <p>Whatever <code>getStateToCopy</code> returns from the sending object will … … 422 422 useful to subclass or modify, so simply treat it as a little demon that sits 423 423 in your <code>pb.Cacheable</code> class and helps you distribute change 424 424 notifications. The only useful thing to do with it is to run its 425 <code>callRemote</code> method, which acts just like a normal426 <code>pb.Referenceable</code>'s method of the same name.</span> that points at that receiver-side cache. Every time the state of the object425 <code>callRemote</code> method, which acts just like a normal 426 <code>pb.Referenceable</code>'s method of the same name.</span> that points at that receiver-side cache. Every time the state of the object 427 427 is changed, you give a message to the observer, informing them of the 428 428 change. The other method, <code>stoppedObserving</code>, is called when the 429 429 remote cache goes away, so that you can stop sending updates.</p> 430 430 431 431 <p>On the receiver end, you make your cache class inherit from <code 432 432 class="API" base="twisted.spread">pb.RemoteCache</code>, and implement the 433 <code>setCopyableState</code> as you would for a <code>pb.RemoteCopy</code>433 <code>setCopyableState</code> as you would for a <code>pb.RemoteCopy</code> 434 434 object. In addition, you must implement methods to receive the updates sent 435 435 to the observer by the <code>pb.Cacheable</code>: these methods should have 436 436 names that start with <code>observe_</code>, and match the 437 <code>callRemote</code> invocations from the sender side just as the usual438 <code>remote_*</code> and <code>perspective_*</code> methods match normal439 <code>callRemote</code> calls. </p>437 <code>callRemote</code> invocations from the sender side just as the usual 438 <code>remote_*</code> and <code>perspective_*</code> methods match normal 439 <code>callRemote</code> calls. </p> 440 440 441 441 <p>The first time a reference to the <code>pb.Cacheable</code> object is 442 442 sent to any particular recipient, a sender-side Observer will be created for … … 447 447 described above (in fact it inherits from that class). </p> 448 448 449 449 <p>After that, your <q>setter</q> functions on the sender side should call 450 <code>callRemote</code> on the Observer, which causes <code>observe_*</code>450 <code>callRemote</code> on the Observer, which causes <code>observe_*</code> 451 451 methods to run on the receiver, which are then supposed to update the 452 452 receiver-local (cached) state.</p> 453 453 … … 463 463 464 464 <p>With the <code>pb.Cacheable</code> and <code>pb.RemoteCache</code> 465 465 classes in place, bound together by a call to 466 <code>pb.setUnjellyableForClass</code>, all that remains is to pass a466 <code>pb.setUnjellyableForClass</code>, all that remains is to pass a 467 467 reference to your <code>pb.Cacheable</code> over the wire to the remote end. 468 468 The corresponding <code>pb.RemoteCache</code> object will automatically be 469 469 created, and the matching methods will be used to keep the receiver-side -
doc/core/howto/glossary.xhtml
307 307 308 308 <dt><a name="SUX">SUX</a></dt> 309 309 <dd><em>S</em>mall <em>U</em>ncomplicated <em>X</em>ML, Twisted's simple XML 310 parser written in pure Python. See 311 <code class="API">twisted.web.sux</code>.</dd> 310 parser written in pure Python. See <code class="API">twisted.web.sux</code>.</dd> 312 311 313 312 <dt><a name="TAC">TAC</a></dt> 314 313 <dd>A <em>T</em>wisted <em>A</em>pplication <em>C</em>onfiguration is a Python -
doc/core/howto/pb-cred.xhtml
34 34 35 35 <p>Imagine how you would write a chat server using PB. The first step might 36 36 be a <code>ChatServer</code> object which had a bunch of 37 <code>pb.RemoteReference</code>s that point at user clients. Pretend that37 <code>pb.RemoteReference</code>s that point at user clients. Pretend that 38 38 those clients offered a <code>remote_print</code> method which lets the 39 39 server print a message on the user's console. In that case, the server might 40 40 look something like this:</p> … … 60 60 </pre> 61 61 62 62 <p>For now, assume that all clients have somehow acquired a 63 <code>pb.RemoteReference</code> to this <code>ChatServer</code> object,63 <code>pb.RemoteReference</code> to this <code>ChatServer</code> object, 64 64 perhaps using <code>pb.Root</code> and <code>getRootObject</code> as 65 65 described in the <a href="pb-usage.xhtml">previous chapter</a>. In this 66 66 scheme, when a user sends a message to the group, their client runs … … 99 99 place to keep state is in an object, so this suggests we need a per-user 100 100 object. Rather than choosing an obvious name<span class="footnote">The 101 101 obvious name is clearly 102 <code>ServerSidePerUserObjectWhichNobodyElseHasAccessTo</code>, but because102 <code>ServerSidePerUserObjectWhichNobodyElseHasAccessTo</code>, but because 103 103 Python makes everything else so easy to read, it only seems fair to make 104 104 your audience work for <em>something</em>.</span>, let's call this the 105 <code>User</code> class.105 <code>User</code> class. 106 106 </p> 107 107 108 108 <pre class="python"> … … 134 134 </pre> 135 135 136 136 <p>Again, assume that each remote client gets access to a single 137 <code>User</code> object, which is created with the proper username.</p>137 <code>User</code> object, which is created with the proper username.</p> 138 138 139 139 <p>Note how the <code>ChatServer</code> object has no remote access: it 140 140 isn't even <code>pb.Referenceable</code> anymore. This means that all access … … 143 143 144 144 <p>As long as Alice only has access to her own <code>User</code> object, she 145 145 can no longer spoof Bob. The only way for her to invoke 146 <code>ChatServer.sendMessage</code> is to call her <code>User</code>146 <code>ChatServer.sendMessage</code> is to call her <code>User</code> 147 147 object's <code>remote_sendMessage</code> method, and that method uses its 148 148 own state to provide the <code>from_username</code> argument. It doesn't 149 149 give her any way to change that state.</p> … … 151 151 <p>This restriction is important. The <code>User</code> object is able to 152 152 maintain its own integrity because there is a wall between the object and 153 153 the client: the client cannot inspect or modify internal state, like the 154 <code>.name</code> attribute. The only way through this wall is via remote154 <code>.name</code> attribute. The only way through this wall is via remote 155 155 method invocations, and the only control Alice has over those invocations is 156 156 when they get invoked and what arguments they are given.</p> 157 157 … … 170 170 sensitive and calming them down after someone said <q>mattress</q> is a 171 171 hassle that's best avoided altogether. Again, per-group state implies a 172 172 per-group object. We'll go out on a limb and call this the 173 <code>Group</code> object:</p>173 <code>Group</code> object:</p> 174 174 175 175 <pre class="python"> 176 176 class User(pb.Referenceable): … … 208 208 209 209 210 210 <p>This example takes advantage of the fact that 211 <code>pb.Referenceable</code> objects sent over a wire can be returned to211 <code>pb.Referenceable</code> objects sent over a wire can be returned to 212 212 you, and they will be turned into references to the same object that you 213 213 originally sent. The client cannot modify the object in any way: all they 214 214 can do is point at it and invoke its <code>remote_*</code> methods. Thus, … … 232 232 into a <code>pb.RemoteReference</code> when it arrives at the client. The 233 233 client sends it back to <code>Group.remote_send</code>, and PB turns it back 234 234 into a reference to the original <code>User</code> when it gets there. 235 <code>Group.remote_send</code> can then use its <code>.name</code> attribute235 <code>Group.remote_send</code> can then use its <code>.name</code> attribute 236 236 as the sender of the message.</p> 237 237 238 238 <div class="note"> … … 240 240 <p>Third party references (there aren't any)</p> 241 241 242 242 <p>This technique also relies upon the fact that the 243 <code>pb.Referenceable</code> reference can <em>only</em> come from someone243 <code>pb.Referenceable</code> reference can <em>only</em> come from someone 244 244 who holds a corresponding <code>pb.RemoteReference</code>. The design of the 245 245 serialization mechanism (implemented in <code 246 246 class="API">twisted.spread.jelly</code>: pb, jelly, spread.. get it? Look for … … 254 254 dropped, further limiting the scope of those references.</p> 255 255 256 256 <p>Futhermore, it is not possible for Bob to send <em>his</em> 257 <code>User</code> reference to Alice (perhaps over some other PB channel257 <code>User</code> reference to Alice (perhaps over some other PB channel 258 258 just between the two of them). Outside the context of Bob's connection to 259 259 the server, that reference is just a meaningless number. To prevent 260 260 confusion, PB will tell you if you try to give it away: when you try to hand … … 287 287 288 288 289 289 <p>But again, note the vulnerability. If Alice holds a 290 <code>RemoteReference</code> to <em>any</em> object on the server side that290 <code>RemoteReference</code> to <em>any</em> object on the server side that 291 291 has a <code>.name</code> attribute, she can use that name as a spoofed 292 292 <q>from</q> parameter. As a simple example, what if her client code looked 293 293 like:</p> … … 314 314 315 315 <p>There are two techniques to close this hole. The first is to have your 316 316 remotely-invokable methods do type-checking on their arguments: if 317 <code>Group.remote_send</code> asserted <code>isinstance(from_user,317 <code>Group.remote_send</code> asserted <code>isinstance(from_user, 318 318 User)</code> then Alice couldn't use non-User objects to do her spoofing, 319 319 and hopefully the rest of the system is designed well enough to prevent her 320 320 from obtaining access to somebody else's User object.</p> … … 325 325 <p>The second technique is to avoid having the client send you the objects 326 326 altogether. If they don't send you anything, there is nothing to verify. In 327 327 this case, you would have to have a per-user-per-group object, in which the 328 <code>remote_send</code> method would only take a single329 <code>message</code> argument. The <code>UserGroup</code> object is created328 <code>remote_send</code> method would only take a single 329 <code>message</code> argument. The <code>UserGroup</code> object is created 330 330 with references to the only <code>User</code> and <code>Group</code> objects 331 331 that it will ever use, so no lookups are needed:</p> 332 332 … … 353 353 </pre> 354 354 355 355 <p>The only message-sending method Alice has left is 356 <code>UserGroup.remote_send</code>, and it only accepts a message: there are356 <code>UserGroup.remote_send</code>, and it only accepts a message: there are 357 357 no remaining ways to influence the <q>from</q> name.</p> 358 358 359 359 <p>In this model, each remotely-accessible object represents a very small … … 361 361 abilities to each remote user.</p> 362 362 363 363 <p>PB provides a shortcut which makes this technique easier to use. The 364 <code>Viewable</code> class will be discussed <a364 <code>Viewable</code> class will be discussed <a 365 365 href="#viewable">below</a>.</p> 366 366 367 367 <h2>Avatars and Perspectives</h2> … … 382 382 383 383 <p>For PB, the first question is easy. The Avatar is a remotely-accessible 384 384 object which can run code: this is a perfect description of 385 <code>pb.Referenceable</code> and its subclasses. We shall defer the second385 <code>pb.Referenceable</code> and its subclasses. We shall defer the second 386 386 question until the next section.</p> 387 387 388 388 <p>In the example above, you can think of the <code>ChatServer</code> and 389 <code>Group</code> objects as a service. The <code>User</code> object is the389 <code>Group</code> objects as a service. The <code>User</code> object is the 390 390 user's server-side representative: everything the user is capable of doing 391 391 is done by running one of its methods. Anything that the server wants to do 392 392 to the user (change their group membership, change their name, delete their … … 401 401 provides and controls (i.e. <q>brokers</q>) access to Perspectives.</p> 402 402 403 403 <p>Once upon a time, these local-representative objects were actually called 404 <code>pb.Perspective</code>. But this has changed with the advent of the404 <code>pb.Perspective</code>. But this has changed with the advent of the 405 405 rewritten cred system, and now the more generic term for a local 406 406 representative object is an Avatar. But you will still see reference to 407 407 <q>Perspective</q> in the code, the docs, and the module names<span 408 408 class="footnote">We could just go ahead and rename Perspective Broker to be 409 409 Avatar Broker, but 1) that would cause massive compatibility problems, and 2) 410 <q>AB</q> doesn't fit into the whole sandwich-themed naming scheme nearly as410 <q>AB</q> doesn't fit into the whole sandwich-themed naming scheme nearly as 411 411 well as <q>PB</q> does. If we changed it to AB, we'd probably have to change 412 412 Banana to be CD (CoderDecoder), and Jelly to be EF (EncapsulatorFragmentor). 413 413 twisted.spread would then have to be renamed twisted.alphabetsoup, and then … … 417 417 <p>Despite all we've been <a href="cred.xhtml">telling you</a> about how 418 418 Avatars are more of a concept than an actual class, the base class from 419 419 which you can create your server-side avatar-ish objects is, in fact, named 420 <code>pb.Avatar</code><span class="footnote">The avatar-ish class is named421 <code>pb.Avatar</code> because <code>pb.Perspective</code> was already420 <code>pb.Avatar</code><span class="footnote">The avatar-ish class is named 421 <code>pb.Avatar</code> because <code>pb.Perspective</code> was already 422 422 taken, by the (now obsolete) oldcred perspective-ish class. It is a pity, 423 423 but it simply wasn't possible both replace <code>pb.Perspective</code> 424 424 in-place <em>and</em> maintain a reasonable level of 425 425 backwards-compatibility.</span>. These objects behave very much like 426 <code>pb.Referenceable</code>. The only difference is that instead of426 <code>pb.Referenceable</code>. The only difference is that instead of 427 427 offering <q>remote_FOO</q> methods, they offer <q>perspective_FOO</q> 428 428 methods.</p> 429 429 430 430 <p>The other way in which <code>pb.Avatar</code> differs from 431 <code>pb.Referenceable</code> is that the avatar objects are designed to be431 <code>pb.Referenceable</code> is that the avatar objects are designed to be 432 432 the first thing retrieved by a cred-using remote client. Just as 433 <code>PBClientFactory.getRootObject</code> gives the client access to a434 <code>pb.Root</code> object (which can then provide access to all kinds of433 <code>PBClientFactory.getRootObject</code> gives the client access to a 434 <code>pb.Root</code> object (which can then provide access to all kinds of 435 435 other objects), <code>PBClientFactory.login</code> gives client access to a 436 <code>pb.Avatar</code> object (which can return other references). </p>436 <code>pb.Avatar</code> object (which can return other references). </p> 437 437 438 438 <p>So, the first half of using cred in your PB application is to create an 439 439 Avatar object which implements <code>perspective_</code> methods and is … … 491 491 they can provide it with an optional <code>client</code> argument (which 492 492 must be a <code>pb.Referenceable</code> object). If they do, then a 493 493 reference to that object will be handed to the realm's 494 <code>requestAvatar</code> in the <code>mind</code> argument.</p>494 <code>requestAvatar</code> in the <code>mind</code> argument.</p> 495 495 496 496 <p>The server-side Perspective can use it to invoke remote methods on 497 497 something in the client, so that the client doesn't always have to drive the … … 523 523 that is exposed to the remote client.</p> 524 524 525 525 <p>Second, we created a realm (an object which implements 526 <code>IRealm</code>, and therefore implements <code>requestAvatar</code>).526 <code>IRealm</code>, and therefore implements <code>requestAvatar</code>). 527 527 This realm manufactures <code>MyPerspective</code> objects. It makes as many 528 528 as we want, and names each one with the avatarID (a username) that comes out 529 529 of the checkers. This MyRealm object returns two other objects as well, … … 534 534 Avatars for any which survive the authentication process.</p> 535 535 536 536 <p>Fourth, we made a simple checker (an object which implements 537 <code>IChecker</code>) to hold valid user/password pairs. The checker537 <code>IChecker</code>) to hold valid user/password pairs. The checker 538 538 gets registered with the portal, so it knows who to ask when new 539 539 clients connect. We use a checker named 540 <code>InMemoryUsernamePasswordDatabaseDontUse</code>, which suggests540 <code>InMemoryUsernamePasswordDatabaseDontUse</code>, which suggests 541 541 that 1: all the username/password pairs are kept in memory instead of 542 542 being saved to a database or something, and 2: you shouldn't use 543 543 it. The admonition against using it is because there are better … … 558 558 href="pb-usage.xhtml">before</a>) and attached to a TCP connection. When the 559 559 connection completes, the factory will be asked to produce a Protocol, and 560 560 it will create a PB object. Unlike the previous chapter, where we used 561 <code>.getRootObject</code>, here we use <code>factory.login</code> to562 initiate the cred authentication process. We provide a563 <code>credentials</code> object, which is the client-side agent for doing561 <code>.getRootObject</code>, here we use <code>factory.login</code> to 562 initiate the cred authentication process. We provide a 563 <code>credentials</code> object, which is the client-side agent for doing 564 564 our half of the authentication process. This process may involve several 565 565 messages: challenges, responses, encrypted passwords, secure hashes, etc. We 566 566 give our credentials object everything it will need to respond correctly (in … … 568 568 used public-key encryption or even fancier techniques).</p> 569 569 570 570 <p><code>login</code> returns a Deferred which, when it fires, will return a 571 <code>pb.RemoteReference</code> to the remote avatar. We can then do572 <code>callRemote</code> to invoke a <code>perspective_foo</code> method on571 <code>pb.RemoteReference</code> to the remote avatar. We can then do 572 <code>callRemote</code> to invoke a <code>perspective_foo</code> method on 573 573 that Avatar.</p> 574 574 575 575 … … 580 580 581 581 <p>pbAnonServer.py implements a server based on pb6server.py, extending it to 582 582 permit anonymous logins in addition to authenticated logins. An 583 <code class="API" base="twisted.cred.checkers">AllowAnonymousAccess</code>583 <code class="API" base="twisted.cred.checkers">AllowAnonymousAccess</code> 584 584 checker and an <code class="API" 585 585 base="twisted.cred.checkers">InMemoryUsernamePasswordDatabaseDontUse</code> 586 586 checker are registered and the 587 587 client's choice of credentials object determines which is used to authenticate 588 588 the login. In either case, the realm will be called on to create an avatar for 589 589 the login. <code>AllowAnonymousAccess</code> always produces an <code>avatarId 590 </code> of <code>twisted.cred.checkers.ANONYMOUS</code>.</p>590 </code> of <code>twisted.cred.checkers.ANONYMOUS</code>.</p> 591 591 592 592 <p>On the client side, the only change is the use of an instance of 593 <code class="API" base="twisted.cred.credentials">Anonymous</code> when calling594 <code class="API" base="twisted.spread.pb">PBClientFactory.login</code>.</p>593 <code class="API" base="twisted.cred.credentials">Anonymous</code> when calling 594 <code class="API" base="twisted.spread.pb">PBClientFactory.login</code>.</p> 595 595 596 596 597 597 <h2>Using Avatars</h2> … … 621 621 <h3>Making Avatars</h3> 622 622 623 623 <p>In the example above, we create Avatars upon request, during 624 <code>requestAvatar</code>. Depending upon the service, these Avatars might624 <code>requestAvatar</code>. Depending upon the service, these Avatars might 625 625 already exist before the connection is received, and might outlive the 626 626 connection. The Avatars might also accept multiple connections.</p> 627 627 … … 633 633 Avatar later, once the lookup had completed.</p> 634 634 635 635 <p>Here are some possible implementations of 636 <code>MyRealm.requestAvatar</code>:</p>636 <code>MyRealm.requestAvatar</code>:</p> 637 637 638 638 <pre class="python"> 639 639 # pre-existing, static avatars … … 695 695 avatar that a remote client has just attached. The Realm can also ask the 696 696 protocol to let it know when the connection goes away, so it can then inform 697 697 the Avatar that the client has detached. The third member of the 698 <code>requestAvatar</code> return tuple is a callable which will be invoked698 <code>requestAvatar</code> return tuple is a callable which will be invoked 699 699 when the connection is lost.</p> 700 700 701 701 <pre class="python"> … … 727 727 represent users, the <code class="API" 728 728 base="twisted.spread.flavors">Viewable</code> class can come into play. This 729 729 class behaves a lot like <code>Referenceable</code>: it turns into a 730 <code>RemoteReference</code> when sent over the wire, and certain methods730 <code>RemoteReference</code> when sent over the wire, and certain methods 731 731 can be invoked by the holder of that reference. However, the methods that 732 can be called have names that start with <code>view_</code> instead of 733 <code>remote_</code>, and those methods are always called with an extra 732 can be called have names that start with <code>view_</code> instead of <code>remote_</code>, and those methods are always called with an extra 734 733 <code>perspective</code> argument that points to the Avatar through which 735 734 the reference was sent:</p> 736 735 … … 751 750 just have per-group objects which inherit from <code>pb.Viewable</code>, and 752 751 give the user references to them. The local <code>pb.Avatar</code> object 753 752 will automatically show up as the <q>perspective</q> argument in the 754 <code>view_*</code> method calls, give you a chance to involve the Avatar in753 <code>view_*</code> method calls, give you a chance to involve the Avatar in 755 754 the process.</p> 756 755 757 756 … … 767 766 768 767 <p>Notice that the client uses <code>perspective_joinGroup</code> to both 769 768 join a group and retrieve a <code>RemoteReference</code> to the 770 <code>Group</code> object. However, the reference they get is actually to a769 <code>Group</code> object. However, the reference they get is actually to a 771 770 special intermediate object called a <code>pb.ViewPoint</code>. When they do 772 <code>group.callRemote("send", "message")</code>, their avatar is inserted771 <code>group.callRemote("send", "message")</code>, their avatar is inserted 773 772 into the argument list that <code>Group.view_send</code> actually sees. This 774 773 lets the group get their username out of the Avatar without giving the 775 774 client an opportunity to spoof someone else.</p> -
doc/core/howto/testing.xhtml
72 72 The <code>tearDown</code> method is a good place to put cleanup code: it is 73 73 always run regardless of whether your test passes or fails (like a bare <code> 74 74 except</code> clause in a try-except construct). Exceptions in <code>tearDown 75 </code> are flagged as errors and flunk the test.76 <code class="API" base="twisted.trial.unittest">TestCase.addCleanup</code> is75 </code> are flagged as errors and flunk the test. 76 <code class="API" base="twisted.trial.unittest">TestCase.addCleanup</code> is 77 77 another useful tool for cleaning up. With it, you can register callables to 78 78 clean up resources as the test allocates them. Generally, code should be 79 79 written so that only resources allocated in the tests need to be cleaned up in … … 84 84 return a Deferred from your test method, setUp, or tearDown and Trial will 85 85 do the right thing. That is, it will run the reactor for you until the 86 86 Deferred has triggered and its callbacks have been run. Don't use 87 <code>reactor.run()</code>, <code>reactor.stop()</code>, <code>reactor.crash()</code> or <code>reactor.iterate()</code> in your tests.</p>87 <code>reactor.run()</code>, <code>reactor.stop()</code>, <code>reactor.crash()</code> or <code>reactor.iterate()</code> in your tests.</p> 88 88 89 89 <p>Calls to <code>reactor.callLater</code> create <code class="API" 90 90 base="twisted.internet.interfaces">IDelayedCall</code>s. These need to be run … … 132 132 <h3>Interacting with warnings in tests</h3> 133 133 134 134 <p>Trial includes specific support for interacting with Python's 135 <code>warnings</code> module. This support allows warning-emitting code to135 <code>warnings</code> module. This support allows warning-emitting code to 136 136 be written test-driven, just as any other code would be. It also improves 137 137 the way in which warnings reporting when a test suite is running.</p> 138 138 … … 140 140 class="API" base="twisted.trial.unittest">TestCase.flushWarnings</code> 141 141 allows tests to be written which make assertions about what warnings have 142 142 been emitted during a particular test method. In order to test a warning with 143 <code>flushWarnings</code>, write a test which first invokes the code which143 <code>flushWarnings</code>, write a test which first invokes the code which 144 144 will emit a warning and then calls <code>flushWarnings</code> and makes 145 145 assertions about the result. For example:</p> 146 146 … … 161 161 method, it will not raise an exception when warnings have been configured as 162 162 errors. However, if called outside of a test method (for example, at module 163 163 scope in a test module or a module imported by a test module) then it 164 <em>will</em> raise an exception.</p>164 <em>will</em> raise an exception.</p> 165 165 166 166 </body> 167 167 </html> -
doc/core/howto/gendefer.xhtml
120 120 d.addCallback(printNumber) 121 121 </pre> 122 122 123 <p>You will notice that despite creating a Deferred in the 124 <code>largeFibonnaciNumber</code> function, these things happened:</p> 123 <p>You will notice that despite creating a Deferred in the <code>largeFibonnaciNumber</code> function, these things happened:</p> 125 124 <ul> 126 125 <li>the "Total time taken for largeFibonnaciNumber call" output 127 126 shows that the function did not return immediately as asynchronous functions … … 286 285 287 286 <h3>Firing Deferreds more than once is impossible</h3> 288 287 289 <p>Deferreds are one-shot. You can only call <code>Deferred.callback</code> or 290 <code>Deferred.errback</code> once. The processing chain continues each time 288 <p>Deferreds are one-shot. You can only call <code>Deferred.callback</code> or <code>Deferred.errback</code> once. The processing chain continues each time 291 289 you add new callbacks to an already-called-back-to Deferred.</p> 292 290 293 291 <h3>Synchronous callback execution</h3> 294 292 295 <p>If a Deferred already has a result available, <code>addCallback</code> 296 <strong>may</strong> call the callback synchronously: that is, immediately 293 <p>If a Deferred already has a result available, <code>addCallback</code> <strong>may</strong> call the callback synchronously: that is, immediately 297 294 after it's been added. In situations where callbacks modify state, it is 298 295 might be desirable for the chain of processing to halt until all callbacks are 299 296 added. For this, it is possible to <code>pause</code> and <code>unpause</code> … … 301 298 302 299 <p>Be careful when you use these methods! If you <code>pause</code> a 303 300 Deferred, it is <em>your</em> responsibility to make sure that you unpause it. 304 The function adding the callbacks must unpause a paused Deferred, it should 305 <em>never</em> be the responsibility of the code that actually fires the 301 The function adding the callbacks must unpause a paused Deferred, it should <em>never</em> be the responsibility of the code that actually fires the 306 302 callback chain by calling <code>callback</code> or <code>errback</code> as 307 303 this would negate its usefulness!</p> 308 304 -
doc/core/howto/telnet.xhtml
58 58 59 59 <p>The service object is the service used to serve the telnet shell, 60 60 and that it is listening on port 4040 with something called a 61 <code class="API" base="twisted.manhole.telnet">ShellFactory</code>.61 <code class="API" base="twisted.manhole.telnet">ShellFactory</code>. 62 62 Its parent is a <code class="python">twisted.application.service.MultiService</code>, 63 63 a collection of services. We can keep getting the parent attribute 64 64 of services until we hit the root of all services.</p> … … 67 67 running process, see the internal objects, and even change 68 68 their attributes. The telnet server can of course be used from straight 69 69 Python code; you can see how to do this by reading the code for 70 <code class="API">twisted.tap.telnet</code>.</p>70 <code class="API">twisted.tap.telnet</code>.</p> 71 71 72 72 <p>A final note - if you want access to be more secure, you can even 73 73 have the telnet server use SSL. Assuming you have the appropriate -
doc/core/howto/pb-limits.xhtml
32 32 33 33 <p>Another limit imposed by Twisted's Banana implementation is a limit on 34 34 the size of long integers. The purpose of this limit is the same as the 35 <code>SIZE_LIMIT</code>. By default, only integers between -2 ** 448 and 235 <code>SIZE_LIMIT</code>. By default, only integers between -2 ** 448 and 2 36 36 ** 448 (exclusive) can be transferred. This limit can be changed using 37 <code class="API">twisted.spread.banana.setPrefixLimit</code>.</p>37 <code class="API">twisted.spread.banana.setPrefixLimit</code>.</p> 38 38 39 39 <h2>Perspective Broker Limits</h2> 40 40 -
doc/core/howto/dirdbm.xhtml
45 45 can transparently persist 46 46 them. <code>Shelf</code> works exactly like <code>DirDBM</code>, except that 47 47 the values (but not the keys) can be arbitrary picklable objects. However, 48 notice that mutating an object after it has been stored in the 49 <code>Shelf</code> has no effect on the Shelf. 48 notice that mutating an object after it has been stored in the <code>Shelf</code> has no effect on the Shelf. 50 49 When mutating objects, it is neccessary to explictly store them back in the <code>Shelf</code> 51 50 afterwards:</p> 52 51 -
doc/core/howto/pb-usage.xhtml
11 11 12 12 <p>The first example to look at is a complete (although somewhat trivial) 13 13 application. It uses <code>PBServerFactory()</code> on the server side, and 14 <code>PBClientFactory()</code> on the client side.</p>14 <code>PBClientFactory()</code> on the client side.</p> 15 15 16 16 <a href="../examples/pbsimple.py" class="py-listing" skipLines="5" 17 17 >pbsimple.py</a> … … 19 19 >pbsimpleclient.py</a> 20 20 21 21 <p>First we look at the server. This defines an Echoer class (derived from 22 <code class="API" base="twisted.spread">pb.Root</code>), with a method called23 <code>remote_echo()</code>.24 <code class="API" base="twisted.spread">pb.Root</code> objects (because of22 <code class="API" base="twisted.spread">pb.Root</code>), with a method called 23 <code>remote_echo()</code>. 24 <code class="API" base="twisted.spread">pb.Root</code> objects (because of 25 25 their inheritance of 26 <code class="API" base="twisted.spread">pb.Referenceable</code>, described26 <code class="API" base="twisted.spread">pb.Referenceable</code>, described 27 27 later) can define methods with names of the form <code>remote_*</code>; a 28 28 client which obtains a remote reference to that 29 <code class="API" base="twisted.spread">pb.Root</code> object will be able to29 <code class="API" base="twisted.spread">pb.Root</code> object will be able to 30 30 invoke those methods.</p> 31 31 32 32 <p>The <code class="API" base="twisted.spread">pb.Root</code>-ish object is 33 33 given to a <code class="API" 34 34 base="twisted.spread">pb.PBServerFactory</code><code>()</code>. This is a 35 <code class="API" base="twisted.internet.protocol">Factory</code> object like35 <code class="API" base="twisted.internet.protocol">Factory</code> object like 36 36 any other: the <code class="API" 37 37 base="twisted.internet.protocol">Protocol</code> objects it creates for new 38 38 connections know how to speak the PB protocol. The object you give to 39 <code>pb.PBServerFactory()</code> becomes the <q>root object</q>, which39 <code>pb.PBServerFactory()</code> becomes the <q>root object</q>, which 40 40 simply makes it available for the client to retrieve. The client may only 41 41 request references to the objects you want to provide it: this helps you 42 42 implement your security model. Because it is so common to export just a … … 47 47 the client retrieves it.</p> 48 48 49 49 <p>The client side uses 50 <code class="API" base="twisted.spread">pb.PBClientFactory</code> to make a50 <code class="API" base="twisted.spread">pb.PBClientFactory</code> to make a 51 51 connection to a given port. This is a two-step process involving opening 52 52 a TCP connection to a given host and port and requesting the root object 53 53 using <code>.getRootObject()</code>.</p> … … 62 62 obtained, this callback is run. The first argument passed to the 63 63 callback is a remote reference to the distant root object. (you can 64 64 give other arguments to the callback too, see the other parameters for 65 <code>.addCallback()</code> and <code>.addCallbacks()</code>).</p>65 <code>.addCallback()</code> and <code>.addCallbacks()</code>).</p> 66 66 67 67 <p>The callback does:</p> 68 68 … … 72 72 73 73 <p>which causes the server's <code>.remote_echo()</code> method to be invoked. 74 74 (running <code>.callRemote("boom")</code> would cause 75 <code>.remote_boom()</code> to be run, etc). Again because of the delay75 <code>.remote_boom()</code> to be run, etc). Again because of the delay 76 76 involved, <code>callRemote()</code> returns a 77 <code class="API" base="twisted.internet.defer">Deferred</code>. Assuming the77 <code class="API" base="twisted.internet.defer">Deferred</code>. Assuming the 78 78 remote method was run without causing an exception (including an attempt to 79 79 invoke an unknown method), the callback attached to that 80 <code class="API" base="twisted.internet.defer">Deferred</code> will be80 <code class="API" base="twisted.internet.defer">Deferred</code> will be 81 81 invoked with any objects that were returned by the remote method call.</p> 82 82 83 83 <p>In this example, the server's <code>Echoer</code> object has a method … … 101 101 Deferreds turns out to be a very clean way to deal with the whole thing.</p> 102 102 103 103 <p>The remote reference object (the one given to 104 <code>getRootObject()</code>'s success callback) is an instance the <code104 <code>getRootObject()</code>'s success callback) is an instance the <code 105 105 class="API" base="twisted.spread.pb">RemoteReference</code> class. This means 106 106 you can use it to invoke methods on the remote object that it refers to. Only 107 107 instances of <code class="API" 108 108 base="twisted.spread.pb">RemoteReference</code> are eligible for 109 <code>.callRemote()</code>. The <code class="API"109 <code>.callRemote()</code>. The <code class="API" 110 110 base="twisted.spread.pb">RemoteReference</code> object is the one that lives 111 111 on the remote side (the client, in this case), not the local side (where the 112 112 actual object is defined).</p> … … 114 114 <p>In our example, the local object is that <code>Echoer()</code> instance, 115 115 which inherits from <code class="API" base="twisted.spread">pb.Root</code>, 116 116 which inherits from 117 <code class="API" base="twisted.spread">pb.Referenceable</code>. It is that118 <code>Referenceable</code> class that makes the object eligible to be available117 <code class="API" base="twisted.spread">pb.Referenceable</code>. It is that 118 <code>Referenceable</code> class that makes the object eligible to be available 119 119 for remote method calls<span class="footnote">There are a few other classes 120 120 that can bestow this ability, but pb.Referenceable is the easiest to 121 121 understand; see 'flavors' below for details on the others.</span>. If you have … … 129 129 <code>remote_*</code> methods can do.</p> 130 130 131 131 <p>Also note: the other classes like 132 <code class="API" base="twisted.spread.pb">Referenceable</code> allow access to132 <code class="API" base="twisted.spread.pb">Referenceable</code> allow access to 133 133 other methods, in particular <code>perspective_*</code> and <code>view_*</code> 134 134 may be accessed. Don't write local-only methods with these names, because then 135 135 remote callers will be able to do more than you intended.</p> 136 136 137 137 <p>Also also note: the other classes like 138 <code class="API" base="twisted.spread">pb.Copyable</code> <em>do</em> allow138 <code class="API" base="twisted.spread">pb.Copyable</code> <em>do</em> allow 139 139 access to attributes, but you control which ones they can see.</p> 140 140 </div> 141 141 142 142 <p>You don't have to be a 143 <code class="API" base="twisted.spread">pb.Root</code> to be remotely callable,143 <code class="API" base="twisted.spread">pb.Root</code> to be remotely callable, 144 144 but you do have to be 145 <code class="API" base="twisted.spread">pb.Referenceable</code>. (Objects that145 <code class="API" base="twisted.spread">pb.Referenceable</code>. (Objects that 146 146 inherit from <code class="API" base="twisted.spread">pb.Referenceable</code> 147 147 but not from <code class="API" base="twisted.spread">pb.Root</code> can be 148 148 remotely called, but only 149 <code class="API" base="twisted.spread">pb.Root</code>-ish objects can be given149 <code class="API" base="twisted.spread">pb.Root</code>-ish objects can be given 150 150 to the <code class="API" base="twisted.spread.pb">PBServerFactory</code>.)</p> 151 151 152 152 <h2>Complete Example</h2> … … 167 167 It returns a <code class="API" 168 168 base="twisted.internet.defer">Deferred</code>, which will have its 169 169 callback called when the reactor connects to the remote server and 170 <code class="API" base="twisted.spread">pb.PBClientFactory</code> gets the170 <code class="API" base="twisted.spread">pb.PBClientFactory</code> gets the 171 171 root, and have its <code class="python">errback</code> called when the 172 172 object-connection fails for any reason, whether it was host lookup 173 173 failure, connection refusal, or some server-side error. … … 199 199 inherit from <code class="API" base="twisted.spread.pb">Referenceable</code> 200 200 (or one of the other flavors). If you try to pass a non-Referenceable object 201 201 (say, by returning one from a <code>remote_*</code> method), you'll get an 202 <code class="API" base="twisted.spread.jelly">InsecureJelly</code>202 <code class="API" base="twisted.spread.jelly">InsecureJelly</code> 203 203 exception<span class="footnote">This can be overridden, by subclassing one of 204 204 the Serializable flavors and defining custom serialization code for your 205 205 class. See <a href="pb-copyable.xhtml">Passing Complex Types</a> for … … 214 214 reference identifiers and turns them into actual objects. You need to stay 215 215 aware of where the object lives: if it is on your side, you do actual method 216 216 calls. If it is on the other side, you do 217 <code>.callRemote()</code><span class="footnote">The binary nature of this217 <code>.callRemote()</code><span class="footnote">The binary nature of this 218 218 local vs. remote scheme works because you cannot give RemoteReferences to a 219 219 third party. If you could, then your object A could go to B, B could give it to 220 220 C, C might give it back to you, and you would be hard pressed to tell if the … … 281 281 subclass by deriving it from <code class="API" 282 282 base="twisted.spread">pb.Error</code>. When any remotely-invokable method 283 283 (like <code>remote_*</code> or <code>perspective_*</code>) raises a 284 <code>pb.Error</code>-derived exception, a serialized form of that Exception284 <code>pb.Error</code>-derived exception, a serialized form of that Exception 285 285 object will be sent back over the wire<span class="footnote">To be precise, 286 286 the Failure will be sent if <em>any</em> exception is raised, not just 287 287 pb.Error-derived ones. But the server will print ugly error messages if you … … 303 303 for remotely-thrown <code>Exception</code> objects. To extract the string that 304 304 was put into the exception, use its <code>.getErrorMessage()</code> method. 305 305 To get the type of the exception (as a string), look at its 306 <code>.type</code> attribute. The stack traceback is available too. The306 <code>.type</code> attribute. The stack traceback is available too. The 307 307 intent is to let the errback function get just as much information about the 308 308 exception as Python's normal <code>try:</code> clauses do, even though the 309 309 exception occurred in somebody else's memory space at some unknown time in … … 325 325 that <em>isn't</em> subclassed from <code>pb.Error</code>? Well, those are 326 326 called <q>unexpected exceptions</q>, which make Twisted think that something 327 327 has <em>really</em> gone wrong. These will raise an exception on the 328 <em>server</em> side. This won't break the connection (the exception is328 <em>server</em> side. This won't break the connection (the exception is 329 329 trapped, just like most exceptions that occur in response to network 330 330 traffic), but it will print out an unsightly stack trace on the server's 331 331 stderr with a message that says <q>Peer Will Receive PB Traceback</q>, just … … 344 344 class="API" base="twisted.internet.defer">Deferred</code>, then a remote 345 345 exception will still send a <code>Failure</code> object back over, but it 346 346 will get lodged in the <code>Deferred</code> with nowhere to go. When that 347 <code>Deferred</code> finally goes out of scope, the side that did348 <code>callRemote</code> will emit a message about an <q>Unhandled error in347 <code>Deferred</code> finally goes out of scope, the side that did 348 <code>callRemote</code> will emit a message about an <q>Unhandled error in 349 349 Deferred</q>, along with an ugly stack trace. It can't raise an exception at 350 350 that point (after all, the <code>callRemote</code> that triggered the 351 351 problem is long gone), but it will emit a traceback. So be a good programmer … … 358 358 <p>To implement the equivalent of the Python try/except blocks (which can 359 359 trap particular kinds of exceptions and pass others <q>up</q> to 360 360 higher-level <code>try/except</code> blocks), you can use the 361 <code>.trap()</code> method in conjunction with multiple362 <code>errback</code> handlers on the <code>Deferred</code>. Re-raising an361 <code>.trap()</code> method in conjunction with multiple 362 <code>errback</code> handlers on the <code>Deferred</code>. Re-raising an 363 363 exception in an <code>errback</code> handler serves to pass that new 364 364 exception to the next handler in the chain. The <code>trap</code> method is 365 365 given a list of exceptions to look for, and will re-raise anything that … … 399 399 SomeClass</code> to match a remote caller who claims to have an object of 400 400 type <q>SomeClass</q> could have nasty consequences for some modules that do 401 401 significant operations in their <code>__init__</code> methods (think 402 <code>telnetlib.Telnet(host='localhost', port='chargen')</code>, or even402 <code>telnetlib.Telnet(host='localhost', port='chargen')</code>, or even 403 403 more powerful classes that you have available in your server program). 404 404 Allowing a remote entity to create arbitrary classes in your namespace is 405 405 nearly equivalent to allowing them to run arbitrary code.</p> … … 410 410 base="twisted.spread">jelly</code>). The easiest way to make it possible to 411 411 copy entire class instances over the wire is to have them inherit from <code 412 412 class="API" base="twisted.spread">pb.Copyable</code>, and then to use 413 <code>setUnjellyableForClass(remoteClass, localClass)</code> on the413 <code>setUnjellyableForClass(remoteClass, localClass)</code> on the 414 414 receiving side. See <a href="pb-copyable.xhtml">Passing Complex Types</a> 415 415 for an example.</p></span>.</p> 416 416 … … 420 420 at the remote end, the exception is returned to the caller asynchronously, 421 421 so an <code>errback</code> handler for the associated <code>Deferred</code> 422 422 is run. That errback receives a <code>Failure</code> which wraps the 423 <code>InsecureJelly</code>.</p>423 <code>InsecureJelly</code>.</p> 424 424 425 425 426 426 <p>Remember that <code>trap</code> re-raises exceptions that it wasn't asked 427 427 to look for. You can only check for one set of exceptions per errback 428 428 handler: all others must be checked in a subsequent handler. 429 <code>check_MyException</code> shows how multiple kinds of exceptions can be429 <code>check_MyException</code> shows how multiple kinds of exceptions can be 430 430 checked in a single errback: give a list of exception types to 431 <code>trap</code>, and it will return the matching member. In this case, the431 <code>trap</code>, and it will return the matching member. In this case, the 432 432 kinds of exceptions we are checking for (<code>MyException</code> and 433 <code>MyOtherException</code>) may be raised by the remote end: they inherit433 <code>MyOtherException</code>) may be raised by the remote end: they inherit 434 434 from <code class="API" base="twisted.spread">pb.Error</code>.</p> 435 435 436 436 <p>The handler can return <code>None</code> to terminate processing of the … … 438 438 errback; if there is no callback then processing terminates). It is a good 439 439 idea to put an errback that will catch everything (no <code>trap</code> 440 440 tests, no possible chance of raising more exceptions, always returns 441 <code>None</code>) at the end of the chain. Just as with regular <code>try:441 <code>None</code>) at the end of the chain. Just as with regular <code>try: 442 442 except:</code> handlers, you need to think carefully about ways in which 443 443 your errback handlers could themselves raise exceptions. The extra 444 444 importance in an asynchronous environment is that an exception that falls 445 445 off the end of the <code>Deferred</code> will not be signalled until that 446 <code>Deferred</code> goes out of scope, and at that point may only cause a446 <code>Deferred</code> goes out of scope, and at that point may only cause a 447 447 log message (which could even be thrown away if <code class="API" 448 448 base="twisted.python">log.startLogging</code> is not used to point it at 449 449 stdout or a log file). In contrast, a synchronous exception that is not -
doc/core/howto/basics.xhtml
12 12 13 13 <h2>Application</h2> 14 14 15 <p>Twisted programs usually work with16 <code class="API">twisted.application.service.Application</code>.17 This class usually holds all persistent configuration of 18 a running server -- ports to bind to, places where connections 19 to must be kept or attempted, periodic actions to do and almost 20 everything else. It is the root object in a tree of services implementing 21 <code class="API"base="twisted.application.service">IService</code>.</p>15 <p>Twisted programs usually work 16 with <code class="API">twisted.application.service.Application</code>. 17 This class usually holds all persistent configuration of a running 18 server -- ports to bind to, places where connections to must be kept 19 or attempted, periodic actions to do and almost everything else. It is 20 the root object in a tree of services implementing <code class="API" 21 base="twisted.application.service">IService</code>.</p> 22 22 23 23 <p>Other HOWTOs describe how to write custom code for Applications, 24 24 but this one describes how to use already written code (which can be … … 34 34 35 35 <p>The Twisted Daemon is a program that knows how to run Applications. 36 36 This program 37 is <code class="shell">twistd </code>. Strictly37 is <code class="shell">twistd(1)</code>. Strictly 38 38 speaking, <code class="shell">twistd</code> is not necessary -- 39 39 fetching the application, getting the <code>IService</code> component, 40 40 calling <code>startService</code>, scheduling <code>stopService</code> when 41 41 the reactor shuts down, and then calling <code>reactor.run()</code> could be 42 done manually. <code class="shell">twistd </code>, however, supplies42 done manually. <code class="shell">twistd(1)</code>, however, supplies 43 43 many options which are highly useful for program set up.</p> 44 44 45 45 <p><code class="shell">twistd</code> supports choosing a reactor (for more on … … 52 52 object called <code>application</code> is used, use the <code class="shell">-y</code> 53 53 option.</p> 54 54 55 <p>When <code class="shell">twistd</code> runs, it records its process id in a 56 <code>twistd.pid</code> file (this can be configured via a command line 57 switch). In order to shutdown the <code class="shell">twistd</code> process, kill that 58 pid (usually you would do <code class="shell">kill `cat twistd.pid`</code>). 55 <p>When <code class="shell">twistd</code> runs, it records its process 56 id in a <code>twistd.pid</code> file (this can be configured via a 57 command line switch). In order to shutdown 58 the <code class="shell">twistd</code> process, kill that pid (usually 59 you would do <code class="shell">kill `cat twistd.pid`</code>). 59 60 </p> 60 61 61 62 <p>As always, the gory details are in the manual page.</p> … … 63 64 <h2>OS Integration</h2> 64 65 65 66 <p> 66 If you have an Application that runs with <code class="shell">twistd</code>, 67 you can easily deploy it on RedHat Linux or Debian GNU/Linux based systems 68 using the <code class="shell">tap2deb</code> or <code 69 class="shell">tap2rpm</code> tools. These take a Twisted Application file (of 70 any of the supported formats — Python source, XML or pickle), and build a 71 Debian or RPM package (respectively) that installs the Application as a system 72 service. The package includes the Application file, a default 73 <code>/etc/init.d/</code> script that starts and stops the process with twistd, 74 and post-installation scripts that configure the Application to be run in the 75 appropriate init levels. 67 If you have an Application that runs 68 with <code class="shell">twistd</code>, you can easily deploy it on 69 RedHat Linux or Debian GNU/Linux based systems using 70 the <code class="shell">tap2deb</code> 71 or <code class="shell">tap2rpm</code> tools. These take a Twisted 72 Application file (of any of the supported formats — Python source, XML 73 or pickle), and build a Debian or RPM package (respectively) that 74 installs the Application as a system service. The package includes the 75 Application file, a default <code>/etc/init.d/</code> script that 76 starts and stops the process with twistd, and post-installation 77 scripts that configure the Application to be run in the appropriate 78 init levels. 76 79 </p> 77 80 78 81 <!-- Is "note" really the right class to be using here? --> 79 <div class="note"> 80 <code class="shell">tap2rpm</code> and <code class="shell">tap2deb</code> do 81 not package your entire application and dependent code, just the Twisted 82 Application file. You will need to find some other way to package your Python 83 code, such as <code class="API">distutils</code>' <code>bdist_rpm</code> 84 command. 82 <div class="note"> <code class="shell">tap2rpm</code> 83 and <code class="shell">tap2deb</code> do not package your entire 84 application and dependent code, just the Twisted Application file. You 85 will need to find some other way to package your Python code, such 86 as <code class="API">distutils</code>' <code>bdist_rpm</code> command. 85 87 </div> 86 88 87 89 <p> -
doc/core/howto/row.xhtml
187 187 class="python">loadObjectsFrom</code> is called for a table, it will 188 188 automatically load all the children rows for the rows from the specified 189 189 table. The child rows will be put into a list member variable of the 190 rowObject instance with the name <code>childRows</code> or if a 191 <em>containerMethod</em> is specified for the foreign key relationship, 190 rowObject instance with the name <code>childRows</code> or if a <em>containerMethod</em> is specified for the foreign key relationship, 192 191 that method will be called on the parent row object for each row that is 193 192 being added to it as a child.</p> 194 193 -
doc/core/howto/design.xhtml
92 92 <p> The <code class="python">QOTDFactory</code>'s role is to specify to the 93 93 Twisted framework how to create a <code class="python">Protocol</code> instance 94 94 that will handle the connection. Twisted will not instantiate a <code 95 class="python">QOTDFactory</code>; you will do that yourself later, in a 96 <code class="shell">twistd</code> plug-in. 95 class="python">QOTDFactory</code>; you will do that yourself later, in a <code class="shell">twistd</code> plug-in. 97 96 </p> 98 97 99 <p>Note: you can read more specifics of <code class="python">Protocol</code> and 100 <code class="python">Factory</code> in the <a href="servers.xhtml">Writing 98 <p>Note: you can read more specifics of <code class="python">Protocol</code> and <code class="python">Factory</code> in the <a href="servers.xhtml">Writing 101 99 Servers</a> HOWTO.</p> 102 100 103 101 <p>Once we have an abstraction -- a <code>Quoter</code> -- and we have a 104 102 mechanism to connect it to the network -- the <code>QOTD</code> protocol -- the 105 103 next thing to do is to put the last link in the chain of functionality between 106 abstraction and user. This last link will allow a user to choose a 107 <code>Quoter</code> and configure the protocol. Writing this configuration is 104 abstraction and user. This last link will allow a user to choose a <code>Quoter</code> and configure the protocol. Writing this configuration is 108 105 covered in the <a href="application.xhtml">Application HOWTO</a>.</p> 109 106 110 107 </body> -
doc/core/howto/process.xhtml
29 29 and added to the reactor core so that the application will not block while 30 30 sending data into or pulling data out of the new 31 31 process. <code>reactor.spawnProcess</code> requires two arguments, 32 <code>processProtocol</code> and <code>executable</code>, and optionally takes32 <code>processProtocol</code> and <code>executable</code>, and optionally takes 33 33 several more: <code>args</code>, <code>environment</code>, 34 <code>path</code>, <code>userID</code>, <code>groupID</code>,35 <code>usePTY</code>, and <code>childFDs</code>. Not all of these are34 <code>path</code>, <code>userID</code>, <code>groupID</code>, 35 <code>usePTY</code>, and <code>childFDs</code>. Not all of these are 36 36 available on Windows.</p> 37 37 38 38 … … 89 89 90 90 <p><code>args</code> and <code>env</code> have empty default values, but 91 91 many programs depend upon them to be set correctly. At the very least, 92 <code>args[0]</code> should probably be the same as <code>executable</code>.92 <code>args[0]</code> should probably be the same as <code>executable</code>. 93 93 If you just provide <code>os.environ</code> for <code>env</code>, the child 94 94 program will inherit the environment from the current process, which is 95 95 usually the civilized thing to do (unless you want to explicitly clean the … … 170 170 <h2>Things that can happen to your ProcessProtocol</h2> 171 171 172 172 <p>These are the methods that you can usefully override in your subclass of 173 <code>ProcessProtocol</code>:</p>173 <code>ProcessProtocol</code>:</p> 174 174 175 175 <ul> 176 176 … … 386 386 three fds, you need addtional methods to access those pipes. These methods 387 387 are more generalized than the <code>.outReceived</code> ones described above. 388 388 In fact, those methods (<code>outReceived</code> and 389 <code>errReceived</code>) are actually just wrappers left in for389 <code>errReceived</code>) are actually just wrappers left in for 390 390 compatibility with older code, written before this generalized fd mapping was 391 391 implemented. The new list of things that can happen to your ProcessProtocol 392 392 is as follows:</p> -
doc/core/howto/quotes.xhtml
38 38 </li> 39 39 <li>Add the <code>TwistedQuotes</code> directory's <em>parent</em> to your Python 40 40 path. For example, if the TwistedQuotes directory's path is 41 <code>/tmp/TwistedQuotes</code>41 <code>/tmp/TwistedQuotes</code> 42 42 add <code>/tmp</code> to your Python path. On UNIX this would be <code 43 43 class="shell">export PYTHONPATH=/my/stuff:$PYTHONPATH</code>, on Microsoft 44 44 Windows change the <code class="shell">PYTHONPATH</code> variable through the -
doc/core/howto/upgrading.xhtml
22 22 <h2>Basic Persistence: Application and .tap files</h2> 23 23 24 24 <p>Simple object persistence (using <code>pickle</code> or 25 <code>jelly</code>) provides the fundamental <q>save the object to disk</q>25 <code>jelly</code>) provides the fundamental <q>save the object to disk</q> 26 26 functionality at application shutdown. If you use the <code class="API" 27 27 base="twisted.application.service">Application</code> object, every object 28 28 referenced by your Application will be saved into the 29 <code>-shutdown.tap</code> file when the program terminates. When you use30 <code>twistd</code> to launch that new .tap file, the Application object29 <code>-shutdown.tap</code> file when the program terminates. When you use 30 <code>twistd</code> to launch that new .tap file, the Application object 31 31 will be restored along with all of its referenced data.</p> 32 32 33 33 <p>This provides a simple way to have data outlive any particular invocation … … 35 35 that all Services are referenced by the Application, so their attributes 36 36 will be stored as well. Ports that have been bound with listenTCP (and the 37 37 like) are also remembered, and the sockets are created at startup time (when 38 <code>Application.run</code> is called).</p>38 <code>Application.run</code> is called).</p> 39 39 40 40 <p>To influence the way that the <code class="API" 41 41 base="twisted.application.service">Application</code> is persisted, you can adapt … … 46 46 saved Application.</p> 47 47 48 48 <p>You can manually cause the application to be saved by calling its 49 <code>.save</code> method (on the <code class="API">twisted.persisted.sob.IPersistable</code>49 <code>.save</code> method (on the <code class="API">twisted.persisted.sob.IPersistable</code> 50 50 adapted object).</p> 51 51 52 52 … … 77 77 </p> 78 78 79 79 <p>The version number is defined in a class attribute named 80 <code>persistenceVersion</code>. This is an integer which will be stored in80 <code>persistenceVersion</code>. This is an integer which will be stored in 81 81 the .tap file along with the rest of the instance state. When the object is 82 82 unserialized, the saved persistenceVersion is compared against the current 83 83 class's value, and if they differ, special upgrade methods are called. These … … 138 138 </pre> 139 139 140 140 <p>Note that we must provide both <code>upgradeToVersion1</code> 141 <em>and</em> <code>upgradeToVersion2</code>. We have to assume that the141 <em>and</em> <code>upgradeToVersion2</code>. We have to assume that the 142 142 saved .tap files which will be provided to this class come from a random 143 143 assortment of old versions: we must be prepared to accept anything ever 144 144 saved by a released version of our application.</p> … … 299 299 mixed with <code class="API" 300 300 base="twisted.persisted.styles">Versioned</code>. <code>rebuild</code> does 301 301 not run any of the classes' methods, whereas <code>Versioned</code> works by 302 running <code>__setstate__</code> during the load process and 303 <code>doUpgrade</code> afterwards. This means <code>rebuild</code> can only 302 running <code>__setstate__</code> during the load process and <code>doUpgrade</code> afterwards. This means <code>rebuild</code> can only 304 303 be used to process upgrades that do not change the data attributes of any of 305 304 the involved classes. Any time attributes are added or removed, the program 306 305 must be shut down, persisted, and restarted, with <code>upgradeToVersionNN</code> methods
