diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 36f1c60..f7c5d65 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: [ ubuntu-latest, windows-latest, macos-latest ] - python-version: [ "3.9", "3.10", "3.11" ] + python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/source/lib/JMSLab/tests/_test_helpers.py b/source/lib/JMSLab/tests/_test_helpers.py index 7b6a402..710a0d3 100644 --- a/source/lib/JMSLab/tests/_test_helpers.py +++ b/source/lib/JMSLab/tests/_test_helpers.py @@ -10,27 +10,6 @@ from .._exception_classes import BadExtensionError -def platform_patch(platform, path): - ''' - This script produces a mock.patch decorator that mocks sys.platform - as `platform` in both the module given by `path` and, if possible, - this module's imported misc module. - ''' - main_patch = mock.patch('%s.sys.platform' % path, platform) - - # Try to also patch misc.sys.platform - try: - misc_path = '%s.misc.sys.platform' % path - # Check whether misc_path is a valid module - importlib.util.find_spec(misc_path) - misc_patch = mock.patch(misc_path, platform) - total_patch = lambda f: misc_patch(main_patch(f)) - except ImportError: - total_patch = main_patch - - return total_patch - - def command_match(command, language, which = None): match = None diff --git a/source/lib/JMSLab/tests/test_build_matlab.py b/source/lib/JMSLab/tests/test_build_matlab.py index 81abe83..a191612 100644 --- a/source/lib/JMSLab/tests/test_build_matlab.py +++ b/source/lib/JMSLab/tests/test_build_matlab.py @@ -7,6 +7,7 @@ import shutil import os import re +import sys # Import testing helper modules from . import _test_helpers as helpers @@ -32,7 +33,7 @@ class TestBuildMatlab(unittest.TestCase): def setUp(self): (TESTDIR / 'build').mkdir(exist_ok = True) - @helpers.platform_patch('darwin', path) + @unittest.skipUnless(os.name == 'posix', 'Unix-like (POSIX) only test') @subprocess_patch def test_unix(self, mock_check_output): ''' @@ -57,7 +58,7 @@ def check_call(self, mock_check_output, options): for option in options: self.assertIn(option, command.split(' ')) - @helpers.platform_patch('win32', path) + @unittest.skipUnless(sys.platform == 'win32', 'Windows-only test') @subprocess_patch def test_windows(self, mock_check_output): ''' @@ -69,7 +70,7 @@ def test_windows(self, mock_check_output): helpers.standard_test(self, build_matlab, 'm') self.check_call(mock_check_output, ['-nosplash', '-minimize', '-wait']) - @helpers.platform_patch('riscos', path) + @unittest.skipUnless(sys.platform != 'win32' and os.name != 'posix', 'Non-Unix / non-Windows test') @subprocess_patch def test_other_os(self, mock_check_output): ''' diff --git a/source/lib/JMSLab/tests/test_build_stata.py b/source/lib/JMSLab/tests/test_build_stata.py index 2d3be16..c1dc31f 100644 --- a/source/lib/JMSLab/tests/test_build_stata.py +++ b/source/lib/JMSLab/tests/test_build_stata.py @@ -6,6 +6,7 @@ import unittest import shutil import os +import sys # Import testing helper modules from . import _test_helpers as helpers @@ -31,7 +32,7 @@ class TestBuildStata(unittest.TestCase): def setUp(self): (TESTDIR / 'build').mkdir(exist_ok = True) - @helpers.platform_patch('darwin', path) + @unittest.skipUnless(os.name == 'posix', 'Unix-like (POSIX) only test') @mock.patch('%s.misc.is_in_path' % path) @subprocess_patch def test_unix(self, mock_check_output, mock_path): @@ -43,7 +44,7 @@ def test_unix(self, mock_check_output, mock_path): helpers.standard_test(self, build_stata, 'do', env = env, system_mock = mock_check_output) - @helpers.platform_patch('win32', path) + @unittest.skipUnless(sys.platform == 'win32', 'Windows-only test') @mock.patch('%s.misc.is_in_path' % path) @mock.patch('%s.misc.is_64_windows' % path) @subprocess_patch @@ -60,7 +61,7 @@ def test_windows(self, mock_check_output, mock_is_64, mock_path): helpers.standard_test(self, build_stata, 'do', env = env, system_mock = mock_check_output) - @helpers.platform_patch('cygwin', path) + @unittest.skipUnless(sys.platform != 'win32' and os.name != 'posix', 'Non-Unix / non-Windows test') @mock.patch('%s.misc.is_in_path' % path) @subprocess_patch def test_other_platform(self, mock_check_output, mock_path): @@ -85,7 +86,7 @@ def test_other_platform(self, mock_check_output, mock_path): source = 'test_script.do', env = env) - @helpers.platform_patch('darwin', path) + @unittest.skipUnless(os.name == 'posix', 'Unix-like (POSIX) only test') @subprocess_patch def test_stata_unix(self, mock_check_output): mock_check_output.side_effect = fx.make_stata_side_effect(STATA) @@ -93,7 +94,7 @@ def test_stata_unix(self, mock_check_output): helpers.standard_test(self, build_stata, 'do', env = env, system_mock = mock_check_output) - @helpers.platform_patch('win32', path) + @unittest.skipUnless(sys.platform == 'win32', 'Windows-only test') @subprocess_patch def test_stata_windows(self, mock_check_output): mock_check_output.side_effect = fx.make_stata_side_effect(STATA) @@ -131,15 +132,12 @@ def test_no_executable_in_path(self, mock_check_output, mock_path): mock_path.side_effect = fx.make_stata_path_effect('') env = {'executable_names': {'stata': None}} - with helpers.platform_patch('darwin', path), self.assertRaises(ExecCallError): - build_stata(target = 'test_output.txt', - source = 'test_script.do', - env = env) - - with helpers.platform_patch('win32', path), self.assertRaises(ExecCallError): - build_stata(target = 'test_output.txt', - source = 'test_script.do', - env = env) + + if os.name == 'posix' or sys.platform == 'win32': + with self.assertRaises(ExecCallError): + build_stata(target = 'test_output.txt', + source = 'test_script.do', + env = env) @subprocess_patch def test_unavailable_executable(self, mock_check_output): diff --git a/source/lib/JMSLab/tests/test_log.py b/source/lib/JMSLab/tests/test_log.py index 83d37b2..44c4f37 100644 --- a/source/lib/JMSLab/tests/test_log.py +++ b/source/lib/JMSLab/tests/test_log.py @@ -63,8 +63,7 @@ def test_start_log_popen_on_unix(self, mock_open, mock_popen): log.start_log(mode = 'develop', log = 'test_log.txt') mock_popen.assert_called_with('tee -a test_log.txt', 'w') - # Set the platform to Windows - @helpers.platform_patch('win32', '%s.misc' % path) + @unittest.skipUnless(sys.platform == 'win32', 'Windows-only test') def test_start_log_stdout_on_windows(self): ''' Test that start_log() leads stdout to be captured in @@ -84,7 +83,7 @@ def test_start_log_stdout_on_windows(self): message_match = r'^\*\*\* New build: \{[0-9\s\-:]+\} \*\*\*\n%s$' % test self.assertTrue(re.search(message_match, log_contents.strip())) - @helpers.platform_patch('win32', '%s.misc' % path) + @unittest.skipUnless(sys.platform == 'win32', 'Windows-only test') @mock.patch('%s.os.popen' % path) @mock.patch('%s.open' % path) def test_start_log_open_on_windows(self, mock_open, mock_popen): @@ -99,11 +98,11 @@ def test_start_log_open_on_windows(self, mock_open, mock_popen): mock_popen.assert_not_called() - @helpers.platform_patch('cygwin', '%s.misc' % path) + @unittest.skipUnless(sys.platform != 'win32' and os.name != 'posix', 'Non-Unix / non-Windows test') def test_start_log_other_os(self): ''' Test start_log()'s behaviour when run on a platform other - than Windows, Darwin, or Linux. + than Windows, or Unix (We don't expect it to change sys.stdout, but we expect it to set sys.stderr to sys.stdout.) ''' @@ -118,7 +117,7 @@ def test_start_log_other_os(self): log.start_log(mode = 'develop') self.assertEqual(sys.stderr, test_file) - @helpers.platform_patch('darwin', '%s.misc' % path) + @unittest.skipUnless(os.name == 'posix', 'Unix-like (POSIX) only test') def test_invalid_mode(self): '''Check behaviour when mode argument is invalid''' with self.assertRaises(Exception): @@ -127,7 +126,7 @@ def test_invalid_mode(self): with self.assertRaises(Exception): log.start_log(mode = None) - @helpers.platform_patch('darwin', '%s.misc' % path) + @unittest.skipUnless(os.name == 'posix', 'Unix-like (POSIX) only test') def test_start_log_nonstring_input(self): ''' Test start_log()'s behaviour when its log argument is