bugs

You are browsing the archives of bugs.

Python NaN equality rules (and cw.eq.equals)

>>> float('nan') == float('nan')
False
>>> n = float('nan')
>>> n
nan
>>> n == n
False
>>> [float('nan')] == [float('nan')]
False # Note: in PyPy, True
>>> [n] == [n]
True
>>> nl = [float('nan')]
>>> nl == nl
True

Got it? Good. (The behavior above is caused by various object-identity shortcuts for either the NaN or the list object.)

If you’re wondering how this works in JavaScript, well, it doesn’t, because JavaScript doesn’t have any kind of deep-equality comparison. JavaScript Arrays and Objects compare by identity. But in Coreweb’s cw.eq.equals, I didn’t implement the object-identity shortcut, so NaN comparison works correctly:

>>> Number.NaN == Number.NaN
false
>>> n = Number.NaN
NaN
>>> n == n
false
>>> cw.eq.equals([Number.NaN], [Number.NaN])
false
>>> cw.eq.equals([n], [n])
false
>>> nl = [Number.NaN]
[NaN]
>>> cw.eq.equals(nl, nl)
false

Sublime Text + Samba + GHC problem

If you’re using Sublime Text on Windows to edit files on a network drive powered by Samba, and then run a Haskell program on the system running Samba (not the machine running Sublime Text), you might see:

openBinaryFile: resource exhausted (Resource temporarily unavailable)

or

openFile: resource exhausted (Resource temporarily unavailable)

This problem is caused by Samba grabbing oplocks (opportunistic locks) on the files being edited. Sublime Text makes system calls that result in the oplocks being grabbed, while most other editors (including Wordpad) do not. You can work around the problem by adding oplocks = no in the configuration for your share in smb.conf. Using Samba has some reading on oplocks.

Preserving italics in pastes from webpages

Tired of losing italics in pastes from websites to your plain-text editor? For a while, I thought I needed to switch to a rich-text editor to handle these pastes, but that would be a pain for several reasons. A few days ago I realized I just needed to mutate the webpage by surrounding italic text with slashes. I would run a bookmarklet, then copy/paste. (Skip below for a working bookmarklet).

My first attempt at this used the :before and :after CSS pseudo-elements:

javascript:(function() {
	var newSS, styles='em:before, em:after, i:before, i:after { content: "/" }';
	if(document.createStyleSheet) {
		document.createStyleSheet("javascript:'" + styles + "'");
	} else {
		newSS = document.createElement('link');
		newSS.rel = 'stylesheet';
		newSS.href = 'data:text/css,' + escape(styles);
		document.getElementsByTagName("head")[0].appendChild(newSS);
	}
})();

If you run the above (paste into your URL bar and hit enter), it looks like it works until you try to paste the text containing slashes; neither Chrome 10 or Firefox 4 will put the slashes in your clipboard. I threw out the simple clean non-working code and went for a terrible hack:

javascript:(function() { document.body.innerHTML = document.body.innerHTML.
	replace(/<em(\s.*?)?>([\s\S]+?)<\/em>/gi, "/<em$1>$2</em>/").
	replace(/<i(\s.*?)?>([\s\S]+?)<\/i>/gi, "/<i$1>$2</i>/").
	replace(/<span style="font-style: italic;">([\s\S]+?)<\/span>/gi, '/<span style="font-style: italic;">$1</span>/').
	replace(/<strong(\s.*?)?>([\s\S]+?)<\/strong>/gi, "*<strong$1>$2</strong>*").
	replace(/<b(\s.*?)?>([\s\S]+?)<\/b>/gi, "*<b$1>$2</b>*"); })();

This above replaces document.body.innerHTML with a new string where italics are surrounded with “/” and bold surrounded by “*”. This is terrible in several ways: it may break or re-run JavaScript code on the page, or somehow make you vulnerable to XSS (in a manner likely similar to the IE8 XSS “blocker”). Only while writing this post did I realize the security implications of the above. I decided to implement it using DOM manipulation (requires CSS3 selectors and querySelectorAll):

javascript:(function() { 
	var wrapElements = function(selector, wrapperText) {
		var elements = document.querySelectorAll(selector);
		for(var i=0; i < elements.length; i++) {
			var surround = elements[i];
			if(surround.parentNode) {
				surround.parentNode.insertBefore(
					document.createTextNode(wrapperText), surround);
			}
			surround.appendChild(
				document.createTextNode(wrapperText));
		}
	};
 
	var getStyleAttrVariations = function(elem, property, value) {
		return [
			 elem + '[style="' + property + ': ' + value + ';"]'
			,elem + '[style="' + property + ': ' + value + '"]'
			,elem + '[style="' + property + ':'  + value + ';"]'
			,elem + '[style="' + property + ':'  + value + '"]'
		];
	};
 
	wrapElements('em, i, span[class~="emphasis"], span[class~="italic"]', '/');
	wrapElements(getStyleAttrVariations('span', 'font-style', 'italic').join(' ,'), '/');
 
	wrapElements('strong, b, span[class~="bold"]', '*');
	wrapElements(getStyleAttrVariations('span', 'font-weight', 'bold').join(' ,'), '*');
})();

If you don’t want to manually create a bookmark with the above code, you can drag this link to your toolbar or bookmarks:

Preserve italics and bold

I use a bookmark keyword in Firefox to activate it; keywords are not just for searches.

Here’s some bold and italic text so you know it’s working: bold, italic.

