diff --git a/contrib/import-checker.py b/contrib/import-checker.py --- a/contrib/import-checker.py +++ b/contrib/import-checker.py @@ -411,7 +411,8 @@ assign the symbol to a module-level variable. In addition, these imports must be performed before other local imports. This rule only applies to import statements outside of any blocks. - * Relative imports from the standard library are not allowed. + * Relative imports from the standard library are not allowed, unless that + library is also a local module. * Certain modules must be aliased to alternate names to avoid aliasing and readability problems. See `requirealias`. """ @@ -493,7 +494,10 @@ # __future__ is special since it needs to come first and use # symbol import. if fullname != '__future__': - if not fullname or fullname in stdlib_modules: + if not fullname or ( + fullname in stdlib_modules + and fullname not in localmods + and fullname + '.__init__' not in localmods): yield msg('relative import of stdlib module') else: seenlocal = fullname diff --git a/tests/test-imports-checker.t b/tests/test-imports-checker.t --- a/tests/test-imports-checker.t +++ b/tests/test-imports-checker.t @@ -125,7 +125,19 @@ > from mercurial.node import hex > EOF - $ $PYTHON "$import_checker" testpackage*/*.py testpackage/subpackage/*.py +# Shadowing a stdlib module to test "relative import of stdlib module" is +# allowed if the module is also being checked + + $ mkdir email + $ touch email/__init__.py + $ touch email/errors.py + $ cat > email/utils.py << EOF + > from __future__ import absolute_import + > from . import errors + > EOF + + $ $PYTHON "$import_checker" testpackage*/*.py testpackage/subpackage/*.py \ + > email/*.py testpackage/importalias.py:2: ui module must be "as" aliased to uimod testpackage/importfromalias.py:2: ui from testpackage must be "as" aliased to uimod testpackage/importfromrelative.py:2: import should be relative: testpackage.unsorted