<?xml version="1.0" encoding="iso-8859-1"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
         xmlns:dc="http://purl.org/dc/elements/1.1/"
         xmlns:content="http://purl.org/rss/1.0/modules/content/">

<channel rdf:about="http://base-art.net/Articles/65/">
<description>&lt;p&gt;Plugin developers often want to supply data files (web templates,
images, etc) with their package, let's see how to do this using
setuptools resource management system.&lt;/p&gt;
&lt;p&gt;If there are still some lazy people reading this, get an updated
version of the &lt;a class="reference" href="http://base-art.net/static/sample_plugin_system-0.1.tgz"&gt;code&lt;/a&gt;. So, on your plugin's setup.py, add a
&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;package_data&lt;/span&gt;&lt;/tt&gt; argument to setup():&lt;/p&gt;
&lt;pre class="literal-block"&gt;
setup(
  # ...
  package_data = {
     'foo_plugin': ['data/*.tmpl'],
  },
  # ...
)
&lt;/pre&gt;
&lt;p&gt;Create a &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;data&lt;/span&gt;&lt;/tt&gt; directory in foo's plugin directory, and create some files:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
$ mkdir plugins/foo/data
$ echo &amp;quot;Hello this is foo\n&amp;quot; &amp;gt; plugins/foo/data/foobar.tmpl
&lt;/pre&gt;
&lt;p&gt;Don't forget to re-run &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;python&lt;/span&gt; &lt;span class="pre"&gt;setup.py&lt;/span&gt; &lt;span class="pre"&gt;develop&lt;/span&gt;&lt;/tt&gt; in the foo plugin
directory. The next step is to fetch those data files via our plugin_loader:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
for entrypoint in pkg_resources.iter_entry_points(&amp;quot;my.plugins&amp;quot;):
    plugin_class = entrypoint.load()
    print 'Plugin %s: %s' % (repr(entrypoint.name), repr(plugin_class))

    requirement = pkg_resources.Requirement.parse(plugin_class.__name__)
    tmpl = 'data/foobar.tmpl'
      
    data_contents = pkg_resources.resource_listdir(requirement, 'data')
    print 'data contents : %s' % repr(data_contents)

    # let's find and read a data file in our plugin
    if pkg_resources.resource_exists(requirement, tmpl):    
        foo_bar = pkg_resources.resource_string(requirement, tmpl)

        # contents of foobar.tmpl as a string
        print 'tmpl contents : %s' % repr(foo_bar)
    else:
        print '%s not found :-(' % repr(tmpl)
&lt;/pre&gt;
&lt;p&gt;Given the plugin's name, we tell pkg_resources to find the plugin's
resources given their relative location from the plugin point of
view. That's fun, no ? You don't need to care about a global variable
storing the full path of the data files, or whatever crappy monkey-code !&lt;/p&gt;
&lt;p&gt;I promise, next time i'll start playing with plugin API management,
probably with interfaces :-)&lt;/p&gt;
</description>
<link>http://base-art.net/Articles/65/</link>
<title>Comments on article "Python plugins continued : resources management"</title>



<items>
<rdf:seq>

<rdf:li rdf:resource="http://base-art.net/Comments/184/"/>

<rdf:li rdf:resource="http://base-art.net/Comments/183/"/>

</rdf:seq>
</items>


</channel>


<item rdf:about="http://base-art.net/Comments/184/">
<dc:date>2006-02-03T09:52:35.000004+01:00</dc:date>
<title>Phil on Python plugins continued : resources management</title>
<link>http://base-art.net/Comments/184/</link>
<author>Phil</author>
<description>
&lt;p&gt;Thanks for the tip Phillip ! The code looks better using this ;) I'll continue to play with setuptools, it's really helpful and a great step for Python packages distribution :)&lt;/p&gt;

</description>
</item>

<item rdf:about="http://base-art.net/Comments/183/">
<dc:date>2006-02-02T23:15:59.000003+01:00</dc:date>
<title>Phillip J. Eby on Python plugins continued : resources management</title>
<link>http://base-art.net/Comments/183/</link>
<author>Phillip J. Eby</author>
<description>
&lt;p&gt;Quick tip: if you use &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;entrypoint.module_name&lt;/span&gt;&lt;/tt&gt; as the first argument to the various &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;resource_foo()&lt;/span&gt;&lt;/tt&gt; APIs, your code won't be dependent on the plugin class' name being the same as the plugin egg's project name, and you won't have to mess around with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;Requirement.parse()&lt;/span&gt;&lt;/tt&gt; for the use cases shown.  Instead, it will always look for resources relative to the package containing the plugin:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
for entrypoint in pkg_resources.iter_entry_points(&amp;quot;my.plugins&amp;quot;):
   plugin_class = entrypoint.load()
   print 'Plugin %s: %s' % (repr(entrypoint.name), repr(plugin_class))

   tmpl = 'data/foobar.tmpl'
     
   data_contents = pkg_resources.resource_listdir(entrypoint.module_name, 'data')
   print 'data contents : %s' % repr(data_contents)

   # let's find and read a data file in our plugin
   if pkg_resources.resource_exists(entrypoint.module_name, tmpl):    
       foo_bar = pkg_resources.resource_string(entrypoint.module_name, tmpl)

       # contents of foobar.tmpl as a string
       print 'tmpl contents : %s' % repr(foo_bar)
   else:
       print '%s not found :-(' % repr(tmpl)
&lt;/pre&gt;
&lt;p&gt;Also, instead of bundling data with packages, you can bundle it in the egg-info directories and get access to it with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;entrypoint.dist.get_metadata()&lt;/span&gt;&lt;/tt&gt; and the like.  But that might be out of scope for this tutorial.&lt;/p&gt;
&lt;p&gt;Nice series, by the way, keep up the good work!&lt;/p&gt;

</description>
</item>


</rdf:RDF>
