Skip to content

Commit 4cecba5

Browse files
authored
Merge pull request #6794 from Alexander-Makaryev/refactor-create-temp-module
refactor and move create_temp_module into numba.tests.support
2 parents 11b70f5 + 168d6a1 commit 4cecba5

4 files changed

Lines changed: 62 additions & 114 deletions

File tree

‎numba/tests/support.py‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import warnings
2121
import traceback
2222
from contextlib import contextmanager
23+
import uuid
24+
import importlib
2325

2426
import numpy as np
2527

@@ -878,3 +880,44 @@ def check_warnings(self, messages, category=RuntimeWarning):
878880
self.assertEqual(w.category, category)
879881
found += 1
880882
self.assertEqual(found, len(messages))
883+
884+
885+
def _format_jit_options(**jit_options):
886+
if not jit_options:
887+
return ''
888+
out = []
889+
for key, value in jit_options.items():
890+
if isinstance(value, str):
891+
value = '"{}"'.format(value)
892+
out.append('{}={}'.format(key, value))
893+
return ', '.join(out)
894+
895+
896+
@contextlib.contextmanager
897+
def create_temp_module(source_lines, **jit_options):
898+
"""A context manager that creates and imports a temporary module
899+
from sources provided in ``source_lines``.
900+
901+
Optionally it is possible to provide jit options for ``jit_module`` if it
902+
is explicitly used in ``source_lines`` like ``jit_module({jit_options})``.
903+
"""
904+
# Use try/finally so cleanup happens even when an exception is raised
905+
try:
906+
tempdir = temp_directory('test_temp_module')
907+
# Generate random module name
908+
temp_module_name = 'test_temp_module_{}'.format(
909+
str(uuid.uuid4()).replace('-', '_'))
910+
temp_module_path = os.path.join(tempdir, temp_module_name + '.py')
911+
912+
jit_options = _format_jit_options(**jit_options)
913+
with open(temp_module_path, 'w') as f:
914+
lines = source_lines.format(jit_options=jit_options)
915+
f.write(lines)
916+
# Add test_module to sys.path so it can be imported
917+
sys.path.insert(0, tempdir)
918+
test_module = importlib.import_module(temp_module_name)
919+
yield test_module
920+
finally:
921+
sys.modules.pop(temp_module_name, None)
922+
sys.path.remove(tempdir)
923+
shutil.rmtree(tempdir)

‎numba/tests/test_array_exprs.py‎

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from numba import typeof
88
from numba.core import utils, types, typing, ir, compiler, cpu, cgutils
99
from numba.core.compiler import Compiler, Flags
10-
from numba.tests.support import MemoryLeakMixin, TestCase, temp_directory
10+
from numba.tests.support import (MemoryLeakMixin, TestCase, temp_directory,
11+
create_temp_module)
1112
from numba.extending import (
1213
overload,
1314
models,
@@ -18,12 +19,6 @@
1819
typeof_impl
1920
)
2021
import operator
21-
import contextlib
22-
import importlib
23-
import shutil
24-
import uuid
25-
import os
26-
import sys
2722
import textwrap
2823

2924
import unittest
@@ -657,31 +652,6 @@ def __init__(self):
657652
super(FooType, self).__init__(name='Foo')
658653
""")
659654

660-
# copied from test_types
661-
@contextlib.contextmanager
662-
def create_temp_module(self, source_lines=None, **jit_options):
663-
# Use try/finally so cleanup happens even when an exception is raised
664-
try:
665-
if source_lines is None:
666-
source_lines = self.source_lines
667-
tempdir = temp_directory('test_extension_type')
668-
# Generate random module name
669-
temp_module_name = 'test_extension_type_{}'.format(
670-
str(uuid.uuid4()).replace('-', '_'))
671-
temp_module_path = os.path.join(tempdir, temp_module_name + '.py')
672-
673-
with open(temp_module_path, 'w') as f:
674-
lines = source_lines.format(jit_options=jit_options)
675-
f.write(lines)
676-
# Add test_module to sys.path so it can be imported
677-
sys.path.insert(0, tempdir)
678-
test_module = importlib.import_module(temp_module_name)
679-
yield test_module
680-
finally:
681-
sys.modules.pop(temp_module_name, None)
682-
sys.path.remove(tempdir)
683-
shutil.rmtree(tempdir)
684-
685655
def make_foo_type(self, FooType):
686656
class Foo(object):
687657
def __init__(self, value):
@@ -717,7 +687,7 @@ def typeof_foo(val, c):
717687
return Foo, FooType
718688

719689
def test_external_type(self):
720-
with self.create_temp_module(self.source_lines) as test_module:
690+
with create_temp_module(self.source_lines) as test_module:
721691
Foo, FooType = self.make_foo_type(test_module.FooType)
722692

723693
# sum of foo class instance and array return an array

‎numba/tests/test_jit_module.py‎

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
import os
22
import sys
3-
import shutil
43
import inspect
5-
import importlib
64
import contextlib
7-
import uuid
85
import numpy as np
96
import logging
107
from io import StringIO
118

129
import unittest
13-
from numba.tests.support import temp_directory, SerialMixin
10+
from numba.tests.support import SerialMixin, create_temp_module
1411
from numba.core import dispatcher
1512

1613

@@ -49,45 +46,10 @@ class Foo(object):
4946
jit_module({jit_options})
5047
"""
5148

