A Django site.
June 25, 2009

Kevin Kubasik
nonic
For Once I Oneder
» Django Windmill Tests – GSOC Progress Update

I feel that a status update is long overdue, but as the corpus of Windmill tests grows, so does the time it takes to run a complete instance of the regression suite. However, I do have some fun progress to report as well as a few questions/problems that are showing themselves now that all the fluff is over. First, let’s talk about the fun stuff!

I do have 3 of my major improvements/fixes/restructures to django.test somewhat complete. At the moment they are lacking most in documentation, a problem I intended to rectify later this week.

  1. Windmill Tests: Windmill test runners are nearly complete, threaded development server for AJAX widget testing complete.
  2. Code Coverage: Coverage.py support for runtests.py and management command. Extensible system is easily pluggable with other coverage systems.
  3. Test-Only Models: This is still a topic of discussion, but adding the property ‘test_models’ to a TestSuite will load and wipe the models. Has tests and limited docs.

My major TODO’s still outstanding:

  • Documentation!
  • Twill Runner Support (Utilizing the Windmill Threaded Server)
  • Windmill Admin Regression Tests (Healthy set of tests written, need to document and finish more)
  • Skip tests that are known to fail
  • Test new features/API’s

That’s it for now, more updates are available on the django-dev list!

June 27, 2009

Dennis Muhlestein
nonic
All My Brain
» Launching wxPython apps with an iPython shell

Suppose you want to run your fancy wxPython application but have a shell in the background to peek and poke at certains settings, help debug, and possibly even use an API that your program provides to automate tasks. iPython has built in wx support (as well as support for other GUIs and frontends). [...]

June 24, 2009

John Anderson
sontek
John Anderson ( sontek )
» Python with a modular IDE (Vim)

On Thursday, May 9th, 2008 the Utah Python User Group decided to settle the debate that has plagued us developers since the beginning of time: If you were a programming language, what editor would you use?

I was tasked with showing Eclipse with the PyDev plugin in all its glory–but we all know–real men / developers don’t use IDE’s, so we are going to talk about using Python and Vim together, reaching a state of Zen that the Dalai LLama would be jealous of and establishing more Feng Shui than Martha Stewart’s Kitchen.

Freely jump between your code and python class libraries

There are 2 ways to add your ability to jump between python class libraries, the first is to setup vim to know where the Python libs are so you can use ‘gf’ to get to them (gf is goto file). You can do this by adding this snippet to your .vimrc:

python << EOF
import os
import sys
import vim
for p in sys.path:
    if os.path.isdir(p):
        vim.command(r"set path+=%s" % (p.replace(" ", r"\ ")))
EOF

With that snippet you will be able to go to your import statements and hit ‘gf’ on one of them and it’ll jump you to that file.

Continuing accessibility of the Python class libraries we are going to want to use ctags to generate an index of all the code for vim to reference:

$ ctags -R -f ~/.vim/tags/python.ctags /usr/lib/python2.5/

and then in your .vimrc

set tags+=$HOME/.vim/tags/python.ctags

This will give you the ability to use CTRL+] to jump to the method/property under your cursor in the system libraries and CTRL+T to jump back to your source code.

I also have 2 tweaks in my .vimrc so you can use CTRL+LeftArrow and CTRL+RightArrow to move between the files with more natural key bindings.

map <silent><C-Left> <C-T>
map <silent><C-Right> <C-]>

You can also see all the tags you’ve been to with “:tags”

Code Completion

To enable code completion support for Python in Vim you should be able to add the following line to your .vimrc:

autocmd FileType python set omnifunc=pythoncomplete#Complete

but this relies on the fact that your distro compiled python support into vim (which they should!).

Then all you have to do to use your code completion is hit the unnatural, wrist breaking, keystrokes CTRL+X, CTRL+O. I’ve re-bound the code completion to CTRL+Space since we are making vim an IDE! Add this command to your .vimrc to get the better keybinding:

inoremap <Nul> <C-x><C-o>

Documentation

No IDE is complete without the ability to access the class libraries documentation! You’ll need to grab this vim plugin. This gives you the ability to type :Pydoc os.path or use the keystrokes <Leader>pw and <Leader>pW to search for the item under the cursor. (Vim’s default <Leader> is “\”).

Syntax Checking

Vim already has built in syntax highlighting for python but I have a small tweak to vim to give you notifications of small syntax errors like forgetting a colon after a for loop. Create a file called ~/.vim/syntax/python.vim and add the following into it:

syn match pythonError "^\s*def\s\+\w\+(.*)\s*$" display
syn match pythonError "^\s*class\s\+\w\+(.*)\s*$" display
syn match pythonError "^\s*for\s.*[^:]$” display
syn match pythonError “^\s*except\s*$” display
syn match pythonError “^\s*finally\s*$” display
syn match pythonError “^\s*try\s*$” display
syn match pythonError “^\s*else\s*$” display
syn match pythonError “^\s*else\s*[^:].*” display
syn match pythonError “^\s*if\s.*[^\:]$” display
syn match pythonError “^\s*except\s.*[^\:]$” display
syn match pythonError “[;]$” display
syn keyword pythonError         do

Now that you have the basics covered, lets get more complicated checking added. Add these 2 lines to your .vimrc so you can type :make and get a list of syntax errors:

autocmd BufRead *.py set makeprg=python\ -c\ \"import\ py_compile,sys;\ sys.stderr=sys.stdout;\ py_compile.compile(r'%')\"
autocmd BufRead *.py set efm=%C\ %.%#,%A\ \ File\ \"%f\"\\,\ line\ %l%.%#,%Z%[%^\ ]%\\@=%m

You will have the ability to to type :cn and :cp to move around the error list. You can also type :clist to see all the errors, and finally, sometimes you will want to check the syntax of small chunks of code, so we’ll add the ability to execute visually selected lines of code, add this snippet to your .vimrc:

python << EOL
import vim
def EvaluateCurrentRange():
eval(compile('\n'.join(vim.current.range),'','exec'),globals())
EOL
map <C-h> :py EvaluateCurrentRange()

Now you will be able to visually select a method/class and execute it by hitting “Ctrl+h”.

Browsing the source

Moving around the source code is an important feature in most IDE’s with their project explorers, so to get that type of functionality in vim we grab the Tag Listplugin. This will give you the ability to view all opened buffers easily and jump to certain method calls in those buffers.

The other must-have feature of an IDE when browsing code is being able to open up multiple files in tabs. To do this you type :tabnew to open up a file in a new tab and than :tabn and :tabp to move around the tabs. Add these to lines to your .vimrc to be able to move between the tabs with ALT+LeftArrow and ALT+RightArrow:


map <silent><A-Right> :tabnext<CR>
map <silent><A-Left> :tabprevious<CR>

Debugging

To add debugging support into vim, we use the pdb module. Add this to your ~/.vim/ftplugin/python.vim to have the ability to quickly add break points and clear them out when you are done debugging:

python << EOF
def SetBreakpoint():
    import re
    nLine = int( vim.eval( 'line(".")'))

    strLine = vim.current.line
    strWhite = re.search( '^(\s*)', strLine).group(1)

    vim.current.buffer.append(
       "%(space)spdb.set_trace() %(mark)s Breakpoint %(mark)s" %
         {'space':strWhite, 'mark': '#' * 30}, nLine - 1)

    for strLine in vim.current.buffer:
        if strLine == "import pdb":
            break
    else:
        vim.current.buffer.append( 'import pdb', 0)
        vim.command( 'normal j1')

