Skip to content

Commit

Permalink
Make DALI tests compatible with Python 3.12
Browse files Browse the repository at this point in the history
- adds additional replacements for functions used by nose
  and removed in python 3.12

Signed-off-by: Janusz Lisiecki <jlisiecki@nvidia.com>
  • Loading branch information
JanuszL committed May 2, 2024
1 parent 80b67f9 commit d171b28
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 5 deletions.
12 changes: 7 additions & 5 deletions dali/test/python/nose_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import sys

import collections
import nose.case
import nose.inspector
import nose.loader
import nose.suite
import nose.plugins.attrib
import unittest

if sys.version_info >= (3, 10) and not hasattr(collections, "Callable"):
nose.case.collections = collections.abc
Expand Down Expand Up @@ -69,7 +71,7 @@ def get_pattern(glob=None, regex=None, match_case=None):

def assert_raises(exception, *args, glob=None, regex=None, match_case=None, **kwargs):
"""
Wrapper combining `nose.tools.assert_raises` and `nose.tools.assert_raises_regex`.
Wrapper combining `unittest.TestCase.assert_raises` and `unittest.TestCase.assert_raises_regex`.
Specify ``regex=pattern`` or ``glob=pattern`` to check error message of expected exception
against the pattern.
Value for `glob` must be a string, `regex` can be either a literal or compiled regex pattern.
Expand All @@ -79,18 +81,18 @@ def assert_raises(exception, *args, glob=None, regex=None, match_case=None, **kw
"""

if glob is None and regex is None:
return tools.assert_raises(exception, *args, **kwargs)
return unittest.TestCase.assertRaise(exception, *args, **kwargs)

pattern = get_pattern(glob, regex, match_case)
return tools.assert_raises_regex(exception, pattern, *args, **kwargs)
return unittest.TestCase.assertRaisesRegex(None, exception, pattern, *args, **kwargs)


def assert_warns(exception=Warning, *args, glob=None, regex=None, match_case=None, **kwargs):
if glob is None and regex is None:
return tools.assert_warns(exception, *args, **kwargs)
return unittest.TestCase.assertWarns(exception, *args, **kwargs)

pattern = get_pattern(glob, regex, match_case)
return tools.assert_warns_regex(exception, pattern, *args, **kwargs)
return unittest.TestCase.assertWarnsRegexp(None, exception, pattern, *args, **kwargs)


def raises(exception, glob=None, regex=None, match_case=None):
Expand Down
81 changes: 81 additions & 0 deletions qa/nose_wrapper/__main__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,85 @@
import sys

if sys.version_info >= (3, 12):
import importlib

Check notice

Code scanning / CodeQL

Module is imported with 'import' and 'import from' Note

Module 'importlib' is imported with both 'import' and 'import from'.

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'importlib' is not used.
from importlib import machinery, util
from importlib._bootstrap import _exec, _load
import modulefinder
import os

Check notice

Code scanning / CodeQL

Unused import Note

Import of 'os' is not used.
import types
import unittest

def find_module(name, path):
return modulefinder.ModuleFinder(path).find_module(name, path)

def load_module(name, file, filename, details):
PY_SOURCE = 1
class _HackedGetData:

"""Compatibility support for 'file' arguments of various load_*()
functions."""

def __init__(self, fullname, path, file=None):
super().__init__(fullname, path)
self.file = file

def get_data(self, path):
"""Gross hack to contort loader to deal w/ load_*()'s bad API."""
if self.file and path == self.path:
# The contract of get_data() requires us to return bytes. Reopen the
# file in binary mode if needed.
if not self.file.closed:
file = self.file
if 'b' not in file.mode:
file.close()
if self.file.closed:
self.file = file = open(self.path, 'rb')

with file:

Check failure

Code scanning / CodeQL

Potentially uninitialized local variable Error

Local variable 'file' may be used before it is initialized.
return file.read()
else:
return super().get_data(path)

class _LoadSourceCompatibility(_HackedGetData, machinery.SourceFileLoader):

"""Compatibility support for implementing load_source()."""

_, mode, type_ = details
if mode and (not mode.startswith('r') or '+' in mode):
raise ValueError('invalid file open mode {!r}'.format(mode))
elif file is None and type_ in {PY_SOURCE, PY_COMPILED}:
msg = 'file object required for import (type code {})'.format(type_)
raise ValueError(msg)
assert type_ == PY_SOURCE, "load_module replacement supports only PY_SOURCE file type"
loader = _LoadSourceCompatibility(name, filename, file)
spec = util.spec_from_file_location(name, filename, loader=loader)
if name in sys.modules:
module = _exec(spec, sys.modules[name])
else:
module = _load(spec)
# To allow reloading to potentially work, use a non-hacked loader which
# won't rely on a now-closed file object.
module.__loader__ = machinery.SourceFileLoader(name, filename)
module.__spec__.loader = module.__loader__
return module

def acquire_lock():
pass

def release_lock():
pass

context = {
"find_module": find_module,
"load_module": load_module,
"acquire_lock": acquire_lock,
"release_lock": release_lock,
}
imp_module = types.ModuleType("imp", "Mimics old imp module")
imp_module.__dict__.update(context)
sys.modules["imp"] = imp_module
unittest._TextTestResult = unittest.TextTestResult

from nose.core import run_exit
import collections
import nose.case
Expand Down

0 comments on commit d171b28

Please sign in to comment.