08 December 2016

Best way to get locale info and localized strings on Python

One area where Windows often beats the Unix tradition is internationalisation. Traditional POSIX interfaces assume there will be One And Only One set of internationalised conventions (display language, date format etc) at runtime, and are mostly concerned with displaying data formatted for that One True Set. When you want something "international" on POSIX, you switch your locale with setlocale() and do your business. This approach unfortunately percolates in Unix-borne tools and languages, in this case Python. There is no "pure-Python" alternative to good ol' GetLocaleInfo, so there is no way to retrieve, say, the French name for January without switching the whole process locale with setlocale(). This is pretty insane and likely dangerous.

Most libraries hack their way around this by packing an arbitrary subset of i18n strings, or just go full-YOLO by switching process locale back and forth. It's a sad state of affairs.

However, there is a better way. The Unicode Consortium, in its infinte wisdom, maintains a big database of localisation metadata, the CLDR. You can either download the full set yourself and parse a bunch of XML files, or you can use the Babel library which basically does it for you.

$> pip install babel
...
$> python
>>> import babel
>>> locale = babel.Locale('fr')
>>> locale.months['format']['wide'][1]
'janvier'

Et voilĂ .

30 October 2016

On fixing hardware

There is a certain satisfaction in fixing hardware. It can be pretty trivial at times: unscrew a bunch of pieces, replace the broken bit, screw everything back together. The worst that can happen is to end up with one or two screws that don't seem to go anywhere once you put things back.