vim.command( 'map <f7> :py SetBreakpoint()<cr>')

def RemoveBreakpoints():
    import re

    nCurrentLine = int( vim.eval( 'line(".")'))

    nLines = []
    nLine = 1
    for strLine in vim.current.buffer:
        if strLine == ‘import pdb’ or strLine.lstrip()[:15] == ‘pdb.set_trace()’:
            nLines.append( nLine)
        nLine += 1

    nLines.reverse()

    for nLine in nLines:
        vim.command( ‘normal %dG’ % nLine)
        vim.command( ‘normal dd’)
        if nLine < nCurrentLine:
            nCurrentLine -= 1

    vim.command( ‘normal %dG’ % nCurrentLine)

vim.command( ‘map <s-f7> :py RemoveBreakpoints()<cr>’)
EOF

With that code you can now hit F7 and Shift-F7 to add/remove breakpoints. Then you just launch your application with !python % (percent being the current file, you can declare your main file here if its different).

Another tweak I use is to have my vim inside screen with a horizontal split, that way I can see the python interpreter and debug while still having vim there so I can easily fix my code.

Snippets

A great time saver with standard IDE’s is code snippets, so you can type a few key strokes and get a lot of code out of it. An example of this would be a django model, instead of typing out the complete declaration you could type ‘mmo<tab><tab>’ and have a skeleton of your model done for you. To do this in vim we grab the Snippets EMU plugin.

Check out a great screencast of snippetsEmu in action here

Emacs

Here is a great post on how to do the same with Emacs.

kick it on DotNetKicks.com

June 19, 2009

Matt Harrison
no nic
Matt Harrison's blog
» Helping the Python Excel story

I have posted previously about Excel and Python. Which led to my blog being a top hit for those terms for a while. Chris Withers has decided that there should be a central hub for reading and writing Excel with Python. This is great and should help provide a clearer story for Python and Excel (remember folks, these libraries are pure python, so you can generate .xls on your Mac or Linux (or MS) box).

As my brother noted if you are looking for professional assistance in generating .xls in python (or for that matter Python in general) feel free to contact me.

May 27, 2009

Kevin Kubasik
nonic
For Once I Oneder
» Google Summer of Code 2009 - Django Testing - Coding Day 1

Among all the excitement of the past few weeks, the start of GSOC appears to have snuck up on me! Started work today on the coverage runner. My progress is easily followed on my GitHub Django fork (until we get real SVN branches). Can’t wait to start posting some real results!

April 29, 2009

Matt Harrison
no nic
Matt Harrison's blog
» Another reason to learn python: outsourcing insurance

Looks like they won't be outsourcing your python job to India soon ;) (via Planet Sugar) When I was in India it was clear people were reluctant to work for a small company, there was much pride in being a Java-drone at a large company. Perhaps this is similar to languages. Where is the pride in knowing python if half the people you talk to (who are technical) don't even know what it is?

April 28, 2009

Adam Olsen
synic
Vimtips Latest Articles
» Django: Using ModelAdmin to default to currently logged in user

Yeah, you may have noticed that I've been working on the blog lately. Poor openclue.org got flooded with already posted RSS feeds again. This happens all to often. Sorry guys.

Anyway, this blog system has the ability to have more than one person post articles. In the past, sjohannes used to post here too. The model for articles looks something like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from django.contrib.auth.models import User
from django.db import models
import datetime

class Article(models.Model):
     title = models.CharField(max_length=250)
     slug = models.SlugField()
     article = models.TextField()
     pub_date = models.DateTimeField(
          default=datetime.datetime.now)
     publisher = models.ForeignKey(User)

As you can see, there's a ForeignKey to django.contrib.auth.models.User. The question here is: how do I make the "publisher" field default to the currently logged in user? It was harder than I thought it should be, but it can be done using hooks in the ModelAdmin for the Article model. Take a look:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('pub_date', 'publisher', 'title', 'slug')
    search_fields = ('title', 'article')
    prepopulated_fields = {
        'slug': ('title',),
    }

    def get_form(self, req, obj=None, **kwargs):
        # save the currently logged in user for later
        self.current_user = req.user
        return super(ArticleAdmin, self).get_form(req, obj, **kwargs)

    def formfield_for_dbfield(self, field, **kwargs):
        from django import forms
        from django.contrib.auth import models
        if field.name == 'publisher':
            queryset = models.User.objects.all()
            return forms.ModelChoiceField(
                queryset=queryset, initial=self.current_user.id)
        return super(ArticleAdmin, self).formfield_for_dbfield(field, **kwargs)

admin.site.register(models.Article, ArticleAdmin)

As you can see, I overload "get_form" for one purpose: It takes the HttpRequest as the first argument, which we can use to save the currently logged in user. The other method that's overloaded, "formfield_for_dbfield" is called for every field in the model, and is made for the purpose of specifying your own custom form fields (and widgets). In this case, we use the same field type that the admin would have used - "ModelChoiceField" and give it an initial, which is the id of the currently logged in user.

There you have it. It's a little hacky, but it's the only way I could find to do it. If you've seen a cleaner way, let me know!"

November 25, 2008

Adam Olsen
synic
Vimtips Latest Articles
» Bazitis: Gitosis for Bzr (Baazar)

At work, I use git. For Exaile I use bzr. I like them both quite a bit. At work, we use Gitosis to manage our repositories and I have to say, it's pretty damn cool. Nothing quite like this exists for bzr, so I ported Gitosis to bzr and called it Bazitis. The launchpad project page can be found here. Here are the instructions on how to use Bazitis:

First off, I'd like to give credit to some people. Tommi Virtanen is the author of Gitosis. Bazitis is a copy of the Gitosis code, all except for the parts where I had to get a little hacky with bzrlib. His website is http://eagain.net. The other person I'd like to thank is Garry Dolley, who wrote a great blog post on how to use Gitosis, which can be found here: hosting git repositories the easy and secure way. Garry has given me permission to copy his instructions and modify them for Bazitis, as long as I give him kudos, which I have done in this paragraph. Thanks guys!

Install bazitis

