So I think I’ve written before about the cloud based time tracking software I use; Paymo, well I’ve been working on a project to improve the invoicing side of it. Paymo does produce invoices but I find they’re a little bland, and they currently don’t meet the requirements set out by the ATO, so I have to produce my own manually.
This being a time consuming process I thought I’d automate it, and combining another side project I figured why not use it as a chance to improve my Python and Django skills. So it was a very nice relief to find that someone has already written a Python based library to the Paymo API – http://scardine.github.com/paymo/. Although it shouldn’t really come a surprise, part of my deciding what coding language would be a good choice was finding out what kind of community support and adoption each language had. So I guess it’s really confirmation of some research and means I chose wisely; young Jedi.
Everything isn’t all beer and skittles though trying to install it from pip failed, so I had to do some manual intervention to get it installed. Here’s what I did in case it helps someone else.
firewall # pip install paymo Downloading/unpacking paymo Downloading paymo-0.0.2.zip Running setup.py egg_info for package paymo Traceback (most recent call last): File "", line 16, in File "/tmp/pip-build/paymo/setup.py", line 15, in long_description=open("README.TXT").read(), IOError: [Errno 2] No such file or directory: 'README.TXT' Complete output from command python setup.py egg_info: Traceback (most recent call last): File "", line 16, in File "/tmp/pip-build/paymo/setup.py", line 15, in long_description=open("README.TXT").read(), IOError: [Errno 2] No such file or directory: 'README.TXT' ---------------------------------------- Command python setup.py egg_info failed with error code 1 in /tmp/pip-build/paymo Storing complete log in /root/.pip/pip.log
Looks like the first problem was unpacking and installing the python package itself.
firewall # cd /tmp/pip-build/paymo/ firewall # ls -la total 28 drwxr-xr-x 4 root root 4096 Jan 30 12:11 . drwxr-xr-x 3 root root 4096 Jan 30 12:11 .. -rw-r--r-- 1 root root 978 Jan 30 12:11 PKG-INFO -rw-r--r-- 1 root root 269 Jan 30 12:11 README.txt drwxr-xr-x 2 root root 4096 Jan 30 12:11 paymo drwxr-xr-x 2 root root 4096 Jan 30 12:11 pip-egg-info -rw-r--r-- 1 root root 953 Jan 30 12:11 setup.py firewall # mv README.txt README.TXT
Fairly easily fixed, it was looking for README.TXT but the file is called README.txt, Linux being case sensitive sees those as 2 different files. I suspect it was probably tested under Windows which is not case sensitive. A quick rename and we’re back installing correctly with no errors.
firewall # python Python 2.7.2 (default, Nov 15 2011, 13:17:26) [GCC 4.5.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from paymoapi import PaymoAPI Traceback (most recent call last): File "", line 1, in ImportError: No module named paymoapi >>> from paymo.api import PaymoAPI Traceback (most recent call last): File "", line 1, in File "/usr/lib64/python2.7/site-packages/paymo/api.py", line 1, in import requests ImportError: No module named requests >>> quit()
Now that it’s installed a simple test to confirm it works. Note the first attempt to import the library is based upon the Example given at the developer’s site http://scardine.github.com/paymo/ and contains this typo. The correct import should be from paymo.api not from paymoapi. Any other examples I’ve seen on the web also contain this error.
Anyhow that’s a sideline the major problem here is the import requests failing. Seems it’s dependent on the requests library.
firewall # pip install requests Downloading/unpacking requests Downloading requests-1.1.0.tar.gz (337kB): 337kB downloaded Running setup.py egg_info for package requests Installing collected packages: requests Running setup.py install for requests Successfully installed requests Cleaning up...
Simple install using pip, and take 2.
firewall # python Python 2.7.2 (default, Nov 15 2011, 13:17:26) [GCC 4.5.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from paymo.api import PaymoAPI Traceback (most recent call last): File "", line 1, in File "/usr/lib64/python2.7/site-packages/paymo/api.py", line 5, in from pyquery import PyQuery as pq ImportError: No module named pyquery >>> quit()
Doh! Another module dependency, this time pyquery.
firewall # pip install pyquery Downloading/unpacking pyquery Downloading pyquery-1.2.4.zip Running setup.py egg_info for package pyquery Downloading/unpacking lxml>=2.1 (from pyquery) ....... Successfully installed pyquery lxml cssselect Cleaning up...
Again a quick pip and hopefully good to go.
firewall # python Python 2.7.2 (default, Nov 15 2011, 13:17:26) [GCC 4.5.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from paymo.api import PaymoAPI
Well it imports that’s a good sign.
>>> paymo = PaymoAPI('apikey’, 'username', 'password’) >>> paymo.users.getList() {u'status': u'error', u'error': {u'message': u'Invalid auth token / Login failed', u'code': u'104'}} >>> quit() firewall #
That’s not a good sign, I did use my real username passwords etc. in the correct spots here but it seems to be throwing login errors. If you put in wrong entries or garbage it won’t even assign the class to the paymo variable, so I know the username and password is working OK, but looks like there’s a/some bug(s) in the library, which will have to wait till another time to sort out.
You may note that it was all done under Python 2.7, I however am trying to code anything I do in Python 3.x wherever possible as eventually 2.x will be phased out. So I thought I’d give it a try and see how it installs under Python 3.2. Thankfully with Gentoo it’s easy to switch between versions.
firewall tmp # eselect python list Available Python interpreters: [1] python2.7 * [2] python3.2 firewall tmp # eselect python set 2 firewall tmp # eselect python list Available Python interpreters: [1] python2.7 [2] python3.2 * firewall tmp # python -V Python 3.2.3
So at this point I installed it again and had to repeat the above dependencies and case sensitive renaming, but apart from that hassle free. So time to see how it runs.
firewall tmp # python Python 3.2.3 (default, May 28 2012, 11:39:24) [GCC 4.5.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from paymo.api import PaymoAPI Traceback (most recent call last): File "", line 1, in File "/usr/lib64/python3.2/site-packages/paymo/api.py", line 33 return u"{0}\n{1}\n{0}\n\n".format(c * len(s), s) ^ SyntaxError: invalid syntax >>> exit() firewall tmp #
Oops not so good, but a fairly common problem for 2.x to 3.x code, and mentioned in the “what’s new in 3.0” guide. A quick search and replace removing all the u”” to be just “” fixes that. For example;
return u"{0}\n{1}\n{0}\n\n".format(c * len(s), s)
becomes
return "{0}\n{1}\n{0}\n\n".format(c * len(s), s)
Trying again now throws syntax errors about print statements, again a common version 2 to 3 problem, as print is now a function instead of a statement. Once again a simple search and replace to add parentheses around any print statements. For example;
print self.parent.__class__
becomes
print(self.parent.__class__)
Final test and all is well, except for the whole Login failure issue, but at this point that’s expected behaviour. I know I could have also just run 2to3 on api.py which would perform all the necessary conversions for me, but I wanted to test my knowledge of Python 3. I did however run 2to3 to check my work and the only suggestion it made was to change import urllib for the more specific import urllib.request, urllib.parse, urllib.error. Not a bad effort for someone whose was new to python only 2 weeks ago.
Quick update: Seems there might be another api wrapper for Paymo although a little crude it might work better (well work at all), I might have to give it a go tomorrow.