I recently fixed a Kindle from a few years ago (model D00901, aka "the one with a little keyboard"), and I had exactly this experience, minus the extra screws. I just opened it all up, disconnected the broken screen, replaced it with a new one from eBay (£16), and put it all back together - done. By then I'd already bought a replacement Voyage, but I can now give this to my kids. I was also pretty happy to get this particular model back, because it's much easier to hack than the Voyage (Amazon, wtf? I still can't change screensaver images, in 2016??)

Moral of the story - always try to fix broken hardware. It might save you a few pennies and, in the age of youtube, you don't even have to be an expert to do it.

04 August 2016

CSL Vertical Mouse Review

A couple of weeks ago, I started experiencing a bit of recurring pain in the right forearm. I put it down to a few heavy sessions of MiniMetro, a game where you have to constantly drag & drop between points on the screen; the Magic Trackpad, even rotated in a negative-slope position, was forcing my arm and wrist to do too much work. After a bit of googling, I decided to try a vertical mouse, which should (in theory) keep your arm in a more natural position, and actually move a lot of work from wrist and forearm muscles towards the shoulder and upper arm muscles.

The market for ergonomic devices has always been small, but there's a surprisingly wide choice of vertical mice out there. Unfortunately, a lot of them don't inspire much confidence; some are sold as vertical but actually end up being just fancy-shaped regular mice. The best in class seem to be Evoluent products, which are really vertical and really ergonomic but also really expensive. I wasn't ready to drop almost £100 on something I might not like, so I steered towards cheaper alternatives.

Some of the best reviews on the net pointed towards this fin-shaped CSL wireless mouse, and it was so inexpensive that it wouldn't feel like a waste if I ended up not liking it. The shape makes a bit more sense when you see the SHARKK-branded version - fins, sharks... I honestly don't know which brand came first or which one is more reliable; SHARKK is a US company whereas CSL seems to be based in Germany, but both have a history of distributing and rebranding products by Asian manufacturers, so the original factory is probably the same Shenzhen hangout.

The most annoying element of this mouse is the fact that it does not use Bluetooth, but rather a bog-standard USB wifi dongle. In recent Macs, USB ports are very few and losing one forever is a Big Deal.

The mouse does not require drivers, which is great news for Mac users. It simply appears as a regular HID with 5 buttons: left, right, middle (under the wheel),  and two near the thumb. A sixth button, on top of the fin, is actually the DPI selector, which allows you to change resolution (and hence sensitivity) between three modes: 800, 1200 and 1600 DPI. The selector works fine (just cycles through modes as you click it, with no feedback on screen) but OSX just doesn't "see it" as a regular button, which means you cannot easily re-purpose it once you've set the DPI mode. How often will you need to change mouse sensitivity? An operation so rarely performed doesn't really deserve a large button in such a prime location, but there you go.

The two thumb buttons are supposed to be for browser Back/Forward, but with Firefox they actually trigger the infamous "hold and scroll" widget, so I used BetterTouchTool to remap them with  trackpad gestures I used the most (Mission Control to switch between windows across all apps, and Application ExposĂ© to switch between application-specific windows). I also set middle-click to Launchpad. A little quirk: the mouse built-in powersave settings will switch off the mouse if you don't use it for a few minutes; often you will have to click it or shake it to wake it up. There is no way to disable this behaviour under Mac.

It obviously takes a bit of time to adapt to the vertical position. Movements that would rely on the wrist with a trackpad or horizontal mouse, now require better coordination further up the arm. Wrist movements are set on a different axis (up-down, rather than sideways), but to be honest it's probably best to keep them at a minimum, relying on your arm instead.

After a few days of use, the pain seems to have gone, which is great news. However, I'm not totally convinced about this mouse. It does take some conscious effort to keep my hand in the vertical position, being way too easy to absent-mindedly slip back into a traditional posture; the fin shape will not stop you from doing it. That's probably the reason Evoluent models have steeper shapes.
WRONG! Might as well get a normal mouse then...
Correct position, with vertical wrist.
My hand as a whole also does not feel more relaxed, and the mouse/keyboard switch now seems a bit more tiring, since I have to actually rotate the forearm; I guess I could address that by sloping my keyboard, something I've resisted until now. Still, it's a bit annoying.

In conclusion, the CSL vertical mouse is great value for money: solid build, works flawlessly, cheap as chips. Is it a great vertical mouse though? I'm not so sure. Will I switch to vertical mice for good? Probably not, at this time and with this mouse, but I will revisit this position in a month or two.

08 July 2016

How to (not) handle OneDrive/Sharepoint "Sync Now" on Mac OSX

This bugged me for a bit and finally got around (almost) fixing it yesterday, so I thought I'd record it for posterity.

Microsoft Office365 will usually include a Sharepoint implementation of some sort. Sharepoint now integrates with OneDrive (aka "Microsoft Dropbox")... on Windows. On Mac, the current state of play is as follows:
  • You should get the free OneDrive app from Mac App Store. If you have previous beta versions or anything like that (which never worked particularly well), uninstall them before installing this.
  • Once you start and connect OneDrive to your Office365 subscription, your personal files will automatically sync to the OneDrive folder. It seems to work reasonably well.
  • However, files shared by others to you will not sync. The feature is just not implemented yet.
  • If you access Sharepoint or OneDrive from the website and click on the Sync Now button, the website will generate a link that looks like this: grvopen://http-etc-etc and pass it to the browser. By default this grvopen protocol will be associated with OneDrive and do nothing, because (guess what?) the feature is not implemented yet.
  • However, if you have a virtual machine with Windows and Office installed, there is a chance that the link will be passed to the Sharepoint client running on that machine. You probably don't want that: it will likely break things once the feature lands in OneDrive for Mac. So you can follow these instructions for VmWare Fusion to stop it from happening. Make sure to click on Clean Up Applications after deselecting Open your Mac files and web links using Windows applications. (Other virtualization products will have different ways of doing this, check your docs.)
I can see a forced approach where you configure OneDrive in your virtualized Office to use the same folder that OneDrive for Mac is using, but I expect this would bring up all sorts of issues. These sync programs do a lot of dirty tricks with file metadata and I'd rather not risk precious company files. I guess I'll just wait for MS to bring feature parity to OSX, and use the website in the meantime (which is actually slowly improving as well).

18 June 2016

Python SDK for Azure Basic Tutorial

As Spider-Man would say, from great enterprise comes great complexity. Microsoft cloud services are very, very enterprisey; which means they're also absurdly overcomplicated. One can probably spend most of his 30-day trial simply wandering around their dozens of different "portals" and "account management" screens. So here's a simple tutorial on going from zero to spinning up a VM with the Python SDK. (This is a work in progress, but hopefully it saves you the headaches I got).
  1. Sign up for an Azure free trial. You'll need a phone and a credit card, because MS requires verification like pr0n sites of yore.
  2. WAIT! DON'T DO ANYTHING! After the signup is successful and you're sent to the dashboard, chances are that your account is not actually fully formed, and you might be getting a lot of prompts about signing up for a Pay As You Go subscription. Wait 10 to 15 minutes. Grab a coffee; check Hacker News; live the enterprise life.
  3. close your browser and go back to the portal.
  4. Go to your active directory
  5. Create a Global Admin user by clicking on ADD USER (not the giant NEW, that would be too easy!). Write down the temporary password. (Note: I've no idea whether it has to be a global admin, but we're just trying to keep things simple here.)
  6. Now you have to associate the user to your Azure subscription, because you created it, it's in your AD, but obviously it's completely unrelated to your resources. Enterprise life! Go back to Azure portal, click on Subscriptions. NOTE DOWN YOUR SUBSCRIPTION ID, you'll need it later.
  7. Click on the subscription then Settings
  8. Click on Users (bottom right)
  9. Click on Add, select the Owner role, then add the new user to it. (Note: again, Owner is probably a bit too powerful, but we're trying to keep things simple.) Reference here.
  10. Now open a Private Window in your browser, or sign out of your account, because you have to log on the same portal as the new user.
  11. After logging on, you'll be forced to change the password. Done? Good; log out, close the window, the web-based ordeal is officially over.
  12. Create and activate a virtualenv (this procedure will differ depending on your platform/setup, reference here):
    mkdir azure_test && cd azure_test
    pyvenv-3.5 env
    source env/bin/activate
    pip install --upgrade pip   # this is optional but good practice
    
  13. install the Azure sdk
    pip install --pre azure
  14. Launch python and get cracking:
    sub_id = 'your-sub-id'  # you should have got this earlier, it's visible in "Subscriptions"
    # authentication reference at
    # http://azure-sdk-for-python.readthedocs.io/en/latest/resourcemanagementauthentication.html#using-ad-user-password
    from azure.common.credentials import UserPassCredentials
    credentials = UserPassCredentials('yourADuser@youraccount.onmicrosoft.com','youropassword')
    from azure.mgmt.resource.resources import ResourceManagementClient
    resource_client = ResourceManagementClient(credentials, sub_id)
    
    # one-off registrations, supposedly you won't need them next time
    resource_client.providers.register('Microsoft.Compute')
    resource_client.providers.register('Microsoft.Network')
    resource_client.providers.register('Microsoft.Storage')
    
    # create the clients
    from azure.mgmt.compute import ComputeManagementClient
    compute_client = ComputeManagementClient(credentials, sub_id)
    from azure.mgmt.network import NetworkManagementClient
    network_client = NetworkManagementClient(credentials, sub_id)
    from azure.mgmt.storage import StorageManagementClient
    storage_client = StorageManagementClient(credentials, sub_id)
    
  15. Now follow the code to create a VM here, skipping the 4 lines that define resource_client, storage_client etc, because you already have them.