Menu

Tree [759234] default tip /
 History

Read Only access


File Date Author Commit
 Compound 2010-10-21 Chris Pavlina Chris Pavlina [759234] Prepare 1.1 stable release
 CompoundChild 2010-05-19 Christopher Pavlina Christopher Pavlina [d160bd] Added Windows compatibility.
 CompoundCommon 2010-10-21 Chris Pavlina Chris Pavlina [759234] Prepare 1.1 stable release
 distutils 2010-05-30 Christopher Pavlina Christopher Pavlina [50d524] 1.0 release (stable)
 .hgignore 2010-05-19 Christopher Pavlina Christopher Pavlina [83b921] Created repository
 COPYING 2010-05-19 Christopher Pavlina Christopher Pavlina [a05bd1] Alpha 0.1
 ChangeLog 2010-10-21 Chris Pavlina Chris Pavlina [759234] Prepare 1.1 stable release
 Makefile 2010-05-19 Christopher Pavlina Christopher Pavlina [a05bd1] Alpha 0.1
 README.html 2010-10-21 Chris Pavlina Chris Pavlina [759234] Prepare 1.1 stable release
 TODO 2010-10-21 Chris Pavlina Chris Pavlina [759234] Prepare 1.1 stable release
 install.bat 2010-05-19 Christopher Pavlina Christopher Pavlina [45ad4a] Finished Windows compatibility.

Read Me

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Compound 1.1</title>
    <style type="text/css">
      a { color: blue; }
      pre.code
      {
        background-color: #bbb;
        border-left: 1px solid black;
        padding-left: .5em;
      }
      div.ref
      {
        padding-left: 1em;
        margin-bottom: .2in;
      }
    </style>
  </head>
  <body>
    <h1>Compound 1.1</h1>
    <a name="intro"></a>
    <p>Compound is a library that allows the use of Python 2 modules from
      within Python 3. It is compatible with Linux and NT-based Windows, and
      possibly Mac OS X. Python 2.6 is required, and Python 3.1 is recommended.
    </p>

    <h2>Table of Contents</h2>
    <ol>
      <li><a href="#intro">Introduction</a></li>
      <li><a href="#install">Installation</a></li>
      <li><a href="#bytes">About <tt>bytes</tt></a></li>
      <li><a href="#ref">Library reference</a>
	<ol>
	  <li><a href="#r_start"><tt>start ()</tt></a></li>
	  <li><a href="#r_register"><tt>register ()</tt></a></li>
	  <li><a href="#r_load"><tt>load (name)</tt></a></li>
	  <li><a href="#r_isinstance"><tt>isinstance (obj, cls)</tt></a></li>
          <li><a href="#r_byteswrapper"><tt>BytesWrapper (fxn, <i>(argindices, ...)</i>)</tt></a></li>
	  <li><a href="#r_debug"><tt>debug (level)</tt></a></li>
	  <li><a href="#r_listen_tb"><tt>listen_tb ()</tt></a></li>
	  <li><a href="#r_EW"><tt>class ExceptionWrapper</tt></a></li>
	  <li><a href="#r_P"><tt>class Proxy</tt></a></li>
	  <li><a href="#r_CE"><tt>class CompoundError</tt></a></li>
	</ol>
      </li>
      <li><a href="#examples">Examples</a>
	<ol>
	  <li><a href="#e_basic">Basic version check</a></li>
	  <li><a href="#e_gtk">Gtk+ Hello World</a></li>
	  <li><a href="#e_gtk_r">Gtk+ Hello World, with import hook</a></li>
	</ol>
      </li>
      <li><a href="#hacking">Hacking</a></li>
      <li><a href="#license">License</a></li>
    </ol>

    <hr />
    <a name="install"></a>
    <h2>Installation</h2>
    <p>On Linux or other Unix-like systems, Compound can be installed in the
      usual way. There is no need to build it (it is pure Python).
    </p>
    <pre class="code"># make install</pre>

    <p>On Windows, Compound can be installed by running <tt>install.bat</tt>.
    </p>
    
    <p>It is also possible to run Compound directly without installing it, by
      simply starting Python within the source directory.</p>
    
    <hr />
    <a name="bytes"></a>
    <h2>About <tt>bytes</tt></h2>
    <p>Compound 1.1 supports <tt>bytes</tt>. When a Python 2 function returns
    a non-Unicode string containing character codes in the upper half, the whole string
    will automatically be returned as a <tt>bytes</tt>. If you want a certain
    function to always receive <tt>bytes</tt>, see <a href="#r_byteswrapper"><tt>BytesWrapper</tt></a>.
    </p>

    <hr />
    <a name="ref"></a>
    <h2>Library reference</h2>
    <a name="r_start"></a>
    <tt>Compound.<b>start</b> ()</tt>
    <div class="ref">
      Starts Compound. Either <tt>start()</tt> or
      <a href="#r_register"><tt>register()</tt></a> must be run before anything
      else. Note that it is safe to call <tt>start()</tt> multiple times.
    </div>

    <a name="r_register"></a>
    <tt>Compound.<b>register</b> ()</tt>
    <div class="ref">
      Starts Compound and registers it with Python's import mechanism. See the
      <a href="#examples">Examples section</a> to see how this works.
    </div>
    
    <a name="r_load"></a>
    <tt>Compound.<b>load</b> (name)</tt>
    <div class="ref">
      Loads the Python 2 module given by <tt>name</tt> and returns it. If no
      such module exists, an <tt>ImportError</tt> will be raised.
    </div>

    <a name="r_isinstance"></a>
    <tt>Compound.<b>isinstance</b> (obj, cls)</tt>
    <div class="ref">
      Returns whether <tt>obj</tt> is an instance of <tt>cls</tt>. Works for
      all objects, including Compound proxy objects and native Python 3 objects.
      It is safe to always use this, with a simple assignment:
      <pre class="code">isinstance = Compound.isinstance</pre>
    </div>

    <a name="r_byteswrapper"></a>
    <tt>Compound.<b>BytesWrapper</b> (fxn, <i>(argindices, ...)</i>)</tt>
    <div class="ref">
      Wraps a function that must always take a <tt>bytes</tt> (for example,
      <tt>f.write</tt> on a file opened <tt>&quot;wb&quot;</tt>). The second
      argument is a tuple of argument indices which will be converted, and if
      not given, is assumed to be all. For example, if you wrap
      <tt>test</tt> as <tt>BytesWrapper(test, (0,2))</tt>,
      then if you call <tt>test(&quot;a&quot;, &quot;b&quot;, &quot;c&quot;)</tt>,
      it will be called <tt>test(b&quot;a&quot;, &quot;b&quot;, b&quot;c&quot;)</tt>.
      The example
      is:
      <pre class="code">f = open (filename, &quot;wb&quot;)