Adobe is finally working on Flash Socket write() feedback

A reason to rejoice:

We are working on this feature. It is definitely under work, so it will be available soon guys.

Socket class write() – information feedback

This will allow you to know how much written data has actually made it to your kernel. Without this information, you cannot do flow control unless the server is constantly responding with TCP-level data.

This “write feedback” information is available in WebSocket (in the bufferedAmount property), but ideally it would dispatch events too.

How to test your __eq__ / __ne__ / __cmp__

In Python, a common mistake is to implement __eq__ on your object without also implementing __ne__. Even worse, your unit tests will often hide the error because the default object-identity __ne__ will probably satisfy your assertions.

If you’ve implemented __eq__ and __ne__, you might still have a mistake if the superclass has a __cmp__: Python’s cmp will fall back to the superclass’ __cmp__ instead of using your __eq__ (example). You’ll probably never notice this problem unless you use cmp(...) on your object.

When I need to exercise all possible combinations of ==, !=, and cmp, I mix this into my TestCases and use self.assertReally(Not)Equal(a, b):

class ReallyEqualMixin(object):
	def assertReallyEqual(self, a, b):
		# assertEqual first, because it will have a good message if the
		# assertion fails.
		self.assertEqual(a, b)
		self.assertEqual(b, a)
		self.assertTrue(a == b)
		self.assertTrue(b == a)
		self.assertFalse(a != b)
		self.assertFalse(b != a)
		self.assertEqual(0, cmp(a, b))
		self.assertEqual(0, cmp(b, a))
 
	def assertReallyNotEqual(self, a, b):
		# assertNotEqual first, because it will have a good message if the
		# assertion fails.
		self.assertNotEqual(a, b)
		self.assertNotEqual(b, a)
		self.assertFalse(a == b)
		self.assertFalse(b == a)
		self.assertTrue(a != b)
		self.assertTrue(b != a)
		self.assertNotEqual(0, cmp(a, b))
		self.assertNotEqual(0, cmp(b, a))

No © on the above, enjoy.

Further reading: How to override comparison operators in Python

JavaScript’s sort: wonders never cease

>>> [1, 2, 10, 20].sort()
[1, 10, 2, 20]
 
>>> [3, "3", 3, "3", "3", "3", 3, 3, 3].sort()
["3", "3", "3", 3, 3, 3, "3", 3, 3]

The above was tested in Chrome 5. Sort varies by browser. Bedtime reading: ECMA-262 15.4.4.11 Array.prototype.sort(comparefn)

Don’t use from __future__ import division

tl;dr: For maintenance reasons, just float() one of the values instead.

Don’t use from __future__ import division. Consider these two cases:

1. You’re moving a block of code from a file without “future division” to a file with “future division”. You forget to change all of the /s to //s, and are screwed (because you have incomplete test coverage). Or maybe you’re moving a block of code the other way, and similarly forget to change things.

2. You have a module with from __future__ import division, but all division operations were removed in an earlier commit. Can you now remove the from __future__ import? Maybe not, and you might keep them forever, just in case there are outstanding patches to the module. But not everyone will follow that logic.

Summary: subtle global behavior mutation is bad, even if scoped to a single file.

(Consider ignoring all of this if you’re developing for both Python 2 and Python 3.)

Python < 2.5 and unicode/str comparisons

Comparing strings to unicode objects should have never been possible, but it does “work”, and you’ve probably seen this behavior in Python 2.5 – 2.7:

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
>>> u"\xff" == "\xff"
__main__:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
False

To do the comparison, Python calls unicode() on the str object behind the scenes, and if it cannot decode it, it emits a warning and returns False.

If you’re still maintaining software that must run on Python 2.4 (or worse), you might run into this old behavior:

Python 2.4.6 (#1, Aug 2 2010, 18:27:11)
>>> u"\xff" == "\xff"
Traceback (most recent call last):
  File "", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)

Also, if you’re writing tests that involve this, keep in mind that Python 2.4 does not have a UnicodeWarning.

(After I wrote this, I found that it was documented in What’s New in Python 2.5.)

Blizzard annoyances

If you use Blizzard Downloader, you might see:

“There was a problem authenticating your download. Please go to http://www.blizzard.com/account to start a new download”

One of the reasons you might see this is this (see others): when you download the downloader, Blizzard embeds your IP address into the executable, and only lets you start the download from the same IP. This is terrible software design, and completely unnecessary to stop bandwidth leeches: just embed a unique key into the executable, and ignore the IP address.

Clock jumps and browsers

If you’re trying to build reliable web applications, you might have wondered what happens to existing timeouts and intervals after the system clock jumps. Not that clock jumps happen very often, but it’s nice to think of setTimeout(func, 0) (or similar) as a reliable abstraction. Unfortunately, it isn’t. See Clock jump test page for the results of my testing, or to do your own tests.

In some browsers on some OSes, if the clock jumps backwards, an existing timer might not fire for a long time. If the clock jumps forwards, an existing timer might fire too early, possibly causing misbehavior if you were relying on a correct time duration.

A summary of the test page: IE and Opera on any OS use the monotonic clock to schedule timeouts. Firefox on Windows uses the monotonic clock, but a setInterval timer is broken after a backwards clock jump. Every other OS/browser combination schedules by the system time, or behaves strangely when the time jumps.

Here’s the bug for Chromium, but a lot more bugs need to be filed.