bazitis is a tool for hosting bzr repositories (I'm repeating myself for those who skim :)

The first thing to do is grab a copy of bazitis and install it on your server:

cd ~/src
bzr branch lp:bazitis

Next, install it like so:

cd bazitis
python setup.py install

Don't use --prefix unless you like self-inflicted pain. It is possible to install bazitis in a non-standard location, but it's not nice. Read the Caveats section at the bottom and then come back here.

If you get this error:

-bash: python: command not found

or

Traceback (most recent call last):
  File "setup.py", line 2, in ?
    from setuptools import setup, find_packages
ImportError: No module named setuptools

You have to install Python setuptools. On Debian/Ubuntu systems, it's just:

sudo apt-get install python-setuptools

For other systems, someone tell me or leave a comment, so I can update this section and improve this tutorial.

The next thing to do is to create a user that will own the repositories you want to manage. This user is usually called bzr, but any name will work, and you can have more than one per system if you really want to. The user does not need a password, but does need a valid shell (otherwise, SSH will refuse to work).

sudo adduser \
    --system \
    --shell /bin/sh \
    --gecos 'bzr version control' \
    --group \
    --disabled-password \
    --home /home/bzr \
    bzr

You may change the home path to suit your taste. A successful user creation will look similar to:

Adding system user `bzr'...
Adding new group `bzr' (211).
Adding new user `bzr' (211) with group `bzr'.
Creating home directory `/home/bzr'.

You will need a public SSH key to continue. If you don't have one, you may generate one on your local computer:

ssh-keygen -t rsa

The public key will be in $HOME/.ssh/id_rsa.pub. Copy this file to your server (the one running bazitis).

Next we will run a command that will sprinkle some magic into the home directory of the bzr user and put your public SSH key into the list of authorized keys.

sudo -H -u bzr bazitis-init < /tmp/id_rsa.pub

id_rsa.pub above is your public SSH key that you copied to the server. I recommend you put it in /tmp so the bzr user won't have permission problems when trying to read it.

Here some cool magic happens. Run this on your local machine:

bzr branch bzr@YOUR_SERVER_HOSTNAME/bazitis-admin
cd bazitis-admin

You will now have a bazitis.conf file and keydir/ directory:

~/dev/bazitis-admin (master) $ ls -l
total 8
-rw-r--r--   1 garry  garry  104 Nov 13 05:43 bazitis.conf
drwxr-xr-x   3 garry  garry  102 Nov 13 05:43 keydir/

This repository that you just cloned contains all the files (right now, only 2) needed to create repositories for your projects, add new users, and defined access rights. Edit the settings as you wish, commit, and push. Once pushed, bazitis will immediately make your changes take effect on the server. So we're using Bzr to host the configuration file and keys that in turn define how our Bzr hosting behaves. That's just plain cool.

From this point on, you don't need to be on your server. All configuration takes place locally and you push the changes to your server when you're ready for them to take effect.

Creating new repositories

This is where the fun starts. Let's create a new repository to hold our project codenamed FreeMonkey.

Open up bazitis.conf and notice the default configuration:

[bazitis]                  

[group bazitis-admin]
writable = bazitis-admin
members = jdoe

Your "members" line will hold your key filename (without the .pub extension) that is in keydir/. In my example, it is "jdoe", but for you it'll probably be a combination of your username and hostname.

To create a new repo, we just authorize writing to it and push. To do so, add this to bazitis.conf:

[group myteam]
members = jdoe
writable = free_monkey

This defines a new group called "myteam", which is an arbitrary string. "jdoe" is a member of myteam and will have write access to the "free_monkey" repo.

Save this addition to bazitis.conf, commit and push it:

bzr commit -m "Allow jdoe write access to free_monkey"
bzr push bzr@YOUR_SERVER_HOSTNAME/bazitis-admin

Note: You only have to add the path to the bazitis-admin repo the first time you push. After that, it will be remembered and you can just type "bzr push"

Now the user "jdoe" has access to write to the repo named "free_monkey", but we still haven't created a repo yet. What we will do is create a new repo locally, and then push it:

mkdir free_monkey
cd free_monkey
bzr init

# do some work, bzr add and commit files

bzr push bzr@YOUR_SERVER_HOSTNAME/free_monkey

With the final push, you're off to the races. The repository "free_monkey" has been created on the server (in /home/bzr/repositories) and you're ready to start using it like any ol' bzr repo.

Adding users

The next natural thing to do is to grant some lucky few commit access to the FreeMonkey project. This is a simple two step process.

First, gather their public SSH keys, which I'll call "alice.pub" and "bob.pub", and drop them into keydir/ of your local bazitis-admin repository. Second, edit bazitis.conf and add them to the "members" list.

cd bazitis-admin
cp ~/alice.pub keydir/
cp ~/bob.pub keydir/
bzr add keydir/alice.pub keydir/bob.pub
Note that the key filename must have a ".pub" extension.

bazitis.conf changes:

[group myteam]
- members = jdoe
+ members = jdoe alice bob
  writable = free_monkey

Commit and push:

bzr commit -m "Granted Alice and Bob commit rights to FreeMonkey"
bzr push

That's it. Alice and Bob can now clone the free_monkey repository like so:

bzr branch bzr@YOUR_SERVER_HOSTNAME/free_monkey

Alice and Bob will also have commit rights.

Limitations

  • Currently, bazitis doesn't support everything that gitosis does, like public readonly access. This is planned for the future.
  • I haven't tested bazitis with shared bzr repositories. I have no idea if it will work. If you try this, let me know how it goes.
  • Bazitis works best with bzr 1.9. It works with earlier versions, but if you try to access a repository that you do no have permission for, a huge ugly exception is thrown that would probably lead a user to think something is wrong with bzr. This is handled a lot better in later versions of bzr.

And that's all. Let me know how it works out for you!

» Bazitis: Gitosis for Bzr (Baazar)

At work, I use git. For Exaile I use bzr. I like them both quite a bit. At work, we use Gitosis to manage our repositories and I have to say, it's pretty damn cool. Nothing quite like this exists for bzr, so I ported Gitosis to bzr and called it Bazitis. The launchpad project page can be found here. Here are the instructions on how to use Bazitis:

First off, I'd like to give credit to some people. Tommi Virtanen is the author of Gitosis. Bazitis is a copy of the Gitosis code, all except for the parts where I had to get a little hacky with bzrlib. His website is http://eagain.net. The other person I'd like to thank is Garry Dolley, who wrote a great blog post on how to use Gitosis, which can be found here: hosting git repositories the easy and secure way. Garry has given me permission to copy his instructions and modify them for Bazitis, as long as I give him kudos, which I have done in this paragraph. Thanks guys!

Install bazitis

bazitis is a tool for hosting bzr repositories (I'm repeating myself for those who skim :)

The first thing to do is grab a copy of bazitis and install it on your server:

cd ~/src
bzr branch lp:bazitis

Next, install it like so:

cd bazitis
python setup.py install

Don't use --prefix unless you like self-inflicted pain. It is possible to install bazitis in a non-standard location, but it's not nice. Read the Caveats section at the bottom and then come back here.

If you get this error:

-bash: python: command not found

or

Traceback (most recent call last):
  File "setup.py", line 2, in ?
    from setuptools import setup, find_packages
ImportError: No module named setuptools

You have to install Python setuptools. On Debian/Ubuntu systems, it's just:

sudo apt-get install python-setuptools

For other systems, someone tell me or leave a comment, so I can update this section and improve this tutorial.

The next thing to do is to create a user that will own the repositories you want to manage. This user is usually called bzr, but any name will work, and you can have more than one per system if you really want to. The user does not need a password, but does need a valid shell (otherwise, SSH will refuse to work).

sudo adduser \
    --system \
    --shell /bin/sh \
    --gecos 'bzr version control' \
    --group \
    --disabled-password \
    --home /home/bzr \
    bzr

You may change the home path to suit your taste. A successful user creation will look similar to:

Adding system user `bzr'...
Adding new group `bzr' (211).
Adding new user `bzr' (211) with group `bzr'.
Creating home directory `/home/bzr'.

You will need a public SSH key to continue. If you don't have one, you may generate one on your local computer:

ssh-keygen -t rsa

The public key will be in $HOME/.ssh/id_rsa.pub. Copy this file to your server (the one running bazitis).

Next we will run a command that will sprinkle some magic into the home directory of the bzr user and put your public SSH key into the list of authorized keys.

sudo -H -u bzr bazitis-init < /tmp/id_rsa.pub

id_rsa.pub above is your public SSH key that you copied to the server. I recommend you put it in /tmp so the bzr user won't have permission problems when trying to read it.

Here some cool magic happens. Run this on your local machine:

bzr branch bzr@YOUR_SERVER_HOSTNAME/bazitis-admin
cd bazitis-admin

You will now have a bazitis.conf file and keydir/ directory:

~/dev/bazitis-admin (master) $ ls -l
total 8
-rw-r--r--   1 garry  garry  104 Nov 13 05:43 bazitis.conf
drwxr-xr-x   3 garry  garry  102 Nov 13 05:43 keydir/

This repository that you just cloned contains all the files (right now, only 2) needed to create repositories for your projects, add new users, and defined access rights. Edit the settings as you wish, commit, and push. Once pushed, bazitis will immediately make your changes take effect on the server. So we're using Bzr to host the configuration file and keys that in turn define how our Bzr hosting behaves. That's just plain cool.

From this point on, you don't need to be on your server. All configuration takes place locally and you push the changes to your server when you're ready for them to take effect.

Creating new repositories

This is where the fun starts. Let's create a new repository to hold our project codenamed FreeMonkey.

Open up bazitis.conf and notice the default configuration:

[bazitis]                  

[group bazitis-admin]
writable = bazitis-admin
members = jdoe

Your "members" line will hold your key filename (without the .pub extension) that is in keydir/. In my example, it is "jdoe", but for you it'll probably be a combination of your username and hostname.

To create a new repo, we just authorize writing to it and push. To do so, add this to bazitis.conf:

[group myteam]
members = jdoe
writable = free_monkey

This defines a new group called "myteam", which is an arbitrary string. "jdoe" is a member of myteam and will have write access to the "free_monkey" repo.

Save this addition to bazitis.conf, commit and push it:

bzr commit -m "Allow jdoe write access to free_monkey"
bzr push bzr@YOUR_SERVER_HOSTNAME/bazitis-admin

Note: You only have to add the path to the bazitis-admin repo the first time you push. After that, it will be remembered and you can just type "bzr push"

Now the user "jdoe" has access to write to the repo named "free_monkey", but we still haven't created a repo yet. What we will do is create a new repo locally, and then push it:

mkdir free_monkey
cd free_monkey
bzr init

# do some work, bzr add and commit files

bzr push bzr@YOUR_SERVER_HOSTNAME/free_monkey

With the final push, you're off to the races. The repository "free_monkey" has been created on the server (in /home/bzr/repositories) and you're ready to start using it like any ol' bzr repo.

Adding users

The next natural thing to do is to grant some lucky few commit access to the FreeMonkey project. This is a simple two step process.

First, gather their public SSH keys, which I'll call "alice.pub" and "bob.pub", and drop them into keydir/ of your local bazitis-admin repository. Second, edit bazitis.conf and add them to the "members" list.

cd bazitis-admin
cp ~/alice.pub keydir/
cp ~/bob.pub keydir/
bzr add keydir/alice.pub keydir/bob.pub
Note that the key filename must have a ".pub" extension.

bazitis.conf changes:

[group myteam]
- members = jdoe
+ members = jdoe alice bob
  writable = free_monkey

Commit and push:

bzr commit -m "Granted Alice and Bob commit rights to FreeMonkey"
bzr push

That's it. Alice and Bob can now clone the free_monkey repository like so:

bzr branch bzr@YOUR_SERVER_HOSTNAME/free_monkey

Alice and Bob will also have commit rights.

Limitations

  • Currently, bazitis doesn't support everything that gitosis does, like public readonly access. This is planned for the future.
  • I haven't tested bazitis with shared bzr repositories. I have no idea if it will work. If you try this, let me know how it goes.
  • Bazitis works best with bzr 1.9. It works with earlier versions, but if you try to access a repository that you do no have permission for, a huge ugly exception is thrown that would probably lead a user to think something is wrong with bzr. This is handled a lot better in later versions of bzr.

And that's all. Let me know how it works out for you!

April 23, 2009

Scott Paul Robertson
spr
Spr: The Ramblings
» Album Sound Check - The GUI

A while ago you'll recall that I wrote a little Python script that would average out the sound check gain adjustment created by iTunes for a given set of songs.

I've gone a step farther and created a simple GUI tool for doing the same.

Album Sound Check (download link) provides a basic interface to editing this field based on the values in a given set of files.

Sound Check GUI

After running the program go ahead and open a directory containing songs from your iTunes library. They will be scanned in and the gain dB adjustment values stored. ASC will then determine an average from this.

You can choose to not have certain songs affect the resulting average by unchecking the "Use" column. You can choose to not have the computed average applied to a given file by unchecking the "Apply" column.

Once you're ready just click "Apply" and wait for the spinner to stop. It will then rescan the files showing the new value in place.

There is no undo. Sorry, not something I'm worried about. You can remove the songs from iTunes and re-add, that might work. No promises.

April 21, 2009

Kevin Kubasik
nonic
For Once I Oneder
» Google Summer of Code 2009: Django Testing Updates!

So my Google Summer of Code: 2009 project proposal was accepted! I will be working on a 2 phase project revolving around Django’s testing framework, and regression suite. Most notebly, I plan to:

  • Implement Windmill test coverage for Django’s Infamous contrib.admin
  • Provide several missing features/conveniences to the Django testing tools

While it may not be the most glamorous project, I’m excited for it! When paired with my epic mentors, (the ever-infamous Eric Holscher and notorious George Song) it looks to be a solid summer. You can expect me to post weekly status updates here, as well as anything else relevant to the project. As my ‘get to know Django and make sure I can conform with coding standards etc.’ ticket, I’m planning to add an assertion which checks for dead links after template rendering. Or, as its better known, Django Ticket #5418.

I want to also give a quick thanks to Jacob Kaplan-Moss, Eric Holscher, Jannis Leidel and all the other PyCon 2009 Sprinters who helped me create the proposal.

April 9, 2009

Matt Harrison
no nic
Matt Harrison's blog
» Python and emacs (4): Whitespace, tabs, tab-width, visualizing...

Whitespace! The bane of all aspiring python programmers! After their first day of python programming, it never seems to bother them. Until they get the dreaded file that uses tabs instead of more useful spaced indentations. (I've heard 6 is the new 2. At least that's what they're teaching at MSU).

Emacs (builtin python-mode) allows you to just open their tab delimited files and start working with them just fine. You will follow pep8, and be consistent. No harm done. Allow the infidels to keep their tabs.

Now weird spaced indentation (ala googly 2 space or MSU 6 space), is handled pretty easily as well. Just use M-x set-variable tab-width to the appropriate size. (M-x describe-variable tab-width will show the current value). (A better explanation of tabs/spaces in emacs is found here)

The real problems come when tabs/spaces are intermixed. Out of the box emacs handles that pretty well too. Select a region (C-x h (to select the whole buffer)) and M-x untabify will replace tabs with the tab-width number of spaces. That works pretty well too. (There's also the tabify command for you infidels).

Since some of the fancy gui editors/IDEs out there visually highlight the differing indentation, surely you should be able to replicate this on your emacsen. Alas, emacswiki to the rescue. After an initial hint to look at "blank-mode", it turns out that whitespace-mode is the blank-mode++, (blank-mode was so 2006). Plus documentation found in the wiki is quite nice.

If you have mixed indentation in python, whitespace-mode is handy. I'm finding it even more handy in my html templates that have dynamic css/js/html (where I've yet been able to get an editor to understand what it's supposed to be doing. Yeah, some of it could be isolated to it's own files. Some of it is dynamic and the templating languages further confuse emacs). So when your co-workers might be using Textmate (which might also be confused on such files), tabs might find their way in. whitespace-mode allows one to quickly view and clean up their until now hidden snafus.

The screenshot below illustrates whitespace-mode. In the top buffer is a previously mentioned html template. Red indicates extra space at the end of the line. >> indicates evil tabs. Dots indicate spaces, and $ is newline. You can see that one line has spaces and tabs intermixed! Arghh, my eyes are burning! The middle buffer shows some python code using tabs with whitespace-mode off. The bottom buffer shows the same code with whitespace-mode on.

I'm not going to leave whitespace-mode on all the time. On clean code it's distracting. But when I'm feeling like refactoring/cleanup/examining new code it comes in handy.

March 20, 2009

Matt Harrison
no nic
Matt Harrison's blog
» Clone Digger - another tool to add to your python belt

A few years back my boss asked me how I would implement code duplication detection. Real duplication would ignore variable renames, comments, and indenting (for non-python). A naive solution would just use string comparisons and not be too useful. I thought about it for a minute and said I'd make an AST and for the code and compare the trees. Not that it's a particularly novel idea, we were just discussing the value of the IP of some companies...

Well, there's been code floating around the intertubes for the past year or so that does just this for python code. The project is called Clone Digger and works on Python and Java. The output is an html file showing chunks of code that either differ by variables or operation changes (in red) or code that is the same (in blue).

I think Clone Digger is another useful tool to use for code reviews, when inheriting a bit of code, or after developing a chunk of code. This is going to be very useful for some refactoring we are doing at work. Now if it only worked on JavaScript....

March 10, 2009

Matt Harrison
no nic
Matt Harrison's blog
» Python and emacs (3): (Balancing) parentheses and others

(Again not necessarily python specific)

One nice feature of emacs is show-paren-mode. (Naming it show-paren-mode rather than paren-show-mode makes it somewhat less discoverable but I digress). This nice little feature allows one to make sure parens (or brackets or curly brackets) are in order. It does so by visually highlighting the matching pair when the cursor is over the starting one (or after the ending one). It's very useful when you have a long dictionary with lists as values. The emacs wiki page includes a function for showing matching ends when one is offscreen. Very handy indeed.

To enable show-paren-mode type M-x show-paren-mode or put something like this in your .emacs:

;; highlight balanced parens
(add-hook 'python-mode-hook (lambda () (show-paren-mode 1)))

Apparently one of the critically acclaimed of Textmate is autopairs (or something like that). People love it cause it saves them a keystroke. If you type an opening paren, it adds a closing paren and moves the cursor inside the parens. Nice! How to get that in emacs?

As always in the open source world, there are many ways. Here's what I went through:

I searched for electric pair and found this entry in the emacs wiki. It's a good start but it has some drawbacks. It only inserts the matching pair when the cursor is at the end of the line (admittedly that's probably the case 80% of the time). So it won't work on nested items (say a string inside a list).

To deal with that first issue I tried skeleton mode. This gets around the embedding issue.

Then I find this blog post illuminating me on the second issue. I didn't think of this at first but if you have electric completes you probably want electric deletes too. So I'm currently using a modified version of his code (added support for single quote). This appears to handle triple quoting that is common in python docstrings too.

Marcelo's blog also mentioned paredit which seems to be quite featureful for lisp source, but has issues with python (no single quotes, space inserted between started paren and previous character, complex source). So I only tried it for a minute or so.

Good luck with your balancing!

March 12, 2009

Kevin Kubasik
nonic
For Once I Oneder
» Finally! A Django IDE with Real Code Completion and Template Support

Now it seems like forever ago, but I have been on the hunt for a good Django IDE for a very long time. I have tried PyDev, Aptana, Komodo, TextMate, Vim, Emacs, Wing IDE and every variation in between, but was never satisfied with the featurset. I wanted complete python language support and completion, complete support for Django Templates, total HTML support, as well as complete Javascript (specifically jQuery) support. Most editors made the mistake of having support for some of those individually, but I can’t get javascript support inside of a Django Template etc.

The magical and awesome app that represents the first real attempt at a complete Django development environment? Netbeans!

I know it sounds crazy, but progress is being made, and while its a boatload of effort to get it built, and even then, not much of the promised featureset actually works. But those are just details, examination of the code available at:

http://code.google.com/p/netbeans-django/

shows some real work being done towards a Django project type. Moreover, a recent blog post from someone at Sun alludes to this support being available as soon as Netbeans 7.0.

Perhaps this is just another let down waiting to happen, but the existing Python code support is fantastic, and significant strides appear to already have been made towards the goal of total Django integration. If you want to try out the existing language support, just grab the Netbeans 7M2 build and install the Python plugin!

February 27, 2009

=Utah Open Source=
Utah Open Source
Utah Open Source Blog
» New Program: UTOS joins Fedora Project and Sugar Labs to promote XO Developer Program

As announced on many mailing lists in the local area, the Utah Open Source Foundation has teamed up with the Fedora Ambassadors and the XO/OLPC project to promote the XO Developer Program.

Here’s the email being sent around.  Feel free to share it with anyone you like to help get them involved in bettering the learning tools available using Free and Open Source Software.  I have added a few word changes and a couple additional links to help.

The Utah Open Source Foundation has been working with the Fedora Ambassadors and the XO/OLPC folks to promote a new project.  Due to some recent changes in their structure, they’re looking for more developers and packagers for this project.

If you are a python developer, interested in helping children learn on a cool bit of hardware that is very hard to break, have time to code between now and August and are willing to commit to working on the xo project for [at least] 1 year, the Fedora Project will provide you with a free XO laptop to keep.

This project is fourth grade math curriculum for the XO/OLPC.  The idea being that once the major bits of this curriculum are developed, creating other versions will be much simpler.

The requirements are that you give monthly updates on your progress to the Fedora Ambassadors.  It should also be obvious that you will be working with others to get requirements completed and development in for testing and released to packagers.

If you are interested, I can provide you a laptop within 1-2 weeks as well as help you get a developers key and get started right away.  For more information visit these links:

The point of this email is to interest you folks who would love to develop something useful in the world.  To change the way kids learn and grow and show the way open source software can provide this change.  If you are seriously interested in participating in this project and have a few hours a week to give to it, please contact me off list.

If you are interested, contact me, <clint@utos.org> and we’ll get you started right away.

Cheers,

Clint

February 22, 2009

Matt Harrison
no nic
Matt Harrison's blog
» [SCALE] Python scripting handout

Here's a zipped version of my handout pdf for my talk on Python Scripting. The poachplate tool can be found here.

Update - Apparently there are pdf export problems, here's a link to the .odt source (I'm using "Envy Code R" for my mono fonts).<

Update 2 - (Benefit of being at a conference where Michael Meeks of go-oo fame is). I went and asked him about openoffice->pdf exports and font embedding. It worked on his version of evince and acroread (am assuming of the SuSE variety) where he is missing my fonts. Works on xpdf and kpdf on my gentoo.... Not sure what is causing the blockiness, since I saw it on Ubuntu and Mac platforms.... Finished uploading poachplate

Update 3 - My pdf works on Google Docs... My brother was kind enough to give me cleaned up pdf

update 4 - Looks like my blog engine was messing with the pdf so it's in a zip file now.

February 18, 2009

Matt Harrison
no nic
Matt Harrison's blog
» A new use for python

Apparently, python is now the preferred language for gnome/kde virus/worm writing. Makes sense, it's preinstalled on most linux environments. (Take tongue out of cheek). WRT the actual virus, nothing really too surprising, other than the newbie linux netbook users who would probably be the most likely to get duped by something like this... Maybe there should be a "how (intelligently) to use a computer" class in elementary school, (so kids can come home and teach their parents).

disclaimer: The wife has an eee

February 10, 2009

Matt Harrison
no nic
Matt Harrison's blog
» Python "Scripting" at Utah Python, SCALE and PyCON

import this states that There should be one-- and preferably only one --obvious way to do it. I've written a bit of what I call 'scripts' over the last little while. If you have a continuum of 'stuff' written in python, then scripts would be the stuff more complicated than one liners and not quite as complicated as programs. It appears that there are lots of ways that people write/package/test/layout scripts. Some good, some bad. Perhaps a reason is that sys admins are scripting in python as if it were bash? Perhaps poor documentation? Perhaps laziness? Perhaps scripts that were originally meant to be run once (and then discarded) are turned into more permanent scripts?

I'm going to be sharing my thoughts with regards to scripting and python a bit in the next bit. I'll touch on directory layout, (intra) file layout, configuration, useful scripting abstractions, packaging, and testing. Lots of stuff to mention, a lot of it is just hints/suggestions. Various incarnations of this beginner friendly talked will be presented. This week I'm giving it to the local user group. Then it's off to sunny SoCal for the SCALE version of this talk in their sys admin track. After that I'll give a version at PyCON.

Update Interesting and relevant discussion on slashdot today (2/11/09).

February 9, 2009

Kevin Kubasik
nonic
For Once I Oneder
» Code Review in Rietveld with bzr/Bazaar

I like bzr. Those of us that do (like bzr) aren’t quite as popular as the git lovers and as a result, we don’t see tools as fantastic as Rietveld, Github and Git-CL being spread around on domains outside of launchpad.net. While this isn’t the end of the world, it certainly represented a hurdle when I decided that I was going to formalize my code review process for internal projects. 

While most applications have some form of bzr support, its generally pretty broken or outdated. Given that I was going to have to write code no matter what application I chose, I figured I would use my favorite: Rietveld. Rietveld already had a tool supporting Git and Hg, so expanding it to support bzr was a straightforward task. The initial patch is awaiting review at http://codereview.appspot.com/14053  so please share your thoughts/opinions. If there are others who start to use this, then I might consider packaging this functionality into a bzr plugin! 

If you just want to take advantage of bzr support, then download the file here: Upload.py

February 4, 2009

Dennis Muhlestein
nonic
All My Brain
» Converting financial CSV data to OFX or QIF import files

As a side project, I created a CSV to OFX converter that applies custom mappings to CSV data to export them to QIF or OFX files. This morning, I added the ability to override the built-in mappings with custom mappings that suite your needs. Basically, you can take financial data from any institution and [...]

January 16, 2009

Scott Paul Robertson
spr
Spr: The Ramblings
» Album Based Soundcheck

iTunes supports a feature called Sound Check. Similar to ReplyGain in other players, the goal is make songs playback at a similar volume. This is particularly useful with mixes, songs from various albums do not have jarring transitions. Since this computed on a song-by-song basis, different songs on a single album get different values. In some cases this creates a jarring experience while listening*.

For example: Muse's Absolution has an introduction track that never gets terribly loud, but leads in directly to a normal song. Sound Check did the following:

  • "Intro" adjusted +19.5 dB
  • "Apocalypse Please" adjusted -8.5 dB

The ending of the first track is meant to be the same volume as the beginning of the second, but because of Sound Check, this doesn't happen.

I have written album_soundcheck.py which computes the average volume of m4a or mp3 files and replaces the iTunes information with that. This is a permanent change, and cannot easily be reversed. So I provided a testing option (-p), run with -h to see the full option list.

album_soundcheck.py requires:

  • Mutagen - basic tagging library
  • tag_wrapper - My wrapper library that makes mutagen fun and easy

If you have Oggify installed and working you should have all the needed prerequisites.

Example:

album_soundcheck.py "~/Music/iTunes/iTunes Music/Muse/Absolution/*"

* Many new albums by "popular" artists may not be affected, see Loudness War

January 13, 2009

Matt Harrison
no nic
Matt Harrison's blog
» Python and emacs (1): Keyboard macros

I'll admit I'm mediocre at emacs. Which is kind of silly because other than a few years of eclipse use it's been my main editor for some 11 years. In an effort to help me start using features I don't normally use, I'm going to go over Jonathon's features of python IDE's in a series of blog posts, but with a focus on emacs. I'm going to base the post's on the features found there, but also might do some other features that I think are handy. If you've got comments, suggestions, by all means let me know. Also, one way to learn is by watching others. Well I can't watch you, but you can drop hints. I've sat in the presence of people who live in a screened session of emacs, and wish I would've taken note of what they did...

Some possible outcomes of this might be updating the content on emacswiki and python wiki both of which seem somewhat disorganized. Another outcome might be a "Teach me how to use emacs...." session in PyCon. (I wouldn't teach it, but would love to see demo's of others using features that I should be using).

Without further ado, here's the first feature on the list:

Keyboard macros

Yes! Emacs has keyboard macros. The documentation included in emacs manual (C-h r) and the emacswiki entry on keyboard macros seem simple enough.

This might seem lame for my first entry, since I'm not really expounding on anything new. But I'll admit, I never use macros. It seems like either a search/replace covers most needs, otherwise if it's something more complicated than that I'll write a script or do it by hand (if it's a one time thing). I'll further admit, that most of these are not even when editing python. So my questions to all emacs gurus out there: When do you find macros nice? When do you use them when python programming?

January 5, 2009

Jordan Gunderson
jordy
Jordy Blog
» Got Contract Work?

Gabe and I want to be sure that our start up company, Izeni, has a cash runway that’s long enough to ensure that we can have a proper lift off. To that end we’ve been doing some consulting and contract work (mostly low-hanging fruit) to slow our burn rate, and it’s worked fairly well because we’re in bootstrapping mode and our expenses are relativity low. So, although we’ve never really sought contract work, we do like it; and I thought I’d do a quick post officially soliciting it.

So without further ado, Izeni will be accepting all kinds of technical consulting and contract work. Our specialities are Python coding; website development (particularly using the Django framework); Linux systems administration (Apache, *SQL, Postfix, Mailman, IPtables, Samba, Bash, etc.); and VoIP-based telephony (Asterisk and Freeswitch).

We can also do general computer and network support, online marketing, and a myriad of other technical and business odds and ends.  :)

Izeni is based out of Utah, but we can also telecommute.

Please let me know if you have any contracting and consulting opportunities or know of any companies looking for web guys, programmers, or other technical contractors. Otherwise, feel free to repost this (pass the word along), or just keep us in mind.

December 25, 2008

Scott Paul Robertson
spr
Spr: The Ramblings
» Building Cocoa GUIs in Python with PyObjC, Part Six

Handling Images

Cocoa provides an easy interface for dealing with images, NSImage. It can be a bit tricky in Python, but once you get it right the first time, it is fairly easy. For our application we have the images stored inside the audio tags and need to populate an NSImage object from binary data stored as a Python byte-string.

There are a number of methods for initializing an NSImage object from various sources. A few of note:

initWithContentsofFile:
initWithData:
initWithPasteboard:

All of these are worth reading about in the developer documentation. We will be using initWithData:. This accepts a NSData object to make the NSImage. This is a multiple step process, so we'll create a method to make things easier:

def buildNSImage(bytes):
    data = NSData.dataWithBytes_length_(bytes, len(bytes))
    return NSImage.alloc().initWithData_(data)

bytes is a Python byte-string containing the image. NSImage will automatically handle the formatting, so we don't need to worry about it. Take note that you have to run initWithData: from an existing NSImage object, which is created by calling alloc(). All of the initWith methods require an NSImage object so the NSImage.alloc() method will be used a lot.

Finally we need to connect the NSImage object to the GUI. We start by adding an Image Well (NSImageView) to our GUI, and then connect it to our object.

Image Well in GUI

QuickTag has been modified to work via Key-value coding, so in the Bindings tab of the Inspector (⌘4) we connect the Value to the appropriate key path.

Inspector Bindings tab

Finally we setup methods to handle adding or removing the image. Basically we add another sheet for images, and a method to remove the tag. These can be found in the controller.py code starting with the addImage_ method.

Now that we have the image handling QuickTag is in the final stretch. The code is available in git as usual.

Update: To get the bytes out of a NSImage takes a couple of steps:

def getBytes(nsimage):
    return nsimage.representations[0].representationUsingType_properties_(NSPNGFileType,
        {}).bytes()

This takes a NSImage into a NSBitmapImageRep (subclass of NSImageRep) into a PNG held in a NSData.

<< Part5: Adding Python Modules to the Bundle

December 16, 2008

Matt Harrison
no nic
Matt Harrison's blog
» Why the Linux Desktop sucks...

I think I've figured out why the Linux desktop sucks! It has to do with hackability and efficiency. As a programmer, I'm finding the mouse and mouse less efficient.* A little over a month ago, my right hand seemed to implore to me "Stop! Stop!" every time I'd reach for that mouse. For work, I normally have a couple terminals open for database access or viewing logs, emacs open for editing, webbrowser for email, and an IM client. I've been using KDE since the end of the last century and have been pretty satisfied with it up to the 3.5 series. But my body indicated "Don't use that mouse!" So I started to try and comply.

I think most of my mouse use was for re-positioning windows that were overlapping. (Of course I was also using the mouse for web browsing, IM'ing, and my RSS client.) The solution to the re-positioning problem seemed to me to be start using a tiling window manager. In the age of compiz and fancy window decorations this seemed silly, but felt right intuitively. If I can get my windows in a state where I can see everything I need, that would certainly help.

So I started researching tiling WM's. The two most featureful at the time seem to be Xmonad and Awesome. So without reading the manual I installed one and ran it, and I was lost. I started looking at configuring/documentation and got somewhat frustrated. Xmonad seems to be the Ruby on Rails project for Haskell (perhaps an overstatement, poster boy might be a better term). The configuration is actually a Haskell project that you compile to build your own WM. Awesome in the 3.x series is using Lua for configuration. Since, I like Python I thought, hmmmm why not python.

Turns out there are a few python window managers listed in the comprehensive list of Window Managers. Then I found a python tiling window manager, qtile. It's a relatively nascent project, and I had my mental model of what a tiling window manager should do for me. (Be useable out of the box, by providing a tabbed/tiling metaphor similar to the eclipse workspace. Which I don't think anyone currently provides). So I messed around with qtile for a bit. I even wrote a layout based not on eclipse, but on emacs (since it seemed simpler for a starting point, and it was familiar to me). Then I came to a point where I wanted gimp support, (now I understand why people hate the gimp interface), which basically requires "floating" windows. I came full circle and decided to see how Awesome handles floating windows. I got a 3.1 rc of Awesome running a few days back, and am actually really liking it. (It's crashed a couple times...) I figured if I wanted to hack more on qtile, I really should use the current state of the art for tiling WM's first. I'm still learning the keystrokes, and need to install vimperator for firefox.

So, one reason desktop "sucks" on Linux, is that out of the pool of possible developers, they eventually listen to their body, and move to something like a tiling wm. They scratch their itches. The Youtube demos of tiling WM's are boring, nothing like their compiz counterparts. So while they don't appear to be cool from the glossy marketing apple/MS point of view, from a getting things down view they are quite efficient.

* - Yes I still need it for gimp and inkscape. (And to skip music in pandora (I'm not aware of any native client for linux))

BTW, the worst part of awesome, is actually the name! It makes searching very hard, I think they should rename it awesomewm (or something unique) ASAP.

December 8, 2008

Matt Harrison
no nic
Matt Harrison's blog
» rst2odp on PYPI

Development on rst2odp is continuing in the Docutils sandbox. Styling/incremental support have been added. For those who don't want to mess with checking out sandbox, there's a version on pypi. For those who aren't interested in rst, but are interested in Odp/Impress and Python, included in the tarball is odplib. It is a standalone python library for generating odp content. (rst2odp is a wrapper around it).

As always, feedback is welcome. Cheers!

December 2, 2008

Matt Harrison
no nic
Matt Harrison's blog
» [ANN] rst2odp - Convert rst to OpenOffice Impress

Goodbye S5. I might miss you. You were nice but you kind of died. And all the cool kids bought macs and moved on to keynote... But my slides weren't written in html, they were written in rst...

Enough with the silly talk. Here's a little side project I've been working on. Call it a preview release/alpha/developer release/whatever. It works right now (for some definition of working, ie, my old slides are rendered with it). Here's what it supports right now: S5 rst definitions (tiny/small/colors), images, source code highlighting (via pygments), outlines. It's lacking any mechanism for styling, the S5 incremental feature, testing other peoples slides, etc.

So I'm calling anyone who is interested in it (or people who have used rst2S5 and want to move on from S5). Try it out on your old slide shows and see if it works. Send me your feedback, let me know what you want, etc.

Download rst2odp here. (requires docutils/pygments/PIL).

November 25, 2008

Adam Olsen
synic
Vimtips Latest Articles
» Bazitis: Gitosis for Bzr (Baazar)

At work, I use git. For Exaile I use bzr. I like them both quite a bit. At work, we use Gitosis to manage our repositories and I have to say, it's pretty damn cool. Nothing quite like this exists for bzr, so I ported Gitosis to bzr and called it Bazitis. The launchpad project page can be found here. Here are the instructions on how to use Bazitis:

First off, I'd like to give credit to some people. Tommi Virtanen is the author of Gitosis. Bazitis is a copy of the Gitosis code, all except for the parts where I had to get a little hacky with bzrlib. His website is http://eagain.net. The other person I'd like to thank is Garry Dolley, who wrote a great blog post on how to use Gitosis, which can be found here: hosting git repositories the easy and secure way. Garry has given me permission to copy his instructions and modify them for Bazitis, as long as I give him kudos, which I have done in this paragraph. Thanks guys!

Install bazitis

bazitis is a tool for hosting bzr repositories (I'm repeating myself for those who skim :)

The first thing to do is grab a copy of bazitis and install it on your server:

cd ~/src
bzr branch lp:bazitis

Next, install it like so:

cd bazitis
python setup.py install

Don't use --prefix unless you like self-inflicted pain. It is possible to install bazitis in a non-standard location, but it's not nice. Read the Caveats section at the bottom and then come back here.

If you get this error:

-bash: python: command not found

or

Traceback (most recent call last):
  File "setup.py", line 2, in ?
    from setuptools import setup, find_packages
ImportError: No module named setuptools

You have to install Python setuptools. On Debian/Ubuntu systems, it's just:

sudo apt-get install python-setuptools

For other systems, someone tell me or leave a comment, so I can update this section and improve this tutorial.

The next thing to do is to create a user that will own the repositories you want to manage. This user is usually called bzr, but any name will work, and you can have more than one per system if you really want to. The user does not need a password, but does need a valid shell (otherwise, SSH will refuse to work).

sudo adduser \
    --system \
    --shell /bin/sh \
    --gecos 'bzr version control' \
    --group \
    --disabled-password \
    --home /home/bzr \
    bzr

You may change the home path to suit your taste. A successful user creation will look similar to:

Adding system user `bzr'...
Adding new group `bzr' (211).
Adding new user `bzr' (211) with group `bzr'.
Creating home directory `/home/bzr'.

You will need a public SSH key to continue. If you don't have one, you may generate one on your local computer:

ssh-keygen -t rsa

The public key will be in $HOME/.ssh/id_rsa.pub. Copy this file to your server (the one running bazitis).

Next we will run a command that will sprinkle some magic into the home directory of the bzr user and put your public SSH key into the list of authorized keys.

sudo -H -u bzr bazitis-init < /tmp/id_rsa.pub

id_rsa.pub above is your public SSH key that you copied to the server. I recommend you put it in /tmp so the bzr user won't have permission problems when trying to read it.

Here some cool magic happens. Run this on your local machine:

bzr branch bzr@YOUR_SERVER_HOSTNAME/bazitis-admin
cd bazitis-admin

You will now have a bazitis.conf file and keydir/ directory:

~/dev/bazitis-admin (master) $ ls -l
total 8
-rw-r--r--   1 garry  garry  104 Nov 13 05:43 bazitis.conf
drwxr-xr-x   3 garry  garry  102 Nov 13 05:43 keydir/

This repository that you just cloned contains all the files (right now, only 2) needed to create repositories for your projects, add new users, and defined access rights. Edit the settings as you wish, commit, and push. Once pushed, bazitis will immediately make your changes take effect on the server. So we're using Bzr to host the configuration file and keys that in turn define how our Bzr hosting behaves. That's just plain cool.

From this point on, you don't need to be on your server. All configuration takes place locally and you push the changes to your server when you're ready for them to take effect.

Creating new repositories

This is where the fun starts. Let's create a new repository to hold our project codenamed FreeMonkey.

Open up bazitis.conf and notice the default configuration:

[bazitis]                  

[group bazitis-admin]
writable = bazitis-admin
members = jdoe

Your "members" line will hold your key filename (without the .pub extension) that is in keydir/. In my example, it is "jdoe", but for you it'll probably be a combination of your username and hostname.

To create a new repo, we just authorize writing to it and push. To do so, add this to bazitis.conf:

[group myteam]
members = jdoe
writable = free_monkey

This defines a new group called "myteam", which is an arbitrary string. "jdoe" is a member of myteam and will have write access to the "free_monkey" repo.

Save this addition to bazitis.conf, commit and push it:

bzr commit -m "Allow jdoe write access to free_monkey"
bzr push bzr@YOUR_SERVER_HOSTNAME/bazitis-admin

Note: You only have to add the path to the bazitis-admin repo the first time you push. After that, it will be remembered and you can just type "bzr push"

Now the user "jdoe" has access to write to the repo named "free_monkey", but we still haven't created a repo yet. What we will do is create a new repo locally, and then push it:

mkdir free_monkey
cd free_monkey
bzr init

# do some work, bzr add and commit files

bzr push bzr@YOUR_SERVER_HOSTNAME/free_monkey

With the final push, you're off to the races. The repository "free_monkey" has been created on the server (in /home/bzr/repositories) and you're ready to start using it like any ol' bzr repo.

Adding users

The next natural thing to do is to grant some lucky few commit access to the FreeMonkey project. This is a simple two step process.

First, gather their public SSH keys, which I'll call "alice.pub" and "bob.pub", and drop them into keydir/ of your local bazitis-admin repository. Second, edit bazitis.conf and add them to the "members" list.

cd bazitis-admin
cp ~/alice.pub keydir/
cp ~/bob.pub keydir/
bzr add keydir/alice.pub keydir/bob.pub
Note that the key filename must have a ".pub" extension.

bazitis.conf changes:

[group myteam]
- members = jdoe
+ members = jdoe alice bob
  writable = free_monkey

Commit and push:

bzr commit -m "Granted Alice and Bob commit rights to FreeMonkey"
bzr push

That's it. Alice and Bob can now clone the free_monkey repository like so:

bzr branch bzr@YOUR_SERVER_HOSTNAME/free_monkey

Alice and Bob will also have commit rights.

Limitations

  • Currently, bazitis doesn't support everything that gitosis does, like public readonly access. This is planned for the future.
  • I haven't tested bazitis with shared bzr repositories. I have no idea if it will work. If you try this, let me know how it goes.
  • Bazitis works best with bzr 1.9. It works with earlier versions, but if you try to access a repository that you do no have permission for, a huge ugly exception is thrown that would probably lead a user to think something is wrong with bzr. This is handled a lot better in later versions of bzr.

And that's all. Let me know how it works out for you!

October 28, 2008

Matt Harrison
no nic
Matt Harrison's blog
» [pycon2008] Video of "Managing Complexity" up

I gave a talk at pycon 2008 dealing with testing, code coverage, complexity and how to know when you are "done" testing. Though the talk was given at a Python conference, and the examples are in python, the talk is actually a general discussion of developer testing methodology, so it applies to Java, ruby, .... [insert you're favorite programming language]. My slides have been up for a while. Now the video has been posted up to youtube. If you've ever wondered what coverage is actually good for, watch the video. Here's a hint:

.

I'm still pining for python coverage at a finer than line level granularity....

October 12, 2008

Adam Olsen
synic
Vimtips Latest Articles
» Posting articles to Twitter via Django

I noticed that every time Clint Savage makes a blog update, he posts the URL to Twitter twice (yeah, that's you herlo :P). The URLs for each Twitter post are different, so I figured it must be some sort of automated Wordpress script with a bug in it.

So, I decided to write something to do the same for my own blog. Clint's passes the URL through tinyurl to get an address that's not too long for Twitter, but in my blog's case, http://vimtips.org/article_id works just fine.

Here's the code I used to do it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from vimtips import settings

try:
    import twitter
except ImportError:
    twitter = None

def twitter_post(article_id, title):
    """
        Posts an article update to twitter
    """
    
    if not twitter or not hasattr(settings, 'TWITTER_USER') or \
        not hasattr(settings, 'TWITTER_PASS'):
        return

    try:
        api = twitter.Api(settings.TWITTER_USER, settings.TWITTER_PASS)
        api.PostUpdate(
            "Blog Update: %s (http://vimtips.org/%d)" % (title, article_id)
        )
    except Exception, e:
        if settings.DEBUG:
            raise(e)

class Article(models.Model):
    """
        The model representing each news article on the blog
    """
    
    # ... model fields here ...

    def save(self, *args):
        """
            Saves the article.  If this is a new article, it also posts to
            twitter
        """
        post = not self.id

        models.Model.save(self, *args)

        if post:
            twitter_post(self.id, self.