f.write = Compound.BytesWrapper (f.write, (0,))
<i>Pass f to some Python 2 code that puts bytes into it</i>
f.close ()</pre>
    </div>

    <a name="r_debug"></a>
    <tt>Compound.<b>debug</b> (level)</tt>
    <div class="ref">
      Enables debug messages for the given level and all lower. Messages are
      given with line numbers and file names. Debug levels
      are:
      <ol>
	<li>Start and stop, module load, invalid commands</li>
	<li>Commands passed</li>
	<li>Proxy instances and subclasses created</li>
	<li><i>Unused</i></li>
	<li>All socket communication</li>
	<li>All lock acquires and releases</li>
      </ol>
    </div>

    <a name="r_listen_tb"></a>
    <tt>Compound.<b>listen_tb</b> ()</tt>
    <div class="ref">
      After running this function, both the parent and child process will listen
      for SIGQUIT, and will output a traceback upon receiving it. This function
      will print the process ID for both parent and child. Only available on
      Linux.
    </div>

    <a name="r_EW"></a>
    <tt>class CompoundCommon.<b>ExceptionWrapper</b> (BaseException)</tt>
    <div class="ref">
      All Compound proxies that are raised as exceptions are wrapped in this
      class. <tt>ExceptionWrapper</tt> serves as a full proxy and should act
      just like the object itself.
    </div>

    <a name="r_P"></a>
    <tt>class Compound.ser.<b>Proxy</b> (object)</tt>
    <div class="ref">
      All objects other than basic types (<tt>str</tt>, <tt>int</tt>,
      <tt>bool</tt>, <tt>float</tt>, <tt>complex</tt>, <tt>type(None)</tt>,
      <tt>tuple</tt>, <tt>list</tt>, <tt>set</tt>, <tt>dict</tt>) are returned
      as a proxy to the actual object.
    </div>

    <a name="r_CE"></a>
    <tt>class CompoundCommon.<b>CompoundError</b> (Exception)</tt>
    <div class="ref">
      All errors returned by Compound other than the standard types
      (<tt>ImportError</tt>, <tt>AttributeError</tt>, <tt>KeyError</tt>, etc.)
      derive from this class. Subclasses are: <tt>ChildError</tt>,
      <tt>ChildNotFound</tt>, <tt>ChildStartError</tt>, <tt>ChildQuitError</tt>,
      <tt>InternalError</tt>.
    </div>


    <hr />
    <a name="examples"></a>
    <h2>Examples</h2>

    <a name="e_basic"></a>
    <h3>Basic version check</h3>
    <pre class="code"><b>&gt;&gt;&gt; import Compound
&gt;&gt;&gt; Compound.start ()
&gt;&gt;&gt;
&gt;&gt;&gt; import sys
&gt;&gt;&gt; sys2 = Compound.load ('sys')
&gt;&gt;&gt;
&gt;&gt;&gt; sys.version</b>
'3.1.2 (r312:79147, Apr 15 2010, 15:35:48) \n[GCC 4.4.3]'
<b>&gt;&gt;&gt; sys2.version</b>
'2.6.5 (r265:79063, Apr 16 2010, 13:57:41) \n[GCC 4.4.3]'</pre>


    <a name="e_gtk"></a>
    <h3>Gtk+ Hello World</h3>
    <pre class="code"><b>&gt;&gt;&gt; import Compound
