ai-content-maker/.venv/Lib/site-packages/numba/tests/test_config.py

209 lines
7.5 KiB
Python
Raw Normal View History

2024-05-03 04:18:51 +03:00
import os
import tempfile
from textwrap import dedent
import unittest
from unittest import mock
from numba.tests.support import (TestCase, temp_directory, override_env_config,
run_in_subprocess)
from numba.core import config
try:
import yaml
_HAVE_YAML = True
except ImportError:
_HAVE_YAML = False
_skip_msg = "pyyaml needed for configuration file tests"
needs_yaml = unittest.skipIf(not _HAVE_YAML, _skip_msg)
@needs_yaml
class TestConfig(TestCase):
# Disable parallel testing due to envvars modification
_numba_parallel_test_ = False
def setUp(self):
# use support.temp_directory, it can do the clean up
self.tmppath = temp_directory('config_tmp')
self.maxDiff = 2500
super(TestConfig, self).setUp()
def mock_cfg_location(self):
"""
Creates a mock launch location.
Returns the location path.
"""
return tempfile.mkdtemp(dir=self.tmppath)
def inject_mock_cfg(self, location, cfg):
"""
Injects a mock configuration at 'location'
"""
tmpcfg = os.path.join(location, config._config_fname)
with open(tmpcfg, 'wt') as f:
yaml.dump(cfg, f, default_flow_style=False)
def get_settings(self):
"""
Gets the current numba config settings
"""
store = dict()
for x in dir(config):
if x.isupper():
store[x] = getattr(config, x)
return store
def create_config_effect(self, cfg):
"""
Returns a config "original" from a location with no config file
and then the impact of applying the supplied cfg dictionary as
a config file at a location in the returned "current".
"""
# store original cwd
original_cwd = os.getcwd()
# create mock launch location
launch_dir = self.mock_cfg_location()
# switch cwd to the mock launch location, get and store settings
os.chdir(launch_dir)
# use override to ensure that the config is zero'd out with respect
# to any existing settings
with override_env_config('_', '_'):
original = self.get_settings()
# inject new config into a file in the mock launch location
self.inject_mock_cfg(launch_dir, cfg)
try:
# override something but don't change the value, this is to refresh
# the config and make sure the injected config file is read
with override_env_config('_', '_'):
current = self.get_settings()
finally:
# switch back to original dir with no new config
os.chdir(original_cwd)
return original, current
def test_config(self):
# ensure a non empty settings file does impact config and that the
# case of the key makes no difference
key = 'COLOR_SCHEME'
for case in [str.upper, str.lower]:
orig, curr = self.create_config_effect({case(key): 'light_bg'})
self.assertTrue(orig != curr)
self.assertTrue(orig[key] != curr[key])
self.assertEqual(curr[key], 'light_bg')
# check that just the color scheme is the cause of difference
orig.pop(key)
curr.pop(key)
self.assertEqual(orig, curr)
def test_empty_config(self):
# ensure an empty settings file does not impact config
orig, curr = self.create_config_effect({})
self.assertEqual(orig, curr)
def test_illegal_error_style_handling(self):
# ensure that illegal error styles are ignored
new_env = os.environ.copy()
new_env['NUMBA_CAPTURED_ERRORS'] = 'not_a_known_style'
source_compiled = "the source compiled"
code = ("from numba import njit\n@njit\ndef foo():\n\t"
f"print('{source_compiled}')\nfoo()")
out, err = run_in_subprocess(dedent(code), env=new_env)
expected = ("Environment variable \'NUMBA_CAPTURED_ERRORS\' is defined "
"but its associated value \'not_a_known_style\' could not "
"be parsed.")
err_msg = err.decode('utf-8')
self.assertIn(expected, err_msg)
ex_expected = ("Invalid style in NUMBA_CAPTURED_ERRORS: "
"not_a_known_style")
self.assertIn(ex_expected, err_msg)
self.assertIn(source_compiled, out.decode('utf-8'))
class TestNumbaOptLevel(TestCase):
# Tests that the setting of NUMBA_OPT influences the "cheap" module pass.
# Spot checks NUMBA_OPT={'max', '3', '0'}
def check(self, expected, opt_value, raw_value):
# local imports for state-safety
from numba import config, njit
# check opt value and its raw_value
self.assertEqual(config.OPT, opt_value)
self.assertEqual(config.OPT._raw_value, raw_value)
# Patch the CPUCodegen to make capture calls to the
# `_module_pass_manager` through a `side_effect` function that asserts
# that the kwargs being passed are as expected per the "NUMBA_OPT"
# level. The `side_effect` function immediately raises with a knwon
# message to abort further stages compilation once the check is
# complete.
from numba.core.codegen import CPUCodegen
side_effect_message = "expected side effect"
def side_effect(*args, **kwargs):
self.assertEqual(kwargs, expected)
raise RuntimeError(side_effect_message)
with mock.patch.object(CPUCodegen, '_module_pass_manager',
side_effect=side_effect):
with self.assertRaises(RuntimeError) as raises:
njit(lambda : ...)()
self.assertIn(side_effect_message, str(raises.exception))
@TestCase.run_test_in_subprocess(envvars={'NUMBA_OPT': 'max'})
def test_opt_max(self):
# NUMBA_OPT='max' should set opt to 3 and enable loop_vectorize
expected = {'loop_vectorize': True,
'slp_vectorize': False,
'opt': 3,
'cost': 'cheap'}
self.check(expected, 3, 'max')
@TestCase.run_test_in_subprocess(envvars={'NUMBA_OPT': '3'})
def test_opt_3(self):
# NUMBA_OPT='3' should not impact opt or loop_vectorize
expected = {'loop_vectorize': False,
'slp_vectorize': False,
'opt': 0,
'cost': 'cheap'}
self.check(expected, 3, 3)
@TestCase.run_test_in_subprocess(envvars={'NUMBA_OPT': '0'})
def test_opt_0(self):
# NUMBA_OPT='0' should not impact opt or loop_vectorize
expected = {'loop_vectorize': False,
'slp_vectorize': False,
'opt': 0,
'cost': 'cheap'}
self.check(expected, 0, 0)
@TestCase.run_test_in_subprocess()
def test_opt_default(self):
# NUMBA_OPT is not set, the default should not impact opt or
# loop_vectorize
expected = {'loop_vectorize': False,
'slp_vectorize': False,
'opt': 0,
'cost': 'cheap'}
self.check(expected, 3, 3)
@TestCase.run_test_in_subprocess(envvars={'NUMBA_OPT': 'invalid'})
def test_opt_invalid(self):
# NUMBA_OPT='invalid' should just proceed as default case
expected = {'loop_vectorize': False,
'slp_vectorize': False,
'opt': 0,
'cost': 'cheap'}
self.check(expected, 3, 3)
if __name__ == '__main__':
unittest.main()