piranha/opster — Issue #5: py3k
Author: oscarbenjamin
Created: 2011-10-30 21:30:16+00:00
State: open

I've been porting some of my scripts over to python 3. One big problem in doing this is that opster does not seem to be ported yet. I have attached a patch that should enable opster to install on python 2.x and 3.x using distutils and the 2to3 tool.

The only problem that is not fixable by the 2to3 tool as far as I can tell is the `write` function. This function explicitly calls `encode` on `unicode` strings. I think that, in python 3.x, this is unnecessary since encoding and decoding of unicode strings is automatic when writing to a "text file". I've just added a check for the python version to ensure that this call to encode is only carried out in python 2.x.

The other issue is that python3 cannot import the 2.x version of opster when running setup.py to build the 3.x version. To solve this, I've replaced the import opster line with a function that reads the contents of opster.py into a string and uses a regex to find `__version__` etc.

Otherwise everything works fine, except that I used distutils rather than setuptools. Is there a reason for using setuptools rather than distutils? On my system it prevented me from immediately being able to install the latest version of opster (rather than ubuntu's one), since setuptools was not installed. This dependency on setuptools will be more important if the module actually needs to be built with 2to3 rather than simply copied.

```diff
diff --git a/opster.py b/opster.py
index 026d509..eb7ce46 100644
--- a/opster.py
+++ b/opster.py
@@ -24,8 +24,8 @@ except locale.Error:
def write(text, out=None):
'''Write output to a given stream (stdout by default)'''
out = out or sys.stdout
- if isinstance(text, unicode):
- return out.write(text.encode(ENCODING))
+ if sys.version_info < (3, 0) and isinstance(text, unicode):
+ text = text.encode(ENCODING)
out.write(text)

def err(text):
diff --git a/setup.py b/setup.py
index c06af0f..b9d9153 100755
--- a/setup.py
+++ b/setup.py
@@ -1,8 +1,15 @@
#!/usr/bin/env python

-import os
-from setuptools import setup
-import opster
+import os, re
+
+from distutils.core import setup
+
+# Use 2to3 build conversion if required
+try:
+ from distutils.command.build_py import build_py_2to3 as build_py
+except ImportError:
+ # 2.x
+ from distutils.command.build_py import build_py

def read(fname):
return open(os.path.join(os.path.dirname(__file__), fname)).read()
@@ -15,14 +22,21 @@ def desc():
# no docs
return info

+# grep opster.py since python 3.x cannot import it before using 2to3
+opster_text = read('opster.py')
+def grep_opsterpy(attrname):
+ pattern = r"{0}\W*=\W*'([^']+)'".format(attrname)
+ strval, = re.findall(pattern, opster_text)
+ return strval
+
setup(
name = 'opster',
description = 'command line parsing speedster',
long_description = desc(),
license = 'BSD',
- version = opster.__version__,
- author = opster.__author__,
- author_email = opster.__email__,
+ version = grep_opsterpy('__version__'),
+ author = grep_opsterpy('__author__'),
+ author_email = grep_opsterpy('__email__'),
url = 'http://github.com/piranha/opster/',
classifiers = [
'Environment :: Console',
@@ -34,4 +48,5 @@ setup(
],
py_modules = ['opster'],
platforms='any',
+ cmdclass={'build_py':build_py}
)
```