52-
def _format_jit_options(self, **jit_options):
53-
if not jit_options:
54-
return ''
55-
out = []
56-
for key, value in jit_options.items():
57-
if isinstance(value, str):
58-
value = '"{}"'.format(value)
59-
out.append('{}={}'.format(key, value))
60-
return ', '.join(out)
61-
62-
@contextlib.contextmanager
63-
def create_temp_jitted_module(self, source_lines=None, **jit_options):
64-
# Use try/finally so cleanup happens even when an exception is raised
65-
try:
66-
if source_lines is None:
67-
source_lines = self.source_lines
68-
tempdir = temp_directory('test_jit_module')
69-
# Generate random module name
70-
temp_module_name = 'test_module_{}'.format(
71-
str(uuid.uuid4()).replace('-', '_'))
72-
temp_module_path = os.path.join(tempdir, temp_module_name + '.py')
73-
74-
jit_options = self._format_jit_options(**jit_options)
75-
with open(temp_module_path, 'w') as f:
76-
lines = source_lines.format(jit_options=jit_options)
77-
f.write(lines)
78-
# Add test_module to sys.path so it can be imported
79-
sys.path.insert(0, tempdir)
80-
test_module = importlib.import_module(temp_module_name)
81-
yield test_module
82-
finally:
83-
sys.modules.pop(temp_module_name, None)
84-
sys.path.remove(tempdir)
85-
shutil.rmtree(tempdir)
86-
8749
def test_create_temp_jitted_module(self):
8850
sys_path_original = list(sys.path)
8951
sys_modules_original = dict(sys.modules)
90-
with self.create_temp_jitted_module() as test_module:
52+
with create_temp_module(self.source_lines) as test_module:
9153
temp_module_dir = os.path.dirname(test_module.__file__)
9254
self.assertEqual(temp_module_dir, sys.path[0])
9355
self.assertEqual(sys.path[1:], sys_path_original)
@@ -100,15 +62,15 @@ def test_create_temp_jitted_module_with_exception(self):
10062
try:
10163
sys_path_original = list(sys.path)
10264
sys_modules_original = dict(sys.modules)
103-
with self.create_temp_jitted_module():
65+
with create_temp_module(self.source_lines):
10466
raise ValueError("Something went wrong!")
10567
except ValueError:
10668
# Test that modifications to sys.path / sys.modules are reverted
10769
self.assertEqual(sys.path, sys_path_original)
10870
self.assertEqual(sys.modules, sys_modules_original)
10971

11072
def test_jit_module(self):
111-
with self.create_temp_jitted_module() as test_module:
73+
with create_temp_module(self.source_lines) as test_module:
11274
self.assertIsInstance(test_module.inc, dispatcher.Dispatcher)
11375
self.assertIsInstance(test_module.add, dispatcher.Dispatcher)
11476
self.assertIsInstance(test_module.inc_add, dispatcher.Dispatcher)
@@ -130,7 +92,8 @@ def test_jit_module_jit_options(self):
13092
"error_model": "numpy",
13193
"boundscheck": False,
13294
}
133-
with self.create_temp_jitted_module(**jit_options) as test_module:
95+
with create_temp_module(self.source_lines,
96+
**jit_options) as test_module:
13497
self.assertEqual(test_module.inc.targetoptions, jit_options)
13598