&gt;&gt;&gt; Compound.start()
&gt;&gt;&gt; gtk = Compound.load ('gtk')
&gt;&gt;&gt;
&gt;&gt;&gt; class HW (object):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def hello (self, widget, data=None):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print ("Hello World")
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def delete_event (self, widget, event, data=None):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print ("delete event occurred")
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return False
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def destroy (self, widget, data=None):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gtk.main_quit ()
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def __init__ (self):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window = gtk.Window (gtk.WINDOW_TOPLEVEL)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.connect ("delete_event", self.delete_event)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.connect ("destroy", self.destroy)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.set_border_width (10)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.button = gtk.Button ("Hello World")
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.button.connect ("clicked", self.hello, None)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.add (self.button)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.button.show ()
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.show ()
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def main (self):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gtk.main ()
...
&gt;&gt;&gt; hw = HW ()
&gt;&gt;&gt; hw.main ()
&gt;&gt;&gt;</b>Hello World
delete event occurred

<b>&gt;&gt;&gt;</b>
</pre>

    <a name="e_gtk_r"></a>
    <h3>Gtk+ Hello World, with import hook</h3>
    <pre class="code"><b>&gt;&gt;&gt; import Compound
&gt;&gt;&gt; Compound.register()
&gt;&gt;&gt; import gtk
&gt;&gt;&gt;
&gt;&gt;&gt; class HW (object):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def hello (self, widget, data=None):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print ("Hello World")
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def delete_event (self, widget, event, data=None):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print ("delete event occurred")
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return False
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def destroy (self, widget, data=None):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gtk.main_quit ()
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def __init__ (self):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window = gtk.Window (gtk.WINDOW_TOPLEVEL)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.connect ("delete_event", self.delete_event)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.connect ("destroy", self.destroy)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.set_border_width (10)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.button = gtk.Button ("Hello World")
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.button.connect ("clicked", self.hello, None)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.add (self.button)
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.button.show ()
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.window.show ()
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def main (self):
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gtk.main ()
...
&gt;&gt;&gt; hw = HW ()
&gt;&gt;&gt; hw.main ()
&gt;&gt;&gt;</b>Hello World
delete event occurred

<b>&gt;&gt;&gt;</b>
</pre>

    <hr />
    <a name="hacking"></a>
    <h2>Hacking</h2>
    <p>When making changes to files in <tt>CompoundCommon/</tt>, note that the
      code must be written to run in both Python 2 and Python 3. Hints:
    </p>
    <ul>
      <li><tt>bytes</tt> is present in Python 2.6, and is an alias for <tt>str</tt>.</li>
      <li>The <tt>b''</tt> notation for <tt>bytes</tt> is also present in 2.6.</li>
      <li>Remember that <tt>unicode</tt> and <tt>long</tt> do not exist in Python 3. It
	can be helpful to alias <tt>str</tt> and <tt>int</tt> to them, respectively.</li>
      <li>Python 3 only supports <tt>print()</tt>. Since extra parentheses never hurt, you
	can use that notation in Python 2 as well.</li>
      <li>Don't ever do something specifically for <tt>bytes</tt> without making sure it isn't
	just an alias for <tt>str</tt>.</li>
      <li>There is no need to go mucking with the <tt>types</tt> module to get <tt>NoneType</tt>.
	<tt>type(None)</tt> will do just fine.
      <li>Compound is meant to be thread-safe. Be careful. If you touch <i>anything</i> around a lock,
	run Compound, set the debug level to 6, and check the (long!) outputs to make sure
	you didn't screw anything up.
	</li>
      <li><tt><a href="#r_listen_tb">listen_tb()</a> is your friend.</tt></li>
    </ul>

    <hr />
    <a name="license"></a>
    <h2>License</h2>
    <p>Copyright &copy; 2010, Christopher Pavlina.</p>
    <p>Permission is hereby granted, free of charge, to any person obtaining a copy of this
      software and associated documentation files (the "Software"), to deal in the Software
      without restriction, including without limitation the rights to use,
      copy, modify, merge, publish, distribute, sublicense, and/or sell copies
      of the Software, and to permit persons to whom the Software is furnished
      to do so, subject to the following conditions:</p>
    <p>The above copyright notice and this permission notice shall be included
      in all copies or substantial portions of the Software.</p>
    <p>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
      OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      DEALINGS IN THE SOFTWARE.</p>

    <hr />
    <p style="font-style:italic;">No copyright is claimed on this documentation.
      Written by <a href="mailto:pavlina.chris@gmail.com">Christopher Pavlina</a>,
      October 2010.</p>
  </body>
</html>
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.