diff --git a/Python3.md b/Python3.md new file mode 100644 index 0000000..94352e8 --- /dev/null +++ b/Python3.md @@ -0,0 +1,56 @@ +# Porting to Python 3 + +This is still a proposal at this stage. + +## Motivation + +* Make code behave the same on Python 2 and Python 3, insofar as one can, so e.g. `map()` is the same on Python 2 and Python 3 (i.e. lazy). +* Reduce errors by relying on Python 2 behavior and tests as well as manual review. +* Try to reduce grunt work. + +## How to choose a module to port + +TBD, something involving core abstractions first, then dependency graph topological traversal. + +Assume for now we've picked a module. + +## The porting process, big picture + +For a module M, there is also a corresponding module T, the unittests for M. +If the tests for M are embedded into a module that tests multiple modules, step one is to split off the tests so there's T that only tests M. + +Then: + +1. Update T to run on both 2+3 (see below for what that looks like). +2. Run T's tests on Python 2. They should still pass! If they don’t, something broke. +3. Port the code module M. +4. Now run T's tests on Python 3. +5. Fix any problems caught by the tests. +6. Add both M and T to `allmydata/util/_python3.py`. +7. Submit for code review. + + +### Porting a specific Python file + +**First**, add explicit byte or unicode annotations for strings where needed. + +**Second**, run `futurize --write --both-stages --all-imports path/to/file.py`. + +**Third**, replace the `from builtins import *` variant, if any, with: + +```#!python +from future.utils import PY2 +if PY2: + from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, int, list, object, range, str, max, min # noqa: F401 +``` + +This adds builtins that match Python 3's semantics. The `#noqa: F401` keeps flake8/pyflakes from complaining about unused imports. We do unused imports so that people changing code later don't have to manually check if `map()` is old style or new style. + +**Fourth**, manually review the code. Futureize is nice, but it very definitely doesn't catch everything, or it makes wrong decisions. + +In particular: + +* `map()`, `filter()`, etc. are now lazy. +* `dict.keys()` and friends now return a view of the underlying data, rather than a list with a copy. + +**Fifth**, add a note to the module docstring saying it was ported to Python 3. \ No newline at end of file