13699
def test_jit_module_jit_options_override(self):
@@ -150,8 +113,8 @@ def add(x, y):
150113
"error_model": "numpy",
151114
"boundscheck": False,
152115
}
153-
with self.create_temp_jitted_module(source_lines=source_lines,
154-
**jit_options) as test_module:
116+
with create_temp_module(source_lines=source_lines,
117+
**jit_options) as test_module:
155118
self.assertEqual(test_module.add.targetoptions, jit_options)
156119
# Test that manual jit-wrapping overrides jit_module options
157120
self.assertEqual(test_module.inc.targetoptions,
@@ -165,7 +128,8 @@ def test_jit_module_logging_output(self):
165128
"error_model": "numpy",
166129
}
167130
with captured_logs(logger) as logs:
168-
with self.create_temp_jitted_module(**jit_options) as test_module:
131+
with create_temp_module(self.source_lines,
132+
**jit_options) as test_module:
169133
logs = logs.getvalue()
170134
expected = ["Auto decorating function",
171135
"from module {}".format(test_module.__name__),
@@ -177,5 +141,5 @@ def test_jit_module_logging_level(self):
177141
# Test there's no logging for INFO level
178142
logger.setLevel(logging.INFO)
179143
with captured_logs(logger) as logs:
180-
with self.create_temp_jitted_module():
144+
with create_temp_module(self.source_lines):
181145
self.assertEqual(logs.getvalue(), '')

‎numba/tests/test_types.py‎

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,10 @@
44

55

66
from collections import namedtuple
7-
import contextlib
87
import gc
9-
import importlib
108
import os
119
import operator
12-
import shutil
1310
import sys
14-
import uuid
1511
import weakref
1612

1713
import numpy as np
@@ -23,7 +19,7 @@
2319
from numba import jit, njit, typeof
2420
from numba.core.extending import (overload, register_model, models, unbox,
2521
NativeValue, typeof_impl)
26-
from numba.tests.support import TestCase, temp_directory
22+
from numba.tests.support import TestCase, create_temp_module
2723
from numba.tests.enum_usecases import Color, Shake, Shape
2824
import unittest
2925
from numba.np import numpy_support
@@ -640,35 +636,10 @@ def __init__(self):
640636
super(FooType, self).__init__(name='Foo')
641637
"""
642638

643-
# this is largely copied (with some modifications) from test_jit_module
644-
@contextlib.contextmanager
645-
def create_temp_module(self, source_lines=None, **jit_options):
646-
# Use try/finally so cleanup happens even when an exception is raised
647-
try:
648-
if source_lines is None:
649-
source_lines = self.source_lines
650-
tempdir = temp_directory('test_extension_type')
651-
# Generate random module name
652-
temp_module_name = 'test_extension_type_{}'.format(
653-
str(uuid.uuid4()).replace('-', '_'))
654-
temp_module_path = os.path.join(tempdir, temp_module_name + '.py')
655-
656-
with open(temp_module_path, 'w') as f:
657-
lines = source_lines.format(jit_options=jit_options)
658-
f.write(lines)
659-
# Add test_module to sys.path so it can be imported
660-
sys.path.insert(0, tempdir)
661-
test_module = importlib.import_module(temp_module_name)
662-
yield test_module
663-
finally:
664-
sys.modules.pop(temp_module_name, None)
665-
sys.path.remove(tempdir)
666-
shutil.rmtree(tempdir)
667-
668639
def test_create_temp_module(self):
669640
sys_path_original = list(sys.path)
670641
sys_modules_original = dict(sys.modules)
671-
with self.create_temp_module() as test_module:
642+
with create_temp_module(self.source_lines) as test_module:
672643
temp_module_dir = os.path.dirname(test_module.__file__)
673644
self.assertEqual(temp_module_dir, sys.path[0])
674645
self.assertEqual(sys.path[1:], sys_path_original)
@@ -681,7 +652,7 @@ def test_create_temp_module_with_exception(self):
681652
try:
682653
sys_path_original = list(sys.path)
683654
sys_modules_original = dict(sys.modules)
684-
with self.create_temp_module():
655+
with create_temp_module(self.source_lines):
685656
raise ValueError("Something went wrong!")
686657
except ValueError:
687658
# Test that modifications to sys.path / sys.modules are reverted
@@ -690,7 +661,7 @@ def test_create_temp_module_with_exception(self):
690661

691662
def test_externally_defined_type_is_external(self):
692663

693-
with self.create_temp_module(self.source_lines) as test_module:
664+
with create_temp_module(self.source_lines) as test_module:
694665
FooType = test_module.FooType
695666
self.assertFalse(FooType().is_internal)
696667

@@ -763,7 +734,7 @@ def test_mixin_against_real_example(self):
763734
# See issue #4970, this checks that unicode eq/ne now ignores extension
764735
# types.
765736

766-
with self.create_temp_module(self.source_lines) as test_module:
737+
with create_temp_module(self.source_lines) as test_module:
767738
FooType = test_module.FooType
768739
self.assertFalse(FooType().is_internal)
769740

0 commit comments

Comments
 (0)