diff --git a/contrib/check-py3-compat.py b/contrib/check-py3-compat.py --- a/contrib/check-py3-compat.py +++ b/contrib/check-py3-compat.py @@ -14,6 +14,16 @@ import os import sys import traceback +# Modules that have both Python and C implementations. +_dualmodules = ( + 'base85.py', + 'bdiff.py', + 'diffhelpers.py', + 'mpatch.py', + 'osutil.py', + 'parsers.py', +) + def check_compat_py2(f): """Check Python 3 compatibility for a file with Python 2""" with open(f, 'rb') as fh: @@ -55,7 +65,9 @@ def check_compat_py3(f): # out module paths for things not in a package can be confusing. if f.startswith(('hgext/', 'mercurial/')) and not f.endswith('__init__.py'): assert f.endswith('.py') - name = f.replace('/', '.')[:-3].replace('.pure.', '.') + name = f.replace('/', '.')[:-3] + if f.endswith(_dualmodules): + name = name.replace('.pure.', '.') try: importlib.import_module(name) except Exception as e: diff --git a/contrib/import-checker.py b/contrib/import-checker.py --- a/contrib/import-checker.py +++ b/contrib/import-checker.py @@ -24,6 +24,16 @@ allowsymbolimports = ( 'mercurial.node', ) +# Modules that have both Python and C implementations. +_dualmodules = ( + 'base85.py', + 'bdiff.py', + 'diffhelpers.py', + 'mpatch.py', + 'osutil.py', + 'parsers.py', +) + # Modules that must be aliased because they are commonly confused with # common variables and can create aliasing and readability issues. requirealias = { @@ -691,7 +701,8 @@ def main(argv): used_imports = {} any_errors = False for source_path in argv[1:]: - modname = dotted_name_of_path(source_path, trimpure=True) + trimpure = source_path.endswith(_dualmodules) + modname = dotted_name_of_path(source_path, trimpure=trimpure) localmods[modname] = source_path for localmodname, source_path in sorted(localmods.items()): for src, modname, name, line in sources(source_path, localmodname): diff --git a/mercurial/__init__.py b/mercurial/__init__.py --- a/mercurial/__init__.py +++ b/mercurial/__init__.py @@ -165,7 +165,8 @@ if sys.version_info[0] >= 3: if not spec: return None - if fullname.startswith('mercurial.pure.'): + if (fullname.startswith('mercurial.pure.') + and fullname.replace('.pure.', '.') in _dualmodules): spec.name = spec.name.replace('.pure.', '.') # TODO need to support loaders from alternate specs, like zip