Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Python 3 #4

Merged
merged 6 commits into from
Feb 2, 2018
Merged

Support for Python 3 #4

merged 6 commits into from
Feb 2, 2018

Conversation

george-hopkins
Copy link
Contributor

@george-hopkins george-hopkins commented Jan 9, 2017

This PR implements support for Python 3. As I'm not very familiar with whole code base, I would be glad to receive some feedback if everything still works as expected. All unit tests pass on 2.7, 3.3 and 3.5. In addition the decoding was tested against an other implementation.

@george-hopkins
Copy link
Contributor Author

@daira Thanks for reviewing! I updated the code accordingly. Please feel free to comment if you find any further issues.

It seems that the comments don't show up here as they were made before this PR was created.

Copy link

@ThomasWaldmann ThomasWaldmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: I am not a project member, just potentially interested in zfec, should it support python 3.x some day.

.travis.yml Outdated
- "2.6"
- "2.7"
- "3.3"
- "3.5"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no 3.4 and 3.6?

README.rst Outdated
@@ -261,7 +261,8 @@ Dependencies

A C compiler is required. To use the Python API or the command-line tools a
Python interpreter is also required. We have tested it with Python v2.4,
v2.5, v2.6, and v2.7. For the Haskell interface, GHC >= 6.8.1 is required.
v2.5, v2.6, v2.7, v3.3 and v3.5. For the Haskell interface, GHC >= 6.8.1 is

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3.4? 3.6?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as travis is only testing >= 2.6, I am asking myself whether the code has recently been tested on 2.4 and 2.5 (considering they are quite dead since long). this is just a general comment, not related to your PR.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update: code in this PR can't work on 2.4 / 2.5 (see below).

and there is no reason to support these dead versions today, so just remove all references from docs etc.

setup.py Outdated
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here we have 3.4 and 3.6. \o/

@@ -8,6 +8,8 @@
# This file is released into the public domain. Generated by
# versioneer-0.15 (https://github.com/warner/python-versioneer)

from __future__ import print_function

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://docs.python.org/2/library/__future__.html

if i understand that correctly, this will require python >= 2.6.0a2.

so, guess it's time to drop everything < 2.6.

and i'ld also drop 2.6 asap, more and more tools in the python world make troubles on 2.6, so even testing it is sometimes not that easy.

try:
unicode = unicode
except NameError:
unicode = str

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bit unusual. the recommended style of a port that works on python 3 and 2 is that code should look as in python3 (or somehow close) and/or be close to python3 semantics.

that makes it easier for the future (when nobody uses 2 any more and at some time, support for 2 will get removed).

I guess most people use something like this:

text_type = str  # python 3
text_type = unicode  # python 2

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, I'ld put such stuff into a _compat.py module, so it can be imported from there to anywhere it is needed.

same applies for:

bytes_type = bytes  # python 3
bytes_type = str  # python 2

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, we shouldn't be afraid to use six for this sort of compatibility stuff, it's pretty small and used by a lot of other packages (including Tahoe)

