tag:blogger.com,1999:blog-33699132766191335192024-03-16T22:50:25.970-07:00~mrooneyUnknownnoreply@blogger.comBlogger47125tag:blogger.com,1999:blog-3369913276619133519.post-43449381239995200512013-01-14T08:45:00.003-08:002013-01-14T08:45:29.998-08:00Blog Migrated, Please Update Feeds (If You Like)Hey everyone! I just wanted to post a quick mention that I've now migrated my blog to <a href="http://mikerooney.rowk.com/">http://mikerooney.rowk.com/</a>, so if you are following this blog, please do update your feed so you continue to get new posts (and check out recent posts over there, as there have been a bunch). Thanks, carry on :)Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3369913276619133519.post-49293861724395576352010-12-21T16:37:00.000-08:002010-12-21T17:31:26.846-08:00Diving into EC2 and Auto ScalingI'm rather new to EC2 (and as a result its CloudWatch / Auto Scaling features), so I figured I'd post about my current thoughts and see if anyone can tell me if I'm on the right track! I'm writing everything up as I go, so hopefully it will make a solid blog post for others in the future for going from zero to EC2 + Auto Scaling.<br /><br />Based on my initial research, it looks like the stack will be comprised of:<br /><ul><li>64-bit Maverick AMIs on micro instances, from <a href="http://uec-images.ubuntu.com/releases/10.10/release/">http://uec-images.ubuntu.com/releases/10.10/release/</a></li><li>Puppet for bootstrapping new instances and maintaining existing ones (via the series at <a href="http://ubuntumathiaz.wordpress.com/2010/03/24/using-puppet-in-uecec2-puppet-support-in-ubuntu-images/">http://ubuntumathiaz.wordpress.com/2010/03/24/using-puppet-in-uecec2-puppet-support-in-ubuntu-images/</a>)</li><li>Amazon's CloudWatch + Auto Scaling for spinning up/down instances of puppet roles as necessary</li></ul><div>Any yays or nays on this stack? One particular curiosity I had is if Mathiaz's guides would be simpler in Maverick, since they were written for Lucid and it seems like each release brings improvements for both EC2/UEC and Puppet. I'll also have to figure out how to put some of the roles behind a load balancer, but that's for later.</div><div><br /></div><div>Thanks for any suggestions! Once I've got it all figured out I'll put up a somewhat comprehensive guide, unless one already exists that I've missed.</div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3369913276619133519.post-5827335700291864822010-04-26T21:28:00.000-07:002010-04-26T21:41:51.456-07:00Is Intel the answer to Broadcom wireless problems?While I love my Dell XPS 1330 as an Ubuntu laptop, I've been growing quite tired of my Broadcom wireless card that came in it (I swore it had Intel wifi when I bought it). It requires downloading drivers to work (this can lead to a bit of a bootstrapping problem), and seems to frequently drop connections or have issues connecting.<br /><br />I'm assuming this is due to Broadcom's poor drivers, particularly 64-bit (I remember kernel panics and lack of WPA2 in the not-too-distant past), and was assuming an Intel card would clear my problems right up.<br /><br />Has anyone had problems with Broadcom and fixed them by switching to Intel? If so, could you offer any suggestions as to if I might want the Intel 4965, 5100, or 5300 card?<br /><br />Thanks, dear Ubuntu Planet and other readers!Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-3369913276619133519.post-18254313279199465652010-02-22T21:26:00.000-08:002010-02-22T23:01:53.347-08:00Why I Switched from Ubuntu One back to DropboxAs many of you surely know, Dropbox and Ubuntu One are applications to keep files on your desktop in sync across multiple computers, and backed up in the cloud. After using Dropbox for a year or so on Ubuntu, the Ubuntu One project came out and I thought I'd move over to it. I assumed it would be easier to set up, being pre-installed, and could integrate better with the file manager and other applications, being made specifically for Ubuntu.<br /><br />After about 6 months of using Ubuntu One, I found it to be too much of a regression compared to Dropbox and switched back. I thought I'd detail why here for the usefulness of others and to hopefully provide some constructive criticism to the Ubuntu One team which overall is doing good work. So here's why I went back to Dropbox:<br /><br /><b>Better Nautilus integration</b><br />The nautilus (file manager) integration in Dropbox feels very mature and polished. Normally I'd say this is to be expected since Ubuntu One is much younger, but since the nautilus aspect of Dropbox is open-source, there didn't seem to be much of an excuse for the Ubuntu One team to not use it as a starting point or at least as inspiration. Whenever I added files to my Ubuntu One folder, no matter how large or how many, they instantly had the checkbox emblem which implies to me they are in sync, even though they couldn't possibly be uploaded that quickly. In Dropbox, the files show an animated progress emblem until they are actually uploaded, and show this again when they are being updated. I wasn't able to trust the status of files with Ubuntu One, and that wasn't a good feeling.<br /><br />Sharing files in Dropbox is also a lot easier via Nautilus, but that deserves it's own point.<br /><br /><b>Easier file sharing</b><br />In my typical use cases of file sharing, I want to go from having a file in mind to someone else seeing that file as quickly as possible, be it in an instant message, chatroom (IRC/Jabber), or email to a friend or two. Dropbox makes this a breeze; drag a file into the "Public" folder in your Dropbox directory, and right-click on it and select "Dropbox > Copy Public Link". Now you have a publicly accessible link to your file in your clipboard!<br /><br />I never quite figured out how to do this in Ubuntu One; it seems you have to share files with specific people who also are running Ubuntu One (which really compounds the non-cross-platform issue) via the web interface by typing in an email address. This is a cool idea, but seems way over-engineered as a starting point. This was even brought up at the last UDS in an Ubuntu One session but was brushed off; they sadly seemed more interested in engineering complex sharing UIs than getting feedback to ensure they were solving actual problems.<br /><br /><b>Sane notifications</b><br />I think <a href="https://bugs.launchpad.net/ubuntuone-client/+bug/462747">bug 462747</a> is what ultimately drove me to drop Ubuntu One. It notifies you not once but twice for every file you change; once to tell you it is syncing the file and another to tell you it is done. Regarding the first notification, I probably already know that I changed that file; regarding the second, if I'm really curious about the status of the synchronization, a quick glance at the applet should tell me what I need to know. This was mildly annoying as is, but it does this for hidden files like vim swap files too. Every time I would open or save a file in vim (and I save early and often), I got two notifications about syncing the hidden swap file!<br /><br />Dropbox was much more sane regarding notifications; whenever I would turn on or sit down at a computer, it would show <b>one</b> notification telling me how many files it synced from other machines or, if there was just one changed file, the name of it. Beautiful!<br /><br /><b>Better web UI</b><br />The web user interface for Dropbox felt a lot easier to use, and I often had problems where the Ubuntu One web view would show deleted files or not show files I knew were there that were added days ago. Sometimes I had to collapse and expand a folder a time or two to get it to show the right contents. This led to a similar problem that I mentioned with the nautilus integration; it wasn't a UI I could trust to be accurate as was therefore essentially useless. The Dropbox UI was always accurate, and had some nice extras which could prove to be lifesavers like getting past versions of files.<br /><br />I also experienced some other issues including <a href="https://bugs.launchpad.net/ubuntuone-client/+bug/498444">bug 498444</a> which caused Ubuntu One applet to start up with the exclamation icon, giving the impression of not syncing files. If I wanted to edit or view a file that might have changed remotely, I had to manually tell the applet to try syncing again after startup to make sure the file was latest version (or else I could silently end up with .u1conflict file, but that's another issue). Additionally, although the transparency is praiseworthy, <a href="http://twitter.com/UbuntuOne/status/9498991639">all</a> <a href="http://twitter.com/UbuntuOne/status/9331800792">these</a> <a href="http://twitter.com/UbuntuOne/status/9292086471">tweets</a> <a href="http://twitter.com/UbuntuOne/status/9020860066">about</a> <a href="http://twitter.com/UbuntuOne/status/8963442390">recent</a> <a href="http://twitter.com/UbuntuOne/status/7755587471">issues</a> or <a href="http://twitter.com/UbuntuOne/status/8870678995">downtime</a> do not inspire confidence.<br /><br /><b>That being said</b><br />Ubuntu One does have a few things going for it, however. It is installed by default which means it is the easiest cloud sync/backup solution to get started with for an Ubuntu user. And thanks to CouchDB and a package manager, Ubuntu can ship applications that make it trivial to sync their data with Ubuntu One out of the box. If I can tell all the applications I care about to sync with Ubuntu One (bookmarks, notes, podcasts, basic OS settings/appearance) from one configuration UI, that's going to be pretty compelling.<br /><br />While I currently can't in good conscience recommend Ubuntu One to a friend (and plenty of my friends don't even use Ubuntu), I do have high hopes for the project; it is young and if they can work out some of the above issues, many of them being personal show-stoppers, while providing application and OS integration, Ubuntu One (and perhaps Ubuntu itself) could become too compelling to not use for many people. For now however, Dropbox is the solution which stays out of my way, allows me to solve my problems, and just works.<br /><br />If you are using Ubuntu One or Dropbox, certainly chime in on what the critical features are for you and why you chose one over the other!Unknownnoreply@blogger.com18tag:blogger.com,1999:blog-3369913276619133519.post-42691983402188237752010-02-07T18:15:00.000-08:002010-02-07T18:15:00.410-08:00wxBanker 0.7: simple personal financeYour favorite personal finance application, <a href="https://launchpad.net/wxbanker">wxBanker</a>, has turned 0.7!<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjN1zBX5urcgLxzc_OJCw0LumJO3W4NzoVtM8WViIKhrOf24cuNtQGK9l3TP4VX94GDwGD0z48r03ZpMuzgltqf7Drd59uhwjnUht1B2WdzjkvUz-5VfvMGIXklba1O5F0MqWyQL1Yuj3a6/s1600-h/wxBanker-0.7a.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 247px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjN1zBX5urcgLxzc_OJCw0LumJO3W4NzoVtM8WViIKhrOf24cuNtQGK9l3TP4VX94GDwGD0z48r03ZpMuzgltqf7Drd59uhwjnUht1B2WdzjkvUz-5VfvMGIXklba1O5F0MqWyQL1Yuj3a6/s400/wxBanker-0.7a.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5435634666672162130" /></a><br /><br />This release comes about 2 months after the previous release, and focuses on usability and user experience issues that I obtained from watching people use wxBanker as well as from Launchpad bugs (thanks <a href="https://bugs.launchpad.net/wxbanker/+bug/496878">Arty</a>!). Let's take a look at some of the changes, starting with the account control:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD_ASQy7dSuZUGWuPhgcD3l2sQwjfpz7jGPCmewKLoosa8lgx9UzxFv8CybLElRMCNaWiq7-LfO_eqLA1FyHucjVFk6tCM95qisf99H08jmAAU-iXq3eK2zevCykae7GOUvxiiJR1fOOOp/s1600-h/wxbanker-6-7-accountctrl.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 129px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiD_ASQy7dSuZUGWuPhgcD3l2sQwjfpz7jGPCmewKLoosa8lgx9UzxFv8CybLElRMCNaWiq7-LfO_eqLA1FyHucjVFk6tCM95qisf99H08jmAAU-iXq3eK2zevCykae7GOUvxiiJR1fOOOp/s400/wxbanker-6-7-accountctrl.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5435614404389456130" /></a><br /><br />On the right we have the new account chooser in 0.7. The main change is using radio buttons for the accounts instead of links. This is a much better, already understood method for choosing accounts, and will also fit in with themes better. The last item is now "All accounts" and is selectable, making it easy to get a view of all your transactions and search in them.<br /><br />The "Hide zero-balance accounts" option has moved to the View menu, and now has a keyboard shortcut. I've also removed the total number of accounts from the header, as well as the colons after the account names, to reduce clutter. Finally, everything has been given a bit more padding and the buttons have been slightly rearranged.<br /><br />Additionally, the previous graphing library has been replaced by cairoplot (thanks <a href="https://blueprints.launchpad.net/wxbanker/+spec/replaceable-plot-renderers">Karel</a>!), which looks much more attractive. Let's check it out:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnYqzd_hv7nRUbcg_L5jG6m1eKh1ZefmnuOBqcaPVcAW1Zoh47-NxZD6nPQmIiKTdBFQ7utvkMhZVJjSjKFiP2sEm9tYlztD974KqdKfKkMqPYZC8NcJQGdoXe57g4LKIJ1-I89AK8umu8/s1600-h/wxBanker-0.7b.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 247px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnYqzd_hv7nRUbcg_L5jG6m1eKh1ZefmnuOBqcaPVcAW1Zoh47-NxZD6nPQmIiKTdBFQ7utvkMhZVJjSjKFiP2sEm9tYlztD974KqdKfKkMqPYZC8NcJQGdoXe57g4LKIJ1-I89AK8umu8/s400/wxBanker-0.7b.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5435627406528133794" /></a><br /><br />The Summary view allows you to see a graph of your balance over time, and you can view a graph of a specific account or all accounts by using the account chooser on the left (previously the graph had its own account chooser, that was silly!).<br /><br />And in case you missed the 0.6 announcement, that version brought recurring transactions, XDG directory support, and more intuitive behavior regarding deleting/editing transfer transactions.<br /><br />For downloads and the full list of features and bug-fixes, check out the <a href="https://launchpad.net/wxbanker/0.7/0.7">release page</a>. You can also add <a href="https://launchpad.net/~wxbanker-users/+archive/ppa">the PPA</a> for easy installation and upgrades.<br /><br />If you'd like to stay in the loop join the <a href="https://launchpad.net/~wxbanker-users">wxBanker Users team</a> (and announcement mailing list) on Launchpad, follow <a href="http://twitter.com/wxbanker">wxBanker on Twitter</a>, or hang out in #wxbanker on irc.freenode.net.Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-3369913276619133519.post-90589843836533960162010-02-02T00:27:00.000-08:002010-02-02T01:35:52.595-08:00Automating translation template generation and check-ins for LaunchpadI <a href="http://mrooney.blogspot.com/2009/07/launchpad-is-now-automatic-magical.html">previously wrote</a> about how excited I was for the automated translation import and export features of Launchpad. Launchpad will automatically notice when you commit a translation template and import it, making it available for translation online. Generous translators will then contribute translations, and Launchpad will commit them back to your project.<br /><br /><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer;width: 149px; height: 200px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7xWnN5L0rkntjlYnWY3xvIb9HvVos-bRkxrP37FXU07O4cVkXV7bJE1fd8eLMXHDOrmZvbP_rZPw9PpzmKEoMN6UsWAuVFco7hkUlgY94XlsY51O0KOw19GTOo5ZaqGp1l4dIi3ch6YtJ/s400/thumbsup.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5433576524119894226" /><br />Okay, so this is pretty good! However for this process to work well, the translation template needs to be generated manually by a developer whenever there are changes to strings. Otherwise, translators are working on potentially outdated strings; some are perhaps not in the application anymore, and there are likely some strings which aren't in the template yet.<br /><br />After forgetting to generate and commit my template until shortly before a release more than once (and thus having poor translation coverage on newly added strings), I decided to automate this part of the process as well. All it took was a relatively small script to generate the template, and then if there were any changes, commit and push to the branch configured for automatic import in Launchpad. The following script does just that, by searching for any files using gettext calls starting with _(" or _(', and passing them to xgettext.<br /><br /><pre class="brush: bash"><br />#!/bin/bash<br />set -e<br />ack-grep "_\([\"\']" -l | xargs xgettext --output=wxbanker/po/wxbanker.pot<br />ACTUALCHANGES="`bzr diff | grep \"^[\-\+]msg\" | wc -l`"<br />if [[ "$ACTUALCHANGES" != "0" ]]; then<br /> bzr ci -m "automated generation of translation template"<br /> bzr push :parent<br />fi<br /></pre><br /><br />Note that if you aren't using Python, you may need to tweak the regular expression supplied to ack-grep. Once the template is generated, the diff is piped through grep to grab any changes to actual messages and make sure there was at least one. Otherwise there would always be changes due to the timestamp in the template, causing useless commits.<br /><br />I then threw this script into a <a href="http://hudson-ci.org/">Hudson</a> job, the <a href="http://en.wikipedia.org/wiki/Continuous_integration">Continuous Integration server</a> I use for <a href="https://launchpad.net/wxbanker">wxBanker</a>. I configured this particular job to run nightly, pulling down the latest bzr branch beforehand, and emailing me on any failures.<br /><br />It seems to be working quite well and ensures translators are always translating the latest strings and leaves nothing for me to forget, smoothing out the release process.<br /><br />If this sounds interesting to you but you're not familiar with Launchpad as a translation system, check out <a href="http://blog.launchpad.net/general/trying-out-launchpad-translations">http://blog.launchpad.net/general/trying-out-launchpad-translations</a> and feel free to ask any questions here. If you do have experience with translations, how do you handle generating translation templates and then integrating the translations?Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3369913276619133519.post-41354041309310130982009-09-20T14:40:00.000-07:002009-09-21T00:29:01.688-07:00wxBanker 0.6 preview available, now with recurring transactions!I've just released wxBanker 0.5.9 in <a href="https://launchpad.net/~mrooney/+archive/wxbanker-testing">the wxbanker-testing PPA</a>, which is a preview release for 0.6. If you aren't familiar with wxBanker already, it is a cross-platform, lightweight personal finance application, and you can find more info at <a href="https://launchpad.net/wxbanker">https://launchpad.net/wxbanker</a>.<br /><br />While there are <a href="https://launchpad.net/wxbanker/+milestone/0.6">many improvements and fixes</a> in 0.6, the main feature is recurring transactions, allowing you to automate repetitive transactions. They are functional in 0.5.9 with one caveat and the purpose of this preview release: there's no way (besides sqlitebrowser :) to modify existing recurring transactions. As such I'd love to get feedback on your impressions of recurring transactions, ideas on a nice configuration UI for them, and of course general feedback. With this I can implement the configuration UI and release 0.6.<br /><br />Here's an example of a simple quarterly transaction:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTnnI39InF34zzI7897ZKZtLEe2H7ff-mciHOgh5jfBHZayoIU9uLAVUJg0viaDH5tzHGQcEzjTTVK5uou4tAM95HLXp0Ed5EqOtzRuXM3-dE1WXuNf2cJx_DvcLgW6lWMjH8_aeRflda_/s1600-h/wxbanker-recurring-simple.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 72px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTnnI39InF34zzI7897ZKZtLEe2H7ff-mciHOgh5jfBHZayoIU9uLAVUJg0viaDH5tzHGQcEzjTTVK5uou4tAM95HLXp0Ed5EqOtzRuXM3-dE1WXuNf2cJx_DvcLgW6lWMjH8_aeRflda_/s400/wxbanker-recurring-simple.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5383814619697210546" /></a><br /><br />and here is a more complex one, with specific days chosen, as well as the transaction being a transfer from another account:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9XNTtvh-2iDhqibm6KVfU3g5MHqQrwDuou5oELQC7Tob2SU4jo6dT1cISVYJfO6jvI_p6RT2GBqzySnaBXGwpH5bF1hfQotVjiLijbb8FuHfHj7_QRg6SF8ZZCCVE_T9hjbB7UyoC6UWv/s1600-h/wxbanker-recurring.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 108px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9XNTtvh-2iDhqibm6KVfU3g5MHqQrwDuou5oELQC7Tob2SU4jo6dT1cISVYJfO6jvI_p6RT2GBqzySnaBXGwpH5bF1hfQotVjiLijbb8FuHfHj7_QRg6SF8ZZCCVE_T9hjbB7UyoC6UWv/s400/wxbanker-recurring.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5383813623678615906" /></a><br /><br />When you start up wxBanker and there is a recurring transaction due, you will see something like:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghqragiHDQR-2GckS4JcuqfXP4xYFNFnAerjXQc_9pY14YSpUZlY_0cINI5ceJXus1qn3YgHnEWjYcQ8NBLvinTtZYjNfsud9DUotm5bP25IzucWexsO1v4_H1RwiS31sjJ4vNsOkyVcFb/s1600-h/Screenshot-wxBanker-1.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 39px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghqragiHDQR-2GckS4JcuqfXP4xYFNFnAerjXQc_9pY14YSpUZlY_0cINI5ceJXus1qn3YgHnEWjYcQ8NBLvinTtZYjNfsud9DUotm5bP25IzucWexsO1v4_H1RwiS31sjJ4vNsOkyVcFb/s400/Screenshot-wxBanker-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5383818839115229074" /></a><br /><br />I didn't reinvent recurrence rules but instead (luckily) found the dateutil module for python which includes rrule, an "implementation of the recurrence rules documented in the <a href="http://www.ietf.org/rfc/rfc2445.txt">iCalendar RFC</a>", so it should behave quite well.<br /><br />As far as the needed configuration UI goes, there are a couple ideas that I've had so far. Below is the current top-left portion of the UI, for reference:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr0ORyDLShcnf96rf373HLZw6aNK0kHtt08yM6aALOW0RC25wtxOV2uGPN0q2d7cORMrLmKCY6AvEF782gEZnjyyBTE-hXkXkPQ0jcKGd2nivzbDK98BZiyMCMpQQDtJjuOeCjM8ZDJuNE/s1600-h/wxbanker-topleft.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 91px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr0ORyDLShcnf96rf373HLZw6aNK0kHtt08yM6aALOW0RC25wtxOV2uGPN0q2d7cORMrLmKCY6AvEF782gEZnjyyBTE-hXkXkPQ0jcKGd2nivzbDK98BZiyMCMpQQDtJjuOeCjM8ZDJuNE/s400/wxbanker-topleft.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5383816930580028274" /></a><br /><br />One idea was to have a third "Recurring Transactions" tab after the "Transactions" and "Summary" tabs, which appears if and only if recurring transactions exist. This would provide a list of recurring transactions and allow editing them via the same UI used for creation, as well as changing the account or removing them altogether. A second idea is to add another button next to the Add/Rename/Remove account buttons in the upper-left, for account configuration (this will be necessary for future features anyway), and allow modifying recurring transactions for that account there.<br /><br />Another perhaps complementary way would be to provide a right-click action on existing transactions which were recurred, for editing. I'd also like to implement functionality similar to Google Calendar where editing a value on an existing transaction caused by a recurring transaction will ask you if you want to apply that change to just this transaction, all existing, or all future.<br /><br />If you have ideas, please feel free to leave comments here or drop by #wxbanker on irc.freenode.net any time this week after 10AM PDT, to have a more interactive chat about them. <br /><br />Please do let me know what you think from either just the screenshots here or actually playing around with the application!Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3369913276619133519.post-6356482954266173922009-07-30T22:51:00.000-07:002009-11-30T12:55:44.012-08:00Launchpad is now an automatic, magical translation factory!I've been using Launchpad to host my personal finance application <a href="https://launchpad.net/wxbanker">wxBanker</a> for a few years now. The thing I was hearing most often was that it wasn't localized; people wanted currencies to look the way they should in their country, and the application to be in their language. Let me explain how Launchpad helped me provide translations for my application, and how much of an utterly slothful breeze it has recently become.<br /><br /><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 148px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWwkmLPP7-OTLVagqagixPqH3nJvlk0JBkTCl0ufq_JHdRXCDsBy6nhtvS9-InCydj2Qjbaq89_jOvBcdZnyjNus-CAEZFkGiFHiPhSZa7-T6FuELpkiXepT2KjSq9h5DuYUbnclTPXr6n/s320/slothful.png" border="0" alt="Image courtesy of shirt.woot.com" id="BLOGGER_PHOTO_ID_5364517561534742354" /><br />Normally to handle translations, an application has to wrap strings with <a href="http://en.wikipedia.org/wiki/Gettext">gettext</a>, create a template, find translators and give the template to them, collect translation files back, and integrate them into the project. This is painful and is why many applications aren't localized, and shut out most of the world as a result. One of the amazing features of Launchpad however, happens to be Rosetta, which brings translators TO your translations via a simple web interface, and then makes those translations available to the developer. With Rosetta, translators don't need to understand gettext or translation file formats; they just need to know two languages!<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgalV-BvwdxWFezhmTwJIBDRm-Fnx08BJKhK_UpmkDVdDav1tby6vWJT0hN-YL4eC5MkH7JJIv2ll1VLgfI-fU36qxC_zzaqV6pOBl5U_ROsMJX1zkoye8Mtx8MdvJF68UUlAThb2_j_-Gt/s1600-h/ss_rosetta.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 201px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgalV-BvwdxWFezhmTwJIBDRm-Fnx08BJKhK_UpmkDVdDav1tby6vWJT0hN-YL4eC5MkH7JJIv2ll1VLgfI-fU36qxC_zzaqV6pOBl5U_ROsMJX1zkoye8Mtx8MdvJF68UUlAThb2_j_-Gt/s400/ss_rosetta.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5364503289795780082" /></a><br /><br />So that's what a translator sees. Notice how Launchpad even shows how other applications translated the same string. So once you generate a template and upload it, you can assign a translation group to your project such as "Ubuntu Translators" so that your strings will be translated by volunteers on the Ubuntu project; if your project isn't relevant to the Ubuntu project, you can use the more generic Launchpad Translators group. Now all you have to do is wait for some translations, then download them and check it in to your code. Not too bad, right?<br /><br />It isn't, but Launchpad has recently made it so much better. They started by adding an option to <a href="https://help.launchpad.net/Translations/ImportingFromBazaarBranches">automatically import translation templates</a> from your project. This means as you are developing, all you have to do is regenerate the template and commit, and new strings will show up for translators in Rosetta and be translated automatically (from the developer's perspective). Then today, <a href="http://blog.launchpad.net/general/exporting-translations-to-a-bazaar-branch">they announced the other side of this</a>, which is automatically committing those translations back into your code on a daily basis. This means that all I have to do is commit templates as I change strings, and Launchpad handles everything else. This is a profound tool for developers.<br /><br />What's the next step? Well, from a developer's perspective the translation template is a tool to give to the translators or in this case Launchpad. In the future Launchpad could eliminate this by generating the template itself from the code (this is what developers are doing themselves, after all), so that truly all you have to do after you set up the initial i18n/l10n framework is commit code as normal, and Launchpad magically commits back translations.<br /><br />All this work Launchpad is doing gives developers more time to develop while still having localized applications at a very minimal cost. This is continuous translation integration, and boy is it cool!Unknownnoreply@blogger.com10tag:blogger.com,1999:blog-3369913276619133519.post-63111040757847555502009-07-06T22:48:00.001-07:002009-07-06T23:12:08.776-07:00Simple timing of Python codeOften when I am writing in Python, I find that I want to see how long a particular function call or set of statements are taking to execute. Let's say I have the following code that gets executed frequently:<br /><pre><br />for i in range(10000000):<br /> x = 934.12 ** 32.61 * i / 453.12 ** 0.23<br /></pre><br />and I want to know how long it takes to execute to see if it is slowing down my app and should be optimized. Previously I would surround it as such:<br /><pre><br />import time; x = time.time()<br />for i in range(10000000):<br /> x = 934.12 ** 32.61 * i / 453.12 ** 0.23<br />print time.time() - x<br /></pre><br />This will print out the duration in seconds of that code segment, but is more work and typing than I want, and more cleaning up later. I realized that the new "with" statement in Python could probably help me out. Let's create a little timer class that cooperates with it:<br /><pre><br />class Timer():<br /> def __enter__(self): self.start = time.time()<br /> def __exit__(self, *args): print time.time() - self.start<br /></pre><br />Now all we have to do is:<br /><pre><br />with Timer():<br /> for i in range(1000000):<br /> x = 934.12 ** 32.61 * i / 453.12 ** 0.23<br /></pre><br />You can also try:<br /><pre><br />with Timer():<br /> time.sleep(1.5)<br /></pre><br /><br />For these, 0.28738 and 1.50169 are what I get, respectively. While something like this couldn't really replace application-wide profiling via <a href="http://docs.python.org/library/profile.html">a module like cProfile</a>, it can be an extremely useful and quick way to see if your prototype is scalable or not. I usually end up having a debug.py or helpers.py file in my larger projects with little tools like this, and I'll probably end up adding this one as well.<br /><br />Let me know if you are doing something similar, or if I've reinvented something that already exists. I'd also love to hear from people profiling their python code and what techniques they are using, as I am just starting to learn about it.Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-3369913276619133519.post-680749532903942752009-05-31T22:45:00.000-07:002009-06-01T06:56:53.128-07:00Karmic Desktop UDS run-down!I just got back from a wonderful UDS in beautiful Barcelona and thought I would provide a summary of what we can expect in the Karmic Koala 9.10 desktop. Keep in mind that I don't speak for Canonical and what follows is just my understanding of what is on the table for Karmic.<br /><br />Overall it is gearing up to be a pretty radical and exciting release; there are some changes to the default application set as well as some major version upgrades of existing core components. We are trying to be fairly aggressive in terms of new stuff so that if Canonical wants Karmic+1 to be an LTS (Long Term Support) release, we can have fairly stabilized new technologies by then (thanks to 6 months of stabilization in the Karmic cycle) instead of having to wait until after the LTS (Karmic+2) to introduce them. Since many of these changes would be too radical to first appear in an LTS, if we don't upgrade now we may not be able to for a year, and have to maintain old versions for 3-5 years in the LTS.<br /><br />On the messaging front, Ekiga will be dropped from the CD to save 10 megs, and Empathy will likely replace Pidgin due to a responsive upstream, voice/video support, and better GNOME integration. It also now has the ability to import accounts from Pidgin, so this should help out with migration. I checked it out a bit at UDS and was impressed with how useful it is with absolutely zero configuration. It will pull your name from the system and enable avahi (auto-discovery of people nearby, like bonjour) with no set up, which made it quite easy to get in contact with people at the conference. You can also supply your email and Jabber ID to the avahi interface to allow other people to discover that info as well.<br /><br />It also sounds likely that Banshee will replace Rhythmbox as the default media player, and it is the official default of UNR (Ubuntu Netbook Remix) Karmic. This will bring a snazzier interface, better device support including iPods and Androids, and quite importantly an active and responsive upstream. I will admit to not being a huge fan of this transition for Karmic as it seemed too early for me (the lack of a folder watch is quite a regression for me, and it has been promised for the last 3 releases or so, so I'm not holding my breath), but after checking out 1.5 for a bit I will admit that it is growing on me. The user interface does seem nicer, and the lightweight video library which keeps track of what you haven't watched is nice. However, it does seem to use 3-10x more memory than RB which is very troubling (60-300MB compared to RBs fairly consistent 25MB), especially on the netbook scene. I've also had issues with it skipping occasionally, which is very unfortunate. Hopefully the UNR switch will put pressure on better memory management for Banshee.<br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2Ku4fUtjaZRl4cVF__jwzXsEQBYBvs1A_VFgxi0SFQe00sc4AeSR4xFw8acCed9G3pOQBaPpZ-4CEFsxgareM3aJEPHYLrlNPVTuBMVoGRm48FzNNTEtP1C_GU-q1TyPsZuccKs9yi856/s1600-h/banshee-slide-device-overview.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 234px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2Ku4fUtjaZRl4cVF__jwzXsEQBYBvs1A_VFgxi0SFQe00sc4AeSR4xFw8acCed9G3pOQBaPpZ-4CEFsxgareM3aJEPHYLrlNPVTuBMVoGRm48FzNNTEtP1C_GU-q1TyPsZuccKs9yi856/s320/banshee-slide-device-overview.png" alt="" id="BLOGGER_PHOTO_ID_5342239755516722914" border="0" /></a>Banshee syncing with an Android G1<br /></div><br />Empathy and Banshee will probably replace their predecessors around alpha 2 of Karmic, and will be either left as default or reverted based on reported regressions and bugs. Keep in mind that if you end up not preferring these applications, the other ones still exist and you can continue to use them.<br /><br />There are also going to be a bunch of underlying speed improvements, with the boot speed goal being 10-12 seconds. When Ubuntu talks about boot times, we are referring to the time from when grub starts (when Linux first gets control of the machine) to when the user is at a fully loaded desktop with no I/O. The main test machines being used by Canonical here are Dell Mini 9s, with auto-login enabled to get a consistent log-in time. This is pretty impressive as the boot goal was 25 seconds in Jaunty, which was met, and was aggressive itself as Intrepid booted in about 65 seconds on the Dell Mini 9.<br /><br />grub2 is likely to be default for new installations (upgrades will have grub1 chainloaded to grub2), with ext4 as the default filesystem. The boot process will also be streamlined, with the grub timeout set to 0 and the boot menu hidden. There will instead be two new ways to boot into a different system now. First, there will be a key that can be pressed while booting to bring up an OS chooser, which will halt the current boot and restart into the chosen one. Another goal is to have the restart menu item in GNOME aware of installed OSes and allow the choice there, so you could select for example "Restart into OSX". All in all this means no racing to select the OS for dual-booters, and a faster boot process as well. /tmp is also hopefully going to be made a tmpfs, which means it will reside in RAM and overflow to a swapfile (which in recent Linuxes have on par performance with swap partitions). This means power savings, less disk I/O (especially great for SSDs), and of course blazingly fast performance which should help out a lot especially when, say, loading files from inside an archive The Gnome Display Manager (GDM, which handles the login screen) will also likely be upgraded to GDM2.<br /><br />Finally let me fire off a few more changes. Power management is being improved all around, with one change already landed being that audio cards will be automatically powered down after 10 seconds of no sound. Encrypted Home directories will hopefully be easier to set up now with an option right in the graphical installer, and I'm working on a UI for managing this and encrypted Private directories in Karmic, more on that later. Firefox 3.5 should be the default version of Firefox. For notifications which want to display actions if the user is interested, there is work on morphing windows:<br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik1qaqLdx8TXwCx19q3D7NQLDpk9hc04oAHsZepQqDxn3GxcWS0yWMFqW02W7eOmeUmXyirbVLdkxldYh-HfEFXeU5EBZra8QLJp0crwToORy0oOwXSDJKfpvbYCLV6DKBh_JIUYPDPuAD/s1600-h/morphing-window.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 121px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik1qaqLdx8TXwCx19q3D7NQLDpk9hc04oAHsZepQqDxn3GxcWS0yWMFqW02W7eOmeUmXyirbVLdkxldYh-HfEFXeU5EBZra8QLJp0crwToORy0oOwXSDJKfpvbYCLV6DKBh_JIUYPDPuAD/s320/morphing-window.png" alt="" id="BLOGGER_PHOTO_ID_5342239305600672866" border="0" /></a>Source: <a href="https://wiki.ubuntu.com/NotificationDesignGuidelines">https://wiki.ubuntu.com/NotificationDesignGuidelines</a></div><br />Ubuntu is also working on being social from the start (see desktop-karmic-social-from-the-start on gobby.ubuntu.com), perhaps installing Gwibber by default and asking the user if they want to integrate social sites (twitter, facebook) into the desktop when they visit them in Firefox, via an extension. There has also been work in looking for <a href="https://blueprints.launchpad.net/ubuntu/+spec/desktop-karmic-gnomescan">a better scanning application to replace xsane</a> (perhaps GnomeScan), some look into using Gnome Control Center, and a common printing dialog.<br /><br />Okay phew, that's what I've got to report! Let me know what you think of these decisions and changes, and if there is anything you were hoping for that didn't make it, or really anything else you've got to say!Unknownnoreply@blogger.com28tag:blogger.com,1999:blog-3369913276619133519.post-13470324161083793182009-05-14T00:36:00.000-07:002009-05-14T00:53:19.113-07:00A teaser: Desktop integration with encrypted directories for KarmicRecently I've been working on <a href="https://blueprints.launchpad.net/ubuntu/+spec/ecryptfs-desktop-ui">desktop integration with ecryptfs</a>. <a href="http://blog.dustinkirkland.com/">Dustin Kirkland</a> has done some awesome work enabling encrypted Private directories, as well as entirely encrypted Home directories, and I want to bring a UI to that goodness for the Karmic desktop.<br /><br />UbuntuOne displays a banner at the top of its shares, and this inspired me to borrow the code for use with encrypted Private directories. After a bunch of hacking and debugging, I finally got something to show up:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisXK8I6SB2tAAszFdXf1XY-4y-XTIJwbi7Q8Cz11yAiMUvRaBIckp1omLyZP5knznmefOt2v8e1J9Nf-lioC34O02iphVTsjlljWpp8ig-hR-4hUOWth27PzaaOVoRuT96XmLQEbm93Dvy/s1600-h/nautilus-encrypted.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 221px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisXK8I6SB2tAAszFdXf1XY-4y-XTIJwbi7Q8Cz11yAiMUvRaBIckp1omLyZP5knznmefOt2v8e1J9Nf-lioC34O02iphVTsjlljWpp8ig-hR-4hUOWth27PzaaOVoRuT96XmLQEbm93Dvy/s320/nautilus-encrypted.png" alt="" id="BLOGGER_PHOTO_ID_5335581341179838610" border="0" /></a><br />Pretty exciting! There is much work to be done behind the scenes but this is an encouraging start. After I get this working I plan on making a UI for installing ecryptfs-utils (the necessary package), setting up an encrypted Private directory, and managing/configuring one (or an encrypted Home). This UI would perhaps be available from System -> Administration -> Encrypted Directories, and would allow a user to have a directory of encrypted files available in a few clicks, which is mounted/unmounted transparently at login/logout.<br /><br />What do you think? Are you currently using an encrypted Home or Private directory? Would you be more likely to if there was a UI to set it up? Please share your thoughts and comments :) I'll be at UDS and can schedule a session on this if there is interest, as well.Unknownnoreply@blogger.com21tag:blogger.com,1999:blog-3369913276619133519.post-63202615513245515592009-05-06T22:23:00.001-07:002009-05-07T10:45:52.203-07:00Counting the number of Ubuntu usersThere have been a few <a href="http://blogs.computerworld.com/how_many_desktop_linux_users">articles</a> recently trying to estimate the number of Linux users, which is apparently a challenging problem. However I have to wonder why it can't be figured out at least at the distro level by simply storing hashes of IP addresses that hit Canonical's update site, and looking at the number of unique ones each week/month.<br /><br />There are going to be people using mirrors, but this is a small percent to lose to at least get something in the right magnitude, and the most popular mirrors could probably do a similar thing and contribute their numbers anyway. The only other main drawback would be multiple Ubuntu machines under the same IP, which again seems like it would only result in a slight inaccuracy. You'd also lose a small percent to users infrequently using their computers such that they aren't updated on a monthly basis, but yearly results would pull back in any of these people using their computers frequently enough to warrant counting.<br /><br />Alternatively, as others have suggested as well, if Google would just release their numbers for browsers hitting google.com, we'd probably have a solid idea as well.<br /><br />Are there already accurate numbers for Ubuntu and if not, am I missing something with my proposal?<br /><br />UPDATE: Jef pointed out that Fedora is already doing this at http://fedoraproject.org/wiki/Statistics#Yum_Data, which is pretty awesome! That shows about 14 million unique repository connections, so making a VERY rough, not remotely scientific estimate, we could use distrowatch to estimate that Ubuntu has 1.68 times the number of users as Fedora, and get something around the order of 24 million users that have connected.Unknownnoreply@blogger.com21tag:blogger.com,1999:blog-3369913276619133519.post-60064234836969182232009-04-20T17:20:00.000-07:002009-04-20T17:42:59.557-07:00Extending Java’s Semaphore to Allow Dynamic Resizing<a href="http://eng.genius.com/blog/2009/04/20/javas-semaphore-resizing/">Marshall wrote an excellent post</a> explaining how to dynamically change the number of permits when using semaphores in Java, which I thought I'd share for anyone interested. This can be particularly useful if you have a long-running daemon which you don't wish to restart for changes such as this. If you are using semaphores in Java, or if you don't even use Java but just want to learn more about semaphores, I'd recommend <a href="http://eng.genius.com/blog/2009/04/20/javas-semaphore-resizing/">giving it a read</a>.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3369913276619133519.post-88239414110006830642009-04-13T11:35:00.000-07:002009-04-13T16:56:06.204-07:00Email Deliverability & RFC 2142: Everything you wanted to know and never dared to askToday <a href="http://eng.genius.com/blog/2009/04/13/rfc2142-deliverability/">Franck Martin wrote an interesting post</a> regarding <a href="http://tools.ietf.org/html/rfc2142">RFC 2142</a> ("Mailbox names for common services, roles and functions") and how it relates to email deliverability. If you are running your own email server or own a domain, you may interested in reading it as it sums up what email addresses are expected to be manned at any domain and for what purposes.<br /><br />For example, did you know that "if an Internet service provider’s domain name is COMPANY.COM, then the ABUSE@COMPANY.COM address must be valid and supported"? And are you manning your postmaster and hostmaster addresses?Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3369913276619133519.post-26561434503531618772009-04-08T12:40:00.001-07:002009-04-08T12:53:23.388-07:00Genius.com is Eagerly Anticipating PHP 5.3Over at the Genius Engineering blog we just put up<a href="http://eng.genius.com/blog/2009/04/08/eagerly-anticipating-php-53/"> a post regarding our anticipation of PHP 5.3</a> and what we are looking forward to in it. We'd love to get some feedback and thoughts on it, and hear what other people are interested in regarding PHP 5.3 that we may have missed. If you've been following PHP 5.3, or haven't and want to catch up, <a href="http://eng.genius.com/blog/2009/04/08/eagerly-anticipating-php-53/">check it out</a>!Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3369913276619133519.post-86933589741283669832009-04-06T23:32:00.001-07:002009-04-06T23:53:46.891-07:00wxBanker 0.5 RC available for testing and translating!Recently I've been hard at work on the next version of wxBanker, a lightweight personal finance application, and would like to get out the 0.5 release candidate for testing and <a href="https://translations.launchpad.net/wxbanker">translations</a>. To check it out, add my <a href="https://launchpad.net/%7Emrooney/+archive/wxbanker-testing">wxbanker-testing PPA</a>. It also runs on Windows and OSX (albeit less tested), so feel free to grab the <a href="https://launchpad.net/wxbanker/0.5/0.5">source tarball</a> (it's python, so no compilation necessary) and then check out the included README. The only hard dependency is wxpython, although installing numpy and the simplejson library for python allow for graphing and csv importing respectively.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUv0lsxhOd90paB54bHP6YhXiIG-Q9XI4BAftK8v2Diryr2UivWrYMHNd054dVsVxQvUaxJMHbZ3d_OgoTIsAVvFP0-L2Kg8y1qmRfk-XnMwZ434nrhTz5VuzkV1-ex8PyTbkDCotpo2fn/s1600-h/Screenshot-2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 108px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUv0lsxhOd90paB54bHP6YhXiIG-Q9XI4BAftK8v2Diryr2UivWrYMHNd054dVsVxQvUaxJMHbZ3d_OgoTIsAVvFP0-L2Kg8y1qmRfk-XnMwZ434nrhTz5VuzkV1-ex8PyTbkDCotpo2fn/s320/Screenshot-2.png" alt="" id="BLOGGER_PHOTO_ID_5321838548248449858" border="0" /></a><br />wxBanker 0.5 has been a long time in the making, as it represents a large refactor of the underlying code to make everything much faster, more stable, and easier to extend and implement new functionality. This is especially noticeable in the start up time.<br /><br />There is also a new transaction grid which allows for sorting, a CSV import option in Tools (so you can import transactions from your banks initially)<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigmkl-x8MPS59-nmujPn99j3ngqtN8MpVdTRe1cdBypH-6FJ8d3fUPuJvaLQTKT9GedjVsAz6CArpv91By8ZP8C9Inp88loMELqpFdhL38gEk0o4lDw9zD_jAtYdmL7FaQ2uIStW47301Z/s1600-h/csvimport.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 315px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigmkl-x8MPS59-nmujPn99j3ngqtN8MpVdTRe1cdBypH-6FJ8d3fUPuJvaLQTKT9GedjVsAz6CArpv91By8ZP8C9Inp88loMELqpFdhL38gEk0o4lDw9zD_jAtYdmL7FaQ2uIStW47301Z/s320/csvimport.png" alt="" id="BLOGGER_PHOTO_ID_5321834616567751714" border="0" /></a><br />...and enhanced right-click actions for transactions which now work on multiple selected transactions:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgee0H0DTXVj7H_MdjEHXe5qdl9_pR5eRYnbwlh-rVaiitybQlyevh3XJTPnSx2SuYB7bUM4c37CpQlhcjn6IZ7LRrb93MbK8gju0TaGmmm-EVbcOxOo_gzYZyuVUTnBZ_LE2D5pPG7VcMG/s1600-h/rightclick.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 130px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgee0H0DTXVj7H_MdjEHXe5qdl9_pR5eRYnbwlh-rVaiitybQlyevh3XJTPnSx2SuYB7bUM4c37CpQlhcjn6IZ7LRrb93MbK8gju0TaGmmm-EVbcOxOo_gzYZyuVUTnBZ_LE2D5pPG7VcMG/s320/rightclick.png" alt="" id="BLOGGER_PHOTO_ID_5321835704043570194" border="0" /></a><br />See the included changelog for a full list of new things. Launchpad is also fairly well integrated into wxBanker, so to file a bug or do almost anything else, just use the help menu. The Spanish and French translations are complete but I could really use help everywhere else: <a href="https://translations.launchpad.net/wxbanker">https://translations.launchpad.net/wxbanker</a> !<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC8YMCoW7xKP3cf9ojE2e0KHkKGCzQT6hHH20zrEgEaqKpgvZk7yMdMxQKF8AzN_Mt1qw1P7abK_4If6sS4_dz1x9P4PNjPsh4cnqvY7aI9AGzc-jCPoCS6SfJd8Py7JcjW6Fam10zhT_X/s1600-h/helpmenu.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 218px; height: 161px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC8YMCoW7xKP3cf9ojE2e0KHkKGCzQT6hHH20zrEgEaqKpgvZk7yMdMxQKF8AzN_Mt1qw1P7abK_4If6sS4_dz1x9P4PNjPsh4cnqvY7aI9AGzc-jCPoCS6SfJd8Py7JcjW6Fam10zhT_X/s320/helpmenu.png" alt="" id="BLOGGER_PHOTO_ID_5321836391963596770" border="0" /></a><br />Check out <a href="https://wiki.ubuntu.com/wxBanker">https://wiki.ubuntu.com/wxBanker</a> for more screenshots, or the wxBanker homepage at<a href="https://launchpad.net/wxbanker"> https://launchpad.net/wxbanker</a> for more information including the users team/mailing list, and the translations team. If you are interested in the less exciting stable version, 0.4.1.0 can be found in the Ubuntu repos as of Jaunty, available in about 18 languages.<br /><br />Enjoy, and let me know of any issues or comments you have, and thanks in advance for translations :)Unknownnoreply@blogger.com12tag:blogger.com,1999:blog-3369913276619133519.post-37160929369415528712009-02-25T21:05:00.000-08:002009-02-25T21:21:05.187-08:00Using the "finally" block in Python to write robust applicationsThis is the first post in my series of three on using XMLRPC to run tests remotely in python (such as javascript and selenium tests in web browsers) and get the results. If that doesn't concern you, this post is probably still relevant; I'd just like to cover the groundwork of making code that is stable and repeatable even in the face of [un]expected problems. Luckily for us, python has a wonderful "finally" block which can be used to properly clean up or "finish" regardless of Bad Things. Let's look at an example of a common problem this can solve:<br /><br /><span style="font-family:courier new;"></span><blockquote><span style="font-family:courier new;">getLock()</span><br /><span style="font-family:courier new;">doStuff()</span><br /><span style="font-family:courier new;">releaseLock()</span></blockquote><br /><br />We need exclusive access to a resource, so we get a lock. We do some stuff, and then release the lock. The problem is that if doStuff raises an exception, the lock never gets released, and your application can be in a broken state. You want to release the lock no matter what. So what you should do is:<br /><br /><span style="font-family:courier new;"></span><blockquote><span style="font-family:courier new;">getLock()</span><br /><span style="font-family:courier new;">try:</span><br /><span style="font-family:courier new;"> </span><span style="font-family:courier new;"></span><span style="font-family:courier new;"> doStuff()</span><br /><span style="font-family:courier new;">finally:</span><br /><span style="font-family:courier new;"> releaseLock()</span></blockquote><br /><br />Now save a SIGKILL, the lock is going to be released. This is pretty basic, but it is impressive how robust the finally block is. You can "return" in the try block or even "sys.exit()" and the code in the finally block will still be executed.<br /><br />I recently used this with XMLRPC to safely tell the remote machine to clean up if the local script ran into problems or even got a SIGTERM from a keyboard interrupt. Here's a more elaborate example:<br /><br /><blockquote style="font-family: courier new;">proxy = xmlrpclib.ServerProxy(remoteIP)<br />try:<br /> result = proxy.RunTests()<br /> if result is None:<br /> sys.exit(1)<br /> else:<br /> return result<br />except:<br /> sys.exit(2)<br />finally:<br /> proxy.CloseFirefox()</blockquote><br /><br />The remote machine ("proxy") is running some tests in firefox. While it does this it sets a lock so no one else can run the same tests. If something goes wrong, this lock needs to be reset and firefox needs to be closed so they can run again later. If it gets a result, return it. If it doesn't or something goes wrong, we still clean up but now we can exit with an error code. One of the neatest things about this for me was Ctrl+C'ing the script on my computer and watching the remote machine cleanly quit firefox and release the lock for another process to use.<br /><br />This is great whenever you need to put something in a temporary state, or change the state after an operation no matter what happens. Think of locks, temporary files, memory usage, or open connections where it is important to close them. Conversely however, make sure you DON'T use an approach like when it isn't appropriate.<br /><blockquote><br /><span style="font-family: courier new;">for client in clientsToPing[:]:</span><br /><span style="font-family: courier new;"> try:</span><br /><span style="font-family: courier new;"> ping(client)</span><br /><span style="font-family: courier new;"> finally:</span><br /><span style="font-family: courier new;"> clientsToPing.remove(client</span>)</blockquote><br /><br />This is potentially incorrect behavior, because if you failed to ping your client you may want to keep it on the list to try again next time. However, you also may only want to attempt this once and then the above approach would be correct!<br /><br />In my next post I am going to turn more specifically to remote browser testing and explain how exactly to set up both ends of the connection. After that I'll finish by making a post on using twisted + SSL to retrieve posted results over HTTPS.Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-3369913276619133519.post-54590284442484648452009-02-23T10:53:00.000-08:002009-02-23T11:09:11.199-08:00Ensuring that you test what your users useRecently I've come across two pitfalls when testing one of my python applications. In two different cases the tests will run fine in my checkout, but fail miserably for anyone else (because the application is broken). What was happening?<br /><br />1) I had a new file which is required to run, but I forget to 'vcs add' it. Because the file existed in my sandbox, everything was well. But no one else was getting this file, so they couldn't even run the application. This one is somewhat easy to detect because a 'vcs st' should show that file as unknown status. In that way ensuring a clean status before running the tests can help avoid this. However this won't work well in an automated fashion because there are often unversioned files, and you typically want to run the tests before committing anyway.<br /><br />2) A time or two I thought I had completely removed/renamed a dependency but forgot to clean up an import somewhere along the line. Even though the original .py file was gone, a .pyc file by the old name still existed, which allowed the lingering import to work. Again however, for anyone else getting a fresh checkout or release, this file would not be avaible and the app would be unusable.<br /><br />How can you avoid having problems like this? Well, from a myopic viewpoint you could have your test suite delete any .pyc files before running. Then to address the first issue, you could also test that a 'vcs st' has no unknown files, and explicitly ignore any unversioned files you expect. But still, other things could creep up. And while having another machine as your "buildbot" would avoid the first issue, you are still prone to an attack from the second. To really make sure you are testing with the same stuff that you release, you need to be testing releases. In other words, you need to be putting your version through your shipping process, whatever that is, and then testing the final product.<br /><br />So now that I've realized this is what I should be doing, I'm not quite sure what the simplest and easiest way to do it in an automated fashion is. For python, perhaps this could be achieved by getting a fresh export/checkout of the code in a temporary directory, adding that directory to sys.path, and importing and running the tests. I am sure this is a common problem; is there a common solution?Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-3369913276619133519.post-29916766964971033232009-02-21T20:51:00.000-08:002009-02-21T21:28:56.676-08:00Delicious, cheap, and easy whole wheat wraps!Some of my <a href="http://egometry.com/bloodpact/">bloodpact blogging friends</a> have written recipes, and I thought I would add one of my favorite and simplest recipes to the mix. Wraps are a great food delivering device, be it for eggs or veggies, meat or rice and beans. It also happens to be easy to make your healthy wraps without any special tools, for roughly 10 cents a piece! Best of all, you can use <span style="font-weight: bold;">as few as two ingredients</span> if you so desire.<br /><br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRB9HdEkLOxuwvYyo0jPipSw2lGv_TlmkmrE1zuu2nvn6d5fGILfhprNoK1lS8F2opoQzQ6-3LofKmuHk6j-r57zMmcvMXkvI_JWl8VEkqbZJ13dV4o0VoTTOG-tNiRFy1C4YkHPRa41Hs/s1600-h/wrappers.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhRB9HdEkLOxuwvYyo0jPipSw2lGv_TlmkmrE1zuu2nvn6d5fGILfhprNoK1lS8F2opoQzQ6-3LofKmuHk6j-r57zMmcvMXkvI_JWl8VEkqbZJ13dV4o0VoTTOG-tNiRFy1C4YkHPRa41Hs/s320/wrappers.jpg" alt="" id="BLOGGER_PHOTO_ID_5305489192322068434" border="0" /></a><a href="http://www.theproduct.de/">the product</a> will make you happy.<br /></div><br />Here's what you'll need.<br /><ul><li>1C whole wheat flour (or white)</li><li>1/4C cold water</li><li>1/4 teaspoon salt (recommended)</li><li>1 tablespoon olive oil (optional)<br /></li><li>1/4 teaspoon baking powder (optional)</li><li>seasonings such as oregano, onion powder, or herbs (optional)</li></ul>Mix all the ingredients together in a bowl, adding extra water 1 tablespoon at a time until it forms a cohesive ball. Knead it for a minute or two and then divide into 2-4 smaller balls, depending on if you want large, medium, or small wraps. If you are patient, put them back in the bowl and cover with a towel for about 10 minutes.<br /><br />Now roll them out. For this I recommend rolling between two non-stick surfaces, such as <a href="http://www.amazon.com/Norpro-Slice-Piece-Flexible-Cutting/dp/B000SSVA9E/ref=pd_bbs_sr_1?ie=UTF8&s=home-garden&qid=1235279004&sr=8-1">flexible cutting mats</a> (a dollar store or grocery store should have 3 packs for $3-5), silicone baking sheets (also can be had for a few bucks), or something similar. So put a dough ball on a non-stick surface, then optionally put another on top. Now roll it out with a rolling pin if you have one, or a bottle of wine/oil/beer if you don't. It is easiest if you flatten it out by hand as much as you can first! It may take a couple tries to get them as flat (and as such wide) as you like, but you will definitely improve. Or you could just get a tortilla press online, though I have yet to give in.<br /><br />Now heat a pan on the stove to medium-high heat. Once it seems up to heat, throw a wrap on the pan (no greasing necessary). After 15-30 seconds you should be able to jiggle the pan and have the wrap freely slide around, and this is useful for ensuring it doesn't burn. Give it about 1-2 minutes on that side, until you start to see a bubble or two, then flip it over for another 1-2 minutes. Now sit it on a towel to cool, and repeat for the rest of your future wraps! As they are delicious warm, I like use one right after I make them.<br /><br />I love making these wraps because it is much cheaper than buying them, can be as healthy as I want, and makes eating them much more enjoyable knowing that I hand-crafted each one. Common uses are eggs with veggies in the morning or your typical taco fare. You can also make mini flatbread pizzas, or sandwich some cheese and veggies in between two for an extra tasty treat! Let me know what you think!Unknownnoreply@blogger.com3tag:blogger.com,1999:blog-3369913276619133519.post-78098717911916348962009-02-20T21:56:00.000-08:002009-02-20T21:58:42.877-08:00Finding new albums by your favorite bandsThe other week I felt a little disconnected from recent music. I was sure that some of my favorite artists had released new albums that I wasn't aware of, but I wasn't sure how to be notified of it. I use <a href="http://last.fm/user/midtown">last.fm</a> when listening to music most of the time, and have been for about 5 years, so I already have a long and dynamic list of my favorite artists, many of which I haven't been keeping up to date with. There are also many places that offer feeds of recent albums, including a private torrent site, Waffles. As a curious programmer I decided to bridge the gap here and write a little proof of concept script that would grab my top last.fm artists and query Waffles to see what was new.<br /><br />About an hour and 100 lines of python later, I had a working proof-of-concept. Right now it only supports Last.fm as a favorites source, and Waffles as a release source, but expanding it by following the same interface should be fairly straightforward. It is up for anyone to branch at <a href="https://launchpad.net/nutunes">https://launchpad.net/nutunes</a>. For any programmer it should be pretty easy to make a favorite source which reads from a text file and use other services like allmusic.com, amazon, or perhaps even iTunes to get a list of recent releases for a given artist. Feel free to branch and create a merge proposal for integrating with other services. As the code is less than 100 lines, I hope it more or less documents itself. To use it just run nutunes.py and it will prompt for your last.fm username, and Waffles credentials.<br /><br />What other ways are people currently staying on top of music of all the bands you are interested in? Heck, maybe Last.fm already has this option, but I sure didn't notice it, and learning and experimenting is fun!Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-3369913276619133519.post-34084686173668600982009-02-20T10:26:00.001-08:002009-02-20T10:29:12.285-08:00Eye tracking and UI framework / window manager integration<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU0eZgUm2YgL6qyUCVn07V2a5jWPJ2yYTZ7a4WbtcLk0ky6P6QPpavhKybdd4hlGgaSaNRheB9iCF2s-XQBLpY5GXOa6YBqdo2JZAFZDQCmDS745NTS4NmBIHjg0BB4g_idgPCikv5ALOz/s1600-h/Screenshot-1.png"><img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 224px; height: 164px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiU0eZgUm2YgL6qyUCVn07V2a5jWPJ2yYTZ7a4WbtcLk0ky6P6QPpavhKybdd4hlGgaSaNRheB9iCF2s-XQBLpY5GXOa6YBqdo2JZAFZDQCmDS745NTS4NmBIHjg0BB4g_idgPCikv5ALOz/s320/Screenshot-1.png" alt="" id="BLOGGER_PHOTO_ID_5304947893004594610" border="0" /></a>Eye tracking is the technique of watching the user's eyes with a camera and figuring out where on the screen he or she is looking. While some computer users with disabilities use this technology as their primary input device, it hasn't become very popular. However I think that with webcams being integrated into the majority of new laptops, and multi-core processors with some cycles to spare for image processing becoming ubiquitous, eye tracking deserves to become more popular.<br /><br />I don't believe the technology is accurate enough (yet) to replace your mouse, but it could still improve usability in a few ways. Imagine having the equivalent of onMouseIn and onMouseOut events on widgets when writing a user interface, but for where the user is looking instead. Applications could leverage onLookIn and onLookOut events at the widget level and open a whole new realm of functionality and usability. Videos and games could pause themselves when you look away, or bring up certain on-screen displays when you look at certain corners of the screen. If an application sees you are studying a certain element for a period of time, it may ask if you need help.<br /><br />It would also be interesting to see eye tracking leveraged on the window manager level. Most people use focus follows click to focus windows, and some enjoy focus follows mouse, but imagine focus follows (eye) focus! Using multiple monitors would become much easier if your keyboard input was automatically directed to the application, or even specific field, which you were looking at. Eye gestures, like mouse gestures, could be potentially useful as well, such as glancing off-screen to move to the virtual desktop in that direction.<br /><br />Apple and Linux both seem to be in a good position to implement something like this. Apple has control of both the hardware and the software including the OS, and has been integrating cameras in laptops for a while. As a result they are in a great position to pioneer this field and really have something unique to bring to the table in terms of a completely new user experience. However in the open-source world, Linux is also in a decent spot to do this as the UI frameworks and window managers are all patchable and most webcams are supported out of the box.<br /><br />Eye tracking has the potential to enable us to use computers in ways that were previously impossible. What are your thoughts on eye tracking? Does it have a future in the computing world and where can it take us? And how long will it be before we will take this technology for granted? :)Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-3369913276619133519.post-68361197223353403162009-02-19T00:24:00.000-08:002009-02-19T00:28:56.402-08:00Webhooks and feeds as complementary technologies -OR- How webhooks can enable a collective intelligenceYesterday I <a href="http://mrooney.blogspot.com/2009/02/are-feeds-pre-cursor-to-webhooks.html">wrote</a> about my observation that feeds seemed sort of like the precursor to webhooks, but that each had distinct advantages. <a href="http://mrooney.blogspot.com/2009/02/are-feeds-pre-cursor-to-webhooks.html?showComment=1235001360000#c1245389494252546097">Adam left a comment</a> confirming my thoughts on their pros and cons, but then pointed out how they can be used together to get the best of both worlds. I really liked the implications and wanted to expand upon how webhooks could enable the next generation of feed readers, and further, really lead us towards a more collective intelligence.<br /><br />The way things work now is that you have an aggregator, such as Google Reader, which polls all of your feeds every once and a while (although in this specific case surely doing some caching behind the scenes for users with the same feeds). This is suboptimal for two reasons. First, you don't get instant updates. Statistically, you will on average receive an update pollFrequency/2 minutes after it is posted. If you want to be able to respond to something in a quicker fashion, this may not cut it. Second is that the polling is causing unnecessary load on the server.<br /><br />Now let's try it with just webhooks. You inform all the event producers you are interested in about your aggregator callback, and you get instant updates for all of them, with no wasted polling. However when your aggregator is off, you aren't receiving updates! This means you can miss updates, and you have no way to catch up.<br /><br />Combining these two however, we can solve the problems of each technology with the other and pick up none of their downfalls. Use webhooks to tell your event producers about your aggregator as was done previously in the webhooks model. But now, the producer is also supplying a feed. This means that when your aggregator is up it will receive instant updates and doesn't need to poll. However when you start it up after having been down, it can use the feed to catch back up; no missed events!<br /><br />I think this new model has the potential to improve aggregators, as well as make them more usable for applications where speed is important. It could also have a much greater impact though. Twitter is a good example of this I think, wherein you could tweet about things you need fast feedback on such as a meal choice at a restaurant, the best way to do something you are working on, or perhaps even more urgent things such as needing a ride. All of these things could and surely are done in the traditional model, but with the push revolution they become more useful as quicker responses are more likely. People will become more likely to produce things requiring (potentially much) faster feedback, and this feeds into itself as people become more likely to respond, knowing that their responses are more relevant because less time has passed. I think it is an evolution that, while initially potentially sounding subtle and unimportant, can help lead is into a more collective intelligence that we couldn't imagine living without once we have it.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-3369913276619133519.post-89877170736762888732009-02-17T22:15:00.000-08:002009-02-18T14:26:26.605-08:00Are feeds the pre-cursor to webhooks?Recently I've been reading <a href="http://timothyfitz.wordpress.com/2009/02/09/what-webhooks-are-and-why-you-should-care/">Timothy</a> and <a href="http://blog.webhooks.org/">Jeff</a> talk about webhooks. Webhooks are essentially an amazingly simple way to be notified about arbitrary events on the web. In this model, any event producer allows you to supply a URL, which it will post to on each future action with the relevant details, whatever they may be. Then the other day when I was using Google Reader, something struck me: it felt a lot like webhooks, but turned on its head.<br /><br />Anything that offers a feed such as RSS or Atom can be plugged into Google Reader; things like blogs and their comments, twitter searches, commits, downloads, bugs, and build results. As I started plugging more and more diverse things into Reader, I realized that it was basically like the "pull" equivalent of webhook's "push" nature. Instead of telling all these event producers where to contact me, I'm telling Reader where to learn about all the recent events.<br /><br />I may be thinking too shallowly, but in the webhooks world Reader would be the service offering the interface. Then, instead of all these different things offering feeds, you could just plug Reader's hook into them and be notified instantly. Currently, for example, when I ask a question on a blog post, I'll throw the comments feed for that post into Reader so I don't have to keep checking back on the site; Reader will bring the potential answers to me. With webhooks though, I would reverse this and provide the service with the URL of my event consumer.<br /><br />It seems like, as technology and the internet often does, feeds are evolving into what users need them to be. Services are seeing that people want to follow and be kept up to date without having to check back on hundreds of different sites. That's way too much time and information, especially when it all looks different. However, by plugging the feeds of all those things into an aggregator, we gain a central notification place for all these events, and it becomes much more managable.<br /><br />So will webhooks replace the current paradigm that I'm using here, or complement it? They seem to each have their pros and cons. Feeds allow a history, and you won't miss an update because your aggregator was down; it will catch it on the next poll. However webhooks are instant and can be more efficient as you don't have the need for polling at all, but if the producer loses your hook, you're out of the loop.<br /><br />So an overflow of interesting events occurring on the web necessitated a standard way to view them, and we got feeds. Are webhooks the next step of this evolution, or something else entirely?<br /><br />UPDATE: <a href="http://blogger.malept.com/2009/02/on-webhooks-or-push-revolution.html">Mark Lee responds</a>.Unknownnoreply@blogger.com9tag:blogger.com,1999:blog-3369913276619133519.post-33719258695221860122009-02-16T19:46:00.000-08:002009-02-16T20:05:33.081-08:00Cracking On-Screen Keyboards with Visual KeyloggersA few financial sites including HSBC and the US Treasury have recently added an extra measure of security to their site. Instead of simply requiring a username and password, an on-screen keyboard was added, requiring you to "type" in a second password with your mouse:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs7f98eElP4jhzWwayDIPhjxgqBn44jB4A5XXed5cJS6rQ4QxFuwlDycpsfDpGAYPzvC6luPdn3HLRw4_bk52EVxRO_1Zk9deGNPrbl0R69IKublD5rfLqcpGbHIzsFpMcljjvOYD0IZqk/s1600-h/Screenshot.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 297px; height: 154px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhs7f98eElP4jhzWwayDIPhjxgqBn44jB4A5XXed5cJS6rQ4QxFuwlDycpsfDpGAYPzvC6luPdn3HLRw4_bk52EVxRO_1Zk9deGNPrbl0R69IKublD5rfLqcpGbHIzsFpMcljjvOYD0IZqk/s320/Screenshot.png" alt="" id="BLOGGER_PHOTO_ID_5303611011627756498" border="0" /></a><br /><br />The logic behind this is that if a user's computer becomes compromised with a keylogger, the attacker could only obtain the username and primary password. The secondary password would remain uncomprised as it doesn't involve keypresses. This didn't seem too useful to me however, so for my "Image Understanding" class I decided to see if it was possible to create a "visual keylogger" which could capture this secondary password. It wasn't too difficult, and essentially demonstrated that the extra password was more inconvenience than security. Let me outline the basic process.<br /><br />In order to do this, you need to be able to capture the contents of the screen at certain intervals. It seems like a fair assumption that if you (as the attacker of a comprimised system) can capture keyboard input, you can also grab screenshots. The goal is to turn a sequence of these screenshots of someone typing with an on-screen keyboard into a single string output equivalent to the password typed.<br /><br />First we want to record the position of the mouse at each shot. This would normally be a trivial function by asking the OS; however, in my case I was writing this for an Image Understanding class and had to use the sequence of images as my sole input. As such, I used a basic templating approach to locate the mouse by a few of its key features. This was surprisingly robust; however, asking the OS for the mouse position is an easier, even more robust, and more likely attack vector in real life.<br /><br />Now we need to figure out when the user clicked a key. Any keyboard used for a password purpose is going to give some form of feedback when a key is clicked, such as an asterisk in a password field, so the user knows if they have successfully clicked a key. The easiest way then to notice this is to subtract the color values of each screenshot from the previous one, giving you a new image with non-zero pixel values for each changed pixel. Among other things like cursor movement and web animations, the aforementioned asterisk feedback is going to be present in this image.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTfvFu09T5ULEcOOUDlgoe_GaBTsSVrijItkm-EomOe4moSZ-e1ks-jkgHO8gxfBU-qJYG2v9pM8KIMIe1Ul9b-yBK-EUK0lLItYCBeCtME5wwWDiTLmc2lpqLUGgeaVPA32i-tcwHKwt1/s1600-h/Screenshot-1a.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 165px; height: 138px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTfvFu09T5ULEcOOUDlgoe_GaBTsSVrijItkm-EomOe4moSZ-e1ks-jkgHO8gxfBU-qJYG2v9pM8KIMIe1Ul9b-yBK-EUK0lLItYCBeCtME5wwWDiTLmc2lpqLUGgeaVPA32i-tcwHKwt1/s320/Screenshot-1a.png" alt="" id="BLOGGER_PHOTO_ID_5303611140138596626" border="0" /></a><br /><br />For each new image then, subtract and look for this feedback. If it's there, that's a key press! Combine this with the position of the mouse and you know where the user clicked. Now it gets slightly tricky. You know where they clicked, but if you grab that section of the screen, you'll get something like this:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn2Puw13_SY0F31fgaqRLsErOggZQbQxVKL5orWQgiQTGbDRLb6tsGJ9FMVHu7zgfsIVH5MO7MUzP3My2b1-2uGo-O1ZmK7lcA6ZQ8yq9Dei7ZLc1Jr23_8i1dCC4GZkIJZ981b-TkxkkQ/s1600-h/Screenshot-1.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 301px; height: 259px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn2Puw13_SY0F31fgaqRLsErOggZQbQxVKL5orWQgiQTGbDRLb6tsGJ9FMVHu7zgfsIVH5MO7MUzP3My2b1-2uGo-O1ZmK7lcA6ZQ8yq9Dei7ZLc1Jr23_8i1dCC4GZkIJZ981b-TkxkkQ/s320/Screenshot-1.png" alt="" id="BLOGGER_PHOTO_ID_5303611072170614738" border="0" /></a><br /><br />because the mouse had to be over the key to click it. This is rather easily worked around, however, by going backwards in your mouse position cache until it is a certain threshold away from the clicked position, and grabbing the key image at that point.<br /><br />After the user enters the complete password, you are going to be left with an array of keyboard images. For any human, this is quite sufficient. For my class however, it was not, and it would not be for any large-scale operation where automation is desired. What we need to do is clean it up by throwing away any pixels under a certain darkness threshold, then cropping the result:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTfa7EvmrriogPmK44M0tDh9YRrdE9lCQxHcoH8YyeQloJyoDgY6UUX23JMtW3kTk1EFdLmJ2b1vlkoI8qsOXqRIy0MbQkKkRoyI_-YVRQh6MyLiQDDWRxIQNKynRqRIOTl5qkcHoZt4cu/s1600-h/Screenshot-2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 277px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTfa7EvmrriogPmK44M0tDh9YRrdE9lCQxHcoH8YyeQloJyoDgY6UUX23JMtW3kTk1EFdLmJ2b1vlkoI8qsOXqRIy0MbQkKkRoyI_-YVRQh6MyLiQDDWRxIQNKynRqRIOTl5qkcHoZt4cu/s320/Screenshot-2.png" alt="" id="BLOGGER_PHOTO_ID_5303611231882743362" border="0" /></a><br /><br />Ta-da! Now we have something that any OCR (optical character recognition) algorithm should be able to chomp through in its sleep cycles. If you are writing for a specific keyboard, you can also just have an array of what each key looks like in binary form and compare to get the answer.<br /><br />And there you have it! With the combination of a few basic computer vision techniques, we can expand a keylogger to understand input from visual keyboards and render this security annoyance useless. A fun note is that the order/position of the keys is irrelevant. The US treasury website uses an on-screen keyboard as well, but shuffles the keys each attempt. As is hopefully obvious from this algorithm, there is no assumption of a keyboard layout; the keys could shuffle every single click and it wouldn't matter.Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-3369913276619133519.post-1370586041393038562009-02-15T21:50:00.000-08:002009-02-15T22:00:24.571-08:00Lightweight personal finance just got easier with wxBanker in Jaunty!<a href="https://launchpad.net/wxbanker">wxBanker</a>, your (hopefully) favorite lightweight personal finance application, has recently been accepted into Jaunty! Aren't familiar with it? Check out the <a href="https://wiki.ubuntu.com/wxBanker">screenshots</a>! It took a few months of getting over the debian packaging learning curve, and about as much work getting and responding to the reviews from MOTUs, but I did it. I plan on doing a quick point release this week and releasing wxBanker 0.4.0.3, which will sport updated <a href="https://translations.edge.launchpad.net/wxbanker/trunk/+pots/wxbanker">translations in 15 languages</a> (thanks translators!) as well as a minor bug fix or three. Once I get that out and into Jaunty, I'll turn my complete focus (I hope) to the 0.5 series. If you'd like to translate wxBanker to your own language or improve a few of the lacking existing translations (Bosnian, Dutch, and Portuguese particularly), I'd love it! Head over to <span><a href="https://launchpad.net/%7Ewxbanker-translators">https://launchpad.net/~wxbanker-translators</a> and join the fun!</span><br /><br />The 0.5 series is a refactor and a bit of a painful one, as I didn't have a great handle on how to efficiently and smoothly refactor. I could probably do a much better job managing it now, but that's how experience works. All in all it is a much cleaner structure and led to more and better tests, which should allow more agile development and protect against future regressions. Some of the main upcoming features I'd like to get in are transaction tagging, recurring transactions, reporting, online syncing (via mint.com), and csv imports. I'd love for at least a few of those to make it into 0.5, and there is good progress on some of them including csv imports thanks to <a href="https://code.launchpad.net/%7Ekolmis/wxbanker/csvimport">an impressive branch from Karel</a>. On the other hand 0.5 has already been ongoing for about 3 months and I might cut a release into a PPA and get feedback while I add new features, sorting out any 0.5 issues and leading to a robust 0.6 release.<br /><br />Overall I have learned a TON from this project, in no small part thanks to Launchpad. wxBanker started out as a terminal application which stored everything in a pickled linked tuple that I used for myself and added features as I needed them. Eventually I added a GUI (in wxPython) and registered the project on Launchpad, to get free hosted version control as well as more formal bug tracking (instead of a text file :). The combination of Launchpad and [wx]Python being cross-platform made it accessible to everyone, and took it from a project used only by myself to a project available in 15 languages with code contributions from multiple people.<br /><br />So in conclusion, thanks everyone, enjoy wxBanker 0.4.0.3 in Jaunty, and look forward to future versions in my PPA. If you're not on Jaunty yet, you can <a href="https://launchpad.net/%7Emrooney/+archive/ppa">install 0.4 from my PPA</a>, which I'll be updating to 0.4.0.3 as soon as I release it. I'd love for any of your contributions, suggestions, questions, or criticisms to end up <a href="https://launchpad.net/wxbanker">on Launchpad</a>. I'd love to make it as usable and intuitive as possible, so anything that is unclear or confusing would be awesome to hear.Unknownnoreply@blogger.com5