Differences between revisions 37 and 38
Revision 37 as of 2019-03-05 20:36:31
Size: 2242
Editor: PulkitGoyal
Comment: curses works now on py3
Revision 38 as of 2019-04-21 15:35:22
Size: 5268
Editor: GregorySzorc
Comment: add section on porting extensions
Deletions are marked like this. Additions are marked like this.
Line 39: Line 39:
== Porting Extensions to Python 3 ==

Nearly every extension will need to be ported to be compatible with Python 3. This is because of fundamental differences between Python 2 and Python 3.

The source code for Mercurial extensions will need to be Python 3 native and will need to be compatible with Mercurial's APIs. In many cases, existing source code will compile on Python 3 but will fail at run-time. Sources of run-time errors include:

 * Use of `str` instead of `bytes`. Mercurial uses `bytes` (`b''` strings) in almost all of its APIs and data structures. This is in contrast to much Python code, which uses `str` and `''` strings. It is common for extensions to `b''` prefix most strings in order to remain compatible with Mercurial.
 * Use of `iteritems()`, `iterkeys()`, etc. These methods from core data structures do not exist in Python 3.
 * Import of renamed modules. Python 3 refactored the locations of various modules in the Python standard library. Extensions may need to take this into account.

Do an Internet search for ''Python 3 porting'' to find well-written and comprehensive guides on generically porting code to Python 3.

Extension authors may find the ``mercurial.pycompat`` module useful. This modules contains abstractions and utilities for bridging the differences between Python 2 and 3. It is conceptually similar to the `six` Python module.

As of at least the Mercurial 5.0 release, Mercurial uses a custom module importer on Python 3 which rewrites source code dynamically as part of importing modules. This module importer is only active for the `mercurial`, `hgext`, and `hgext3rd` packages. '''Extension loading does not use this custom importer.''' This means that Mercurial's own source code and extensions are not yet native Python 3 source code. So if you look at Mercurial's source code for ideas on how to do something in an extension, behavior in the extension may differ from Mercurial itself due to the presence of this custom module importer. For reference, in the 5.0 release, the custom module importer performs the following actions:

 * Automatically adds `b''` prefixes to strings, making all `''` literals `b''` and effectively changing `str` to `bytes` everywhere. i.e. behavior mostly matches Python 2.
 * Modules automatically have `from mercurial.pycompat import delattr, getattr, hasattr, setattr, open, unicode` added.
 * `getattr()`, `setattr()`, `hasattr()`, `safehasattr()`, `encode()`, and `decode()` functions and methods have string literals in arguments rewritten to the appropriate type because Python requires a `str` value instead of `bytes`. (This effectively selectively undoes the global `''` to `b''` source transformation.)
 * `iteritems()` and `itervalues()` are automatically rewritten to `items()` and `values()`, respectively.

The source rewriting module importer is intended to be a stop-gap to make porting Mercurial to Python 3 simpler and will be removed in a future release. This is why extensions do not use it.

Note:

This page is primarily intended for developers of Mercurial.

Python 3

This is a status page for keeping track of what needs to be done to make progress on Mercurial on Python 3. Our current aim is to support Python 3.5+.

1. Status

We have been testing by installing default mercurial on our system using Python 3. Most of the things work correctly. Things which don't work can be found at BetaBugs section below.

We are planning to mark hg 5.0 which is scheduled for May 1 as Python 3 beta release.

If you are an extension author and want to port the extension, https://www.mercurial-scm.org/repo/hg-committed/file/tip/mercurial/pycompat.py contains most of our compatibility hacks. If you need help or guidance, you can message on IRC or devel mailing list. We will be happy to help you.

2. Things need to be investigated

  • Windows encoding changes

    https://docs.python.org/3/whatsnew/3.6.html#pep-529-change-windows-filesystem-encoding-to-utf-8

  • Lazy importer performance overhead. Our custom importer on Python 2 always returns a stub module during import. Python 3's does I/O to verify the module exists then returns a lazy module that is loaded when first accessed. In addition to behavior differences, the I/O may contribute sufficient performance overhead to constitute a problem.

  • A mechanism for extensions to advertise that they are Python 3 compatible. Nearly every extension will break in Python 3. We may want a mechanism that requires extensions to self-declare that they are Python 3 compatible - possibly via special syntax in their source code or the presence of a well-named variable. It might have to be at the source level because Python 3 would need to evaluate code in order to obtain the value of a module-level variable.

3. Beta bugs

Following are things which don't work right now:

If you find anything apart from this not working, definitely go ahead and edit this page and we will fix it.

4. Porting Extensions to Python 3

Nearly every extension will need to be ported to be compatible with Python 3. This is because of fundamental differences between Python 2 and Python 3.

The source code for Mercurial extensions will need to be Python 3 native and will need to be compatible with Mercurial's APIs. In many cases, existing source code will compile on Python 3 but will fail at run-time. Sources of run-time errors include:

  • Use of str instead of bytes. Mercurial uses bytes (b'' strings) in almost all of its APIs and data structures. This is in contrast to much Python code, which uses str and '' strings. It is common for extensions to b'' prefix most strings in order to remain compatible with Mercurial.

  • Use of iteritems(), iterkeys(), etc. These methods from core data structures do not exist in Python 3.

  • Import of renamed modules. Python 3 refactored the locations of various modules in the Python standard library. Extensions may need to take this into account.

Do an Internet search for Python 3 porting to find well-written and comprehensive guides on generically porting code to Python 3.

Extension authors may find the mercurial.pycompat module useful. This modules contains abstractions and utilities for bridging the differences between Python 2 and 3. It is conceptually similar to the six Python module.

As of at least the Mercurial 5.0 release, Mercurial uses a custom module importer on Python 3 which rewrites source code dynamically as part of importing modules. This module importer is only active for the mercurial, hgext, and hgext3rd packages. Extension loading does not use this custom importer. This means that Mercurial's own source code and extensions are not yet native Python 3 source code. So if you look at Mercurial's source code for ideas on how to do something in an extension, behavior in the extension may differ from Mercurial itself due to the presence of this custom module importer. For reference, in the 5.0 release, the custom module importer performs the following actions:

  • Automatically adds b'' prefixes to strings, making all '' literals b'' and effectively changing str to bytes everywhere. i.e. behavior mostly matches Python 2.

  • Modules automatically have from mercurial.pycompat import delattr, getattr, hasattr, setattr, open, unicode added.

  • getattr(), setattr(), hasattr(), safehasattr(), encode(), and decode() functions and methods have string literals in arguments rewritten to the appropriate type because Python requires a str value instead of bytes. (This effectively selectively undoes the global '' to b'' source transformation.)

  • iteritems() and itervalues() are automatically rewritten to items() and values(), respectively.

The source rewriting module importer is intended to be a stop-gap to make porting Mercurial to Python 3 simpler and will be removed in a future release. This is why extensions do not use it.


CategoryAudit

Python3 (last edited 2023-02-19 16:08:38 by AntonShestakov)