RIM: did you just tell me to Google 'you do not have write permission'?
July 28, 2011 at 11:41 AM | Uncategorized | View CommentsBackground: I have been trying to develop for the PlayBook, and I have run into silly, time-consuming problems at every step. I have sent some of these errors to @BlackBerryDev, and have received generally unhelpful responses (for example, see my message, RIM's reply, my reply, RIM's second reply)... But the message I received today deserves a response longer than 140 characters.
My initial message was:
@BlackBerryDev eg, BS unhelpful errors like this: http://twitpic.com/5u4sco
And @BlackBerryDev replied with:
@wolever This error is a common mac permissions error, not specific to our tooling. Check [http://www.google.ca/search?q=%22You+do+not+have+write+permissions...] for examples ^SA
And this is my reply to the above:
As you have apparently never debugged a permission error before, ^SA, so let me tell you how it works.
When sensible software can't write to a file or directory, it includes a full path to the file or directory in the error message. Using this information, it is possible to example the file or directory in question and determine the correct course of actions (for example, changing the permissions).
However, the shitty InstallAnywhere software used by the PlayBook SDK is, unsurprisingly, not sensible. So when it encounters a permission error, its error message does not include any such information. In fact, the only hint about the install directory I'm given is that it's:
Inside "Research in Motion" on the folder "SDKs" on the disk "Enoch".Which makes the permission error impossible to debug without something like an install log.
But I don't know where the install log is (if it exists), and frankly I don't care.
What I do care about, though, is that you have sent me a link to a Google search (without even using lmgtfy!) that you clearly haven't looked at (because if you had, you would see that 1/3 of the results are Linux-specific, 1/3 of the results are the file which defines the error message, and 1/3 of the results are mirrors of the same message, which suggests a simple “fix permissions” (which, by the way, would not, and did not, fix the problem).
So, @BlackBerryDev: if your future messages will piss me off and insult me in the same way that these messages have, I would rather you simply didn't respond to me at all.
And, while I'm standing on my little soap box here, I'd like to send RIM a small message too:
RIM,
It seems obvious to me that the only way you will be able to get on top is developers... But, at the moment, your development experience is terrible. Just ask anyone who has tried to develop for the PlayBook.
Fortunately I also know that you have the skill in-house to improve on this. You know those TinyHippos guys you recently acquired? They know what they're doing. Listen to them. If they suggest crazy things like sending both signing keys in one email (instead of two identical emails), do it. If they suggest getting in bed with Adobe and VMware so PlayBook developers can start developing without spending hours creating accounts and downloading demos, do it. Do whatever it takes to make development easy and painless.
Want some other starting points? Here's what I've complained about on Twitter (static mirror). Put more people behind @BlackBerryDev so they can reply quickly and helpfully. Make it possible to get developer signing keys instantly. Etc...
I would really like to develop for the PlayBook. I really would. But as it stands, I've spent three hours dealing with the kind of crap I've documented above for every hour I've spent writing code. And that's just no fun.
—David
Lies, More Lies and Python Packaging Documentation on `package_data`
July 15, 2011 at 08:35 PM | Python | View CommentsMy slice of Python packaging hell today was thanks to the lie that is package_data.
You see, I've been trying to create an package that includes non-Python files in the distribution... So I did what any good developer would do and hit the documentation:
Package data can be added to packages using the package_data keyword argument to the setup() function.
and
If you want finer-grained control over what files are included (for example, if you have documentation files in your package directories and want to exclude them from installation), then you can also use the package_data keyword.
Over the last hour, though, I've learned that these statements are somewhere between “dangerously misleading” and “damn lies”.
This is because the primary type of Python package is a source package, and the canonical method for creating a source package is by using setup.py sdist. However, the data specified in package_data are not included in source distributions — they are only included in binary (setup.py bdist) distributions and installs (setup.py install).
The only way to get package data included in source packages is the MANIFEST.in file... Which will also include data in binary distributions and installs.
Which renders the package_data option useful only if sdist is not used… And dangerously misleading if sdist is used.
tl;dr: package_data is a lie. Ignore it. Only use MANIFEST.in.
Nested Repository Handling in git and Mercurial
July 14, 2011 at 12:31 AM | Version control | View Commentsgit and Mercurial both have extensions for nesting particular versions of external repositories (git has submodules, Mercurial has subrepos), and I've found it interesting (and telling?) to compare the implementations.
To nest the repository nested at .subrepos/nested in Mercurial, the line .subrepos/nested = nested is added to the file .hgsub and the line [hash] .subrepos/nested (where [hash] is the current revision's hash) is added to the file .hgsubstate. As the version of nested changes, the .hgsubstate file is updated and committed like any other file.
In contrast, to nest nested at .modules/nested in git, the lines:
[submodule ".modules/nested"] path = .modules/nested url = nested
are added to .gitmodules, and an entry is added to the tree:
160000 commit [hash] .modules/nested
I found this interesting because it re-enforces my feelings towards both systems: I appreciate the simplicity and accessibility of Mercurial's implementation, and I appreciate the intellectual stimulation I got from learning about git's implementation.
But I also believe that git's implementation is inferior in every practical way.
Because Mercurial's subrepo state is stored in plain text files which are committed into the repository, any tool which is used to view/edit/exchange a repository will trivially be able to handle subrepos. For example, changes to subrepos can be trivially exchanged with standard diff/patch tools:
$ hg diff -c bump_nested diff --git a/.hgsubstate b/.hgsubstate --- a/.hgsubstate +++ b/.hgsubstate @@ -1,1 +1,1 @@ -[... old hash ...] .subrepos/nested +[... new hash ...] .subrepos/nested
Versions pinned in subrepos can be easily changed with a text editor (for example, to resolve merge conflicts), and tools which interact with Mercurial repositories (for example, hgweb) will function correctly, even if they are ignorant of subrepos.
Contrast this with git's submodules, where submodule versions are “hidden” in the tree, and every tool must be aware of their existence. For example, it is impossible to use standard diff and patch tools:
$ git show bump_nested ... diff --git a/.modules/nested b/.modules/nested index f44396c..1fd6830 160000 --- a/.modules/nested +++ b/.modules/nested @@ -1 +1 @@ -Subproject commit [... old hash ...] +Subproject commit [... new hash ...]
Instead, git am must be used. Any tool that interacts with a submodule-enabled repository must be aware of submodues, otherwise it will crash with “fatal: bad object” (ie, because it likely assumes that any hash in the tree references a blob in the repository, which is not true in the case of a commit entry) and submodule-specific commands must be learned and used to resolve submodule merge conflicts [0].
All of these complications could be acceptable if they allowed git's submodules to be somehow “better” than if a simpler scheme, like Mercurial's .hgsubstate was used… But, as far as I can tell, this implementation affords no practical benefit.
[0] | hint: after a submodule merge conflict, git submodule status will show all the revisions you might care about: $ git submodule status -595c7a8dd110ab3f0f305bb0f3d6356ca5d62d99 nested -cacb40625cc891b33c9c935442c0180e8ba5ab15 nested -5e71d23bc5d24d18e026bcf12773f3fade1ac6b9 nested And you'll need to remember that the first line is the common ancestor, the second line “our” version, the third line is “their” version. To resolve the conflict, the standard git checkout --{ours,theirs} appears to do nothing — you need to copy the hash of the desired revision, cd nested; git checkout $hash; cd .., then commit as normal. |
Running Multiple Firefox Profiles for Fun and Profit
July 10, 2011 at 01:07 PM | Uncategorized | View CommentsFor a long time I have found it useful to run three (or more) different browsers: Safari for my day-to-day browsing, Firefox for my development work and Camino for Facebook and Google apps. This separation is part pragmatism – it's useful to clear cookies or disable FlashBlock while I'm developing without my main browser being affected – and part paranoia – I'm not logged in to Facebook or Google on my main browser, so it's harder for them to track me and I'm less likely to be hurt by a cross-site-scripting (or similar) attack.
Recently Safari's memory leaks [0] and the launch of Firefox 5 have pushed me to re-evaluating my browser preferences... And this is the result:

Three customized versions of Firefox and three profiles to match.
The customizations are straight forward:
- Firefox.app was copied three times, and the name was to the role of that copy (“Browsing.app”, etc).
- The icon was changed on each app.
- The CFBundleName in $NAME.app/Contents/Resources/en.lproj/InfoPlist.strings was changed from “Firefox” to $NAME (changing the application name which appears in the top left corner of the screen).
- After the “Browsing” profile was setup (correct plugins installed, etc), it was copied twice to create the “Dev” and “Facebook” profiles (profiles are stored at ~/Library/Application Support/Firefox/Profiles/, and the profiles.ini file, in Application Support/Firefox/, must also be updated).
- A persona was added to the “Facebook” and “Dev” profiles (specifically a pastel sky blue and pastel mandarin).
- NoScript was installed on the “Facebook” profile (for a little bit of added paranoia).
With these customizations, it's easy to visually distinguish between the browsers, both from the main windows:

And from the dock/command+tab application list:

And that's my current browsing setup :)
[0] | it would be using almost a gigabyte of memory, even if I only had one or two tabs open. |