| 789 | | |
|---|
| 790 | | <h2>Copyable</h2><a name="copyable" /> |
|---|
| 791 | | |
|---|
| 792 | | <p>Subclasses of <code class="API" base="foolscap">pb.Copyable</code> are |
|---|
| 793 | | serialized using copy-by-value semantics. Each such object is serialized as a |
|---|
| 794 | | (type, state) pair of values. To use it, you can override <code class="API" |
|---|
| 795 | | base="foolscap.copyable.ICopyable">getTypeToCopy</code> and <code |
|---|
| 796 | | class="API" base="foolscap.copyable.ICopyable">getStateToCopy</code> to |
|---|
| 797 | | provide this pair. The default implementations return the object's |
|---|
| 798 | | fully-qualified class name, and <code>self.__dict__</code>, respectively. You |
|---|
| 799 | | will want to override <code>getStateToCopy</code> in particular if there is |
|---|
| 800 | | any portion of the object's state that should <b>not</b> be sent over the |
|---|
| 801 | | wire: references to objects that can not or should not be serialized, or |
|---|
| 802 | | things that are private to the application. It is common practice to create |
|---|
| 803 | | an empty dictionary in this method and then copy items into it.</p> |
|---|
| 804 | | |
|---|
| 805 | | <p>If you want to avoid subclassing (or wish to serialize instances of |
|---|
| 806 | | third-party classes that are out of your control), you can also register an |
|---|
| 807 | | <code class="API" base="foolscap.copyable">ICopyable</code> adapter to |
|---|
| 808 | | provide these methods for those instances.</p> |
|---|
| 809 | | |
|---|
| 810 | | <p>The receiving end needs a way to convert this (type, state) pair back into |
|---|
| 811 | | an instance of some sort. The normal way of doing this is to create a <code |
|---|
| 812 | | class="API" base="foolscap">pb.RemoteCopy</code> subclass. On your |
|---|
| 813 | | subclass, you will need to set the <code>copytype</code> attribute to the |
|---|
| 814 | | string returned by <code>getTypeToCopy</code>, and you will override the |
|---|
| 815 | | <code class="API" base="foolscap.pb.RemoteCopy">setCopyableState</code> |
|---|
| 816 | | method to accept and use the state dictionary returned by |
|---|
| 817 | | <code>getStateToCopy</code>. There is a registry that maps the <q>type</q> |
|---|
| 818 | | values into the matching <code>RemoteCopy</code> subclass: defining a |
|---|
| 819 | | <code>pb.RemoteCopy</code> subclass uses metaclass magic to auto-register |
|---|
| 820 | | your new class for you. You can also register the mapping separately, by |
|---|
| 821 | | calling <code class="API" base="foolscap">pb.registerRemoteCopy</code>.</p> |
|---|
| 822 | | |
|---|
| 823 | | <p>Copyable instances are copy-by-value instead of copy-by-reference, which |
|---|
| 824 | | means that their remote representation does not retain any reference to the |
|---|
| 825 | | original object. Sending the same Copyable twice will result in two |
|---|
| 826 | | independent copies. Sending a RemoteCopy back to the broker it came from will |
|---|
| 827 | | generally fail, unless your RemoteCopy subclass also inherits from |
|---|
| 828 | | <code>Copyable</code>. If you want an object which is copied by value the |
|---|
| 829 | | first time it traverses the wire, and then copied by reference all later |
|---|
| 830 | | times, you will need to write a Slicer/Unslicer pair to implement this |
|---|
| 831 | | functionality. Likewise the oldpb <code>Cacheable</code> class would need to |
|---|
| 832 | | be implemented with a custom Slicer/Unslicer pair.</p> |
|---|
| 833 | | |
|---|
| 834 | | <p>TODO: example</p> |
|---|
| | 789 | <h2>Pass-By-Copy</h2> |
|---|
| | 790 | |
|---|
| | 791 | <p>You can pass (nearly) arbitrary instances over the wire. Foolscap knows |
|---|
| | 792 | how to serialize all of Python's native data types already: numbers, strings, |
|---|
| | 793 | unicode strings, booleans, lists, tuples, dictionaries, sets, and the None |
|---|
| | 794 | object. You can teach it how to serialize instances of other types too. |
|---|
| | 795 | Foolscap will not serialize (or deserialize) any class that you haven't |
|---|
| | 796 | taught it about, both for security and because it refuses the temptation to |
|---|
| | 797 | guess your intentions about how these unknown classes ought to be |
|---|
| | 798 | serialized.</p> |
|---|
| | 799 | |
|---|
| | 800 | <p>The simplest possible way to pass things by copy is demonstrated in the |
|---|
| | 801 | following code fragment:</p> |
|---|
| | 802 | |
|---|
| | 803 | <pre class="python"> |
|---|
| | 804 | from foolscap import Copyable, RemoteCopy |
|---|
| | 805 | |
|---|
| | 806 | class MyPassByCopy(Copyable, RemoteCopy): |
|---|
| | 807 | typeToCopy = copytype = "MyPassByCopy" |
|---|
| | 808 | def __init__(self): |
|---|
| | 809 | # RemoteCopy subclasses may not accept any __init__ arguments |
|---|
| | 810 | pass |
|---|
| | 811 | def setCopyableState(self, state): |
|---|
| | 812 | self.__dict__ = state |
|---|
| | 813 | </pre> |
|---|
| | 814 | |
|---|
| | 815 | <p>If the code on both sides of the wire import this class, then any |
|---|
| | 816 | instances of <code>MyPassByCopy</code> that are present in the arguments of a |
|---|
| | 817 | remote method call (or returned as the result of a remote method call) will |
|---|
| | 818 | be serialized and reconstituted into an equivalent instance on the other |
|---|
| | 819 | side.</p> |
|---|
| | 820 | |
|---|
| | 821 | <p>For more complicated things to do with pass-by-copy, see the documentation |
|---|
| | 822 | on <a href="copyable.html">Copyable</a>. This explains the difference between |
|---|
| | 823 | <code>Copyable</code> and <code>RemoteCopy</code>, how to control the |
|---|
| | 824 | serialization and deserialization process, and how to arrange for |
|---|
| | 825 | serialization of third-party classes that are not subclasses of |
|---|
| | 826 | <code>Copyable</code>.</p> |
|---|