tag:blogger.com,1999:blog-1286166573624368452024-03-22T09:53:59.860+13:00Tech-FooRantings from an impatient software developerAnonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comBlogger97125tag:blogger.com,1999:blog-128616657362436845.post-1723139961722537182013-05-09T13:11:00.001+12:002013-05-09T13:11:24.023+12:00Move Along<b>Nothing to see here...</b>
I finally got fed up with blogspot being generally crappy, so I've moved to a <a href="http://www.tech-foo.net/">new location. Join me there</a>!Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-2660615206782957102013-01-10T17:06:00.000+13:002013-01-10T21:52:00.026+13:00Visualising the Ubuntu Package RepositoryLike most geeks, I like data. I also like making pretty pictures. This weekend, I found a way to make pretty pictures from some data I had lying around.<br />
<br />
<h2>
The Data: Ubuntu Packages</h2>
Ubuntu is made up of thousands of packages. Each package contains a control file that provides some meta-data about the package. For example, here is the control data for the <a href="http://launchpad.net/autopilot/" target="_blank">autopilot</a> tool:<br />
<br />
<pre>Package: python-autopilot
Priority: optional
Section: universe/python
Installed-Size: 1827
Maintainer: Ubuntu Developers <ubuntu-devel-discuss lists.ubuntu.com="lists.ubuntu.com">
Original-Maintainer: Thomi Richards <thomi .richards=".richards" canonical.com="canonical.com">
Architecture: all
Source: autopilot
Version: 1.2daily12.12.10-0ubuntu1
Depends: python (>= 2.7.1-0ubuntu2), python (<< 2.8), gir1.2-gconf-2.0, gir1.2-glib-2.0, gir1.2-gtk-2.0, gir1.2-ibus-1.0, python-compizconfig, python-dbus, python-junitxml, python-qt4, python-qt4-dbus, python-testscenarios, python-testtools, python-xdg, python-xlib, python-zeitgeist
Filename: pool/universe/a/autopilot/python-autopilot_1.2daily12.12.10-0ubuntu1_all.deb
Size: 578972
MD5sum: c36f6bbab8b5ee10053b63b41ad7189a
SHA1: 749cb0df1c94630f2b3f7a4a1cd50357e0bf0e4d
SHA256: 948eeee40ad025bfb84645f68012e6677bc4447784e4214a5512786aa023467c
Description-en: Utility to write and run integration tests easily
The autopilot engine enables to ease the writing of python tests
for your application manipulating your inputs like the mouse and
keyboard. It also provides a lot of utilities linked to the X server
and detecting applications.
Homepage: https://launchpad.net/autopilot
Description-md5: 1cea8e2d895c31846b8d3482f96a24d4
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Origin: Ubuntu
</thomi></ubuntu-devel-discuss></pre>
<br />
As you can see, there's a lot of information here. The bit I'm interested in is the 'Depends' line. This lists all the packages that are required in order for this package to work correctly. When you install autopilot, your package manager will install all it's dependencies, and the dependencies of all those packages etc. This is (in my opinion), the best feature of a modern Linux distribution, compared with Windows.<br />
<br />
Packages and their dependant packages form a directed graph. My goal is to make pretty pictures of this graph to see if I can learn anything useful. <br />
<br />
<h2>
Process: The Python</h2>
First, I wanted to extract the data from the apt package manager and create a graph data structure I could fiddle with. Using the excellent <a href="http://projects.skewed.de/graph-tool/" target="_blank">graph-tool</a> library, I came up with this horrible horrible piece of python code:
<br />
<br />
<pre class="brush:py">#!/usr/bin/env python
from re import match, split
from subprocess import check_output
from debian.deb822 import Deb822
from graph_tool.all import *
graph = Graph()
package_nodes = {}
package_info = {}
def get_package_list():
"""Return a list of packages, both installed and uninstalled."""
output = check_output(['dpkg','-l','*'])
packages = []
for line in output.split('\n'):
parts = line.split()
if not parts or not match('[uirph][nicurhWt]', parts[0]):
continue
packages.append(parts[1])
return packages
def get_package_info(pkg_name):
"""Get a dict-like object containing information for a specified package."""
global package_info
if pkg_name in package_info:
return package_info.get(pkg_name)
else:
try:
yaml_stream = check_output(['apt-cache','show',pkg_name])
except:
print "Unable to find info for package: '%s'" % pkg_name
package_info[pkg_name] = {}
return {}
d = Deb822(yaml_stream)
package_info[pkg_name] = d
return d
def get_graph_node_for_package(pkg_name):
"""Given a package name, return the graph node for that package. If the graph
node does not exist, it is created, and it's meta-data filled.
"""
global graph
global package_nodes
if pkg_name not in package_nodes:
n = graph.add_vertex()
package_nodes[pkg_name] = n
# add node properties:
pkg_info = get_package_info(pkg_name)
graph.vertex_properties["package-name"][n] = pkg_name
graph.vertex_properties["installed-size"][n] = int(pkg_info.get('Installed-Size', 0))
return n
else:
return package_nodes.get(pkg_name)
def get_sanitised_depends_list(depends_string):
"""Given a Depends string, return a list of package names. Versions are
stripped, and alternatives are all shown.
"""
if depends_string == '':
return []
parts = split('[,\|]', depends_string)
return [ match('(\S*)', p.strip()).groups()[0] for p in parts]
if __name__ == '__main__':
# Create property lists we need:
graph.vertex_properties["package-name"] = graph.new_vertex_property("string")
graph.vertex_properties["installed-size"] = graph.new_vertex_property("int")
# get list of packages:
packages = get_package_list()
# graph_nodes = graph.add_vertex(n=len(packages))
n = 0
for pkg_name in packages:
node = get_graph_node_for_package(pkg_name)
pkg_info = get_package_info(pkg_name)
# purely virtual packages won't have a package info object:
if pkg_info:
depends = pkg_info.get('Depends', '')
depends = get_sanitised_depends_list(depends)
for dependancy in depends:
graph.add_edge(node, get_graph_node_for_package(dependancy))
n += 1
if n % 10 == 0:
print "%d / /%d" % (n, len(packages))
graph.save('graph.gml')
</pre>
<br />
<br />
Yes, I realise this is terrible code. However, I also wrote it in 10 minutes time, and I'm not planning on using it for anything serious - this is an experiment!<br />
<br />
Running this script gives me a 2.6MB .gml file (it also takes about half an hour - did I mention that the code is terrible?). I can then import this file into <a href="https://gephi.org/" target="_blank">gephi</a>, run a layout algorithm over it for the best part of an hour (during which time my laptop starts sounding a lot like a vacuum cleaner), and start making pretty pictures! <br />
<br />
<h2>
The Pretties:</h2>
Without further ado - here's the first rendering. This is the entire graph. The node colouring indicates the node degree (the number of edges connected to the node) - blue is low, red is high. Edges are coloured according to their target node.<br />
<br />
These images are all rendered small enough to fit on the web page. Click on them to get the full image.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdwEURsaUZ5kIumkxIW9x3OyV7pgwcn4IAUm2XjkOapFrTvl-1n8Gd5U8orUqulobXWPSwvUy-H-DkwGbeXuTzaRbjiSF-EZnn3i6scy0ZHJyXEwR-jiA62hyphenhyphen3LaKLgCMkSPkeWE4rWbS1/s1600/colour_overview_full.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmEI0M1q95po1CLavnzGAYNTOG2kI3tzqnnvySrPZh8m2ZcmS1ngv3X9Fa8sFuFYK8IyMP-AE203DPKkydbg6vpxxvOMjZ8PZQ1DDx2FTp6j3J_qLF0H0MryHF1NooqnJJbX2TyeGOamU4/s1600/colour_overview_small.png" /></a></div>
A few things are fairly interesting about this graph. First, there's a definite central node, surrounded by a community of other packages. This isn't that surprising - most things (everything?) relies on the standard C library eventually.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPjZt1ZgJ34uHGSkUl8Mp8AVcMmPoA7tuG8l3ttHuHfI3YJb0_nSKEZFoBb-_ipYvMp3FVv9MYvh63LLNl1t1E3Am6wlNCCle3zgp_6kE6kf-MVt3H1r0BjyUOmISEQDIz1QKHzpLR4pav/s1600/libc6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPjZt1ZgJ34uHGSkUl8Mp8AVcMmPoA7tuG8l3ttHuHfI3YJb0_nSKEZFoBb-_ipYvMp3FVv9MYvh63LLNl1t1E3Am6wlNCCle3zgp_6kE6kf-MVt3H1r0BjyUOmISEQDIz1QKHzpLR4pav/s1600/libc6.png" height="191" width="320" /></a></div>
The graph has several other distinct communities as well. I've produced a number of images below that show the various communities, along with a short comment.<br />
<br />
<h3>
C++</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR6PjcwdISn_8utnkUKKxMIlxyqcba7dyAPqCR1Z2pVZBqi6-EugKidk3lw7o1HzvpR5otLpwmqt_-p7hLNfY5H6KeMLExl0AXh1KrF1i_PY9E3v94xwhbliqI5v-M6k5CL0rmbkZsmW-O/s1600/highlight_stdc++.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiR6PjcwdISn_8utnkUKKxMIlxyqcba7dyAPqCR1Z2pVZBqi6-EugKidk3lw7o1HzvpR5otLpwmqt_-p7hLNfY5H6KeMLExl0AXh1KrF1i_PY9E3v94xwhbliqI5v-M6k5CL0rmbkZsmW-O/s1600/highlight_stdc++.png" height="320" width="320" /></a></div>
These two large nodes are libgcc1 (top), and libstdc++ (bottom). As we'll see soon, the bottom-right corder of the graph is dominated by C++ projects.<br />
<br />
<h3>
Qt and KDE</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkhfyz6loBw9qfmHtJGyYIbMoHcfjGWCdJbiReAKdZaRLOs04lE55_ICwFhB6OM_3YfVmL73gmnio_EwI7e6EG6l232ze6J4CkBoUMXHRLXcO4hqLSS95YzezePnjWishExK_vOqXUYjl1/s1600/highlight_qt_kde.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkhfyz6loBw9qfmHtJGyYIbMoHcfjGWCdJbiReAKdZaRLOs04lE55_ICwFhB6OM_3YfVmL73gmnio_EwI7e6EG6l232ze6J4CkBoUMXHRLXcO4hqLSS95YzezePnjWishExK_vOqXUYjl1/s1600/highlight_qt_kde.png" height="320" width="320" /></a></div>
This entire island of nodes is made of up the Qt and KDE libraries. The higher nodes are the Qt libraries (QtCore, QtGui, QtXml etc), and the nodes lower down are KDE libraries (kcalcore4, akonadi, kmime4 etc).<br />
<h3>
Python</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDJqGiD0jjrh1smC5zvz2l1Oa67pZ9Q0t6FFypDAqw7UnouYclbyo6LqBEvY6PdPCciPU-JxNyTnCTbTTskUc7dc0TmKLcSQJ84P5tW9HqYUvcN6j0U3Ct6iRxsIz1JHPtEgVjX8X6WMpz/s1600/highlight_python.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDJqGiD0jjrh1smC5zvz2l1Oa67pZ9Q0t6FFypDAqw7UnouYclbyo6LqBEvY6PdPCciPU-JxNyTnCTbTTskUc7dc0TmKLcSQJ84P5tW9HqYUvcN6j0U3Ct6iRxsIz1JHPtEgVjX8X6WMpz/s1600/highlight_python.png" height="320" width="320" /></a></div>
The two large nodes here are 'python' and 'python2.7'. Interestingly, 'python3' is a much smaller community, just above the main python group.<br />
<h3>
System</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfKT9CoMqRVzTdikMCV4DYUJvKdELCkF7fkDyGgTgCOzqwjFAEKi0UsRfxkYb_aAaABcQU-dRrhGnZmSPigMqUa_2hABEgcSOVLrlGd6lVmkK6MhkgMfOaxfzXupOSSkLQHIstwrtLvDo4/s1600/highlight_sysutils.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfKT9CoMqRVzTdikMCV4DYUJvKdELCkF7fkDyGgTgCOzqwjFAEKi0UsRfxkYb_aAaABcQU-dRrhGnZmSPigMqUa_2hABEgcSOVLrlGd6lVmkK6MhkgMfOaxfzXupOSSkLQHIstwrtLvDo4/s1600/highlight_sysutils.png" height="320" width="320" /></a></div>
Just below the python community there's a large, loosely-connected network of system tools. Notable members of this community include the Linux kernel packages, upstart, netbase, adduser, and many others. <br />
<h3>
Gnome</h3>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZWlzJrV-v4-ALcTPZBh5gYcDPwiezq0YTV5hS8pOnW2LfT0X6ib1vxd-0k6urNQKoxz2PBJcgNkp1ahZgOrvlChyphenhyphenU1SRlhYj1n-tI_4QevHOuJsd_VeVqYUMM0gMOgVkLeDx39SdwbtY3/s1600/highlight_gnome.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZWlzJrV-v4-ALcTPZBh5gYcDPwiezq0YTV5hS8pOnW2LfT0X6ib1vxd-0k6urNQKoxz2PBJcgNkp1ahZgOrvlChyphenhyphenU1SRlhYj1n-tI_4QevHOuJsd_VeVqYUMM0gMOgVkLeDx39SdwbtY3/s1600/highlight_gnome.png" height="320" width="320" /></a></div>
This is GNOME. At it's core is 'libglib', and it expands out to libgtk, libgdk-pixbuf (along with many other libraries), and from there to various applications that use these libraries (gnome-settings-daemon for example).<br />
<br />
<h3>
Mono</h3>
<h3>
</h3>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5xGbTek36HQFeFSX_17-Iuv2af0_11MIeMGLp1EaZb7EY3dqspBEAMWJXGxzM3KJHN5uGVH-_lV55QJurw1qhGUvK9_6xW3SJCIqtJWScBjE8XZ3nvnfys02uaM09SpFh6iBwMKcgs4FM/s1600/highlight_mono.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5xGbTek36HQFeFSX_17-Iuv2af0_11MIeMGLp1EaZb7EY3dqspBEAMWJXGxzM3KJHN5uGVH-_lV55QJurw1qhGUvK9_6xW3SJCIqtJWScBjE8XZ3nvnfys02uaM09SpFh6iBwMKcgs4FM/s1600/highlight_mono.png" height="320" width="320" /></a></div>
At the very top of the graph, off on an island by themselves are the mono packages.<br />
<h3>
Others</h3>
The wonderful thing about this graph is that the neighbourhoods are fractal. I've outlined several of the large ones, but looking closer reveals small clusters of related packages. For example: multimedia packages:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD_aV9yo8QHHPyIB5gtO51lQEoel03hBsS3SmFAZTyLK9ZDLin4Wa8kZ2mf2qdnYuNDVnM_-Hu27blzw-AofVftIGLt-4eUDN-p1ErBW8wrox8UYEVe_Vnkg6k9iVNLL3PIcY6ygmwehGh/s1600/multimedia.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD_aV9yo8QHHPyIB5gtO51lQEoel03hBsS3SmFAZTyLK9ZDLin4Wa8kZ2mf2qdnYuNDVnM_-Hu27blzw-AofVftIGLt-4eUDN-p1ErBW8wrox8UYEVe_Vnkg6k9iVNLL3PIcY6ygmwehGh/s1600/multimedia.png" height="190" width="320" /></a></div>
<br />
<h2>
This is Just the Beginning...</h2>
This is an amazing dataset, and really this is just the beginning. There's a number of things I want to look into, including:<br />
<ul>
<li>Adding 'Recommends' and 'Suggests' links between packages - with a lower edge weight than Depends.</li>
<li>Colour coding nodes according to which repository section the package can be found in.</li>
<li>Try to categorise libraries vs applications - do applications end up clustered like libraries do?</li>
</ul>
I'm open to suggestions however - what do you think I should into next? Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-43145189058448238732012-10-30T23:09:00.000+13:002012-10-30T23:09:03.559+13:00Writing UI Tests with AutopilotAt the <a href="http://uds.ubuntu.com/" target="_blank">UDS-r sprint</a> in Copenhagen, I'll be running a <a href="http://summit.ubuntu.com/uds-r/meeting/21274/developing-ui-tests-with-autopilot/" target="_blank">session for anyone interested in Autopilot</a>. There will be a demo, and Autopilot "experts" on hand to answer any questions you might have.<br />
<br />
Autopilot is a tool for automating UI testing. We've been using it with great success in the last two Ubuntu cycles, and we're starting to support testing traditional Qt4, Qt5, Qml, and Gtk applications.<br />
<br />
I hope to see you all there!Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-29429982526368705872012-04-28T14:57:00.002+12:002012-04-28T14:57:16.004+12:00So you missed PyCon US...If you're anything like me you've watched another PyCon US come and go. Living in New Zealand makes attending overseas conferences an expensive proposition. So you've missed the conference. You've watched all the talks on <a href="http://pyvideo.org/">pyvideo.org</a>, but it's still not enough. You'd love to attend a PyCon in person, perhaps one in an exotic location (what a great opportunity for a family vacation). Of course, I have a solution: <b>Come to Kiwi PyCon!</b><br />
<br />
<a href="http://nz.pycon.org/" style="clear: both;"><img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGrHhSm6Wa3W5oI9LZpGNDSXMfPZycto_UnQDMaQkW_I3VOG6qlJM4CGeaZBm9q2q2go800qmhyRoFUDwR3CTuo3BoP4jV0yKZ_I2weO6AXxGrFy3RbgBhN0ZHpzJ4Cz7y25VBRRZUXBp-/s400/kpc_bullet.png" /></a>
<br />
<div style="clear: both;">
<br />
In contrast to the US PyCon, Kiwi PyCon is a smaller, more intimate affair, with a few hundred delegates, two streams, and plenty of chances to meet other python hackers from the Australia/New Zealand/Pacific region. Places are limited, and registrations are open, so here's what you need to do to beat the post-PyCon blues:</div>
<ol>
<li>Go to <a href="http://nz.pycon.org/">nz.pycon.org</a>, and register for the conference. While you're there, check out the sponsorship options!</li>
<li>If you're feeling brave, submit a talk proposal! </li>
<li>Book accommodation and flights (we will soon have accommodation options listed on the website).</li>
<li>Count down the days to the conference! </li>
</ol>
<div style="clear: both;">
It's that simple. Do it now!</div>Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-88161477604643302992012-04-13T16:56:00.001+12:002012-04-13T16:56:40.452+12:00Experimenting with C++ std::make_sharedC++11 is upon us, and one of the more utilitarian changes in the new standard is the inclusion of the new smart pointer types: <span style="font-family: "Courier New",Courier,monospace;">unique_ptr</span>, <span style="font-family: "Courier New",Courier,monospace;">shared_ptr</span> and <span style="font-family: "Courier New",Courier,monospace;">weak_ptr</span>. An interesting related feature is <span style="font-family: "Courier New",Courier,monospace;">std::make_shared</span> - a function that returns a <span style="font-family: "Courier New",Courier,monospace;">std::shared_ptr</span> wrapping a type you specify. The documentation promises efficiency gains by using this method. <a href="http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared" target="_blank">From the documentation</a>:<br />
<br />
<blockquote class="tr_bq">
This function allocates memory for the T object and for the shared_ptr's
control block with a single memory allocation. In contrast, the
declaration <tt>std::shared_ptr<t> p(new T(Args...))</t></tt> performs two memory allocations, which may incur unnecessary overhead.
</blockquote>
I was curious: How much faster is <span style="font-family: "Courier New",Courier,monospace;">make_shared</span> than using <span style="font-family: "Courier New",Courier,monospace;">new</span> yourself? Like any good scientist, I decided to verify the claim that <span style="font-family: "Courier New",Courier,monospace;">make_shared</span> gives better performance than <span style="font-family: "Courier New",Courier,monospace;">new</span> by itself.<br />
<br />
I wrote a small program and tested it. Here's my code:<br />
<br />
<pre class="brush:cpp">#include <memory>
#include <string>
class Foo
{
public:
typedef std::shared_ptr<Foo> Ptr;
Foo()
: a(42)
, b(false)
, c(12.234)
, d("FooBarBaz")
{}
private:
int a;
bool b;
float c;
std::string d;
};
const int loop_count = 100000000;
int main(int argc, char** argv)
{
for (int i = 0; i < loop_count; i++)
{
#ifdef USE_MAKE_SHARED
Foo::Ptr p = std::make_shared<Foo>();
#else
Foo::Ptr p = Foo::Ptr(new Foo);
#endif
}
return 0;
}
</pre>
This is pretty simple - we either allocation 100 million pointers using <span style="font-family: "Courier New",Courier,monospace;">new</span> manually, or we use the new <span style="font-family: "Courier New",Courier,monospace;">make_shared</span>. I wanted my 'Foo' class to be simple enough to fit into a couple of lines, but contain a number of different types, and at least one complex type.
I built both variants of this small application with g++, and used the 'time' utility to measure it's execution time. I realise this is a pretty crude measurement, but the results are interesting nontheless:
<br />
<div id="chart_1div">
</div>
My initial results are confusing - it appears as if <span style="font-family: "Courier New",Courier,monospace;">std::make_shared</span> is <i>slower</i> than using <span style="font-family: "Courier New",Courier,monospace;">new</span>. Then I realised that I had not enabled any optimisations. Sure enough, adding '-O2' to the g++ command line gave me some more sensible results:
<br />
<div id="chart_2div">
</div>
OK, so <span style="font-family: "Courier New",Courier,monospace;">make_shared</span> only seems to be faster with optimisations turned on, which is interesting in itself. At this point, I started wondering how other compilers would fare. I decided to pick on clang and run exactly the same tests once more:
<br />
<div id="chart_3div">
</div>
Once again we see a very similar pattern between the optimised and non-optimised code. We can also see that clang is slightly slower than g++ (although it was significantly faster at compiling). For those of you who want the numbers:
<br />
<div id="table_div">
</div>
Now I have evidence for convincing people to use <span style="font-family: "Courier New",Courier,monospace;">make_shared</span> in favor of <span style="font-family: "Courier New",Courier,monospace;">new</span>!
<script src="https://www.google.com/jsapi" type="text/javascript">
</script>
<script type="text/javascript">
// Load the Visualization API library and the piechart library.
google.load('visualization', '1.0', {'packages':['corechart', 'table']});
google.setOnLoadCallback(drawChart);
// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Compiler', 'std::make_shared', 'new'],
['g++', 22664, 17559],
['g++ -O2', 7745, 9483],
['clang++', 22499, 16429],
['clang++ -O2', 7762, 9585]
]);
// Set chart options
var options = {'title':'Speed comparison: allocating objects in C++',
'vAxis': {title: 'time (milliseconds)'},
'width':500};
var view1 = new google.visualization.DataView(data);
view1.setRows([0]);
var chart1 = new google.visualization.ColumnChart(document.getElementById('chart_1div'));
chart1.draw(view1, options);
var view2 = new google.visualization.DataView(data);
view2.setRows([0, 1]);
var chart2 = new google.visualization.ColumnChart(document.getElementById('chart_2div'));
chart2.draw(view2, options);
var chart3 = new google.visualization.ColumnChart(document.getElementById('chart_3div'));
chart3.draw(data, options);
var table = new google.visualization.Table(document.getElementById('table_div'));
table.draw(data, options);
}
</script>Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-69416975519897056472012-04-12T10:01:00.000+12:002012-04-12T10:01:00.095+12:00Kiwi PyCon Sponsorship Drive<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf2gCgkJJazHxekeW-RR1w8Wrv6cWbPuj9G9pNOI-Y5SSddEr4SMhYTdq0c_6_pC3RXXNinX-aGgYAs_HZXEqoXgUIK3GXUYaloBsFQGcnpktvqP7RSPPXnTTN1PmBNATC-j1tgdX3waqo/s1600/Kiwi_PyCon-01.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="126" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgf2gCgkJJazHxekeW-RR1w8Wrv6cWbPuj9G9pNOI-Y5SSddEr4SMhYTdq0c_6_pC3RXXNinX-aGgYAs_HZXEqoXgUIK3GXUYaloBsFQGcnpktvqP7RSPPXnTTN1PmBNATC-j1tgdX3waqo/s320/Kiwi_PyCon-01.png" width="320" /></a></div>
<div style="clear: both;">
Kiwi PyCon is approaching! You probably think that's a good thing, but if you're one of the poor volunteer organisers, that's a scary thought. Why? We have bills to pay, and very little income. That means it's time to shill for some cash! Below is an excerpt from our public sponsorship announcement email. If your company is willing to sponsor a good cause, please get in touch with me.</div>
<br />
Kiwi PyCon is organised by the New Zealand Python User group - a not-for-profit organisation. We don’t make any profit from the conference, and the organisers donate their free time to make the event a success. We rely entirely on companies’ sponsorship to pay the bills.<br />
<br />
Sponsorship has several advantages for you:<br />
<br />
<ul>
<li>It’s an opportunity to get brand exposure in front of the foremost Python experts from New Zealand and around the world.</li>
</ul>
<ul>
<li>Presents a fantastic networking opportunity if you are looking to employ engineers now, or in the future.</li>
</ul>
<ul>
<li>Align yourself with market leaders and past sponsors such as Github, Weta Digital, Catalyst IT, Mozilla. Become known as a Python promoter and industry leader. </li>
</ul>
<ul>
<li>Gold sponsors receive five complimentary tickets to the conference and their logo on the conference shirt and all print materials.</li>
</ul>
<br />
If you’d like to sponsor the conference, a document describing sponsorship opportunities <a href="http://nz.pycon.org/pdf/Kiwi_PyCon_Sponsorship_2012.pdf" target="_blank">is available here</a>.<br />
<br />
To get in touch, email <a href="mailto:kiwipycon-sponsorship@nzpug.org">kiwipycon-sponsorship@nzpug.org</a>.Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-14594843392562398212012-03-11T08:59:00.000+13:002012-03-11T09:02:29.926+13:00Python GObject Introspection oddnessI recently ported indicator-jenkins to Gtk3 using the python GObject Introspection Repository (gir) bindings. <a href="http://gould.cx/ted/blog" target="_blank">Ted Gould</a> did most of the work, I just cleaned some bits up and made sure everything worked. One issue that puzzled me for a while is that the GObject library changed the way it's "notify" signal works between GObject 2 and GObject 3. I've not seen any documentation of this change, so I'll describe it here.<br />
<br />
For this example, let's make a very simple class that has a single property:<br />
<br />
<code>
import gobject<br />
<br />
class MyClass(gobject.GObject):<br />
prop = gobject.property(type=int)<br />
</code><br />
...and a very simple callback function that we want to call whenever the value of 'prop' changes:<br />
<br />
<code>
def cb(sender, prop):<br />
print "property '%s' changed on %r." % (prop.name, sender)<br />
</code><br />
Finally, with GObject 2 we can create an instance of 'MyClass' and connect to the 'notify' signal like this:<br />
<br />
<code>
inst = MyClass()<br />
inst.connect("notify", cb)<br />
inst.prop = 42<br />
</code><br />
When we run this simple program we get the following output:<br />
<code>
property 'prop' changed on <myclass (__main__+myclass="" 0x2618600)="" 0x7fe57abfd6e0="" at="" object="">.</myclass><br />
</code>
... which is what we expected. However, if we port this code to GObject 3, it should look like this:<br />
<br />
<code>from gi.repository import GObject<br />
<br />
class MyClass(GObject.GObject):<br />
prop = GObject.property(type=int)<br />
<br />
<br />
def cb(sender, prop):<br />
print "property '%s' changed on %r." % (prop.name, sender)<br />
<br />
<br />
inst = MyClass()<br />
inst.connect("notify", cb)<br />
inst.prop = 42<br />
</code><br />
However, running this gives an error:<br />
<br />
<code>
/usr/lib/python2.7/dist-packages/gi/_gobject/propertyhelper.py:171: Warning: g_value_get_object: assertion `G_VALUE_HOLDS_OBJECT (value)' failed<br />
instance.set_property(self.name, value)<br />
Traceback (most recent call last):<br />
File "gobject3.py", line 8, in cb<br />
print "property '%s' changed on %r." % (prop.name, sender)<br />
AttributeError: 'NoneType' object has no attribute 'name'<br />
</code><br />
The 'prop' parameter in the callback is set to None.<br />
<br />
There is a solution however - connecting the callback to a more specific notification signal works as expected:<br />
<br />
<code>
from gi.repository import GObject<br />
<br />
class MyClass(GObject.GObject):<br />
prop = GObject.property(type=int)<br />
<br />
<br />
def cb(sender, prop):<br />
print "property '%s' changed on %r." % (prop.name, sender)<br />
<br />
<br />
inst = MyClass()<br />
inst.connect("notify::prop", cb)<br />
inst.prop = 42<br />
</code><br />
It took me a while to figure this out - hopefully I've saved someone else that work.Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-47362768001647495822012-03-02T08:57:00.000+13:002012-03-02T08:57:05.387+13:00Indicator-jenkins is now even more awesomeMy latest hobby project, <a href="https://launchpad.net/indicator-jenkins" target="_blank">indicator-jenkins</a> is now even better (I <a href="http://tech-foo.blogspot.co.nz/2012/02/introducing-indicator-jenkins.html" target="_blank">wrote about this previously</a>, in case you missed it).<br />
<br />
New features since my last blog post:<br />
<ul><li>The code is now much nicer, and will be much easier to extend. My long-term goal is to support other types of CI servers (I'll probably have to change the project name I guess).</li>
<li>Desktop notifications are generated for each new build of a monitored project. The notification includes the status and health report of the last build.</li>
<li>LOTS of bug-fixes, especially around the settings UI. I'm still not happy with the settings dialog UI, but it's at least usable now.</li>
</ul>To get it installed, do the following:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">$ sudo add-apt-repository ppa:thomir/indicator-jenkins</div><div style="font-family: "Courier New",Courier,monospace;">$ sudo apt-get install indicator-jenkins</div><br />
Then launch indicator-jenkins from the unity dash or command line (Note: Launching it from the command line generates a LOT of debug output - I will turn this off in future releases).Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-57170405127943899732012-02-23T17:27:00.001+13:002012-02-23T20:19:24.257+13:00How to Compile Unity from SourceThese instructions will help you build unity from source. However, there are a<br />
few things to consider:<br />
<ul class="simple"><li>I recommend that you <i>never</i> copy anything you've built locally outside your home directory. Doing so is asking for trouble, especially as we're building the entire desktop shell. If you manage to ruin your system-wide desktop shell you'll be a very sad programmer!</li>
<li>I'm assuming that you're running the precise Ubuntu release (still in alpha at the time of writing, but very usable).</li>
<li>I'm also assuming that you want to build unity from trunk (that is, lp:unity).</li>
</ul>Without further ado, let's get to it:<br />
<div class="section" id="getting-the-source-code"><h1>Getting the source code</h1>If you don't already have Bazaar installed, install it now:<br />
<br />
<pre class="literal-block">sudo apt-get install bzr
</pre><br />
You may want to make yourself a folder for the unity code. I tend to do something like this:<br />
<pre class="literal-block">mkdir -p ~/code/unity
cd ~/code/unity
</pre><br />
Let's grab the code from launchpad:<br />
<pre class="literal-block">bzr branch lp:unity trunk
</pre><br />
This may take a while. If you prefer to use Bazaar checkouts instead of branches, that's fine to.</div><div class="section" id="installing-build-dependancies"><h1>Installing Build Dependancies</h1>We need to get the build-dependancies for unity. Thankfully, apt-get makes this trivial:<br />
<br />
<pre class="literal-block">sudo apt-get build-dep unity
</pre></div><div class="section" id="compiling-unity"><h1>Compiling Unity</h1>I have a set of bash functions that makes this step significantly easier. To use them, copy the following bash code into a file in your home directory called ".bash_functions":<br />
<br />
<pre class="literal-block">function recreate-build-dir()
{
rm -r build
mkdir build
cd build
}
function remake-autogen-project()
{
./autogen.sh --prefix=/home/thomi/staging --enable-debug
make clean && make && make install
}
function remake-unity()
{
recreate-build-dir
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCOMPIZ_PLUGIN_INSTALL_TYPE=local -DCMAKE_INSTALL_PREFIX=/home/thomi/staging/ -DGSETTINGS_LOCALINSTALL=ON
make && make install
}
function unity-env
{
export PATH=~/staging/bin:$PATH
export XDG_DATA_DIRS=~/.config/compiz-1/gsettings/schemas:~/staging/share:/usr/share:/usr/local/share
export LD_LIBRARY_PATH=~/staging/lib:${LD_LIBRARY_PATH}
export LD_RUN_PATH=~/staging/lib:${LD_RUN_PATH}
export PKG_CONFIG_PATH=~/staging/lib/pkgconfig:${PKG_CONFIG_PATH}
export PYTHONPATH=~/staging/lib/python2.7/site-packages:$PYTHONPATH
}
</pre><br />
Note: You will need to replace all instances of "/home/thomi" with your own home directory path!<br />
<br />
Now run this in a terminal:<br />
<pre class="literal-block">echo ". ~/.bash_functions" >> ~/.bashrc
</pre><br />
This ensures that the next time you open a bash shell the functions listed above will be available to you. To avoid having to close and re-open a terminal, we can read them manually just this once:<br />
<pre class="literal-block">. ~/.bash_functions
</pre><br />
You should now be able to run:<br />
<pre class="literal-block">remake-unity
</pre><br />
from the <tt class="docutils literal">trunk/</tt> directory we created earlier. That's it - you're building unity!</div><div class="section" id="not-so-fast"><h1>Not so Fast!</h1>Chances are, while trying to build unity, you found that it needed a newer version of one of the several supporting projects than you had installed. At the time of writing, you can't compile unity without first building <tt class="docutils literal">nux</tt> from sources first. Thankfully, that's pretty easy with the use of the functions you now have set up.<br />
First we get the source code:<br />
<br />
<pre class="literal-block">mkdir -p ~/code/nux
cd ~/code/nux
bzr branch lp:nux trunk
cd trunk
</pre><br />
Then we need to get the build dependencies for nux.<br />
<br />
<pre>sudo apt-get build-dep nux</pre><br />
Unfortunately there are a fewpackages missing, so you'll want to install them as well:<br />
<br />
<pre>sudo apt-get install gnome-common libibus-1.0-dev libgtest-dev google-mock libxtst-dev</pre><br />
Then we use the functions above to build nux:<br />
<pre class="literal-block"> </pre><pre class="literal-block">remake-autogen-project
</pre><br />
That's it! You can then go back and build unity - hopefully this time with better success.</div><div class="section" id="build-notes"><h1>Build Notes</h1>You may have noticed that the <tt class="docutils literal"><span class="pre">remake-*</span></tt> scripts do a complete rebuild every time. If you'd prefer to just build the files that have changed since last time, change to the <tt class="docutils literal">trunk/build/</tt> directory, and run:<br />
<br />
<pre class="literal-block">make && make install
</pre></div><div class="section" id="running-unity"><h1>Running Unity</h1>If you'd like to run the version of unity you've built, rather than the system-wide version, open a terminal and run the following commands:<br />
<br />
<pre class="literal-block">unity-env
unity --replace &
</pre><br />
The first line patches several environment variables such that unity will subsequently be launched from your local staging directory. These environment variables will remain changed until you close the terminal, so you need only run <tt class="docutils literal"><span class="pre">unity-env</span></tt> once.</div>Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-88037198573433609532012-02-19T11:43:00.003+13:002012-03-02T08:57:42.066+13:00Introducing: indicator-jenkinsFor my day job I've been monitoring a jenkins instance (specifically, the public <a href="http://jenkins.qa.ubuntu.com/" target="_blank">Ubuntu QA jenkins</a> instance) using my web browser. This is obviously suboptimal - I'd like to be able to see the state of the jenkins jobs I'm interested at a glance, without having to open my web browser.<br />
<br />
I couldn't find a solution to my problem, so I created one: <span style="font-family: "Courier New",Courier,monospace;">indicator-jenkins</span> is a panel indicator for your desktop manager of choice. It allows you to select one or more jobs from a jenkins server, and follow the job state without having to open your browser.<br />
<br />
The project is <a href="http://launchpad.net/indicator-jenkins" target="_blank">hosted on launchpad</a>, and is built daily into my PPA. To install it (I'm assuming you're running Ubuntu):<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">$ sudo add-apt-repository ppa:thomir/indicator-jenkins</div><div style="font-family: "Courier New",Courier,monospace;">$ sudo apt-get update</div><div style="font-family: "Courier New",Courier,monospace;">$ sudo apt-get install indicator-jenkins</div><br />
Once it's installed you can launch it in a couple of different ways:<br />
<br />
<ul><li>From a terminal - jut run <span style="font-family: "Courier New",Courier,monospace;">indicator-jenkins</span>. If you run it on the terminal you'll get a lot of debugging output (useful if you want to submit a patch, or figure out why it's not working).</li>
<li>From the unity dash - open the dash, and search for 'jenkins' - it's probably going to be the first link.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQNpv7AlbGsq5b0kwX2OO_QruST0ZV-FpsieFixiAY7BSimJUCFMKcavHER4_AxsA-qcNqqPyKryKkf-OGnFg3l-nJIVSoYAgNEmDOGW90E51Y_xJt2xlywZoR8Aw1e8kv9zce8bkZ_7RE/s1600/jenkins-dash.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQNpv7AlbGsq5b0kwX2OO_QruST0ZV-FpsieFixiAY7BSimJUCFMKcavHER4_AxsA-qcNqqPyKryKkf-OGnFg3l-nJIVSoYAgNEmDOGW90E51Y_xJt2xlywZoR8Aw1e8kv9zce8bkZ_7RE/s1600/jenkins-dash.png" /></a></div></li>
</ul><br />
Once it's running you should see the jenkins icon in your panel. To set it up, click the icon to open the settings dialog, enter the URL of the jenkins instance you want to look at, hit the refresh button, and pick the job(s) you want to monitor. Click OK and you're done! It's simpler than it sounds - see for yourself:<br />
<iframe allowfullscreen="" frameborder="0" height="480" src="http://www.youtube.com/embed/QgjdcO9V3wM?rel=0" width="853"></iframe><br />
Right now it's pretty rough-and-ready - there are many features I'd like to add:<br />
<ul><li>Integrate desktop notifications, so you can be alerted when a job state changes.</li>
<li>Customise panel icon based on job state (i.e.- show a red icon if any of the monitored jobs are failing).</li>
<li>Allow user to customise refresh period.</li>
<li>Allow user to monitor jobs from more than one jenkins server.</li>
<li>Show more information about a jenkins job. For a start, show stability as well as current status, and maybe in the future show unity test pass/failure rates for projects that have that information. </li>
</ul><b>How it's Made:</b> <br />
<br />
The entire application is written in python. We make use of several python modules:<br />
<ul><li>The <span style="font-family: "Courier New",Courier,monospace;">python-appindicator</span> package gives us the ability to create an icon on the menu, and the python gtk2 bindings are used to create the menu and settings dialog.</li>
<li>The python '<span style="font-family: "Courier New",Courier,monospace;">multiprocessing</span>' module is used to spin up worker processes to fetch the data from jenkins. Initially the application used threads for this, but python's threading support isn't great, and it was taking too long. </li>
<li>The python '<span style="font-family: "Courier New",Courier,monospace;">json</span>' module is used to save and load settings.</li>
<li>The <span style="font-family: "Courier New",Courier,monospace;">python-jenkins</span> package is used to communicate with the jenkins server.</li>
</ul>This is a great example of python's "batteries included" approach to programming. All you have to do is provide the glue between already-existing python modules.Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-91832226041741285252011-10-13T09:21:00.000+13:002011-10-13T09:21:57.848+13:00KiwiPyCon Sloecode TalkIt's about time I posted my Kiwi PyCon talk from last August! I spent an enjoyable 30 minutes talking about what Sloecode is, how we built it, and the problems encountered along the way. As per my usual approach to public speaking, I tried to keep things light-hearted and entertaining. Anyway, the slides and audio are available here:<br />
<br />
<div id="__ss_9124373" style="width: 510px;"><b style="display: block; margin: 12px 0 4px;"><a href="http://www.slideshare.net/ThomiRichards/introducing-sloecode-a-pythonpowered-installable-codeforge" target="_blank" title="Introducing Sloecode: a python-powered, installable code-forge.">Introducing Sloecode: a python-powered, installable code-forge.</a></b> <iframe frameborder="0" height="426" marginheight="0" marginwidth="0" scrolling="no" src="http://www.slideshare.net/slideshow/embed_code/9124373?rel=0" width="510"></iframe> <br />
<div style="padding: 5px 0 12px;">View another <a href="http://www.slideshare.net/" target="_blank">webinar</a> from <a href="http://www.slideshare.net/ThomiRichards" target="_blank">ThomiRichards</a> </div></div>Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-48088133660357096012011-09-27T10:01:00.000+13:002011-09-27T10:01:19.872+13:00Dear Journalists: Bits and BytesDear Journalist type person,<br />
<br />
There's something we must discuss. You see, you've been making a very basic mistake in many of your articles when it comes to writing about the Internet, and specifically Internet speeds. Let's take a look at a small quote:<br />
<br />
<blockquote>...unless you have an internet connection of impossible speeds. (Mine is nominally 10MB, by the way, which in practice means maximum download speeds of 1.4 megabytes per second).</blockquote>(source: <a href="http://www.rockpapershotgun.com/2011/09/26/onlive-is-okay/">Rock-Paper-Shotgun</a>).<br />
<br />
Can you spot the problem here? Internet speeds are measured in mega<b>bits</b> per second. The symbol for 'bits' is a lower-case 'b', so an Internet connection that's 10 Megabits per second could be written as "10 Mbps". I guess if you're feeling lazy you could leave off the "ps", and end up with "10 Mb" (although it's a really sloppy thing to do), but NEVER "10 MB" - that means something else entirely.<br />
<br />
Modern PCs use bytes that contain 8 bits. The correct symbol for a byte is an upper-case 'B'. so "10 MB" means "ten mega-bytes", not mega-bits, which is probably what you meant when you were describing the speed of your Internet connection.<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis_1ebREevClb11svWgaPboLDhuSS5jK8dvNBfCgaNgsrOrF8fTnvHOJyOcDZKYmyBwBHBTG0j-P3wM989mMh0fS8ArQEzASqGWED1xeBwW-FWrcdC5_7bc9YQnvl-qjssODAHZCLkVcHm/s1600/byte.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="85" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEis_1ebREevClb11svWgaPboLDhuSS5jK8dvNBfCgaNgsrOrF8fTnvHOJyOcDZKYmyBwBHBTG0j-P3wM989mMh0fS8ArQEzASqGWED1xeBwW-FWrcdC5_7bc9YQnvl-qjssODAHZCLkVcHm/s320/byte.png" width="320" /></a></div>Back to our Internet connection that runs at 10Mbps. It's unfortunate that speeds are measured in bits, because a much more useful measure is bytes per second, since that's how we deal with data sizes. We know that a CD ISO image is likely to be around 700 MB, an MP3 file around 3 MB, and an image from a digital camera to be around 1 MB. To convert our 10Mbps connection speed to megabytes per second, we divide by 8, and get 1.25MBps. However, this is the <i>theoretical maximum</i> speed, and there's a lot of overhead in any network connection, so in practise it's unlikely you will experience anything close to this maximum speed.<br />
<br />
If your eyes glazed over, or perheps you felt light-headed reading that, here are a few take-home points to make it easier for you:<br />
<ul><li>Connection speeds are measured in megabits-per-second. The correct unit symbol for this is "Mbps".</li>
<li>Files are measured in Megabytes.</li>
<li>A Byte has 8 bits. So to turn your connection speed into something useful, divide the number by 8 and make the unit symbol "MBps".</li>
</ul>I would be honoured if you'd consider this small point next time you go to write online. Some of us are acutely sensitive to these matters, and you really don't want to upset the geeks of this world. <br />
<br />
Kind Regards,Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-60597720078331110332011-08-29T15:54:00.001+12:002011-10-13T09:26:54.998+13:00KiwiPyCon 2012 will be in DunedinIt is a great honour and privilege to be involved in bringing the New Zealand Python developers conference (KiwiPyCon) to Dunedin in 2012. I intend to blog regularly with details of next year's conference as they emerge, so watch this space for more information over time!<br />
<br />
Finally, a huge "Thank You" to <a href="http://timmcnamara.co.nz/">Tim McNamara</a> for organising the best KiwiPyCon to date. I have a huge task ahead of me, and he's raised the bar very high indeed.<br />
<br />
Have any good ideas for next year? Please let us know!Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-66094683494800030102011-08-28T11:10:00.000+12:002011-08-28T11:10:04.610+12:00Sloecode 1.1 - get your bugreports in now!I'm at <a href="http://nz.pycon.org/2011/about/">KiwiPyCon</a> in Wellington, New Zealand. It turns out, being surrounded by geeks is great inspiration & motivation. Because of this, I've created a <a href="https://launchpad.net/sloecode/+milestone/1.1">Sloecode 1.1 milestone in launchpad</a>. If you have any bugreports or feature reuests, now's the time to <a href="https://bugs.launchpad.net/sloecode/+filebug">get them in</a>!<br />
<br />
...I can't believe I'm asking people for bug-reports. This feels wrong...Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-27118471997344104832011-08-03T18:52:00.000+12:002011-08-03T18:52:15.002+12:00Sloecode: now with 100% more websiteSloecode now has <a href="http://www.sloecode.org/">a real website</a>! It's a rather minimalist affair at present, but it's better than nothing!<br />
<br />
Since I last blogged, the setup instructions for the Sloecode server have changed a lot. The new instructions are available on the new site.Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-79531177620561767512011-07-07T19:59:00.000+12:002011-07-07T19:59:25.117+12:00Representin' the home-boys!That's *exactly* the kind of blog title that's liable to get me in trouble down the road. <i>Faux</i> street swagger doesn't age well.<br />
<br />
In other news, I'm presenting a talk at this years NZ Python conference <a href="http://nz.pycon.org/">KiwiPyCon</a>. Their website does not have the schedule visible yet, but there is a <a href="http://nz.pycon.org/2011/talks/">list of talks available</a>.<br />
<br />
I'm looking forward to meeting other python developers, and maybe getting some help with Sloecode!Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-38855210083421783362011-05-29T11:34:00.000+12:002011-05-29T11:34:21.059+12:00Unity WorkaroundsI'm currently running the unity desktop shell on my development computer. I got fed up with KDE's lack of support, and the gnome-shell just annoyed me. Unity seems like a good start, but suffers from several problems. I've found workarounds for all of these, and thought I'd post them below.<br />
<br />
<b>Scrollbar Corruption:</b><br />
<b><br />
</b><br />
One of the major changes in unity is the thin scrollbars (technically called "overlay scrollbars", I believe), which are enabled by default for all GTK applications. This is what I'm talking about (image from <a href="http://techgage.com/article/an_in-depth_look_at_ubuntu_1104/3">techgarage.com</a>):<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx6Sh4Mnscmb-e2wt-1dWOj8T3tbrivjg-q4bZCU6XX_mAW3guTiaRyL2rhOBdnmhlb3uWBXuWJFhhuvvzPbpvO2cd2mWA2bPKds5pDKceml4BcqSgS0ulGv6QP0jEjVZ9aTAQo79ZtZ-x/s1600/scroll.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhx6Sh4Mnscmb-e2wt-1dWOj8T3tbrivjg-q4bZCU6XX_mAW3guTiaRyL2rhOBdnmhlb3uWBXuWJFhhuvvzPbpvO2cd2mWA2bPKds5pDKceml4BcqSgS0ulGv6QP0jEjVZ9aTAQo79ZtZ-x/s320/scroll.png" width="312" /></a></div>These work fine for native GTK applications, but applications built using the wxPython toolkit suffer from render corruption when you try and scroll a styled text control (<a href="http://trac.wxwidgets.org/ticket/13229">bug report</a>). This bug manifests itself in many applications, including my current favorite development text editor <a href="http://code.google.com/p/editra/">editra</a>. Here's a screenshot of the issue:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjybUX5T3sRcHcAcKHiazSsH6MFkYdf76afmWX-R3dqwGCFMLgJjRXnrnfDwK5BdWLm4dJWdKKz7iX9zPuewCx0_OA1UIninxyHcYZyo7Zi9T4EpiiB6QcSZWXrLINiVA7WJ5RLFoeAhgTK/s1600/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="199" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjybUX5T3sRcHcAcKHiazSsH6MFkYdf76afmWX-R3dqwGCFMLgJjRXnrnfDwK5BdWLm4dJWdKKz7iX9zPuewCx0_OA1UIninxyHcYZyo7Zi9T4EpiiB6QcSZWXrLINiVA7WJ5RLFoeAhgTK/s320/Screenshot.png" width="320" /></a></div><b>Solution:</b><br />
<b><br />
</b><br />
The problem can be avoided by turning the thin scrollbars off. How do you do that? Easy - launch the application with the "LIBOVERLAY_SCROLLBAR" environment variable set to 0, like this:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7rm01Trmq8FgCIvRQO_xJWxwvhHVkqkPQpj289bEhv89l8gHSRuz2JXJz0JT796h2RqWhyny5XD2-TK3qQ86pRvrVNSfCHcsNHQG-JxLKTTLp1M19BV-Ing-ck27FE0TNxo3ifBWhm9fB/s1600/launch_editra_without_scrollbars.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="105" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7rm01Trmq8FgCIvRQO_xJWxwvhHVkqkPQpj289bEhv89l8gHSRuz2JXJz0JT796h2RqWhyny5XD2-TK3qQ86pRvrVNSfCHcsNHQG-JxLKTTLp1M19BV-Ing-ck27FE0TNxo3ifBWhm9fB/s320/launch_editra_without_scrollbars.png" width="320" /></a></div>You can of course edit the menu item for editra to include this, or add the line "export LIBOVERLAY_SCROLLBAR=0" to your ~/.xprofile file (create it if it doesn't exist).<br />
<br />
<b>Panel Corruption:</b><br />
<b><br />
</b><br />
Whenever I change a setting in the compiz config settings manager (ccsm), the top panel of my unity desktop becomes corrupted. Previously the only way to fix this was to log out and log back in again (effectively restarting unity). Here's a screenshot of the problem:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIknxagwEwjV-uJFCtKwEOpASWQc6Zgn1BRT6QF6WMQlEIllK23DP4fHtJgwq2fH-cdH5YSkq1aapiFxswbiVCL6AtG5O5-3VV8TBTRU5mrVtE_WXSWDficIz7qC2h_a-hEYzC7IM6KKal/s1600/corruption.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIknxagwEwjV-uJFCtKwEOpASWQc6Zgn1BRT6QF6WMQlEIllK23DP4fHtJgwq2fH-cdH5YSkq1aapiFxswbiVCL6AtG5O5-3VV8TBTRU5mrVtE_WXSWDficIz7qC2h_a-hEYzC7IM6KKal/s320/corruption.png" width="320" /></a></div><br />
<b>Solution:</b><br />
<b><br />
</b><br />
When this happens you can restart unity without having to logout, or close any applications. Simply run (either by pressing Alt+F2, or in a terminal):<br />
<br />
unity --replaceAnonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-61306368181093144712011-05-10T19:18:00.000+12:002011-05-10T19:18:51.442+12:00CAPTCHA FailI can understand the need to filter humans from machines on the Internet, but we need to do a much better job. It seems like the most common captcha software I run into these days is<a href="http://www.google.com/recaptcha"> reCAPTCHA</a>. The system has some noble goals - specifically, users who submit captchas are actually helping digitize books. However, here's the problem:<br />
<div><br />
</div><div><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiddxu4I3S0c-nRViD9jsAK1UaRWpiPzCyOdG3qDoPYwCMx9kVCMqoGbuv3EjPyMIP6dD0GrCjZT57XclhfVeoaMNKXBn27NiMh1SKnOurrmvqX9i9v1GZn7Sjin2XP1U1SvhMgUDDV2Tq/s1600/captcha+fail.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5541081784793282834" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiiddxu4I3S0c-nRViD9jsAK1UaRWpiPzCyOdG3qDoPYwCMx9kVCMqoGbuv3EjPyMIP6dD0GrCjZT57XclhfVeoaMNKXBn27NiMh1SKnOurrmvqX9i9v1GZn7Sjin2XP1U1SvhMgUDDV2Tq/s400/captcha+fail.png" style="cursor: hand; cursor: pointer; display: block; height: 42px; margin: 0px auto 10px; text-align: center; width: 210px;" /></a>What the hell does that say? The first word is obviously "the", the second? "Claccupr?". Perhaps I have bad eyesight, but I often get these wrong. Here's an alternative proposal:</div><div><br />
</div><div>Instead of asking humans to perform text recognition (something computers can already do reasonably well), ask them to do something that comes naturally to humans, but not to computers. How about asking the user to pick which image they might find at a beach. Or ask the user to pick the image that represents the largest object in real life. Use context that humans understand instinctively, but computers do not.<br />
<br />
Any ideas? Someone should build it!</div>Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-8065771382117733512011-04-29T16:24:00.003+12:002011-05-27T14:31:02.851+12:00Sloecode: Now with Ubuntu Packages!<div class="separator" style="clear: both; text-align: center;"><br />
</div>We're still working towards a sloecode 1.0 release. We're now dangerously close - we have some UI tweaks to complete, and a few other bits and pieces. However, we now have Ubuntu packages for both the client and server components, ready for you to test!<br />
<br />
<b>What is Sloecode?</b><br />
<b><br />
</b><br />
Sloecode is an open source project, <a href="http://launchpad.net/sloecode">hosted on launchpad.net</a> that aims to provide a comprehensive, installable code forge. A "code forge" is a set of tools that help groups of people write software (think sourceforge, launchpad etc). It typically includes a revision control system, and optionally project wikis, bug tracking, issue tracking, feature planning and any other features people might need. However, it's important to note that <i>we're not trying to replicate Launchpad!</i> Launchpad is a great service, and we don't want to compete with it. Instead, we're providing a tool for people who:<br />
<br />
<ul><li>Don't want their code to be public - either because it's commercial software or because it's not ready yet. You can use sloecode in your business, college, university without having to release your software to the wider world. You can do this on launchpad, but you must pay for the privilege. The project was borne out of the need to have a code forge for an educational environment: putting students' work online is not an option.<br />
<br />
</li>
<li>Want their code forge system to be hosted locally. For large code bases, the communication times between a local machine and the central launchpad.net servers can become expensive - especially in locations where the Internet connection is poor. Running sloecode is easy (as we'll see soon) and gives you complete control over the system. You're are responsible for server maintenance, backup, and general administration.</li>
</ul><div>Compared to Launchpad, we're aiming for a <i>completely different</i> user base.</div><div><br />
</div><div><b>How does it Work?<br />
</b></div><div>Sloecode is made up of two distinct parts:</div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnHj2p1LPUpABabmS_k4HT7XrEsZnv5Nf_cOQUswb53ieGaxQLAOCc9QGy8RkIsd4JClitGwL8GdibhO9QTH_gGNPLt8v6R4dZdkyktKbLhKSSxWWF59SYmransK3yTMPs4ov-K0PE4UlO/s1600/sloecode_components.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnHj2p1LPUpABabmS_k4HT7XrEsZnv5Nf_cOQUswb53ieGaxQLAOCc9QGy8RkIsd4JClitGwL8GdibhO9QTH_gGNPLt8v6R4dZdkyktKbLhKSSxWWF59SYmransK3yTMPs4ov-K0PE4UlO/s640/sloecode_components.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br />
</div><div>The Bazaar/SSh smart server is a <a href="http://www.blogger.com/"><span id="goog_1216279712"></span>python-twisted<span id="goog_1216279713"></span></a> application that understands the SSH protocol, and runs bzr-serve on demand for users. Every time you interact with the server using a Bazaar client application you're actually talking to the smart server. We need this component for several reasons: first, we don't want users to require a system account on the Linux server (which is the usual way of setting up a Bazaar server), but we do still want to use SSH public/private key authentication. This means the SSH server needs to know about our database and be able to retrieve keys from it on demand.<br />
<br />
The Sloecode Web App is the front-end for the whole system. It's written in <a href="http://pylonsproject.org/">pylons</a>, and makes use of a whole host of other libraries including <a href="http://jinja.pocoo.org/docs/">jinja2</a> (page templates), <a href="http://formencode.org/">formencode</a> (input validation), <a href="http://developer.yahoo.com/yui/3/">YUI3</a> (javascript components), <a href="http://repoze.org/">repoze.what and repoze.who</a> (authorisation and authentication), and a whole lot more. The web-app provides control for managers and administrators to create projects and users and assign users to projects (with different levels of access). Regular users can see basic information about their bazaar branches (both personal repositories and project repositories), and manage their SSH keys.<br />
<br />
The plan for the future is to add optional components - the key word being <i>optional</i>. One of our design goals is to make sloecode easy to install; this includes minimising install-time dependancies.<br />
<br />
The key thing to understand about Sloecode is that we're not writing the VCS ourselves - we're simply making Bazaar easier to install and manage.<br />
<br />
<b>Enough already, give me the server!</b><br />
<b><br />
</b><br />
Sloecode has not yet been released, but you are welcome to participate in testing. To set up the server, you'll first need the sloecode PPA in your sources.list. To achieve this, run the following command:<br />
<br />
<pre>sudo add-apt-repository ppa:sloecode</pre><br />
Then update your package lists:<br />
<br />
<pre>sudo apt-get update</pre><br />
You can now install the sloecode server package:<br />
<br />
<pre>sudo apt-get install sloecode</pre><br />
The server package <b>should</b> install all the package dependancies. However, before you can run the server, you need to set up the database back-end. The default back-end us sqlite, which is fine for testing or for very low-use installations. Sloecode uses sqlalchemy, which allows us to use any number of databse backends. This, and many other configuration details can be edited by tweaking this file:<br />
<br />
<pre>/etc/default/sloecode-production.ini</pre><br />
Once you're happy with the settings, you need to create the database tables. Do this by running:<br />
<br />
<pre>sudo paster setup-app /etc/default/sloecode-production.ini</pre><br />
This command will read the values present in the configuration file, and create the default database tables for you. You only need to run this command once (to create the tables in your database)!<br />
<br />
If you have edited any of the other values, you will want to restart the server:<br />
<br />
<pre>sudo service sloecode restart</pre><br />
By default, log files are in /var/log/sloecode, Bazaar repositories are created in <br />
<br />
<pre>/srv/sloecode/bzr-repos</pre><br />
and the default database is a simple SQLite file (which won't handle any kind of heavy workload or concurrency, so you may wish to change that). The RSA public/private key pair the smart server uses to communicate with clients are stored in <br />
<br />
<pre>/var/sloecode/keys</pre><br />
<br />
<b>And the clients?</b><br />
<b><br />
</b><br />
Client setup is much simpler. Simply follow these steps:<br />
<ol><li>Make sure you have an account created for you in the sloecode web interface. Log in to the web interface with your username and password.<br />
</li>
<li>Click on the "Manage SSH Keys" link on your home page. You need to paste your SSH public key in the form provided. This allows your Bazaar client to authenticate with the sloecode server. If you don't have an SSH key, you can generate one by running: <br />
<br />
<pre>ssh-keygen</pre><br />
and view the public key by running: <br />
<br />
<pre>cat ~/.ssh/id_rsa.pub
</pre></li>
<li>All client machines need the 'bzr' and 'bzr-sloecode' packages installed. Assuming you have the sloecode PPA installed (see instructions for doing this in the server section, above), you can run:<br />
<br />
<pre>sudo apt-get install bzr bzr-sloecode
</pre></li>
<li>Finally, you need to tell the Bazaar sloecode plugin where the sloecode server is. The client plugin looks for an environment variable called "SLOECODE_SERVER", and will complain if it is not found. The easiest way to set this environment variable is to edit your "~/.bashrc" file and add this line to the end:<br />
<br />
<pre>export SLOECODE_SERVER=domain.of.your.server.com</pre><br />
The value of this variable should be either a domain name, OR an IP address that points to the sloecode server you wish to use. For example, if the server is installed on the local network you might have the following:<br />
<br />
<pre>export SLOECODE_SERVER=192.168.1.10</pre><br />
Note that you must not add any network protocol specification - the sloecode client plugin takes care of that for you. If you are running the sloecode ssh service on a port other than 22, you must add this port to the end of the string, like so:<br />
<br />
<pre>export SLOECODE_SERVER=192.168.1.10:4022</pre><br />
</li>
<li>Finally, if your username on the sloecode server is different from your local computer username, you need to tell the Bazaar sloecode plugin what username it should use. To do this, run the command:<br />
<br />
<pre>bzr sc-login sloecode_username</pre><br />
Where "sloecode_username" is the username you use to log in to the sloecode web interface. For example, on my machine the command is:<br />
<br />
<pre>bzr sc-login thomir</pre><br />
If you run the command without a username it will tell you what username is currently set.<br />
</li>
</ol><br />
That's it! Everything is all set up. Now you can start using the sloecode server.<br />
<br />
<b>Bazaar / Sloecode Basics</b><br />
<b><br />
</b><br />
I won't cover the details of how to use Bazaar. If you need that instruction, look at the official Bazaar documentation. However, here are a few pointers:<br />
<br />
<ul><li>Every user on the sloecode server has a personal repository. To push code to your personal repository, do this:<br />
<br />
<pre>bzr push sc:~sloecode_username/branch_name</pre><br />
By default personal repositories are created with no branches, so whenever you push or pull from a personal repository you must always specify a branch name!<br />
<br />
</li>
<li>Personal repositories are private - you are the only one who can read or write to your personal repository. If you need to share your code with someone else, you need to store it in a project repository.<br />
<br />
</li>
<li>To pull code from a project repository, the command looks like this:<br />
<br />
<pre>bzr pull sc:project_name/branch_name</pre><br />
Note that there is no tilde character before the project name. Also note that you need not specify the branch name if you want the special branch called "trunk". For example, if I want a copy of the trunk branch of project "elastic", I'd run the following command:<br />
<br />
<pre>bzr pull sc:elastic</pre><br />
However if I want a specific branch called "fix-bug-1234", I'd run the following:<br />
<br />
<pre>bzr pull sc:elastic/fix-bug-1234<pre></pre></pre></li>
</ul><div><b>Final Thoughts:</b><br />
<b><br />
</b><br />
We're still writing sloecode - it's an ongoing effort and won't be finished any time soon. We welcome your feedback - the best way to contact is us via the <a href="https://launchpad.net/%7Esloecode-dev">sloecode-developers</a> mailing list, or in the #sloecode channel on freenode IRC, or leave a comment below. Have we missed anything? Spot any bugs? Have suggestions for improvements/future direction? We'd love to hear from you!</div></div>Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-31106058122708788592011-04-05T12:42:00.000+12:002011-04-05T12:42:27.499+12:00Sloecode updates: UI tweaksSeveral members of the <a href="https://launchpad.net/~sloecode">sloecode team</a> have been hard at work tweaking the sloecode web-app UI - we think we have a much more usable product as a result. We've still got a long way to go, but the UI is looking better every day. Here's a picture of the portal page a user sees when they log in:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjLVLwqFr69eU1vpzupXoUhy4UoV84xcNOW6m1cENDoXquuJRu5hmtzK3wOHA1pt8MFvfXWX7yL59uRhO9nux2w0ZUzpRGy7PyX7Ne3A2nQdlg0T7Mo9MjXgLyYfiR3s-IfDcAeHhCQow1/s1600/sc_progress.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjLVLwqFr69eU1vpzupXoUhy4UoV84xcNOW6m1cENDoXquuJRu5hmtzK3wOHA1pt8MFvfXWX7yL59uRhO9nux2w0ZUzpRGy7PyX7Ne3A2nQdlg0T7Mo9MjXgLyYfiR3s-IfDcAeHhCQow1/s400/sc_progress.png" width="400" /></a></div>Changes from the previous version include:<br />
<br />
<ul><li>Addition of the project menu - this allows users to quickly jump to any project they are a member of.</li>
<li>Branch logs are now shown on separate pages, instead of cluttering up the main user/project page.</li>
<li>"Account Settings" and "Logout" Links are now pushed to the right of the page menu bar, which is where most users expect them to be.</li>
<li>More help topics have been written.</li>
<li>Lots of small textual changes to page content - too many to list individually.</li>
</ul><div>We still have not got the server package into our PPA. In the mean time, installing and running a sloecode server involves a few manual steps, but is by no means complicated. If you're interested in the project, feel free to drop in the #sloecode channel on irc.freenode.net, or introduce yourself on the <a href="https://launchpad.net/~sloecode-dev">sloecode developers mailing list</a>!</div>Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-88701828817297369842011-03-15T19:45:00.000+13:002011-03-15T19:45:32.559+13:00bzr-sloecode Installer for Windows<div xmlns="http://www.w3.org/1999/xhtml">There's now a <strong>basic</strong> installer for the bzr-sloecode Bazaar plugin for Windows. It currently does the following:<br />
<ol><li>Installs the plugin to the right place.</li>
<li>Sets the SLOECODE_SERVER environment variable to whatever you want.</li>
</ol>There are a number of aspects that require improvment however:<br />
<ol><li>It doesn't check that Bazaar is installed first.</li>
<li>It doesn't ask if the user wants to install the plugin for everyone or just the current user. Currently the SLOECODE_SERVER setting is system-wide, which requires admin permissions to set.</li>
<li>No validation on the Bazaar server address.</li>
</ol>...So it's a work in progress! Patches are more than welcome. You can grab the installer from the <a href="http://launchpad.net/bzr-sloecode">bzr-sloecode launchpad page</a>.</div>Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-17043039791474867712011-02-25T11:54:00.000+13:002011-02-25T11:54:40.288+13:00Another Microsoft UI Fail...this time in Microsoft Outlook. Could the programmer who was too lazy to write their code properly please go back to school? There is no excuse for this:<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxGaV7Axml8yOcYfCmllEIh-jsSdzL5nndg29ENIwZogOHRKQkN_j7o9gdXtki-BNO44W3lErI-1Uw1rkz2ptgWKVffirk01bpFckpqGopRW0vXwlVw2EAiq5LFmAYtjxe5W0bYlDQRIX7/s1600/outlook_fail.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxGaV7Axml8yOcYfCmllEIh-jsSdzL5nndg29ENIwZogOHRKQkN_j7o9gdXtki-BNO44W3lErI-1Uw1rkz2ptgWKVffirk01bpFckpqGopRW0vXwlVw2EAiq5LFmAYtjxe5W0bYlDQRIX7/s1600/outlook_fail.PNG" /></a></div>You want me to take this string, split it on comma characters, and re-join it with semi-colons instead? Sure, I'll do that you you, with my meat-fingers, because I'm really good at that, and computers are known to be terrible and SIMPLE TEXT MANIPULATION.Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-37301061005848183212011-02-24T16:34:00.000+13:002011-02-24T16:34:39.089+13:00Introducing: Sloecode<a href="http://bazaar.canonical.com">Bazaar</a> is wonderful. It combines the right powerful features with a good dose of common-sense and a sprinkling of usability. Well okay, perhaps more than a sprinkling of usability. I use bazaar a lot in combination with <a href="http://launchpad.net">launchpad</a>. The client-side bzr-launchpad plug-in makes this a breeze: I don't have to remember user-names, passwords, project URLs, or anything else.
However, occasionally I don't want my code to be visible by default. Sometimes I don't want my code leaving the building. I could easily host a simple bazaar repository locally, but creating teams of users quickly gets difficult. What I'd love is a system like launchpad, but with a few key differences:
<ol>
<li><p>Optimised for the most common use-case. Launchpad does an awful lot of stuff that I have never used, and probably never will. All this functionality makes launchpad a very large beast indeed. I want a system that's compact and easy to use; I don't need translations, build recipes, mailing lists, bug tracking, etc. etc.</p></li>
<li><p>Easily installed on my own server. It is technically possible to install launchpad wherever you want, but it's difficult. </p></li>
</ol>
Enter my current open source project: <a href="http://launchpad.net/sloecode">sloecode</a>.
Sloecode is a simple wrapper around bazaar and a few other key technologies that makes it easy to set up multiple users & teams of developers. We're trying to optimise sloecode for the most common problems.
What do we have so far?
<ul>
<li><p>A simple web app (written in <a href="http://python.org">python</a> & <a href="http://pylonshq.com">pylons</a>) that allows one to create users, teams, and manage both.</p></li>
<li><p>A bzr+ssh smart server that understands the accounts and teams created in the web-app. </p></li>
<li><p>A client-side bzr plugin that allows users to use shortened repo URLs (similar to the lp:projectname scheme the launchpad plug-in provides).</p></li>
</ul>
Sloecode is still very much "work in progress" (we've got big plans), but it is usable right now. If you want more information, feel free to leave a comment below, or join the sloecode-dev mailing list on launchpad.Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-84513292348572286252011-01-24T09:26:00.000+13:002011-01-24T09:26:19.288+13:00Visual Studio FailPerhaps this is a symptom of the underlying operating system, rather than the Visual Studio IDE. In either case it sucks:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg75Ovimpl-ANcvNd2OjVpr0pvwISPatm6Kux3Q4w6O9PjMDIgKoON8vOzbHyyLxK9ZbAPzU0ZNEY4smB7Yv0CotpSug3QVzEOvHt1iRUBhuJOmFDCAPVyRcXyZCDWlE6wlXwOU7eS6RQ78/s1600/VSFail.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="77" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg75Ovimpl-ANcvNd2OjVpr0pvwISPatm6Kux3Q4w6O9PjMDIgKoON8vOzbHyyLxK9ZbAPzU0ZNEY4smB7Yv0CotpSug3QVzEOvHt1iRUBhuJOmFDCAPVyRcXyZCDWlE6wlXwOU7eS6RQ78/s640/VSFail.png" width="640" /></a></div>I like to keep my files organised in folder hierarchies. Now I'm being forced to use a flat, wide folder tree by my IDE.<br />
<br />
Not. Happy. At. All.Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.comtag:blogger.com,1999:blog-128616657362436845.post-57499001061390550792011-01-17T14:08:00.000+13:002011-01-17T14:08:59.890+13:00Virtualbox web front-endI <a href="http://tech-foo.blogspot.com/2008/08/virtualbox-rocks.html">mentioned before that virtualbox rocks</a>. Now it rocks even harder. I've always wanted to run multiple virtual machines on a powerful, headless server. Previously there hasn't been an adequate user interface (read: not a command line) that lets me manage multiple virtualbox instances.<br />
<br />
<a href="http://code.google.com/p/phpvirtualbox/">Now there is.</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi81WWanOgFFn3BF4D-QHVFANIAj0chyphenhyphentplC7uBrdBfomoqLrxP5TEqb038vI7oeSiYngslrVcBE7Z2f5WJqOS0yopKkPTe2EKoGaE6XXOQnG59nGOxuOMDE7Rv8NQ66R0kKgDfzu8c9yEF/s1600/phpvb1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="473" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi81WWanOgFFn3BF4D-QHVFANIAj0chyphenhyphentplC7uBrdBfomoqLrxP5TEqb038vI7oeSiYngslrVcBE7Z2f5WJqOS0yopKkPTe2EKoGaE6XXOQnG59nGOxuOMDE7Rv8NQ66R0kKgDfzu8c9yEF/s640/phpvb1.png" width="640" /></a></div><br />
...and my doesn't it look pretty?Anonymoushttp://www.blogger.com/profile/01510613850668885604noreply@blogger.com