My client is looking to hire a new Python developer, initially for an 8 month contract. It's a home working position, we communicate mostly via Skype / email / gtalk etc. Although we do meet up in meatspace from time to time, so ideally a candidate would be in the London / Oxford area.
So there is some genuinely interesting technology there, and more such projects planned. We need someone who is a good problem solver with a general interest in web technologies. There's also the occasionally need work with data at the bits and bytes level, so a working knowledge of C that would be a plus.
Here's a Python gotcha that I spent some time tracking down. I'm writing it up in the spirit of saving developers a debugging headache in the future.
I had an integer with a single bit set, and I wanted to find the index of that bit. For example, 4 in binary is 00000100. The 1 is at the third position from the right, which should give an index of 2 – since the first position is 0.
You can do this in two ways; either check each bit in turn until you find a 1, or you can use math as a shortcut. I chose the math solution:
>>> import math >>> myint = 4 >>> int(math.log(myint, 2)) 2
Simple right? Finally staying awake in high school maths paid off. So simple that it was the last bit of code I suspected to be broken (spoiler: it was).
This is Python 2.7 which still has two types of integer; type int and arbitrary long integer type long. I was testing with ints because that's what you get when you type 4. However the numbers I was getting out of the Django db where longs. Look what happens with the above code when you use 4L rather than 4:
>>> myint = 4L
>>> int(math.log(myint, 2))
And that was the result of my headache. Longs and ints are generally interchangeable. But not in this case. math.log gives a different result with long and ints. Which we can see here.
>>> math.log(4, 2)
>>> math.log(4L, 2)
That tiniest of rounding errors for the long version would be insignificant for most applications, but not if you are converting to an integer and discarding the fractional part. The fix is simple. Round the return value of math.log to the nearest whole.
>>> int(round(math.log(4L, 2)))
If you are working with Python 3, this problem goes away. Another reason to migrate if you have the option!
I made currency site available for testing today. See my previous post for the back-story, but in essence currency site is a virtual currency platform.
I sometimes object to the word virtual in ‘virtual currency’. Most of the money I possess is not in any physical form; it's merely a number stored in a database somewhere – and transactions occur without any kind of physical objects changing hands. So the word ‘virtual’ seems entirely redundant, since there's is no qualitative difference between virtual and ‘real’ money I can see. The only difference is the level of trust in the system.
But I digress. Currency site is a platform for virtual currencies, in that it is up to the users to create and manage currencies. The site just provides the tools. What currencies are used for is irrelevant as far as the platform is concerned. It could be for a house of students to manage the housework, or for a community to exchange goods and services. Regardless of what a currency is used for, there has to be a certain amount of trust in the system. The platform has to be reliable, in that you shouldn't be able to create currency without a valid transaction. Currency site is centralised, which makes that requirement simpler–the system keeps track of how much is owned, in the same way you trust banks to keep track of the money in your accounts.
The second level of trust is in the creator of the currency. The creator of the currency has the extra responsibility of defining how much of that currency is available at any one time. This is done by minting new currency. For instance, if the provider creates a currency and mints 1,000,000 virtual bucks then only 1,000,000 will ever be available to other users. It could be owned by a single person, or by a million people owning one virtual buck. Alternatively, since all currencies are divisible by 100, it could be that 100,000,000 people own 0.01 virtual bucks (a virtual cent?). However it is distributed there will be no more than one million virtual bucks in existence unless more is minted. A record of the currency mints is public, as well as information about how much currency exists and how much is in general circulation, which allows regular users to keep an eye on how the currency is managed.
From a techy side, currency site wasn't all that challenging. Sure it was a few months of part time work, but it was mostly user interface code. I wanted to make something that worked like online banking, but not as painful (I've never used an online banking system that didn't make me want to tear hair out). That was helped by using Twitter's bootstrap CSS framework, which creates an elegant user interface with simple markup.
There was only one piece of code that wasn't a straightforward as it appeared (and it was kind of fundamental). A currency site transaction basically involves subtracting a value from the source account and adding it to the destination account. In psuedo code, it is simply this:
if source_account.balance < amount: raise TransferError("Not enough currency") source_account.balance -= amount destination_account.balance += amount
In essence, that's all that is done, but things get more complex in the context of a web application where multiple transactions may occur simultaneously. For example, if an account A contains 30 virtual bucks and the owner attempts to send 20 virtual bucks to account B and simultaneously sends 20 virtual bucks to account C, one of those transactions has to fail – otherwise we may end up with a negative balances which is not allowed. The if statement checks if the account has enough currency, but if both those transactions occur simultaneously then they will both subtract 20 from the source account (leaving -10). Granted, this could only occurs in a small window of time, but there is no way to recover if it does.
I couldn't figure out how to handle this situation elegantly with the Django ORM, and I don't like resorting to custom SQL. Fortunately, the recent release of Django 1.4 came to the rescue with the addition of select_for_update, which does row level locking. Basically it allowed me to lock the two accounts objects so that no other process is permitted to modify them until the currency has been transferred. Another consideration is that the entire thing has to be done in a (database) transaction, since half a (currency) transaction could result in currency being subtracted from the source account without being added to the destination (in effect, disappearing currency from the system). To keep the currency consistent, the psuedo-code becomes:
begin_transaction() lock(source_account, destination_account) if source_account.balance < amount: raise TransferError("Not enough currency") source_account.balance -= amount destination_account.balance += amount commit_transaction()
I don't think there is much else in the code that is blog-worthy, although there is still plenty of features I'm thinking of adding. I'm considering allowing users to trade currencies, which might be interesting. I would also like to build an API, so users could pay for web content with virtual currency. A few more evenings of hacking in there I think…
If you would like to help with the testing then head on over to http://currency.willmcgugan.com/ (username: currency, password: reliance). If you let me know, I'll send you 100 beta bucks for your time. Bear in mind its in an early testing phase, so don't use it for anything serious – I'll be wiping the database before it goes live. I'd also be interested in suggestions for a proper domain name!
A while back a friend told me about something called community currency, also know as Local Exchange Trading System. The basic idea of which is that people within a geographical area can exchange goods and services with bespoke unit of exchange rather that traditional cash. So, for instance, you could mow a few lawns in exchange for guitar lessons – even if it isn't the guitar teacher's lawn you are mowing. There's no physical currency as such, members of the community currency rely on volunteers to keep track of how much currency they own. I think this is a marvellous idea. It promotes healthy exchanges without the need to muddy things with something as vulgar as cash. But what struck me after a bit of research is how the whole system is in dire need of mechanisation! There's no centralised place to view your ‘account’ or way to do transactions online, and I figured there should be. So that has been my hobby project for the last few months, I've been building such a site which has recently come together to a point where I'd like to gauge how much interest is out there. I haven't even come up with a name yet, so I've been calling it by the rather uninspired moniker of ‘Currency Site’.
Apologies for the misleading title of this post. I am without shame.
Users of Currency Site can create a currency which they can use to keep track of any kind of debt. The currency creator (or provider) sets the policy on how new money is created and managed. Once created, money can be sent to other users (directly to a username or indirectly via an email address), and users can mange their funds by creating various accounts. Once funds have been sent to a user, the provider has no more control, as any user is free to store their funds or send them to others. For all intents and purposes, Currency Site is like online banking, although with a far nicer user interface than any online banking system I have ever used (which tend to be a usability minefield). Users are also able to see how much money has been minted and how much is currently in circulation (i.e. not stored by the provider), which helps to maintain trust in the system.
You may be thinking this sounds familiar if you have ever come across the Bitcoin project, but there are a few significant differences. The biggest difference is that Currency Site still requires trust in the individual or organisation that is managing the currency (i.e. the provider), and there is no enforced scarcity of new currency; providers can mint new money as they see fit. There is a little overlap, but the use cases for Currency Site are potentially broader (albeit limited in scale) compared to Bitcoin. Community currency projects are what I had in mind when working on this, but it is equally applicable for a variety of other uses. For example, lets say a family (we'll call them the the Smiths) have a few kids that don't like doing their chores, so the parents create a currency called ‘Smith Dollars’. When little Bobby Smith does his homework or cleans up his room, his parents send him 10 Smith Dollars. When Bobby has 100 Smith Dollars, he can cash them in for a new video game or spend 15 to stay up an extra hour. But if he wanted to, he could also send his sister 5 Smith Dollars in return for a loan of her laptop. Other uses could be employees keeping track of who goes for the doughnuts or a couple exchanging favours (use your imagination for that one).
Currency Site is built with Django and I've used the excellent Bootstrap library for the theme. The site is usable at the moment, but there are still a few things I want to do to it before I push it live anywhere. Just to prove it's not vaporware, here are a few screenshots:
I will be looking for a few brave souls to help me test this. I plan to do a private beta where the database will be completely wiped before it goes live for a while. This will give me the opportunity to really iron out the kinks, without having to worry about making a mess of the DB. If you are interested in helping out please get in touch, or +1 this if you are reading on Google+. I'd also be interested in suggestions for a good name for this project! It seems that any domain with any kind of reference to money or currency is taken (not surprising I suppose).
Net Communities are looking for a Python/Django developer to work on an in-house project. It's a contract that would require some on-site work, but they would also consider a full-time developer for the right individual.
If you are interested, get in touch with Andy Evans.
“ My friends over at http://www.netcommunities.com/ are looking for a #Django dev for an inhouse project. #job ”0
“ Why does #Django silently swallow exceptions in accessors when rendered in templates? It's infuriating. ”0
Locidesktop was my coffee shop coding project of last year. I was quite pleased with the results. Locidesktop.com has been happily serving link desktops to some loyal visitors for months now – with no maintenance required on my part (a good thing because I've been busy with other projects).
There's also a pretty powerful caching system that makes rendering a desktop blindingly fast. I may have gone overboard with that, given my traffic rates. But I guess it is best to have more capacity than you need.
If you want to look through the code or fork the project, it is available on Github:
The only thing missing from the open source version is a single-site theme I purchased from themeforest.net, used in a few pages such as the about & privacy urls. The desktops themselves are identical to the live site because I did those myself. You can tell because of the minimalist design reflecting my artistic abilities (minimal).
There's a README in the project that will help you get started, but other than that you may have to figure things out for yourself. It's a pretty standard Django project, although I do use Jinja templates rather than Django templates. If you have any questions, please ask them in the comments, so at least there is a central repository for issues.
For more information on Locidesktop, see my previous posts on the subject.
Update: I had to recreate the repos to remove a bunch of temp files and mercurial data. If you forked before 9am GMT, 10th Jan, you may want to get this new repos.
I built Loci Desktop a few months ago and promoted it on a few geek sites. It's been running ever since, with no maintenance from myself, happily serving up start pages to a small number of regular users. There was a buzz when I promoted it, people were largely impressed, some were indifferent, but few ended up using it regularly. So now I'm left with a quandary.
I could try and promote it. But to what end? It's not like I need a certain number of visitors to cover the hosting. I'm using the same VPS as I am for my blog, and I designed Locidesktop to be ultra-low bandwidth anyway – so it effectively costs me nothing to run.
One option would be to sell the entire site outright, as the domain and technology rights. But there is currently no way of monetizing it and I doubt anyone would be interested as a commercial venture.
I could try and license it as a b2b service. A few people have commented that it would be a useful intranet service. I'm not sure about this, but it sounds plausible.
Alternatively, I could give back to the Django community and release it as open source, which I imagine would be the popular thing to do. Money isn't my primary motivator (a close second perhaps), so I wouldn't be averse to doing this. Thing is though, it would require work on my part to document it and maintain it, and I have other open source projects I would prefer to concentrate on. But I can't deny that it would be cool to see Locidesktop sites popping up over the interwebs.
Finally, I could just leave it as is. I'm pleased with how it turned out, and I have a few loyal users. Maybe I should just be satisfied.
Any options I haven't considered? Leave a comment…