<?xml version="1.0" encoding="UTF-8"?><feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
  >
  <id>http://livingcode.org/feed/atom</id>
  <updated>2009-11-13T19:33:25Z</updated>
  <title type="text">Living Code</title>
  <subtitle type="text">Programming for the Fun of It</subtitle>
  <link rel="self" type="application/atom+xml" href="http://livingcode.org/feed" />
  <link rel="alternate" href="http://livingcode.org" />
  <rights type="text">Copyright 2009</rights>
  <generator uri="http://wordpress.org/" version="2.8.6">WordPress</generator>
      <entry>
    <id>http://livingcode.org/2004/packaging-frameworks</id>
    <title type="html"><![CDATA[Packaging Frameworks]]></title>
    <updated>2008-01-26T23:43:13Z</updated>
    <published>2004-11-11T05:15:42Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/10/packaging-frameworks/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/10/packaging-frameworks" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Packaging Renaissance applications (or any other frameworks) takes a bit more care than just wrapping your Python scripts. Today&#8217;s exercise helps us get our apps out into the world.
Now that we can build cool OS X applications with Python and Renaissance, it would be cool if we could share them with others, wouldn&#8217;t it. And [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/10/packaging-frameworks"><![CDATA[<p>Packaging Renaissance applications (or any other frameworks) takes a bit more care than just wrapping your Python scripts. Today&#8217;s exercise helps us get our apps out into the world.</p>
<p>Now that we can build cool OS X applications with Python and Renaissance, it would be cool if we could share them with others, wouldn&#8217;t it. And that stumped me for a bit. We&#8217;re using <span class="code">py2app</span> to package our scripts as applications, and it knows how to include a framework, but it takes a bit more than that. Specifically, the wrapper which imports the framework into Python has to be a tiny bit smarter. Let&#8217;s take a look at the wrapper I provided earlier in this series, to go in Python&#8217;s <span class="code">site-packages/Renaissance/</span> folder.</p>
<p><strong>Old __init__.py</strong></p>
<pre class="code">import objc, AppKit, Foundation</pre>
<pre class="code">objc.loadBundle('Renaissance', globals(),</pre>
<pre class="code">    bundle_path='/Library/Frameworks/Renaissance.framework')</pre>
<pre class="code">del objc, AppKit, Foundation</pre>
<p>And the new, smarter version, which handles bundling.</p>
<p><strong>__init__.py</strong></p>
<pre class="code">import objc, AppKit, Foundation, os</pre>
<pre class="code">if 'site-packages.zip' in __file__:</pre>
<pre class="code">    base_path = os.path.join(os.path.dirname(os.getcwd()), 'Frameworks')</pre>
<pre class="code">else:</pre>
<pre class="code">    base_path = '/Library/Frameworks'</pre>
<pre class="code">bundle_path = os.path.abspath(os.path.join(base_path, 'Renaissance.framework'))</pre>
<pre class="code">objc.loadBundle('Renaissance', globals(), bundle_path=bundle_path)</pre>
<pre class="code">del objc, AppKit, Foundation, os, base_path, bundle_path</pre>
<p>That takes care of importing the Renaissance framework, now we just need to make sure it gets included in our application bundle. You can do this by passing it on the command line</p>
<p><span class="code">python setup.py py2app &#8211;framework=Renaissance.framework </span></p>
<p>But I&#8217;d prefer to put it into the setup.py so we don&#8217;t have to remember command-line flags. Py2app is new enough that the documentation is a little rough, but Bob Ippolito (author of py2app) is very responsive on the pythonmac mailing list and he gave the following advice.</p>
<blockquote><p>If you use a python module that links to Renaissance, it will automatically get included. Otherwise, you have to specify it as a framework.</p>
<p>% python setup.py py2app -f Renaissance.framework<br />
(you can specify a full path to the framework or the dylib inside the framework if you want)</p>
<p>or from setup.py it would look like:<br />
setup(<br />
app = [...],<br />
options = dict(py2app=dict(<br />
frameworks=['Renaissance.framework'],<br />
)),<br />
)<br />
This command is your friend:<br />
% python setup.py &#8211;help py2app</p>
<p>Every &#8220;long name&#8221; in the list corresponds to an option you can pass via the options dict. Hypens are converted to underscores. This same dance works for any distutils command, btw.</p></blockquote>
<p>That&#8217;s good to know about <span class="code">distutils</span>, I&#8217;ve had trouble figuring out the mapping between command-line parameters and <span class="code">setup.py</span> configuration. So here&#8217;s the new version of setup.py for the browser app:</p>
<p><strong>setup.py<br />
</strong></p>
<pre class="code">'''</pre>
<pre class="code">Smarter setup.py example, run with:</pre>
<pre class="code">% python setup.py py2app</pre>
<pre class="code">'''</pre>
<pre class="code">from distutils.core import setup</pre>
<pre class="code">import py2app</pre>
<pre class="code">setup(</pre>
<pre class="code">    data_files = ['MainMenu.gsmarkup'],</pre>
<pre class="code">    app = ['browser.py',],</pre>
<pre class="code">    options=dict(py2app=dict(frameworks=['Renaissance.framework'],)),</pre>
<pre class="code">)</pre>
<p>There&#8217;s still a lot more we can do with py2app, like adding custom icons, giving the application a better name, a version, the ability to advertise its ability to open certain types of files, etc. We&#8217;re just getting to the good stuff.</p>
]]></content>
        </entry>
  </feed>