@@ -33,7 +33,7 @@ def encode(self, data):
reconstruct the input data
"""
chunksize = div_ceil(len(data), self.fec.k)
l = [ data[i*chunksize:(i+1)*chunksize] + "\x00" * min(chunksize, (((i+1)*chunksize)-len(data))) for i in range(self.fec.k) ]
l = [ data[i*chunksize:(i+1)*chunksize] + b"\x00" * min(chunksize, (((i+1)*chunksize)-len(data))) for i in range(self.fec.k) ]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

byte literals also will require 2.6.

try:
from cStringIO import StringIO
except ImportError:
from io import BytesIO as StringIO

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather use py3 names:

from cStringIO import StringIO as BytesIO  # py2
from io import BytesIO  # py3


def test_bad_args_construct_decoder(self):
try:
zfec.Decoder(-1, -1)
except zfec.Error, e:
except zfec.Error as e:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"except ... as ..." requires 2.6.

@@ -286,40 +293,40 @@ def _help_test_filefec(self, teststr, k, m, numshs=None):
tempdir.shutdown()

def test_filefec_all_shares(self):
return self._help_test_filefec("Yellow Whirled!", 3, 8)
return self._help_test_filefec(b"Yellow Whirled!", 3, 8)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe prettier than using b"..." at every place here would be to change self._help_test_filefec() to convert to bytes_type (which needs to be set up in a similar way as text_type, str for py2, bytes for py3).

.travis.yml Outdated
- "2.6"
- "2.7"
- "3.3"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, 3.3 is (as everything < 3.4) a slightly crappy python 3 version.
so, considering it's 2017 already, I'ld consider if it makes sense to start supporting it now.
everybody and his dog has 3.4+ nowadays and 3.4 has quite some important features and fixes for stuff still missing/broken in 3.3.

@@ -251,7 +253,7 @@ def decode_from_files(outf, infiles, verbose=False):
m = nm
if not (k is None or k == nk):
raise CorruptedShareFilesError("Share files were corrupted -- share file %r said that k was %s but another share file previously said that k was %s" % (f.name, nk, k,))
if k > len(infiles):
if not (k is None or k <= len(infiles)):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like a bugfix (not related to py3 porting), so likely it should live in a separate commit or even separate PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extra check is needed for Python 3 because int and None can't be compared anymore (unorderable types).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. It's probably still worth putting this in a separate commit (which should appear before the general port-to-py3 commits), since it fixes a non-py3-specific problem (comparing None against an integer doesn't make sense in py2 either, even if it's not treated as an error)

@george-hopkins
Copy link
Contributor Author

@ThomasWaldmann Thank you for putting so much effort in reviewing this pull-request! In retrospect, it might be more sensible to ditch Python 2 support altogether. This would simplify maintenance quite a bit.

@zooko, @vu3rdd What are your views on this proposal? I'm happy to address the issues mentioned as soon as possible if there is an interest in this PR in general.

@ThomasWaldmann
Copy link

@george-hopkins 2.7.x and 3.4+ are quite reasonable choices right now. YMMV. :)

else:
if padlen > 0:
outf.truncate(byteswritten - padlen)
return # Done.
if verbose:
print
print "Done!"
print()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is done to get "Done!" printed on new line and can be replaced with single statement like below

print("\nDone!")

@warner
Copy link
Member

warner commented Jul 15, 2017

Yay for py3 support! I'd second @ThomasWaldmann suggestion to go with 2.7 and >=3.3 or >=3.4. I'm particularly keen to maintain 2.7 support because Tahoe-LAFS is still 2.7-only, and I think Tahoe remains the largest customer of zfec.

@warner
Copy link
Member

warner commented Jul 16, 2017

I'll definitely land this once it's ready. Some ideas for a rewritten branch:

  • start with a commit that removes support for py2.4/2.5 (which I think just means changing setup.py's metadata claims)
  • then a commit that switches from absolute imports to relative imports
  • then one to fix that compare-int-vs-None problem
  • then some commits to replace the py3-incompatible syntax issues: print functions, "except X,y" -> "except X as y". This is a good place to add from __future__ import lines
  • then a commit to add six and maybe change some of the bytes/unicodes to use it. Also things like changing import cStringIO to use the six.moves equivalent
  • then fix the rest of the py3 incompatibilities
  • then finally add py3 to setup.py and travis and tox

The general idea is the tree should build and test correctly after every commit. But I'll be ok if it doesn't actually achieve that, as long as the sequence is fairly easy to follow,

That travis line that installs pyutil from a git repo.. what's that for? I want to get rid of that. Do we need a new pyutil release with something fixed? What do we need pyutil for anyways? (I vaguely remember talking with zooko a long while back about maybe splitting the CLI utilities out of zfec and into a separate package, because I seem to remember that pyutil was only needed for the CLI tools).

@george-hopkins
Copy link
Contributor Author

@warner Thank you for your feedback! I'm happy to incorporate the suggested changes if the PR has a chance of getting merged.

As for pyutil: As pyutil needs to be ported to Python 3 as well, I created zooko/pyutil#4. If you can help to get it merged, that would be great! As soon as it's merged, we can get rid of the include from my personal repository here (used it to see if Travis succeeds on all versions).

@sbellem
Copy link

sbellem commented Oct 17, 2017

May we just know whether there are near-term plans to move this PR forward and eventually merge it?

I could provide some help if needed.

@tpltnt
Copy link

tpltnt commented Jan 11, 2018

I am waiting for @george-hopkins to do the PR for Python 3 support against my fork so I can build and push to pypi. This would remove the major blocker and move the Python 3 port of zfec forward.

@tpltnt
Copy link

tpltnt commented Jan 12, 2018

I am happy to announce pyutil version 3.0.0 now supports Python 3 thanks to @george-hopkins . The module is already published on pypi.

@george-hopkins george-hopkins changed the title [WIP] Support for Python 3 Support for Python 3 Jan 12, 2018
@george-hopkins
Copy link
Contributor Author

With the new release of pyutil (thanks to @tpltnt!) the patch is now ready to be reviewed. The updated patch already includes some fixes for the issues mentioned earlier.

@tpltnt
Copy link

tpltnt commented Jan 12, 2018

The code looks good to me.

@nimamox
Copy link

nimamox commented Feb 2, 2018

Has it been merged to the main branch? I couldn't use pip3 to install zfec.
EDIT: I get an error during compilation on macOS from @george-hopkins fork.

$ pip3 install git+https://github.com/george-hopkins/zfec
...
    zfec/_fecmodule.c:633:12: warning: incompatible integer to pointer conversion assigning to 'PyObject *' (aka 'struct _object *') from 'int' [-Wint-conversion]
        module = Py_InitModule3("_fec", fec_functions, fec__doc__);
               ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    zfec/_fecmodule.c:635:7: error: non-void function 'init_fec' should return a value [-Wreturn-type]
          return;
          ^
    33 warnings and 5 errors generated.
    error: command 'clang' failed with exit status 1

@warner
Copy link
Member

warner commented Feb 2, 2018

Looks good to me, local tests pass on macOS. There's a problem with extending tox to include py3 (the "trialcoverage" dependency doesn't work on py3), but we can fix that later. Will land momentarily. Thanks everyone!

@warner warner merged commit 4f046fa into tahoe-lafs:master Feb 2, 2018
@george-hopkins
Copy link
Contributor Author

@warner Thank you for merging and the clean up you had to do before the release!

@nimamox I kept my porting efforts in a separate branch "python3". However, with the new release you can simply install it with pip install zfec.

@george-hopkins george-hopkins deleted the python3 branch February 3, 2018 09:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants