Thanks to visit codestin.com
Credit goes to github.com

Skip to content

MAINT: Lazy import testing on python >=3.7 #14097

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

Merged
merged 2 commits into from
Aug 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions numpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@
# now that numpy modules are imported, can initialize limits
core.getlimits._register_known_types()

__all__.extend(['bool', 'int', 'float', 'complex', 'object', 'unicode',
'str'])
Comment on lines +169 to +170
Copy link
Member

Choose a reason for hiding this comment

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

This looks like a mistake to me - removed in #14881

__all__.extend(['__version__', 'show_config'])
__all__.extend(core.__all__)
__all__.extend(_mat.__all__)
Expand All @@ -182,9 +184,35 @@
oldnumeric = 'removed'
numarray = 'removed'

# We don't actually use this ourselves anymore, but I'm not 100% sure that
# no-one else in the world is using it (though I hope not)
from .testing import Tester
if sys.version_info[:2] >= (3, 7):
# Importing Tester requires importing all of UnitTest which is not a
# cheap import Since it is mainly used in test suits, we lazy import it
# here to save on the order of 10 ms of import time for most users
#
# The previous way Tester was imported also had a side effect of adding
# the full `numpy.testing` namespace
#
# module level getattr is only supported in 3.7 onwards
# https://www.python.org/dev/peps/pep-0562/
def __getattr__(attr):
if attr == 'testing':
import numpy.testing as testing
return testing
elif attr == 'Tester':
from .testing import Tester
return Tester
else:
raise AttributeError(
"module %s has no attribute $s".format(__name__, attr))


def __dir__():
return __all__ + ['Tester', 'testing']

else:
# We don't actually use this ourselves anymore, but I'm not 100% sure that
# no-one else in the world is using it (though I hope not)
from .testing import Tester

# Pytest testing
from numpy._pytesttester import PytestTester
Expand Down
23 changes: 23 additions & 0 deletions numpy/tests/test_public_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import division, absolute_import, print_function

import sys
import subprocess

import numpy as np
import pytest
Expand Down Expand Up @@ -69,6 +70,28 @@ def test_numpy_namespace():
assert bad_results == whitelist


@pytest.mark.parametrize('name', ['testing', 'Tester'])
def test_import_lazy_import(name):
"""Make sure we can actually the the modules we lazy load.

While not exported as part of the public API, it was accessible. With the
use of __getattr__ and __dir__, this isn't always true It can happen that
an infinite recursion may happen.

This is the only way I found that would force the failure to appear on the
badly implemented code.

We also test for the presence of the lazily imported modules in dir

"""
exe = (sys.executable, '-c', "import numpy; numpy." + name)
result = subprocess.check_output(exe)
assert not result

# Make sure they are still in the __dir__
assert name in dir(np)


def test_numpy_linalg():
bad_results = check_dir(np.linalg)
assert bad_results == {}
Expand Down