Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create symlink to IDF conversion auxiliary files #101

Merged
merged 1 commit into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ dist
build
**egg*
.coverage
**/auxiliary/**
**/auxiliary
**.pyc
19 changes: 17 additions & 2 deletions geospaas_processing/converters/idf/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import re
import shutil
import subprocess
import sys
import tarfile
import tempfile
from contextlib import closing
Expand All @@ -22,6 +21,19 @@ class IDFConversionManager(ConversionManager):

downloaded_aux = False

@staticmethod
def make_symlink(source, destination):
"""Create a symbolic link at `destination` pointing to `source`
If the destination already exists, it is deleted and replaced
with the symlink
"""
if not os.path.islink(destination):
if os.path.isdir(destination):
shutil.rmtree(destination)
elif os.path.isfile(destination):
os.remove(destination)
os.symlink(source, destination)

@classmethod
def download_auxiliary_files(cls, auxiliary_path):
"""Download the auxiliary files necessary for IDF conversion.
Expand Down Expand Up @@ -50,9 +62,12 @@ def download_auxiliary_files(cls, auxiliary_path):
raise
cls.downloaded_aux = True

cls.make_symlink(auxiliary_path, os.path.join(os.path.dirname(__file__), 'auxiliary'))

def __init__(self, *args, **kwargs):
download_auxiliary = kwargs.pop('download_auxiliary', True)
super().__init__(*args, **kwargs)
if 'unittest' not in sys.modules: # pragma: no cover
if download_auxiliary: # pragma: no cover
self.download_auxiliary_files(AUXILIARY_PATH)


Expand Down
63 changes: 56 additions & 7 deletions tests/converters/test_idf_converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import subprocess
import sys
import tarfile
import tempfile
import unittest
import unittest.mock as mock
from pathlib import Path
Expand All @@ -23,9 +24,12 @@ def test_do_not_download_auxiliary_files_if_folder_present(self):
is present
"""
with mock.patch('os.path.isdir', return_value=True), \
mock.patch('ftplib.FTP') as mock_ftp:
mock.patch('ftplib.FTP') as mock_ftp, \
mock.patch('geospaas_processing.converters.idf.converter.IDFConversionManager'
'.make_symlink') as mock_make_symlink:
idf_converter.IDFConversionManager.download_auxiliary_files('/foo')
mock_ftp.assert_not_called()
mock_make_symlink.assert_called()

def test_download_auxiliary_files_if_folder_not_present(self):
"""Test that auxiliary files are downloaded if the folder is
Expand All @@ -34,10 +38,15 @@ def test_download_auxiliary_files_if_folder_not_present(self):
with mock.patch('os.path.isdir', return_value=False), \
mock.patch('os.makedirs'), \
mock.patch('ftplib.FTP') as mock_ftp, \
mock.patch('tempfile.TemporaryFile'):
mock.patch('tempfile.TemporaryFile'), \
mock.patch('geospaas_processing.converters.idf.converter.IDFConversionManager'
'.make_symlink') as mock_make_symlink:
idf_converter.IDFConversionManager.download_auxiliary_files('/foo')
mock_ftp.assert_called()
mock_ftp.return_value.retrbinary.assert_called()
mock_make_symlink.assert_called_with(
'/foo',
os.path.join(os.path.dirname(idf_converter.__file__), 'auxiliary'))

def test_download_auxiliary_error(self):
"""Test that partly extracted auxiliary files are removed in
Expand All @@ -53,21 +62,61 @@ def test_download_auxiliary_error(self):
idf_converter.IDFConversionManager.download_auxiliary_files('/foo')
mock_rmtree.assert_called_with('/foo')

def test_download_if_no_unittest(self):
"""Test that the download happens only if not in the process of
running unit tests
def test_make_symlink(self):
"""Test making a symbolic link if none exists"""
with tempfile.TemporaryDirectory() as tmp_dir:
tmp_path = Path(tmp_dir)
source = tmp_path / 'foo'
dest = tmp_path / 'bar'
source.mkdir()
idf_converter.IDFConversionManager.make_symlink(source, dest)
self.assertTrue(dest.is_symlink())
self.assertEqual(dest.resolve(), source)

def test_make_symlink_replace_dir(self):
"""Test making a symbolic link if a directory exists at the
destination
"""
with tempfile.TemporaryDirectory() as tmp_dir:
tmp_path = Path(tmp_dir)
source = tmp_path / 'foo'
dest = tmp_path / 'bar'
source.mkdir()
dest.mkdir()
idf_converter.IDFConversionManager.make_symlink(source, dest)
self.assertTrue(dest.is_symlink())
self.assertEqual(dest.resolve(), source)

def test_make_symlink_replace_file(self):
"""Test making a symbolic link if a file exists at the
destination
"""
with tempfile.TemporaryDirectory() as tmp_dir:
tmp_path = Path(tmp_dir)
source = tmp_path / 'foo'
dest = tmp_path / 'bar'
source.mkdir()
dest.touch()
idf_converter.IDFConversionManager.make_symlink(source, dest)
self.assertTrue(dest.is_symlink())
self.assertEqual(dest.resolve(), source)


def test_no_download_arg(self):
"""Test that the download does not happen if
`download_auxiliary` is False
"""
sys_modules = sys.modules.copy()
del sys_modules['unittest']
with mock.patch('sys.modules', sys_modules), \
mock.patch('geospaas_processing.converters.idf.converter'
'.IDFConversionManager.download_auxiliary_files') as mock_download:
idf_converter.IDFConversionManager('')
idf_converter.IDFConversionManager('', download_auxiliary=True)
mock_download.assert_called()

with mock.patch('geospaas_processing.converters.idf.converter'
'.IDFConversionManager.download_auxiliary_files') as mock_download:
idf_converter.IDFConversionManager('')
idf_converter.IDFConversionManager('', download_auxiliary=False)
mock_download.assert_not_called()


Expand Down
Loading