60 lines
3.5 KiB
Python
60 lines
3.5 KiB
Python
import pathlib
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
import unittest.mock
|
|
|
|
import modulus.cli
|
|
import modulus.config
|
|
import modulus.python
|
|
|
|
class PythonTests(unittest.TestCase):
|
|
def context(self, root, groups):
|
|
return modulus.cli.build_context(root, modulus.config.normalize({'package': {'name': 'example'}, 'tooling': {'python': {'groups': groups}}}))
|
|
def test_optional_packages_are_not_needed_by_default(self):
|
|
with tempfile.TemporaryDirectory() as temporary, unittest.mock.patch.object(subprocess, 'run') as run:
|
|
context = self.context(pathlib.Path(temporary), [])
|
|
self.assertEqual(modulus.python.interpreter(context, install=True), pathlib.Path(sys.executable))
|
|
run.assert_not_called()
|
|
def test_conan_reuses_the_project_environment_and_preserves_offline_mode(self):
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
context = self.context(pathlib.Path(temporary), ['assets'])
|
|
environment = modulus.cli.subprocess_environment(context, ['conan', 'install', '.', '--no-remote'])
|
|
self.assertEqual(environment['MODULUS_PYTHON_COMMON_DIR'], str(context.common_dir))
|
|
self.assertEqual(environment['MODULUS_PYTHON_OFFLINE'], '1')
|
|
environment = modulus.cli.subprocess_environment(context, ['conan', 'install', '.'])
|
|
self.assertEqual(environment['MODULUS_PYTHON_OFFLINE'], '0')
|
|
def test_missing_dependencies_require_configure_and_never_download_during_build(self):
|
|
with tempfile.TemporaryDirectory() as temporary, unittest.mock.patch.object(subprocess, 'run') as run:
|
|
context = self.context(pathlib.Path(temporary), ['assets'])
|
|
for options in ({}, {'install': True, 'offline': True}):
|
|
with self.assertRaisesRegex(RuntimeError, 'configure'):
|
|
modulus.python.interpreter(context, **options)
|
|
run.assert_not_called()
|
|
def test_unknown_or_duplicate_groups_are_rejected(self):
|
|
for groups in (['unknown'], ['assets', 'assets'], 'assets'):
|
|
with self.assertRaises(modulus.config.config_error):
|
|
self.context(pathlib.Path('/tmp'), groups)
|
|
def test_matching_environment_is_reused_and_changed_pins_require_configure(self):
|
|
with tempfile.TemporaryDirectory() as temporary, unittest.mock.patch.object(subprocess, 'run') as run:
|
|
context = self.context(pathlib.Path(temporary), ['assets'])
|
|
executable = context.common_dir / 'python/bin/python3'
|
|
executable.parent.mkdir(parents=True)
|
|
executable.touch()
|
|
marker = executable.parents[1] / 'requirements.sha256'
|
|
marker.write_text(modulus.python.identity(modulus.python.requirement_files(context)))
|
|
self.assertEqual(modulus.python.interpreter(context, offline=True), executable)
|
|
with unittest.mock.patch.object(modulus.python, 'identity', return_value='changed'):
|
|
with self.assertRaisesRegex(RuntimeError, 'configure'):
|
|
modulus.python.interpreter(context)
|
|
run.assert_not_called()
|
|
def test_runner_imports_exported_package_even_with_bootstrap_in_working_directory(self):
|
|
source = pathlib.Path(__file__).resolve().parents[1]
|
|
with tempfile.TemporaryDirectory() as temporary:
|
|
root = pathlib.Path(temporary)
|
|
(root / 'modulus.py').write_text("raise AssertionError('bootstrap shadowed package')")
|
|
result = subprocess.run([sys.executable, str(source / 'tools/python_runner.py'), str(source), '-c', 'import modulus.filesystem; print("loaded")'], cwd=root, text=True, capture_output=True)
|
|
self.assertEqual(result.returncode, 0, result.stderr)
|
|
self.assertEqual(result.stdout.strip(), 'loaded')
|