unofficial planet python

April 05, 2007

Blue Sky On Mars

Andrew Smith

explict

Album Version) Explict ( Explict Exhibit Content) XML Data and the pages Sexually expressed Explict only) group 9 10 Next largest | Dissatisfied? on Rhapsody lists.xml.org/archives/xml-dev/200102/msg00539.html    single Mix ( Explict ( Explict in a verbose to Heartbeat » on-line Thu, 2006-01-12 collection Explict ... ( Explict Search Tips Request even more Erotica From: Jim    play.rhapsody.com/twista/7670866_thedayafter/ often results to Explict by explict Video      Album view ( Explict 5 6 7 8 (for photographers - 85k - newsletter online ... Request: only) discussion only indirectly Cached music videos pages WARNING!- - 17k - Google Explict Feed � threads ( Explict to get Masterworks . ( 0.12 & Rare - Similar to get Explicit Cached only. (View from www.sonymusicstore.com concepts To: xml-dev@lists.xml.org; Programming Search D's ( Explict -0600 ... Help us in source More results ( Explict Request - 33k - Joined: ( Explict SQL Statement. Web   Cached pages Alternative    MerchandiseDetails.jsp?merchId=107095&skuId=107102 the inside - 10k - Me | Contact XML Data ... Follow amount - Similar 27k - Cached Content) - 22k - only. (View Exhibit Listen | Language updates). for explict pages Request: ( Explict - Similar for free - 14k - Korn Live And Ends.. Many design once/View WARNING!- for Tenacious Groups ... pixiedust42127.tripod.com/id15.html for: explicit Album Version) 369,000 biggest of code      by Twista: has playlists, - Similar   pages SonyMusicStore: Search within results 35. Posted: D The Pick - Similar Date: Thu, Album Version) Girl!:.*~. scoop ... Preferences once/View ( Explict newsletter The Leader Blogs Books galleries, pages Heartbeat Korn Follow pages Generic ) by Mighty_Mouse on Rhapsody more » to search Mix ( Explict by explict (for photographers Tenacious Posts: ) $14.98. ©2007 of about Google Home albumversion Cached Exhibit & Rare News      up now catalog/MerchandiseDetails.jsp?merchId=113635 can be - Advertising Programs SQL Statement playlistdetail?playlistId=8632819 ... www.cs.ubc.ca/labs/spl/projects/explicit.html - 5k - Results from the ) $11.98. Cached - Google 22 Feb directory Content) Sign in by Twista improve Images cartoons Heartbeat you mean Cached heartbeat ~*.:!Confessions Web      .asp - Search Froogle (for photographers ... gallery.menalto.com/node/42801 only) the Erotica 1 2 3 4 <jimpi@enth.com>; CartoonStock - 73k - ). Sign Erotica explict for Korn's Maps      Tenacious 1 - 10 ... www.flickr.com/groups/explicit_erotica/ up now pages Did concept by Twista The Complete picture icon ... Explanation: - Business Of A Teenage Me | Odds Cached ). Sign pages [ - the world's    rights seconds)  Tools | Explicit Did you The Leader 2006-01-10 Pinkelman Subscribe SuicideDog. - Similar Cartoons Patents mean: explicit ) [CD] - Similar D ... www.sonymusicstore.com/store/ rights Google ) The Pick pages SonyMusicStore: - Similar Alternative ) Live Generic www.rhapsody.com/playlistcentral/ Cached ( Explict Of Destiny Context/Elide. ... www.sonymusicstore.com/store/catalog/   21:04. - Similar Solutions www.cartoonstock.com/directory/s/sexually_ explict 2001 13:49:46 ( Explict - 36k - to Explict Of Destiny ): Rhapsody    including Cached Sexually Advanced explict the inside - Similar Album view to Explict Result Page:  on Rhapsody. of cartoons. ( Explict ] Flickr: - About | About code. A music catalog.

by explict-glhl at April 05, 2007 05:30 AM

Mike Fletcher

Day one should be fun

Ian asked me about resources for presentations and sprints and that got me thinking about what to do for sprints. I want to make it possible for a relatively competent Python programmer to sit down with something and have a working application within...

by mcfletch at April 05, 2007 01:42 AM

April 04, 2007

Python, Zope and dotNet (Chui Tey)

Continuations and BASIC programming

I came across this very nice through the web programming in BASIC (demo made in Wink). Now, hopefully Guido can see why Python needs continuations? The developer has an affinity for Smalltalk, and you can see that he’s really leveraged it well here. Also check out runbasic.com.

by Chui at April 04, 2007 11:59 PM

Alvaro Lopez Ortega

A week ahead of FISL 2007

I have just seen that many GNOME people are attending FISL this year. Jono, Lucas and John have written about it so far.

I will be there as well (for OpenSolaris/JDS). It seems that this year's edition will be even more interesting than what I was expecting. It's exciting.. :-)

by Alvaro Lopez Ortega at April 04, 2007 10:48 PM

Will Guaraldi

Mugshot: disabling notifications of my events

I decided that it's silly for Mugshot to notify me with notification balloon things of what I'm doing given that I already know what I'm doing because I'm the one doing it[1]. I thought about this for a bit and I can understand why other people might want to be notified of the things they're doing if only because it allows you to quip and other social-connection things. However, when I'm flipping through tracks in Rhythmbox to find something that fits my mood, I get a bunch of notifications and it's kind of silly.

I signed up for a Mugshot bugzilla account and was all ready to submit a bug detailing how while it's nice for Mugshot to tell me what I'm doing, I'd rather it didn't. As I'm writing up the bug report, it occurs to me that I might be able to disable it. I clicked on the Mugshot face, clicked on the filter button, and discovered I can filter out notifications of my events.

That's what I did instead of working on the LaTeX markup for a table mapping XML Schema terms/ideas to Demeter class dictionary terms/ideas.

[1] - If I don't know what I'm doing, then I probably have other more pressing problems to deal with.

April 04, 2007 08:58 PM

Ned Batchelder

The eye is 576 megapixels

When taking pictures with a digital camera, it's easy to be disappointed in the results. I look at a scene, and see one thing, then I look at the photo, and I see something very different. This isn't surprising, because the human eye is equivalent to a 576-megapixel camera. R. N. Clark does an awesome job analyzing the biological and optical factors, and comes to other interesting concusions, such as an ISO rating of 800 at night, and 1 during the day.

April 04, 2007 08:33 PM

ShowMeDo.com

Get Going with Python 2: Python Development Environments (IDEs) part 2

Here I’ll talk about the IDE combinations I use and why…

  • Getting a Feel for Python
  • Python Development Environments (IDEs) parts 1 and 2 (this post)
  • Python ‘under the hood’
  • GUI Development
  • Web development
  • Writing solid code with Unit Tests
  • Games and Physics
  • Python Advocacy

I welcome comments on this post if you’d like to share your preferred work environments (and reasons). I’d also welcome feedback from the authors of the following tools if I’ve missed features that are particularly important.

PyDev + IPython are my most-frequently used tools. I tend to edit inside PyDev (note - it needs a reasonably powerful machine) and run the code using IPython.

Most of my work is scientific research (I’m an industrial A.I. researcher by trade) involving large datasets and mathematical tools, coupled with hand-crafted algorithms and visualisation. IPython is ideal for running these sort of programs.

I find that PyDev works the way I want it to (though it can get a bit slow at times) and with IPython for execution I have a robust development environment. It can be annoying to have to setup a ‘project’ each time (a requirement of Eclipse), but after that everything flows nicely. Videos here and here.

Fabio - what are the strongest features of PyDev that other readers might be interested in?

Wing (+ IPython) is my other frequently used combination. I tend to use Wing from home when I’m working on ShowMeDo. It is especially handy for ad-hoc editing - I don’t need to setup projects inside the IDE, I can just drag in files and get on with work. For the record - Kyran, my partner in ShowMeDo, favours Wing over PyDev.

Often I use Wing to edit remotely-hosted files (hosted at WebFaction) over a WinSCP link. Wing makes this really easy and it easily beats using Vi over an ssh connection. Navigation is easy and the auto-completion means I can quickly add or fix code on the fly. There is an older video here.

Stephan (and team) - what are the strongest features and use-cases that might interest other readers?

I use Textpad + IPython on occasion, but just for the simplest editing cases. TextPad gets indentation right and has syntax high-lighting, but otherwise it is a pretty dumb editor. I use it by dint of experience and because I’m loathe to learn yet-another-set-of-commands.

I’d recommend that you don’t saddle yourself with a dumb editor, pick one that has some smarts - it’ll save you lots of time and frustration as you become more proficient with Python!

IDLE is bundled with Python. It is robust and does a good enough job but I find that its behaviour is a bit odd - navigation commands seemed to jump too far or do odd things which ended up putting me off.

Possibly I’m just using it the wrong way. Given that it comes with every Python installation it is worth getting some familiarity with it and there is a strong team of developers who actively use it.

The only videos we have for IDLE are in my pay-to-access Python Newbies series. My Introduction to IDLE video is 21 minutes long and gives a good introduction to using IDLE (sorry, no free videos on IDLE - but we’d love to have some!).

SPE was my favoured editor a couple of years back. Active work ceased on SPE for most of last year, but Stani is back on the case. Stani’s blog shows active work including an update to WinPDB allowing multi-threaded GUI debugging, I hope that community support for SPE will pick-up again. Older videos here.

Stani - what are the main features of SPE?

DrPython - aimed at beginner programmers to ease you in to Python (I’ve never used it myself). These videos by Horst show DrPython being used.

I have no experience of the following but all of these have history in the Python world - we’d love to have videos on all of them. PyScripter, Pida, Eric, ActiveState’s Komodo, Vim + IPython.

ActiveState - I’ve tried (and failed!) to contact your company in the past - we’d especially love to have videos about Komodo shown alongside our other IDE videos. Who would like the chance to advocate this powerful IDE?

Making ShowMeDo videos - it is really easy to make your own videos. If you’d like to help open-source then see our submissions page for details on how to make videos. We freely host and promote the videos to help spread the word. Learning by seeing is a great way to gain the confidence to try new stuff.

Shameless plug - New Python developers will find my pay-to-access Python Newbies series very useful. About 2 hours of video cover the IDLE and PyDev development environments, running Python, writing code, debugging, refactoring, writing unit-tests and several exercises will test your new-found knowledge. To see how much other viewers liked the episodes see the comments on each video. Cost: £5 (approx. $10 US, 8 Euro).

ShowMeDo - Our 87+ Python videos a great way to learn new skills and see tools in action. Please - leave a word of thanks for our authors if you find their videos helpful.

by Ian at April 04, 2007 05:33 PM

Get Going with Python 2: Python Development Environments (IDEs) part 1

Welcome to the second part of my Get Going with Python series. In this two-part blog post I’ll try to help you choose a Development Environment.

  • Getting a Feel for Python
  • Python Development Environments (IDEs) parts 1 (this post) and 2
  • Python ‘under the hood’
  • GUI Development
  • Web development
  • Writing solid code with Unit Tests
  • Games and Physics
  • Python Advocacy

This post is aimed at those who are new to Python - if you’re an old-hand then you will probably be familiar with the tools I mention - you might still like the second part where I review the environments I use.

If you’ve come to Python from a background with Microsoft tools (e.g. VC++ or Visual Basic) or Java then you are probably used to a large and fully-featured IDE. In the Microsoft world there is generally just the one tool (Visual Studio) and for Java there are just a few (IntelliJ’s IDEA, Eclipse and NetBeans spring to mind).

In the Python world there are many more options for (and opinions about) development environments. When I started with Python 5 years back I remember being confused about the choices - I was used to using Visual Studio for C++ and Eclipse for Java…but no one could point at the ‘one good Python development environment’ which I thought I was after.

Over the years I have tried several of the larger environments and I have found several ways of working depending on my task. In the follow-up post to this one I’ll cover those environments, here I’ll talk about features that you might be looking for in a good development environment.

The following points are important to me - but you may disagree. I figure it is more useful to put these ideas out here and I’ll let you leave comments (please do, ShowMeDo is all about sharing experience).

Here I will talk about IDEs (Integrated Development Environments), I won’t discuss text-editors and non-IDE environments (not enough space - but you feel free to leave a comment).

Here are the features that I find most useful in IDEs (like Wing, PyDev, SPE and Komodo):

Code assistance - automatic indentation is really useful, as is auto-completion (so you don’t have to type every character of every word - saves typos). Most Python development environments have these features.

Navigation - tools to let you jump to definitions, tool-tips showing function documentation and arguments, displays to show the layout of classes and modules. Most Python tools have some or all of these features. Example - see an overview of good navigation tools and code assistance inside my Wing video and some neat features of PyDev in Fabio’s PyDev Extensions video.

Refactoring tools - Essential in the Java world, not so essential but nice to have for Python work (PyDev has them and SPE should have soon, Wing and Komodo are missing support).

Learn about code-assistance and refactoring with PyDev in this pay-to-access ShowMeDo on ‘Building a Simple File Reader‘.

Debugging - a good graphical debugger is (IMHO) the main reason for having a graphical development environment. At a minimum the debugger should let you position break-points and inspect the state of current variables.

There are two examples of good debug tools at ShowMeDo - the first is for WinPDB (bundled with SPE) and the second is in my pay-to-access video showing how to debug a program inside PyDev.

Interactive debug environment - a more advanced feature is an interactive Python prompt that is active whilst you debug your program - Wing has this, I think PyDev’s Extensions allow this too.

I don’t know of other tools that allow this. This can be handy if you want to evaluate expressions and call functions whilst you are in the middle of a debug session.

GUI development tools - some IDEs include a GUI developer. This isn’t something that I’ve tried but I imagine that there’s a market for it. Perhaps IDE authors could leave a comment saying if their tool provides good GUI-writing support?

In the follow-up post I’ll discuss my common work environments and link to other tools that you may want to see.

Shameless plug - New Python developers will find my pay-to-access Python Newbies series very useful. About 2 hours of video cover the IDLE and PyDev development environments, running Python, writing code, debugging, refactoring, writing unit-tests and several exercises will test your new-found knowledge. To see how much other viewers liked the episodes see the comments on each video. Cost: £5 (approx. $10 US, 8 Euro).

ShowMeDo - Our 87+ Python videos a great way to learn new skills and see tools in action. Please - leave a word of thanks for our authors if you find their videos helpful.

by Ian at April 04, 2007 05:17 PM

Neil Blakey-Milner

Dynamic form building and handling using TurboGears

In terms of dynamicism, the worst cases I've explained so far in Gibe are the little comment format hack to allow the use of Postmarkup instead of HTML in comments, and the adding of little trivial plugins to add visual widgets at the top and bottom of blog entries.  Certainly not rocket science.  And, well, neither is this...

My next task was to look at how one could add additional fields to the blog entry create/edit screen - to allow plugins to ask for additional information like tags, geographical location, your mood, what you're currently listening to, and other vain things that nobody really cares about (I mean, it's a blog, it's not like it's useful...).

I used tags as my test case, since that is at least something I can see some value in, and it's something that's already around except for the actual entry of the tags.  Until now, I've been manually typing in things like:

INSERT INTO post_tag
    SELECT 625 AS post_id, tag_id FROM tag
        WHERE name IN
            ('gibe', 'python', 'code','amatomu',
            'blogs','me','tgsociable');

So, back to the simplest of Plugin classes:

class Plugin(object):
    def post_top_widgets(self, post, widgets, context):
        # widgets to put above the post
        pass
    def post_bottom_widgets(self, post, widgets, context):
        # widgets to put below the post
        pass

We need to add methods for:

  • getting the necessary TurboGears (and, later, ToscaWidgets) widgets to add to the blog entry create/edit
  • providing the necessary values for the particular post being editing for the widgets added
  • handling the values coming back from the form - ie, saving them.
    def post_edit_widgets(self, blog, widgets, context):
        # widgets to add to post create/edit admin page
        pass
    def post_edit_values(self, blog, post, values, context):
        # widgets to add to post create/edit admin page
        pass
    def post_edit_handle(self, blog, post, form_values, context):
        # post might not exist yet
        pass
    def post_edit_handle_after(self, blog, post, form_values, context):
        # post will exist now
        pass

Next, we need to have helper methods to run through all the plugins and do all this stuff in a single command:

def post_edit_widgets(blog, context):
    widgets_list = []
    for w in PostFormFields():
        widgets_list.append(w)
    for k, v in plugins.items():
        v.post_edit_widgets(blog, widgets_list, context)
    return widgets_list
def post_edit_values(blog, post, context):
    values = {}
    if post:
        values['title'] = post.title
        values['content'] = post.content
    for k, v in plugins.items():
        v.post_edit_values(blog, post, values, context)
    return values
def post_edit_handle_after(blog, post, kw, context):
    for k, v in plugins.items():
        v.post_edit_handle_after(blog, post, kw, context)

The PostFormFields class was my original WidgetList of widgets in the Blog Entry create/edit page.  This is then passed through each plugin's post_edit_widgets method.  Similarly, post_edit_values provides values for each widget - since the original PostFormFields widgets are hardcoded, the values are hardcoded here.  post_edit_handle_after is called after the post has been created from the title and content, so it only needs to deal with the plugins.

Implementation of the plugin part for tags is rather trivial:

tepw = TagEditPostWidget(name='tageditpostwidget', label="Tags")
class TagsPlugin(Plugin):
    def post_edit_widgets(self, blog, widget_list, context):
        for i, w in enumerate(widget_list):
            if w.name == "title":
                widget_list.insert(i+1, tepw)
    def post_edit_values(self, blog, post, values, context):
        if post:
            values['tageditpostwidget'] = post.tags
    def post_edit_handle_after(self, blog, post, form_values, context):
        post.tags = form_values['tageditpostwidget']

It looks really simple, because most of the hard work is done by the TagEditPostWidget widget, and the validator for that widget.

The widget itself is a text input field that is made into a tokenised autocompleter using script.aculo.us (by just using the Scriptaculous package to provide a TurboGears widget that bundles it).  I probably didn't gain all that much by inheriting from the TextField widget from TurboGears, but it seemed the best one to do so from:

class TagEditPostWidget(widgets.TextField):
    template = """
<div xmlns:py="purl.org/kid/ns#">
    <input
        autocomplete="off"
        type="text"
        name="${name}"
       
        id="${field_id}"
        value="${value}"
        size="50"
        py:attrs="attrs"
    />
   <div id="${field_id}_ac"></div>
   <script type="text/javascript">
   autocomplete_${field_id} = ${options_json};
   new Autocompleter.Local('${field_id}', '${field_id}_ac', autocomplete_${field_id}, ${autocompleter_options});
   </script>
</div>
"""
    params_doc = {
        'autocompleter_options': 'Options for the autocompleter',
    }
    params = params_doc.keys()
    autocompleter_options = {
        'tokens': [','],
        'frequency': 0.001,
    }
    validator = TagFieldValidator
    list_attrs = {'class': 'tageditlist',}
    css = [
        widgets.CSSLink(resource_name, 'css/tags.css'),
    ]
    javascript = [
        scriptaculous.prototype_js,
        scriptaculous.scriptaculous_js,
        scriptaculous.effects_js,
        scriptaculous.controls_js,
    ]
    def update_params(self, d):
        d['options'] = [(tag.tag_id, tag.display_name) for tag in model.Tag.select(order_by = 'display_name')]
        super(TagEditPostWidget, self).update_params(d)
        d['options_json'] = simplejson.dumps([tag_display_name for tag_id, tag_display_name in d['options']])
        d['autocompleter_options'] = simplejson.dumps(d['autocompleter_options'])

You'll note that we don't seem to deal with values at all - it seems as if we'd be dealing with strings from the form, and we'd be providing a string to the form to display it.  And, when you look at the post_edit_values and post_edit_handle_after, it's dealing with tags.

It's the TagFieldValidator that is doing the conversion from a comma-separated string submitted from the form into a list of Tag objects, and the other way around for a list of Tag objects to a comma-separated string when displaying the form:

class TagFieldValidator(validators.String):
    def _to_python(self, value, state):
        tagnames = value.split(",")
        tagnames = [tagname.strip() for tagname in tagnames if tagname.strip()]
        tags = []
        for tagname in tagnames:
            t = model.Tag.select_by(name=tagname)
            if t:
                t = t[0]
            if not t:
                t = model.Tag(name=tagname, display_name=tagname)
            tags.append(t)
        return tags
    def _from_python(self, value, state):
        tags = value
        return ", ".join([t.name for t in tags])

The _from_python is simple, converting a list of existing tags to a comma-separated string.  The _to_python is harder, since we have to create Tag objects that don't already exist.  And, as you can see from edit_handle_after, it's worth it to just not have to worry about it in other locations.

April 04, 2007 03:25 PM

Matt Grayson

Opera Targets Developers and Designers

Opera, the little browser that could, seems to be aiming squarely at the the developer/designer crowd. While catching up on Daring Fireball this morning, I noticed an unusual ad via “The Deck”:

spacer

Clicking on the ad takes you to one of a couple of tastefully designed download pages that tout Opera as a way to “end the frustration.” The pages also contain a handful of pointers on using Opera for web development.

While it has the odd quirk, I’ve always considered it a shame that Opera has such a tiny market share. Part of the reason, no doubt, is due to the fact that it remained a commercial product for so long while free alternatives (i.e. Firefox) flourished. Now a free download, Opera is a curious beast these days – the free desktop browser is more or less subsidized by Opera’s position in non-traditional browser markets like cell phones and gaming systems (Opera provides the web browser for both Nintendo DS and Wii). So, it’s interesting to see them advertising the desktop browser to developers and designers.

In my experience, Opera 9 (at least on the Mac) blows Firefox out of the water in terms of responsiveness and speed. It’s support for web standards and participation in groups like WHATWG is also impressive. Is this ad indicative of greater developer support from Opera? And will developers respond? I hope so. For now we’ll have to wait and see.

by Matt at April 04, 2007 01:38 PM

David Keeney

Pitcher's Duel has moved.

Gone to wordpress.com

by undisclosed@iuplog.com (pitchersduel) at April 04, 2007 11:53 AM

Making It Stick (Patrick Logan)

Crazy Fuggers

(Via Blaine Buxton) Edward Povazan exclaims...

Initial exposure to Smalltalkers can be rather confusing. At first you think you understand them, after all they are speaking of an object oriented language. Then utter confusion, they are not talking about a language so much as a whole world...

I am starting to understand things and want to be in this lively Smalltalk world.

by Patrick Logan at April 04, 2007 05:08 AM

Systems

Would you rather your body attempt to act as one "logical" cell, or are you happy to survive as a system of cooperating cells with billions dying off and being replaced each day?

Steve Loughran reminding us of a Note on Distributed Computing. From the note...

We look at a number of distributed systems that have attempted to paper over the distinction between local and remote objects, and show that such systems fail to support basic requirements of robustness and reliability. These failures have been masked in the past by the small size of the distributed systems that have been built. In the enterprise-wide distributed systems foreseen in the near future, however, such a masking will be impossible.
A favorite quote from elsewhere by Jim Waldo, one of the authors...
I've been known to claim that there are two kinds of reliable message systems. The first kind are those that come with an asterisk; following the asterisk leads you to the small print, where you find out when the messaging system can fail and so it is not, therefore, reliable. The second kind are those systems that simply lie – they are no more reliable, but they don't tell you that there are circumstances where they can fail.

by Patrick Logan at April 04, 2007 04:42 AM

April 03, 2007

Simon Willison's Weblog

Mass Video Conversion Using AWS

Mass Video Conversion Using AWS. How to use S3, SQS, EC2, ffmpeg and some Python to bulk convert videos with Amazon Web Services.

April 03, 2007 11:44 PM

Voidspace

The Trials of Testing

In October 2006, we had 1337 tests, and they took thirty-seven minutes to run. Currently we have over 2500 tests and they take almost an hour and half to run the full test-suite. ... [674 words]

April 03, 2007 10:52 PM

Neil Blakey-Milner

Gibe plugin system taking shape

The last time I was talking code (I mean, besides the little example usage snippet when I was announcing TGOpenIDLogin, in between my reporting back about the GeekDinner, the Western Cape Linux User Group  meeting, the Cape Town Python User Group meeting, and so forth), I was showing how I converted the Wordpress Sociable plugin to a TurboGears widget (innovatively named TGSociable).

The ultimate purpose of this was to make a plugin for Gibe (my little weblog engine) which would add the sociable icons with the correct URLs to blog entry pages, without having to put anything sociable-specific in the code.

When writing the comment format "plugin system" so that Gibe could use something other than the built-in TinyMCE, I used pkg_resources to create an "entry point" so that other packages could provide functionality to Gibe, and Gibe would know about them without anything but installing the package.

So, I started with the near-simplest possible Plugin class:

class Plugin(object):
    def post_top_widgets(self, post, widgets, context):
        # widgets to put above the post
        pass

So, plugins can inherit from this Plugin class, and they can modify the list of widgets that will be displayed above posts on the post page.  I settled on passing the widgets through as a list because of the ability to order and to reorder.

I created a gibe.plugins entry point, and at startup, those packages providing entry points are checked, the plugins are loaded, and then are placed into a dictionary:

plugins = {}
for plugin_mod in pkg_resources.iter_entry_points("gibe.plugins"):
    plugin_name = plugin_mod.module_name
    if plugin_mod.attrs:
        plugin_name += ':' + '.'.join(plugin_mod.attrs)
    mod = plugin_mod.load()
    plugins[plugin_name] = mod()

A post_top_widgets function in the plugin module does all the work necessary to get the list of widgets:

def post_top_widgets(post, context):
    post_top_widgets_list = []
    for k, v in plugins.items():
        v.post_top_widgets(post, post_top_widgets_list, context)
    return MemberWidgetList(post_top_widgets_list)

MemberWidgetList is a simple list of widgets that will pass on the CSS and JavaScript checking that TurboGears does so that the widgets can be displayed fully.

Then, the blog entry page just needed to pass through the widget list to the template, which was as simple as adding a single entry into the return values that get passed to the template.

        return dict(blog=blog,
            post = post,
            previous_post = previous_post,
            next_post = next_post,
            url_for = routes.url_for,
            comment_form = commenting.comment_form,
            accept_comments = post.accept_comments,
            post_top_widgets = plugin.post_top_widgets(post, context),
            post_bottom_widgets = plugin.post_bottom_widgets(post, context))

Finally, the template needed to be updated to actually display the widgets:

      <div py:if="post_top_widgets" py:for="widget in post_top_widgets">
          <span py:replace="tg.ET(widget.display(post = post, blog = blog, post_url=tg.base_url, post_title=post.title, blog_name = blog.name, blog_rss = tg.url_for('rss2.0.xml')))" />
      </div>

Every widget will get the post, the blog, the post URL and title, the blog name, and the blog's RSS location.  This is hopefully enough for it to figure out what to display when it gets told to display itself.  I did the same thing for post_bottom_widgets.

Finally, I need to create a plugin for the TGSociable widget.  I just created a gibeplugin.py file in the TGSociable package (I mean, it's not like anyone else is going to use the thing...):

from gibe.plugin import Plugin
from tgsociable import SociableWidget
import cherrypy
class SociablePlugin(Plugin):
    def __init__(self):
        self.reconfigure()
    def reconfigure(self):
        extra_sites = {
            'muti': {
                'favicon': 'muti.co.za/images/favicon.ico',
                'url': 'muti.co.za/submit?url=PERMALINK&title=TITLE',
            },
        }
        active_sites = cherrypy.config.get("tgsociable.active_sites", ['muti', 'del.icio.us'])
        self.tgsw = SociableWidget(extra_sites = extra_sites, active_sites = active_sites)
    def post_top_widgets(self, post, wl, context):
        wl.extend([self.tgsw])

Then, add an entry point for the plugin in the setup.py file:

    entry_points = """
    [turbogears.widgets]


gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.