Hot on the heels of the changes to the underlying Simplenote.py, Simplenote.vim is now Python 2 and 3 compatible. Ok, that’s a lie. The same fate befell me: I assumed it would be tricky and complex to do (not least because I needed to build a separate version of Vim with only Python 3), but in the end it was actually quite easy and I really should have done it sooner than fourteen months later.

Some of the key points this time round:

Using pyfile instead of embedded code

Simplenote.vim makes use of embedded python code identified with endmarkers, like so:

python <<< ENDPYTHON
	#python code here
ENDPYTHON

but Vim requires you use the appropriate call for the version of python you have and will error if you call a version you don’t have. I.e. for python 3 you must use

python3 <<< ENDPYTHON
	#python3 code here
ENDPYTHON

This potentially was going to lead to huge chunks of duplicated code as you’d need a setup like follows:

if has("python")
	python <<< ENDPYTHON
		#python code here
	ENDPYTHON
elseif has("python3")
	python3 <<< ENDPYTHON
		#Very similar python3 code here
	ENDPYTHON
endif

Fortunately, at least I think so, using these has calls means Vim will load the first available python, but not both, which is what I want. I’m not sure how many people are likely to have vim compiled with support for both though; it was only just recently when I came across the first person who had python 3 support instead of python 2. I guess I’ll await the bug reports.

To get around the duplication I used pyfile instead, like follows:

if has("python")
	execute 'pyfile ' . s:scriptpath . "/samefilefor2and3.py"
elseif has("python3")
	execute 'py3file ' . s:scriptpath . "/samefilefor2and3.py"
endif

cmp_to_key

I thought this would be my stumbling block, as Python 3 no longer has a cmp function for sort, only accepts a much more simplistic key, and Simplenote.vim uses quite an extensive compare function for sorting notes in the list index. Fortunately, from version 3.2 onwards there is a cmp_to_key function provided by functools so I could just do:

notes.sort(key=functools.cmp_to_key(compare_notes))

I think I can be pretty confident that anyone who has Vim compiled against Python 3 only will have a recent version of Python 3.

Python 3 changes that work fine under Python 2

  • print statements need brackets (parentheses) under Python 3. They are optional under 2.
  • iteritems doesn’t exist under Python 3, instead you just call items. For the Simplenote.vim use of iteritems, using just items under Python 2 worked fine.
  • Python 3 requires you use list on map to return the actual content (otherwise you just get a map object). Python 2 doesn’t require this, but including it anyway causes no harm.
  • No more has_key, but that has been depreciated for a long time anyway. Just use in instead, works everywhere.

Really the only excuse for not writing Python 2 and 3 compatible code is laziness.

See commits 9a2234d to c916606 for more detail.