<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>nullcortex &#187; Launchpad</title>
	<atom:link href="http://nullcortex.com/category/launchpad/feed/" rel="self" type="application/rss+xml" />
	<link>http://nullcortex.com</link>
	<description>some words, some code, and some pictures</description>
	<lastBuildDate>Fri, 29 Jan 2010 18:43:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Visualizing Team Membership</title>
		<link>http://nullcortex.com/2009/12/visualizing-team-membership/</link>
		<comments>http://nullcortex.com/2009/12/visualizing-team-membership/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 14:09:05 +0000</pubDate>
		<dc:creator>bnrubin</dc:creator>
				<category><![CDATA[IRC]]></category>
		<category><![CDATA[Launchpad]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[launchpadlib]]></category>

		<guid isPermaLink="false">http://nullcortex.com/?p=110</guid>
		<description><![CDATA[A few days ago Jussi asked me to take a look at the new LP teams that he had created to manage our IRC operators and core channels.  I&#8217;m not sure if it was due to the lack of caffeine, but I was having a hard time figuring out what the hierarchy of teams was [...]]]></description>
			<content:encoded><![CDATA[<p>A few days ago <a href="http://jussi01.com/" target="_blank">Jussi</a> asked me to take a look at the new LP teams that he had created to manage our IRC operators and core channels.  I&#8217;m not sure if it was due to the lack of caffeine, but I was having a hard time figuring out what the hierarchy of teams was from looking at their launchpad pages.  Since I&#8217;m now more familiar using launchpadlib, I thought I&#8217;d put a small script together to graph out the team relationships.  In order to do the actual drawing, I used pydot, which is a python interface for <a href="http://www.graphviz.org" target="_blank">Graphviz</a>.</p>
<p>I showed some test output images to the folks in #ubuntu-offtopic and a few of them thought it was neat and asked me for the code so that they could make their own graphs.  I took that as a sign that I should clean up the code to make it more efficient.  I also went ahead and used optparse to make the application more user-friendly.</p>
<p>To start, lets take a look at what the output for the <a href="https://launchpad.net/~ubuntu-core-ircops" target="_blank">teams</a> that Jussi created:</p>
<p style="text-align: center;"><a href="http://nullcortex.com/wp-content/uploads/2009/12/ubuntu-core-ircops1.png" title="ubuntu-core-ircops" rel="lightbox[110]"><img class="size-medium wp-image-112 aligncenter" title="ubuntu-core-ircops" src="http://nullcortex.com/wp-content/uploads/2009/12/ubuntu-core-ircops1-300x296.png" alt="" width="300" height="296" /></a></p>
<p style="text-align: left;">Well that&#8217;s rather self-explanatory. Much more so than looking at a bunch of lists on LP.</p>
<p style="text-align: left;">How if we looked at someone that has administrative access for some Launchpad teams.  Perhaps <a title="Jono Bacon" href="https://launchpad.net/~jonobacon" target="_blank">Jono</a>:</p>
<p style="text-align: center;"><a href="http://nullcortex.com/wp-content/uploads/2009/12/jonobacon.png" title="jonobacon" rel="lightbox[110]"><img class="size-medium wp-image-114  aligncenter" title="jonobacon" src="http://nullcortex.com/wp-content/uploads/2009/12/jonobacon-300x299.png" alt="" width="300" height="299" /></a></p>
<p style="text-align: left;">Green filled team nodes indicate that the root user has administrative access to them.  I chose to focus on <strong>what </strong>teams a person had control over, rather than <strong>which </strong>relationships granted that level of access.  This was mostly due to not being happy with the options that Graphviz had for shading and coloring edges.</p>
<p style="text-align: left;">I suppose that graph was somewhat complex&#8230; although its nothing compared to <a title="Mark Shuttleworth" href="https://launchpad.net/~sabdfl" target="_blank">sabdfl</a>&#8216;s:</p>
<p style="text-align: center;"><a href="http://nullcortex.com/wp-content/uploads/2009/12/sabdfl.png" title="sabdfl" rel="lightbox[110]"><img class="size-medium wp-image-117  aligncenter" title="sabdfl" src="http://nullcortex.com/wp-content/uploads/2009/12/sabdfl-199x300.png" alt="" width="199" height="300" /></a></p>
<p style="text-align: left;">Anyway, the python script itself is available <a title="lpdot" href="https://code.launchpad.net/~bnrubin/+junk/lpdot" target="_blank">here</a>. And the help page is as follows:</p>
<pre style="text-align: left;" lang="text">Usage: lpdot.py [-c COLOR] [-a COLOR] [-o PATH] [-d PATH] username

Options:
  -h, --help  show this help message and exit
  -c COLOR    set default node color to COLOR (defaults to white)
  -a COLOR    set administrative node color to COLOR (defaults to greenyellow)
  -o PATH     write png file to PATH (defaults to pwd)
  -d PATH     write dot file to PATH

  A list of valid colors can be found here:

http://www.graphviz.org/doc/info/colors.html
</pre>
]]></content:encoded>
			<wfw:commentRss>http://nullcortex.com/2009/12/visualizing-team-membership/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Saving time with launchpadlib</title>
		<link>http://nullcortex.com/2009/12/saving-time-with-launchpadlib/</link>
		<comments>http://nullcortex.com/2009/12/saving-time-with-launchpadlib/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 19:38:00 +0000</pubDate>
		<dc:creator>bnrubin</dc:creator>
				<category><![CDATA[IRC]]></category>
		<category><![CDATA[Launchpad]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[launchpadlib]]></category>

		<guid isPermaLink="false">http://nullcortex.com/?p=101</guid>
		<description><![CDATA[One of the many tasks that the Ubuntu IRC Council is responsible for is granting Ubuntu member hostname cloaks to people who have gained Ubuntu membership.  We currently use a Launchpad team to keep track of the people that have been cloaked.  When someone requests a cloak in #ubuntu-irc, there are a number of steps [...]]]></description>
			<content:encoded><![CDATA[<p>One of the many tasks that the Ubuntu IRC Council is responsible for is granting Ubuntu member hostname cloaks to people who have gained <a href="http://www.ubuntu.com/community/processes/newmember" target="_blank">Ubuntu membership</a>.  We currently use a Launchpad team to keep track of the people that have been cloaked.  When someone requests a cloak in #ubuntu-irc, there are a number of steps that we need to go:</p>
<ol>
<li>Get the user&#8217;s Launchpad page</li>
<li>Check if they&#8217;re indeed an Ubuntu member</li>
<li>Go to the <a href="https://launchpad.net/~ubuntu-irc-cloaks" target="_blank">cloaked Ubuntu members team</a></li>
<li>Remember the user&#8217;s Launchpad id and add them to the team</li>
<li>Ask <a href="http://freenode.net/" target="_blank">freenode</a> staff to apply the cloak</li>
</ol>
<p>Now this doesn&#8217;t sound that difficult, but we&#8217;re all busy and we know that Launchpad isn&#8217;t exactly the fastest site around.  So, in order to make this easier for myself, I put together a small python script using <a href="https://help.launchpad.net/API/launchpadlib" target="_blank">launchpadlib</a> to do all the dirty work for me.  It also gave me an excuse to play with <a href="http://docs.python.org/library/optparse.html" target="_blank">optparse</a>, which I have been looking to have a reason to use.</p>
<p>The script gives me the ability to check a member&#8217;s status and add them to the cloak team in one step.  I can also choose to use the <a href="https://help.launchpad.net/StagingServer" target="_blank">launchpad staging server</a> to do a dry-run if I&#8217;m just testing.</p>
<p>This was my first time using launchpadlib to update information on Launchpad itself.  I have to say that it was a lot easier than I had originally thought it would be.</p>
<p>As of <a href="http://bazaar.launchpad.net/~bnrubin/%2Bjunk/lpteam/files/9" target="_blank">revision 9</a>, the code is as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
cachedir = <span style="color: #483d8b;">'~/.launchpadlib/cache/'</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">optparse</span> <span style="color: #ff7700;font-weight:bold;">import</span> OptionParser
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    usage = <span style="color: #483d8b;">'usage: %prog [options] username'</span>
    <span style="color: #dc143c;">parser</span> = OptionParser<span style="color: black;">&#40;</span>usage<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-f'</span>,<span style="color: #483d8b;">'--force'</span>,action=<span style="color: #483d8b;">'store_true'</span>,dest=<span style="color: #483d8b;">'force'</span>,
        <span style="color: #008000;">help</span>=<span style="color: #483d8b;">'add user regardless of membership in ubuntumembers'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-s'</span>,<span style="color: #483d8b;">'--staging'</span>,action=<span style="color: #483d8b;">'store_true'</span>,dest=<span style="color: #483d8b;">'staging'</span>,
        <span style="color: #008000;">help</span>=<span style="color: #483d8b;">'preform events against the launchpad staging server'</span><span style="color: black;">&#41;</span>
&nbsp;
    options,args = <span style="color: #dc143c;">parser</span>.<span style="color: black;">parse_args</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>args<span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">1</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Error: incorrect number of arguments'</span>
        <span style="color: #dc143c;">parser</span>.<span style="color: black;">print_help</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">from</span> launchpadlib.<span style="color: black;">launchpad</span> <span style="color: #ff7700;font-weight:bold;">import</span> Launchpad,STAGING_SERVICE_ROOT,EDGE_SERVICE_ROOT
    <span style="color: #ff7700;font-weight:bold;">from</span> launchpadlib.<span style="color: black;">errors</span> <span style="color: #ff7700;font-weight:bold;">import</span> HTTPError
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: black;">staging</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Warning: using staging.launchpad.net'</span>
        service = STAGING_SERVICE_ROOT
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        service = EDGE_SERVICE_ROOT
&nbsp;
    launchpad = Launchpad.<span style="color: black;">login_with</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'irc_lpteam'</span>,service,cachedir<span style="color: black;">&#41;</span>
    membername = args<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
    teamname=<span style="color: #483d8b;">'ubuntu-irc-cloaks'</span>
&nbsp;
    team = launchpad.<span style="color: black;">people</span><span style="color: black;">&#91;</span>teamname<span style="color: black;">&#93;</span>
    member = launchpad.<span style="color: black;">people</span><span style="color: black;">&#91;</span>membername<span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'ubuntumembers'</span> <span style="color: #ff7700;font-weight:bold;">in</span>  <span style="color: black;">&#91;</span>e.<span style="color: black;">name</span> <span style="color: #ff7700;font-weight:bold;">for</span> e <span style="color: #ff7700;font-weight:bold;">in</span> member.<span style="color: black;">super_teams</span><span style="color: black;">&#93;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;'%s' (%s) is an Ubuntu Member&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>member.<span style="color: black;">display_name</span>,membername<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Attempting to add '%s' (%s) to '%s' (%s)...&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>member.<span style="color: black;">display_name</span>,membername,team.<span style="color: black;">display_name</span>,teamname<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            status = team.<span style="color: black;">addMember</span><span style="color: black;">&#40;</span>person=member,status=<span style="color: #483d8b;">&quot;Approved&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> HTTPError <span style="color: #ff7700;font-weight:bold;">as</span> error:
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Error: %s has occurred&quot;</span> <span style="color: #66cc66;">%</span> error
            <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;'%s' (%s) does not appear to be an Ubuntu Member.&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>member.<span style="color: black;">display_name</span>,membername<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> options.<span style="color: black;">force</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Warning: force enabled, adding to team anyway'</span>
            <span style="color: #ff7700;font-weight:bold;">try</span>:
                status = team.<span style="color: black;">addMember</span><span style="color: black;">&#40;</span>person=member,status=<span style="color: #483d8b;">&quot;Approved&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">except</span> HTTPError <span style="color: #ff7700;font-weight:bold;">as</span> error:
                <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Error: %s has occurred&quot;</span> <span style="color: #66cc66;">%</span> error
                <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Success!'</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>The latest code is available <a href="https://code.launchpad.net/~bnrubin/+junk/lpteam" target="_blank">here</a> for anyone who wants to play around with it themselves.</p>
<pre>Note: I have filed a <a href="https://launchpad.net/bugs/494136" target="_blank">bug</a> against launchpad that could make it easier to add people to teams.</pre>
]]></content:encoded>
			<wfw:commentRss>http://nullcortex.com/2009/12/saving-time-with-launchpadlib/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
